volute 0.53.0 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/dist/{activity-events-LQII6PZS.js → activity-events-TFAJBNBW.js} +2 -2
  2. package/dist/{ai-service-YW5SWCSB.js → ai-service-KEK2V3AP.js} +2 -2
  3. package/dist/{auth-KRDSM55Q.js → auth-Y27LTNZK.js} +3 -3
  4. package/dist/auto-upgrade-2MZF7NG3.js +46 -0
  5. package/dist/{avatar-image-52WGXLHV.js → avatar-image-SN576P45.js} +2 -2
  6. package/dist/{backup-WWXVIMYQ.js → backup-GDCWH6MC.js} +12 -12
  7. package/dist/channels-AFJWGX7W.js +203 -0
  8. package/dist/{chat-WK2BLM7B.js → chat-HVPOZK3O.js} +9 -9
  9. package/dist/{chunk-QUSMYGNQ.js → chunk-2674KIGI.js} +1 -0
  10. package/dist/chunk-2GATCSZK.js +520 -0
  11. package/dist/{chunk-P2TBUKLW.js → chunk-3SFKY4GI.js} +4 -4
  12. package/dist/{chunk-RMADJFA7.js → chunk-45QTYKQQ.js} +4 -4
  13. package/dist/{chunk-TAWRJ24T.js → chunk-4VAQKLMU.js} +8 -5
  14. package/dist/{chunk-OXWUEU5V.js → chunk-5U5GLZSD.js} +2 -2
  15. package/dist/{chunk-TPX6E6PL.js → chunk-6HBGUPBA.js} +2 -2
  16. package/dist/{chunk-UFTDRTCP.js → chunk-7AA4T2RT.js} +2 -2
  17. package/dist/{chunk-LN7XJ56R.js → chunk-7XKPG66D.js} +9 -9
  18. package/dist/{chunk-VDZ4I4ZP.js → chunk-BP2X5AIK.js} +8 -14
  19. package/dist/{chunk-PIZDPY4G.js → chunk-CKOA4LWV.js} +12 -12
  20. package/dist/{chunk-6NLW72HP.js → chunk-CKPAVQNK.js} +1 -1
  21. package/dist/{chunk-IQ7VNWH6.js → chunk-DUV4EMNW.js} +37 -3
  22. package/dist/{chunk-CV6BNGFK.js → chunk-FSXPPOPM.js} +3 -3
  23. package/dist/{chunk-UTKUO2KY.js → chunk-FZUPIS3T.js} +3 -3
  24. package/dist/{chunk-L7BKTZ5U.js → chunk-G3XAB4DK.js} +1 -1
  25. package/dist/{chunk-23UJGVYP.js → chunk-HLWQ3P3R.js} +50 -46
  26. package/dist/{chunk-AP2KQMMW.js → chunk-HTSWDOJE.js} +11 -14
  27. package/dist/{chunk-EDR47UE2.js → chunk-IR2FW4W7.js} +2 -2
  28. package/dist/{chunk-ICXY54ZC.js → chunk-IT4GEFDH.js} +1 -1
  29. package/dist/{chunk-F6D766VQ.js → chunk-KS62IHE2.js} +1 -1
  30. package/dist/{chunk-LNNI3MS4.js → chunk-MNKPAAQF.js} +9 -2
  31. package/dist/{chunk-HASADR3E.js → chunk-NCRG4SBR.js} +241 -66
  32. package/dist/{chunk-I7U5EEZC.js → chunk-NM5FDH4T.js} +1 -1
  33. package/dist/{chunk-7LT3YZUR.js → chunk-OFU6WJJZ.js} +1 -1
  34. package/dist/{chunk-M77B73VV.js → chunk-OIOW3FPT.js} +7 -2
  35. package/dist/{chunk-BDHKCLWK.js → chunk-OKM67ZWH.js} +1 -1
  36. package/dist/chunk-OUGD5L5U.js +918 -0
  37. package/dist/{chunk-X67BDDZR.js → chunk-P3GXOT2X.js} +48 -2
  38. package/dist/{chunk-U54PJPTB.js → chunk-PRZUBJ4K.js} +1 -1
  39. package/dist/{chunk-UO4MZQNO.js → chunk-QVS3C4DK.js} +15 -7
  40. package/dist/{chunk-RQRO6PC7.js → chunk-TMTAHKYP.js} +324 -48
  41. package/dist/{chunk-5DBGQBQR.js → chunk-UEZC5MNB.js} +29 -18
  42. package/dist/{chunk-7ARONCZW.js → chunk-VTFXZPC3.js} +13 -13
  43. package/dist/{chunk-UDZLPR34.js → chunk-W3OIPJPB.js} +14 -9
  44. package/dist/{chunk-HTB7KDRU.js → chunk-WZZCA23D.js} +5 -4
  45. package/dist/{chunk-5Y54AE3L.js → chunk-XAG53RWY.js} +1 -1
  46. package/dist/{chunk-HTRSSOHY.js → chunk-YU5EYQAE.js} +1 -1
  47. package/dist/{chunk-5N32EN4O.js → chunk-Z4Q6TQWL.js} +1 -1
  48. package/dist/{chunk-EGV6R6UF.js → chunk-Z7TNIIHW.js} +3 -1
  49. package/dist/cli.js +19 -19
  50. package/dist/{clock-SH4NQC2F.js → clock-X7V3C7NL.js} +3 -3
  51. package/dist/{cloud-sync-MJVJ33LD.js → cloud-sync-FM73SVFJ.js} +21 -21
  52. package/dist/{conversations-ZL6PHROD.js → conversations-FH3ODBL7.js} +3 -3
  53. package/dist/{create-G2RIKQYK.js → create-P75ZFTVN.js} +1 -1
  54. package/dist/{daemon-restart-BIGU4OKS.js → daemon-restart-JQMMMITM.js} +4 -4
  55. package/dist/daemon.js +469 -857
  56. package/dist/db-JH3NTERX.js +36 -0
  57. package/dist/delivery-manager-H23Q23N7.js +41 -0
  58. package/dist/{delivery-notices-65TB3CBX.js → delivery-notices-S7TKOACE.js} +5 -5
  59. package/dist/{delivery-router-RHANNTAC.js → delivery-router-KHBVEVVL.js} +4 -2
  60. package/dist/{down-QSNEMTTX.js → down-UN2EDX2Y.js} +3 -3
  61. package/dist/echo-text-ULEIFJJF.js +40 -0
  62. package/dist/{exec-ABD3DYA2.js → exec-Z34TTUO3.js} +1 -1
  63. package/dist/extensions-QD22GXZD.js +74 -0
  64. package/dist/{files-CHPNEQXN.js → files-DUGRXN6V.js} +5 -5
  65. package/dist/{import-DB2KULRO.js → import-RDDUGGFI.js} +3 -3
  66. package/dist/{isolation-GVV2IBAU.js → isolation-UQPDO34R.js} +1 -1
  67. package/dist/message-delivery-LU4EP244.js +46 -0
  68. package/dist/migrate-init-infrastructure-Z72UJ5NT.js +44 -0
  69. package/dist/migrate-name-placeholder-64AEAWPE.js +37 -0
  70. package/dist/{migrate-thread-config-EQSEP2XG.js → migrate-thread-config-SVF2M3D3.js} +1 -1
  71. package/dist/{mind-IX5AWUST.js → mind-BARCLI7O.js} +14 -14
  72. package/dist/{mind-activity-tracker-QF6DCX2X.js → mind-activity-tracker-UT23RGBF.js} +3 -3
  73. package/dist/{mind-contacts-BKUOUJPV.js → mind-contacts-PEXCDRXA.js} +8 -8
  74. package/dist/{mind-list-KNU34SUD.js → mind-list-7KBLPLES.js} +2 -2
  75. package/dist/mind-service-ZJCUBAUL.js +48 -0
  76. package/dist/{mind-sleep-D3DEYAWG.js → mind-sleep-24HV4RCA.js} +5 -5
  77. package/dist/{mind-status-BPTLQ5Z6.js → mind-status-4YW4PHMO.js} +6 -3
  78. package/dist/{package-BN5KMU54.js → package-AUDBDKAO.js} +12 -14
  79. package/dist/{prompts-HNKGCAEY.js → prompts-MOBF3TMO.js} +1 -1
  80. package/dist/{sandbox-NNWCTHRI.js → sandbox-VI7XWBIA.js} +2 -2
  81. package/dist/scheduler-GLINVC2B.js +27 -0
  82. package/dist/{seed-LHZ33UB4.js → seed-5JGR7ZRA.js} +1 -1
  83. package/dist/{seed-cmd-U4RVJ3UA.js → seed-cmd-M6A7N7F3.js} +2 -2
  84. package/dist/{seed-create-OQU4KNCB.js → seed-create-TGFZW4IO.js} +3 -3
  85. package/dist/{seed-readiness-WJYYRRCK.js → seed-readiness-XBH2MUNA.js} +2 -2
  86. package/dist/{seed-sprout-SFUYH2RG.js → seed-sprout-3IC5ZVTI.js} +11 -11
  87. package/dist/{send-FWZAMDBN.js → send-DHYBAYK4.js} +11 -11
  88. package/dist/{service-XQPMZAGI.js → service-T4P5W6RS.js} +2 -2
  89. package/dist/{service-install-2EWD7KXD.js → service-install-R4SNYUVO.js} +3 -3
  90. package/dist/{setup-RVSGCIF3.js → setup-6KAH3GRW.js} +4 -4
  91. package/dist/skills/dreaming/SKILL.md +2 -2
  92. package/dist/skills/dreaming/references/INSTALL.md +1 -1
  93. package/dist/skills/tending/SKILL.md +2 -0
  94. package/dist/skills/volute-mind/SKILL.md +8 -0
  95. package/dist/skills/volute-mind/references/integrations.md +3 -2
  96. package/dist/skills/volute-mind/references/routing.md +18 -5
  97. package/dist/{skills-QRPU6BWY.js → skills-LKQCYFVP.js} +3 -3
  98. package/dist/sleep-manager-Q3ITFNOJ.js +42 -0
  99. package/dist/{spirit-I5ECLGRI.js → spirit-FKXMGO3N.js} +8 -6
  100. package/dist/spirit-availability-5R2WYSWF.js +43 -0
  101. package/dist/{sprout-A2PMEF7Z.js → sprout-VEW3CUNX.js} +1 -1
  102. package/dist/src-246GSX7A.js +519 -0
  103. package/dist/src-LOUB3WPR.js +4189 -0
  104. package/dist/{status-EYG4A3OK.js → status-LCKTTIWS.js} +5 -5
  105. package/dist/{system-events-YTOU66QI.js → system-events-ZYOCYAO2.js} +5 -3
  106. package/dist/{systems-2DIJY4RF.js → systems-HL7SGSW7.js} +6 -6
  107. package/dist/{tailscale-KHNZFC7L.js → tailscale-F2IMBILZ.js} +1 -1
  108. package/dist/{template-hash-YKWMVYMM.js → template-hash-RJRMF6DT.js} +2 -2
  109. package/dist/{template-staleness-PY2CULH6.js → template-staleness-IBD722PN.js} +4 -4
  110. package/dist/{turn-tracker-NNHS6MAR.js → turn-tracker-BE34OI6O.js} +7 -7
  111. package/dist/{up-UGBHH743.js → up-J47J5JRB.js} +3 -3
  112. package/dist/{update-CIWI2JYA.js → update-ILCPVNDD.js} +2 -2
  113. package/dist/{upgrade-LIE46UBB.js → upgrade-XY2J7NWZ.js} +9 -1
  114. package/dist/variant-cleanup-JGJZ5KB4.js +24 -0
  115. package/dist/{version-notify-SJVAQLZI.js → version-notify-KIXYNHJC.js} +28 -13
  116. package/dist/web-assets/assets/{index-b7G7ZsVk.js → index-CoU1eUKE.js} +25 -25
  117. package/dist/web-assets/assets/index-hPn_fkz3.css +1 -0
  118. package/dist/web-assets/index.html +2 -2
  119. package/package.json +12 -14
  120. package/packages/extensions/intentions/dist/ui/assets/index-3FneLCKR.css +1 -0
  121. package/packages/extensions/intentions/dist/ui/assets/index-Bl5KEcli.js +67 -0
  122. package/packages/extensions/{notes → intentions}/dist/ui/index.html +3 -3
  123. package/packages/extensions/intentions/skills/intention-review/SKILL.md +38 -0
  124. package/packages/extensions/intentions/skills/intentions/SKILL.md +49 -0
  125. package/packages/extensions/intentions/skills/intentions/scripts/intentions-hook.sh +45 -0
  126. package/packages/extensions/pages/dist/ui/assets/index-BKxVQkA9.css +1 -0
  127. package/packages/extensions/pages/dist/ui/assets/index-BMt6sStP.js +68 -0
  128. package/packages/extensions/pages/dist/ui/index.html +2 -2
  129. package/packages/extensions/pages/skills/commons-gardening/SKILL.md +50 -0
  130. package/packages/extensions/pages/skills/pages/SKILL.md +140 -16
  131. package/templates/_base/.init/.config/prompts.json +2 -3
  132. package/templates/{pi → _base}/.init/.config/routes.json +1 -0
  133. package/templates/_base/.init/.local/hooks/pre-prompt/turn-context.ts +30 -0
  134. package/templates/_base/.init/memory/dreams/.gitkeep +0 -0
  135. package/templates/_base/home/.config/routes.json +1 -1
  136. package/templates/_base/home/VOLUTE.md +1 -1
  137. package/templates/_base/src/lib/codex-session-seed.ts +6 -55
  138. package/templates/_base/src/lib/context-breakdown.ts +11 -3
  139. package/templates/_base/src/lib/pi-session-seed.ts +8 -57
  140. package/templates/_base/src/lib/routing.ts +2 -2
  141. package/templates/_base/src/lib/seed-note.ts +4 -4
  142. package/templates/_base/src/lib/session-seed.ts +8 -53
  143. package/templates/_base/src/lib/startup.ts +4 -22
  144. package/templates/claude/.init/CLAUDE.md +4 -0
  145. package/templates/claude/package.json +2 -2
  146. package/templates/claude/src/agent.ts +60 -112
  147. package/templates/claude/src/lib/hooks/pre-compact.ts +6 -6
  148. package/templates/claude/src/lib/message-channel.ts +43 -15
  149. package/templates/claude/src/lib/recover.ts +69 -0
  150. package/templates/claude/src/lib/stream-consumer.ts +23 -5
  151. package/templates/claude/src/server.ts +0 -1
  152. package/templates/claude/volute-template.json +1 -1
  153. package/templates/codex/.init/AGENTS.md +4 -0
  154. package/templates/codex/package.json +2 -2
  155. package/templates/codex/src/agent.ts +23 -89
  156. package/templates/codex/volute-template.json +1 -1
  157. package/templates/pi/.init/MINDS.md +4 -0
  158. package/templates/pi/package.json +1 -1
  159. package/templates/pi/src/agent.ts +26 -93
  160. package/templates/pi/src/lib/mechanics-doc.ts +30 -0
  161. package/templates/pi/src/server.ts +3 -2
  162. package/templates/pi/volute-template.json +1 -1
  163. package/dist/channels-LW5ZLMSQ.js +0 -90
  164. package/dist/chunk-R772ET2M.js +0 -164
  165. package/dist/db-IPXRJUI7.js +0 -20
  166. package/dist/delivery-manager-FDHCZ7PU.js +0 -37
  167. package/dist/echo-text-KU6G4Z7V.js +0 -40
  168. package/dist/extensions-VACUKFA5.js +0 -60
  169. package/dist/message-delivery-TUXM3AAE.js +0 -46
  170. package/dist/mind-service-WHFBUKZE.js +0 -48
  171. package/dist/scheduler-5X5UIQOQ.js +0 -27
  172. package/dist/skills/plan-coordinator/SKILL.md +0 -60
  173. package/dist/sleep-manager-NWUCRBZB.js +0 -42
  174. package/dist/spirit-availability-NIUUYKU2.js +0 -43
  175. package/dist/src-HGNE2XG4.js +0 -832
  176. package/dist/src-LCSOQY6Z.js +0 -2222
  177. package/dist/src-UDMJZ6MH.js +0 -426
  178. package/dist/variant-cleanup-CZDLIY3F.js +0 -24
  179. package/dist/web-assets/assets/index-BHSU9r-4.css +0 -1
  180. package/packages/extensions/notes/dist/ui/assets/index-BBs8pyel.js +0 -67
  181. package/packages/extensions/notes/dist/ui/assets/index-D3cdui42.css +0 -1
  182. package/packages/extensions/notes/skills/notes/SKILL.md +0 -90
  183. package/packages/extensions/pages/dist/ui/assets/index-B589e8Xe.js +0 -2
  184. package/packages/extensions/pages/dist/ui/assets/index-BuXnE-rb.css +0 -1
  185. package/packages/extensions/plan/dist/ui/assets/index-B8s8wxyt.js +0 -67
  186. package/packages/extensions/plan/dist/ui/assets/index-jIkrt-vI.css +0 -1
  187. package/packages/extensions/plan/dist/ui/index.html +0 -14
  188. package/packages/extensions/plan/skills/plan/SKILL.md +0 -43
  189. package/packages/extensions/plan/skills/plan/scripts/plan-hook.sh +0 -37
  190. package/templates/claude/.init/.config/routes.json +0 -11
  191. package/templates/codex/.init/.config/routes.json +0 -11
  192. package/dist/{accept-I4GVGWA3.js → accept-RSDIVJL6.js} +3 -3
  193. package/dist/{bridge-KU2IKSH3.js → bridge-YK7NTRU5.js} +3 -3
  194. package/dist/{create-C3XZACTV.js → create-M727VUDF.js} +3 -3
  195. package/dist/{env-BJGM6FBA.js → env-7AZFBPWX.js} +7 -7
  196. package/dist/{extension-B2W52WZY.js → extension-MRYJWSMV.js} +3 -3
  197. package/dist/{list-R2GDWOEE.js → list-UQGIW7OF.js} +3 -3
  198. package/dist/{login-EZ4RRDQX.js → login-4NUS72Z5.js} +3 -3
  199. package/dist/{login-JDOAK465.js → login-57MMYILL.js} +4 -4
  200. package/dist/{logout-MWSIUOQU.js → logout-BYV433X6.js} +3 -3
  201. package/dist/{logout-K6ZGAJY5.js → logout-YFZAJRPY.js} +3 -3
  202. package/dist/{mind-history-RVF6KJ7K.js → mind-history-RZMMCHMX.js} +9 -9
  203. package/dist/{mind-wake-DCDFFQKX.js → mind-wake-LDGPRA42.js} +3 -3
  204. package/dist/{read-J5RM674N.js → read-RJ5NAW5J.js} +3 -3
  205. package/dist/{register-53LBGSDC.js → register-WNCSOTAU.js} +3 -3
  206. package/dist/{reject-K2A4UK2Y.js → reject-4NFLXKRN.js} +3 -3
  207. package/dist/{restart-R2WFNF5K.js → restart-B4GNMVF2.js} +7 -7
  208. package/dist/{skill-DXLLSUHB.js → skill-QYTBUDNQ.js} +7 -7
  209. package/dist/{start-XDOUAWN3.js → start-BDHJVOVX.js} +6 -6
  210. package/dist/{stop-O62RTEMD.js → stop-45QYSGYS.js} +7 -7
package/dist/daemon.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  readBackupState,
7
7
  resticVersion,
8
8
  runBackup
9
- } from "./chunk-EDR47UE2.js";
9
+ } from "./chunk-IR2FW4W7.js";
10
10
  import {
11
11
  acceptPending,
12
12
  formatFileSize,
@@ -14,47 +14,60 @@ import {
14
14
  rejectPending,
15
15
  stageFile,
16
16
  validateFilePath
17
- } from "./chunk-F6D766VQ.js";
17
+ } from "./chunk-KS62IHE2.js";
18
+ import {
19
+ getMemoryStatus
20
+ } from "./chunk-5RBEEAKW.js";
18
21
  import {
19
22
  findOpenClawSession,
20
23
  importOpenClawConnectors,
21
24
  importPiSession,
22
25
  parseNameFromIdentity
23
- } from "./chunk-I7U5EEZC.js";
24
- import {
25
- getMemoryStatus
26
- } from "./chunk-5RBEEAKW.js";
27
- import {
28
- checkForUpdate,
29
- checkForUpdateCached,
30
- getCurrentVersion
31
- } from "./chunk-LAUCO2HC.js";
26
+ } from "./chunk-NM5FDH4T.js";
32
27
  import {
33
28
  SPIRIT_NOTICE_PREFIX,
34
29
  ensureSpiritAvailable
35
- } from "./chunk-P2TBUKLW.js";
36
- import {
37
- isHomeOnlyArchive
38
- } from "./chunk-FLIEXG2T.js";
30
+ } from "./chunk-3SFKY4GI.js";
39
31
  import {
40
- evaluateSeedChecklist
41
- } from "./chunk-RMADJFA7.js";
32
+ TEMPLATE_BRANCH,
33
+ UpgradeInProgressError,
34
+ VariantMergeError,
35
+ abortUpgrade,
36
+ configureGitIdentity,
37
+ continueUpgrade,
38
+ findUnresolvedHomeFiles,
39
+ formatUnresolvedHomeFilesMessage,
40
+ getUpgradeBlocked,
41
+ mergeVariantExcludingMemory,
42
+ npmInstallAsMind,
43
+ npmInstallNeeded,
44
+ runUpgrade,
45
+ upgradeDiff,
46
+ upgradeInProgress,
47
+ validateBranchName
48
+ } from "./chunk-OUGD5L5U.js";
42
49
  import {
43
50
  isTemplateStale
44
- } from "./chunk-CV6BNGFK.js";
51
+ } from "./chunk-FSXPPOPM.js";
45
52
  import {
46
53
  computeTemplateHash
47
- } from "./chunk-HTRSSOHY.js";
54
+ } from "./chunk-YU5EYQAE.js";
48
55
  import {
49
56
  cleanupVariant
50
- } from "./chunk-UO4MZQNO.js";
57
+ } from "./chunk-QVS3C4DK.js";
58
+ import {
59
+ isHomeOnlyArchive
60
+ } from "./chunk-FLIEXG2T.js";
61
+ import {
62
+ evaluateSeedChecklist
63
+ } from "./chunk-45QTYKQQ.js";
51
64
  import {
52
65
  PLATFORMS,
53
66
  echoTextToChannel,
54
67
  fixModelEscapes,
55
68
  getPlatformDriver,
56
69
  routeOutboundBridge
57
- } from "./chunk-7ARONCZW.js";
70
+ } from "./chunk-VTFXZPC3.js";
58
71
  import {
59
72
  getBridgeConfig,
60
73
  readBridgesConfig,
@@ -63,7 +76,12 @@ import {
63
76
  resolveChannelMapping,
64
77
  setBridgeConfig,
65
78
  setChannelMapping
66
- } from "./chunk-L7BKTZ5U.js";
79
+ } from "./chunk-G3XAB4DK.js";
80
+ import {
81
+ checkForUpdate,
82
+ checkForUpdateCached,
83
+ getCurrentVersion
84
+ } from "./chunk-LAUCO2HC.js";
67
85
  import {
68
86
  SESSION_MAX_AGE,
69
87
  announceSprout,
@@ -71,6 +89,7 @@ import {
71
89
  authMiddleware,
72
90
  backfillSystemChannelMembers,
73
91
  cleanExpiredSessions,
92
+ collectTurnContext,
74
93
  createSession,
75
94
  deleteSession,
76
95
  deleteSystemsConfig,
@@ -95,8 +114,10 @@ import {
95
114
  linkToolResultToTurn,
96
115
  listApiTokens,
97
116
  loadAllExtensions,
117
+ normalizeTrailingSlash,
98
118
  notifyExtensionsDaemonStart,
99
119
  notifyExtensionsDaemonStop,
120
+ notifyExtensionsSpiritReady,
100
121
  readSystemsConfig,
101
122
  recordOutbound,
102
123
  requireAdmin,
@@ -109,25 +130,25 @@ import {
109
130
  uninstallNpmExtension,
110
131
  willGateMessage,
111
132
  writeSystemsConfig
112
- } from "./chunk-HASADR3E.js";
113
- import "./chunk-5DBGQBQR.js";
133
+ } from "./chunk-NCRG4SBR.js";
134
+ import "./chunk-UEZC5MNB.js";
114
135
  import {
115
136
  applyInitFiles,
116
- applyTemplateHomeFiles,
117
137
  composeTemplate,
118
138
  copyTemplateToDir,
119
139
  findTemplatesRoot,
120
140
  isKnownTemplate,
121
141
  listFiles
122
- } from "./chunk-X67BDDZR.js";
142
+ } from "./chunk-P3GXOT2X.js";
123
143
  import {
124
144
  getScheduler,
125
145
  initScheduler
126
- } from "./chunk-PIZDPY4G.js";
146
+ } from "./chunk-CKOA4LWV.js";
127
147
  import {
128
148
  recordDeliveryFailure
129
- } from "./chunk-UTKUO2KY.js";
149
+ } from "./chunk-FZUPIS3T.js";
130
150
  import {
151
+ UnknownChannelError,
131
152
  checkStaleSend,
132
153
  formatHoldNotice,
133
154
  getDeliveryManager,
@@ -135,7 +156,7 @@ import {
135
156
  initDeliveryManager,
136
157
  isConversationId,
137
158
  publishTypingForChannels
138
- } from "./chunk-RQRO6PC7.js";
159
+ } from "./chunk-TMTAHKYP.js";
139
160
  import {
140
161
  MindStartupError,
141
162
  RestartTracker,
@@ -145,10 +166,7 @@ import {
145
166
  initMindManager,
146
167
  syncProviderToMinds,
147
168
  tryGetMindManager
148
- } from "./chunk-23UJGVYP.js";
149
- import {
150
- extractTextContent
151
- } from "./chunk-UDZLPR34.js";
169
+ } from "./chunk-HLWQ3P3R.js";
152
170
  import {
153
171
  SYSTEM_MIND,
154
172
  assignSession,
@@ -162,7 +180,6 @@ import {
162
180
  initSummarizer,
163
181
  isoWeekKeyForDateStr,
164
182
  markErrored,
165
- parseDbTimestamp,
166
183
  parseUtcDateTime,
167
184
  summarizeOrphanedTurns,
168
185
  summarizeTurn,
@@ -170,83 +187,11 @@ import {
170
187
  takeErrored,
171
188
  trackToolUse,
172
189
  utcDateTimeStr
173
- } from "./chunk-VDZ4I4ZP.js";
174
- import {
175
- SEED_SKILLS,
176
- STANDARD_SKILLS,
177
- autoUpdateMindSkills,
178
- getSharedSkill,
179
- getStandardSkillsWithExtensions,
180
- importSkillFromDir,
181
- initDefaultSkills,
182
- installSkill,
183
- isAutoUpdateSkillsEnabled,
184
- listFilesRecursive,
185
- listMindSkills,
186
- listSharedSkills,
187
- migrateSkillsToTemplate,
188
- mindSkillsDir,
189
- publishSkill,
190
- removeSharedSkill,
191
- sharedSkillsDir,
192
- syncBuiltinSkills,
193
- uninstallSkill,
194
- updateSkill
195
- } from "./chunk-TAWRJ24T.js";
196
- import {
197
- approveUser,
198
- changePassword,
199
- countAdmins,
200
- createUser,
201
- deleteExternalMindUser,
202
- deleteMindUser as deleteMindUser2,
203
- deleteUser,
204
- getDisplayNames,
205
- getOrCreateMindUser,
206
- getOrCreateSystemUser,
207
- getUser,
208
- getUserByUsername,
209
- listPendingUsers,
210
- listUsers,
211
- listUsersByType,
212
- setUserRole,
213
- syncMindProfile,
214
- updateUserProfile,
215
- verifyUser,
216
- withSenderDisplayNames
217
- } from "./chunk-7LT3YZUR.js";
218
- import {
219
- MIND_LEVEL_THREAD,
220
- captureReflection,
221
- cleanExpiredEvents,
222
- clearDeliveredEvents,
223
- deliverEvent,
224
- drainEvents,
225
- eventLabel,
226
- formatEvents,
227
- latestEvent,
228
- latestFailureEvent,
229
- listEvents,
230
- parseMeta,
231
- recordNotice
232
- } from "./chunk-IQ7VNWH6.js";
233
- import {
234
- publish as publish2,
235
- subscribe as subscribe2,
236
- subscribeAll
237
- } from "./chunk-LNNI3MS4.js";
238
- import {
239
- PROMPT_DEFAULTS,
240
- PROMPT_KEYS,
241
- getMindPromptDefaults,
242
- getPrompt,
243
- getPromptIfCustom,
244
- substitute
245
- } from "./chunk-AP2KQMMW.js";
190
+ } from "./chunk-BP2X5AIK.js";
246
191
  import {
247
192
  isSandboxEnabled,
248
193
  wrapForSandbox
249
- } from "./chunk-5Y54AE3L.js";
194
+ } from "./chunk-XAG53RWY.js";
250
195
  import {
251
196
  addMessage,
252
197
  createChannel,
@@ -282,22 +227,15 @@ import {
282
227
  subscribe as subscribe3,
283
228
  subscribeParticipantAdded,
284
229
  updateChannelSettings
285
- } from "./chunk-TPX6E6PL.js";
230
+ } from "./chunk-6HBGUPBA.js";
286
231
  import {
287
232
  getActiveMinds,
288
233
  onMindEvent,
289
234
  stopAll
290
- } from "./chunk-UFTDRTCP.js";
291
- import {
292
- broadcast,
293
- getEventsSince,
294
- nextEventId,
295
- publish,
296
- subscribe
297
- } from "./chunk-U54PJPTB.js";
235
+ } from "./chunk-7AA4T2RT.js";
298
236
  import {
299
237
  normalizeAvatar
300
- } from "./chunk-ICXY54ZC.js";
238
+ } from "./chunk-IT4GEFDH.js";
301
239
  import {
302
240
  safeResolveWithinBase
303
241
  } from "./chunk-DW4TRDOZ.js";
@@ -305,7 +243,90 @@ import {
305
243
  readVoluteConfig,
306
244
  writeVoluteConfig
307
245
  } from "./chunk-WCFSBH33.js";
308
- import "./chunk-6NLW72HP.js";
246
+ import {
247
+ extractTextContent
248
+ } from "./chunk-W3OIPJPB.js";
249
+ import {
250
+ approveUser,
251
+ changePassword,
252
+ countAdmins,
253
+ createUser,
254
+ deleteExternalMindUser,
255
+ deleteMindUser as deleteMindUser2,
256
+ deleteUser,
257
+ getDisplayNames,
258
+ getOrCreateMindUser,
259
+ getOrCreateSystemUser,
260
+ getUser,
261
+ getUserByUsername,
262
+ listPendingUsers,
263
+ listUsers,
264
+ listUsersByType,
265
+ setUserRole,
266
+ syncMindProfile,
267
+ updateUserProfile,
268
+ verifyUser,
269
+ withSenderDisplayNames
270
+ } from "./chunk-OFU6WJJZ.js";
271
+ import {
272
+ broadcast,
273
+ getEventsSince,
274
+ nextEventId,
275
+ publish,
276
+ subscribe
277
+ } from "./chunk-PRZUBJ4K.js";
278
+ import {
279
+ MIND_LEVEL_THREAD,
280
+ captureReflection,
281
+ cleanExpiredEvents,
282
+ clearDeliveredEvents,
283
+ deliverEvent,
284
+ drainEvents,
285
+ eventLabel,
286
+ findStrandedEventMinds,
287
+ formatEvents,
288
+ latestEvent,
289
+ latestFailureEvent,
290
+ listEvents,
291
+ parseMeta,
292
+ recordNotice
293
+ } from "./chunk-DUV4EMNW.js";
294
+ import {
295
+ parseDbTimestamp,
296
+ publish as publish2,
297
+ subscribe as subscribe2,
298
+ subscribeAll
299
+ } from "./chunk-MNKPAAQF.js";
300
+ import {
301
+ PROMPT_DEFAULTS,
302
+ PROMPT_KEYS,
303
+ getMindPromptDefaults,
304
+ getPrompt,
305
+ getPromptIfCustom,
306
+ substitute
307
+ } from "./chunk-HTSWDOJE.js";
308
+ import {
309
+ SEED_SKILLS,
310
+ STANDARD_SKILLS,
311
+ autoUpdateMindSkills,
312
+ getSharedSkill,
313
+ getStandardSkillsWithExtensions,
314
+ importSkillFromDir,
315
+ initDefaultSkills,
316
+ installSkill,
317
+ isAutoUpdateSkillsEnabled,
318
+ listFilesRecursive,
319
+ listMindSkills,
320
+ listSharedSkills,
321
+ mindSkillsDir,
322
+ publishSkill,
323
+ removeSharedSkill,
324
+ sharedSkillsDir,
325
+ syncBuiltinSkills,
326
+ uninstallSkill,
327
+ updateSkill
328
+ } from "./chunk-4VAQKLMU.js";
329
+ import "./chunk-CKPAVQNK.js";
309
330
  import {
310
331
  chownMindDir,
311
332
  chownMindFile,
@@ -317,7 +338,7 @@ import {
317
338
  isIsolationEnabled,
318
339
  resolveVoluteBin,
319
340
  wrapForIsolation
320
- } from "./chunk-M77B73VV.js";
341
+ } from "./chunk-OIOW3FPT.js";
321
342
  import {
322
343
  loadMergedEnv,
323
344
  mindEnvPath,
@@ -350,11 +371,11 @@ import {
350
371
  setProviderRefreshHook,
351
372
  setUtilityModel,
352
373
  unqualifyModelId
353
- } from "./chunk-EGV6R6UF.js";
374
+ } from "./chunk-Z7TNIIHW.js";
354
375
  import {
355
376
  logBuffer,
356
377
  logger_default
357
- } from "./chunk-QUSMYGNQ.js";
378
+ } from "./chunk-2674KIGI.js";
358
379
  import {
359
380
  buildVoluteSlug
360
381
  } from "./chunk-LGNUFVMR.js";
@@ -382,7 +403,6 @@ import {
382
403
  resolveMindDir,
383
404
  setMindRunning,
384
405
  setMindStage,
385
- setMindTemplate,
386
406
  setMindTemplateHash,
387
407
  stateDir,
388
408
  validateMindName,
@@ -409,7 +429,7 @@ import "./chunk-K3NQKI34.js";
409
429
  import { randomBytes as randomBytes3 } from "crypto";
410
430
  import { chmodSync, mkdirSync as mkdirSync10, readFileSync as readFileSync12, unlinkSync as unlinkSync2, writeFileSync as writeFileSync11 } from "fs";
411
431
  import { homedir as homedir3 } from "os";
412
- import { resolve as resolve20 } from "path";
432
+ import { resolve as resolve18 } from "path";
413
433
  import { format } from "util";
414
434
 
415
435
  // packages/daemon/src/lib/daemon/backup-manager.ts
@@ -520,7 +540,7 @@ var BackupManager = class {
520
540
  } catch (pubErr) {
521
541
  blog.error("failed to publish backup-failure activity", logger_default.errorData(pubErr));
522
542
  }
523
- const { deliverEvent: deliverEvent2 } = await import("./system-events-YTOU66QI.js");
543
+ const { deliverEvent: deliverEvent2 } = await import("./system-events-ZYOCYAO2.js");
524
544
  await deliverEvent2(getSpiritName(), {
525
545
  type: "notice",
526
546
  meta: { subtype: "backup" },
@@ -744,8 +764,8 @@ var BridgeManager = class {
744
764
  if (!tracked) return;
745
765
  this.stopping.add(platform);
746
766
  this.bridges.delete(platform);
747
- await new Promise((resolve21) => {
748
- tracked.child.on("exit", () => resolve21());
767
+ await new Promise((resolve19) => {
768
+ tracked.child.on("exit", () => resolve19());
749
769
  try {
750
770
  if (tracked.child.pid) {
751
771
  process.kill(-tracked.child.pid, "SIGTERM");
@@ -756,7 +776,7 @@ var BridgeManager = class {
756
776
  if (err instanceof Error && err.code !== "ESRCH") {
757
777
  blog2.warn(`failed to stop bridge ${platform}`, logger_default.errorData(err));
758
778
  }
759
- resolve21();
779
+ resolve19();
760
780
  }
761
781
  setTimeout(() => {
762
782
  try {
@@ -767,7 +787,7 @@ var BridgeManager = class {
767
787
  }
768
788
  } catch {
769
789
  }
770
- resolve21();
790
+ resolve19();
771
791
  }, 5e3);
772
792
  });
773
793
  this.stopping.delete(platform);
@@ -882,6 +902,19 @@ async function runMaintenance() {
882
902
  } catch (err) {
883
903
  logger_default.warn("maintenance: failed to clean expired events", logger_default.errorData(err));
884
904
  }
905
+ try {
906
+ await warnStrandedEvents();
907
+ } catch (err) {
908
+ logger_default.warn("maintenance: failed to check for stranded events", logger_default.errorData(err));
909
+ }
910
+ }
911
+ async function warnStrandedEvents() {
912
+ for (const s of await findStrandedEventMinds()) {
913
+ logger_default.warn(
914
+ `${s.mind} has ${s.pending} undelivered next-turn system event${s.pending === 1 ? "" : "s"} and has completed ${s.turnsSince} turns without draining them (oldest is ${s.ageHours}h old). Its pre-prompt drain hook is missing or failing \u2014 check home/.local/hooks/pre-prompt/notices.ts and run \`volute mind upgrade ${s.mind}\`.`,
915
+ { mind: s.mind, pending: s.pending, turnsSince: s.turnsSince, ageHours: s.ageHours }
916
+ );
917
+ }
885
918
  }
886
919
  function startMaintenanceInterval(intervalMs = MAINTENANCE_INTERVAL_MS, task = runMaintenance) {
887
920
  const handle = setInterval(() => void task(), intervalMs);
@@ -1444,10 +1477,10 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
1444
1477
  stream.writeSSE({ data: JSON.stringify(entry) }).catch(() => {
1445
1478
  });
1446
1479
  });
1447
- await new Promise((resolve21) => {
1480
+ await new Promise((resolve19) => {
1448
1481
  stream.onAbort(() => {
1449
1482
  unsubscribe();
1450
- resolve21();
1483
+ resolve19();
1451
1484
  });
1452
1485
  });
1453
1486
  });
@@ -1472,7 +1505,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
1472
1505
  config2.name = name.trim() || void 0;
1473
1506
  writeGlobalConfig(config2);
1474
1507
  if (config2.name !== previousName) {
1475
- const { notifySpiritSystemChange } = await import("./spirit-I5ECLGRI.js");
1508
+ const { notifySpiritSystemChange } = await import("./spirit-FKXMGO3N.js");
1476
1509
  await notifySpiritSystemChange();
1477
1510
  }
1478
1511
  return c.json({ name: config2.name ?? null });
@@ -1831,8 +1864,8 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
1831
1864
  createdAt: Date.now()
1832
1865
  };
1833
1866
  oauthFlows.set(flowId, flow);
1834
- const promptPromise = needsManualCode ? new Promise((resolve21) => {
1835
- flow.resolveCode = resolve21;
1867
+ const promptPromise = needsManualCode ? new Promise((resolve19) => {
1868
+ flow.resolveCode = resolve19;
1836
1869
  }) : void 0;
1837
1870
  oauthProvider.login({
1838
1871
  onAuth: (info) => {
@@ -1871,7 +1904,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
1871
1904
  existing.error = err instanceof Error ? err.message : String(err);
1872
1905
  }
1873
1906
  });
1874
- await new Promise((resolve21) => setTimeout(resolve21, 2e3));
1907
+ await new Promise((resolve19) => setTimeout(resolve19, 2e3));
1875
1908
  const state = oauthFlows.get(flowId);
1876
1909
  return c.json({
1877
1910
  flowId,
@@ -2132,8 +2165,8 @@ var app2 = new Hono2().get("/events", async (c) => {
2132
2165
  });
2133
2166
  }, 15e3);
2134
2167
  cleanups.push(() => clearInterval(keepAlive));
2135
- await new Promise((resolve21) => {
2136
- stream.onAbort(() => resolve21());
2168
+ await new Promise((resolve19) => {
2169
+ stream.onAbort(() => resolve19());
2137
2170
  });
2138
2171
  } finally {
2139
2172
  for (const cleanup of cleanups) {
@@ -2714,7 +2747,7 @@ async function fanOutToMinds(opts) {
2714
2747
  );
2715
2748
  }
2716
2749
  if (ap.userType === "system") {
2717
- import("./spirit-availability-NIUUYKU2.js").then(({ ensureSpiritAvailable: ensureSpiritAvailable2 }) => ensureSpiritAvailable2()).catch((err) => logger_default.warn("fan-out: on-demand spirit start failed", logger_default.errorData(err)));
2750
+ import("./spirit-availability-5R2WYSWF.js").then(({ ensureSpiritAvailable: ensureSpiritAvailable2 }) => ensureSpiritAvailable2()).catch((err) => logger_default.warn("fan-out: on-demand spirit start failed", logger_default.errorData(err)));
2718
2751
  }
2719
2752
  }
2720
2753
  return null;
@@ -2847,7 +2880,7 @@ var app4 = new Hono5().post("/:platform/inbound", zValidator4("json", inboundSch
2847
2880
  }
2848
2881
  const participants = await getParticipants(channel.id);
2849
2882
  if (!participants.some((p) => p.userId === puppet.id)) {
2850
- const { addParticipant } = await import("./conversations-ZL6PHROD.js");
2883
+ const { addParticipant } = await import("./conversations-FH3ODBL7.js");
2851
2884
  await addParticipant(channel.id, puppet.id);
2852
2885
  }
2853
2886
  const contentBlocks = body.content;
@@ -3131,11 +3164,11 @@ async function notifyMind(mindName, message) {
3131
3164
  const entry = await findMind(mindName);
3132
3165
  if (!entry) return false;
3133
3166
  try {
3134
- const { deliverEvent: deliverEvent2 } = await import("./system-events-YTOU66QI.js");
3167
+ const { deliverEvent: deliverEvent2 } = await import("./system-events-ZYOCYAO2.js");
3135
3168
  const result = await deliverEvent2(mindName, { type: "file-share", body: message });
3136
3169
  if (result.delivered) return true;
3137
3170
  if (result.id == null) return false;
3138
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
3171
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Q3ITFNOJ.js");
3139
3172
  const { getBaseName: getBaseName2 } = await import("./registry-TRC2HJXR.js");
3140
3173
  return getSleepManagerIfReady2()?.isSleeping(await getBaseName2(mindName)) ?? false;
3141
3174
  } catch (err) {
@@ -4108,9 +4141,9 @@ var app11 = new Hono14().get("/:name/logs", requireSelf(), async (c) => {
4108
4141
  stream.onAbort(() => {
4109
4142
  tail.kill();
4110
4143
  });
4111
- await new Promise((resolve21) => {
4112
- tail.on("exit", resolve21);
4113
- stream.onAbort(resolve21);
4144
+ await new Promise((resolve19) => {
4145
+ tail.on("exit", resolve19);
4146
+ stream.onAbort(resolve19);
4114
4147
  });
4115
4148
  });
4116
4149
  }).get("/:name/logs/tail", requireSelf(), async (c) => {
@@ -4128,8 +4161,8 @@ var app11 = new Hono14().get("/:name/logs", requireSelf(), async (c) => {
4128
4161
  tail.stdout.on("data", (data) => {
4129
4162
  output += data.toString();
4130
4163
  });
4131
- await new Promise((resolve21) => {
4132
- tail.on("exit", resolve21);
4164
+ await new Promise((resolve19) => {
4165
+ tail.on("exit", resolve19);
4133
4166
  });
4134
4167
  return c.text(output);
4135
4168
  });
@@ -4222,14 +4255,14 @@ var mind_skills_default = app12;
4222
4255
  // packages/daemon/src/web/api/minds.ts
4223
4256
  import {
4224
4257
  cpSync,
4225
- existsSync as existsSync8,
4258
+ existsSync as existsSync7,
4226
4259
  mkdirSync as mkdirSync6,
4227
4260
  readdirSync as readdirSync2,
4228
4261
  readFileSync as readFileSync9,
4229
4262
  rmSync as rmSync3,
4230
4263
  writeFileSync as writeFileSync8
4231
4264
  } from "fs";
4232
- import { relative, resolve as resolve13 } from "path";
4265
+ import { relative, resolve as resolve11 } from "path";
4233
4266
  import { zValidator as zValidator6 } from "@hono/zod-validator";
4234
4267
  import { and as and5, desc as desc3, eq as eq5, sql as sql3 } from "drizzle-orm";
4235
4268
  import { Hono as Hono16 } from "hono";
@@ -4672,49 +4705,6 @@ async function commitSrcChanges(dir, mindName) {
4672
4705
  glog.info(`committed known-good src changes (${dir})`);
4673
4706
  }
4674
4707
 
4675
- // packages/daemon/src/lib/mind/npm-install.ts
4676
- import { existsSync as existsSync7 } from "fs";
4677
- import { resolve as resolve10 } from "path";
4678
- var NPM_INSTALL_ARGS = [
4679
- "install",
4680
- "--no-audit",
4681
- "--no-fund",
4682
- "--prefer-offline",
4683
- "--loglevel=error"
4684
- ];
4685
- function lowPriorityArgv(cmd, args, ionice) {
4686
- return ionice ? ["ionice", ["-c2", "-n7", "nice", "-n19", cmd, ...args]] : ["nice", ["-n19", cmd, ...args]];
4687
- }
4688
- function hasIonice() {
4689
- return process.platform === "linux" && (existsSync7("/usr/bin/ionice") || existsSync7("/bin/ionice"));
4690
- }
4691
- async function npmInstallAsMind(cwd, mindName) {
4692
- const [cmd, args] = lowPriorityArgv("npm", NPM_INSTALL_ARGS, hasIonice());
4693
- if (isIsolationEnabled()) {
4694
- const [wrappedCmd, wrappedArgs] = await wrapForIsolation(cmd, args, mindName);
4695
- await exec(wrappedCmd, wrappedArgs, {
4696
- cwd,
4697
- env: { ...process.env, HOME: resolve10(cwd, "home") }
4698
- });
4699
- } else {
4700
- await exec(cmd, args, { cwd });
4701
- }
4702
- }
4703
- async function depsChangedSince(dir, fromRef) {
4704
- try {
4705
- await gitExec(["diff", "--quiet", fromRef, "HEAD", "--", "package.json", "package-lock.json"], {
4706
- cwd: dir
4707
- });
4708
- return false;
4709
- } catch {
4710
- return true;
4711
- }
4712
- }
4713
- async function npmInstallNeeded(dir, preMergeRef) {
4714
- if (!existsSync7(resolve10(dir, "node_modules"))) return true;
4715
- return depsChangedSince(dir, preMergeRef);
4716
- }
4717
-
4718
4708
  // packages/daemon/src/lib/mind/thinking-config.ts
4719
4709
  var CLAUDE_EFFORT = {
4720
4710
  minimal: "low",
@@ -4756,150 +4746,6 @@ function deriveThinkingLevel(config2) {
4756
4746
  return null;
4757
4747
  }
4758
4748
 
4759
- // packages/daemon/src/lib/mind/variants.ts
4760
- import { statSync as statSync3 } from "fs";
4761
- import { resolve as resolve11 } from "path";
4762
- var SAFE_BRANCH_RE = /^[a-zA-Z0-9._\-/]+$/;
4763
- function validateBranchName(branch) {
4764
- if (!SAFE_BRANCH_RE.test(branch)) {
4765
- return `Invalid branch name: ${branch}. Only alphanumeric, '.', '_', '-', '/' allowed.`;
4766
- }
4767
- if (branch.includes("..")) {
4768
- return `Invalid branch name: ${branch}. '..' not allowed.`;
4769
- }
4770
- return null;
4771
- }
4772
- var MERGE_EXCLUDED_PATHS = ["home/MEMORY.md", "home/memory/journal/"];
4773
- var MAX_DELTA_CHARS = 12e3;
4774
- var NEVER_REPORT_PREFIXES = ["home/.claude/", "home/.pi/", "home/.agents/"];
4775
- var MAX_LISTED_UNRESOLVED_FILES = 20;
4776
- async function findUnresolvedHomeFiles(cwd) {
4777
- const raw = await gitExec(
4778
- ["ls-files", "--others", "--ignored", "--exclude-standard", "-z", "--", "home"],
4779
- { cwd }
4780
- );
4781
- const allPaths = raw.split("\0").filter((path) => path && !NEVER_REPORT_PREFIXES.some((prefix) => path.startsWith(prefix)));
4782
- const files = [];
4783
- let totalBytes = 0;
4784
- for (const path of allPaths) {
4785
- let bytes = -1;
4786
- try {
4787
- bytes = statSync3(resolve11(cwd, path)).size;
4788
- } catch {
4789
- }
4790
- if (bytes > 0) totalBytes += bytes;
4791
- if (files.length < MAX_LISTED_UNRESOLVED_FILES) files.push({ path, bytes });
4792
- }
4793
- return { files, totalCount: allPaths.length, totalBytes };
4794
- }
4795
- function formatBytes(bytes) {
4796
- if (bytes < 0) return "size unknown";
4797
- if (bytes < 1024) return `${bytes} B`;
4798
- const units = ["KB", "MB", "GB", "TB"];
4799
- let value = bytes / 1024;
4800
- for (const unit of units) {
4801
- if (value < 1024) return `${value.toFixed(1)} ${unit}`;
4802
- value /= 1024;
4803
- }
4804
- return `${value.toFixed(1)} PB`;
4805
- }
4806
- function formatUnresolvedHomeFilesMessage(variantName, result) {
4807
- const lines = result.files.map(
4808
- (f) => ` - ${f.path.replace(/^home\//, "")} (${formatBytes(f.bytes)})`
4809
- );
4810
- const remaining = result.totalCount - result.files.length;
4811
- if (remaining > 0) lines.push(` ...and ${remaining} more`);
4812
- return `Cannot join variant "${variantName}": it has ${result.totalCount} untracked file${result.totalCount === 1 ? "" : "s"} under home/ that .gitignore is hiding from git \u2014 never committed, and joining would destroy them when the variant is cleaned up (total: ${formatBytes(result.totalBytes)}):
4813
-
4814
- ${lines.join("\n")}
4815
-
4816
- Before retrying the join, resolve each file in the variant \u2014 one of:
4817
- 1. Track it: git add -f -- <path> (then commit it, or let auto-commit pick it up next turn)
4818
- 2. Copy it out of home/ to somewhere safe, then delete it
4819
- 3. Delete it if it's disposable
4820
-
4821
- Once resolved, retry the join. To join anyway and discard everything listed above, pass discardUnresolved: true.`;
4822
- }
4823
- async function mergeVariantExcludingMemory(projectRoot, variantBranch) {
4824
- const opts = { cwd: projectRoot };
4825
- let memoryDelta = "";
4826
- try {
4827
- const base = (await gitExec(["merge-base", "HEAD", variantBranch], opts)).trim();
4828
- memoryDelta = (await gitExec(["diff", `${base}..${variantBranch}`, "--", ...MERGE_EXCLUDED_PATHS], opts)).trim();
4829
- } catch (err) {
4830
- logger_default.error(
4831
- `variant join: failed to compute memory delta for ${variantBranch}`,
4832
- logger_default.errorData(err)
4833
- );
4834
- memoryDelta = `(journal delta unavailable \u2014 ${err instanceof Error ? err.message : String(err)})`;
4835
- }
4836
- if (memoryDelta.length > MAX_DELTA_CHARS) {
4837
- memoryDelta = `${memoryDelta.slice(0, MAX_DELTA_CHARS)}
4838
- \u2026 (delta truncated)`;
4839
- }
4840
- try {
4841
- await gitExec(["merge", "--no-ff", "--no-commit", variantBranch], opts).catch(() => {
4842
- });
4843
- await gitExec(["reset", "-q", "HEAD", "--", ...MERGE_EXCLUDED_PATHS], opts);
4844
- for (const path of MERGE_EXCLUDED_PATHS) {
4845
- await gitExec(["checkout", "--", path], opts).catch(() => {
4846
- });
4847
- }
4848
- await gitExec(["clean", "-fdq", "--", ...MERGE_EXCLUDED_PATHS], opts);
4849
- await assertExcludedPathsRestored(opts);
4850
- if (await mergeInProgress(opts)) {
4851
- await gitExec(["commit", "--no-edit"], opts);
4852
- }
4853
- } catch (err) {
4854
- const conflicts = await listConflicts(opts);
4855
- const abortFailed = await gitExec(["merge", "--abort"], opts).then(
4856
- () => false,
4857
- () => true
4858
- );
4859
- throw new VariantMergeError(
4860
- `variant join aborted: ${err instanceof Error ? err.message : String(err)}`,
4861
- conflicts,
4862
- abortFailed
4863
- );
4864
- }
4865
- return memoryDelta;
4866
- }
4867
- var VariantMergeError = class extends Error {
4868
- constructor(message, conflicts, abortFailed = false) {
4869
- super(message);
4870
- this.conflicts = conflicts;
4871
- this.abortFailed = abortFailed;
4872
- this.name = "VariantMergeError";
4873
- }
4874
- };
4875
- async function mergeInProgress(opts) {
4876
- return gitExec(["rev-parse", "-q", "--verify", "MERGE_HEAD"], opts).then(
4877
- () => true,
4878
- () => false
4879
- );
4880
- }
4881
- async function listConflicts(opts) {
4882
- try {
4883
- const out = (await gitExec(["diff", "--name-only", "--diff-filter=U"], opts)).trim();
4884
- return out ? out.split("\n") : [];
4885
- } catch {
4886
- return [];
4887
- }
4888
- }
4889
- async function assertExcludedPathsRestored(opts) {
4890
- await gitExec(["diff", "--cached", "--quiet", "HEAD", "--", ...MERGE_EXCLUDED_PATHS], opts);
4891
- await gitExec(["diff", "--quiet", "HEAD", "--", ...MERGE_EXCLUDED_PATHS], opts);
4892
- const untracked = (await gitExec(
4893
- ["ls-files", "--others", "--exclude-standard", "--", ...MERGE_EXCLUDED_PATHS],
4894
- opts
4895
- )).trim();
4896
- if (untracked) {
4897
- throw new Error(
4898
- `untracked memory files remain after restore: ${untracked.replace(/\n/g, ", ")}`
4899
- );
4900
- }
4901
- }
4902
-
4903
4749
  // packages/daemon/src/lib/services/imagegen-jobs.ts
4904
4750
  import { mkdir, writeFile } from "fs/promises";
4905
4751
  import { dirname as dirname2 } from "path";
@@ -5022,7 +4868,7 @@ async function waitForImagegenJob(mind, id, timeoutMs) {
5022
4868
  import { randomUUID } from "crypto";
5023
4869
  import { mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
5024
4870
  import { homedir } from "os";
5025
- import { resolve as resolve12 } from "path";
4871
+ import { resolve as resolve10 } from "path";
5026
4872
  function convertSession(opts) {
5027
4873
  const lines = readFileSync8(opts.sessionPath, "utf-8").trim().split("\n");
5028
4874
  const sessionId = randomUUID();
@@ -5138,9 +4984,9 @@ function convertSession(opts) {
5138
4984
  }
5139
4985
  }
5140
4986
  const projectId = opts.projectDir.replace(/\//g, "-");
5141
- const sdkDir = resolve12(homedir(), ".claude", "projects", projectId);
4987
+ const sdkDir = resolve10(homedir(), ".claude", "projects", projectId);
5142
4988
  mkdirSync5(sdkDir, { recursive: true });
5143
- const sdkPath = resolve12(sdkDir, `${sessionId}.jsonl`);
4989
+ const sdkPath = resolve10(sdkDir, `${sessionId}.jsonl`);
5144
4990
  writeFileSync7(sdkPath, `${sdkEvents.join("\n")}
5145
4991
  `);
5146
4992
  console.log(`Converted ${sdkEvents.length} messages \u2192 ${sdkPath}`);
@@ -5201,7 +5047,7 @@ async function getMindStatus(name, port, registryRunning, seed) {
5201
5047
  let status = "stopped";
5202
5048
  let wakeAt = null;
5203
5049
  try {
5204
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
5050
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Q3ITFNOJ.js");
5205
5051
  const sleepManager = getSleepManagerIfReady2();
5206
5052
  if (sleepManager?.isSleeping(name)) {
5207
5053
  status = "sleeping";
@@ -5265,13 +5111,6 @@ function toPublicMind(entry, status, extras) {
5265
5111
  lastActiveAt: extras.lastActiveAt ?? null
5266
5112
  };
5267
5113
  }
5268
- var TEMPLATE_BRANCH = "volute/template";
5269
- async function configureGitIdentity(mindName, opts) {
5270
- const systemsConfig = readSystemsConfig();
5271
- const system = systemsConfig?.system ?? "local";
5272
- await gitExec(["config", "user.name", mindName], opts);
5273
- await gitExec(["config", "user.email", `${mindName}.${system}@volute.systems`], opts);
5274
- }
5275
5114
  async function initTemplateBranch(projectRoot, composedDir, manifest, mindName, env) {
5276
5115
  const templateFiles = listFiles(composedDir).filter((f) => !f.startsWith(".init/") && !f.startsWith(".init\\")).filter((f) => !f.startsWith("home/") && !f.startsWith("home\\") || f === "home/VOLUTE.md").map((f) => manifest.rename[f] ?? f);
5277
5116
  const opts = { cwd: projectRoot, mindName, env };
@@ -5282,164 +5121,9 @@ async function initTemplateBranch(projectRoot, composedDir, manifest, mindName,
5282
5121
  await gitExec(["add", "-A"], opts);
5283
5122
  await gitExec(["commit", "-m", "initial commit"], opts);
5284
5123
  }
5285
- async function updateTemplateBranch(projectRoot, template, mindName) {
5286
- const tempWorktree = resolve13(projectRoot, ".variants", "_template_update");
5287
- let branchExists = false;
5288
- try {
5289
- await gitExec(["rev-parse", "--verify", TEMPLATE_BRANCH], { cwd: projectRoot });
5290
- branchExists = true;
5291
- } catch {
5292
- }
5293
- try {
5294
- await gitExec(["worktree", "remove", "--force", tempWorktree], { cwd: projectRoot });
5295
- } catch {
5296
- }
5297
- if (existsSync8(tempWorktree)) {
5298
- rmSync3(tempWorktree, { recursive: true, force: true });
5299
- }
5300
- const templatesRoot = findTemplatesRoot();
5301
- const { composedDir, manifest } = composeTemplate(templatesRoot, template);
5302
- try {
5303
- if (branchExists) {
5304
- await gitExec(["worktree", "add", tempWorktree, TEMPLATE_BRANCH], {
5305
- cwd: projectRoot
5306
- });
5307
- } else {
5308
- await gitExec(["worktree", "add", "--detach", tempWorktree], { cwd: projectRoot });
5309
- await gitExec(["checkout", "--orphan", TEMPLATE_BRANCH], { cwd: tempWorktree });
5310
- await gitExec(["rm", "-rf", "--cached", "."], { cwd: tempWorktree });
5311
- await gitExec(["clean", "-fd"], { cwd: tempWorktree });
5312
- }
5313
- if (branchExists) {
5314
- await gitExec(["rm", "-rf", "."], { cwd: tempWorktree }).catch(() => {
5315
- });
5316
- }
5317
- copyTemplateToDir(composedDir, tempWorktree, mindName, manifest);
5318
- const initDir = resolve13(tempWorktree, ".init");
5319
- if (existsSync8(initDir)) {
5320
- rmSync3(initDir, { recursive: true, force: true });
5321
- }
5322
- const homeDir = resolve13(tempWorktree, "home");
5323
- if (existsSync8(homeDir)) {
5324
- for (const entry of readdirSync2(homeDir)) {
5325
- if (entry !== "VOLUTE.md") {
5326
- rmSync3(resolve13(homeDir, entry), { recursive: true, force: true });
5327
- }
5328
- }
5329
- }
5330
- await gitExec(["add", "-A"], { cwd: tempWorktree });
5331
- try {
5332
- await gitExec(["diff", "--cached", "--quiet"], { cwd: tempWorktree });
5333
- } catch {
5334
- await gitExec(["commit", "-m", "template update"], { cwd: tempWorktree });
5335
- }
5336
- } finally {
5337
- try {
5338
- await gitExec(["worktree", "remove", "--force", tempWorktree], { cwd: projectRoot });
5339
- } catch {
5340
- }
5341
- if (existsSync8(tempWorktree)) {
5342
- rmSync3(tempWorktree, { recursive: true, force: true });
5343
- }
5344
- rmSync3(composedDir, { recursive: true, force: true });
5345
- }
5346
- }
5347
- async function mergeTemplateBranch(worktreeDir) {
5348
- try {
5349
- await gitExec(
5350
- ["merge", TEMPLATE_BRANCH, "--allow-unrelated-histories", "-m", "merge template update"],
5351
- { cwd: worktreeDir }
5352
- );
5353
- return false;
5354
- } catch (e) {
5355
- try {
5356
- const status = await gitExec(["status", "--porcelain"], { cwd: worktreeDir });
5357
- const hasConflictMarkers = status.split("\n").some((line) => line.startsWith("UU") || line.startsWith("AA"));
5358
- if (hasConflictMarkers) return true;
5359
- } catch {
5360
- }
5361
- throw e;
5362
- }
5363
- }
5364
- async function mergeUpgradeAndRestart(mindName, dir, worktreeDir, upgradeVariantName, upgradeBranch, template, oldTemplate) {
5365
- const templateChanged = template !== oldTemplate;
5366
- const mainStatus = (await gitExec(["status", "--porcelain"], { cwd: dir })).trim();
5367
- if (mainStatus) {
5368
- await gitExec(["add", "-A"], { cwd: dir });
5369
- await gitExec(["commit", "-m", "Auto-commit before upgrade merge"], { cwd: dir });
5370
- }
5371
- const preMergeHead = (await gitExec(["rev-parse", "HEAD"], { cwd: dir })).trim();
5372
- await gitExec(["merge", upgradeBranch], { cwd: dir });
5373
- try {
5374
- await cleanupVariant(upgradeVariantName, mindName, dir, worktreeDir);
5375
- } catch (err) {
5376
- logger_default.warn(`failed to clean up upgrade worktree for ${mindName}`, logger_default.errorData(err));
5377
- }
5378
- try {
5379
- await gitExec(["branch", "-D", upgradeBranch], { cwd: dir });
5380
- } catch {
5381
- }
5382
- let switchWarning;
5383
- if (templateChanged) {
5384
- try {
5385
- applyTemplateHomeFiles(resolve13(dir, "home"), template);
5386
- const migratedSkills = migrateSkillsToTemplate(dir, oldTemplate, template);
5387
- await gitExec(["add", "home/"], { cwd: dir });
5388
- try {
5389
- await gitExec(["diff", "--cached", "--quiet"], { cwd: dir });
5390
- } catch {
5391
- await gitExec(["commit", "-m", `swap template-owned home files for ${template}`], {
5392
- cwd: dir
5393
- });
5394
- }
5395
- await chownMindDir(dir, mindName);
5396
- const skillNote = migratedSkills.length > 0 ? ` Migrated skills to the ${template} skills dir: ${migratedSkills.join(", ")}.` : "";
5397
- switchWarning = `Switched ${oldTemplate}\u2192${template}: config reset to ${template} defaults, mechanics doc replaced, conversation starts fresh (sessions aren't portable across runtimes).${skillNote}`;
5398
- } catch (err) {
5399
- logger_default.warn(`failed to swap template home files for ${mindName}`, logger_default.errorData(err));
5400
- return {
5401
- ok: true,
5402
- warning: `Upgrade merged but template switch ${oldTemplate}\u2192${template} failed: ${err instanceof Error ? err.message : String(err)}. The mind is still registered as ${oldTemplate}; re-run the switch or fix home/ manually.`
5403
- };
5404
- }
5405
- }
5406
- try {
5407
- await setMindTemplateHash(mindName, computeTemplateHash(template));
5408
- await setMindTemplate(mindName, template);
5409
- } catch (err) {
5410
- logger_default.warn(`failed to update template for ${mindName}`, logger_default.errorData(err));
5411
- }
5412
- if (await npmInstallNeeded(dir, preMergeHead)) {
5413
- try {
5414
- await npmInstallAsMind(dir, mindName);
5415
- } catch (err) {
5416
- logger_default.warn(`npm install failed after upgrade merge for ${mindName}`, logger_default.errorData(err));
5417
- return {
5418
- ok: true,
5419
- warning: `Upgrade merged but npm install failed: ${err instanceof Error ? err.message : String(err)}. You may need to run npm install manually.`
5420
- };
5421
- }
5422
- } else {
5423
- logger_default.info(`skipping npm install for ${mindName} \u2014 dependencies unchanged by upgrade`);
5424
- }
5425
- const manager = getMindManager();
5426
- try {
5427
- if (manager.isRunning(mindName)) {
5428
- await manager.stopMind(mindName);
5429
- }
5430
- manager.setPendingContext(mindName, { type: "upgraded" });
5431
- await manager.startMind(mindName, { healthTimeoutMs: 12e4 });
5432
- } catch (e) {
5433
- return {
5434
- ok: true,
5435
- warning: `Upgrade merged but mind restart failed: ${e instanceof Error ? e.message : String(e)}`
5436
- };
5437
- }
5438
- return { ok: true, warning: switchWarning };
5439
- }
5440
5124
  async function importFromArchive(c, tempDir, nameOverride, manifest) {
5441
- const extractedMindDir = resolve13(tempDir, "mind");
5442
- if (!existsSync8(extractedMindDir)) {
5125
+ const extractedMindDir = resolve11(tempDir, "mind");
5126
+ if (!existsSync7(extractedMindDir)) {
5443
5127
  return c.json({ error: "Invalid archive: missing mind/ directory" }, 400);
5444
5128
  }
5445
5129
  if (!manifest?.includes || !manifest.name || !manifest.template) {
@@ -5457,7 +5141,7 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
5457
5141
  if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
5458
5142
  ensureVoluteHome();
5459
5143
  const dest = mindDir(name);
5460
- if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5144
+ if (existsSync7(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5461
5145
  try {
5462
5146
  cpSync(extractedMindDir, dest, { recursive: true });
5463
5147
  if (!manifest.includes.identity) {
@@ -5465,9 +5149,9 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
5465
5149
  }
5466
5150
  const state = stateDir(name);
5467
5151
  mkdirSync6(state, { recursive: true });
5468
- const envJson = resolve13(tempDir, "state/env.json");
5469
- if (existsSync8(envJson)) {
5470
- cpSync(envJson, resolve13(state, "env.json"));
5152
+ const envJson = resolve11(tempDir, "state/env.json");
5153
+ if (existsSync7(envJson)) {
5154
+ cpSync(envJson, resolve11(state, "env.json"));
5471
5155
  }
5472
5156
  const port = await nextPort();
5473
5157
  await addMind(name, port, manifest.stage, manifest.template);
@@ -5476,30 +5160,30 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
5476
5160
  } catch (err) {
5477
5161
  logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
5478
5162
  }
5479
- const homeDir = resolve13(dest, "home");
5163
+ const homeDir = resolve11(dest, "home");
5480
5164
  ensureVoluteGroup();
5481
5165
  createMindUser(name, homeDir);
5482
5166
  await chownMindDir(dest, name);
5483
5167
  await npmInstallAsMind(dest, name);
5484
5168
  await importHistoryFromArchive(name, tempDir);
5485
5169
  importSessionsFromArchive(dest, tempDir);
5486
- if (!existsSync8(resolve13(dest, ".git"))) {
5170
+ if (!existsSync7(resolve11(dest, ".git"))) {
5487
5171
  try {
5488
- const env = isIsolationEnabled() ? { ...process.env, HOME: resolve13(dest, "home") } : void 0;
5172
+ const env = isIsolationEnabled() ? { ...process.env, HOME: resolve11(dest, "home") } : void 0;
5489
5173
  await gitExec(["init"], { cwd: dest, mindName: name, env });
5490
5174
  await configureGitIdentity(name, { cwd: dest, mindName: name, env });
5491
5175
  await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
5492
5176
  await gitExec(["commit", "-m", "import from archive"], { cwd: dest, mindName: name, env });
5493
5177
  } catch (err) {
5494
5178
  logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
5495
- rmSync3(resolve13(dest, ".git"), { recursive: true, force: true });
5179
+ rmSync3(resolve11(dest, ".git"), { recursive: true, force: true });
5496
5180
  }
5497
5181
  }
5498
5182
  await chownMindDir(dest, name);
5499
5183
  rmSync3(tempDir, { recursive: true, force: true });
5500
5184
  return c.json({ ok: true, name, port, message: `Imported mind: ${name} (port ${port})` });
5501
5185
  } catch (err) {
5502
- if (existsSync8(dest)) rmSync3(dest, { recursive: true, force: true });
5186
+ if (existsSync7(dest)) rmSync3(dest, { recursive: true, force: true });
5503
5187
  try {
5504
5188
  await removeMind(name);
5505
5189
  } catch (cleanupErr) {
@@ -5516,7 +5200,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5516
5200
  if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
5517
5201
  ensureVoluteHome();
5518
5202
  const dest = mindDir(name);
5519
- if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5203
+ if (existsSync7(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5520
5204
  const templatesRoot = findTemplatesRoot();
5521
5205
  const { composedDir, manifest: templateManifest } = composeTemplate(
5522
5206
  templatesRoot,
@@ -5525,36 +5209,36 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5525
5209
  try {
5526
5210
  copyTemplateToDir(composedDir, dest, name, templateManifest);
5527
5211
  applyInitFiles(dest);
5528
- const extractedHome = resolve13(extractedMindDir, "home");
5529
- if (existsSync8(extractedHome)) {
5530
- cpSync(extractedHome, resolve13(dest, "home"), { recursive: true });
5212
+ const extractedHome = resolve11(extractedMindDir, "home");
5213
+ if (existsSync7(extractedHome)) {
5214
+ cpSync(extractedHome, resolve11(dest, "home"), { recursive: true });
5531
5215
  }
5532
- const extractedMindInternal = resolve13(extractedMindDir, ".mind");
5533
- if (existsSync8(extractedMindInternal)) {
5534
- cpSync(extractedMindInternal, resolve13(dest, ".mind"), { recursive: true });
5216
+ const extractedMindInternal = resolve11(extractedMindDir, ".mind");
5217
+ if (existsSync7(extractedMindInternal)) {
5218
+ cpSync(extractedMindInternal, resolve11(dest, ".mind"), { recursive: true });
5535
5219
  }
5536
- const identityDir = resolve13(dest, ".mind/identity");
5220
+ const identityDir = resolve11(dest, ".mind/identity");
5537
5221
  let publicKeyPem;
5538
- if (!manifest.includes.identity || !existsSync8(resolve13(identityDir, "private.pem"))) {
5222
+ if (!manifest.includes.identity || !existsSync7(resolve11(identityDir, "private.pem"))) {
5539
5223
  ({ publicKeyPem } = generateIdentity(dest));
5540
5224
  } else {
5541
- publicKeyPem = readFileSync9(resolve13(identityDir, "public.pem"), "utf-8");
5225
+ publicKeyPem = readFileSync9(resolve11(identityDir, "public.pem"), "utf-8");
5542
5226
  }
5543
- const promptsPath = resolve13(dest, "home/.config/prompts.json");
5544
- if (!existsSync8(promptsPath)) {
5227
+ const promptsPath = resolve11(dest, "home/.config/prompts.json");
5228
+ if (!existsSync7(promptsPath)) {
5545
5229
  const mindPrompts = await getMindPromptDefaults();
5546
5230
  writeFileSync8(promptsPath, `${JSON.stringify(mindPrompts, null, 2)}
5547
5231
  `);
5548
5232
  }
5549
5233
  const state = stateDir(name);
5550
5234
  mkdirSync6(state, { recursive: true });
5551
- const envJson = resolve13(tempDir, "state/env.json");
5552
- if (existsSync8(envJson)) {
5553
- cpSync(envJson, resolve13(state, "env.json"));
5235
+ const envJson = resolve11(tempDir, "state/env.json");
5236
+ if (existsSync7(envJson)) {
5237
+ cpSync(envJson, resolve11(state, "env.json"));
5554
5238
  }
5555
5239
  const port = await nextPort();
5556
5240
  await addMind(name, port, manifest.stage, manifest.template);
5557
- const homeDir = resolve13(dest, "home");
5241
+ const homeDir = resolve11(dest, "home");
5558
5242
  ensureVoluteGroup();
5559
5243
  createMindUser(name, homeDir);
5560
5244
  await chownMindDir(dest, name);
@@ -5567,7 +5251,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5567
5251
  await initTemplateBranch(dest, composedDir, templateManifest, name, env);
5568
5252
  } catch (err) {
5569
5253
  logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
5570
- rmSync3(resolve13(dest, ".git"), { recursive: true, force: true });
5254
+ rmSync3(resolve11(dest, ".git"), { recursive: true, force: true });
5571
5255
  gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
5572
5256
  }
5573
5257
  const skillSet = manifest.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions();
@@ -5597,7 +5281,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5597
5281
  ...skillWarnings.length > 0 && { skillWarnings }
5598
5282
  });
5599
5283
  } catch (err) {
5600
- if (existsSync8(dest)) rmSync3(dest, { recursive: true, force: true });
5284
+ if (existsSync7(dest)) rmSync3(dest, { recursive: true, force: true });
5601
5285
  try {
5602
5286
  await removeMind(name);
5603
5287
  } catch (cleanupErr) {
@@ -5610,8 +5294,8 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5610
5294
  }
5611
5295
  }
5612
5296
  async function importHistoryFromArchive(name, tempDir) {
5613
- const historyJsonl = resolve13(tempDir, "history.jsonl");
5614
- if (!existsSync8(historyJsonl)) return;
5297
+ const historyJsonl = resolve11(tempDir, "history.jsonl");
5298
+ if (!existsSync7(historyJsonl)) return;
5615
5299
  try {
5616
5300
  const db = await getDb();
5617
5301
  const lines = readFileSync9(historyJsonl, "utf-8").trim().split("\n");
@@ -5651,13 +5335,13 @@ async function importHistoryFromArchive(name, tempDir) {
5651
5335
  }
5652
5336
  }
5653
5337
  function importSessionsFromArchive(dest, tempDir) {
5654
- const sessionsDir = resolve13(tempDir, "sessions");
5655
- if (!existsSync8(sessionsDir)) return;
5338
+ const sessionsDir = resolve11(tempDir, "sessions");
5339
+ if (!existsSync7(sessionsDir)) return;
5656
5340
  try {
5657
- const destSessions = resolve13(dest, ".mind/sessions");
5341
+ const destSessions = resolve11(dest, ".mind/sessions");
5658
5342
  mkdirSync6(destSessions, { recursive: true });
5659
5343
  for (const file of readdirSync2(sessionsDir)) {
5660
- cpSync(resolve13(sessionsDir, file), resolve13(destSessions, file));
5344
+ cpSync(resolve11(sessionsDir, file), resolve11(destSessions, file));
5661
5345
  }
5662
5346
  } catch (err) {
5663
5347
  logger_default.error("Failed to import sessions from archive", logger_default.errorData(err));
@@ -5737,7 +5421,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
5737
5421
  }
5738
5422
  ensureVoluteHome();
5739
5423
  const dest = mindDir(name);
5740
- if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5424
+ if (existsSync7(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5741
5425
  const templatesRoot = findTemplatesRoot();
5742
5426
  const { composedDir, manifest } = composeTemplate(templatesRoot, template);
5743
5427
  try {
@@ -5774,9 +5458,9 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
5774
5458
  writeVoluteConfig(dest, config2);
5775
5459
  const modelId = body.model ?? cog?.model;
5776
5460
  effectiveModel = modelId ? qualifyModelId(modelId) : void 0;
5777
- const sdkConfigPath = resolve13(dest, "home/.config/config.json");
5461
+ const sdkConfigPath = resolve11(dest, "home/.config/config.json");
5778
5462
  if (modelId || cog?.compaction) {
5779
- const existing = existsSync8(sdkConfigPath) ? JSON.parse(readFileSync9(sdkConfigPath, "utf-8")) : {};
5463
+ const existing = existsSync7(sdkConfigPath) ? JSON.parse(readFileSync9(sdkConfigPath, "utf-8")) : {};
5780
5464
  if (modelId) {
5781
5465
  existing.model = template === "pi" ? qualifyModelId(modelId) : unqualifyModelId(modelId);
5782
5466
  }
@@ -5789,7 +5473,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
5789
5473
  }
5790
5474
  const mindPrompts = await getMindPromptDefaults();
5791
5475
  writeFileSync8(
5792
- resolve13(dest, "home/.config/prompts.json"),
5476
+ resolve11(dest, "home/.config/prompts.json"),
5793
5477
  `${JSON.stringify(mindPrompts, null, 2)}
5794
5478
  `
5795
5479
  );
@@ -5801,7 +5485,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
5801
5485
  } catch (err) {
5802
5486
  logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
5803
5487
  }
5804
- const homeDir = resolve13(dest, "home");
5488
+ const homeDir = resolve11(dest, "home");
5805
5489
  ensureVoluteGroup();
5806
5490
  createMindUser(name, homeDir);
5807
5491
  await chownMindDir(dest, name);
@@ -5814,7 +5498,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
5814
5498
  await initTemplateBranch(dest, composedDir, manifest, name, env);
5815
5499
  } catch (err) {
5816
5500
  logger_default.error(`git setup failed for ${name}`, logger_default.errorData(err));
5817
- rmSync3(resolve13(dest, ".git"), { recursive: true, force: true });
5501
+ rmSync3(resolve11(dest, ".git"), { recursive: true, force: true });
5818
5502
  gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
5819
5503
  }
5820
5504
  if (body.stage === "seed") {
@@ -5823,7 +5507,7 @@ Your creator described you as: "${body.description}"
5823
5507
  ` : "";
5824
5508
  const seedSoulRaw = body.seedSoul ?? await getPrompt("seed_soul", { name, description: descLine });
5825
5509
  const seedSoul = body.seedSoul ? substitute(seedSoulRaw, { name, description: descLine }) : seedSoulRaw;
5826
- writeFileSync8(resolve13(dest, "home/SOUL.md"), seedSoul);
5510
+ writeFileSync8(resolve11(dest, "home/SOUL.md"), seedSoul);
5827
5511
  }
5828
5512
  let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
5829
5513
  if (body.stage === "seed" && !body.skills) {
@@ -5849,7 +5533,7 @@ Your creator described you as: "${body.description}"
5849
5533
  const spiritName = getSpiritName();
5850
5534
  const spiritEntry = await findMind(spiritName);
5851
5535
  if (spiritEntry) {
5852
- const { spiritDir } = await import("./spirit-I5ECLGRI.js");
5536
+ const { spiritDir } = await import("./spirit-FKXMGO3N.js");
5853
5537
  const sDir = spiritEntry.dir ?? spiritDir();
5854
5538
  const spiritConfig = readVoluteConfig(sDir) ?? {};
5855
5539
  const schedules = spiritConfig.schedules ?? [];
@@ -5864,7 +5548,7 @@ Your creator described you as: "${body.description}"
5864
5548
  });
5865
5549
  spiritConfig.schedules = schedules;
5866
5550
  writeVoluteConfig(sDir, spiritConfig);
5867
- const { getScheduler: getScheduler2 } = await import("./scheduler-5X5UIQOQ.js");
5551
+ const { getScheduler: getScheduler2 } = await import("./scheduler-GLINVC2B.js");
5868
5552
  getScheduler2().loadSchedules(spiritName, sDir);
5869
5553
  }
5870
5554
  }
@@ -5875,11 +5559,11 @@ Your creator described you as: "${body.description}"
5875
5559
  if (body.stage !== "seed") {
5876
5560
  const customSoul = await getPromptIfCustom("default_soul");
5877
5561
  if (customSoul) {
5878
- writeFileSync8(resolve13(dest, "home/SOUL.md"), customSoul.replace(/\{\{name\}\}/g, name));
5562
+ writeFileSync8(resolve11(dest, "home/SOUL.md"), customSoul.replace(/\{\{name\}\}/g, name));
5879
5563
  }
5880
5564
  const customMemory = await getPromptIfCustom("default_memory");
5881
5565
  if (customMemory) {
5882
- writeFileSync8(resolve13(dest, "home/MEMORY.md"), customMemory);
5566
+ writeFileSync8(resolve11(dest, "home/MEMORY.md"), customMemory);
5883
5567
  }
5884
5568
  }
5885
5569
  await chownMindDir(dest, name);
@@ -5919,7 +5603,7 @@ Your creator described you as: "${body.description}"
5919
5603
  ...skillWarnings.length > 0 && { skillWarnings }
5920
5604
  });
5921
5605
  } catch (err) {
5922
- if (existsSync8(dest)) rmSync3(dest, { recursive: true, force: true });
5606
+ if (existsSync7(dest)) rmSync3(dest, { recursive: true, force: true });
5923
5607
  try {
5924
5608
  await removeMind(name);
5925
5609
  } catch (cleanupErr) {
@@ -5940,13 +5624,13 @@ Your creator described you as: "${body.description}"
5940
5624
  return importFromArchive(c, body.archivePath, body.name, body.manifest);
5941
5625
  }
5942
5626
  const wsDir = body.workspacePath;
5943
- if (!wsDir || !existsSync8(resolve13(wsDir, "SOUL.md")) || !existsSync8(resolve13(wsDir, "IDENTITY.md"))) {
5627
+ if (!wsDir || !existsSync7(resolve11(wsDir, "SOUL.md")) || !existsSync7(resolve11(wsDir, "IDENTITY.md"))) {
5944
5628
  return c.json({ error: "Invalid workspace: missing SOUL.md or IDENTITY.md" }, 400);
5945
5629
  }
5946
- const soul = readFileSync9(resolve13(wsDir, "SOUL.md"), "utf-8");
5947
- const identity = readFileSync9(resolve13(wsDir, "IDENTITY.md"), "utf-8");
5948
- const userPath = resolve13(wsDir, "USER.md");
5949
- const user = existsSync8(userPath) ? readFileSync9(userPath, "utf-8") : "";
5630
+ const soul = readFileSync9(resolve11(wsDir, "SOUL.md"), "utf-8");
5631
+ const identity = readFileSync9(resolve11(wsDir, "IDENTITY.md"), "utf-8");
5632
+ const userPath = resolve11(wsDir, "USER.md");
5633
+ const user = existsSync7(userPath) ? readFileSync9(userPath, "utf-8") : "";
5950
5634
  const name = body.name ?? parseNameFromIdentity(identity) ?? "imported-mind";
5951
5635
  const template = body.template ?? "claude";
5952
5636
  const nameErr = validateMindName(name);
@@ -5966,33 +5650,33 @@ ${user.trimEnd()}
5966
5650
  ` : "";
5967
5651
  ensureVoluteHome();
5968
5652
  const dest = mindDir(name);
5969
- if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5653
+ if (existsSync7(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5970
5654
  const templatesRoot = findTemplatesRoot();
5971
5655
  const { composedDir, manifest } = composeTemplate(templatesRoot, template);
5972
5656
  try {
5973
5657
  copyTemplateToDir(composedDir, dest, name, manifest);
5974
5658
  applyInitFiles(dest);
5975
5659
  const { publicKeyPem: importPublicKey } = generateIdentity(dest);
5976
- writeFileSync8(resolve13(dest, "home/SOUL.md"), mergedSoul);
5977
- const wsMemoryPath = resolve13(wsDir, "MEMORY.md");
5978
- const hasMemory = existsSync8(wsMemoryPath);
5660
+ writeFileSync8(resolve11(dest, "home/SOUL.md"), mergedSoul);
5661
+ const wsMemoryPath = resolve11(wsDir, "MEMORY.md");
5662
+ const hasMemory = existsSync7(wsMemoryPath);
5979
5663
  if (hasMemory) {
5980
5664
  const existingMemory = readFileSync9(wsMemoryPath, "utf-8");
5981
5665
  writeFileSync8(
5982
- resolve13(dest, "home/MEMORY.md"),
5666
+ resolve11(dest, "home/MEMORY.md"),
5983
5667
  `${existingMemory.trimEnd()}${mergedMemoryExtra}`
5984
5668
  );
5985
5669
  } else if (user) {
5986
- writeFileSync8(resolve13(dest, "home/MEMORY.md"), `${user.trimEnd()}
5670
+ writeFileSync8(resolve11(dest, "home/MEMORY.md"), `${user.trimEnd()}
5987
5671
  `);
5988
5672
  }
5989
- const wsMemoryDir = resolve13(wsDir, "memory");
5673
+ const wsMemoryDir = resolve11(wsDir, "memory");
5990
5674
  let dailyLogCount = 0;
5991
- if (existsSync8(wsMemoryDir)) {
5992
- const destMemoryDir = resolve13(dest, "home/memory");
5675
+ if (existsSync7(wsMemoryDir)) {
5676
+ const destMemoryDir = resolve11(dest, "home/memory");
5993
5677
  const files = readdirSync2(wsMemoryDir).filter((f) => f.endsWith(".md"));
5994
5678
  for (const file of files) {
5995
- cpSync(resolve13(wsMemoryDir, file), resolve13(destMemoryDir, file));
5679
+ cpSync(resolve11(wsMemoryDir, file), resolve11(destMemoryDir, file));
5996
5680
  }
5997
5681
  dailyLogCount = files.length;
5998
5682
  }
@@ -6003,7 +5687,7 @@ ${user.trimEnd()}
6003
5687
  } catch (err) {
6004
5688
  logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
6005
5689
  }
6006
- const homeDir = resolve13(dest, "home");
5690
+ const homeDir = resolve11(dest, "home");
6007
5691
  ensureVoluteGroup();
6008
5692
  createMindUser(name, homeDir);
6009
5693
  await chownMindDir(dest, name);
@@ -6011,20 +5695,20 @@ ${user.trimEnd()}
6011
5695
  if (!hasMemory && dailyLogCount > 0) {
6012
5696
  await consolidateMemory(dest);
6013
5697
  }
6014
- const env = isIsolationEnabled() ? { ...process.env, HOME: resolve13(dest, "home") } : void 0;
5698
+ const env = isIsolationEnabled() ? { ...process.env, HOME: resolve11(dest, "home") } : void 0;
6015
5699
  await gitExec(["init"], { cwd: dest, mindName: name, env });
6016
5700
  await configureGitIdentity(name, { cwd: dest, mindName: name, env });
6017
5701
  await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
6018
5702
  await gitExec(["commit", "-m", "import from OpenClaw"], { cwd: dest, mindName: name, env });
6019
- const sessionFile = body.sessionPath ? resolve13(body.sessionPath) : findOpenClawSession(wsDir);
6020
- if (sessionFile && existsSync8(sessionFile)) {
5703
+ const sessionFile = body.sessionPath ? resolve11(body.sessionPath) : findOpenClawSession(wsDir);
5704
+ if (sessionFile && existsSync7(sessionFile)) {
6021
5705
  if (template === "pi") {
6022
5706
  importPiSession(sessionFile, dest);
6023
5707
  } else if (template === "claude") {
6024
5708
  const sessionId = convertSession({ sessionPath: sessionFile, projectDir: dest });
6025
- const mindRuntimeDir = resolve13(dest, ".mind");
5709
+ const mindRuntimeDir = resolve11(dest, ".mind");
6026
5710
  mkdirSync6(mindRuntimeDir, { recursive: true });
6027
- writeFileSync8(resolve13(mindRuntimeDir, "session.json"), JSON.stringify({ sessionId }));
5711
+ writeFileSync8(resolve11(mindRuntimeDir, "session.json"), JSON.stringify({ sessionId }));
6028
5712
  }
6029
5713
  }
6030
5714
  importOpenClawConnectors(name, dest);
@@ -6034,7 +5718,7 @@ ${user.trimEnd()}
6034
5718
  );
6035
5719
  return c.json({ ok: true, name, port, message: `Imported mind: ${name} (port ${port})` });
6036
5720
  } catch (err) {
6037
- if (existsSync8(dest)) rmSync3(dest, { recursive: true, force: true });
5721
+ if (existsSync7(dest)) rmSync3(dest, { recursive: true, force: true });
6038
5722
  try {
6039
5723
  await removeMind(name);
6040
5724
  } catch (cleanupErr) {
@@ -6070,7 +5754,7 @@ ${user.trimEnd()}
6070
5754
  stage: entry.stage,
6071
5755
  dir: entry.dir
6072
5756
  });
6073
- const hasPages = existsSync8(resolve13(mindDir(entry.name), "home", "pages"));
5757
+ const hasPages = existsSync7(resolve11(mindDir(entry.name), "home", "pages"));
6074
5758
  const lastActiveAt = lastActiveMap.get(entry.name) ?? null;
6075
5759
  if (!privileged) return toPublicMind(entry, mindStatus, { hasPages, lastActiveAt });
6076
5760
  return {
@@ -6078,6 +5762,7 @@ ${user.trimEnd()}
6078
5762
  ...mindStatus,
6079
5763
  hasPages,
6080
5764
  templateStale: isTemplateStale(entry),
5765
+ upgradeBlocked: getUpgradeBlocked(entry.name)?.reason,
6081
5766
  lastActiveAt
6082
5767
  };
6083
5768
  })
@@ -6088,12 +5773,12 @@ ${user.trimEnd()}
6088
5773
  const entry = await findMind(name);
6089
5774
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6090
5775
  const dir = entry.dir ?? mindDir(entry.parent ?? name);
6091
- if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
5776
+ if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
6092
5777
  const mindStatus = await getMindStatus(name, entry.port, void 0, {
6093
5778
  stage: entry.stage,
6094
5779
  dir: entry.dir
6095
5780
  });
6096
- const hasPages = existsSync8(resolve13(mindDir(name), "home", "pages"));
5781
+ const hasPages = existsSync7(resolve11(mindDir(name), "home", "pages"));
6097
5782
  if (!isPrivileged(c)) {
6098
5783
  return c.json(toPublicMind(entry, mindStatus, { hasPages }));
6099
5784
  }
@@ -6116,6 +5801,7 @@ ${user.trimEnd()}
6116
5801
  variants: variantStatuses,
6117
5802
  hasPages,
6118
5803
  templateStale: isTemplateStale(entry),
5804
+ upgradeBlocked: getUpgradeBlocked(name)?.reason,
6119
5805
  ...notice && {
6120
5806
  lastNotice: {
6121
5807
  kind: notice.kind,
@@ -6133,7 +5819,7 @@ ${user.trimEnd()}
6133
5819
  const projectDir = entry.dir ?? mindDir(name);
6134
5820
  if (entry.parent) {
6135
5821
  if (!entry.dir) return c.json({ error: `Variant ${name} has no directory` }, 404);
6136
- } else if (!existsSync8(projectDir)) {
5822
+ } else if (!existsSync7(projectDir)) {
6137
5823
  return c.json({ error: "Mind directory missing" }, 404);
6138
5824
  }
6139
5825
  if (getMindManager().isRunning(name)) {
@@ -6154,7 +5840,7 @@ ${user.trimEnd()}
6154
5840
  const projectDir = entry.dir ?? mindDir(name);
6155
5841
  if (entry.parent) {
6156
5842
  if (!entry.dir) return c.json({ error: `Variant ${name} has no directory` }, 404);
6157
- } else if (!existsSync8(projectDir)) {
5843
+ } else if (!existsSync7(projectDir)) {
6158
5844
  return c.json({ error: "Mind directory missing" }, 404);
6159
5845
  }
6160
5846
  let context;
@@ -6170,7 +5856,7 @@ ${user.trimEnd()}
6170
5856
  const manager = getMindManager();
6171
5857
  try {
6172
5858
  if (context?.type === "reload") {
6173
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
5859
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Q3ITFNOJ.js");
6174
5860
  const sleepState = getSleepManagerIfReady2()?.getState(name);
6175
5861
  if (sleepState?.sleeping) {
6176
5862
  logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
@@ -6191,7 +5877,7 @@ ${user.trimEnd()}
6191
5877
  if (variantEntry && variantEntry.parent === baseName && variantEntry.dir && variantEntry.branch) {
6192
5878
  const projectRoot = mindDir(baseName);
6193
5879
  const discardUnresolved = context.discardUnresolvedHomeFiles === true;
6194
- if (existsSync8(variantEntry.dir)) {
5880
+ if (existsSync7(variantEntry.dir)) {
6195
5881
  const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
6196
5882
  if (status) {
6197
5883
  try {
@@ -6221,7 +5907,7 @@ ${user.trimEnd()}
6221
5907
  const preMergeHead = (await gitExec(["rev-parse", "HEAD"], { cwd: projectRoot })).trim();
6222
5908
  const memoryDelta = await mergeVariantExcludingMemory(projectRoot, variantEntry.branch);
6223
5909
  let unresolvedNotice;
6224
- if (existsSync8(variantEntry.dir) && !discardUnresolved) {
5910
+ if (existsSync7(variantEntry.dir) && !discardUnresolved) {
6225
5911
  try {
6226
5912
  const unresolved = await findUnresolvedHomeFiles(variantEntry.dir);
6227
5913
  if (unresolved.totalCount > 0) {
@@ -6319,7 +6005,7 @@ ${user.trimEnd()}
6319
6005
  const name = c.req.param("name");
6320
6006
  const entry = await findMind(name);
6321
6007
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6322
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
6008
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Q3ITFNOJ.js");
6323
6009
  const sm = getSleepManagerIfReady2();
6324
6010
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
6325
6011
  return c.json(sm.getState(name));
@@ -6327,7 +6013,7 @@ ${user.trimEnd()}
6327
6013
  const name = c.req.param("name");
6328
6014
  const entry = await findMind(name);
6329
6015
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6330
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
6016
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Q3ITFNOJ.js");
6331
6017
  const sm = getSleepManagerIfReady2();
6332
6018
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
6333
6019
  if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
@@ -6347,7 +6033,7 @@ ${user.trimEnd()}
6347
6033
  const name = c.req.param("name");
6348
6034
  const entry = await findMind(name);
6349
6035
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6350
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
6036
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Q3ITFNOJ.js");
6351
6037
  const sm = getSleepManagerIfReady2();
6352
6038
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
6353
6039
  const sleepState = sm.getState(name);
@@ -6362,7 +6048,7 @@ ${user.trimEnd()}
6362
6048
  const name = c.req.param("name");
6363
6049
  const entry = await findMind(name);
6364
6050
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6365
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
6051
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Q3ITFNOJ.js");
6366
6052
  const sm = getSleepManagerIfReady2();
6367
6053
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
6368
6054
  const flushed = await sm.flushQueuedMessages(name);
@@ -6378,19 +6064,19 @@ ${user.trimEnd()}
6378
6064
  if (body.displayName !== void 0) profile.displayName = body.displayName;
6379
6065
  if (body.description !== void 0) profile.description = body.description;
6380
6066
  if (body.avatar !== void 0) {
6381
- const homeDir = resolve13(dir, "home");
6067
+ const homeDir = resolve11(dir, "home");
6382
6068
  const avatarPath = safeResolveWithinBase(homeDir, body.avatar);
6383
6069
  if (!avatarPath) {
6384
6070
  return c.json({ error: "Avatar path must be inside the mind's home directory" }, 400);
6385
6071
  }
6386
- if (!existsSync8(avatarPath)) {
6072
+ if (!existsSync7(avatarPath)) {
6387
6073
  return c.json({ error: `Avatar file not found: ${relative(homeDir, avatarPath)}` }, 400);
6388
6074
  }
6389
6075
  profile.avatar = relative(homeDir, avatarPath);
6390
6076
  }
6391
6077
  config2.profile = profile;
6392
6078
  writeVoluteConfig(dir, config2);
6393
- const { syncMindProfile: syncMindProfile2 } = await import("./auth-KRDSM55Q.js");
6079
+ const { syncMindProfile: syncMindProfile2 } = await import("./auth-Y27LTNZK.js");
6394
6080
  await syncMindProfile2(name, profile);
6395
6081
  broadcast({ type: "profile_updated", mind: name, summary: `${name} profile updated` });
6396
6082
  return c.json({ ok: true });
@@ -6434,7 +6120,7 @@ ${user.trimEnd()}
6434
6120
  });
6435
6121
  }
6436
6122
  if (!force) {
6437
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
6123
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Q3ITFNOJ.js");
6438
6124
  if (getSleepManagerIfReady2()?.isSleeping(name)) {
6439
6125
  return c.json({ output: "" });
6440
6126
  }
@@ -6489,7 +6175,7 @@ ${user.trimEnd()}
6489
6175
  }
6490
6176
  }
6491
6177
  const dir = entry.dir ?? mindDir(name);
6492
- const { evaluateSeedChecklist: evaluateSeedChecklist2 } = await import("./seed-readiness-WJYYRRCK.js");
6178
+ const { evaluateSeedChecklist: evaluateSeedChecklist2 } = await import("./seed-readiness-XBH2MUNA.js");
6493
6179
  const checklist = evaluateSeedChecklist2(dir);
6494
6180
  const done = [];
6495
6181
  const remaining = [];
@@ -6531,7 +6217,7 @@ ${user.trimEnd()}
6531
6217
  try {
6532
6218
  const sproutedDir = entry.dir ?? mindDir(name);
6533
6219
  if (setupDefaultDreaming(sproutedDir).schedulesChanged) {
6534
- const { getScheduler: getScheduler2 } = await import("./scheduler-5X5UIQOQ.js");
6220
+ const { getScheduler: getScheduler2 } = await import("./scheduler-GLINVC2B.js");
6535
6221
  getScheduler2().loadSchedules(name, sproutedDir);
6536
6222
  }
6537
6223
  } catch (err) {
@@ -6541,7 +6227,7 @@ ${user.trimEnd()}
6541
6227
  const spiritName = getSpiritName();
6542
6228
  const spiritEntry = await findMind(spiritName);
6543
6229
  if (spiritEntry) {
6544
- const { firstWeekSchedules, spiritDir } = await import("./spirit-I5ECLGRI.js");
6230
+ const { firstWeekSchedules, spiritDir } = await import("./spirit-FKXMGO3N.js");
6545
6231
  const sDir = spiritEntry.dir ?? spiritDir();
6546
6232
  const spiritConfig = readVoluteConfig(sDir);
6547
6233
  if (spiritConfig) {
@@ -6555,7 +6241,7 @@ ${user.trimEnd()}
6555
6241
  spiritConfig.schedules = schedules;
6556
6242
  writeVoluteConfig(sDir, spiritConfig);
6557
6243
  try {
6558
- const { getScheduler: getScheduler2 } = await import("./scheduler-5X5UIQOQ.js");
6244
+ const { getScheduler: getScheduler2 } = await import("./scheduler-GLINVC2B.js");
6559
6245
  getScheduler2().loadSchedules(spiritName, sDir);
6560
6246
  } catch (err) {
6561
6247
  logger_default.warn(
@@ -6609,10 +6295,10 @@ ${user.trimEnd()}
6609
6295
  await deleteMindUser2(name);
6610
6296
  invalidateMindUserCache(name);
6611
6297
  const state = stateDir(name);
6612
- if (existsSync8(state)) {
6298
+ if (existsSync7(state)) {
6613
6299
  rmSync3(state, { recursive: true, force: true });
6614
6300
  }
6615
- if (force && existsSync8(dir)) {
6301
+ if (force && existsSync7(dir)) {
6616
6302
  rmSync3(dir, { recursive: true, force: true });
6617
6303
  deleteMindUser(name);
6618
6304
  }
@@ -6627,7 +6313,7 @@ ${user.trimEnd()}
6627
6313
  const entry = await findMind(mindName);
6628
6314
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6629
6315
  const dir = mindDir(mindName);
6630
- if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
6316
+ if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
6631
6317
  let body = {};
6632
6318
  try {
6633
6319
  body = await c.req.json();
@@ -6638,27 +6324,12 @@ ${user.trimEnd()}
6638
6324
  if (!isKnownTemplate(template)) {
6639
6325
  return c.json({ error: `Unknown template: ${template}` }, 400);
6640
6326
  }
6641
- const UPGRADE_BRANCH = "upgrade";
6642
- const upgradeVariantName = `${mindName}-upgrade`;
6643
- const worktreeDir = resolve13(dir, ".variants", UPGRADE_BRANCH);
6644
6327
  if (body.abort) {
6645
- if (!existsSync8(worktreeDir)) {
6328
+ if (!upgradeInProgress(mindName)) {
6646
6329
  return c.json({ error: "No upgrade in progress" }, 400);
6647
6330
  }
6648
6331
  try {
6649
- try {
6650
- const gitDirContent = readFileSync9(resolve13(worktreeDir, ".git"), "utf-8").trim();
6651
- const gitDir = gitDirContent.replace("gitdir: ", "");
6652
- if (existsSync8(resolve13(gitDir, "MERGE_HEAD"))) {
6653
- await gitExec(["merge", "--abort"], { cwd: worktreeDir });
6654
- }
6655
- } catch {
6656
- }
6657
- await cleanupVariant(upgradeVariantName, mindName, dir, worktreeDir, { stop: true });
6658
- try {
6659
- await gitExec(["branch", "-D", UPGRADE_BRANCH], { cwd: dir });
6660
- } catch {
6661
- }
6332
+ await abortUpgrade(mindName);
6662
6333
  return c.json({ ok: true });
6663
6334
  } catch (err) {
6664
6335
  return c.json(
@@ -6668,81 +6339,45 @@ ${user.trimEnd()}
6668
6339
  }
6669
6340
  }
6670
6341
  if (body.continue) {
6671
- if (!existsSync8(worktreeDir)) {
6342
+ if (!upgradeInProgress(mindName)) {
6672
6343
  return c.json({ error: "No upgrade in progress" }, 400);
6673
6344
  }
6674
- const status = await gitExec(["status", "--porcelain"], { cwd: worktreeDir });
6675
- const hasConflicts2 = status.split("\n").some((line) => line.startsWith("UU") || line.startsWith("AA"));
6676
- if (hasConflicts2) {
6677
- return c.json({ error: "Unresolved conflicts remain" }, 409);
6678
- }
6679
- try {
6680
- await gitExec(["add", "-A"], { cwd: worktreeDir });
6681
- await gitExec(["commit", "-m", "merge template update"], { cwd: worktreeDir });
6682
- } catch (e) {
6683
- const msg = e instanceof Error ? e.message : String(e);
6684
- const stderr = e?.stderr ?? "";
6685
- const stdout = e?.stdout ?? "";
6686
- if (!msg.includes("nothing to commit") && !stderr.includes("nothing to commit") && !stdout.includes("nothing to commit"))
6687
- throw e;
6688
- }
6689
- try {
6690
- await gitExec(["add", "home/"], { cwd: worktreeDir });
6691
- } catch (err) {
6692
- logger_default.warn(`failed to re-add home files during upgrade for ${mindName}`, logger_default.errorData(err));
6693
- }
6694
- try {
6695
- await gitExec(["diff", "--cached", "--quiet"], { cwd: worktreeDir });
6696
- } catch {
6697
- await gitExec(["commit", "-m", "re-add allowlisted home files"], {
6698
- cwd: worktreeDir
6699
- });
6700
- }
6701
- await chownMindDir(dir, mindName);
6702
6345
  try {
6703
- const result = await mergeUpgradeAndRestart(
6704
- mindName,
6705
- dir,
6706
- worktreeDir,
6707
- upgradeVariantName,
6708
- UPGRADE_BRANCH,
6709
- template,
6710
- oldTemplate
6711
- );
6712
- return c.json(result);
6346
+ const result = await continueUpgrade(mindName, { template });
6347
+ if (result.status === "conflicts") {
6348
+ return c.json({
6349
+ ok: false,
6350
+ conflicts: true,
6351
+ worktreeDir: result.worktreeDir,
6352
+ files: result.files,
6353
+ message: result.message ?? "Merge conflicts detected. Resolve them, then run with continue."
6354
+ });
6355
+ }
6356
+ return c.json({ ok: true, warning: result.warning });
6713
6357
  } catch (err) {
6714
- return c.json(
6715
- { error: err instanceof Error ? err.message : "Failed to merge upgrade" },
6716
- 500
6717
- );
6358
+ const msg = err instanceof Error ? err.message : "Failed to merge upgrade";
6359
+ if (msg === "Unresolved conflicts remain") {
6360
+ return c.json({ error: msg }, 409);
6361
+ }
6362
+ return c.json({ error: msg }, 500);
6718
6363
  }
6719
6364
  }
6720
6365
  if (body.accept) {
6721
- if (existsSync8(worktreeDir)) {
6366
+ if (upgradeInProgress(mindName)) {
6722
6367
  try {
6723
- await cleanupVariant(upgradeVariantName, mindName, dir, worktreeDir, { stop: true });
6368
+ await abortUpgrade(mindName);
6724
6369
  } catch (err) {
6725
6370
  logger_default.warn(`failed to clean up legacy upgrade variant for ${mindName}`, logger_default.errorData(err));
6726
6371
  }
6727
- try {
6728
- await gitExec(["branch", "-D", UPGRADE_BRANCH], { cwd: dir });
6729
- } catch {
6730
- }
6731
6372
  }
6732
6373
  return c.json({ error: "Upgrades now auto-merge. Run 'volute mind upgrade' again." }, 400);
6733
6374
  }
6734
6375
  if (body.diff) {
6376
+ if (!existsSync7(resolve11(dir, ".git"))) {
6377
+ return c.json({ error: "Mind has no git history \u2014 nothing to diff against" }, 400);
6378
+ }
6735
6379
  try {
6736
- if (!existsSync8(resolve13(dir, ".git"))) {
6737
- return c.json({ error: "Mind has no git history \u2014 nothing to diff against" }, 400);
6738
- }
6739
- await updateTemplateBranch(dir, template, mindName);
6740
- let diff;
6741
- try {
6742
- diff = await gitExec(["diff", "HEAD...volute/template"], { cwd: dir });
6743
- } catch {
6744
- diff = await gitExec(["diff", "HEAD", "volute/template"], { cwd: dir });
6745
- }
6380
+ const diff = await upgradeDiff(mindName, template);
6746
6381
  return c.json({ ok: true, diff: diff || "(no changes)" });
6747
6382
  } catch (err) {
6748
6383
  return c.json(
@@ -6751,103 +6386,21 @@ ${user.trimEnd()}
6751
6386
  );
6752
6387
  }
6753
6388
  }
6754
- if (existsSync8(worktreeDir)) {
6755
- return c.json(
6756
- { error: "Upgrade variant already exists. Use continue or delete it first." },
6757
- 409
6758
- );
6759
- }
6760
- if (!existsSync8(resolve13(dir, ".git"))) {
6761
- try {
6762
- const env = isIsolationEnabled() ? { ...process.env, HOME: resolve13(dir, "home") } : void 0;
6763
- await gitExec(["init"], { cwd: dir, mindName, env });
6764
- await configureGitIdentity(mindName, { cwd: dir, mindName, env });
6765
- await gitExec(["add", "-A"], { cwd: dir, mindName, env });
6766
- await gitExec(["commit", "-m", "initial commit"], { cwd: dir, mindName, env });
6767
- await chownMindDir(dir, mindName);
6768
- } catch (err) {
6769
- rmSync3(resolve13(dir, ".git"), { recursive: true, force: true });
6770
- return c.json(
6771
- {
6772
- error: `Git initialization failed: ${err instanceof Error ? err.message : String(err)}`
6773
- },
6774
- 500
6775
- );
6776
- }
6777
- }
6778
- await gitExec(["worktree", "prune"], { cwd: dir });
6779
- try {
6780
- await gitExec(["branch", "-D", UPGRADE_BRANCH], { cwd: dir });
6781
- } catch {
6782
- }
6783
- await updateTemplateBranch(dir, template, mindName);
6784
- const parentDir = resolve13(dir, ".variants");
6785
- if (!existsSync8(parentDir)) {
6786
- mkdirSync6(parentDir, { recursive: true });
6787
- }
6788
- await gitExec(["worktree", "add", "-b", UPGRADE_BRANCH, worktreeDir], { cwd: dir });
6789
- await gitExec(["rm", "-r", "--cached", "--ignore-unmatch", "home/"], {
6790
- cwd: worktreeDir
6791
- });
6792
- try {
6793
- await gitExec(["checkout", "HEAD", "--", "home/VOLUTE.md"], { cwd: worktreeDir });
6794
- await gitExec(["add", "home/VOLUTE.md"], { cwd: worktreeDir });
6795
- } catch (err) {
6796
- const msg = String(err?.message ?? err);
6797
- if (!msg.includes("did not match")) {
6798
- logger_default.warn(
6799
- `unexpected error restoring VOLUTE.md during upgrade for ${mindName}`,
6800
- logger_default.errorData(err)
6801
- );
6802
- }
6803
- }
6804
6389
  try {
6805
- await gitExec(["diff", "--cached", "--quiet"], { cwd: worktreeDir });
6806
- } catch {
6807
- await gitExec(["commit", "-m", "prepare for home/ allowlist migration"], {
6808
- cwd: worktreeDir
6809
- });
6810
- }
6811
- const hasConflicts = await mergeTemplateBranch(worktreeDir);
6812
- if (!hasConflicts) {
6813
- try {
6814
- await gitExec(["add", "home/"], { cwd: worktreeDir });
6815
- } catch (err) {
6816
- logger_default.warn(`failed to re-add home files during upgrade for ${mindName}`, logger_default.errorData(err));
6817
- }
6818
- try {
6819
- await gitExec(["diff", "--cached", "--quiet"], { cwd: worktreeDir });
6820
- } catch {
6821
- await gitExec(["commit", "-m", "re-add allowlisted home files"], {
6822
- cwd: worktreeDir
6390
+ const result = await runUpgrade(mindName, { template });
6391
+ if (result.status === "conflicts") {
6392
+ return c.json({
6393
+ ok: false,
6394
+ conflicts: true,
6395
+ worktreeDir: result.worktreeDir,
6396
+ files: result.files,
6397
+ message: result.message ?? "Merge conflicts detected. Resolve them, then run with continue."
6823
6398
  });
6824
6399
  }
6825
- }
6826
- await chownMindDir(dir, mindName);
6827
- if (hasConflicts) {
6828
- return c.json({
6829
- ok: false,
6830
- conflicts: true,
6831
- worktreeDir,
6832
- message: "Merge conflicts detected. Resolve them, then run with continue."
6833
- });
6834
- }
6835
- try {
6836
- const result = await mergeUpgradeAndRestart(
6837
- mindName,
6838
- dir,
6839
- worktreeDir,
6840
- upgradeVariantName,
6841
- UPGRADE_BRANCH,
6842
- template,
6843
- oldTemplate
6844
- );
6845
- return c.json(result);
6400
+ return c.json({ ok: true, warning: result.warning });
6846
6401
  } catch (err) {
6847
- try {
6848
- await cleanupVariant(upgradeVariantName, mindName, dir, worktreeDir);
6849
- } catch (cleanupErr) {
6850
- logger_default.warn(`cleanup failed after upgrade error for ${mindName}`, logger_default.errorData(cleanupErr));
6402
+ if (err instanceof UpgradeInProgressError) {
6403
+ return c.json({ error: err.message }, 409);
6851
6404
  }
6852
6405
  return c.json({ error: err instanceof Error ? err.message : "Failed to merge upgrade" }, 500);
6853
6406
  }
@@ -6915,11 +6468,11 @@ ${user.trimEnd()}
6915
6468
  const entry = await findMind(name);
6916
6469
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6917
6470
  const dir = entry.dir ?? mindDir(name);
6918
- if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
6471
+ if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
6919
6472
  let config2 = readVoluteConfig(dir);
6920
6473
  if (!config2 && entry.template === "pi") {
6921
- const piConfigPath = resolve13(dir, "home/.config/config.json");
6922
- if (existsSync8(piConfigPath)) {
6474
+ const piConfigPath = resolve11(dir, "home/.config/config.json");
6475
+ if (existsSync7(piConfigPath)) {
6923
6476
  try {
6924
6477
  config2 = JSON.parse(readFileSync9(piConfigPath, "utf-8"));
6925
6478
  } catch {
@@ -6927,8 +6480,8 @@ ${user.trimEnd()}
6927
6480
  }
6928
6481
  }
6929
6482
  let templateConfig = {};
6930
- const configJsonPath = resolve13(dir, "home/.config/config.json");
6931
- if (existsSync8(configJsonPath)) {
6483
+ const configJsonPath = resolve11(dir, "home/.config/config.json");
6484
+ if (existsSync7(configJsonPath)) {
6932
6485
  try {
6933
6486
  templateConfig = JSON.parse(readFileSync9(configJsonPath, "utf-8"));
6934
6487
  } catch {
@@ -6970,7 +6523,7 @@ ${user.trimEnd()}
6970
6523
  const entry = await findMind(name);
6971
6524
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6972
6525
  const dir = entry.dir ?? mindDir(name);
6973
- if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
6526
+ if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
6974
6527
  const body = c.req.valid("json");
6975
6528
  const existing = readVoluteConfig(dir) ?? {};
6976
6529
  if (body.model !== void 0) existing.model = body.model;
@@ -6996,14 +6549,14 @@ ${user.trimEnd()}
6996
6549
  }
6997
6550
  writeVoluteConfig(dir, existing);
6998
6551
  if (body.unescapeNewlines !== void 0) {
6999
- const { clearEchoTextCache } = await import("./echo-text-KU6G4Z7V.js");
6552
+ const { clearEchoTextCache } = await import("./echo-text-ULEIFJJF.js");
7000
6553
  clearEchoTextCache(name);
7001
6554
  }
7002
6555
  const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.compaction !== void 0;
7003
6556
  if (needsConfigJson) {
7004
- const configJsonPath = resolve13(dir, "home/.config/config.json");
6557
+ const configJsonPath = resolve11(dir, "home/.config/config.json");
7005
6558
  let templateConfig = {};
7006
- if (existsSync8(configJsonPath)) {
6559
+ if (existsSync7(configJsonPath)) {
7007
6560
  try {
7008
6561
  templateConfig = JSON.parse(readFileSync9(configJsonPath, "utf-8"));
7009
6562
  } catch {
@@ -7068,15 +6621,49 @@ ${user.trimEnd()}
7068
6621
  if (err instanceof Error && err.message.includes("not initialized")) {
7069
6622
  return c.json({ error: "Delivery manager not available" }, 503);
7070
6623
  }
6624
+ if (err instanceof UnknownChannelError) return c.json({ error: err.message }, 400);
7071
6625
  logger_default.error(`failed to decline channel ${channel} for ${name}`, logger_default.errorData(err));
7072
6626
  return c.json({ error: "Failed to decline channel" }, 500);
7073
6627
  }
6628
+ }).post("/:name/gates/accept", requireSelf(), async (c) => {
6629
+ const name = c.req.param("name");
6630
+ const body = await c.req.json().catch(() => ({}));
6631
+ const channel = body.channel?.trim();
6632
+ if (!channel) return c.json({ error: "channel required" }, 400);
6633
+ if (!await findMind(name)) return c.json({ error: "Mind not found" }, 404);
6634
+ try {
6635
+ const result = await getDeliveryManager().acceptChannel(name, channel, body.thread?.trim());
6636
+ return c.json({ ok: true, channel, ...result });
6637
+ } catch (err) {
6638
+ if (err instanceof Error && err.message.includes("not initialized")) {
6639
+ return c.json({ error: "Delivery manager not available" }, 503);
6640
+ }
6641
+ if (err instanceof Error && err.message.includes("malformed")) {
6642
+ return c.json({ error: err.message }, 409);
6643
+ }
6644
+ if (err instanceof UnknownChannelError) return c.json({ error: err.message }, 400);
6645
+ logger_default.error(`failed to accept channel ${channel} for ${name}`, logger_default.errorData(err));
6646
+ return c.json({ error: "Failed to accept channel" }, 500);
6647
+ }
6648
+ }).get("/:name/gates/peek", requireSelf(), async (c) => {
6649
+ const name = c.req.param("name");
6650
+ const channel = c.req.query("channel")?.trim();
6651
+ if (!channel) return c.json({ error: "channel required" }, 400);
6652
+ try {
6653
+ return c.json(await getDeliveryManager().peekChannel(name, channel));
6654
+ } catch (err) {
6655
+ if (err instanceof Error && err.message.includes("not initialized")) {
6656
+ return c.json({ error: "Delivery manager not available" }, 503);
6657
+ }
6658
+ logger_default.error(`failed to peek channel ${channel} for ${name}`, logger_default.errorData(err));
6659
+ return c.json({ error: "Failed to read held messages" }, 500);
6660
+ }
7074
6661
  }).post("/:name/ai/complete", requireSelf(), async (c) => {
7075
6662
  const body = await c.req.json();
7076
6663
  if (!body.systemPrompt || !body.message) {
7077
6664
  return c.json({ error: "systemPrompt and message required" }, 400);
7078
6665
  }
7079
- const { aiComplete: aiCompleteFn, isAiConfigured: isAiConfigured2 } = await import("./ai-service-YW5SWCSB.js");
6666
+ const { aiComplete: aiCompleteFn, isAiConfigured: isAiConfigured2 } = await import("./ai-service-KEK2V3AP.js");
7080
6667
  if (!isAiConfigured2()) {
7081
6668
  return c.json({ error: "AI service not configured" }, 503);
7082
6669
  }
@@ -7321,6 +6908,11 @@ ${lines.join("\n")}` });
7321
6908
  const maxId = notices.reduce((m, n) => Math.max(m, n.id), 0);
7322
6909
  setNoticeDrainWatermark(baseName, session, maxId);
7323
6910
  return c.json({ context: formatEvents(notices), notices });
6911
+ }).get("/:name/turn-context", requireSelf(), async (c) => {
6912
+ const name = c.req.param("name");
6913
+ const baseName = await getBaseName(name);
6914
+ const reason = c.req.query("reason") === "wake" ? "wake" : "turn";
6915
+ return c.json({ context: await collectTurnContext(baseName, reason) });
7324
6916
  }).post("/:name/notices", requireSelf(), async (c) => {
7325
6917
  const MIND_POSTABLE_KINDS = ["context_lost", "delivery_failed"];
7326
6918
  const name = c.req.param("name");
@@ -7840,7 +7432,7 @@ var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) =>
7840
7432
  const entry = await findMind(name);
7841
7433
  if (!entry) return c.json({ error: "Mind not found" }, 404);
7842
7434
  const body = await c.req.text();
7843
- const { deliverEvent: deliverEvent2 } = await import("./system-events-YTOU66QI.js");
7435
+ const { deliverEvent: deliverEvent2 } = await import("./system-events-ZYOCYAO2.js");
7844
7436
  const { id, delivered } = await deliverEvent2(name, {
7845
7437
  type: "webhook",
7846
7438
  body,
@@ -7858,14 +7450,14 @@ var schedules_default = app15;
7858
7450
  // packages/daemon/src/web/api/setup.ts
7859
7451
  import { mkdirSync as mkdirSync7, rmSync as rmSync4, writeFileSync as writeFileSync9 } from "fs";
7860
7452
  import { homedir as homedir2 } from "os";
7861
- import { basename, resolve as resolve14 } from "path";
7453
+ import { basename, resolve as resolve12 } from "path";
7862
7454
  import { Hono as Hono19 } from "hono";
7863
7455
  import { setCookie as setCookie2 } from "hono/cookie";
7864
7456
  var DEFAULT_API_URL2 = "https://volute.systems";
7865
7457
  var setup = new Hono19();
7866
7458
  function writeSetupConfig(systemName, description) {
7867
- const configHome = process.env.VOLUTE_HOME ?? resolve14(homedir2(), ".volute");
7868
- const mindsDir = resolve14(configHome, "minds");
7459
+ const configHome = process.env.VOLUTE_HOME ?? resolve12(homedir2(), ".volute");
7460
+ const mindsDir = resolve12(configHome, "minds");
7869
7461
  mkdirSync7(configHome, { recursive: true });
7870
7462
  mkdirSync7(mindsDir, { recursive: true });
7871
7463
  const existingConfig = readGlobalConfig();
@@ -7899,7 +7491,7 @@ setup.get("/status", async (c) => {
7899
7491
  let hasAccount = false;
7900
7492
  if (hasSystem) {
7901
7493
  try {
7902
- const { listUsersByType: listUsersByType2 } = await import("./auth-KRDSM55Q.js");
7494
+ const { listUsersByType: listUsersByType2 } = await import("./auth-Y27LTNZK.js");
7903
7495
  const brains = await listUsersByType2("human");
7904
7496
  hasAccount = brains.length > 0;
7905
7497
  } catch (err) {
@@ -8111,7 +7703,7 @@ setup.post("/account", async (c) => {
8111
7703
  }
8112
7704
  }
8113
7705
  try {
8114
- const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-KRDSM55Q.js");
7706
+ const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-Y27LTNZK.js");
8115
7707
  const user = await createUser2(body.username.trim(), body.password);
8116
7708
  if (body.displayName?.trim()) {
8117
7709
  await updateUserProfile2(user.id, { display_name: body.displayName.trim() });
@@ -8157,7 +7749,7 @@ setup.post("/models", async (c) => {
8157
7749
  return c.json({ error: "Spirit model is required" }, 400);
8158
7750
  }
8159
7751
  try {
8160
- const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-YW5SWCSB.js");
7752
+ const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-KEK2V3AP.js");
8161
7753
  setEnabledModels3(body.models);
8162
7754
  const config2 = readGlobalConfig();
8163
7755
  config2.spiritModel = body.spiritModel.trim();
@@ -8200,7 +7792,7 @@ setup.post("/spirit", async (c) => {
8200
7792
  config2.setup.spiritDescription = description || void 0;
8201
7793
  const clearOldStash = () => {
8202
7794
  if (config2.setup?.spiritAvatar) {
8203
- rmSync4(resolve14(voluteSystemDir(), basename(config2.setup.spiritAvatar)), { force: true });
7795
+ rmSync4(resolve12(voluteSystemDir(), basename(config2.setup.spiritAvatar)), { force: true });
8204
7796
  config2.setup.spiritAvatar = void 0;
8205
7797
  }
8206
7798
  };
@@ -8224,7 +7816,7 @@ setup.post("/spirit", async (c) => {
8224
7816
  }
8225
7817
  clearOldStash();
8226
7818
  const filename = `spirit-avatar.${ext}`;
8227
- writeFileSync9(resolve14(voluteSystemDir(), filename), bytes);
7819
+ writeFileSync9(resolve12(voluteSystemDir(), filename), bytes);
8228
7820
  config2.setup.spiritAvatar = filename;
8229
7821
  } else {
8230
7822
  clearOldStash();
@@ -8237,15 +7829,16 @@ setup.post("/complete", async (c) => {
8237
7829
  return c.json({ error: "Setup already complete" }, 400);
8238
7830
  }
8239
7831
  try {
8240
- const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-I5ECLGRI.js");
8241
- const { startSpiritFull } = await import("./mind-service-WHFBUKZE.js");
7832
+ const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-FKXMGO3N.js");
7833
+ const { startSpiritFull } = await import("./mind-service-ZJCUBAUL.js");
8242
7834
  await ensureSpiritProject();
8243
7835
  await syncSpiritTemplate();
7836
+ await notifyExtensionsSpiritReady();
8244
7837
  const warnings = [];
8245
7838
  const config2 = readGlobalConfig();
8246
7839
  if (config2.setup?.service && config2.setup?.type === "local") {
8247
7840
  try {
8248
- const { installUserService } = await import("./service-install-2EWD7KXD.js");
7841
+ const { installUserService } = await import("./service-install-R4SNYUVO.js");
8249
7842
  const installed = await installUserService(config2.port, config2.hostname);
8250
7843
  if (!installed) {
8251
7844
  warnings.push("Service installation is not supported on this platform.");
@@ -8275,8 +7868,8 @@ setup.post("/complete", async (c) => {
8275
7868
  }
8276
7869
  let spiritConversationId;
8277
7870
  try {
8278
- const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-KRDSM55Q.js");
8279
- const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-ZL6PHROD.js");
7871
+ const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-Y27LTNZK.js");
7872
+ const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-FH3ODBL7.js");
8280
7873
  const spiritUser = await getOrCreateMindUser2(spiritName);
8281
7874
  const brains = await listUsersByType2("human");
8282
7875
  const admin2 = brains.find((u) => u.role === "admin");
@@ -8298,8 +7891,8 @@ setup.post("/complete", async (c) => {
8298
7891
  logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
8299
7892
  if (spiritConversationId && spiritStarted) {
8300
7893
  try {
8301
- const { deliverMessage: deliverMessage2 } = await import("./message-delivery-TUXM3AAE.js");
8302
- const { listUsersByType: listUsers2 } = await import("./auth-KRDSM55Q.js");
7894
+ const { deliverMessage: deliverMessage2 } = await import("./message-delivery-LU4EP244.js");
7895
+ const { listUsersByType: listUsers2 } = await import("./auth-Y27LTNZK.js");
8303
7896
  const admins = await listUsers2("human");
8304
7897
  const admin2 = admins.find((u) => u.role === "admin");
8305
7898
  if (admin2) {
@@ -8338,9 +7931,9 @@ setup.post("/complete", async (c) => {
8338
7931
  var setup_default = setup;
8339
7932
 
8340
7933
  // packages/daemon/src/web/api/skills.ts
8341
- import { existsSync as existsSync9, mkdtempSync, readdirSync as readdirSync3, rmSync as rmSync5 } from "fs";
7934
+ import { existsSync as existsSync8, mkdtempSync, readdirSync as readdirSync3, rmSync as rmSync5 } from "fs";
8342
7935
  import { tmpdir } from "os";
8343
- import { join, resolve as resolve15 } from "path";
7936
+ import { join, resolve as resolve13 } from "path";
8344
7937
  import AdmZip from "adm-zip";
8345
7938
  import { Hono as Hono20 } from "hono";
8346
7939
  var app16 = new Hono20().get("/", async (c) => {
@@ -8416,19 +8009,19 @@ var app16 = new Hono20().get("/", async (c) => {
8416
8009
  try {
8417
8010
  const zip = new AdmZip(buffer);
8418
8011
  for (const entry of zip.getEntries()) {
8419
- const target = resolve15(tmpDir, entry.entryName);
8012
+ const target = resolve13(tmpDir, entry.entryName);
8420
8013
  if (!target.startsWith(tmpDir)) {
8421
8014
  return c.json({ error: "Invalid zip: paths must not escape archive" }, 400);
8422
8015
  }
8423
8016
  }
8424
8017
  zip.extractAllTo(tmpDir, true);
8425
8018
  let skillDir = null;
8426
- if (existsSync9(join(tmpDir, "SKILL.md"))) {
8019
+ if (existsSync8(join(tmpDir, "SKILL.md"))) {
8427
8020
  skillDir = tmpDir;
8428
8021
  } else {
8429
8022
  const entries = readdirSync3(tmpDir, { withFileTypes: true }).filter((e) => e.isDirectory());
8430
8023
  for (const entry of entries) {
8431
- if (existsSync9(join(tmpDir, entry.name, "SKILL.md"))) {
8024
+ if (existsSync8(join(tmpDir, entry.name, "SKILL.md"))) {
8432
8025
  skillDir = join(tmpDir, entry.name);
8433
8026
  break;
8434
8027
  }
@@ -8790,8 +8383,8 @@ var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
8790
8383
  });
8791
8384
  }, 15e3);
8792
8385
  cleanups.push(() => clearInterval(keepAlive));
8793
- await new Promise((resolve21) => {
8794
- stream.onAbort(() => resolve21());
8386
+ await new Promise((resolve19) => {
8387
+ stream.onAbort(() => resolve19());
8795
8388
  });
8796
8389
  } finally {
8797
8390
  for (const cleanup of cleanups) {
@@ -9072,23 +8665,23 @@ var app21 = new Hono25().use("*", authMiddleware).get("/", async (c) => {
9072
8665
  var feed_default = app21;
9073
8666
 
9074
8667
  // packages/daemon/src/web/api/variants.ts
9075
- import { existsSync as existsSync11, mkdirSync as mkdirSync9, writeFileSync as writeFileSync10 } from "fs";
9076
- import { resolve as resolve18 } from "path";
8668
+ import { existsSync as existsSync10, mkdirSync as mkdirSync9, writeFileSync as writeFileSync10 } from "fs";
8669
+ import { resolve as resolve16 } from "path";
9077
8670
  import { Hono as Hono26 } from "hono";
9078
8671
 
9079
8672
  // packages/daemon/src/lib/mind/farewell.ts
9080
- import { existsSync as existsSync10, readFileSync as readFileSync10, rmSync as rmSync6 } from "fs";
9081
- import { resolve as resolve16 } from "path";
8673
+ import { existsSync as existsSync9, readFileSync as readFileSync10, rmSync as rmSync6 } from "fs";
8674
+ import { resolve as resolve14 } from "path";
9082
8675
  var flog = logger_default.child("farewell");
9083
8676
  var FAREWELL_RELPATH = ".mind/farewell.md";
9084
8677
  var FAREWELL_MIND_PATH = "../.mind/farewell.md";
9085
8678
  var FAREWELL_TIMEOUT_MS = 12e4;
9086
8679
  function farewellPath(variantDir) {
9087
- return resolve16(variantDir, FAREWELL_RELPATH);
8680
+ return resolve14(variantDir, FAREWELL_RELPATH);
9088
8681
  }
9089
8682
  function readFarewell(variantDir) {
9090
8683
  const path = farewellPath(variantDir);
9091
- if (!existsSync10(path)) return void 0;
8684
+ if (!existsSync9(path)) return void 0;
9092
8685
  try {
9093
8686
  const text = readFileSync10(path, "utf-8").trim();
9094
8687
  return text || void 0;
@@ -9111,7 +8704,7 @@ function waitForFarewell(name, variantDir, timeoutMs) {
9111
8704
  const unsub = subscribe((event) => {
9112
8705
  if (event.mind !== name) return;
9113
8706
  if (event.type !== "mind_done" && event.type !== "mind_idle") return;
9114
- if (existsSync10(farewellPath(variantDir))) cleanup();
8707
+ if (existsSync9(farewellPath(variantDir))) cleanup();
9115
8708
  });
9116
8709
  return { done, cancel: cleanup };
9117
8710
  }
@@ -9144,8 +8737,8 @@ async function runFarewellTurn(opts) {
9144
8737
 
9145
8738
  // packages/daemon/src/lib/mind/spawn-server.ts
9146
8739
  import { spawn as spawn4 } from "child_process";
9147
- import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync11, statSync as statSync4 } from "fs";
9148
- import { resolve as resolve17 } from "path";
8740
+ import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync11, statSync as statSync3 } from "fs";
8741
+ import { resolve as resolve15 } from "path";
9149
8742
  async function spawnServer(cwd, port, options) {
9150
8743
  let cmd = process.env.VOLUTE_NODE_PATH ?? process.execPath;
9151
8744
  let args = ["--import", "tsx", "src/server.ts", "--port", String(port)];
@@ -9166,34 +8759,34 @@ function spawnAttached(cmd, args, cwd) {
9166
8759
  cwd,
9167
8760
  stdio: ["ignore", "pipe", "pipe"]
9168
8761
  });
9169
- return new Promise((resolve21) => {
9170
- const timeout = setTimeout(() => resolve21(null), 3e4);
8762
+ return new Promise((resolve19) => {
8763
+ const timeout = setTimeout(() => resolve19(null), 3e4);
9171
8764
  function checkOutput(data) {
9172
8765
  const match = data.toString().match(/listening on :(\d+)/);
9173
8766
  if (match) {
9174
8767
  clearTimeout(timeout);
9175
- resolve21({ child, actualPort: parseInt(match[1], 10) });
8768
+ resolve19({ child, actualPort: parseInt(match[1], 10) });
9176
8769
  }
9177
8770
  }
9178
8771
  child.stdout?.on("data", checkOutput);
9179
8772
  child.stderr?.on("data", checkOutput);
9180
8773
  child.on("error", () => {
9181
8774
  clearTimeout(timeout);
9182
- resolve21(null);
8775
+ resolve19(null);
9183
8776
  });
9184
8777
  child.on("exit", () => {
9185
8778
  clearTimeout(timeout);
9186
- resolve21(null);
8779
+ resolve19(null);
9187
8780
  });
9188
8781
  });
9189
8782
  }
9190
8783
  function spawnDetached(cmd, args, cwd, logDir) {
9191
- const logsDir = logDir ?? resolve17(cwd, ".mind", "logs");
8784
+ const logsDir = logDir ?? resolve15(cwd, ".mind", "logs");
9192
8785
  mkdirSync8(logsDir, { recursive: true });
9193
- const logPath = resolve17(logsDir, "mind.log");
8786
+ const logPath = resolve15(logsDir, "mind.log");
9194
8787
  let startOffset = 0;
9195
8788
  try {
9196
- startOffset = statSync4(logPath).size;
8789
+ startOffset = statSync3(logPath).size;
9197
8790
  } catch {
9198
8791
  }
9199
8792
  const logFd = openSync(logPath, "a");
@@ -9331,11 +8924,11 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9331
8924
  return c.json({ error: `Name already in use: ${variantName}` }, 409);
9332
8925
  }
9333
8926
  const projectRoot = entry.dir ?? mindDir(mindName);
9334
- const variantDir = resolve18(projectRoot, ".variants", variantName);
9335
- if (existsSync11(variantDir)) {
8927
+ const variantDir = resolve16(projectRoot, ".variants", variantName);
8928
+ if (existsSync10(variantDir)) {
9336
8929
  return c.json({ error: `Variant directory already exists: ${variantDir}` }, 409);
9337
8930
  }
9338
- mkdirSync9(resolve18(projectRoot, ".variants"), { recursive: true });
8931
+ mkdirSync9(resolve16(projectRoot, ".variants"), { recursive: true });
9339
8932
  try {
9340
8933
  await gitExec(["worktree", "add", "-b", variantName, variantDir], { cwd: projectRoot });
9341
8934
  } catch (e) {
@@ -9371,7 +8964,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9371
8964
  const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
9372
8965
  await exec(cmd, args, {
9373
8966
  cwd: variantDir,
9374
- env: { ...process.env, HOME: resolve18(variantDir, "home") }
8967
+ env: { ...process.env, HOME: resolve16(variantDir, "home") }
9375
8968
  });
9376
8969
  } else {
9377
8970
  await exec("npm", ["install"], { cwd: variantDir });
@@ -9382,7 +8975,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9382
8975
  return c.json({ error: `npm install failed: ${msg}` }, 500);
9383
8976
  }
9384
8977
  if (body.soul) {
9385
- writeFileSync10(resolve18(variantDir, "home/SOUL.md"), body.soul);
8978
+ writeFileSync10(resolve16(variantDir, "home/SOUL.md"), body.soul);
9386
8979
  }
9387
8980
  const variantPort = body.port ?? await nextPort();
9388
8981
  try {
@@ -9465,7 +9058,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9465
9058
  logger_default.warn(`farewell turn failed for ${variantName}`, logger_default.errorData(err));
9466
9059
  }
9467
9060
  try {
9468
- if (existsSync11(variantEntry.dir)) {
9061
+ if (existsSync10(variantEntry.dir)) {
9469
9062
  const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
9470
9063
  if (status) {
9471
9064
  try {
@@ -9523,7 +9116,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9523
9116
  { conflicts: err.conflicts }
9524
9117
  );
9525
9118
  }
9526
- if (existsSync11(variantEntry.dir) && !body.discardUnresolved) {
9119
+ if (existsSync10(variantEntry.dir) && !body.discardUnresolved) {
9527
9120
  let unresolved;
9528
9121
  try {
9529
9122
  unresolved = await findUnresolvedHomeFiles(variantEntry.dir);
@@ -9548,7 +9141,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9548
9141
  await chownMindDir(projectRoot, mindName);
9549
9142
  if (variantName.endsWith("-upgrade") || variantName === "upgrade") {
9550
9143
  try {
9551
- const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-YKWMVYMM.js");
9144
+ const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-RJRMF6DT.js");
9552
9145
  const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-TRC2HJXR.js");
9553
9146
  const tmpl = parentEntry.template ?? "claude";
9554
9147
  await setMindTemplateHash2(mindName, computeTemplateHash2(tmpl));
@@ -9562,7 +9155,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9562
9155
  const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
9563
9156
  await exec(cmd, args, {
9564
9157
  cwd: projectRoot,
9565
- env: { ...process.env, HOME: resolve18(projectRoot, "home") }
9158
+ env: { ...process.env, HOME: resolve16(projectRoot, "home") }
9566
9159
  });
9567
9160
  } else {
9568
9161
  await exec("npm", ["install"], { cwd: projectRoot });
@@ -10057,11 +9650,11 @@ var app24 = new Hono28().get("/:name/conversations/:id/events", async (c) => {
10057
9650
  if (!stream.aborted) console.error("[chat] SSE ping error:", err);
10058
9651
  });
10059
9652
  }, 15e3);
10060
- await new Promise((resolve21) => {
9653
+ await new Promise((resolve19) => {
10061
9654
  stream.onAbort(() => {
10062
9655
  unsubscribe();
10063
9656
  clearInterval(keepAlive);
10064
- resolve21();
9657
+ resolve19();
10065
9658
  });
10066
9659
  });
10067
9660
  });
@@ -10245,6 +9838,7 @@ app26.get("/api/health", (c) => {
10245
9838
  ...cached?.updateAvailable ? { updateAvailable: true, latest: cached.latest } : {}
10246
9839
  });
10247
9840
  });
9841
+ app26.use("/api/ext/*", normalizeTrailingSlash(app26));
10248
9842
  app26.use("/api/activity/*", authMiddleware);
10249
9843
  app26.use("/api/minds/*", authMiddleware);
10250
9844
  app26.use("/api/conversations/*", authMiddleware);
@@ -10278,10 +9872,10 @@ app26.route("/api/conversations", conversations_default);
10278
9872
  var app_default = app26;
10279
9873
 
10280
9874
  // packages/daemon/src/web/server.ts
10281
- import { existsSync as existsSync12 } from "fs";
9875
+ import { existsSync as existsSync11 } from "fs";
10282
9876
  import { readFile as readFile2, stat as stat2 } from "fs/promises";
10283
9877
  import { createServer as createHttpsServer } from "https";
10284
- import { dirname as dirname3, extname as extname3, resolve as resolve19 } from "path";
9878
+ import { dirname as dirname3, extname as extname3, resolve as resolve17 } from "path";
10285
9879
  import { serve } from "@hono/node-server";
10286
9880
  var MIME_TYPES2 = {
10287
9881
  ".html": "text/html",
@@ -10300,8 +9894,8 @@ async function startServer({
10300
9894
  let assetsDir = "";
10301
9895
  let searchDir = dirname3(new URL(import.meta.url).pathname);
10302
9896
  for (let i = 0; i < 5; i++) {
10303
- const candidate = resolve19(searchDir, "dist", "web-assets");
10304
- if (existsSync12(candidate)) {
9897
+ const candidate = resolve17(searchDir, "dist", "web-assets");
9898
+ if (existsSync11(candidate)) {
10305
9899
  assetsDir = candidate;
10306
9900
  break;
10307
9901
  }
@@ -10311,7 +9905,7 @@ async function startServer({
10311
9905
  app_default.get("*", async (c) => {
10312
9906
  const urlPath = new URL(c.req.url).pathname;
10313
9907
  if (urlPath.startsWith("/api/") || urlPath.startsWith("/ext/")) return c.notFound();
10314
- const filePath = resolve19(assetsDir, urlPath.slice(1));
9908
+ const filePath = resolve17(assetsDir, urlPath.slice(1));
10315
9909
  if (!filePath.startsWith(assetsDir)) return c.text("Forbidden", 403);
10316
9910
  const s = await stat2(filePath).catch(() => null);
10317
9911
  if (s?.isFile()) {
@@ -10324,7 +9918,7 @@ async function startServer({
10324
9918
  const cacheControl = isHashed ? "public, max-age=31536000, immutable" : "no-cache";
10325
9919
  return c.body(body, 200, { "Content-Type": mime, "Cache-Control": cacheControl });
10326
9920
  }
10327
- const indexPath = resolve19(assetsDir, "index.html");
9921
+ const indexPath = resolve17(assetsDir, "index.html");
10328
9922
  const indexStat = await stat2(indexPath).catch(() => null);
10329
9923
  if (indexStat?.isFile()) {
10330
9924
  const body = await readFile2(indexPath, "utf-8");
@@ -10341,10 +9935,10 @@ async function startServer({
10341
9935
  createServer: createHttpsServer,
10342
9936
  serverOptions: { key: tls.key, cert: tls.cert }
10343
9937
  });
10344
- await new Promise((resolve21, reject) => {
9938
+ await new Promise((resolve19, reject) => {
10345
9939
  server2.on("listening", () => {
10346
9940
  logger_default.info("Volute UI running (https)", { hostname, port });
10347
- resolve21();
9941
+ resolve19();
10348
9942
  });
10349
9943
  server2.on("error", (err) => {
10350
9944
  reject(err);
@@ -10352,13 +9946,13 @@ async function startServer({
10352
9946
  });
10353
9947
  const internalPort = port + 1;
10354
9948
  const internalServer = serve({ fetch: app_default.fetch, port: internalPort, hostname: "127.0.0.1" });
10355
- await new Promise((resolve21, reject) => {
9949
+ await new Promise((resolve19, reject) => {
10356
9950
  internalServer.on("listening", () => {
10357
9951
  logger_default.info("Volute API running (http, internal)", {
10358
9952
  hostname: "127.0.0.1",
10359
9953
  port: internalPort
10360
9954
  });
10361
- resolve21();
9955
+ resolve19();
10362
9956
  });
10363
9957
  internalServer.on("error", (err) => {
10364
9958
  reject(err);
@@ -10367,10 +9961,10 @@ async function startServer({
10367
9961
  return { server: server2, internalPort };
10368
9962
  }
10369
9963
  const server = serve({ fetch: app_default.fetch, port, hostname });
10370
- await new Promise((resolve21, reject) => {
9964
+ await new Promise((resolve19, reject) => {
10371
9965
  server.on("listening", () => {
10372
9966
  logger_default.info("Volute API running (http)", { hostname, port });
10373
- resolve21();
9967
+ resolve19();
10374
9968
  });
10375
9969
  server.on("error", (err) => {
10376
9970
  reject(err);
@@ -10381,17 +9975,17 @@ async function startServer({
10381
9975
 
10382
9976
  // packages/daemon/src/daemon.ts
10383
9977
  if (!process.env.VOLUTE_HOME) {
10384
- process.env.VOLUTE_HOME = resolve20(homedir3(), ".volute");
9978
+ process.env.VOLUTE_HOME = resolve18(homedir3(), ".volute");
10385
9979
  }
10386
9980
  if (process.env.VOLUTE_TIMEZONE && !process.env.TZ) {
10387
9981
  process.env.TZ = process.env.VOLUTE_TIMEZONE;
10388
9982
  }
10389
9983
  function writeDaemonConfig(systemDir, config2, token) {
10390
- const configPath = resolve20(systemDir, "daemon.json");
9984
+ const configPath = resolve18(systemDir, "daemon.json");
10391
9985
  writeFileSync11(configPath, `${JSON.stringify(config2, null, 2)}
10392
9986
  `, { mode: 420 });
10393
9987
  chmodSync(configPath, 420);
10394
- const tokenPath = resolve20(systemDir, "daemon-token");
9988
+ const tokenPath = resolve18(systemDir, "daemon-token");
10395
9989
  writeFileSync11(tokenPath, `${token}
10396
9990
  `, { mode: 384 });
10397
9991
  chmodSync(tokenPath, 384);
@@ -10402,7 +9996,7 @@ async function startDaemon(opts) {
10402
9996
  const home = voluteHome();
10403
9997
  const systemDir = voluteSystemDir();
10404
9998
  if (!opts.foreground) {
10405
- const rotatingLog = new RotatingLog(resolve20(systemDir, "daemon.log"));
9999
+ const rotatingLog = new RotatingLog(resolve18(systemDir, "daemon.log"));
10406
10000
  logger_default.setOutput((line) => rotatingLog.write(`${line}
10407
10001
  `));
10408
10002
  const write = (...args) => rotatingLog.write(`${format(...args)}
@@ -10412,15 +10006,15 @@ async function startDaemon(opts) {
10412
10006
  console.warn = write;
10413
10007
  console.info = write;
10414
10008
  }
10415
- const DAEMON_PID_PATH = resolve20(systemDir, "daemon.pid");
10416
- const DAEMON_JSON_PATH = resolve20(systemDir, "daemon.json");
10417
- const DAEMON_TOKEN_PATH = resolve20(systemDir, "daemon-token");
10009
+ const DAEMON_PID_PATH = resolve18(systemDir, "daemon.pid");
10010
+ const DAEMON_JSON_PATH = resolve18(systemDir, "daemon.json");
10011
+ const DAEMON_TOKEN_PATH = resolve18(systemDir, "daemon-token");
10418
10012
  mkdirSync10(home, { recursive: true });
10419
10013
  ensureSystemDir();
10420
10014
  const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-WZSXHHRJ.js");
10421
10015
  migrateConfigSecrets();
10422
10016
  migrateSetupCompleted();
10423
- const { migrateAiModelQualification } = await import("./ai-service-YW5SWCSB.js");
10017
+ const { migrateAiModelQualification } = await import("./ai-service-KEK2V3AP.js");
10424
10018
  migrateAiModelQualification();
10425
10019
  await (await import("./db-BONH4SUG.js")).getDb();
10426
10020
  try {
@@ -10432,18 +10026,30 @@ async function startDaemon(opts) {
10432
10026
  logger_default.warn("failed to migrate system user role", logger_default.errorData(err));
10433
10027
  }
10434
10028
  try {
10435
- const { migrateAvatarSizes } = await import("./avatar-image-52WGXLHV.js");
10029
+ const { migrateAvatarSizes } = await import("./avatar-image-SN576P45.js");
10436
10030
  await migrateAvatarSizes();
10437
10031
  } catch (err) {
10438
10032
  logger_default.warn("avatar size migration failed", logger_default.errorData(err));
10439
10033
  }
10440
10034
  try {
10441
- const { migrateThreadConfigs } = await import("./migrate-thread-config-EQSEP2XG.js");
10035
+ const { migrateThreadConfigs } = await import("./migrate-thread-config-SVF2M3D3.js");
10442
10036
  await migrateThreadConfigs();
10443
10037
  } catch (err) {
10444
10038
  logger_default.warn("session\u2192thread config migration failed", logger_default.errorData(err));
10445
10039
  }
10446
- const { initSandbox } = await import("./sandbox-NNWCTHRI.js");
10040
+ try {
10041
+ const { migrateNamePlaceholders } = await import("./migrate-name-placeholder-64AEAWPE.js");
10042
+ await migrateNamePlaceholders();
10043
+ } catch (err) {
10044
+ logger_default.warn("{{name}} placeholder migration failed", logger_default.errorData(err));
10045
+ }
10046
+ try {
10047
+ const { migrateInitInfrastructure } = await import("./migrate-init-infrastructure-Z72UJ5NT.js");
10048
+ await migrateInitInfrastructure();
10049
+ } catch (err) {
10050
+ logger_default.warn("`.init/` infrastructure backfill failed", logger_default.errorData(err));
10051
+ }
10052
+ const { initSandbox } = await import("./sandbox-VI7XWBIA.js");
10447
10053
  await initSandbox();
10448
10054
  try {
10449
10055
  await syncBuiltinSkills();
@@ -10475,7 +10081,7 @@ async function startDaemon(opts) {
10475
10081
  logger_default.warn("failed to backfill minds into #system", logger_default.errorData(err));
10476
10082
  }
10477
10083
  try {
10478
- const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-KRDSM55Q.js");
10084
+ const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-Y27LTNZK.js");
10479
10085
  await getOrCreateSystemUser2();
10480
10086
  } catch (err) {
10481
10087
  logger_default.warn(
@@ -10489,7 +10095,7 @@ async function startDaemon(opts) {
10489
10095
  let tls;
10490
10096
  if (opts.tailscale || globalCfg.tailscale) {
10491
10097
  try {
10492
- const { getTailscaleTls } = await import("./tailscale-KHNZFC7L.js");
10098
+ const { getTailscaleTls } = await import("./tailscale-F2IMBILZ.js");
10493
10099
  const tlsConfig = await getTailscaleTls();
10494
10100
  tls = { key: tlsConfig.key, cert: tlsConfig.cert };
10495
10101
  logger_default.info("Tailscale HTTPS enabled", { hostname: tlsConfig.hostname });
@@ -10543,7 +10149,7 @@ async function startDaemon(opts) {
10543
10149
  const orphanedTurns = await completeOrphanedTurns();
10544
10150
  summarizeOrphanedTurns(orphanedTurns);
10545
10151
  try {
10546
- const { reconcileVariants } = await import("./variant-cleanup-CZDLIY3F.js");
10152
+ const { reconcileVariants } = await import("./variant-cleanup-JGJZ5KB4.js");
10547
10153
  await reconcileVariants();
10548
10154
  } catch (err) {
10549
10155
  logger_default.error("failed to reconcile variants", logger_default.errorData(err));
@@ -10579,16 +10185,17 @@ async function startDaemon(opts) {
10579
10185
  try {
10580
10186
  const { isSetupComplete: isSetupComplete2, getSpiritName: getSpiritName2 } = await import("./setup-WZSXHHRJ.js");
10581
10187
  if (isSetupComplete2()) {
10582
- const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-I5ECLGRI.js");
10583
- const { startSpiritFull } = await import("./mind-service-WHFBUKZE.js");
10188
+ const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-FKXMGO3N.js");
10189
+ const { startSpiritFull } = await import("./mind-service-ZJCUBAUL.js");
10584
10190
  await ensureSpiritProject();
10585
10191
  const spiritName = getSpiritName2();
10586
10192
  const spiritEntry = await findMind(spiritName);
10587
10193
  if (spiritEntry?.dir) {
10588
- const { registerMindDir } = await import("./delivery-router-RHANNTAC.js");
10194
+ const { registerMindDir } = await import("./delivery-router-KHBVEVVL.js");
10589
10195
  registerMindDir(spiritName, spiritEntry.dir);
10590
10196
  }
10591
10197
  await syncSpiritTemplate();
10198
+ if (spiritEntry) await notifyExtensionsSpiritReady();
10592
10199
  if (spiritEntry && !manager.isRunning(spiritName)) {
10593
10200
  await startSpiritFull(spiritName);
10594
10201
  }
@@ -10599,7 +10206,7 @@ async function startDaemon(opts) {
10599
10206
  bridgeManager.startBridges(daemonPort).catch((err) => {
10600
10207
  logger_default.warn("failed to start bridges", logger_default.errorData(err));
10601
10208
  });
10602
- import("./cloud-sync-MJVJ33LD.js").then(
10209
+ import("./cloud-sync-FM73SVFJ.js").then(
10603
10210
  ({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
10604
10211
  logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
10605
10212
  })
@@ -10607,12 +10214,14 @@ async function startDaemon(opts) {
10607
10214
  logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
10608
10215
  });
10609
10216
  try {
10610
- const { backfillTemplateHashes, notifyVersionUpdate, warnStaleTemplates } = await import("./version-notify-SJVAQLZI.js");
10611
- backfillTemplateHashes().then(() => warnStaleTemplates()).catch((err) => {
10612
- logger_default.warn("failed to check template staleness", logger_default.errorData(err));
10613
- });
10217
+ const { backfillTemplateHashes, notifyVersionUpdate, warnStaleTemplates } = await import("./version-notify-KIXYNHJC.js");
10614
10218
  notifyVersionUpdate().catch((err) => {
10615
10219
  logger_default.warn("failed to send version update notifications", logger_default.errorData(err));
10220
+ }).then(() => backfillTemplateHashes()).then(() => warnStaleTemplates()).then(async () => {
10221
+ const { runAutoUpgrades } = await import("./auto-upgrade-2MZF7NG3.js");
10222
+ await runAutoUpgrades();
10223
+ }).catch((err) => {
10224
+ logger_default.warn("template staleness/auto-upgrade pass failed", logger_default.errorData(err));
10616
10225
  });
10617
10226
  } catch (err) {
10618
10227
  logger_default.warn("failed to initialize version notifications", logger_default.errorData(err));
@@ -10621,6 +10230,9 @@ async function startDaemon(opts) {
10621
10230
  logger_default.warn("failed to restore delivery queue", logger_default.errorData(err));
10622
10231
  });
10623
10232
  delivery.startRedrive();
10233
+ delivery.releaseGatedSweep().catch((err) => {
10234
+ logger_default.warn("failed to sweep gated messages", logger_default.errorData(err));
10235
+ });
10624
10236
  cleanExpiredSessions().catch((err) => {
10625
10237
  logger_default.warn("failed to clean expired sessions", logger_default.errorData(err));
10626
10238
  });