volute 0.34.0 → 0.35.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 (209) hide show
  1. package/README.md +7 -6
  2. package/dist/accept-ZBDVVCEU.js +42 -0
  3. package/dist/{activity-events-BN7V6KCC.js → activity-events-ZW4SDL2C.js} +4 -4
  4. package/dist/{ai-service-PSILB5WD.js → ai-service-LURBEDDB.js} +5 -5
  5. package/dist/{api-client-XUXOB7LI.js → api-client-3A77HMH7.js} +1 -1
  6. package/dist/api.d.ts +1 -5618
  7. package/dist/{archive-C2VEMQOR.js → archive-ESU2FUN4.js} +3 -3
  8. package/dist/{auth-ZFZXJZDQ.js → auth-WX4TESEI.js} +5 -5
  9. package/dist/bridge-PXIO6PS2.js +206 -0
  10. package/dist/chat-QXAJF3FU.js +51 -0
  11. package/dist/{chunk-7F2SW2KD.js → chunk-2TGZJFAT.js} +3 -3
  12. package/dist/{chunk-6LXAAQ43.js → chunk-33ODGMFZ.js} +1 -1
  13. package/dist/{chunk-4JSR7YO7.js → chunk-5N7Y5WAM.js} +1 -1
  14. package/dist/{chunk-FYCALD4Q.js → chunk-5T5YMX6S.js} +1 -1
  15. package/dist/{chunk-B2BVAIZ4.js → chunk-5XJYUFZH.js} +21 -15
  16. package/dist/{chunk-M3K5AARV.js → chunk-A2ZLHBHG.js} +2 -2
  17. package/dist/{chunk-U5BTYSAL.js → chunk-AN2W47GW.js} +2 -2
  18. package/dist/{chunk-G53F3JA4.js → chunk-AOB6GVRM.js} +1 -1
  19. package/dist/{chunk-N7BLAHNE.js → chunk-BDYXIWA5.js} +5 -5
  20. package/dist/{chunk-YUIHSKR6.js → chunk-BKF4WQCY.js} +2 -2
  21. package/dist/{chunk-6OWJXUAR.js → chunk-BMZQYACC.js} +2 -2
  22. package/dist/{chunk-NAOW2CLO.js → chunk-BTY4WNFE.js} +1 -1
  23. package/dist/{chunk-MLOQKQNB.js → chunk-BV65KRHM.js} +2 -2
  24. package/dist/{chunk-XWXBJQBE.js → chunk-CORXD635.js} +4 -4
  25. package/dist/{chunk-PVY5W6QN.js → chunk-F7ZNLYKZ.js} +2 -2
  26. package/dist/{chunk-BFWHBQK4.js → chunk-FT5KETXZ.js} +3 -3
  27. package/dist/{chunk-N3DNFPVA.js → chunk-IJHIXLVN.js} +8 -8
  28. package/dist/{chunk-V6ZCNULL.js → chunk-J6CJQDWI.js} +37 -28
  29. package/dist/{chunk-4RQBJWQX.js → chunk-LOPXTW6H.js} +1 -1
  30. package/dist/{chunk-47ZPNLF4.js → chunk-MDJGMOSD.js} +8 -137
  31. package/dist/{chunk-BTWAGDV5.js → chunk-N446KRP7.js} +3 -3
  32. package/dist/{chunk-6WAWMWR5.js → chunk-N5LMGYXX.js} +2 -2
  33. package/dist/{chunk-G6BSYHPK.js → chunk-NJK5SDGR.js} +1 -1
  34. package/dist/{chunk-D424ZQGI.js → chunk-O7IGP7ZW.js} +11 -3
  35. package/dist/{chunk-2IOP6PHB.js → chunk-OTC67N2Z.js} +2 -2
  36. package/dist/{chunk-V45JXOWY.js → chunk-PWQ2ITYG.js} +4 -4
  37. package/dist/{chunk-KTLFDYPT.js → chunk-QCH6K235.js} +1 -1
  38. package/dist/chunk-QHG4OMZL.js +145 -0
  39. package/dist/{chunk-IS7WJ56Q.js → chunk-QWTR6AWZ.js} +3 -3
  40. package/dist/chunk-TXSA4Q3V.js +116 -0
  41. package/dist/{chunk-BDK73LK6.js → chunk-VHJRZM2S.js} +2 -2
  42. package/dist/{chunk-SSI47XP2.js → chunk-VHWGEJ4V.js} +1 -1
  43. package/dist/chunk-VY3RB2V7.js +164 -0
  44. package/dist/chunk-WJPROOU5.js +8314 -0
  45. package/dist/{chunk-E5C7OWZ2.js → chunk-WZRZFFCL.js} +8 -8
  46. package/dist/{chunk-BM474GX6.js → chunk-XRQSAMX2.js} +4 -4
  47. package/dist/{chunk-OYAKCAVY.js → chunk-ZSR72JB3.js} +1 -1
  48. package/dist/{chunk-PLDWHR4D.js → chunk-ZX7EAV5J.js} +17 -7
  49. package/dist/cli.js +90 -29
  50. package/dist/clock-HSEKS5AR.js +289 -0
  51. package/dist/{cloud-sync-TG3TIX5H.js → cloud-sync-6JL4C24T.js} +21 -22
  52. package/dist/config-UTS7QULS.js +76 -0
  53. package/dist/connectors/discord-bridge.js +3 -3
  54. package/dist/connectors/slack-bridge.js +3 -3
  55. package/dist/connectors/telegram-bridge.js +3 -3
  56. package/dist/{conversations-HL2JP5GI.js → conversations-2PW57WO2.js} +5 -5
  57. package/dist/create-5BPOOJAN.js +75 -0
  58. package/dist/create-UVCK2CS6.js +50 -0
  59. package/dist/daemon-client-RVIKXGFQ.js +12 -0
  60. package/dist/daemon-restart-HSZ3BCX5.js +65 -0
  61. package/dist/daemon.js +845 -1766
  62. package/dist/{db-PLEDCBHZ.js → db-BDMH4SZ2.js} +7 -3
  63. package/dist/{db-RYX3SS2W.js → db-BVBJ57TU.js} +2 -2
  64. package/dist/delete-L5PAVDGQ.js +42 -0
  65. package/dist/delivery-manager-H5ZVBMCQ.js +31 -0
  66. package/dist/{delivery-router-D5ELDMS2.js → delivery-router-HEJSJAHQ.js} +4 -4
  67. package/dist/down-74VXM45A.js +17 -0
  68. package/dist/env-E4XHO2BI.js +223 -0
  69. package/dist/{exec-DVLXKRIO.js → exec-PY7THYH4.js} +4 -4
  70. package/dist/export-OAS6QVBN.js +113 -0
  71. package/dist/{extension-PM42QCID.js → extension-D74CNM7G.js} +25 -33
  72. package/dist/{extensions-BBGVL5JC.js → extensions-XDDFY72A.js} +22 -11
  73. package/dist/files-CWTK6V3H.js +53 -0
  74. package/dist/import-5A3T7QV4.js +143 -0
  75. package/dist/{isolation-62MKDZN3.js → isolation-TK5RX2WM.js} +3 -3
  76. package/dist/join-DF5XSJAC.js +67 -0
  77. package/dist/list-PDMQM7ZV.js +53 -0
  78. package/dist/login-7TE6CIZF.js +60 -0
  79. package/dist/login-GOTAYLXP.js +51 -0
  80. package/dist/logout-6KIA74EV.js +29 -0
  81. package/dist/logout-T4XS6LRU.js +50 -0
  82. package/dist/message-delivery-GRC4W6P7.js +41 -0
  83. package/dist/mind-5IEYKV7I.js +97 -0
  84. package/dist/{mind-activity-tracker-2ACNHA7B.js → mind-activity-tracker-QBLIV7ZJ.js} +5 -5
  85. package/dist/{mind-history-WOYFLQAI.js → mind-history-IE2QH7U5.js} +82 -71
  86. package/dist/mind-list-GEWHWAL4.js +38 -0
  87. package/dist/mind-manager-HFLB5653.js +31 -0
  88. package/dist/mind-profile-DCBDVF5B.js +53 -0
  89. package/dist/mind-service-X2CAA6W6.js +37 -0
  90. package/dist/mind-sleep-ITCF6OQA.js +47 -0
  91. package/dist/mind-status-X4SX3YUG.js +65 -0
  92. package/dist/mind-wake-KXMKMGWX.js +42 -0
  93. package/dist/{package-V2WHWVG6.js → package-D2FSVFAX.js} +5 -5
  94. package/dist/read-67VRP2DO.js +91 -0
  95. package/dist/{read-stdin-PIRM6A2Y.js → read-stdin-3X5VYKNS.js} +1 -1
  96. package/dist/register-SB7NXCOE.js +51 -0
  97. package/dist/{registry-UYV5S6QT.js → registry-GBSNW3HG.js} +2 -2
  98. package/dist/reject-MUR2KWJ4.js +40 -0
  99. package/dist/restart-5EGG4JXU.js +42 -0
  100. package/dist/{sandbox-SI5HMBP3.js → sandbox-R37VIU36.js} +5 -5
  101. package/dist/scheduler-Y7O4CJXL.js +31 -0
  102. package/dist/{schema-ETMABTW4.js → schema-XVZ2CLKW.js} +1 -1
  103. package/dist/{seed-WNGI6PNW.js → seed-EQORWX77.js} +2 -2
  104. package/dist/seed-check-KJNTL72M.js +35 -0
  105. package/dist/seed-cmd-ZM2XGVU2.js +30 -0
  106. package/dist/seed-create-DRWGGHEI.js +113 -0
  107. package/dist/seed-sprout-JYXGXOP3.js +148 -0
  108. package/dist/send-JBJJQ7CA.js +409 -0
  109. package/dist/service-WNPCNHOX.js +121 -0
  110. package/dist/{setup-Z3DEVWV7.js → setup-BJ4YAY26.js} +153 -127
  111. package/dist/{setup-GGMKENLN.js → setup-RHJRFURI.js} +3 -3
  112. package/dist/skill-TAAKEYBV.js +389 -0
  113. package/dist/skills/volute-mind/SKILL.md +3 -7
  114. package/dist/skills/volute-mind/references/extensions.md +8 -11
  115. package/dist/{skills-Q6VZ2UGD.js → skills-EKMCQ46K.js} +7 -7
  116. package/dist/sleep-manager-7KFK3USC.js +35 -0
  117. package/dist/spirit-ZFRDXMG7.js +23 -0
  118. package/dist/split-AWVOYOPZ.js +64 -0
  119. package/dist/{sprout-E3HJIV2Z.js → sprout-HE4TITMK.js} +2 -2
  120. package/dist/start-3UXOPXQG.js +39 -0
  121. package/dist/status-ZK34WYIM.js +125 -0
  122. package/dist/stop-3XYIBGFM.js +41 -0
  123. package/dist/system-chat-IDPHYHY4.js +35 -0
  124. package/dist/systems-O43WGQY6.js +52 -0
  125. package/dist/{tailscale-ZEUK7GKZ.js → tailscale-ZIZ2HWJ5.js} +4 -4
  126. package/dist/{template-hash-EJRTKE36.js → template-hash-A7FNHTB7.js} +2 -2
  127. package/dist/up-77ICEDEW.js +19 -0
  128. package/dist/update-ANE5ZM7F.js +225 -0
  129. package/dist/{update-check-X3YG4WVP.js → update-check-UV55CBEP.js} +3 -3
  130. package/dist/upgrade-ZMDGC7M2.js +74 -0
  131. package/dist/variant-QWL2WSRI.js +62 -0
  132. package/dist/{version-notify-YCH4UVQ2.js → version-notify-FXSEMXWW.js} +28 -27
  133. package/dist/{volute-config-WBKYJGYQ.js → volute-config-D2XVS2YI.js} +1 -1
  134. package/dist/web-assets/assets/index-BhxWKvbB.css +1 -0
  135. package/dist/web-assets/assets/index-CHVKJ9II.js +75 -0
  136. package/dist/web-assets/index.html +2 -2
  137. package/dist/web-assets/sw.js +117 -0
  138. package/package.json +5 -5
  139. package/packages/extensions/pages/dist/ui/assets/index-DKZLNMED.js +2 -0
  140. package/packages/extensions/pages/dist/ui/index.html +1 -1
  141. package/packages/extensions/pages/skills/pages/SKILL.md +84 -9
  142. package/templates/_base/src/lib/auto-commit.ts +8 -8
  143. package/templates/_base/src/lib/volute-server.ts +6 -0
  144. package/templates/claude/src/agent.ts +8 -1
  145. package/dist/accept-TW6V4WI4.js +0 -42
  146. package/dist/bridge-O753D5F4.js +0 -207
  147. package/dist/chat-BHYX7DJ4.js +0 -68
  148. package/dist/chunk-47XDEWWV.js +0 -156
  149. package/dist/chunk-CVL5IGIR.js +0 -2084
  150. package/dist/chunk-PB65JZK2.js +0 -85
  151. package/dist/chunk-TAHX36HZ.js +0 -3679
  152. package/dist/clock-3X4DSC2N.js +0 -281
  153. package/dist/config-OROA5DUA.js +0 -72
  154. package/dist/create-3SEKKI6P.js +0 -71
  155. package/dist/create-UOSOQ2HN.js +0 -44
  156. package/dist/daemon-client-WOAQXXBM.js +0 -12
  157. package/dist/daemon-restart-5ABHNXJZ.js +0 -52
  158. package/dist/delete-KYOVWR23.js +0 -35
  159. package/dist/delivery-manager-2BR5NZKF.js +0 -32
  160. package/dist/down-QVFN4UPK.js +0 -15
  161. package/dist/env-R34DT7XL.js +0 -195
  162. package/dist/export-6ZXAXATG.js +0 -112
  163. package/dist/files-VQV2VZQO.js +0 -47
  164. package/dist/import-MK2I2T6F.js +0 -23
  165. package/dist/join-DGYHTJUH.js +0 -66
  166. package/dist/list-C644WTHV.js +0 -49
  167. package/dist/login-IIGEQPHL.js +0 -47
  168. package/dist/login-KZQLMAWE.js +0 -47
  169. package/dist/logout-AGTZVRGP.js +0 -40
  170. package/dist/logout-KD6GXIJJ.js +0 -21
  171. package/dist/message-delivery-V3R6NXJP.js +0 -42
  172. package/dist/mind-BI4EPBVZ.js +0 -108
  173. package/dist/mind-list-6VPM7GUQ.js +0 -30
  174. package/dist/mind-manager-MWW3BTS4.js +0 -32
  175. package/dist/mind-profile-WPG42U5Y.js +0 -47
  176. package/dist/mind-service-VIKZJK2M.js +0 -38
  177. package/dist/mind-sleep-XDISJY74.js +0 -42
  178. package/dist/mind-status-7FTZWPZF.js +0 -56
  179. package/dist/mind-wake-KIIKEI3A.js +0 -37
  180. package/dist/read-H5C26YO7.js +0 -85
  181. package/dist/register-J27WP33N.js +0 -47
  182. package/dist/reject-OEANJYIA.js +0 -40
  183. package/dist/restart-V5EGYBJG.js +0 -33
  184. package/dist/scheduler-AGG3L2FO.js +0 -32
  185. package/dist/seed-check-PXTH7YXS.js +0 -32
  186. package/dist/seed-cmd-VENFTGS3.js +0 -36
  187. package/dist/seed-create-663ALOKH.js +0 -112
  188. package/dist/seed-sprout-EH3AGKAI.js +0 -132
  189. package/dist/send-7FUUUZZH.js +0 -386
  190. package/dist/skill-DKNYJS4P.js +0 -362
  191. package/dist/skills/shared-files/SKILL.md +0 -44
  192. package/dist/skills/shared-files/scripts/merge.ts +0 -72
  193. package/dist/skills/shared-files/scripts/pull.ts +0 -52
  194. package/dist/sleep-manager-BJK2ROPX.js +0 -36
  195. package/dist/spirit-4JP4TY4C.js +0 -23
  196. package/dist/split-3YPMS2CL.js +0 -63
  197. package/dist/start-W3TPKX4D.js +0 -33
  198. package/dist/status-4OVFXFEJ.js +0 -115
  199. package/dist/stop-GTT6YWYO.js +0 -32
  200. package/dist/system-channel-DXD2JBOU.js +0 -36
  201. package/dist/system-chat-TYLOL7SX.js +0 -36
  202. package/dist/systems-AYLO727G.js +0 -61
  203. package/dist/up-PA7F2CXE.js +0 -18
  204. package/dist/update-HG4LCUSG.js +0 -215
  205. package/dist/upgrade-YGNIDICG.js +0 -67
  206. package/dist/variant-MZUMRTQO.js +0 -41
  207. package/dist/web-assets/assets/index-DiiwC-CZ.css +0 -1
  208. package/dist/web-assets/assets/index-d6y5b9Ij.js +0 -75
  209. package/packages/extensions/pages/dist/ui/assets/index-tLTROSk5.js +0 -2
package/dist/daemon.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  checkForUpdate,
4
4
  checkForUpdateCached,
5
5
  getCurrentVersion
6
- } from "./chunk-2IOP6PHB.js";
6
+ } from "./chunk-OTC67N2Z.js";
7
7
  import {
8
8
  computeTemplateHash
9
- } from "./chunk-PVY5W6QN.js";
9
+ } from "./chunk-F7ZNLYKZ.js";
10
10
  import {
11
11
  acceptPending,
12
12
  formatFileSize,
@@ -14,7 +14,7 @@ import {
14
14
  rejectPending,
15
15
  stageFile,
16
16
  validateFilePath
17
- } from "./chunk-MLOQKQNB.js";
17
+ } from "./chunk-BV65KRHM.js";
18
18
  import {
19
19
  PROMPT_DEFAULTS,
20
20
  PROMPT_KEYS,
@@ -25,12 +25,16 @@ import {
25
25
  completeOrphanedTurns,
26
26
  completeTurn,
27
27
  createTurn,
28
+ deleteSystemsConfig,
28
29
  deliverMessage,
29
30
  ensureSystemChannel,
30
31
  generateSystemReply,
31
32
  getActiveTurnId,
33
+ getAllDiscoveredExtensions,
32
34
  getDeliveryManager,
35
+ getExtensionStandardSkills,
33
36
  getLastToolUseEventId,
37
+ getLoadedExtensions,
34
38
  getMindManager,
35
39
  getMindPromptDefaults,
36
40
  getPrompt,
@@ -44,46 +48,43 @@ import {
44
48
  initMindManager,
45
49
  initScheduler,
46
50
  initSleepManager,
51
+ initSummarizer,
47
52
  initTokenBudget,
53
+ installNpmExtension,
48
54
  isConversationId,
49
55
  joinSystemChannel,
50
56
  linkToolResultToTurn,
57
+ loadAllExtensions,
58
+ notifyExtensionsDaemonStart,
59
+ notifyExtensionsDaemonStop,
51
60
  publish as publish2,
52
61
  publishTypingForChannels,
62
+ readSystemsConfig,
53
63
  recordInbound,
54
64
  recordOutbound,
55
65
  resolveMindToken,
66
+ setExtensionEnabled,
56
67
  startMindFull,
57
68
  stopMindFull,
58
69
  subscribe as subscribe3,
59
70
  subscribeAll,
60
71
  substitute,
72
+ summarizeOrphanedTurns,
73
+ summarizeTurn,
61
74
  tagUntaggedInbound,
62
75
  tagUntaggedOutbound,
63
- trackToolUse
64
- } from "./chunk-TAHX36HZ.js";
65
- import {
66
- deleteSystemsConfig,
67
- getAllDiscoveredExtensions,
68
- getExtensionStandardSkills,
69
- getLoadedExtensions,
70
- installNpmExtension,
71
- loadAllExtensions,
72
- notifyExtensionsDaemonStart,
73
- notifyExtensionsDaemonStop,
74
- readSystemsConfig,
75
- setExtensionEnabled,
76
+ trackToolUse,
76
77
  uninstallNpmExtension,
77
78
  writeSystemsConfig
78
- } from "./chunk-CVL5IGIR.js";
79
- import "./chunk-B2BVAIZ4.js";
79
+ } from "./chunk-WJPROOU5.js";
80
+ import "./chunk-5XJYUFZH.js";
80
81
  import {
81
82
  applyInitFiles,
82
83
  composeTemplate,
83
84
  copyTemplateToDir,
84
85
  findTemplatesRoot,
85
86
  listFiles
86
- } from "./chunk-G53F3JA4.js";
87
+ } from "./chunk-AOB6GVRM.js";
87
88
  import {
88
89
  SEED_SKILLS,
89
90
  STANDARD_SKILLS,
@@ -103,45 +104,16 @@ import {
103
104
  syncBuiltinSkills,
104
105
  uninstallSkill,
105
106
  updateSkill
106
- } from "./chunk-N3DNFPVA.js";
107
- import {
108
- readVoluteConfig,
109
- writeVoluteConfig
110
- } from "./chunk-OYAKCAVY.js";
111
- import "./chunk-V45JXOWY.js";
107
+ } from "./chunk-IJHIXLVN.js";
112
108
  import {
113
109
  extractTextContent
114
- } from "./chunk-IS7WJ56Q.js";
110
+ } from "./chunk-QWTR6AWZ.js";
115
111
  import {
116
112
  getActiveMinds,
117
113
  onMindEvent,
118
114
  stopAll
119
- } from "./chunk-BTWAGDV5.js";
120
- import {
121
- findBridgeForChannel,
122
- findOpenClawSession,
123
- getBridgeConfig,
124
- importOpenClawConnectors,
125
- importPiSession,
126
- parseNameFromIdentity,
127
- readBridgesConfig,
128
- removeBridgeConfig,
129
- removeChannelMapping,
130
- resolveChannelMapping,
131
- setBridgeConfig,
132
- setChannelMapping
133
- } from "./chunk-47ZPNLF4.js";
134
- import {
135
- loadMergedEnv,
136
- mindEnvPath,
137
- readEnv,
138
- sharedEnvPath,
139
- writeEnv
140
- } from "./chunk-M3K5AARV.js";
141
- import {
142
- isHomeOnlyArchive
143
- } from "./chunk-6WAWMWR5.js";
144
- import "./chunk-PB65JZK2.js";
115
+ } from "./chunk-N446KRP7.js";
116
+ import "./chunk-QHG4OMZL.js";
145
117
  import {
146
118
  approveUser,
147
119
  changePassword,
@@ -160,7 +132,7 @@ import {
160
132
  syncMindProfile,
161
133
  updateUserProfile,
162
134
  verifyUser
163
- } from "./chunk-BM474GX6.js";
135
+ } from "./chunk-XRQSAMX2.js";
164
136
  import {
165
137
  addMessage,
166
138
  createChannel,
@@ -188,13 +160,41 @@ import {
188
160
  publish,
189
161
  setConversationPrivate,
190
162
  subscribe as subscribe2
191
- } from "./chunk-E5C7OWZ2.js";
163
+ } from "./chunk-WZRZFFCL.js";
192
164
  import {
193
165
  broadcast,
194
166
  subscribe
195
- } from "./chunk-XWXBJQBE.js";
167
+ } from "./chunk-CORXD635.js";
168
+ import {
169
+ readVoluteConfig,
170
+ writeVoluteConfig
171
+ } from "./chunk-ZSR72JB3.js";
172
+ import "./chunk-PWQ2ITYG.js";
173
+ import {
174
+ findBridgeForChannel,
175
+ findOpenClawSession,
176
+ getBridgeConfig,
177
+ importOpenClawConnectors,
178
+ importPiSession,
179
+ parseNameFromIdentity,
180
+ readBridgesConfig,
181
+ removeBridgeConfig,
182
+ removeChannelMapping,
183
+ resolveChannelMapping,
184
+ setBridgeConfig,
185
+ setChannelMapping
186
+ } from "./chunk-MDJGMOSD.js";
187
+ import {
188
+ loadMergedEnv,
189
+ mindEnvPath,
190
+ readEnv,
191
+ sharedEnvPath,
192
+ writeEnv
193
+ } from "./chunk-A2ZLHBHG.js";
194
+ import {
195
+ isHomeOnlyArchive
196
+ } from "./chunk-N5LMGYXX.js";
196
197
  import {
197
- aiCompleteUtility,
198
198
  getAiConfig,
199
199
  getAvailableModels,
200
200
  getConfiguredProviders,
@@ -209,38 +209,33 @@ import {
209
209
  setEnabledModels,
210
210
  setUtilityModel,
211
211
  unqualifyModelId
212
- } from "./chunk-BFWHBQK4.js";
212
+ } from "./chunk-FT5KETXZ.js";
213
213
  import {
214
214
  logBuffer,
215
215
  logger_default
216
- } from "./chunk-YUIHSKR6.js";
217
- import "./chunk-D424ZQGI.js";
216
+ } from "./chunk-BKF4WQCY.js";
218
217
  import {
219
218
  exec,
220
219
  gitExec,
221
220
  resolveVoluteBin
222
- } from "./chunk-U5BTYSAL.js";
221
+ } from "./chunk-AN2W47GW.js";
223
222
  import {
224
223
  chownMindDir,
225
224
  createMindUser,
226
225
  deleteMindUser,
227
226
  ensureVoluteGroup,
228
227
  isIsolationEnabled,
229
- mindUserName,
230
228
  wrapForIsolation
231
- } from "./chunk-BDK73LK6.js";
229
+ } from "./chunk-VHJRZM2S.js";
232
230
  import {
233
231
  isSetupComplete,
234
232
  readGlobalConfig,
235
233
  writeGlobalConfig
236
- } from "./chunk-6OWJXUAR.js";
237
- import {
238
- readSessionFile
239
- } from "./chunk-PLDWHR4D.js";
234
+ } from "./chunk-BMZQYACC.js";
240
235
  import {
241
236
  buildVoluteSlug,
242
237
  slugify
243
- } from "./chunk-G6BSYHPK.js";
238
+ } from "./chunk-NJK5SDGR.js";
244
239
  import {
245
240
  addMind,
246
241
  addVariant,
@@ -263,36 +258,35 @@ import {
263
258
  validateMindName,
264
259
  voluteHome,
265
260
  voluteSystemDir
266
- } from "./chunk-N7BLAHNE.js";
261
+ } from "./chunk-BDYXIWA5.js";
267
262
  import {
268
263
  activity,
269
264
  conversationParticipants,
270
265
  conversations,
271
- messages,
272
266
  mindHistory,
273
267
  sessions,
274
268
  summaries,
275
269
  systemPrompts,
276
270
  turns,
277
271
  users
278
- } from "./chunk-4JSR7YO7.js";
272
+ } from "./chunk-5N7Y5WAM.js";
279
273
  import {
280
274
  __export
281
275
  } from "./chunk-7KJOFUNN.js";
282
276
 
283
- // src/daemon.ts
277
+ // packages/daemon/src/daemon.ts
284
278
  import { randomBytes } from "crypto";
285
- import { mkdirSync as mkdirSync11, readFileSync as readFileSync12, unlinkSync as unlinkSync2, writeFileSync as writeFileSync10 } from "fs";
279
+ import { mkdirSync as mkdirSync10, readFileSync as readFileSync11, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "fs";
286
280
  import { homedir as homedir3 } from "os";
287
- import { resolve as resolve19 } from "path";
281
+ import { resolve as resolve17 } from "path";
288
282
  import { format } from "util";
289
283
 
290
- // src/lib/daemon/bridge-manager.ts
284
+ // packages/daemon/src/lib/daemon/bridge-manager.ts
291
285
  import { spawn } from "child_process";
292
286
  import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, unlinkSync, writeFileSync } from "fs";
293
287
  import { dirname, resolve as resolve2 } from "path";
294
288
 
295
- // src/lib/bridge-defs.ts
289
+ // packages/daemon/src/lib/bridge-defs.ts
296
290
  import { existsSync, readFileSync } from "fs";
297
291
  import { resolve } from "path";
298
292
  var BUILTIN_DEFS = {
@@ -354,7 +348,7 @@ function checkMissingBridgeEnv(def, env) {
354
348
  return def.envVars.filter((v) => v.required && !env[v.name]);
355
349
  }
356
350
 
357
- // src/lib/daemon/bridge-manager.ts
351
+ // packages/daemon/src/lib/daemon/bridge-manager.ts
358
352
  var blog = logger_default.child("bridges");
359
353
  function searchUpwards(...segments) {
360
354
  let searchDir = dirname(new URL(import.meta.url).pathname);
@@ -494,8 +488,8 @@ var BridgeManager = class {
494
488
  if (!tracked) return;
495
489
  this.stopping.add(platform);
496
490
  this.bridges.delete(platform);
497
- await new Promise((resolve20) => {
498
- tracked.child.on("exit", () => resolve20());
491
+ await new Promise((resolve18) => {
492
+ tracked.child.on("exit", () => resolve18());
499
493
  try {
500
494
  if (tracked.child.pid) {
501
495
  process.kill(-tracked.child.pid, "SIGTERM");
@@ -506,7 +500,7 @@ var BridgeManager = class {
506
500
  if (err instanceof Error && err.code !== "ESRCH") {
507
501
  blog.warn(`failed to stop bridge ${platform}`, logger_default.errorData(err));
508
502
  }
509
- resolve20();
503
+ resolve18();
510
504
  }
511
505
  setTimeout(() => {
512
506
  try {
@@ -517,7 +511,7 @@ var BridgeManager = class {
517
511
  }
518
512
  } catch {
519
513
  }
520
- resolve20();
514
+ resolve18();
521
515
  }, 5e3);
522
516
  });
523
517
  this.stopping.delete(platform);
@@ -567,983 +561,54 @@ var BridgeManager = class {
567
561
  try {
568
562
  const pid = parseInt(readFileSync2(pidPath, "utf-8").trim(), 10);
569
563
  if (pid > 0) {
570
- try {
571
- process.kill(-pid, "SIGTERM");
572
- } catch {
573
- try {
574
- process.kill(pid, "SIGTERM");
575
- } catch {
576
- }
577
- }
578
- blog.warn(`killed orphan bridge ${platform} (pid ${pid})`);
579
- }
580
- } catch (err) {
581
- if (err instanceof Error && err.code !== "ESRCH") {
582
- blog.debug(`orphan bridge ${platform} cleanup: ${err}`);
583
- }
584
- }
585
- try {
586
- unlinkSync(pidPath);
587
- } catch (err) {
588
- if (err instanceof Error && err.code !== "ENOENT") {
589
- blog.warn(`failed to clean up PID file for orphan bridge ${platform}`, logger_default.errorData(err));
590
- }
591
- }
592
- }
593
- resolveBuiltinBridge(platform) {
594
- return searchUpwards("connectors", `${platform}-bridge.js`);
595
- }
596
- };
597
- var instance = null;
598
- function initBridgeManager() {
599
- if (instance) throw new Error("BridgeManager already initialized");
600
- instance = new BridgeManager();
601
- return instance;
602
- }
603
- function getBridgeManager() {
604
- if (!instance) throw new Error("BridgeManager not initialized \u2014 call initBridgeManager() first");
605
- return instance;
606
- }
607
-
608
- // src/lib/daemon/summarizer.ts
609
- import { and, desc, eq, gte, like, lt, sql } from "drizzle-orm";
610
-
611
- // src/lib/format-tool.ts
612
- function summarizeTool(name, input) {
613
- if (input && typeof input === "object") {
614
- const args = input;
615
- const val = args.path ?? args.command ?? args.query ?? args.url;
616
- if (typeof val === "string") {
617
- const brief = val.length > 60 ? `${val.slice(0, 57)}...` : val;
618
- return `[${name} ${brief}]`;
619
- }
620
- }
621
- return `[${name}]`;
622
- }
623
-
624
- // src/lib/daemon/summarizer.ts
625
- var sLog = logger_default.child("summarizer");
626
- var SYSTEM_MIND = "_system";
627
- function getPeriodKey(date, period) {
628
- switch (period) {
629
- case "hour": {
630
- const y = date.getFullYear();
631
- const m = String(date.getMonth() + 1).padStart(2, "0");
632
- const d = String(date.getDate()).padStart(2, "0");
633
- const h = String(date.getHours()).padStart(2, "0");
634
- return `${y}-${m}-${d}T${h}`;
635
- }
636
- case "day": {
637
- const y = date.getFullYear();
638
- const m = String(date.getMonth() + 1).padStart(2, "0");
639
- const d = String(date.getDate()).padStart(2, "0");
640
- return `${y}-${m}-${d}`;
641
- }
642
- case "week":
643
- return getISOWeekKey(date);
644
- case "month": {
645
- const y = date.getFullYear();
646
- const m = String(date.getMonth() + 1).padStart(2, "0");
647
- return `${y}-${m}`;
648
- }
649
- }
650
- }
651
- function getISOWeekKey(date) {
652
- const d = new Date(date.getFullYear(), date.getMonth(), date.getDate());
653
- d.setDate(d.getDate() + 4 - (d.getDay() || 7));
654
- const yearStart = new Date(d.getFullYear(), 0, 1);
655
- const weekNum = Math.ceil(((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7);
656
- return `${d.getFullYear()}-W${String(weekNum).padStart(2, "0")}`;
657
- }
658
- function getPreviousPeriodKey(key, period) {
659
- switch (period) {
660
- case "hour": {
661
- const d = /* @__PURE__ */ new Date(`${key.slice(0, 10)}T${key.slice(11)}:00:00`);
662
- d.setHours(d.getHours() - 1);
663
- return getPeriodKey(d, "hour");
664
- }
665
- case "day": {
666
- const d = /* @__PURE__ */ new Date(`${key}T00:00:00`);
667
- d.setDate(d.getDate() - 1);
668
- return getPeriodKey(d, "day");
669
- }
670
- case "week": {
671
- const d = isoWeekToDate(key);
672
- d.setDate(d.getDate() - 7);
673
- return getPeriodKey(d, "week");
674
- }
675
- case "month": {
676
- const [y, m] = key.split("-").map(Number);
677
- const d = new Date(y, m - 2, 1);
678
- return getPeriodKey(d, "month");
679
- }
680
- }
681
- }
682
- function isoWeekToDate(weekKey) {
683
- const [yearStr, weekStr] = weekKey.split("-W");
684
- const year = parseInt(yearStr, 10);
685
- const week = parseInt(weekStr, 10);
686
- const jan4 = new Date(year, 0, 4);
687
- const dayOfWeek = jan4.getDay() || 7;
688
- const monday = new Date(jan4);
689
- monday.setDate(jan4.getDate() - dayOfWeek + 1 + (week - 1) * 7);
690
- return monday;
691
- }
692
- function localDateStr(d) {
693
- const y = d.getFullYear();
694
- const m = String(d.getMonth() + 1).padStart(2, "0");
695
- const day = String(d.getDate()).padStart(2, "0");
696
- return `${y}-${m}-${day}`;
697
- }
698
- function utcDateTimeStr(d) {
699
- return d.toISOString().replace("T", " ").slice(0, 19);
700
- }
701
- function getTimeRange(periodKey, period) {
702
- switch (period) {
703
- case "hour": {
704
- const d = /* @__PURE__ */ new Date(`${periodKey.slice(0, 10)}T${periodKey.slice(11)}:00:00`);
705
- const dEnd = new Date(d.getTime() + 36e5);
706
- return { start: utcDateTimeStr(d), end: utcDateTimeStr(dEnd) };
707
- }
708
- case "day":
709
- return { start: `${periodKey} 00:00:00`, end: `${periodKey} 23:59:59` };
710
- case "week": {
711
- const monday = isoWeekToDate(periodKey);
712
- const sunday = new Date(monday);
713
- sunday.setDate(monday.getDate() + 6);
714
- return {
715
- start: `${localDateStr(monday)} 00:00:00`,
716
- end: `${localDateStr(sunday)} 23:59:59`
717
- };
718
- }
719
- case "month": {
720
- const [y, m] = periodKey.split("-").map(Number);
721
- const lastDay = new Date(y, m, 0).getDate();
722
- return {
723
- start: `${periodKey}-01 00:00:00`,
724
- end: `${periodKey}-${String(lastDay).padStart(2, "0")} 23:59:59`
725
- };
726
- }
727
- }
728
- }
729
- async function gatherTurnEvents(mind, session, doneId) {
730
- const db = await getDb();
731
- const conditions = [
732
- eq(mindHistory.mind, mind),
733
- eq(mindHistory.type, "done"),
734
- lt(mindHistory.id, doneId)
735
- ];
736
- if (session) {
737
- conditions.push(eq(mindHistory.session, session));
738
- }
739
- const prevDone = await db.select({ id: mindHistory.id }).from(mindHistory).where(and(...conditions)).orderBy(desc(mindHistory.id)).limit(1);
740
- const prevDoneId = prevDone.length > 0 ? prevDone[0].id : 0;
741
- const turnConditions = [
742
- eq(mindHistory.mind, mind),
743
- sql`${mindHistory.id} > ${prevDoneId}`,
744
- sql`${mindHistory.id} <= ${doneId}`
745
- ];
746
- if (session) {
747
- turnConditions.push(eq(mindHistory.session, session));
748
- }
749
- const events = await db.select({
750
- id: mindHistory.id,
751
- type: mindHistory.type,
752
- channel: mindHistory.channel,
753
- session: mindHistory.session,
754
- content: mindHistory.content,
755
- metadata: mindHistory.metadata,
756
- created_at: mindHistory.created_at
757
- }).from(mindHistory).where(and(...turnConditions)).orderBy(mindHistory.id);
758
- return {
759
- events,
760
- fromId: events.length > 0 ? events[0].id : doneId,
761
- toId: doneId
762
- };
763
- }
764
- async function gatherTurnEventsByTurnId(turnId) {
765
- const db = await getDb();
766
- const events = await db.select({
767
- id: mindHistory.id,
768
- type: mindHistory.type,
769
- channel: mindHistory.channel,
770
- session: mindHistory.session,
771
- content: mindHistory.content,
772
- metadata: mindHistory.metadata,
773
- created_at: mindHistory.created_at
774
- }).from(mindHistory).where(eq(mindHistory.turn_id, turnId)).orderBy(mindHistory.id);
775
- return {
776
- events,
777
- fromId: events.length > 0 ? events[0].id : 0,
778
- toId: events.length > 0 ? events[events.length - 1].id : 0
779
- };
780
- }
781
- function buildTurnDeterministicSummary(events) {
782
- const channels = /* @__PURE__ */ new Set();
783
- const tools = [];
784
- let hasInbound = false;
785
- let hasOutbound = false;
786
- for (const ev of events) {
787
- if (ev.type === "inbound") {
788
- hasInbound = true;
789
- if (ev.channel) channels.add(ev.channel);
790
- }
791
- if (ev.type === "outbound" || ev.type === "text") {
792
- hasOutbound = true;
793
- }
794
- if (ev.type === "tool_use" && ev.metadata) {
795
- try {
796
- const meta = JSON.parse(ev.metadata);
797
- if (meta.name) tools.push(meta.name);
798
- } catch (err) {
799
- sLog.debug(`failed to parse tool_use metadata for event ${ev.id}`, logger_default.errorData(err));
800
- }
801
- }
802
- }
803
- const parts = [];
804
- if (hasInbound) {
805
- const channelList = [...channels];
806
- parts.push(
807
- channelList.length > 0 ? `Received message on ${channelList.join(", ")}` : "Received message"
808
- );
809
- }
810
- if (tools.length > 0) {
811
- const unique = [...new Set(tools)];
812
- parts.push(`Used ${unique.join(", ")}`);
813
- }
814
- if (hasOutbound) {
815
- parts.push("Sent response");
816
- }
817
- return parts.length > 0 ? `${parts.join(". ")}.` : "Turn completed.";
818
- }
819
- function buildTranscript(events) {
820
- const lines = [];
821
- for (const ev of events) {
822
- switch (ev.type) {
823
- case "inbound":
824
- lines.push(`[inbound${ev.channel ? ` ${ev.channel}` : ""}] ${ev.content ?? ""}`);
825
- break;
826
- case "outbound":
827
- case "text":
828
- lines.push(`[response] ${(ev.content ?? "").slice(0, 500)}`);
829
- break;
830
- case "tool_use": {
831
- let toolInfo = "tool";
832
- if (ev.metadata) {
833
- try {
834
- const meta = JSON.parse(ev.metadata);
835
- toolInfo = summarizeTool(meta.name ?? "tool", meta.input ?? {});
836
- } catch (err) {
837
- sLog.debug(`failed to parse tool_use metadata for event ${ev.id}`, logger_default.errorData(err));
838
- }
839
- }
840
- lines.push(toolInfo);
841
- break;
842
- }
843
- case "tool_result": {
844
- const content = ev.content ?? "";
845
- let isError = false;
846
- if (ev.metadata) {
847
- try {
848
- const meta = JSON.parse(ev.metadata);
849
- isError = !!meta.is_error;
850
- } catch (err) {
851
- sLog.debug(
852
- `failed to parse tool_result metadata for event ${ev.id}`,
853
- logger_default.errorData(err)
854
- );
855
- }
856
- }
857
- lines.push(isError ? "[result error]" : `[result] ${content.slice(0, 200)}`);
858
- break;
859
- }
860
- case "thinking":
861
- lines.push(`[thinking] ${(ev.content ?? "").slice(0, 300)}`);
862
- break;
863
- }
864
- }
865
- return lines.join("\n");
866
- }
867
- async function summarizeTurn(mind, session, channel, doneId, turnId) {
868
- const { events, fromId, toId } = turnId ? await gatherTurnEventsByTurnId(turnId) : await gatherTurnEvents(mind, session, doneId);
869
- if (events.length === 0) return;
870
- const substantiveTypes = /* @__PURE__ */ new Set(["text", "outbound", "tool_use", "tool_result", "thinking"]);
871
- const hasSubstantiveOutput = events.some((ev) => substantiveTypes.has(ev.type));
872
- if (!hasSubstantiveOutput) {
873
- sLog.info(
874
- `skipping summary for interrupted turn ${turnId ?? "(no turn)"} (no substantive output)`
875
- );
876
- if (turnId) {
877
- try {
878
- const db2 = await getDb();
879
- await db2.update(mindHistory).set({ turn_id: null }).where(and(eq(mindHistory.turn_id, turnId), eq(mindHistory.type, "inbound")));
880
- await db2.update(messages).set({ turn_id: null }).where(eq(messages.turn_id, turnId));
881
- } catch (err) {
882
- sLog.error(`failed to un-tag events for interrupted turn ${turnId}`, logger_default.errorData(err));
883
- }
884
- }
885
- return;
886
- }
887
- const tools = [];
888
- for (const ev of events) {
889
- if (ev.type === "tool_use" && ev.metadata) {
890
- try {
891
- const meta = JSON.parse(ev.metadata);
892
- if (meta.name) tools.push(meta.name);
893
- } catch (err) {
894
- sLog.debug(`failed to parse tool_use metadata for event ${ev.id}`, logger_default.errorData(err));
895
- }
896
- }
897
- }
898
- const fromTime = events[0].created_at;
899
- const toTime = events[events.length - 1].created_at;
900
- let summaryText;
901
- let deterministic;
902
- const transcript = buildTranscript(events);
903
- if (transcript.trim()) {
904
- const summaryPrompt = await getPrompt("turn_summary");
905
- const aiResult = await aiCompleteUtility(summaryPrompt, transcript);
906
- if (aiResult) {
907
- summaryText = aiResult;
908
- deterministic = false;
909
- } else {
910
- summaryText = buildTurnDeterministicSummary(events);
911
- deterministic = true;
912
- }
913
- } else {
914
- summaryText = buildTurnDeterministicSummary(events);
915
- deterministic = true;
916
- }
917
- const metadata = {
918
- deterministic,
919
- tool_count: tools.length,
920
- tools: [...new Set(tools)],
921
- from_id: fromId,
922
- to_id: toId,
923
- from_time: fromTime,
924
- to_time: toTime
925
- };
926
- const periodKey = turnId ?? `${mind}-${doneId}`;
927
- const db = await getDb();
928
- let summaryId;
929
- try {
930
- const result = await db.insert(summaries).values({
931
- mind,
932
- period: "turn",
933
- period_key: periodKey,
934
- content: summaryText,
935
- metadata: JSON.stringify(metadata)
936
- }).onConflictDoNothing().returning({ id: summaries.id });
937
- summaryId = result[0]?.id;
938
- if (summaryId == null) {
939
- const existing = await db.select({ id: summaries.id }).from(summaries).where(
940
- and(
941
- eq(summaries.mind, mind),
942
- eq(summaries.period, "turn"),
943
- eq(summaries.period_key, periodKey)
944
- )
945
- ).get();
946
- summaryId = existing?.id;
947
- }
948
- } catch (err) {
949
- sLog.error(
950
- `failed to persist turn summary for ${mind} (events ${fromId}-${toId})`,
951
- logger_default.errorData(err)
952
- );
953
- return;
954
- }
955
- if (turnId && summaryId != null) {
956
- setSummaryId(turnId, summaryId).catch((err) => {
957
- sLog.error(`failed to link summary to turn ${turnId}`, logger_default.errorData(err));
958
- });
959
- }
960
- publish2(mind, {
961
- mind,
962
- type: "summary",
963
- session,
964
- channel,
965
- content: summaryText,
966
- metadata,
967
- turnId
968
- });
969
- }
970
- async function setSummaryId(turnId, summaryId) {
971
- const db = await getDb();
972
- await db.update(turns).set({ summary_id: summaryId }).where(eq(turns.id, turnId));
973
- }
974
- function getChildPeriod(period) {
975
- switch (period) {
976
- case "hour":
977
- return "turn";
978
- case "day":
979
- return "hour";
980
- case "week":
981
- case "month":
982
- return "day";
983
- }
984
- }
985
- function getScopeInstruction(mind) {
986
- if (mind === SYSTEM_MIND) {
987
- return 'Write in third person, describing what the minds in the system did (e.g. "Alice explored...", "The system saw activity in..."). Reference minds by name.';
988
- }
989
- return 'Write in first person as the mind who performed the actions (e.g. "I explored...", "I worked on...").';
990
- }
991
- function buildPeriodicDeterministicSummary(sources, period, periodKey) {
992
- if (sources.length === 0) return "";
993
- switch (period) {
994
- case "hour":
995
- return `Activity during ${periodKey.slice(11)}:00: ${sources.join(" ")}`;
996
- case "day":
997
- return `Activity on ${periodKey}:
998
-
999
- ${sources.join("\n\n")}`;
1000
- case "week":
1001
- return `Week ${periodKey} summary:
1002
-
1003
- ${sources.join("\n\n")}`;
1004
- case "month":
1005
- return `${periodKey} summary:
1006
-
1007
- ${sources.join("\n\n")}`;
1008
- }
1009
- }
1010
- async function gatherChildSummaries(mind, period, periodKey) {
1011
- const db = await getDb();
1012
- const childPeriod = getChildPeriod(period);
1013
- if (period === "hour") {
1014
- const { start: start2, end: end2 } = getTimeRange(periodKey, "hour");
1015
- const rows2 = await db.select({ id: summaries.id, content: summaries.content }).from(summaries).where(
1016
- and(
1017
- eq(summaries.mind, mind),
1018
- eq(summaries.period, childPeriod),
1019
- gte(summaries.created_at, start2),
1020
- lt(summaries.created_at, end2)
1021
- )
1022
- ).orderBy(summaries.created_at);
1023
- return {
1024
- texts: rows2.map((r) => r.content),
1025
- sourceIds: rows2.map((r) => r.id)
1026
- };
1027
- }
1028
- if (period === "day") {
1029
- const rows2 = await db.select({ id: summaries.id, content: summaries.content }).from(summaries).where(
1030
- and(
1031
- eq(summaries.mind, mind),
1032
- eq(summaries.period, childPeriod),
1033
- like(summaries.period_key, `${periodKey}%`)
1034
- )
1035
- ).orderBy(summaries.period_key);
1036
- return {
1037
- texts: rows2.map((r) => r.content),
1038
- sourceIds: rows2.map((r) => r.id)
1039
- };
1040
- }
1041
- const { start, end } = getTimeRange(periodKey, period);
1042
- const startKey = start.slice(0, 10);
1043
- const endKey = end.slice(0, 10);
1044
- const rows = await db.select({ id: summaries.id, content: summaries.content }).from(summaries).where(
1045
- and(
1046
- eq(summaries.mind, mind),
1047
- eq(summaries.period, childPeriod),
1048
- gte(summaries.period_key, startKey),
1049
- sql`${summaries.period_key} <= ${endKey}`
1050
- )
1051
- ).orderBy(summaries.period_key);
1052
- return {
1053
- texts: rows.map((r) => r.content),
1054
- sourceIds: rows.map((r) => r.id)
1055
- };
1056
- }
1057
- async function summarizePeriod(mind, period, periodKey) {
1058
- if (await summaryExists(mind, period, periodKey)) return false;
1059
- const db = await getDb();
1060
- const sources = await gatherChildSummaries(mind, period, periodKey);
1061
- if (sources.texts.length === 0) return false;
1062
- if (sources.texts.length === 1) {
1063
- try {
1064
- await db.insert(summaries).values({
1065
- mind,
1066
- period,
1067
- period_key: periodKey,
1068
- content: sources.texts[0],
1069
- metadata: JSON.stringify({
1070
- deterministic: false,
1071
- promoted: true,
1072
- source_count: 1,
1073
- source_ids: sources.sourceIds
1074
- })
1075
- }).onConflictDoNothing();
1076
- } catch (err) {
1077
- sLog.error(
1078
- `failed to persist promoted ${period} summary for ${mind} (${periodKey})`,
1079
- logger_default.errorData(err)
1080
- );
1081
- return false;
1082
- }
1083
- sLog.info(`promoted single-child ${period} summary for ${mind} (${periodKey})`);
1084
- return true;
1085
- }
1086
- const promptKey = `meta_summary_${period}`;
1087
- const scopeInstruction = getScopeInstruction(mind);
1088
- const systemPrompt = await getPrompt(promptKey, { scope_instruction: scopeInstruction });
1089
- const userMessage = sources.texts.join("\n\n---\n\n");
1090
- let content;
1091
- let deterministic;
1092
- const aiResult = await aiCompleteUtility(systemPrompt, userMessage);
1093
- if (aiResult) {
1094
- content = aiResult;
1095
- deterministic = false;
1096
- } else {
1097
- content = buildPeriodicDeterministicSummary(sources.texts, period, periodKey);
1098
- deterministic = true;
1099
- }
1100
- const metadata = {
1101
- deterministic,
1102
- source_count: sources.texts.length,
1103
- source_ids: sources.sourceIds
1104
- };
1105
- try {
1106
- await db.insert(summaries).values({
1107
- mind,
1108
- period,
1109
- period_key: periodKey,
1110
- content,
1111
- metadata: JSON.stringify(metadata)
1112
- }).onConflictDoNothing();
1113
- } catch (err) {
1114
- sLog.error(
1115
- `failed to persist ${period} summary for ${mind} (${periodKey})`,
1116
- logger_default.errorData(err)
1117
- );
1118
- return false;
1119
- }
1120
- sLog.info(
1121
- `generated ${period} summary for ${mind} (${periodKey})${deterministic ? " [deterministic]" : ""}`
1122
- );
1123
- return true;
1124
- }
1125
- async function summarizeSystem(period, periodKey) {
1126
- if (await summaryExists(SYSTEM_MIND, period, periodKey)) return;
1127
- const db = await getDb();
1128
- const rows = await db.select({ mind: summaries.mind, content: summaries.content }).from(summaries).where(
1129
- and(
1130
- eq(summaries.period, period),
1131
- eq(summaries.period_key, periodKey),
1132
- sql`${summaries.mind} != ${SYSTEM_MIND}`
1133
- )
1134
- ).orderBy(summaries.mind);
1135
- if (rows.length === 0) return;
1136
- const minds = [...new Set(rows.map((r) => r.mind))];
1137
- const texts = rows.map((r) => `[${r.mind}] ${r.content}`);
1138
- const promptKey = `meta_summary_${period}`;
1139
- const scopeInstruction = getScopeInstruction(SYSTEM_MIND);
1140
- const systemPrompt = await getPrompt(promptKey, { scope_instruction: scopeInstruction });
1141
- const userMessage = texts.join("\n\n---\n\n");
1142
- let content;
1143
- let deterministic;
1144
- const aiResult = await aiCompleteUtility(systemPrompt, userMessage);
1145
- if (aiResult) {
1146
- content = aiResult;
1147
- deterministic = false;
1148
- } else {
1149
- content = buildPeriodicDeterministicSummary(texts, period, periodKey);
1150
- deterministic = true;
1151
- }
1152
- try {
1153
- await db.insert(summaries).values({
1154
- mind: SYSTEM_MIND,
1155
- period,
1156
- period_key: periodKey,
1157
- content,
1158
- metadata: JSON.stringify({ deterministic, minds, source_count: rows.length })
1159
- }).onConflictDoNothing();
1160
- } catch (err) {
1161
- sLog.error(`failed to persist system ${period} summary (${periodKey})`, logger_default.errorData(err));
1162
- }
1163
- }
1164
- async function mindsWithTurnSummaries(start, end) {
1165
- const db = await getDb();
1166
- const rows = await db.select({ mind: summaries.mind }).from(summaries).where(
1167
- and(
1168
- eq(summaries.period, "turn"),
1169
- gte(summaries.created_at, start),
1170
- lt(summaries.created_at, end),
1171
- sql`${summaries.mind} != ${SYSTEM_MIND}`
1172
- )
1173
- ).groupBy(summaries.mind);
1174
- return rows.map((r) => r.mind);
1175
- }
1176
- async function mindsWithSummaries(period, keyPattern) {
1177
- const db = await getDb();
1178
- const rows = await db.select({ mind: summaries.mind }).from(summaries).where(
1179
- and(
1180
- eq(summaries.period, period),
1181
- like(summaries.period_key, keyPattern),
1182
- sql`${summaries.mind} != ${SYSTEM_MIND}`
1183
- )
1184
- ).groupBy(summaries.mind);
1185
- return rows.map((r) => r.mind);
1186
- }
1187
- async function mindsWithDailySummariesInRange(startKey, endKey) {
1188
- const db = await getDb();
1189
- const rows = await db.select({ mind: summaries.mind }).from(summaries).where(
1190
- and(
1191
- eq(summaries.period, "day"),
1192
- gte(summaries.period_key, startKey),
1193
- sql`${summaries.period_key} <= ${endKey}`,
1194
- sql`${summaries.mind} != ${SYSTEM_MIND}`
1195
- )
1196
- ).groupBy(summaries.mind);
1197
- return rows.map((r) => r.mind);
1198
- }
1199
- async function processHour(periodKey) {
1200
- const { start, end } = getTimeRange(periodKey, "hour");
1201
- const minds = await mindsWithTurnSummaries(start, end);
1202
- for (const mind of minds) {
1203
- try {
1204
- await summarizePeriod(mind, "hour", periodKey);
1205
- } catch (err) {
1206
- sLog.error(`failed to summarize hour for ${mind} (${periodKey})`, logger_default.errorData(err));
1207
- }
1208
- }
1209
- if (minds.length > 0) {
1210
- await summarizeSystem("hour", periodKey);
1211
- }
1212
- }
1213
- async function processDay(periodKey) {
1214
- const minds = await mindsWithSummaries("hour", `${periodKey}%`);
1215
- for (const mind of minds) {
1216
- try {
1217
- await summarizePeriod(mind, "day", periodKey);
1218
- } catch (err) {
1219
- sLog.error(`failed to summarize day for ${mind} (${periodKey})`, logger_default.errorData(err));
1220
- }
1221
- }
1222
- if (minds.length > 0) {
1223
- await summarizeSystem("day", periodKey);
1224
- }
1225
- }
1226
- async function processWeek(periodKey) {
1227
- const { start, end } = getTimeRange(periodKey, "week");
1228
- const startKey = start.slice(0, 10);
1229
- const endKey = end.slice(0, 10);
1230
- const minds = await mindsWithDailySummariesInRange(startKey, endKey);
1231
- for (const mind of minds) {
1232
- try {
1233
- await summarizePeriod(mind, "week", periodKey);
1234
- } catch (err) {
1235
- sLog.error(`failed to summarize week for ${mind} (${periodKey})`, logger_default.errorData(err));
1236
- }
1237
- }
1238
- if (minds.length > 0) {
1239
- await summarizeSystem("week", periodKey);
1240
- }
1241
- }
1242
- async function processMonth(periodKey) {
1243
- const minds = await mindsWithSummaries("day", `${periodKey}%`);
1244
- for (const mind of minds) {
1245
- try {
1246
- await summarizePeriod(mind, "month", periodKey);
1247
- } catch (err) {
1248
- sLog.error(`failed to summarize month for ${mind} (${periodKey})`, logger_default.errorData(err));
1249
- }
1250
- }
1251
- if (minds.length > 0) {
1252
- await summarizeSystem("month", periodKey);
1253
- }
1254
- }
1255
- async function summaryExists(mind, period, periodKey) {
1256
- const db = await getDb();
1257
- const row = await db.select({ id: summaries.id }).from(summaries).where(
1258
- and(
1259
- eq(summaries.mind, mind),
1260
- eq(summaries.period, period),
1261
- eq(summaries.period_key, periodKey)
1262
- )
1263
- ).get();
1264
- return !!row;
1265
- }
1266
- async function backfill() {
1267
- const now = /* @__PURE__ */ new Date();
1268
- for (let i = 1; i <= 48; i++) {
1269
- try {
1270
- const d = new Date(now);
1271
- d.setHours(d.getHours() - i);
1272
- const key = getPeriodKey(d, "hour");
1273
- if (!await summaryExists(SYSTEM_MIND, "hour", key)) {
1274
- await processHour(key);
1275
- }
1276
- } catch (err) {
1277
- sLog.error(`backfill failed for hour -${i}`, logger_default.errorData(err));
1278
- }
1279
- }
1280
- for (let i = 1; i <= 7; i++) {
1281
- try {
1282
- const d = new Date(now);
1283
- d.setDate(d.getDate() - i);
1284
- const key = getPeriodKey(d, "day");
1285
- if (!await summaryExists(SYSTEM_MIND, "day", key)) {
1286
- await processDay(key);
1287
- }
1288
- } catch (err) {
1289
- sLog.error(`backfill failed for day -${i}`, logger_default.errorData(err));
1290
- }
1291
- }
1292
- for (let i = 1; i <= 4; i++) {
1293
- try {
1294
- const d = new Date(now);
1295
- d.setDate(d.getDate() - i * 7);
1296
- const key = getPeriodKey(d, "week");
1297
- if (!await summaryExists(SYSTEM_MIND, "week", key)) {
1298
- await processWeek(key);
1299
- }
1300
- } catch (err) {
1301
- sLog.error(`backfill failed for week -${i}`, logger_default.errorData(err));
1302
- }
1303
- }
1304
- for (let i = 1; i <= 3; i++) {
1305
- try {
1306
- const d = new Date(now);
1307
- d.setMonth(d.getMonth() - i);
1308
- const key = getPeriodKey(d, "month");
1309
- if (!await summaryExists(SYSTEM_MIND, "month", key)) {
1310
- await processMonth(key);
1311
- }
1312
- } catch (err) {
1313
- sLog.error(`backfill failed for month -${i}`, logger_default.errorData(err));
1314
- }
1315
- }
1316
- }
1317
- var Summarizer = class {
1318
- interval = null;
1319
- lastHourKey = null;
1320
- hasBackfilled = false;
1321
- start() {
1322
- this.interval = setInterval(() => this.tick(), 5 * 6e4);
1323
- this.tick();
1324
- }
1325
- stop() {
1326
- if (this.interval) {
1327
- clearInterval(this.interval);
1328
- this.interval = null;
1329
- }
1330
- }
1331
- async tick() {
1332
- try {
1333
- if (!this.hasBackfilled) {
1334
- await backfill();
1335
- this.hasBackfilled = true;
1336
- }
1337
- const now = /* @__PURE__ */ new Date();
1338
- const currentHourKey = getPeriodKey(now, "hour");
1339
- if (this.lastHourKey && this.lastHourKey !== currentHourKey) {
1340
- await processHour(this.lastHourKey);
1341
- }
1342
- this.lastHourKey = currentHourKey;
1343
- const yesterday = new Date(now);
1344
- yesterday.setDate(yesterday.getDate() - 1);
1345
- const yesterdayKey = getPeriodKey(yesterday, "day");
1346
- if (!await summaryExists(SYSTEM_MIND, "day", yesterdayKey)) {
1347
- await processDay(yesterdayKey);
1348
- }
1349
- const currentWeekKey = getPeriodKey(now, "week");
1350
- const prevWeekKey = getPreviousPeriodKey(currentWeekKey, "week");
1351
- if (!await summaryExists(SYSTEM_MIND, "week", prevWeekKey)) {
1352
- await processWeek(prevWeekKey);
1353
- }
1354
- const currentMonthKey = getPeriodKey(now, "month");
1355
- const prevMonthKey = getPreviousPeriodKey(currentMonthKey, "month");
1356
- if (!await summaryExists(SYSTEM_MIND, "month", prevMonthKey)) {
1357
- await processMonth(prevMonthKey);
1358
- }
1359
- } catch (err) {
1360
- sLog.error("tick failed", logger_default.errorData(err));
1361
- }
1362
- }
1363
- };
1364
- var instance2 = null;
1365
- function initSummarizer() {
1366
- if (instance2) throw new Error("Summarizer already initialized");
1367
- instance2 = new Summarizer();
1368
- return instance2;
1369
- }
1370
-
1371
- // src/lib/history-cleanup.ts
1372
- import { and as and2, eq as eq2, lt as lt2 } from "drizzle-orm";
1373
- var LOG_RETENTION_MS = 24 * 60 * 60 * 1e3;
1374
- async function cleanExpiredLogs() {
1375
- const db = await getDb();
1376
- const cutoff = new Date(Date.now() - LOG_RETENTION_MS).toISOString().replace("T", " ").slice(0, 19);
1377
- await db.delete(mindHistory).where(and2(eq2(mindHistory.type, "log"), lt2(mindHistory.created_at, cutoff)));
1378
- }
1379
-
1380
- // src/lib/shared.ts
1381
- import { execFileSync } from "child_process";
1382
- import { chmodSync, existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync2 } from "fs";
1383
- import { resolve as resolve3 } from "path";
1384
- function readWorktreeGitDir(worktreePath) {
1385
- const dotGit = resolve3(worktreePath, ".git");
1386
- if (!existsSync3(dotGit)) return null;
1387
- try {
1388
- const content = readFileSync3(dotGit, "utf-8").trim();
1389
- const match = content.match(/^gitdir:\s*(.+)$/);
1390
- return match ? match[1] : null;
1391
- } catch {
1392
- return null;
1393
- }
1394
- }
1395
- function sharedDir() {
1396
- return resolve3(voluteHome(), "shared");
1397
- }
1398
- async function ensureSharedRepo() {
1399
- const dir = sharedDir();
1400
- mkdirSync2(dir, { recursive: true });
1401
- if (existsSync3(resolve3(dir, ".git"))) {
1402
- try {
1403
- await gitExec(["rev-parse", "HEAD"], { cwd: dir });
1404
- return;
1405
- } catch (err) {
1406
- const msg = err instanceof Error ? err.message : String(err);
1407
- if (msg.includes("unknown revision") || msg.includes("bad default revision")) {
1408
- logger_default.warn("shared repo has no commits, re-initializing");
1409
- rmSync(resolve3(dir, ".git"), { recursive: true, force: true });
1410
- } else {
1411
- throw err;
1412
- }
1413
- }
1414
- }
1415
- const initArgs = isIsolationEnabled() ? ["init", "--shared=group"] : ["init"];
1416
- await gitExec(initArgs, { cwd: dir });
1417
- await gitExec(["checkout", "-b", "main"], { cwd: dir });
1418
- const pagesDir = resolve3(dir, "pages");
1419
- mkdirSync2(pagesDir, { recursive: true });
1420
- writeFileSync2(resolve3(pagesDir, ".gitkeep"), "");
1421
- await gitExec(["add", "-A"], { cwd: dir });
1422
- await gitExec(["commit", "-m", "init shared repo"], { cwd: dir });
1423
- if (isIsolationEnabled()) {
1424
- try {
1425
- execFileSync("chgrp", ["-R", "volute", dir], { stdio: "ignore" });
1426
- } catch (err) {
1427
- logger_default.warn("failed to chgrp shared repo to volute group", logger_default.errorData(err));
1428
- }
1429
- chmodSync(dir, 1533);
1430
- }
1431
- }
1432
- async function addSharedWorktree(mindName, mindDir2) {
1433
- const dir = sharedDir();
1434
- if (!existsSync3(resolve3(dir, ".git"))) return;
1435
- const worktreePath = resolve3(mindDir2, "home", "shared");
1436
- if (existsSync3(worktreePath)) return;
1437
- let branchExists = false;
1438
- try {
1439
- await gitExec(["rev-parse", "--verify", mindName], { cwd: dir });
1440
- branchExists = true;
1441
- } catch {
1442
- }
1443
- if (branchExists) {
1444
- await gitExec(["worktree", "add", worktreePath, mindName], { cwd: dir });
1445
- } else {
1446
- await gitExec(["worktree", "add", "-b", mindName, worktreePath], { cwd: dir });
1447
- }
1448
- if (isIsolationEnabled()) {
1449
- const worktreeGitDir = readWorktreeGitDir(worktreePath);
1450
- if (worktreeGitDir) {
1451
- try {
1452
- const user = mindUserName(mindName);
1453
- execFileSync("chown", ["-R", `${user}:volute`, worktreeGitDir], { stdio: "ignore" });
1454
- } catch (err) {
1455
- logger_default.warn(`failed to chown worktree git dir for ${mindName}`, logger_default.errorData(err));
564
+ try {
565
+ process.kill(-pid, "SIGTERM");
566
+ } catch {
567
+ try {
568
+ process.kill(pid, "SIGTERM");
569
+ } catch {
570
+ }
571
+ }
572
+ blog.warn(`killed orphan bridge ${platform} (pid ${pid})`);
573
+ }
574
+ } catch (err) {
575
+ if (err instanceof Error && err.code !== "ESRCH") {
576
+ blog.debug(`orphan bridge ${platform} cleanup: ${err}`);
1456
577
  }
1457
578
  }
1458
- }
1459
- }
1460
- async function removeSharedWorktree(mindName, mindDir2) {
1461
- const dir = sharedDir();
1462
- if (!existsSync3(resolve3(dir, ".git"))) return;
1463
- const worktreePath = resolve3(mindDir2, "home", "shared");
1464
- if (existsSync3(worktreePath)) {
1465
579
  try {
1466
- await gitExec(["worktree", "remove", "--force", worktreePath], { cwd: dir });
580
+ unlinkSync(pidPath);
1467
581
  } catch (err) {
1468
- logger_default.debug(`worktree remove failed for ${mindName}`, logger_default.errorData(err));
582
+ if (err instanceof Error && err.code !== "ENOENT") {
583
+ blog.warn(`failed to clean up PID file for orphan bridge ${platform}`, logger_default.errorData(err));
584
+ }
1469
585
  }
1470
586
  }
1471
- try {
1472
- await gitExec(["worktree", "prune"], { cwd: dir });
1473
- } catch (err) {
1474
- logger_default.debug(`worktree prune failed for ${mindName}`, logger_default.errorData(err));
1475
- }
1476
- try {
1477
- await gitExec(["branch", "-D", mindName], { cwd: dir });
1478
- } catch {
1479
- }
1480
- }
1481
- var sharedLock = Promise.resolve();
1482
- function rechownWorktree(worktreePath, mindName) {
1483
- if (!isIsolationEnabled()) return;
1484
- try {
1485
- const user = mindUserName(mindName);
1486
- execFileSync("chown", ["-R", `${user}:volute`, worktreePath], { stdio: "ignore" });
1487
- } catch (err) {
1488
- logger_default.warn(`failed to rechown worktree for ${mindName}`, logger_default.errorData(err));
587
+ resolveBuiltinBridge(platform) {
588
+ return searchUpwards("connectors", `${platform}-bridge.js`);
1489
589
  }
590
+ };
591
+ var instance = null;
592
+ function initBridgeManager() {
593
+ if (instance) throw new Error("BridgeManager already initialized");
594
+ instance = new BridgeManager();
595
+ return instance;
1490
596
  }
1491
- async function withSharedLock(fn) {
1492
- const prev = sharedLock;
1493
- let resolve_;
1494
- sharedLock = new Promise((r) => {
1495
- resolve_ = r;
1496
- });
1497
- await prev;
1498
- try {
1499
- return await fn();
1500
- } finally {
1501
- resolve_();
1502
- }
597
+ function getBridgeManager() {
598
+ if (!instance) throw new Error("BridgeManager not initialized \u2014 call initBridgeManager() first");
599
+ return instance;
1503
600
  }
1504
- async function sharedMerge(mindName, mindDir2, message) {
1505
- return withSharedLock(async () => {
1506
- const dir = sharedDir();
1507
- const worktreePath = resolve3(mindDir2, "home", "shared");
1508
- const status = (await gitExec(["status", "--porcelain"], { cwd: worktreePath })).trim();
1509
- if (status) {
1510
- await gitExec(["add", "-A"], { cwd: worktreePath });
1511
- await gitExec(
1512
- ["commit", "--author", `${mindName} <${mindName}@volute>`, "-m", `wip: ${mindName}`],
1513
- { cwd: worktreePath }
1514
- );
1515
- }
1516
- const diff = (await gitExec(["diff", `main...${mindName}`, "--stat"], { cwd: dir })).trim();
1517
- if (!diff) {
1518
- return { ok: true, message: "Nothing to merge" };
1519
- }
1520
- try {
1521
- await gitExec(["merge", "--squash", mindName], { cwd: dir });
1522
- } catch {
1523
- try {
1524
- await gitExec(["reset", "--hard", "HEAD"], { cwd: dir });
1525
- } catch (resetErr) {
1526
- logger_default.error("reset after squash conflict failed in shared repo", logger_default.errorData(resetErr));
1527
- }
1528
- return { ok: false, conflicts: true, message: "Merge conflicts detected" };
1529
- }
1530
- await gitExec(["commit", "--author", `${mindName} <${mindName}@volute>`, "-m", message], {
1531
- cwd: dir
1532
- });
1533
- try {
1534
- await gitExec(["reset", "--hard", "main"], { cwd: worktreePath });
1535
- } catch {
1536
- return {
1537
- ok: true,
1538
- message: "Merged to main, but branch reset failed \u2014 run 'volute shared pull' to sync"
1539
- };
1540
- }
1541
- rechownWorktree(worktreePath, mindName);
1542
- return { ok: true };
1543
- });
601
+
602
+ // packages/daemon/src/lib/history-cleanup.ts
603
+ import { and, eq, lt } from "drizzle-orm";
604
+ var LOG_RETENTION_MS = 24 * 60 * 60 * 1e3;
605
+ async function cleanExpiredLogs() {
606
+ const db = await getDb();
607
+ const cutoff = new Date(Date.now() - LOG_RETENTION_MS).toISOString().replace("T", " ").slice(0, 19);
608
+ await db.delete(mindHistory).where(and(eq(mindHistory.type, "log"), lt(mindHistory.created_at, cutoff)));
1544
609
  }
1545
610
 
1546
- // src/web/api/system.ts
611
+ // packages/daemon/src/web/api/system.ts
1547
612
  import { zValidator } from "@hono/zod-validator";
1548
613
  import { getProviders } from "@mariozechner/pi-ai";
1549
614
  import { getOAuthProvider, getOAuthProviders } from "@mariozechner/pi-ai/oauth";
@@ -1551,7 +616,7 @@ import { Hono } from "hono";
1551
616
  import { streamSSE } from "hono/streaming";
1552
617
  import { z } from "zod";
1553
618
 
1554
- // src/lib/services/imagegen.ts
619
+ // packages/daemon/src/lib/services/imagegen.ts
1555
620
  import Replicate from "replicate";
1556
621
  var PROVIDERS = {
1557
622
  replicate: {
@@ -1746,9 +811,9 @@ async function generateImage(model, prompt) {
1746
811
  return PROVIDERS[providerId].generate(modelId, prompt, apiKey);
1747
812
  }
1748
813
 
1749
- // src/web/middleware/auth.ts
814
+ // packages/daemon/src/web/middleware/auth.ts
1750
815
  import { timingSafeEqual } from "crypto";
1751
- import { eq as eq3, lt as lt3 } from "drizzle-orm";
816
+ import { eq as eq2, lt as lt2 } from "drizzle-orm";
1752
817
  import { getCookie } from "hono/cookie";
1753
818
  import { createMiddleware } from "hono/factory";
1754
819
  function isValidDaemonToken(token) {
@@ -1771,14 +836,14 @@ async function createSession(userId) {
1771
836
  async function deleteSession(sessionId) {
1772
837
  sessionCache.delete(sessionId);
1773
838
  const db = await getDb();
1774
- await db.delete(sessions).where(eq3(sessions.id, sessionId));
839
+ await db.delete(sessions).where(eq2(sessions.id, sessionId));
1775
840
  }
1776
841
  async function getSessionUserId(sessionId) {
1777
842
  const db = await getDb();
1778
- const row = await db.select().from(sessions).where(eq3(sessions.id, sessionId)).get();
843
+ const row = await db.select().from(sessions).where(eq2(sessions.id, sessionId)).get();
1779
844
  if (!row) return void 0;
1780
845
  if (Date.now() - row.createdAt > SESSION_MAX_AGE) {
1781
- await db.delete(sessions).where(eq3(sessions.id, sessionId));
846
+ await db.delete(sessions).where(eq2(sessions.id, sessionId));
1782
847
  return void 0;
1783
848
  }
1784
849
  return row.userId;
@@ -1786,7 +851,7 @@ async function getSessionUserId(sessionId) {
1786
851
  async function cleanExpiredSessions() {
1787
852
  const db = await getDb();
1788
853
  const cutoff = Date.now() - SESSION_MAX_AGE;
1789
- await db.delete(sessions).where(lt3(sessions.createdAt, cutoff));
854
+ await db.delete(sessions).where(lt2(sessions.createdAt, cutoff));
1790
855
  }
1791
856
  var requireAdmin = createMiddleware(async (c, next) => {
1792
857
  const user = c.get("user");
@@ -1878,7 +943,7 @@ var requireSelf = (paramName = "name") => createMiddleware(async (c, next) => {
1878
943
  await next();
1879
944
  });
1880
945
 
1881
- // src/web/api/system.ts
946
+ // packages/daemon/src/web/api/system.ts
1882
947
  var DEFAULT_API_URL = "https://volute.systems";
1883
948
  var igLog = logger_default.child("imagegen");
1884
949
  var app = new Hono().post("/restart", requireAdmin, (c) => {
@@ -1898,10 +963,10 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
1898
963
  stream.writeSSE({ data: JSON.stringify(entry) }).catch(() => {
1899
964
  });
1900
965
  });
1901
- await new Promise((resolve20) => {
966
+ await new Promise((resolve18) => {
1902
967
  stream.onAbort(() => {
1903
968
  unsubscribe();
1904
- resolve20();
969
+ resolve18();
1905
970
  });
1906
971
  });
1907
972
  });
@@ -2089,7 +1154,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
2089
1154
  const { model, prompt } = c.req.valid("json");
2090
1155
  try {
2091
1156
  const buf = await generateImage(model, prompt);
2092
- return new Response(buf, {
1157
+ return new Response(new Uint8Array(buf), {
2093
1158
  headers: {
2094
1159
  "Content-Type": "image/png",
2095
1160
  "Content-Length": String(buf.length)
@@ -2116,13 +1181,15 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
2116
1181
  let authMethod = null;
2117
1182
  if (providerConfig?.oauth) authMethod = "oauth";
2118
1183
  else if (providerConfig?.apiKey) authMethod = "api_key";
1184
+ const health = authMethod === "oauth" ? oauthHealth.get(id) : void 0;
2119
1185
  return {
2120
1186
  id,
2121
1187
  oauth: !!oauth,
2122
1188
  oauthName: oauth?.name,
2123
1189
  usesCallbackServer: !!oauth?.usesCallbackServer,
2124
1190
  configured,
2125
- authMethod
1191
+ authMethod,
1192
+ ...health && { oauthHealthy: health.healthy, oauthError: health.error }
2126
1193
  };
2127
1194
  });
2128
1195
  return c.json(result);
@@ -2210,8 +1277,8 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
2210
1277
  createdAt: Date.now()
2211
1278
  };
2212
1279
  oauthFlows.set(flowId, flow);
2213
- const promptPromise = needsManualCode ? new Promise((resolve20) => {
2214
- flow.resolveCode = resolve20;
1280
+ const promptPromise = needsManualCode ? new Promise((resolve18) => {
1281
+ flow.resolveCode = resolve18;
2215
1282
  }) : void 0;
2216
1283
  oauthProvider.login({
2217
1284
  onAuth: (info) => {
@@ -2228,10 +1295,11 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
2228
1295
  return "";
2229
1296
  },
2230
1297
  onManualCodeInput: needsManualCode ? () => promptPromise : void 0
2231
- }).then((credentials) => {
1298
+ }).then(async (credentials) => {
2232
1299
  saveProviderConfig(provider, { oauth: credentials });
2233
1300
  const existing = oauthFlows.get(flowId);
2234
1301
  if (existing) existing.status = "complete";
1302
+ await restartMindsForProvider(provider);
2235
1303
  }).catch((err) => {
2236
1304
  const existing = oauthFlows.get(flowId);
2237
1305
  if (existing) {
@@ -2239,7 +1307,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
2239
1307
  existing.error = err instanceof Error ? err.message : String(err);
2240
1308
  }
2241
1309
  });
2242
- await new Promise((resolve20) => setTimeout(resolve20, 2e3));
1310
+ await new Promise((resolve18) => setTimeout(resolve18, 2e3));
2243
1311
  const state = oauthFlows.get(flowId);
2244
1312
  return c.json({
2245
1313
  flowId,
@@ -2343,8 +1411,29 @@ function cleanupOAuthFlows() {
2343
1411
  }
2344
1412
  }
2345
1413
  }
1414
+ var PROVIDER_TEMPLATES = {
1415
+ anthropic: (t) => !t || t === "claude"
1416
+ };
1417
+ async function restartMindsForProvider(provider) {
1418
+ const matchTemplate = PROVIDER_TEMPLATES[provider];
1419
+ if (!matchTemplate) return;
1420
+ const manager = getMindManager();
1421
+ const running = manager.getRunningMinds();
1422
+ for (const name of running) {
1423
+ try {
1424
+ const entry = await findMind(name);
1425
+ if (entry && matchTemplate(entry.template)) {
1426
+ slog.info(`restarting ${name} after ${provider} credential refresh`);
1427
+ await manager.restartMind(name);
1428
+ }
1429
+ } catch (err) {
1430
+ slog.warn(`failed to check mind ${name} for restart`, logger_default.errorData(err));
1431
+ }
1432
+ }
1433
+ }
2346
1434
  var apiKeyCache = /* @__PURE__ */ new Map();
2347
- var API_KEY_TTL_MS = 4 * 60 * 1e3;
1435
+ var API_KEY_CACHE_TTL_MS = 4 * 60 * 1e3;
1436
+ var REFRESH_CHECK_INTERVAL_MS = 6e4;
2348
1437
  function getCachedApiKey(provider) {
2349
1438
  const cached = apiKeyCache.get(provider);
2350
1439
  if (cached && Date.now() < cached.expiresAt) return cached.key;
@@ -2352,15 +1441,41 @@ function getCachedApiKey(provider) {
2352
1441
  }
2353
1442
  var keyRefreshTimer = null;
2354
1443
  var slog = logger_default.child("ai-keys");
1444
+ var oauthHealth = /* @__PURE__ */ new Map();
1445
+ function needsRefresh(oauth) {
1446
+ const expires = oauth.expires;
1447
+ if (!expires || Date.now() >= expires) return true;
1448
+ return expires - Date.now() < 15 * 60 * 1e3;
1449
+ }
2355
1450
  async function refreshApiKeyCache() {
2356
- for (const provider of getConfiguredProviders()) {
1451
+ const ai = getAiConfig();
1452
+ const providers = getConfiguredProviders();
1453
+ for (const id of oauthHealth.keys()) {
1454
+ if (!providers.includes(id)) oauthHealth.delete(id);
1455
+ }
1456
+ for (const provider of providers) {
1457
+ const providerConfig = ai?.providers[provider];
1458
+ if (!providerConfig?.oauth) continue;
1459
+ if (!needsRefresh(providerConfig.oauth) && getCachedApiKey(provider)) {
1460
+ if (!oauthHealth.has(provider)) oauthHealth.set(provider, { healthy: true });
1461
+ continue;
1462
+ }
2357
1463
  try {
2358
1464
  const key = await resolveApiKey(provider);
2359
1465
  if (key) {
2360
- apiKeyCache.set(provider, { key, expiresAt: Date.now() + API_KEY_TTL_MS });
1466
+ apiKeyCache.set(provider, { key, expiresAt: Date.now() + API_KEY_CACHE_TTL_MS });
1467
+ oauthHealth.set(provider, { healthy: true });
1468
+ } else {
1469
+ oauthHealth.set(provider, {
1470
+ healthy: false,
1471
+ error: "Failed to resolve credentials",
1472
+ since: oauthHealth.get(provider)?.since ?? Date.now()
1473
+ });
2361
1474
  }
2362
1475
  } catch (err) {
1476
+ const message = err instanceof Error ? err.message : String(err);
2363
1477
  slog.warn(`API key refresh failed for ${provider}`, logger_default.errorData(err));
1478
+ oauthHealth.set(provider, { healthy: false, error: message, since: Date.now() });
2364
1479
  }
2365
1480
  }
2366
1481
  }
@@ -2373,7 +1488,7 @@ function startApiKeyRefresh() {
2373
1488
  refreshApiKeyCache().catch((err) => {
2374
1489
  slog.warn("periodic API key cache refresh failed", logger_default.errorData(err));
2375
1490
  });
2376
- }, API_KEY_TTL_MS);
1491
+ }, REFRESH_CHECK_INTERVAL_MS);
2377
1492
  }
2378
1493
  function stopApiKeyRefresh() {
2379
1494
  if (keyRefreshTimer) {
@@ -2383,14 +1498,15 @@ function stopApiKeyRefresh() {
2383
1498
  }
2384
1499
  var system_default = app;
2385
1500
 
2386
- // src/web/app.ts
2387
- import { Hono as Hono30 } from "hono";
1501
+ // packages/daemon/src/web/app.ts
1502
+ import { Hono as Hono28 } from "hono";
2388
1503
  import { bodyLimit } from "hono/body-limit";
1504
+ import { cors } from "hono/cors";
2389
1505
  import { csrf } from "hono/csrf";
2390
1506
  import { HTTPException } from "hono/http-exception";
2391
1507
 
2392
- // src/web/api/activity.ts
2393
- import { desc as desc2 } from "drizzle-orm";
1508
+ // packages/daemon/src/web/api/activity.ts
1509
+ import { desc } from "drizzle-orm";
2394
1510
  import { Hono as Hono2 } from "hono";
2395
1511
  import { streamSSE as streamSSE2 } from "hono/streaming";
2396
1512
  var app2 = new Hono2().get("/events", async (c) => {
@@ -2401,7 +1517,7 @@ var app2 = new Hono2().get("/events", async (c) => {
2401
1517
  let recentActivity = [];
2402
1518
  try {
2403
1519
  const db = await getDb();
2404
- recentActivity = await db.select().from(activity).orderBy(desc2(activity.created_at)).limit(50);
1520
+ recentActivity = await db.select().from(activity).orderBy(desc(activity.created_at)).limit(50);
2405
1521
  recentActivity = recentActivity.map((row) => ({
2406
1522
  ...row,
2407
1523
  metadata: row.metadata ? JSON.parse(row.metadata) : null
@@ -2447,8 +1563,8 @@ var app2 = new Hono2().get("/events", async (c) => {
2447
1563
  });
2448
1564
  }, 15e3);
2449
1565
  cleanups.push(() => clearInterval(keepAlive));
2450
- await new Promise((resolve20) => {
2451
- stream.onAbort(() => resolve20());
1566
+ await new Promise((resolve18) => {
1567
+ stream.onAbort(() => resolve18());
2452
1568
  });
2453
1569
  } finally {
2454
1570
  for (const cleanup of cleanups) {
@@ -2462,9 +1578,9 @@ var app2 = new Hono2().get("/events", async (c) => {
2462
1578
  });
2463
1579
  var activity_default = app2;
2464
1580
 
2465
- // src/web/api/auth.ts
2466
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
2467
- import { extname, resolve as resolve4 } from "path";
1581
+ // packages/daemon/src/web/api/auth.ts
1582
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync2 } from "fs";
1583
+ import { extname, resolve as resolve3 } from "path";
2468
1584
  import { zValidator as zValidator2 } from "@hono/zod-validator";
2469
1585
  import { Hono as Hono3 } from "hono";
2470
1586
  import { deleteCookie, getCookie as getCookie2, setCookie } from "hono/cookie";
@@ -2501,7 +1617,7 @@ var AVATAR_MIME = {
2501
1617
  };
2502
1618
  var MAX_AVATAR_SIZE = 2 * 1024 * 1024;
2503
1619
  function avatarsDir() {
2504
- return resolve4(voluteHome(), "avatars");
1620
+ return resolve3(voluteHome(), "avatars");
2505
1621
  }
2506
1622
  var authenticated = new Hono3().use(authMiddleware).post("/change-password", zValidator2("json", changePasswordSchema), async (c) => {
2507
1623
  const user = c.get("user");
@@ -2536,13 +1652,13 @@ var authenticated = new Hono3().use(authMiddleware).post("/change-password", zVa
2536
1652
  return c.json({ error: "Invalid file type (png, jpg, gif, webp only)" }, 400);
2537
1653
  }
2538
1654
  const dir = avatarsDir();
2539
- mkdirSync3(dir, { recursive: true });
1655
+ mkdirSync2(dir, { recursive: true });
2540
1656
  const filename = `avatar-${user.id}${ext}`;
2541
1657
  const buffer2 = Buffer.from(await file.arrayBuffer());
2542
- writeFileSync3(resolve4(dir, filename), buffer2);
1658
+ writeFileSync2(resolve3(dir, filename), buffer2);
2543
1659
  if (user.avatar && user.avatar !== filename) {
2544
- const oldPath = resolve4(dir, user.avatar);
2545
- rmSync2(oldPath, { force: true });
1660
+ const oldPath = resolve3(dir, user.avatar);
1661
+ rmSync(oldPath, { force: true });
2546
1662
  }
2547
1663
  await updateUserProfile(user.id, { avatar: filename });
2548
1664
  const sessionId = getCookie2(c, "volute_session");
@@ -2556,8 +1672,8 @@ var authenticated = new Hono3().use(authMiddleware).post("/change-password", zVa
2556
1672
  }).delete("/avatar", async (c) => {
2557
1673
  const user = c.get("user");
2558
1674
  if (user.avatar) {
2559
- const path = resolve4(avatarsDir(), user.avatar);
2560
- rmSync2(path, { force: true });
1675
+ const path = resolve3(avatarsDir(), user.avatar);
1676
+ rmSync(path, { force: true });
2561
1677
  }
2562
1678
  await updateUserProfile(user.id, { avatar: null });
2563
1679
  const sessionId = getCookie2(c, "volute_session");
@@ -2686,7 +1802,13 @@ var app3 = new Hono3().post("/register", zValidator2("json", credentialsSchema),
2686
1802
  }
2687
1803
  return c.json({ ok: true });
2688
1804
  }).get("/me", async (c) => {
2689
- const sessionId = getCookie2(c, "volute_session");
1805
+ let sessionId = getCookie2(c, "volute_session");
1806
+ if (!sessionId) {
1807
+ const authHeader = c.req.header("Authorization");
1808
+ if (authHeader?.startsWith("Bearer ")) {
1809
+ sessionId = authHeader.slice(7);
1810
+ }
1811
+ }
2690
1812
  if (!sessionId) return c.json({ error: "Not logged in" }, 401);
2691
1813
  const userId = await getSessionUserId(sessionId);
2692
1814
  if (userId == null) return c.json({ error: "Not logged in" }, 401);
@@ -2706,13 +1828,13 @@ var app3 = new Hono3().post("/register", zValidator2("json", credentialsSchema),
2706
1828
  return c.json({ error: "Invalid filename" }, 400);
2707
1829
  }
2708
1830
  const dir = avatarsDir();
2709
- const filePath = resolve4(dir, filename);
1831
+ const filePath = resolve3(dir, filename);
2710
1832
  if (!filePath.startsWith(`${dir}/`)) return c.json({ error: "Invalid path" }, 400);
2711
- if (!existsSync4(filePath)) return c.json({ error: "Not found" }, 404);
1833
+ if (!existsSync3(filePath)) return c.json({ error: "Not found" }, 404);
2712
1834
  const ext = extname(filename).toLowerCase();
2713
1835
  const mime = AVATAR_MIME[ext];
2714
1836
  if (!mime) return c.json({ error: "Invalid file type" }, 400);
2715
- const data = readFileSync4(filePath);
1837
+ const data = readFileSync3(filePath);
2716
1838
  return c.body(data, 200, {
2717
1839
  "Content-Type": mime,
2718
1840
  "Cache-Control": "public, max-age=3600",
@@ -2721,13 +1843,13 @@ var app3 = new Hono3().post("/register", zValidator2("json", credentialsSchema),
2721
1843
  }).route("/", admin).route("/", authenticated);
2722
1844
  var auth_default = app3;
2723
1845
 
2724
- // src/web/api/bridges.ts
1846
+ // packages/daemon/src/web/api/bridges.ts
2725
1847
  import { zValidator as zValidator3 } from "@hono/zod-validator";
2726
1848
  import { Hono as Hono4 } from "hono";
2727
1849
  import { z as z3 } from "zod";
2728
1850
 
2729
- // src/lib/puppets.ts
2730
- import { and as and3, eq as eq4 } from "drizzle-orm";
1851
+ // packages/daemon/src/lib/puppets.ts
1852
+ import { and as and2, eq as eq3 } from "drizzle-orm";
2731
1853
  async function findOrCreatePuppet(platform, platformId, displayName) {
2732
1854
  const username = `${platform}:${platformId}`;
2733
1855
  const db = await getDb();
@@ -2736,10 +1858,10 @@ async function findOrCreatePuppet(platform, platformId, displayName) {
2736
1858
  username: users.username,
2737
1859
  display_name: users.display_name,
2738
1860
  avatar: users.avatar
2739
- }).from(users).where(and3(eq4(users.username, username), eq4(users.user_type, "puppet"))).get();
1861
+ }).from(users).where(and2(eq3(users.username, username), eq3(users.user_type, "puppet"))).get();
2740
1862
  if (existing) {
2741
1863
  if (existing.display_name !== displayName) {
2742
- await db.update(users).set({ display_name: displayName }).where(eq4(users.id, existing.id));
1864
+ await db.update(users).set({ display_name: displayName }).where(eq3(users.id, existing.id));
2743
1865
  existing.display_name = displayName;
2744
1866
  }
2745
1867
  return existing;
@@ -2765,14 +1887,14 @@ async function findOrCreatePuppet(platform, platformId, displayName) {
2765
1887
  username: users.username,
2766
1888
  display_name: users.display_name,
2767
1889
  avatar: users.avatar
2768
- }).from(users).where(and3(eq4(users.username, username), eq4(users.user_type, "puppet"))).get();
1890
+ }).from(users).where(and2(eq3(users.username, username), eq3(users.user_type, "puppet"))).get();
2769
1891
  if (retried) return retried;
2770
1892
  }
2771
1893
  throw err;
2772
1894
  }
2773
1895
  }
2774
1896
 
2775
- // src/web/api/bridges.ts
1897
+ // packages/daemon/src/web/api/bridges.ts
2776
1898
  var inboundSchema = z3.object({
2777
1899
  content: z3.array(
2778
1900
  z3.union([
@@ -2847,7 +1969,7 @@ var app4 = new Hono4().post("/:platform/inbound", zValidator3("json", inboundSch
2847
1969
  }
2848
1970
  const participants = await getParticipants(channel.id);
2849
1971
  if (!participants.some((p) => p.userId === puppet.id)) {
2850
- const { addParticipant } = await import("./conversations-HL2JP5GI.js");
1972
+ const { addParticipant } = await import("./conversations-2PW57WO2.js");
2851
1973
  await addParticipant(channel.id, puppet.id);
2852
1974
  }
2853
1975
  const contentBlocks = body.content;
@@ -2940,8 +2062,8 @@ async function fanOutToBridgedMinds(opts) {
2940
2062
  const participants = await getParticipants(opts.conversationId);
2941
2063
  const mindParticipants = participants.filter((p) => p.userType === "mind");
2942
2064
  const participantNames = participants.map((p) => p.username);
2943
- const { getMindManager: getMindManager2 } = await import("./mind-manager-MWW3BTS4.js");
2944
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BJK2ROPX.js");
2065
+ const { getMindManager: getMindManager2 } = await import("./mind-manager-HFLB5653.js");
2066
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-7KFK3USC.js");
2945
2067
  const manager = getMindManager2();
2946
2068
  const sm = getSleepManagerIfReady2();
2947
2069
  const targetMinds = mindParticipants.filter((ap) => {
@@ -2969,10 +2091,10 @@ async function fanOutToBridgedMinds(opts) {
2969
2091
  }
2970
2092
  var bridges_default = app4;
2971
2093
 
2972
- // src/web/api/channels.ts
2094
+ // packages/daemon/src/web/api/channels.ts
2973
2095
  import { Hono as Hono5 } from "hono";
2974
2096
 
2975
- // src/lib/channels/discord.ts
2097
+ // packages/daemon/src/lib/channels/discord.ts
2976
2098
  var discord_exports = {};
2977
2099
  __export(discord_exports, {
2978
2100
  createConversation: () => createConversation2,
@@ -2982,7 +2104,7 @@ __export(discord_exports, {
2982
2104
  send: () => send
2983
2105
  });
2984
2106
 
2985
- // src/connectors/sdk.ts
2107
+ // packages/daemon/src/connectors/sdk.ts
2986
2108
  function splitMessage(text, maxLength) {
2987
2109
  const chunks = [];
2988
2110
  while (text.length > maxLength) {
@@ -2995,7 +2117,7 @@ function splitMessage(text, maxLength) {
2995
2117
  return chunks;
2996
2118
  }
2997
2119
 
2998
- // src/lib/channels/discord.ts
2120
+ // packages/daemon/src/lib/channels/discord.ts
2999
2121
  var DISCORD_MAX_LENGTH = 2e3;
3000
2122
  var API_BASE = "https://discord.com/api/v10";
3001
2123
  function requireToken(env) {
@@ -3021,8 +2143,8 @@ async function read(env, channelSlug, limit) {
3021
2143
  if (!res.ok) {
3022
2144
  throw new Error(`Discord API error: ${res.status} ${res.statusText}`);
3023
2145
  }
3024
- const messages2 = await res.json();
3025
- return messages2.reverse().map((m) => `${m.author.username}: ${m.content}`).join("\n");
2146
+ const messages = await res.json();
2147
+ return messages.reverse().map((m) => `${m.author.username}: ${m.content}`).join("\n");
3026
2148
  }
3027
2149
  async function send(env, channelSlug, message, images) {
3028
2150
  const token = requireToken(env);
@@ -3142,7 +2264,7 @@ async function createConversation2(env, participants, _name) {
3142
2264
  return `discord:${dmChannel.id}`;
3143
2265
  }
3144
2266
 
3145
- // src/lib/channels/slack.ts
2267
+ // packages/daemon/src/lib/channels/slack.ts
3146
2268
  var slack_exports = {};
3147
2269
  __export(slack_exports, {
3148
2270
  createConversation: () => createConversation3,
@@ -3313,7 +2435,7 @@ async function createConversation3(env, participants, name) {
3313
2435
  return `slack:${openData.channel.id}`;
3314
2436
  }
3315
2437
 
3316
- // src/lib/channels/telegram.ts
2438
+ // packages/daemon/src/lib/channels/telegram.ts
3317
2439
  var telegram_exports = {};
3318
2440
  __export(telegram_exports, {
3319
2441
  createConversation: () => createConversation4,
@@ -3409,7 +2531,7 @@ async function createConversation4() {
3409
2531
  );
3410
2532
  }
3411
2533
 
3412
- // src/lib/channels/volute.ts
2534
+ // packages/daemon/src/lib/channels/volute.ts
3413
2535
  var volute_exports = {};
3414
2536
  __export(volute_exports, {
3415
2537
  createConversation: () => createConversation5,
@@ -3418,16 +2540,28 @@ __export(volute_exports, {
3418
2540
  read: () => read4,
3419
2541
  send: () => send4
3420
2542
  });
3421
- import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
3422
- import { resolve as resolve5 } from "path";
2543
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
2544
+ import { resolve as resolve4 } from "path";
2545
+ function readSessionFile(mindDir2) {
2546
+ try {
2547
+ const p = resolve4(mindDir2, ".mind", "current-session");
2548
+ if (existsSync4(p)) return readFileSync4(p, "utf-8").trim() || void 0;
2549
+ } catch (err) {
2550
+ const code = err.code;
2551
+ if (code !== "ENOENT") {
2552
+ console.error(`[volute] failed to read session file: ${code ?? err}`);
2553
+ }
2554
+ }
2555
+ return void 0;
2556
+ }
3423
2557
  function getDaemonConfig() {
3424
- const configPath = resolve5(voluteSystemDir(), "daemon.json");
3425
- if (!existsSync5(configPath)) {
2558
+ const configPath = resolve4(voluteSystemDir(), "daemon.json");
2559
+ if (!existsSync4(configPath)) {
3426
2560
  throw new Error("Volute daemon is not running");
3427
2561
  }
3428
2562
  let config2;
3429
2563
  try {
3430
- config2 = JSON.parse(readFileSync5(configPath, "utf-8"));
2564
+ config2 = JSON.parse(readFileSync4(configPath, "utf-8"));
3431
2565
  } catch (err) {
3432
2566
  throw new Error(`Failed to parse ${configPath}: ${err}`);
3433
2567
  }
@@ -3575,7 +2709,7 @@ async function createConversation5(env, participants, name) {
3575
2709
  return conv.id;
3576
2710
  }
3577
2711
 
3578
- // src/lib/channels.ts
2712
+ // packages/daemon/src/lib/channels.ts
3579
2713
  var CHANNELS = {
3580
2714
  volute: {
3581
2715
  name: "volute",
@@ -3609,7 +2743,7 @@ function resolveChannelId(slug) {
3609
2743
  return colonIdx !== -1 ? slug.slice(colonIdx + 1) : slug;
3610
2744
  }
3611
2745
 
3612
- // src/web/api/channels.ts
2746
+ // packages/daemon/src/web/api/channels.ts
3613
2747
  function buildEnv(name) {
3614
2748
  return { ...loadMergedEnv(name), VOLUTE_MIND: name, VOLUTE_MIND_DIR: mindDir(name) };
3615
2749
  }
@@ -3637,7 +2771,7 @@ var app5 = new Hono5().post("/:name/channels/create", requireSelf(), async (c) =
3637
2771
  });
3638
2772
  var channels_default = app5;
3639
2773
 
3640
- // src/web/api/config.ts
2774
+ // packages/daemon/src/web/api/config.ts
3641
2775
  import { Hono as Hono6 } from "hono";
3642
2776
  var config = new Hono6();
3643
2777
  config.get("/models", (c) => {
@@ -3665,7 +2799,7 @@ config.get("/status", (c) => {
3665
2799
  });
3666
2800
  var config_default = config;
3667
2801
 
3668
- // src/web/api/env.ts
2802
+ // packages/daemon/src/web/api/env.ts
3669
2803
  import { Hono as Hono7 } from "hono";
3670
2804
  var app6 = new Hono7().get("/:name/env", async (c) => {
3671
2805
  const name = c.req.param("name");
@@ -3739,7 +2873,7 @@ var sharedEnvApp = new Hono7().get("/", (c) => {
3739
2873
  });
3740
2874
  var env_default = app6;
3741
2875
 
3742
- // src/web/api/extensions.ts
2876
+ // packages/daemon/src/web/api/extensions.ts
3743
2877
  import { Hono as Hono8 } from "hono";
3744
2878
  var app7 = new Hono8().get("/", (c) => {
3745
2879
  return c.json(getLoadedExtensions());
@@ -3784,15 +2918,15 @@ var app7 = new Hono8().get("/", (c) => {
3784
2918
  });
3785
2919
  var extensions_default = app7;
3786
2920
 
3787
- // src/web/api/file-sharing.ts
3788
- import { readFileSync as readFileSync6, statSync } from "fs";
3789
- import { resolve as resolve6 } from "path";
2921
+ // packages/daemon/src/web/api/file-sharing.ts
2922
+ import { readFileSync as readFileSync5, statSync } from "fs";
2923
+ import { resolve as resolve5 } from "path";
3790
2924
  import { Hono as Hono9 } from "hono";
3791
2925
  async function notifyMind(mindName, message) {
3792
2926
  const entry = await findMind(mindName);
3793
2927
  if (!entry) return;
3794
2928
  try {
3795
- const { sendSystemMessage } = await import("./system-chat-TYLOL7SX.js");
2929
+ const { sendSystemMessage } = await import("./system-chat-IDPHYHY4.js");
3796
2930
  await sendSystemMessage(mindName, message);
3797
2931
  } catch (err) {
3798
2932
  logger_default.warn(`[file-sharing] notify mind ${mindName} failed`, logger_default.errorData(err));
@@ -3811,21 +2945,21 @@ var app8 = new Hono9().post("/:name/files/send", requireSelf(), async (c) => {
3811
2945
  const pathErr = validateFilePath(body.filePath);
3812
2946
  if (pathErr) return c.json({ error: pathErr }, 400);
3813
2947
  const senderDir = mindDir(senderName);
3814
- const filePath = resolve6(senderDir, "home", body.filePath);
2948
+ const filePath = resolve5(senderDir, "home", body.filePath);
3815
2949
  const MAX_FILE_SIZE3 = 50 * 1024 * 1024;
3816
- const stat4 = statSync(filePath, { throwIfNoEntry: false });
3817
- if (!stat4) return c.json({ error: `File not found: ${body.filePath}` }, 404);
3818
- if (stat4.size > MAX_FILE_SIZE3) {
2950
+ const stat3 = statSync(filePath, { throwIfNoEntry: false });
2951
+ if (!stat3) return c.json({ error: `File not found: ${body.filePath}` }, 404);
2952
+ if (stat3.size > MAX_FILE_SIZE3) {
3819
2953
  return c.json(
3820
2954
  {
3821
- error: `File too large (${formatFileSize(stat4.size)}, max ${formatFileSize(MAX_FILE_SIZE3)})`
2955
+ error: `File too large (${formatFileSize(stat3.size)}, max ${formatFileSize(MAX_FILE_SIZE3)})`
3822
2956
  },
3823
2957
  413
3824
2958
  );
3825
2959
  }
3826
2960
  let content;
3827
2961
  try {
3828
- content = readFileSync6(filePath);
2962
+ content = readFileSync5(filePath);
3829
2963
  } catch (err) {
3830
2964
  const code = err.code;
3831
2965
  if (code === "ENOENT") {
@@ -3914,10 +3048,10 @@ var app8 = new Hono9().post("/:name/files/send", requireSelf(), async (c) => {
3914
3048
  });
3915
3049
  var file_sharing_default = app8;
3916
3050
 
3917
- // src/web/api/files.ts
3918
- import { mkdirSync as mkdirSync4, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
3919
- import { readFile, realpath, stat } from "fs/promises";
3920
- import { extname as extname2, resolve as resolve7 } from "path";
3051
+ // packages/daemon/src/web/api/files.ts
3052
+ import { mkdirSync as mkdirSync3, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
3053
+ import { readdir, readFile, realpath, stat } from "fs/promises";
3054
+ import { extname as extname2, resolve as resolve6 } from "path";
3921
3055
  import { Hono as Hono10 } from "hono";
3922
3056
  var AVATAR_MIME2 = {
3923
3057
  ".png": "image/png",
@@ -3927,6 +3061,24 @@ var AVATAR_MIME2 = {
3927
3061
  ".webp": "image/webp"
3928
3062
  };
3929
3063
  var MAX_AVATAR_SIZE2 = 2 * 1024 * 1024;
3064
+ var MAX_FILE_SIZE = 50 * 1024 * 1024;
3065
+ var MIME_TYPES = {
3066
+ ".html": "text/html",
3067
+ ".css": "text/css",
3068
+ ".js": "application/javascript",
3069
+ ".json": "application/json",
3070
+ ".svg": "image/svg+xml",
3071
+ ".png": "image/png",
3072
+ ".jpg": "image/jpeg",
3073
+ ".jpeg": "image/jpeg",
3074
+ ".gif": "image/gif",
3075
+ ".webp": "image/webp",
3076
+ ".txt": "text/plain",
3077
+ ".md": "text/markdown",
3078
+ ".xml": "application/xml",
3079
+ ".woff": "font/woff",
3080
+ ".woff2": "font/woff2"
3081
+ };
3930
3082
  var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
3931
3083
  const name = c.req.param("name");
3932
3084
  const entry = await findMind(name);
@@ -3944,17 +3096,17 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
3944
3096
  return c.json({ error: "Invalid file type (png, jpg, gif, webp only)" }, 400);
3945
3097
  }
3946
3098
  const dir = entry.dir ?? mindDir(name);
3947
- const homeDir = resolve7(dir, "home");
3099
+ const homeDir = resolve6(dir, "home");
3948
3100
  const filename = `avatar${ext}`;
3949
- const avatarPath = resolve7(homeDir, filename);
3101
+ const avatarPath = resolve6(homeDir, filename);
3950
3102
  const config2 = readVoluteConfig(dir) ?? {};
3951
3103
  const oldAvatar = config2.profile?.avatar;
3952
3104
  if (oldAvatar && oldAvatar !== filename) {
3953
- rmSync3(resolve7(homeDir, oldAvatar), { force: true });
3105
+ rmSync2(resolve6(homeDir, oldAvatar), { force: true });
3954
3106
  }
3955
3107
  const buffer2 = Buffer.from(await file.arrayBuffer());
3956
- mkdirSync4(homeDir, { recursive: true });
3957
- writeFileSync4(avatarPath, buffer2);
3108
+ mkdirSync3(homeDir, { recursive: true });
3109
+ writeFileSync3(avatarPath, buffer2);
3958
3110
  const profile = config2.profile ?? {};
3959
3111
  profile.avatar = filename;
3960
3112
  config2.profile = profile;
@@ -3972,8 +3124,8 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
3972
3124
  const ext = extname2(config2.profile.avatar).toLowerCase();
3973
3125
  const mime = AVATAR_MIME2[ext];
3974
3126
  if (!mime) return c.json({ error: "Invalid avatar extension" }, 400);
3975
- const homeDir = resolve7(dir, "home");
3976
- const avatarPath = resolve7(homeDir, config2.profile.avatar);
3127
+ const homeDir = resolve6(dir, "home");
3128
+ const avatarPath = resolve6(homeDir, config2.profile.avatar);
3977
3129
  if (!avatarPath.startsWith(`${homeDir}/`)) return c.json({ error: "Invalid avatar path" }, 400);
3978
3130
  let realAvatarPath;
3979
3131
  try {
@@ -3997,11 +3149,67 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
3997
3149
  } catch {
3998
3150
  return c.json({ error: "Failed to read avatar file" }, 500);
3999
3151
  }
3152
+ }).get("/:name/files/", requireAdmin, async (c) => {
3153
+ const name = c.req.param("name");
3154
+ const entry = await findMind(name);
3155
+ if (!entry) return c.json({ error: "Mind not found" }, 404);
3156
+ const homeDir = resolve6(entry.dir ?? mindDir(name), "home");
3157
+ let entries;
3158
+ try {
3159
+ entries = await readdir(homeDir, { withFileTypes: true });
3160
+ } catch (err) {
3161
+ if (err.code === "ENOENT")
3162
+ return c.json({ error: "Mind home directory not found" }, 404);
3163
+ return c.json({ error: "Failed to read directory" }, 500);
3164
+ }
3165
+ const items = entries.filter((e) => !e.name.startsWith(".")).map((e) => ({ name: e.name, type: e.isDirectory() ? "directory" : "file" }));
3166
+ return c.json(items);
3167
+ }).get("/:name/files/*", requireAdmin, async (c) => {
3168
+ const name = c.req.param("name");
3169
+ const entry = await findMind(name);
3170
+ if (!entry) return c.json({ error: "Mind not found" }, 404);
3171
+ const homeDir = resolve6(entry.dir ?? mindDir(name), "home");
3172
+ const wildcard = c.req.path.replace(new RegExp(`^.*/minds/${name}/files`), "") || "/";
3173
+ const relativePath = wildcard.slice(1);
3174
+ const requestedPath = resolve6(homeDir, relativePath);
3175
+ if (requestedPath !== homeDir && !requestedPath.startsWith(`${homeDir}/`))
3176
+ return c.text("Forbidden", 403);
3177
+ if (relativePath.split("/").some((seg) => seg.startsWith("."))) return c.text("Forbidden", 403);
3178
+ let resolvedPath;
3179
+ try {
3180
+ const realHome = await realpath(homeDir);
3181
+ resolvedPath = await realpath(requestedPath);
3182
+ if (resolvedPath !== realHome && !resolvedPath.startsWith(`${realHome}/`))
3183
+ return c.text("Forbidden", 403);
3184
+ } catch (err) {
3185
+ if (err.code === "ENOENT") return c.text("Not found", 404);
3186
+ return c.text("Internal server error", 500);
3187
+ }
3188
+ let fileStat;
3189
+ try {
3190
+ fileStat = await stat(resolvedPath);
3191
+ } catch (err) {
3192
+ if (err.code === "ENOENT") return c.text("Not found", 404);
3193
+ console.error(`[files] stat failed for ${resolvedPath}:`, err);
3194
+ return c.text("Internal server error", 500);
3195
+ }
3196
+ if (fileStat.isDirectory()) {
3197
+ if (!c.req.path.endsWith("/")) return c.redirect(`${c.req.path}/`);
3198
+ const dirEntries = await readdir(resolvedPath, { withFileTypes: true }).catch(
3199
+ () => []
3200
+ );
3201
+ const items = dirEntries.filter((e) => !e.name.startsWith(".")).map((e) => ({ name: e.name, type: e.isDirectory() ? "directory" : "file" }));
3202
+ return c.json(items);
3203
+ }
3204
+ if (fileStat.size > MAX_FILE_SIZE) return c.text("File too large", 413);
3205
+ const body = await readFile(resolvedPath);
3206
+ const mime = MIME_TYPES[extname2(resolvedPath).toLowerCase()] || "application/octet-stream";
3207
+ return c.body(body, 200, { "Content-Type": mime });
4000
3208
  });
4001
3209
  var files_default = app9;
4002
3210
 
4003
- // src/web/api/history.ts
4004
- import { and as and4, desc as desc3, eq as eq5, gte as gte2, inArray, sql as sql2 } from "drizzle-orm";
3211
+ // packages/daemon/src/web/api/history.ts
3212
+ import { and as and3, desc as desc2, eq as eq4, gte, inArray, sql } from "drizzle-orm";
4005
3213
  import { Hono as Hono11 } from "hono";
4006
3214
  var history = new Hono11().get("/turns", async (c) => {
4007
3215
  const mindFilter = c.req.query("mind");
@@ -4011,16 +3219,16 @@ var history = new Hono11().get("/turns", async (c) => {
4011
3219
  const offset = Math.max(parseInt(c.req.query("offset") ?? "0", 10) || 0, 0);
4012
3220
  const db = await getDb();
4013
3221
  const conditions = [];
4014
- if (mindFilter) conditions.push(eq5(turns.mind, mindFilter));
4015
- if (turnIdFilter) conditions.push(eq5(turns.id, turnIdFilter));
3222
+ if (mindFilter) conditions.push(eq4(turns.mind, mindFilter));
3223
+ if (turnIdFilter) conditions.push(eq4(turns.id, turnIdFilter));
4016
3224
  if (turnIdsFilter) {
4017
3225
  const ids = turnIdsFilter.split(",").filter(Boolean);
4018
3226
  if (ids.length > 0) conditions.push(inArray(turns.id, ids));
4019
3227
  }
4020
- const turnRows = await db.select().from(turns).where(conditions.length > 0 ? and4(...conditions) : void 0).orderBy(desc3(turns.created_at)).limit(limit).offset(offset);
3228
+ const turnRows = await db.select().from(turns).where(conditions.length > 0 ? and3(...conditions) : void 0).orderBy(desc2(turns.created_at)).limit(limit).offset(offset);
4021
3229
  if (turnRows.length === 0) return c.json([]);
4022
3230
  const turnIds = turnRows.map((t) => t.id);
4023
- const summaryRows = await db.select().from(summaries).where(and4(eq5(summaries.period, "turn"), inArray(summaries.period_key, turnIds)));
3231
+ const summaryRows = await db.select().from(summaries).where(and3(eq4(summaries.period, "turn"), inArray(summaries.period_key, turnIds)));
4024
3232
  const summaryByTurn = /* @__PURE__ */ new Map();
4025
3233
  for (const s of summaryRows) {
4026
3234
  summaryByTurn.set(s.period_key, { content: s.content, metadata: s.metadata });
@@ -4035,9 +3243,9 @@ var history = new Hono11().get("/turns", async (c) => {
4035
3243
  turn_id: mindHistory.turn_id,
4036
3244
  created_at: mindHistory.created_at
4037
3245
  }).from(mindHistory).where(
4038
- and4(
3246
+ and3(
4039
3247
  inArray(mindHistory.turn_id, turnIds),
4040
- sql2`${mindHistory.type} IN ('inbound', 'outbound')`
3248
+ sql`${mindHistory.type} IN ('inbound', 'outbound')`
4041
3249
  )
4042
3250
  ).orderBy(mindHistory.created_at);
4043
3251
  const msgsByTurnChannel = /* @__PURE__ */ new Map();
@@ -4127,8 +3335,8 @@ var history = new Hono11().get("/turns", async (c) => {
4127
3335
  });
4128
3336
  if (channelNames.length > 0) {
4129
3337
  const channelRows = await db.select({ id: conversations.id, name: conversations.name }).from(conversations).where(
4130
- and4(
4131
- eq5(conversations.type, "channel"),
3338
+ and3(
3339
+ eq4(conversations.type, "channel"),
4132
3340
  inArray(
4133
3341
  conversations.name,
4134
3342
  channelNames.map((c2) => c2.name)
@@ -4148,22 +3356,22 @@ var history = new Hono11().get("/turns", async (c) => {
4148
3356
  db.select({
4149
3357
  conversation_id: conversationParticipants.conversation_id,
4150
3358
  username: users.username
4151
- }).from(conversationParticipants).innerJoin(users, eq5(conversationParticipants.user_id, users.id))
3359
+ }).from(conversationParticipants).innerJoin(users, eq4(conversationParticipants.user_id, users.id))
4152
3360
  );
4153
3361
  const dmRows = await db.with(cp2).select({
4154
3362
  id: conversations.id,
4155
3363
  targetUsername: users.username
4156
3364
  }).from(conversations).innerJoin(
4157
3365
  conversationParticipants,
4158
- eq5(conversations.id, conversationParticipants.conversation_id)
4159
- ).innerJoin(users, eq5(conversationParticipants.user_id, users.id)).where(and4(eq5(conversations.type, "dm"), inArray(users.username, targetNames)));
3366
+ eq4(conversations.id, conversationParticipants.conversation_id)
3367
+ ).innerJoin(users, eq4(conversationParticipants.user_id, users.id)).where(and3(eq4(conversations.type, "dm"), inArray(users.username, targetNames)));
4160
3368
  for (const row of dmRows) {
4161
3369
  const slug = `@${row.targetUsername}`;
4162
3370
  const mindNames = dmSlugMinds.get(slug);
4163
3371
  if (mindNames && !channelIdMap.has(slug)) {
4164
- const mindCheck = await db.select({ id: conversationParticipants.user_id }).from(conversationParticipants).innerJoin(users, eq5(conversationParticipants.user_id, users.id)).where(
4165
- and4(
4166
- eq5(conversationParticipants.conversation_id, row.id),
3372
+ const mindCheck = await db.select({ id: conversationParticipants.user_id }).from(conversationParticipants).innerJoin(users, eq4(conversationParticipants.user_id, users.id)).where(
3373
+ and3(
3374
+ eq4(conversationParticipants.conversation_id, row.id),
4167
3375
  inArray(users.username, [...mindNames])
4168
3376
  )
4169
3377
  ).get();
@@ -4318,9 +3526,9 @@ var history = new Hono11().get("/turns", async (c) => {
4318
3526
  return c.json({ error: "period is required (turn, hour, day, week, month)" }, 400);
4319
3527
  }
4320
3528
  const db = await getDb();
4321
- const conditions = [eq5(summaries.mind, mind), eq5(summaries.period, period)];
4322
- if (from) conditions.push(gte2(summaries.period_key, from));
4323
- if (to) conditions.push(sql2`${summaries.period_key} <= ${to}`);
3529
+ const conditions = [eq4(summaries.mind, mind), eq4(summaries.period, period)];
3530
+ if (from) conditions.push(gte(summaries.period_key, from));
3531
+ if (to) conditions.push(sql`${summaries.period_key} <= ${to}`);
4324
3532
  const rows = await db.select({
4325
3533
  id: summaries.id,
4326
3534
  mind: summaries.mind,
@@ -4329,7 +3537,7 @@ var history = new Hono11().get("/turns", async (c) => {
4329
3537
  content: summaries.content,
4330
3538
  metadata: summaries.metadata,
4331
3539
  created_at: summaries.created_at
4332
- }).from(summaries).where(and4(...conditions)).orderBy(desc3(summaries.period_key)).limit(limit);
3540
+ }).from(summaries).where(and3(...conditions)).orderBy(desc2(summaries.period_key)).limit(limit);
4333
3541
  const result = rows.map((r) => {
4334
3542
  let metadata = null;
4335
3543
  if (r.metadata) {
@@ -4345,24 +3553,24 @@ var history = new Hono11().get("/turns", async (c) => {
4345
3553
  });
4346
3554
  var history_default = history;
4347
3555
 
4348
- // src/web/api/keys.ts
3556
+ // packages/daemon/src/web/api/keys.ts
4349
3557
  import { Hono as Hono12 } from "hono";
4350
3558
 
4351
- // src/lib/identity.ts
3559
+ // packages/daemon/src/lib/identity.ts
4352
3560
  import { createHash, generateKeyPairSync, sign, verify } from "crypto";
4353
- import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
4354
- import { resolve as resolve8 } from "path";
3561
+ import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
3562
+ import { resolve as resolve7 } from "path";
4355
3563
  function generateIdentity(mindDir2) {
4356
- const identityDir = resolve8(mindDir2, ".mind/identity");
4357
- mkdirSync5(identityDir, { recursive: true });
3564
+ const identityDir = resolve7(mindDir2, ".mind/identity");
3565
+ mkdirSync4(identityDir, { recursive: true });
4358
3566
  const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
4359
3567
  publicKeyEncoding: { type: "spki", format: "pem" },
4360
3568
  privateKeyEncoding: { type: "pkcs8", format: "pem" }
4361
3569
  });
4362
- const privatePath = resolve8(identityDir, "private.pem");
4363
- const publicPath = resolve8(identityDir, "public.pem");
4364
- writeFileSync5(privatePath, privateKey, { mode: 384 });
4365
- writeFileSync5(publicPath, publicKey, { mode: 420 });
3570
+ const privatePath = resolve7(identityDir, "private.pem");
3571
+ const publicPath = resolve7(identityDir, "public.pem");
3572
+ writeFileSync4(privatePath, privateKey, { mode: 384 });
3573
+ writeFileSync4(publicPath, publicKey, { mode: 420 });
4366
3574
  const config2 = readVoluteConfig(mindDir2) ?? {};
4367
3575
  config2.identity = {
4368
3576
  privateKey: ".mind/identity/private.pem",
@@ -4375,9 +3583,9 @@ function getPublicKey(mindDir2) {
4375
3583
  const config2 = readVoluteConfig(mindDir2);
4376
3584
  const relPath = config2?.identity?.publicKey;
4377
3585
  if (!relPath) return null;
4378
- const fullPath = resolve8(mindDir2, relPath);
4379
- if (!existsSync6(fullPath)) return null;
4380
- return readFileSync7(fullPath, "utf-8");
3586
+ const fullPath = resolve7(mindDir2, relPath);
3587
+ if (!existsSync5(fullPath)) return null;
3588
+ return readFileSync6(fullPath, "utf-8");
4381
3589
  }
4382
3590
  function getFingerprint(publicKeyPem) {
4383
3591
  return createHash("sha256").update(publicKeyPem).digest("hex");
@@ -4405,7 +3613,7 @@ async function publishPublicKey(mindName, publicKeyPem) {
4405
3613
  }
4406
3614
  }
4407
3615
 
4408
- // src/web/api/keys.ts
3616
+ // packages/daemon/src/web/api/keys.ts
4409
3617
  var app10 = new Hono12().get("/:fingerprint", async (c) => {
4410
3618
  const fingerprint = c.req.param("fingerprint");
4411
3619
  for (const entry of await readRegistry()) {
@@ -4422,18 +3630,18 @@ var app10 = new Hono12().get("/:fingerprint", async (c) => {
4422
3630
  });
4423
3631
  var keys_default = app10;
4424
3632
 
4425
- // src/web/api/logs.ts
3633
+ // packages/daemon/src/web/api/logs.ts
4426
3634
  import { spawn as spawn2 } from "child_process";
4427
- import { existsSync as existsSync7 } from "fs";
4428
- import { resolve as resolve9 } from "path";
3635
+ import { existsSync as existsSync6 } from "fs";
3636
+ import { resolve as resolve8 } from "path";
4429
3637
  import { Hono as Hono13 } from "hono";
4430
3638
  import { streamSSE as streamSSE3 } from "hono/streaming";
4431
3639
  var app11 = new Hono13().get("/:name/logs", async (c) => {
4432
3640
  const name = c.req.param("name");
4433
3641
  const entry = await findMind(name);
4434
3642
  if (!entry) return c.json({ error: "Mind not found" }, 404);
4435
- const logFile = resolve9(stateDir(name), "logs", "mind.log");
4436
- if (!existsSync7(logFile)) {
3643
+ const logFile = resolve8(stateDir(name), "logs", "mind.log");
3644
+ if (!existsSync6(logFile)) {
4437
3645
  return c.json({ error: "No log file found" }, 404);
4438
3646
  }
4439
3647
  return streamSSE3(c, async (stream) => {
@@ -4451,17 +3659,17 @@ var app11 = new Hono13().get("/:name/logs", async (c) => {
4451
3659
  stream.onAbort(() => {
4452
3660
  tail.kill();
4453
3661
  });
4454
- await new Promise((resolve20) => {
4455
- tail.on("exit", resolve20);
4456
- stream.onAbort(resolve20);
3662
+ await new Promise((resolve18) => {
3663
+ tail.on("exit", resolve18);
3664
+ stream.onAbort(resolve18);
4457
3665
  });
4458
3666
  });
4459
3667
  }).get("/:name/logs/tail", async (c) => {
4460
3668
  const name = c.req.param("name");
4461
3669
  const entry = await findMind(name);
4462
3670
  if (!entry) return c.json({ error: "Mind not found" }, 404);
4463
- const logFile = resolve9(stateDir(name), "logs", "mind.log");
4464
- if (!existsSync7(logFile)) {
3671
+ const logFile = resolve8(stateDir(name), "logs", "mind.log");
3672
+ if (!existsSync6(logFile)) {
4465
3673
  return c.json({ error: "No log file found" }, 404);
4466
3674
  }
4467
3675
  const nParam = parseInt(c.req.query("n") ?? "50", 10);
@@ -4471,14 +3679,14 @@ var app11 = new Hono13().get("/:name/logs", async (c) => {
4471
3679
  tail.stdout.on("data", (data) => {
4472
3680
  output += data.toString();
4473
3681
  });
4474
- await new Promise((resolve20) => {
4475
- tail.on("exit", resolve20);
3682
+ await new Promise((resolve18) => {
3683
+ tail.on("exit", resolve18);
4476
3684
  });
4477
3685
  return c.text(output);
4478
3686
  });
4479
3687
  var logs_default = app11;
4480
3688
 
4481
- // src/web/api/mind-skills.ts
3689
+ // packages/daemon/src/web/api/mind-skills.ts
4482
3690
  import { zValidator as zValidator4 } from "@hono/zod-validator";
4483
3691
  import { Hono as Hono14 } from "hono";
4484
3692
  import { z as z4 } from "zod";
@@ -4559,36 +3767,36 @@ var app12 = new Hono14().get("/:name/skills", async (c) => {
4559
3767
  });
4560
3768
  var mind_skills_default = app12;
4561
3769
 
4562
- // src/web/api/minds.ts
3770
+ // packages/daemon/src/web/api/minds.ts
4563
3771
  import {
4564
3772
  cpSync,
4565
- existsSync as existsSync9,
4566
- mkdirSync as mkdirSync7,
3773
+ existsSync as existsSync8,
3774
+ mkdirSync as mkdirSync6,
4567
3775
  readdirSync as readdirSync2,
4568
- readFileSync as readFileSync10,
4569
- rmSync as rmSync5,
4570
- writeFileSync as writeFileSync8
3776
+ readFileSync as readFileSync9,
3777
+ rmSync as rmSync4,
3778
+ writeFileSync as writeFileSync7
4571
3779
  } from "fs";
4572
- import { resolve as resolve12 } from "path";
3780
+ import { resolve as resolve11 } from "path";
4573
3781
  import { zValidator as zValidator5 } from "@hono/zod-validator";
4574
- import { and as and5, desc as desc4, eq as eq6, sql as sql3 } from "drizzle-orm";
3782
+ import { and as and4, desc as desc3, eq as eq5, sql as sql2 } from "drizzle-orm";
4575
3783
  import { Hono as Hono15 } from "hono";
4576
3784
  import { z as z5 } from "zod";
4577
3785
 
4578
- // src/lib/consolidate.ts
4579
- import { readdirSync, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
4580
- import { resolve as resolve10 } from "path";
3786
+ // packages/daemon/src/lib/consolidate.ts
3787
+ import { readdirSync, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
3788
+ import { resolve as resolve9 } from "path";
4581
3789
  async function consolidateMemory(mindDir2) {
4582
- const soulPath = resolve10(mindDir2, "home/SOUL.md");
4583
- const memoryPath = resolve10(mindDir2, "home/MEMORY.md");
4584
- const memoryDir = resolve10(mindDir2, "home/memory");
4585
- const soul = readFileSync8(soulPath, "utf-8");
3790
+ const soulPath = resolve9(mindDir2, "home/SOUL.md");
3791
+ const memoryPath = resolve9(mindDir2, "home/MEMORY.md");
3792
+ const memoryDir = resolve9(mindDir2, "home/memory");
3793
+ const soul = readFileSync7(soulPath, "utf-8");
4586
3794
  const logs = [];
4587
3795
  try {
4588
3796
  const files = readdirSync(memoryDir).filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)).sort();
4589
3797
  for (const filename of files) {
4590
3798
  const date = filename.replace(".md", "");
4591
- const content2 = readFileSync8(resolve10(memoryDir, filename), "utf-8").trim();
3799
+ const content2 = readFileSync7(resolve9(memoryDir, filename), "utf-8").trim();
4592
3800
  if (content2) {
4593
3801
  logs.push(`### ${date}
4594
3802
 
@@ -4638,7 +3846,7 @@ ${content2}`);
4638
3846
  const data = await res.json();
4639
3847
  const content = data.content.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("").trim();
4640
3848
  if (content) {
4641
- writeFileSync6(memoryPath, `${content}
3849
+ writeFileSync5(memoryPath, `${content}
4642
3850
  `);
4643
3851
  console.log("MEMORY.md created successfully.");
4644
3852
  } else {
@@ -4646,26 +3854,26 @@ ${content2}`);
4646
3854
  }
4647
3855
  }
4648
3856
 
4649
- // src/lib/convert-session.ts
3857
+ // packages/daemon/src/lib/convert-session.ts
4650
3858
  import { randomUUID } from "crypto";
4651
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
3859
+ import { mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
4652
3860
  import { homedir } from "os";
4653
- import { resolve as resolve11 } from "path";
3861
+ import { resolve as resolve10 } from "path";
4654
3862
  function convertSession(opts) {
4655
- const lines = readFileSync9(opts.sessionPath, "utf-8").trim().split("\n");
3863
+ const lines = readFileSync8(opts.sessionPath, "utf-8").trim().split("\n");
4656
3864
  const sessionId = randomUUID();
4657
3865
  const idMap = /* @__PURE__ */ new Map();
4658
- const messages2 = [];
3866
+ const messages = [];
4659
3867
  for (const line of lines) {
4660
3868
  const event = JSON.parse(line);
4661
3869
  if (event.type === "message" && event.message) {
4662
- messages2.push(event);
3870
+ messages.push(event);
4663
3871
  }
4664
3872
  }
4665
3873
  const sdkEvents = [];
4666
3874
  let lastSdkUuid = null;
4667
- for (let i = 0; i < messages2.length; i++) {
4668
- const event = messages2[i];
3875
+ for (let i = 0; i < messages.length; i++) {
3876
+ const event = messages[i];
4669
3877
  const msg = event.message;
4670
3878
  if (msg.role === "user") {
4671
3879
  const uuid = randomUUID();
@@ -4726,8 +3934,8 @@ function convertSession(opts) {
4726
3934
  let lastToolResultId = event.id;
4727
3935
  let lastTimestamp = event.timestamp;
4728
3936
  let j = i;
4729
- while (j < messages2.length && messages2[j].message.role === "toolResult") {
4730
- const tr = messages2[j];
3937
+ while (j < messages.length && messages[j].message.role === "toolResult") {
3938
+ const tr = messages[j];
4731
3939
  const trMsg = tr.message;
4732
3940
  lastToolResultId = tr.id;
4733
3941
  lastTimestamp = tr.timestamp;
@@ -4766,10 +3974,10 @@ function convertSession(opts) {
4766
3974
  }
4767
3975
  }
4768
3976
  const projectId = opts.projectDir.replace(/\//g, "-");
4769
- const sdkDir = resolve11(homedir(), ".claude", "projects", projectId);
4770
- mkdirSync6(sdkDir, { recursive: true });
4771
- const sdkPath = resolve11(sdkDir, `${sessionId}.jsonl`);
4772
- writeFileSync7(sdkPath, `${sdkEvents.join("\n")}
3977
+ const sdkDir = resolve10(homedir(), ".claude", "projects", projectId);
3978
+ mkdirSync5(sdkDir, { recursive: true });
3979
+ const sdkPath = resolve10(sdkDir, `${sessionId}.jsonl`);
3980
+ writeFileSync6(sdkPath, `${sdkEvents.join("\n")}
4773
3981
  `);
4774
3982
  console.log(`Converted ${sdkEvents.length} messages \u2192 ${sdkPath}`);
4775
3983
  return sessionId;
@@ -4820,7 +4028,7 @@ function convertAssistantContent(content) {
4820
4028
  return result;
4821
4029
  }
4822
4030
 
4823
- // src/lib/health.ts
4031
+ // packages/daemon/src/lib/health.ts
4824
4032
  async function checkHealth(port) {
4825
4033
  try {
4826
4034
  const res = await fetch(`http://127.0.0.1:${port}/health`, {
@@ -4834,8 +4042,8 @@ async function checkHealth(port) {
4834
4042
  }
4835
4043
  }
4836
4044
 
4837
- // src/lib/variant-cleanup.ts
4838
- import { existsSync as existsSync8, rmSync as rmSync4 } from "fs";
4045
+ // packages/daemon/src/lib/variant-cleanup.ts
4046
+ import { existsSync as existsSync7, rmSync as rmSync3 } from "fs";
4839
4047
  async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
4840
4048
  if (opts?.stop) {
4841
4049
  try {
@@ -4844,14 +4052,14 @@ async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
4844
4052
  logger_default.warn(`failed to stop variant ${variantName}`, logger_default.errorData(err));
4845
4053
  }
4846
4054
  }
4847
- const { findMind: findMind2 } = await import("./registry-UYV5S6QT.js");
4055
+ const { findMind: findMind2 } = await import("./registry-GBSNW3HG.js");
4848
4056
  const variantEntry = await findMind2(variantName);
4849
4057
  const branchName = variantEntry?.branch ?? variantName;
4850
- if (existsSync8(variantPath)) {
4058
+ if (existsSync7(variantPath)) {
4851
4059
  try {
4852
4060
  await gitExec(["worktree", "remove", "--force", variantPath], { cwd: projectRoot });
4853
4061
  } catch {
4854
- rmSync4(variantPath, { recursive: true, force: true });
4062
+ rmSync3(variantPath, { recursive: true, force: true });
4855
4063
  try {
4856
4064
  await gitExec(["worktree", "prune"], { cwd: projectRoot });
4857
4065
  } catch (err) {
@@ -4880,7 +4088,7 @@ async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
4880
4088
  }
4881
4089
  }
4882
4090
 
4883
- // src/lib/variants.ts
4091
+ // packages/daemon/src/lib/variants.ts
4884
4092
  var SAFE_BRANCH_RE = /^[a-zA-Z0-9._\-/]+$/;
4885
4093
  function validateBranchName(branch) {
4886
4094
  if (!SAFE_BRANCH_RE.test(branch)) {
@@ -4892,13 +4100,13 @@ function validateBranchName(branch) {
4892
4100
  return null;
4893
4101
  }
4894
4102
 
4895
- // src/web/api/minds.ts
4103
+ // packages/daemon/src/web/api/minds.ts
4896
4104
  var SUBSTANTIVE_TYPES = /* @__PURE__ */ new Set(["thinking", "text", "tool_use", "tool_result", "outbound"]);
4897
4105
  async function getMindStatus(name, port) {
4898
4106
  const manager = getMindManager();
4899
4107
  let status = "stopped";
4900
4108
  try {
4901
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BJK2ROPX.js");
4109
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-7KFK3USC.js");
4902
4110
  if (getSleepManagerIfReady2()?.isSleeping(name)) {
4903
4111
  status = "sleeping";
4904
4112
  }
@@ -4944,7 +4152,7 @@ async function initTemplateBranch(projectRoot, composedDir, manifest, mindName,
4944
4152
  await gitExec(["commit", "-m", "initial commit"], opts);
4945
4153
  }
4946
4154
  async function updateTemplateBranch(projectRoot, template, mindName) {
4947
- const tempWorktree = resolve12(projectRoot, ".variants", "_template_update");
4155
+ const tempWorktree = resolve11(projectRoot, ".variants", "_template_update");
4948
4156
  let branchExists = false;
4949
4157
  try {
4950
4158
  await gitExec(["rev-parse", "--verify", TEMPLATE_BRANCH], { cwd: projectRoot });
@@ -4955,8 +4163,8 @@ async function updateTemplateBranch(projectRoot, template, mindName) {
4955
4163
  await gitExec(["worktree", "remove", "--force", tempWorktree], { cwd: projectRoot });
4956
4164
  } catch {
4957
4165
  }
4958
- if (existsSync9(tempWorktree)) {
4959
- rmSync5(tempWorktree, { recursive: true, force: true });
4166
+ if (existsSync8(tempWorktree)) {
4167
+ rmSync4(tempWorktree, { recursive: true, force: true });
4960
4168
  }
4961
4169
  const templatesRoot = findTemplatesRoot();
4962
4170
  const { composedDir, manifest } = composeTemplate(templatesRoot, template);
@@ -4976,15 +4184,15 @@ async function updateTemplateBranch(projectRoot, template, mindName) {
4976
4184
  });
4977
4185
  }
4978
4186
  copyTemplateToDir(composedDir, tempWorktree, mindName, manifest);
4979
- const initDir = resolve12(tempWorktree, ".init");
4980
- if (existsSync9(initDir)) {
4981
- rmSync5(initDir, { recursive: true, force: true });
4187
+ const initDir = resolve11(tempWorktree, ".init");
4188
+ if (existsSync8(initDir)) {
4189
+ rmSync4(initDir, { recursive: true, force: true });
4982
4190
  }
4983
- const homeDir = resolve12(tempWorktree, "home");
4984
- if (existsSync9(homeDir)) {
4191
+ const homeDir = resolve11(tempWorktree, "home");
4192
+ if (existsSync8(homeDir)) {
4985
4193
  for (const entry of readdirSync2(homeDir)) {
4986
4194
  if (entry !== "VOLUTE.md") {
4987
- rmSync5(resolve12(homeDir, entry), { recursive: true, force: true });
4195
+ rmSync4(resolve11(homeDir, entry), { recursive: true, force: true });
4988
4196
  }
4989
4197
  }
4990
4198
  }
@@ -4999,10 +4207,10 @@ async function updateTemplateBranch(projectRoot, template, mindName) {
4999
4207
  await gitExec(["worktree", "remove", "--force", tempWorktree], { cwd: projectRoot });
5000
4208
  } catch {
5001
4209
  }
5002
- if (existsSync9(tempWorktree)) {
5003
- rmSync5(tempWorktree, { recursive: true, force: true });
4210
+ if (existsSync8(tempWorktree)) {
4211
+ rmSync4(tempWorktree, { recursive: true, force: true });
5004
4212
  }
5005
- rmSync5(composedDir, { recursive: true, force: true });
4213
+ rmSync4(composedDir, { recursive: true, force: true });
5006
4214
  }
5007
4215
  }
5008
4216
  async function mergeTemplateBranch(worktreeDir) {
@@ -5025,7 +4233,7 @@ async function mergeTemplateBranch(worktreeDir) {
5025
4233
  async function npmInstallAsMind(cwd, mindName) {
5026
4234
  if (isIsolationEnabled()) {
5027
4235
  const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
5028
- await exec(cmd, args, { cwd, env: { ...process.env, HOME: resolve12(cwd, "home") } });
4236
+ await exec(cmd, args, { cwd, env: { ...process.env, HOME: resolve11(cwd, "home") } });
5029
4237
  } else {
5030
4238
  await exec("npm", ["install"], { cwd });
5031
4239
  }
@@ -5076,8 +4284,8 @@ async function mergeUpgradeAndRestart(mindName, dir, worktreeDir, upgradeVariant
5076
4284
  return { ok: true };
5077
4285
  }
5078
4286
  async function importFromArchive(c, tempDir, nameOverride, manifest) {
5079
- const extractedMindDir = resolve12(tempDir, "mind");
5080
- if (!existsSync9(extractedMindDir)) {
4287
+ const extractedMindDir = resolve11(tempDir, "mind");
4288
+ if (!existsSync8(extractedMindDir)) {
5081
4289
  return c.json({ error: "Invalid archive: missing mind/ directory" }, 400);
5082
4290
  }
5083
4291
  if (!manifest?.includes || !manifest.name || !manifest.template) {
@@ -5095,17 +4303,17 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
5095
4303
  if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
5096
4304
  ensureVoluteHome();
5097
4305
  const dest = mindDir(name);
5098
- if (existsSync9(dest)) return c.json({ error: "Mind directory already exists" }, 409);
4306
+ if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5099
4307
  try {
5100
4308
  cpSync(extractedMindDir, dest, { recursive: true });
5101
4309
  if (!manifest.includes.identity) {
5102
4310
  generateIdentity(dest);
5103
4311
  }
5104
4312
  const state = stateDir(name);
5105
- mkdirSync7(state, { recursive: true });
5106
- const envJson = resolve12(tempDir, "state/env.json");
5107
- if (existsSync9(envJson)) {
5108
- cpSync(envJson, resolve12(state, "env.json"));
4313
+ mkdirSync6(state, { recursive: true });
4314
+ const envJson = resolve11(tempDir, "state/env.json");
4315
+ if (existsSync8(envJson)) {
4316
+ cpSync(envJson, resolve11(state, "env.json"));
5109
4317
  }
5110
4318
  const port = await nextPort();
5111
4319
  await addMind(name, port, manifest.stage, manifest.template);
@@ -5114,36 +4322,36 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
5114
4322
  } catch (err) {
5115
4323
  logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
5116
4324
  }
5117
- const homeDir = resolve12(dest, "home");
4325
+ const homeDir = resolve11(dest, "home");
5118
4326
  ensureVoluteGroup();
5119
4327
  createMindUser(name, homeDir);
5120
4328
  chownMindDir(dest, name);
5121
4329
  await npmInstallAsMind(dest, name);
5122
4330
  await importHistoryFromArchive(name, tempDir);
5123
4331
  importSessionsFromArchive(dest, tempDir);
5124
- if (!existsSync9(resolve12(dest, ".git"))) {
4332
+ if (!existsSync8(resolve11(dest, ".git"))) {
5125
4333
  try {
5126
- const env = isIsolationEnabled() ? { ...process.env, HOME: resolve12(dest, "home") } : void 0;
4334
+ const env = isIsolationEnabled() ? { ...process.env, HOME: resolve11(dest, "home") } : void 0;
5127
4335
  await gitExec(["init"], { cwd: dest, mindName: name, env });
5128
4336
  await configureGitIdentity(name, { cwd: dest, mindName: name, env });
5129
4337
  await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
5130
4338
  await gitExec(["commit", "-m", "import from archive"], { cwd: dest, mindName: name, env });
5131
4339
  } catch (err) {
5132
4340
  logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
5133
- rmSync5(resolve12(dest, ".git"), { recursive: true, force: true });
4341
+ rmSync4(resolve11(dest, ".git"), { recursive: true, force: true });
5134
4342
  }
5135
4343
  }
5136
4344
  chownMindDir(dest, name);
5137
- rmSync5(tempDir, { recursive: true, force: true });
4345
+ rmSync4(tempDir, { recursive: true, force: true });
5138
4346
  return c.json({ ok: true, name, port, message: `Imported mind: ${name} (port ${port})` });
5139
4347
  } catch (err) {
5140
- if (existsSync9(dest)) rmSync5(dest, { recursive: true, force: true });
4348
+ if (existsSync8(dest)) rmSync4(dest, { recursive: true, force: true });
5141
4349
  try {
5142
4350
  await removeMind(name);
5143
4351
  } catch (cleanupErr) {
5144
4352
  logger_default.error(`Failed to clean up registry for ${name}`, logger_default.errorData(cleanupErr));
5145
4353
  }
5146
- rmSync5(tempDir, { recursive: true, force: true });
4354
+ rmSync4(tempDir, { recursive: true, force: true });
5147
4355
  return c.json({ error: err instanceof Error ? err.message : "Failed to import mind" }, 500);
5148
4356
  }
5149
4357
  }
@@ -5154,7 +4362,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5154
4362
  if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
5155
4363
  ensureVoluteHome();
5156
4364
  const dest = mindDir(name);
5157
- if (existsSync9(dest)) return c.json({ error: "Mind directory already exists" }, 409);
4365
+ if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5158
4366
  const templatesRoot = findTemplatesRoot();
5159
4367
  const { composedDir, manifest: templateManifest } = composeTemplate(
5160
4368
  templatesRoot,
@@ -5163,36 +4371,36 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5163
4371
  try {
5164
4372
  copyTemplateToDir(composedDir, dest, name, templateManifest);
5165
4373
  applyInitFiles(dest);
5166
- const extractedHome = resolve12(extractedMindDir, "home");
5167
- if (existsSync9(extractedHome)) {
5168
- cpSync(extractedHome, resolve12(dest, "home"), { recursive: true });
4374
+ const extractedHome = resolve11(extractedMindDir, "home");
4375
+ if (existsSync8(extractedHome)) {
4376
+ cpSync(extractedHome, resolve11(dest, "home"), { recursive: true });
5169
4377
  }
5170
- const extractedMindInternal = resolve12(extractedMindDir, ".mind");
5171
- if (existsSync9(extractedMindInternal)) {
5172
- cpSync(extractedMindInternal, resolve12(dest, ".mind"), { recursive: true });
4378
+ const extractedMindInternal = resolve11(extractedMindDir, ".mind");
4379
+ if (existsSync8(extractedMindInternal)) {
4380
+ cpSync(extractedMindInternal, resolve11(dest, ".mind"), { recursive: true });
5173
4381
  }
5174
- const identityDir = resolve12(dest, ".mind/identity");
4382
+ const identityDir = resolve11(dest, ".mind/identity");
5175
4383
  let publicKeyPem;
5176
- if (!manifest.includes.identity || !existsSync9(resolve12(identityDir, "private.pem"))) {
4384
+ if (!manifest.includes.identity || !existsSync8(resolve11(identityDir, "private.pem"))) {
5177
4385
  ({ publicKeyPem } = generateIdentity(dest));
5178
4386
  } else {
5179
- publicKeyPem = readFileSync10(resolve12(identityDir, "public.pem"), "utf-8");
4387
+ publicKeyPem = readFileSync9(resolve11(identityDir, "public.pem"), "utf-8");
5180
4388
  }
5181
- const promptsPath = resolve12(dest, "home/.config/prompts.json");
5182
- if (!existsSync9(promptsPath)) {
4389
+ const promptsPath = resolve11(dest, "home/.config/prompts.json");
4390
+ if (!existsSync8(promptsPath)) {
5183
4391
  const mindPrompts = await getMindPromptDefaults();
5184
- writeFileSync8(promptsPath, `${JSON.stringify(mindPrompts, null, 2)}
4392
+ writeFileSync7(promptsPath, `${JSON.stringify(mindPrompts, null, 2)}
5185
4393
  `);
5186
4394
  }
5187
4395
  const state = stateDir(name);
5188
- mkdirSync7(state, { recursive: true });
5189
- const envJson = resolve12(tempDir, "state/env.json");
5190
- if (existsSync9(envJson)) {
5191
- cpSync(envJson, resolve12(state, "env.json"));
4396
+ mkdirSync6(state, { recursive: true });
4397
+ const envJson = resolve11(tempDir, "state/env.json");
4398
+ if (existsSync8(envJson)) {
4399
+ cpSync(envJson, resolve11(state, "env.json"));
5192
4400
  }
5193
4401
  const port = await nextPort();
5194
4402
  await addMind(name, port, manifest.stage, manifest.template);
5195
- const homeDir = resolve12(dest, "home");
4403
+ const homeDir = resolve11(dest, "home");
5196
4404
  ensureVoluteGroup();
5197
4405
  createMindUser(name, homeDir);
5198
4406
  chownMindDir(dest, name);
@@ -5205,14 +4413,9 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5205
4413
  await initTemplateBranch(dest, composedDir, templateManifest, name, env);
5206
4414
  } catch (err) {
5207
4415
  logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
5208
- rmSync5(resolve12(dest, ".git"), { recursive: true, force: true });
4416
+ rmSync4(resolve11(dest, ".git"), { recursive: true, force: true });
5209
4417
  gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
5210
4418
  }
5211
- try {
5212
- await addSharedWorktree(name, dest);
5213
- } catch (err) {
5214
- logger_default.warn(`failed to add shared worktree for ${name}`, logger_default.errorData(err));
5215
- }
5216
4419
  const skillSet = manifest.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions();
5217
4420
  const skillWarnings = [];
5218
4421
  for (const skillId of skillSet) {
@@ -5229,7 +4432,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5229
4432
  publishPublicKey(name, publicKeyPem).catch(
5230
4433
  (err) => logger_default.warn(`failed to publish key for ${name}`, { error: err.message })
5231
4434
  );
5232
- rmSync5(tempDir, { recursive: true, force: true });
4435
+ rmSync4(tempDir, { recursive: true, force: true });
5233
4436
  return c.json({
5234
4437
  ok: true,
5235
4438
  name,
@@ -5240,24 +4443,24 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5240
4443
  ...skillWarnings.length > 0 && { skillWarnings }
5241
4444
  });
5242
4445
  } catch (err) {
5243
- if (existsSync9(dest)) rmSync5(dest, { recursive: true, force: true });
4446
+ if (existsSync8(dest)) rmSync4(dest, { recursive: true, force: true });
5244
4447
  try {
5245
4448
  await removeMind(name);
5246
4449
  } catch (cleanupErr) {
5247
4450
  logger_default.error(`Failed to clean up registry for ${name}`, logger_default.errorData(cleanupErr));
5248
4451
  }
5249
- rmSync5(tempDir, { recursive: true, force: true });
4452
+ rmSync4(tempDir, { recursive: true, force: true });
5250
4453
  return c.json({ error: err instanceof Error ? err.message : "Failed to import mind" }, 500);
5251
4454
  } finally {
5252
- rmSync5(composedDir, { recursive: true, force: true });
4455
+ rmSync4(composedDir, { recursive: true, force: true });
5253
4456
  }
5254
4457
  }
5255
4458
  async function importHistoryFromArchive(name, tempDir) {
5256
- const historyJsonl = resolve12(tempDir, "history.jsonl");
5257
- if (!existsSync9(historyJsonl)) return;
4459
+ const historyJsonl = resolve11(tempDir, "history.jsonl");
4460
+ if (!existsSync8(historyJsonl)) return;
5258
4461
  try {
5259
4462
  const db = await getDb();
5260
- const lines = readFileSync10(historyJsonl, "utf-8").trim().split("\n");
4463
+ const lines = readFileSync9(historyJsonl, "utf-8").trim().split("\n");
5261
4464
  let imported = 0;
5262
4465
  let failed = 0;
5263
4466
  for (const line of lines) {
@@ -5293,13 +4496,13 @@ async function importHistoryFromArchive(name, tempDir) {
5293
4496
  }
5294
4497
  }
5295
4498
  function importSessionsFromArchive(dest, tempDir) {
5296
- const sessionsDir = resolve12(tempDir, "sessions");
5297
- if (!existsSync9(sessionsDir)) return;
4499
+ const sessionsDir = resolve11(tempDir, "sessions");
4500
+ if (!existsSync8(sessionsDir)) return;
5298
4501
  try {
5299
- const destSessions = resolve12(dest, ".mind/sessions");
5300
- mkdirSync7(destSessions, { recursive: true });
4502
+ const destSessions = resolve11(dest, ".mind/sessions");
4503
+ mkdirSync6(destSessions, { recursive: true });
5301
4504
  for (const file of readdirSync2(sessionsDir)) {
5302
- cpSync(resolve12(sessionsDir, file), resolve12(destSessions, file));
4505
+ cpSync(resolve11(sessionsDir, file), resolve11(destSessions, file));
5303
4506
  }
5304
4507
  } catch (err) {
5305
4508
  logger_default.error("Failed to import sessions from archive", logger_default.errorData(err));
@@ -5334,7 +4537,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
5334
4537
  if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
5335
4538
  ensureVoluteHome();
5336
4539
  const dest = mindDir(name);
5337
- if (existsSync9(dest)) return c.json({ error: "Mind directory already exists" }, 409);
4540
+ if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5338
4541
  const templatesRoot = findTemplatesRoot();
5339
4542
  const { composedDir, manifest } = composeTemplate(templatesRoot, template);
5340
4543
  try {
@@ -5342,7 +4545,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
5342
4545
  applyInitFiles(dest);
5343
4546
  const { publicKeyPem } = generateIdentity(dest);
5344
4547
  {
5345
- const { readGlobalConfig: readGlobal } = await import("./setup-GGMKENLN.js");
4548
+ const { readGlobalConfig: readGlobal } = await import("./setup-RHJRFURI.js");
5346
4549
  const mindDefaults = readGlobal().mindDefaults;
5347
4550
  const config2 = readVoluteConfig(dest);
5348
4551
  if (!config2) throw new Error("Failed to read volute.json after identity generation");
@@ -5379,22 +4582,22 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
5379
4582
  }
5380
4583
  writeVoluteConfig(dest, config2);
5381
4584
  const modelId = body.model ?? cog?.model;
5382
- const sdkConfigPath = resolve12(dest, "home/.config/config.json");
4585
+ const sdkConfigPath = resolve11(dest, "home/.config/config.json");
5383
4586
  if (modelId || cog?.compaction) {
5384
- const existing = existsSync9(sdkConfigPath) ? JSON.parse(readFileSync10(sdkConfigPath, "utf-8")) : {};
4587
+ const existing = existsSync8(sdkConfigPath) ? JSON.parse(readFileSync9(sdkConfigPath, "utf-8")) : {};
5385
4588
  if (modelId) {
5386
4589
  existing.model = template === "pi" ? qualifyModelId(modelId) : unqualifyModelId(modelId);
5387
4590
  }
5388
4591
  if (cog?.compaction && !existing.compaction) {
5389
4592
  existing.compaction = cog.compaction;
5390
4593
  }
5391
- writeFileSync8(sdkConfigPath, `${JSON.stringify(existing, null, 2)}
4594
+ writeFileSync7(sdkConfigPath, `${JSON.stringify(existing, null, 2)}
5392
4595
  `);
5393
4596
  }
5394
4597
  }
5395
4598
  const mindPrompts = await getMindPromptDefaults();
5396
- writeFileSync8(
5397
- resolve12(dest, "home/.config/prompts.json"),
4599
+ writeFileSync7(
4600
+ resolve11(dest, "home/.config/prompts.json"),
5398
4601
  `${JSON.stringify(mindPrompts, null, 2)}
5399
4602
  `
5400
4603
  );
@@ -5406,7 +4609,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
5406
4609
  } catch (err) {
5407
4610
  logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
5408
4611
  }
5409
- const homeDir = resolve12(dest, "home");
4612
+ const homeDir = resolve11(dest, "home");
5410
4613
  ensureVoluteGroup();
5411
4614
  createMindUser(name, homeDir);
5412
4615
  chownMindDir(dest, name);
@@ -5419,14 +4622,9 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
5419
4622
  await initTemplateBranch(dest, composedDir, manifest, name, env);
5420
4623
  } catch (err) {
5421
4624
  logger_default.error(`git setup failed for ${name}`, logger_default.errorData(err));
5422
- rmSync5(resolve12(dest, ".git"), { recursive: true, force: true });
4625
+ rmSync4(resolve11(dest, ".git"), { recursive: true, force: true });
5423
4626
  gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
5424
4627
  }
5425
- try {
5426
- await addSharedWorktree(name, dest);
5427
- } catch (err) {
5428
- logger_default.warn(`failed to add shared worktree for ${name}`, logger_default.errorData(err));
5429
- }
5430
4628
  chownMindDir(dest, name);
5431
4629
  if (body.stage === "seed") {
5432
4630
  const descLine = body.description ? `
@@ -5434,11 +4632,11 @@ The human who planted you described you as: "${body.description}"
5434
4632
  ` : "";
5435
4633
  const seedSoulRaw = body.seedSoul ?? await getPrompt("seed_soul", { name, description: descLine });
5436
4634
  const seedSoul = body.seedSoul ? substitute(seedSoulRaw, { name, description: descLine }) : seedSoulRaw;
5437
- writeFileSync8(resolve12(dest, "home/SOUL.md"), seedSoul);
4635
+ writeFileSync7(resolve11(dest, "home/SOUL.md"), seedSoul);
5438
4636
  }
5439
4637
  let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
5440
4638
  if (body.stage === "seed" && !body.skills) {
5441
- const { isImagegenEnabled } = await import("./setup-GGMKENLN.js");
4639
+ const { isImagegenEnabled } = await import("./setup-RHJRFURI.js");
5442
4640
  if (isImagegenEnabled()) {
5443
4641
  skillSet = [...skillSet, "imagegen"];
5444
4642
  }
@@ -5456,7 +4654,7 @@ The human who planted you described you as: "${body.description}"
5456
4654
  try {
5457
4655
  const spiritEntry = await findMind("volute");
5458
4656
  if (spiritEntry) {
5459
- const { spiritDir } = await import("./spirit-4JP4TY4C.js");
4657
+ const { spiritDir } = await import("./spirit-ZFRDXMG7.js");
5460
4658
  const sDir = spiritEntry.dir ?? spiritDir();
5461
4659
  const spiritConfig = readVoluteConfig(sDir) ?? {};
5462
4660
  const schedules = spiritConfig.schedules ?? [];
@@ -5471,7 +4669,7 @@ The human who planted you described you as: "${body.description}"
5471
4669
  });
5472
4670
  spiritConfig.schedules = schedules;
5473
4671
  writeVoluteConfig(sDir, spiritConfig);
5474
- const { getScheduler: getScheduler2 } = await import("./scheduler-AGG3L2FO.js");
4672
+ const { getScheduler: getScheduler2 } = await import("./scheduler-Y7O4CJXL.js");
5475
4673
  getScheduler2().loadSchedules("volute", sDir);
5476
4674
  }
5477
4675
  }
@@ -5482,11 +4680,11 @@ The human who planted you described you as: "${body.description}"
5482
4680
  if (body.stage !== "seed") {
5483
4681
  const customSoul = await getPromptIfCustom("default_soul");
5484
4682
  if (customSoul) {
5485
- writeFileSync8(resolve12(dest, "home/SOUL.md"), customSoul.replace(/\{\{name\}\}/g, name));
4683
+ writeFileSync7(resolve11(dest, "home/SOUL.md"), customSoul.replace(/\{\{name\}\}/g, name));
5486
4684
  }
5487
4685
  const customMemory = await getPromptIfCustom("default_memory");
5488
4686
  if (customMemory) {
5489
- writeFileSync8(resolve12(dest, "home/MEMORY.md"), customMemory);
4687
+ writeFileSync7(resolve11(dest, "home/MEMORY.md"), customMemory);
5490
4688
  }
5491
4689
  }
5492
4690
  publishPublicKey(name, publicKeyPem).catch(
@@ -5515,14 +4713,14 @@ The human who planted you described you as: "${body.description}"
5515
4713
  ...skillWarnings.length > 0 && { skillWarnings }
5516
4714
  });
5517
4715
  } catch (err) {
5518
- if (existsSync9(dest)) rmSync5(dest, { recursive: true, force: true });
4716
+ if (existsSync8(dest)) rmSync4(dest, { recursive: true, force: true });
5519
4717
  try {
5520
4718
  await removeMind(name);
5521
4719
  } catch {
5522
4720
  }
5523
4721
  return c.json({ error: err instanceof Error ? err.message : "Failed to create mind" }, 500);
5524
4722
  } finally {
5525
- rmSync5(composedDir, { recursive: true, force: true });
4723
+ rmSync4(composedDir, { recursive: true, force: true });
5526
4724
  }
5527
4725
  }).post("/import", requireAdmin, async (c) => {
5528
4726
  let body;
@@ -5535,13 +4733,13 @@ The human who planted you described you as: "${body.description}"
5535
4733
  return importFromArchive(c, body.archivePath, body.name, body.manifest);
5536
4734
  }
5537
4735
  const wsDir = body.workspacePath;
5538
- if (!wsDir || !existsSync9(resolve12(wsDir, "SOUL.md")) || !existsSync9(resolve12(wsDir, "IDENTITY.md"))) {
4736
+ if (!wsDir || !existsSync8(resolve11(wsDir, "SOUL.md")) || !existsSync8(resolve11(wsDir, "IDENTITY.md"))) {
5539
4737
  return c.json({ error: "Invalid workspace: missing SOUL.md or IDENTITY.md" }, 400);
5540
4738
  }
5541
- const soul = readFileSync10(resolve12(wsDir, "SOUL.md"), "utf-8");
5542
- const identity = readFileSync10(resolve12(wsDir, "IDENTITY.md"), "utf-8");
5543
- const userPath = resolve12(wsDir, "USER.md");
5544
- const user = existsSync9(userPath) ? readFileSync10(userPath, "utf-8") : "";
4739
+ const soul = readFileSync9(resolve11(wsDir, "SOUL.md"), "utf-8");
4740
+ const identity = readFileSync9(resolve11(wsDir, "IDENTITY.md"), "utf-8");
4741
+ const userPath = resolve11(wsDir, "USER.md");
4742
+ const user = existsSync8(userPath) ? readFileSync9(userPath, "utf-8") : "";
5545
4743
  const name = body.name ?? parseNameFromIdentity(identity) ?? "imported-mind";
5546
4744
  const template = body.template ?? "claude";
5547
4745
  const nameErr = validateMindName(name);
@@ -5561,33 +4759,33 @@ ${user.trimEnd()}
5561
4759
  ` : "";
5562
4760
  ensureVoluteHome();
5563
4761
  const dest = mindDir(name);
5564
- if (existsSync9(dest)) return c.json({ error: "Mind directory already exists" }, 409);
4762
+ if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5565
4763
  const templatesRoot = findTemplatesRoot();
5566
4764
  const { composedDir, manifest } = composeTemplate(templatesRoot, template);
5567
4765
  try {
5568
4766
  copyTemplateToDir(composedDir, dest, name, manifest);
5569
4767
  applyInitFiles(dest);
5570
4768
  const { publicKeyPem: importPublicKey } = generateIdentity(dest);
5571
- writeFileSync8(resolve12(dest, "home/SOUL.md"), mergedSoul);
5572
- const wsMemoryPath = resolve12(wsDir, "MEMORY.md");
5573
- const hasMemory = existsSync9(wsMemoryPath);
4769
+ writeFileSync7(resolve11(dest, "home/SOUL.md"), mergedSoul);
4770
+ const wsMemoryPath = resolve11(wsDir, "MEMORY.md");
4771
+ const hasMemory = existsSync8(wsMemoryPath);
5574
4772
  if (hasMemory) {
5575
- const existingMemory = readFileSync10(wsMemoryPath, "utf-8");
5576
- writeFileSync8(
5577
- resolve12(dest, "home/MEMORY.md"),
4773
+ const existingMemory = readFileSync9(wsMemoryPath, "utf-8");
4774
+ writeFileSync7(
4775
+ resolve11(dest, "home/MEMORY.md"),
5578
4776
  `${existingMemory.trimEnd()}${mergedMemoryExtra}`
5579
4777
  );
5580
4778
  } else if (user) {
5581
- writeFileSync8(resolve12(dest, "home/MEMORY.md"), `${user.trimEnd()}
4779
+ writeFileSync7(resolve11(dest, "home/MEMORY.md"), `${user.trimEnd()}
5582
4780
  `);
5583
4781
  }
5584
- const wsMemoryDir = resolve12(wsDir, "memory");
4782
+ const wsMemoryDir = resolve11(wsDir, "memory");
5585
4783
  let dailyLogCount = 0;
5586
- if (existsSync9(wsMemoryDir)) {
5587
- const destMemoryDir = resolve12(dest, "home/memory");
4784
+ if (existsSync8(wsMemoryDir)) {
4785
+ const destMemoryDir = resolve11(dest, "home/memory");
5588
4786
  const files = readdirSync2(wsMemoryDir).filter((f) => f.endsWith(".md"));
5589
4787
  for (const file of files) {
5590
- cpSync(resolve12(wsMemoryDir, file), resolve12(destMemoryDir, file));
4788
+ cpSync(resolve11(wsMemoryDir, file), resolve11(destMemoryDir, file));
5591
4789
  }
5592
4790
  dailyLogCount = files.length;
5593
4791
  }
@@ -5598,7 +4796,7 @@ ${user.trimEnd()}
5598
4796
  } catch (err) {
5599
4797
  logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
5600
4798
  }
5601
- const homeDir = resolve12(dest, "home");
4799
+ const homeDir = resolve11(dest, "home");
5602
4800
  ensureVoluteGroup();
5603
4801
  createMindUser(name, homeDir);
5604
4802
  chownMindDir(dest, name);
@@ -5606,42 +4804,37 @@ ${user.trimEnd()}
5606
4804
  if (!hasMemory && dailyLogCount > 0) {
5607
4805
  await consolidateMemory(dest);
5608
4806
  }
5609
- const env = isIsolationEnabled() ? { ...process.env, HOME: resolve12(dest, "home") } : void 0;
4807
+ const env = isIsolationEnabled() ? { ...process.env, HOME: resolve11(dest, "home") } : void 0;
5610
4808
  await gitExec(["init"], { cwd: dest, mindName: name, env });
5611
4809
  await configureGitIdentity(name, { cwd: dest, mindName: name, env });
5612
4810
  await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
5613
4811
  await gitExec(["commit", "-m", "import from OpenClaw"], { cwd: dest, mindName: name, env });
5614
- const sessionFile = body.sessionPath ? resolve12(body.sessionPath) : findOpenClawSession(wsDir);
5615
- if (sessionFile && existsSync9(sessionFile)) {
4812
+ const sessionFile = body.sessionPath ? resolve11(body.sessionPath) : findOpenClawSession(wsDir);
4813
+ if (sessionFile && existsSync8(sessionFile)) {
5616
4814
  if (template === "pi") {
5617
4815
  importPiSession(sessionFile, dest);
5618
4816
  } else if (template === "claude") {
5619
4817
  const sessionId = convertSession({ sessionPath: sessionFile, projectDir: dest });
5620
- const mindRuntimeDir = resolve12(dest, ".mind");
5621
- mkdirSync7(mindRuntimeDir, { recursive: true });
5622
- writeFileSync8(resolve12(mindRuntimeDir, "session.json"), JSON.stringify({ sessionId }));
4818
+ const mindRuntimeDir = resolve11(dest, ".mind");
4819
+ mkdirSync6(mindRuntimeDir, { recursive: true });
4820
+ writeFileSync7(resolve11(mindRuntimeDir, "session.json"), JSON.stringify({ sessionId }));
5623
4821
  }
5624
4822
  }
5625
4823
  importOpenClawConnectors(name, dest);
5626
- try {
5627
- await addSharedWorktree(name, dest);
5628
- } catch (err) {
5629
- logger_default.warn(`failed to add shared worktree for ${name}`, logger_default.errorData(err));
5630
- }
5631
4824
  chownMindDir(dest, name);
5632
4825
  publishPublicKey(name, importPublicKey).catch(
5633
4826
  (err) => logger_default.warn(`failed to publish key for ${name}`, { error: err.message })
5634
4827
  );
5635
4828
  return c.json({ ok: true, name, port, message: `Imported mind: ${name} (port ${port})` });
5636
4829
  } catch (err) {
5637
- if (existsSync9(dest)) rmSync5(dest, { recursive: true, force: true });
4830
+ if (existsSync8(dest)) rmSync4(dest, { recursive: true, force: true });
5638
4831
  try {
5639
4832
  await removeMind(name);
5640
4833
  } catch {
5641
4834
  }
5642
4835
  return c.json({ error: err instanceof Error ? err.message : "Failed to import mind" }, 500);
5643
4836
  } finally {
5644
- rmSync5(composedDir, { recursive: true, force: true });
4837
+ rmSync4(composedDir, { recursive: true, force: true });
5645
4838
  }
5646
4839
  }).get("/", async (c) => {
5647
4840
  const entries = await readRegistry();
@@ -5650,7 +4843,7 @@ ${user.trimEnd()}
5650
4843
  const db = await getDb();
5651
4844
  const lastActiveRows = await db.select({
5652
4845
  mind: mindHistory.mind,
5653
- lastActiveAt: sql3`MAX(${mindHistory.created_at})`
4846
+ lastActiveAt: sql2`MAX(${mindHistory.created_at})`
5654
4847
  }).from(mindHistory).groupBy(mindHistory.mind);
5655
4848
  lastActiveMap = new Map(lastActiveRows.map((r) => [r.mind, r.lastActiveAt]));
5656
4849
  } catch {
@@ -5658,7 +4851,7 @@ ${user.trimEnd()}
5658
4851
  const minds = await Promise.all(
5659
4852
  entries.map(async (entry) => {
5660
4853
  const mindStatus = await getMindStatus(entry.name, entry.port);
5661
- const hasPages = existsSync9(resolve12(mindDir(entry.name), "home", "public", "pages"));
4854
+ const hasPages = existsSync8(resolve11(mindDir(entry.name), "home", "pages"));
5662
4855
  return {
5663
4856
  ...entry,
5664
4857
  ...mindStatus,
@@ -5673,7 +4866,7 @@ ${user.trimEnd()}
5673
4866
  const entry = await findMind(name);
5674
4867
  if (!entry) return c.json({ error: "Mind not found" }, 404);
5675
4868
  const dir = entry.dir ?? mindDir(entry.parent ?? name);
5676
- if (!existsSync9(dir)) return c.json({ error: "Mind directory missing" }, 404);
4869
+ if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
5677
4870
  const mindStatus = await getMindStatus(name, entry.port);
5678
4871
  const variants = await findVariants(name);
5679
4872
  const manager = getMindManager();
@@ -5687,7 +4880,7 @@ ${user.trimEnd()}
5687
4880
  return { name: s.name, port: s.port, status: variantStatus };
5688
4881
  })
5689
4882
  );
5690
- const hasPages = existsSync9(resolve12(mindDir(name), "home", "public", "pages"));
4883
+ const hasPages = existsSync8(resolve11(mindDir(name), "home", "pages"));
5691
4884
  return c.json({ ...entry, ...mindStatus, variants: variantStatuses, hasPages });
5692
4885
  }).get("/:name/context", async (c) => {
5693
4886
  const name = c.req.param("name");
@@ -5724,7 +4917,7 @@ ${user.trimEnd()}
5724
4917
  if (!entry.dir) return c.json({ error: `Variant ${name} has no directory` }, 404);
5725
4918
  } else {
5726
4919
  const dir = mindDir(name);
5727
- if (!existsSync9(dir)) return c.json({ error: "Mind directory missing" }, 404);
4920
+ if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
5728
4921
  }
5729
4922
  if (getMindManager().isRunning(name)) {
5730
4923
  return c.json({ error: "Mind already running" }, 409);
@@ -5745,7 +4938,7 @@ ${user.trimEnd()}
5745
4938
  if (!entry.dir) return c.json({ error: `Variant ${name} has no directory` }, 404);
5746
4939
  } else {
5747
4940
  const dir = mindDir(name);
5748
- if (!existsSync9(dir)) return c.json({ error: "Mind directory missing" }, 404);
4941
+ if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
5749
4942
  }
5750
4943
  let context;
5751
4944
  const contentType = c.req.header("content-type");
@@ -5760,7 +4953,7 @@ ${user.trimEnd()}
5760
4953
  const manager = getMindManager();
5761
4954
  try {
5762
4955
  if (context?.type === "reload") {
5763
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BJK2ROPX.js");
4956
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-7KFK3USC.js");
5764
4957
  const sleepState = getSleepManagerIfReady2()?.getState(name);
5765
4958
  if (sleepState?.sleeping) {
5766
4959
  logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
@@ -5780,7 +4973,7 @@ ${user.trimEnd()}
5780
4973
  const variantEntry = await findMind(mergeVariantName);
5781
4974
  if (variantEntry && variantEntry.parent === baseName && variantEntry.dir && variantEntry.branch) {
5782
4975
  const projectRoot = mindDir(baseName);
5783
- if (existsSync9(variantEntry.dir)) {
4976
+ if (existsSync8(variantEntry.dir)) {
5784
4977
  const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
5785
4978
  if (status) {
5786
4979
  try {
@@ -5822,7 +5015,7 @@ ${user.trimEnd()}
5822
5015
  if (context?.type === "sprouted" && !entry.parent) {
5823
5016
  try {
5824
5017
  const db = await getDb();
5825
- const activeConvs = await db.select({ id: conversations.id, channel: conversations.channel }).from(conversations).where(eq6(conversations.mind_name, baseName)).all();
5018
+ const activeConvs = await db.select({ id: conversations.id, channel: conversations.channel }).from(conversations).where(eq5(conversations.mind_name, baseName)).all();
5826
5019
  for (const conv of activeConvs) {
5827
5020
  await recordInbound(baseName, conv.channel, "system", "[seed has sprouted]");
5828
5021
  await addMessage(conv.id, "assistant", "system", [
@@ -5856,7 +5049,7 @@ ${user.trimEnd()}
5856
5049
  const name = c.req.param("name");
5857
5050
  const entry = await findMind(name);
5858
5051
  if (!entry) return c.json({ error: "Mind not found" }, 404);
5859
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BJK2ROPX.js");
5052
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-7KFK3USC.js");
5860
5053
  const sm = getSleepManagerIfReady2();
5861
5054
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
5862
5055
  return c.json(sm.getState(name));
@@ -5864,7 +5057,7 @@ ${user.trimEnd()}
5864
5057
  const name = c.req.param("name");
5865
5058
  const entry = await findMind(name);
5866
5059
  if (!entry) return c.json({ error: "Mind not found" }, 404);
5867
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BJK2ROPX.js");
5060
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-7KFK3USC.js");
5868
5061
  const sm = getSleepManagerIfReady2();
5869
5062
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
5870
5063
  if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
@@ -5884,7 +5077,7 @@ ${user.trimEnd()}
5884
5077
  const name = c.req.param("name");
5885
5078
  const entry = await findMind(name);
5886
5079
  if (!entry) return c.json({ error: "Mind not found" }, 404);
5887
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BJK2ROPX.js");
5080
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-7KFK3USC.js");
5888
5081
  const sm = getSleepManagerIfReady2();
5889
5082
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
5890
5083
  const sleepState = sm.getState(name);
@@ -5899,7 +5092,7 @@ ${user.trimEnd()}
5899
5092
  const name = c.req.param("name");
5900
5093
  const entry = await findMind(name);
5901
5094
  if (!entry) return c.json({ error: "Mind not found" }, 404);
5902
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BJK2ROPX.js");
5095
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-7KFK3USC.js");
5903
5096
  const sm = getSleepManagerIfReady2();
5904
5097
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
5905
5098
  const flushed = await sm.flushQueuedMessages(name);
@@ -5917,7 +5110,7 @@ ${user.trimEnd()}
5917
5110
  if (body.avatar !== void 0) profile.avatar = body.avatar;
5918
5111
  config2.profile = profile;
5919
5112
  writeVoluteConfig(dir, config2);
5920
- const { syncMindProfile: syncMindProfile2 } = await import("./auth-ZFZXJZDQ.js");
5113
+ const { syncMindProfile: syncMindProfile2 } = await import("./auth-WX4TESEI.js");
5921
5114
  await syncMindProfile2(name, profile);
5922
5115
  broadcast({ type: "profile_updated", mind: name, summary: `${name} profile updated` });
5923
5116
  return c.json({ ok: true });
@@ -5933,21 +5126,21 @@ ${user.trimEnd()}
5933
5126
  const rawSpirit = Number(process.env.VOLUTE_NURTURE_SPIRIT_MINUTES);
5934
5127
  const spiritThreshold = Number.isNaN(rawSpirit) ? 15 : rawSpirit;
5935
5128
  const lastCreatorMsg = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(
5936
- and5(
5937
- eq6(mindHistory.mind, name),
5938
- eq6(mindHistory.type, "inbound"),
5939
- sql3`${mindHistory.sender} != 'volute'`,
5940
- sql3`${mindHistory.sender} != ${name}`,
5941
- sql3`${mindHistory.sender} IS NOT NULL`
5129
+ and4(
5130
+ eq5(mindHistory.mind, name),
5131
+ eq5(mindHistory.type, "inbound"),
5132
+ sql2`${mindHistory.sender} != 'volute'`,
5133
+ sql2`${mindHistory.sender} != ${name}`,
5134
+ sql2`${mindHistory.sender} IS NOT NULL`
5942
5135
  )
5943
- ).orderBy(desc4(mindHistory.created_at)).limit(1);
5136
+ ).orderBy(desc3(mindHistory.created_at)).limit(1);
5944
5137
  const lastSpiritMsg = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(
5945
- and5(
5946
- eq6(mindHistory.mind, name),
5947
- eq6(mindHistory.type, "inbound"),
5948
- eq6(mindHistory.sender, "volute")
5138
+ and4(
5139
+ eq5(mindHistory.mind, name),
5140
+ eq5(mindHistory.type, "inbound"),
5141
+ eq5(mindHistory.sender, "volute")
5949
5142
  )
5950
- ).orderBy(desc4(mindHistory.created_at)).limit(1);
5143
+ ).orderBy(desc3(mindHistory.created_at)).limit(1);
5951
5144
  const now = Date.now();
5952
5145
  const creatorTime = lastCreatorMsg[0] ? new Date(lastCreatorMsg[0].created_at).getTime() : 0;
5953
5146
  const spiritTime = lastSpiritMsg[0] ? new Date(lastSpiritMsg[0].created_at).getTime() : 0;
@@ -5957,14 +5150,14 @@ ${user.trimEnd()}
5957
5150
  return c.json({ output: "" });
5958
5151
  }
5959
5152
  const dir = entry.dir ?? mindDir(name);
5960
- const soulPath = resolve12(dir, "home/SOUL.md");
5961
- const memoryPath = resolve12(dir, "home/MEMORY.md");
5962
- const soulCustom = existsSync9(soulPath) && !readFileSync10(soulPath, "utf-8").includes(ORIENTATION_MARKER);
5963
- const memoryWritten = existsSync9(memoryPath) && readFileSync10(memoryPath, "utf-8").trim().length > 0;
5153
+ const soulPath = resolve11(dir, "home/SOUL.md");
5154
+ const memoryPath = resolve11(dir, "home/MEMORY.md");
5155
+ const soulCustom = existsSync8(soulPath) && !readFileSync9(soulPath, "utf-8").includes(ORIENTATION_MARKER);
5156
+ const memoryWritten = existsSync8(memoryPath) && readFileSync9(memoryPath, "utf-8").trim().length > 0;
5964
5157
  const config2 = readVoluteConfig(dir);
5965
5158
  const displayNameSet = !!config2?.profile?.displayName;
5966
5159
  const avatarSet = !!config2?.profile?.avatar;
5967
- const { isImagegenEnabled } = await import("./setup-GGMKENLN.js");
5160
+ const { isImagegenEnabled } = await import("./setup-RHJRFURI.js");
5968
5161
  const imagegenEnabled = isImagegenEnabled();
5969
5162
  const done = [];
5970
5163
  const remaining = [];
@@ -6002,7 +5195,7 @@ ${user.trimEnd()}
6002
5195
  try {
6003
5196
  const spiritEntry = await findMind("volute");
6004
5197
  if (spiritEntry) {
6005
- const { spiritDir } = await import("./spirit-4JP4TY4C.js");
5198
+ const { spiritDir } = await import("./spirit-ZFRDXMG7.js");
6006
5199
  const sDir = spiritEntry.dir ?? spiritDir();
6007
5200
  const spiritConfig = readVoluteConfig(sDir);
6008
5201
  if (spiritConfig?.schedules) {
@@ -6010,7 +5203,7 @@ ${user.trimEnd()}
6010
5203
  spiritConfig.schedules = spiritConfig.schedules.filter((s) => s.id !== nurtureId);
6011
5204
  if (spiritConfig.schedules.length === 0) spiritConfig.schedules = void 0;
6012
5205
  writeVoluteConfig(sDir, spiritConfig);
6013
- const { getScheduler: getScheduler2 } = await import("./scheduler-AGG3L2FO.js");
5206
+ const { getScheduler: getScheduler2 } = await import("./scheduler-Y7O4CJXL.js");
6014
5207
  getScheduler2().loadSchedules("volute", sDir);
6015
5208
  }
6016
5209
  }
@@ -6034,19 +5227,14 @@ ${user.trimEnd()}
6034
5227
  await cleanupVariant(s.name, dir, s.dir, { stop: true });
6035
5228
  }
6036
5229
  }
6037
- try {
6038
- await removeSharedWorktree(name, dir);
6039
- } catch (err) {
6040
- logger_default.warn(`failed to clean up shared worktree for ${name}`, logger_default.errorData(err));
6041
- }
6042
5230
  await removeMind(name);
6043
5231
  await deleteMindUser2(name);
6044
5232
  const state = stateDir(name);
6045
- if (existsSync9(state)) {
6046
- rmSync5(state, { recursive: true, force: true });
5233
+ if (existsSync8(state)) {
5234
+ rmSync4(state, { recursive: true, force: true });
6047
5235
  }
6048
- if (force && existsSync9(dir)) {
6049
- rmSync5(dir, { recursive: true, force: true });
5236
+ if (force && existsSync8(dir)) {
5237
+ rmSync4(dir, { recursive: true, force: true });
6050
5238
  deleteMindUser(name);
6051
5239
  }
6052
5240
  fireWebhook({
@@ -6060,7 +5248,7 @@ ${user.trimEnd()}
6060
5248
  const entry = await findMind(mindName);
6061
5249
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6062
5250
  const dir = mindDir(mindName);
6063
- if (!existsSync9(dir)) return c.json({ error: "Mind directory missing" }, 404);
5251
+ if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
6064
5252
  let body = {};
6065
5253
  try {
6066
5254
  body = await c.req.json();
@@ -6069,16 +5257,16 @@ ${user.trimEnd()}
6069
5257
  const template = body.template ?? entry.template ?? "claude";
6070
5258
  const UPGRADE_BRANCH = "upgrade";
6071
5259
  const upgradeVariantName = `${mindName}-upgrade`;
6072
- const worktreeDir = resolve12(dir, ".variants", UPGRADE_BRANCH);
5260
+ const worktreeDir = resolve11(dir, ".variants", UPGRADE_BRANCH);
6073
5261
  if (body.abort) {
6074
- if (!existsSync9(worktreeDir)) {
5262
+ if (!existsSync8(worktreeDir)) {
6075
5263
  return c.json({ error: "No upgrade in progress" }, 400);
6076
5264
  }
6077
5265
  try {
6078
5266
  try {
6079
- const gitDirContent = readFileSync10(resolve12(worktreeDir, ".git"), "utf-8").trim();
5267
+ const gitDirContent = readFileSync9(resolve11(worktreeDir, ".git"), "utf-8").trim();
6080
5268
  const gitDir = gitDirContent.replace("gitdir: ", "");
6081
- if (existsSync9(resolve12(gitDir, "MERGE_HEAD"))) {
5269
+ if (existsSync8(resolve11(gitDir, "MERGE_HEAD"))) {
6082
5270
  await gitExec(["merge", "--abort"], { cwd: worktreeDir });
6083
5271
  }
6084
5272
  } catch {
@@ -6097,7 +5285,7 @@ ${user.trimEnd()}
6097
5285
  }
6098
5286
  }
6099
5287
  if (body.continue) {
6100
- if (!existsSync9(worktreeDir)) {
5288
+ if (!existsSync8(worktreeDir)) {
6101
5289
  return c.json({ error: "No upgrade in progress" }, 400);
6102
5290
  }
6103
5291
  const status = await gitExec(["status", "--porcelain"], { cwd: worktreeDir });
@@ -6146,7 +5334,7 @@ ${user.trimEnd()}
6146
5334
  }
6147
5335
  }
6148
5336
  if (body.accept) {
6149
- if (existsSync9(worktreeDir)) {
5337
+ if (existsSync8(worktreeDir)) {
6150
5338
  try {
6151
5339
  await cleanupVariant(upgradeVariantName, dir, worktreeDir, { stop: true });
6152
5340
  } catch (err) {
@@ -6161,7 +5349,7 @@ ${user.trimEnd()}
6161
5349
  }
6162
5350
  if (body.diff) {
6163
5351
  try {
6164
- if (!existsSync9(resolve12(dir, ".git"))) {
5352
+ if (!existsSync8(resolve11(dir, ".git"))) {
6165
5353
  return c.json({ error: "Mind has no git history \u2014 nothing to diff against" }, 400);
6166
5354
  }
6167
5355
  await updateTemplateBranch(dir, template, mindName);
@@ -6179,22 +5367,22 @@ ${user.trimEnd()}
6179
5367
  );
6180
5368
  }
6181
5369
  }
6182
- if (existsSync9(worktreeDir)) {
5370
+ if (existsSync8(worktreeDir)) {
6183
5371
  return c.json(
6184
5372
  { error: "Upgrade variant already exists. Use continue or delete it first." },
6185
5373
  409
6186
5374
  );
6187
5375
  }
6188
- if (!existsSync9(resolve12(dir, ".git"))) {
5376
+ if (!existsSync8(resolve11(dir, ".git"))) {
6189
5377
  try {
6190
- const env = isIsolationEnabled() ? { ...process.env, HOME: resolve12(dir, "home") } : void 0;
5378
+ const env = isIsolationEnabled() ? { ...process.env, HOME: resolve11(dir, "home") } : void 0;
6191
5379
  await gitExec(["init"], { cwd: dir, mindName, env });
6192
5380
  await configureGitIdentity(mindName, { cwd: dir, mindName, env });
6193
5381
  await gitExec(["add", "-A"], { cwd: dir, mindName, env });
6194
5382
  await gitExec(["commit", "-m", "initial commit"], { cwd: dir, mindName, env });
6195
5383
  chownMindDir(dir, mindName);
6196
5384
  } catch (err) {
6197
- rmSync5(resolve12(dir, ".git"), { recursive: true, force: true });
5385
+ rmSync4(resolve11(dir, ".git"), { recursive: true, force: true });
6198
5386
  return c.json(
6199
5387
  {
6200
5388
  error: `Git initialization failed: ${err instanceof Error ? err.message : String(err)}`
@@ -6208,20 +5396,10 @@ ${user.trimEnd()}
6208
5396
  await gitExec(["branch", "-D", UPGRADE_BRANCH], { cwd: dir });
6209
5397
  } catch {
6210
5398
  }
6211
- if (!existsSync9(resolve12(dir, "home", "shared"))) {
6212
- try {
6213
- await addSharedWorktree(mindName, dir);
6214
- } catch (err) {
6215
- logger_default.warn(
6216
- `failed to add shared worktree during upgrade for ${mindName}`,
6217
- logger_default.errorData(err)
6218
- );
6219
- }
6220
- }
6221
5399
  await updateTemplateBranch(dir, template, mindName);
6222
- const parentDir = resolve12(dir, ".variants");
6223
- if (!existsSync9(parentDir)) {
6224
- mkdirSync7(parentDir, { recursive: true });
5400
+ const parentDir = resolve11(dir, ".variants");
5401
+ if (!existsSync8(parentDir)) {
5402
+ mkdirSync6(parentDir, { recursive: true });
6225
5403
  }
6226
5404
  await gitExec(["worktree", "add", "-b", UPGRADE_BRANCH, worktreeDir], { cwd: dir });
6227
5405
  await gitExec(["rm", "-r", "--cached", "--ignore-unmatch", "home/"], {
@@ -6349,22 +5527,22 @@ ${user.trimEnd()}
6349
5527
  const entry = await findMind(name);
6350
5528
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6351
5529
  const dir = entry.dir ?? mindDir(name);
6352
- if (!existsSync9(dir)) return c.json({ error: "Mind directory missing" }, 404);
5530
+ if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
6353
5531
  let config2 = readVoluteConfig(dir);
6354
5532
  if (!config2 && entry.template === "pi") {
6355
- const piConfigPath = resolve12(dir, "home/.config/config.json");
6356
- if (existsSync9(piConfigPath)) {
5533
+ const piConfigPath = resolve11(dir, "home/.config/config.json");
5534
+ if (existsSync8(piConfigPath)) {
6357
5535
  try {
6358
- config2 = JSON.parse(readFileSync10(piConfigPath, "utf-8"));
5536
+ config2 = JSON.parse(readFileSync9(piConfigPath, "utf-8"));
6359
5537
  } catch {
6360
5538
  }
6361
5539
  }
6362
5540
  }
6363
5541
  let templateConfig = {};
6364
- const configJsonPath = resolve12(dir, "home/.config/config.json");
6365
- if (existsSync9(configJsonPath)) {
5542
+ const configJsonPath = resolve11(dir, "home/.config/config.json");
5543
+ if (existsSync8(configJsonPath)) {
6366
5544
  try {
6367
- templateConfig = JSON.parse(readFileSync10(configJsonPath, "utf-8"));
5545
+ templateConfig = JSON.parse(readFileSync9(configJsonPath, "utf-8"));
6368
5546
  } catch {
6369
5547
  }
6370
5548
  }
@@ -6418,7 +5596,7 @@ ${user.trimEnd()}
6418
5596
  const entry = await findMind(name);
6419
5597
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6420
5598
  const dir = entry.dir ?? mindDir(name);
6421
- if (!existsSync9(dir)) return c.json({ error: "Mind directory missing" }, 404);
5599
+ if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
6422
5600
  const body = c.req.valid("json");
6423
5601
  const existing = readVoluteConfig(dir) ?? {};
6424
5602
  if (body.model !== void 0) existing.model = body.model;
@@ -6449,11 +5627,11 @@ ${user.trimEnd()}
6449
5627
  writeVoluteConfig(dir, existing);
6450
5628
  const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.maxThinkingTokens !== void 0 || body.compaction !== void 0;
6451
5629
  if (needsConfigJson) {
6452
- const configJsonPath = resolve12(dir, "home/.config/config.json");
5630
+ const configJsonPath = resolve11(dir, "home/.config/config.json");
6453
5631
  let templateConfig = {};
6454
- if (existsSync9(configJsonPath)) {
5632
+ if (existsSync8(configJsonPath)) {
6455
5633
  try {
6456
- templateConfig = JSON.parse(readFileSync10(configJsonPath, "utf-8"));
5634
+ templateConfig = JSON.parse(readFileSync9(configJsonPath, "utf-8"));
6457
5635
  } catch {
6458
5636
  }
6459
5637
  }
@@ -6516,12 +5694,12 @@ ${user.trimEnd()}
6516
5694
  templateConfig.compaction = comp;
6517
5695
  }
6518
5696
  }
6519
- writeFileSync8(configJsonPath, `${JSON.stringify(templateConfig, null, 2)}
5697
+ writeFileSync7(configJsonPath, `${JSON.stringify(templateConfig, null, 2)}
6520
5698
  `);
6521
5699
  }
6522
5700
  if (entry.mindType === "spirit" && body.model !== void 0) {
6523
5701
  try {
6524
- const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-GGMKENLN.js");
5702
+ const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-RHJRFURI.js");
6525
5703
  const globalConfig = readGlobalConfig2();
6526
5704
  globalConfig.spiritModel = body.model;
6527
5705
  writeGlobalConfig2(globalConfig);
@@ -6549,7 +5727,7 @@ ${user.trimEnd()}
6549
5727
  if (!body.systemPrompt || !body.message) {
6550
5728
  return c.json({ error: "systemPrompt and message required" }, 400);
6551
5729
  }
6552
- const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-PSILB5WD.js");
5730
+ const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-LURBEDDB.js");
6553
5731
  if (!isAiConfigured()) {
6554
5732
  return c.json({ error: "AI service not configured" }, 503);
6555
5733
  }
@@ -6783,32 +5961,32 @@ ${user.trimEnd()}
6783
5961
  const db = await getDb();
6784
5962
  const rows = await db.select({
6785
5963
  session: mindHistory.session,
6786
- started_at: sql3`MIN(${mindHistory.created_at})`,
6787
- event_count: sql3`COUNT(*)`,
6788
- message_count: sql3`SUM(CASE WHEN ${mindHistory.type} IN ('inbound','outbound') THEN 1 ELSE 0 END)`,
6789
- tool_count: sql3`SUM(CASE WHEN ${mindHistory.type}='tool_use' THEN 1 ELSE 0 END)`
6790
- }).from(mindHistory).where(and5(eq6(mindHistory.mind, name), sql3`${mindHistory.session} IS NOT NULL`)).groupBy(mindHistory.session).orderBy(sql3`MIN(${mindHistory.created_at}) DESC`);
5964
+ started_at: sql2`MIN(${mindHistory.created_at})`,
5965
+ event_count: sql2`COUNT(*)`,
5966
+ message_count: sql2`SUM(CASE WHEN ${mindHistory.type} IN ('inbound','outbound') THEN 1 ELSE 0 END)`,
5967
+ tool_count: sql2`SUM(CASE WHEN ${mindHistory.type}='tool_use' THEN 1 ELSE 0 END)`
5968
+ }).from(mindHistory).where(and4(eq5(mindHistory.mind, name), sql2`${mindHistory.session} IS NOT NULL`)).groupBy(mindHistory.session).orderBy(sql2`MIN(${mindHistory.created_at}) DESC`);
6791
5969
  return c.json(rows);
6792
5970
  }).get("/:name/history/channels", async (c) => {
6793
5971
  const name = c.req.param("name");
6794
5972
  const db = await getDb();
6795
- const rows = await db.selectDistinct({ channel: mindHistory.channel }).from(mindHistory).where(eq6(mindHistory.mind, name));
5973
+ const rows = await db.selectDistinct({ channel: mindHistory.channel }).from(mindHistory).where(eq5(mindHistory.mind, name));
6796
5974
  return c.json(rows.map((r) => r.channel));
6797
5975
  }).get("/:name/history/export", async (c) => {
6798
5976
  const name = c.req.param("name");
6799
5977
  if (!await findMind(name)) return c.json({ error: "Mind not found" }, 404);
6800
5978
  const db = await getDb();
6801
- const rows = await db.select().from(mindHistory).where(eq6(mindHistory.mind, name));
5979
+ const rows = await db.select().from(mindHistory).where(eq5(mindHistory.mind, name));
6802
5980
  return c.json(rows);
6803
5981
  }).get("/:name/history/turn", async (c) => {
6804
5982
  const name = c.req.param("name");
6805
5983
  const turnId = c.req.query("turn_id");
6806
5984
  const detail = c.req.query("detail") === "1";
6807
5985
  const db = await getDb();
6808
- const typeFilter = detail ? void 0 : sql3`${mindHistory.type} IN ('inbound','outbound','tool_use','tool_result','text','thinking','activity')`;
5986
+ const typeFilter = detail ? void 0 : sql2`${mindHistory.type} IN ('inbound','outbound','tool_use','tool_result','text','thinking','activity')`;
6809
5987
  let rows;
6810
5988
  if (turnId) {
6811
- rows = await db.select().from(mindHistory).where(and5(eq6(mindHistory.mind, name), eq6(mindHistory.turn_id, turnId), typeFilter)).orderBy(mindHistory.id);
5989
+ rows = await db.select().from(mindHistory).where(and4(eq5(mindHistory.mind, name), eq5(mindHistory.turn_id, turnId), typeFilter)).orderBy(mindHistory.id);
6812
5990
  } else {
6813
5991
  const session = c.req.query("session");
6814
5992
  const fromId = parseInt(c.req.query("from_id") ?? "", 10);
@@ -6817,11 +5995,11 @@ ${user.trimEnd()}
6817
5995
  return c.json({ error: "turn_id, or session with from_id and to_id, required" }, 400);
6818
5996
  }
6819
5997
  rows = await db.select().from(mindHistory).where(
6820
- and5(
6821
- eq6(mindHistory.mind, name),
6822
- eq6(mindHistory.session, session),
6823
- sql3`${mindHistory.id} >= ${fromId}`,
6824
- sql3`${mindHistory.id} <= ${toId}`,
5998
+ and4(
5999
+ eq5(mindHistory.mind, name),
6000
+ eq5(mindHistory.session, session),
6001
+ sql2`${mindHistory.id} >= ${fromId}`,
6002
+ sql2`${mindHistory.id} <= ${toId}`,
6825
6003
  typeFilter
6826
6004
  )
6827
6005
  ).orderBy(mindHistory.id);
@@ -6834,14 +6012,14 @@ ${user.trimEnd()}
6834
6012
  let sinceTimestamp = null;
6835
6013
  if (currentSession) {
6836
6014
  const lastTurn = await db.select({ turn_id: mindHistory.turn_id }).from(mindHistory).where(
6837
- and5(
6838
- eq6(mindHistory.mind, name),
6839
- eq6(mindHistory.session, currentSession),
6840
- sql3`${mindHistory.turn_id} IS NOT NULL`
6015
+ and4(
6016
+ eq5(mindHistory.mind, name),
6017
+ eq5(mindHistory.session, currentSession),
6018
+ sql2`${mindHistory.turn_id} IS NOT NULL`
6841
6019
  )
6842
- ).orderBy(desc4(mindHistory.created_at)).limit(1);
6020
+ ).orderBy(desc3(mindHistory.created_at)).limit(1);
6843
6021
  if (lastTurn.length > 0 && lastTurn[0].turn_id) {
6844
- const firstEvent = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(eq6(mindHistory.turn_id, lastTurn[0].turn_id)).orderBy(mindHistory.created_at).limit(1);
6022
+ const firstEvent = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(eq5(mindHistory.turn_id, lastTurn[0].turn_id)).orderBy(mindHistory.created_at).limit(1);
6845
6023
  if (firstEvent.length > 0) {
6846
6024
  sinceTimestamp = firstEvent[0].created_at;
6847
6025
  }
@@ -6851,18 +6029,18 @@ ${user.trimEnd()}
6851
6029
  sinceTimestamp = new Date(Date.now() - 36e5).toISOString().replace("T", " ").slice(0, 19);
6852
6030
  }
6853
6031
  const conditions = [
6854
- eq6(summaries.mind, name),
6855
- eq6(summaries.period, "turn"),
6856
- sql3`${summaries.created_at} > ${sinceTimestamp}`
6032
+ eq5(summaries.mind, name),
6033
+ eq5(summaries.period, "turn"),
6034
+ sql2`${summaries.created_at} > ${sinceTimestamp}`
6857
6035
  ];
6858
6036
  if (currentSession) {
6859
- conditions.push(sql3`${turns.session} != ${currentSession}`);
6037
+ conditions.push(sql2`${turns.session} != ${currentSession}`);
6860
6038
  }
6861
6039
  const rows = await db.select({
6862
6040
  session: turns.session,
6863
6041
  content: summaries.content,
6864
6042
  created_at: summaries.created_at
6865
- }).from(summaries).innerJoin(turns, eq6(turns.id, summaries.period_key)).where(and5(...conditions)).orderBy(desc4(summaries.created_at)).limit(50);
6043
+ }).from(summaries).innerJoin(turns, eq5(turns.id, summaries.period_key)).where(and4(...conditions)).orderBy(desc3(summaries.created_at)).limit(50);
6866
6044
  if (rows.length === 0) {
6867
6045
  return c.json({ context: null });
6868
6046
  }
@@ -6882,18 +6060,18 @@ ${lines.join("\n")}` });
6882
6060
  const limit = Math.min(Math.max(parseInt(c.req.query("limit") ?? "50", 10) || 50, 1), 200);
6883
6061
  const offset = Math.max(parseInt(c.req.query("offset") ?? "0", 10) || 0, 0);
6884
6062
  const db = await getDb();
6885
- const conditions = [eq6(mindHistory.mind, name)];
6063
+ const conditions = [eq5(mindHistory.mind, name)];
6886
6064
  if (channel) {
6887
- conditions.push(eq6(mindHistory.channel, channel));
6065
+ conditions.push(eq5(mindHistory.channel, channel));
6888
6066
  }
6889
6067
  if (session) {
6890
- conditions.push(eq6(mindHistory.session, session));
6068
+ conditions.push(eq5(mindHistory.session, session));
6891
6069
  }
6892
6070
  const effectivePreset = full ? "all" : preset;
6893
6071
  if (!effectivePreset || effectivePreset === "summary") {
6894
- const sumConditions = [eq6(summaries.mind, name), eq6(summaries.period, "turn")];
6072
+ const sumConditions = [eq5(summaries.mind, name), eq5(summaries.period, "turn")];
6895
6073
  if (session) {
6896
- sumConditions.push(eq6(turns.session, session));
6074
+ sumConditions.push(eq5(turns.session, session));
6897
6075
  const sumRows2 = await db.select({
6898
6076
  id: summaries.id,
6899
6077
  mind: summaries.mind,
@@ -6903,7 +6081,7 @@ ${lines.join("\n")}` });
6903
6081
  metadata: summaries.metadata,
6904
6082
  created_at: summaries.created_at,
6905
6083
  session: turns.session
6906
- }).from(summaries).innerJoin(turns, eq6(turns.id, summaries.period_key)).where(and5(...sumConditions)).orderBy(desc4(summaries.created_at)).limit(limit).offset(offset);
6084
+ }).from(summaries).innerJoin(turns, eq5(turns.id, summaries.period_key)).where(and4(...sumConditions)).orderBy(desc3(summaries.created_at)).limit(limit).offset(offset);
6907
6085
  return c.json(
6908
6086
  sumRows2.map((r) => ({
6909
6087
  id: r.id,
@@ -6920,7 +6098,7 @@ ${lines.join("\n")}` });
6920
6098
  }))
6921
6099
  );
6922
6100
  }
6923
- const sumRows = await db.select().from(summaries).where(and5(...sumConditions)).orderBy(desc4(summaries.created_at)).limit(limit).offset(offset);
6101
+ const sumRows = await db.select().from(summaries).where(and4(...sumConditions)).orderBy(desc3(summaries.created_at)).limit(limit).offset(offset);
6924
6102
  return c.json(
6925
6103
  sumRows.map((r) => ({
6926
6104
  id: r.id,
@@ -6941,22 +6119,22 @@ ${lines.join("\n")}` });
6941
6119
  case "all":
6942
6120
  break;
6943
6121
  case "conversation":
6944
- conditions.push(sql3`${mindHistory.type} IN ('inbound','outbound','tool_use')`);
6122
+ conditions.push(sql2`${mindHistory.type} IN ('inbound','outbound','tool_use')`);
6945
6123
  break;
6946
6124
  case "detailed":
6947
6125
  conditions.push(
6948
- sql3`${mindHistory.type} IN ('inbound','outbound','tool_use','tool_result','text','thinking')`
6126
+ sql2`${mindHistory.type} IN ('inbound','outbound','tool_use','tool_result','text','thinking')`
6949
6127
  );
6950
6128
  break;
6951
6129
  }
6952
- const rows = await db.select().from(mindHistory).where(and5(...conditions)).orderBy(desc4(mindHistory.created_at)).limit(limit).offset(offset);
6130
+ const rows = await db.select().from(mindHistory).where(and4(...conditions)).orderBy(desc3(mindHistory.created_at)).limit(limit).offset(offset);
6953
6131
  return c.json(rows);
6954
6132
  });
6955
6133
  var minds_default = app13;
6956
6134
 
6957
- // src/web/api/prompts.ts
6135
+ // packages/daemon/src/web/api/prompts.ts
6958
6136
  import { zValidator as zValidator6 } from "@hono/zod-validator";
6959
- import { eq as eq7, sql as sql4 } from "drizzle-orm";
6137
+ import { eq as eq6, sql as sql3 } from "drizzle-orm";
6960
6138
  import { Hono as Hono16 } from "hono";
6961
6139
  import { z as z6 } from "zod";
6962
6140
  var app14 = new Hono16().get("/", async (c) => {
@@ -6989,9 +6167,9 @@ var app14 = new Hono16().get("/", async (c) => {
6989
6167
  }
6990
6168
  const { content } = c.req.valid("json");
6991
6169
  const db = await getDb();
6992
- await db.insert(systemPrompts).values({ key, content, updated_at: sql4`(datetime('now'))` }).onConflictDoUpdate({
6170
+ await db.insert(systemPrompts).values({ key, content, updated_at: sql3`(datetime('now'))` }).onConflictDoUpdate({
6993
6171
  target: systemPrompts.key,
6994
- set: { content, updated_at: sql4`(datetime('now'))` }
6172
+ set: { content, updated_at: sql3`(datetime('now'))` }
6995
6173
  });
6996
6174
  return c.json({ ok: true });
6997
6175
  }).delete("/:key", requireAdmin, async (c) => {
@@ -7000,103 +6178,14 @@ var app14 = new Hono16().get("/", async (c) => {
7000
6178
  return c.json({ error: "Unknown prompt key" }, 404);
7001
6179
  }
7002
6180
  const db = await getDb();
7003
- await db.delete(systemPrompts).where(eq7(systemPrompts.key, key));
6181
+ await db.delete(systemPrompts).where(eq6(systemPrompts.key, key));
7004
6182
  return c.json({ ok: true });
7005
6183
  });
7006
6184
  var prompts_default = app14;
7007
6185
 
7008
- // src/web/api/public-files.ts
7009
- import { readdir, readFile as readFile2, stat as stat2 } from "fs/promises";
7010
- import { extname as extname3, resolve as resolve13 } from "path";
7011
- import { Hono as Hono17 } from "hono";
7012
- var MAX_FILE_SIZE = 50 * 1024 * 1024;
7013
- async function resolvePublicRoot(name) {
7014
- if (name === "_system") return resolve13(voluteHome(), "shared");
7015
- if (!await findMind(name)) return null;
7016
- return resolve13(mindDir(name), "home", "public");
7017
- }
7018
- function hasDotSegment(relativePath) {
7019
- return relativePath.split("/").some((seg) => seg.startsWith("."));
7020
- }
7021
- var MIME_TYPES = {
7022
- ".html": "text/html",
7023
- ".js": "application/javascript",
7024
- ".css": "text/css",
7025
- ".json": "application/json",
7026
- ".svg": "image/svg+xml",
7027
- ".png": "image/png",
7028
- ".jpg": "image/jpeg",
7029
- ".jpeg": "image/jpeg",
7030
- ".gif": "image/gif",
7031
- ".ico": "image/x-icon",
7032
- ".woff": "font/woff",
7033
- ".woff2": "font/woff2",
7034
- ".txt": "text/plain",
7035
- ".xml": "application/xml",
7036
- ".md": "text/markdown",
7037
- ".webp": "image/webp"
7038
- };
7039
- async function listDir(dirPath) {
7040
- let entries;
7041
- try {
7042
- entries = await readdir(dirPath, { withFileTypes: true });
7043
- } catch (err) {
7044
- if (err?.code === "ENOENT") return [];
7045
- throw err;
7046
- }
7047
- return entries.filter((e) => !e.name.startsWith(".")).map((e) => ({
7048
- name: e.name,
7049
- type: e.isDirectory() ? "directory" : "file"
7050
- }));
7051
- }
7052
- var app15 = new Hono17().get("/:name/", async (c) => {
7053
- const name = c.req.param("name");
7054
- const publicRoot = await resolvePublicRoot(name);
7055
- if (!publicRoot) return c.json({ error: "Not found" }, 404);
7056
- return c.json(await listDir(publicRoot));
7057
- }).get("/:name/*", async (c) => {
7058
- const name = c.req.param("name");
7059
- const publicRoot = await resolvePublicRoot(name);
7060
- if (!publicRoot) return c.text("Not found", 404);
7061
- const wildcard = c.req.path.replace(`/public/${name}`, "") || "/";
7062
- const relativePath = wildcard.slice(1);
7063
- const requestedPath = resolve13(publicRoot, relativePath);
7064
- if (!requestedPath.startsWith(publicRoot)) return c.text("Forbidden", 403);
7065
- if (hasDotSegment(relativePath)) return c.text("Forbidden", 403);
7066
- let fileStat;
7067
- try {
7068
- fileStat = await stat2(requestedPath);
7069
- } catch (err) {
7070
- if (err?.code === "ENOENT") return c.text("Not found", 404);
7071
- if (err?.code === "EACCES") return c.text("Forbidden", 403);
7072
- return c.text("Internal server error", 500);
7073
- }
7074
- if (fileStat.isDirectory()) {
7075
- if (wildcard.endsWith("/")) {
7076
- return c.json(await listDir(requestedPath));
7077
- }
7078
- return c.text("Not found", 404);
7079
- }
7080
- if (fileStat.isFile()) {
7081
- if (fileStat.size > MAX_FILE_SIZE) return c.text("File too large", 413);
7082
- const ext = extname3(requestedPath);
7083
- const mime = MIME_TYPES[ext] || "application/octet-stream";
7084
- try {
7085
- const body = await readFile2(requestedPath);
7086
- return c.body(body, 200, { "Content-Type": mime });
7087
- } catch (err) {
7088
- if (err?.code === "ENOENT") return c.text("Not found", 404);
7089
- if (err?.code === "EACCES") return c.text("Forbidden", 403);
7090
- return c.text("Failed to read file", 500);
7091
- }
7092
- }
7093
- return c.text("Not found", 404);
7094
- });
7095
- var public_files_default = app15;
7096
-
7097
- // src/web/api/schedules.ts
6186
+ // packages/daemon/src/web/api/schedules.ts
7098
6187
  import { CronExpressionParser } from "cron-parser";
7099
- import { Hono as Hono18 } from "hono";
6188
+ import { Hono as Hono17 } from "hono";
7100
6189
  var slog2 = logger_default.child("schedules");
7101
6190
  function readSchedules(name) {
7102
6191
  return readVoluteConfig(mindDir(name))?.schedules ?? [];
@@ -7114,7 +6203,7 @@ function writeSchedules(name, schedules) {
7114
6203
  data: { schedules }
7115
6204
  });
7116
6205
  }
7117
- var app16 = new Hono18().get("/:name/clock/status", async (c) => {
6206
+ var app15 = new Hono17().get("/:name/clock/status", async (c) => {
7118
6207
  const name = c.req.param("name");
7119
6208
  if (!await findMind(name)) return c.json({ error: "Mind not found" }, 404);
7120
6209
  const sleepManager = getSleepManagerIfReady();
@@ -7329,7 +6418,7 @@ var app16 = new Hono18().get("/:name/clock/status", async (c) => {
7329
6418
  const body = await c.req.text();
7330
6419
  const message = `[webhook: ${event}] ${body}`;
7331
6420
  try {
7332
- const { sendSystemMessage } = await import("./system-chat-TYLOL7SX.js");
6421
+ const { sendSystemMessage } = await import("./system-chat-IDPHYHY4.js");
7333
6422
  await sendSystemMessage(name, message);
7334
6423
  return c.json({ ok: true });
7335
6424
  } catch (err) {
@@ -7337,21 +6426,21 @@ var app16 = new Hono18().get("/:name/clock/status", async (c) => {
7337
6426
  return c.json({ error: "Failed to reach mind" }, 502);
7338
6427
  }
7339
6428
  });
7340
- var schedules_default = app16;
6429
+ var schedules_default = app15;
7341
6430
 
7342
- // src/web/api/setup.ts
7343
- import { mkdirSync as mkdirSync8 } from "fs";
6431
+ // packages/daemon/src/web/api/setup.ts
6432
+ import { mkdirSync as mkdirSync7 } from "fs";
7344
6433
  import { homedir as homedir2 } from "os";
7345
- import { resolve as resolve14 } from "path";
7346
- import { Hono as Hono19 } from "hono";
6434
+ import { resolve as resolve12 } from "path";
6435
+ import { Hono as Hono18 } from "hono";
7347
6436
  import { setCookie as setCookie2 } from "hono/cookie";
7348
6437
  var DEFAULT_API_URL2 = "https://volute.systems";
7349
- var setup = new Hono19();
6438
+ var setup = new Hono18();
7350
6439
  function writeSetupConfig(systemName, description) {
7351
- const configHome = process.env.VOLUTE_HOME ?? resolve14(homedir2(), ".volute");
7352
- const mindsDir = resolve14(configHome, "minds");
7353
- mkdirSync8(configHome, { recursive: true });
7354
- mkdirSync8(mindsDir, { recursive: true });
6440
+ const configHome = process.env.VOLUTE_HOME ?? resolve12(homedir2(), ".volute");
6441
+ const mindsDir = resolve12(configHome, "minds");
6442
+ mkdirSync7(configHome, { recursive: true });
6443
+ mkdirSync7(mindsDir, { recursive: true });
7355
6444
  const existingConfig = readGlobalConfig();
7356
6445
  const setupConfig = {
7357
6446
  type: "local",
@@ -7382,7 +6471,7 @@ setup.get("/status", async (c) => {
7382
6471
  let hasAccount = false;
7383
6472
  if (hasSystem) {
7384
6473
  try {
7385
- const { listUsersByType: listUsersByType2 } = await import("./auth-ZFZXJZDQ.js");
6474
+ const { listUsersByType: listUsersByType2 } = await import("./auth-WX4TESEI.js");
7386
6475
  const brains = await listUsersByType2("brain");
7387
6476
  hasAccount = brains.length > 0;
7388
6477
  } catch (err) {
@@ -7431,7 +6520,11 @@ setup.post("/system", async (c) => {
7431
6520
  return c.json({ error: "System name is required" }, 400);
7432
6521
  }
7433
6522
  try {
7434
- writeSetupConfig(body.name.trim(), body.description?.trim());
6523
+ const config2 = writeSetupConfig(body.name.trim(), body.description?.trim());
6524
+ if (body.remote) {
6525
+ config2.hostname = "0.0.0.0";
6526
+ writeGlobalConfig(config2);
6527
+ }
7435
6528
  return c.json({ ok: true });
7436
6529
  } catch (err) {
7437
6530
  return c.json({ error: `Failed to write configuration: ${err.message}` }, 500);
@@ -7567,7 +6660,7 @@ setup.post("/account", async (c) => {
7567
6660
  }
7568
6661
  }
7569
6662
  try {
7570
- const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-ZFZXJZDQ.js");
6663
+ const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-WX4TESEI.js");
7571
6664
  const user = await createUser2(body.username.trim(), body.password);
7572
6665
  if (body.displayName?.trim()) {
7573
6666
  await updateUserProfile2(user.id, { display_name: body.displayName.trim() });
@@ -7613,7 +6706,7 @@ setup.post("/models", async (c) => {
7613
6706
  return c.json({ error: "Spirit model is required" }, 400);
7614
6707
  }
7615
6708
  try {
7616
- const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-PSILB5WD.js");
6709
+ const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-LURBEDDB.js");
7617
6710
  setEnabledModels3(body.models);
7618
6711
  const config2 = readGlobalConfig();
7619
6712
  config2.spiritModel = body.spiritModel.trim();
@@ -7631,8 +6724,8 @@ setup.post("/complete", async (c) => {
7631
6724
  return c.json({ error: "Setup already complete" }, 400);
7632
6725
  }
7633
6726
  try {
7634
- const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-4JP4TY4C.js");
7635
- const { startSpiritFull } = await import("./mind-service-VIKZJK2M.js");
6727
+ const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-ZFRDXMG7.js");
6728
+ const { startSpiritFull } = await import("./mind-service-X2CAA6W6.js");
7636
6729
  await ensureSpiritProject();
7637
6730
  await syncSpiritTemplate();
7638
6731
  const warnings = [];
@@ -7648,8 +6741,8 @@ setup.post("/complete", async (c) => {
7648
6741
  }
7649
6742
  let spiritConversationId;
7650
6743
  try {
7651
- const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-ZFZXJZDQ.js");
7652
- const { createConversation: createConversation6, findDMConversation: findDMConversation2 } = await import("./conversations-HL2JP5GI.js");
6744
+ const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-WX4TESEI.js");
6745
+ const { createConversation: createConversation6, findDMConversation: findDMConversation2 } = await import("./conversations-2PW57WO2.js");
7653
6746
  const spiritUser = await getOrCreateMindUser2("volute");
7654
6747
  const brains = await listUsersByType2("brain");
7655
6748
  const admin2 = brains.find((u) => u.role === "admin");
@@ -7672,8 +6765,8 @@ setup.post("/complete", async (c) => {
7672
6765
  logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
7673
6766
  if (spiritConversationId && spiritStarted) {
7674
6767
  try {
7675
- const { deliverMessage: deliverMessage2 } = await import("./message-delivery-V3R6NXJP.js");
7676
- const { listUsersByType: listUsers6 } = await import("./auth-ZFZXJZDQ.js");
6768
+ const { deliverMessage: deliverMessage2 } = await import("./message-delivery-GRC4W6P7.js");
6769
+ const { listUsersByType: listUsers6 } = await import("./auth-WX4TESEI.js");
7677
6770
  const admins = await listUsers6("brain");
7678
6771
  const admin2 = admins.find((u) => u.role === "admin");
7679
6772
  const adminName = admin2?.display_name || admin2?.username || "the admin";
@@ -7709,35 +6802,13 @@ setup.post("/complete", async (c) => {
7709
6802
  });
7710
6803
  var setup_default = setup;
7711
6804
 
7712
- // src/web/api/shared.ts
7713
- import { Hono as Hono20 } from "hono";
7714
- var app17 = new Hono20().post("/:name/shared/merge", requireAdmin, async (c) => {
7715
- const name = c.req.param("name");
7716
- const entry = await findMind(name);
7717
- if (!entry) return c.json({ error: "Mind not found" }, 404);
7718
- let body;
7719
- try {
7720
- body = await c.req.json();
7721
- } catch {
7722
- return c.json({ error: "Invalid JSON in request body" }, 400);
7723
- }
7724
- const message = body.message || `shared: merge from ${name}`;
7725
- try {
7726
- const result = await sharedMerge(name, mindDir(name), message);
7727
- return c.json(result);
7728
- } catch (err) {
7729
- return c.json({ error: err instanceof Error ? err.message : "Merge failed" }, 500);
7730
- }
7731
- });
7732
- var shared_default = app17;
7733
-
7734
- // src/web/api/skills.ts
7735
- import { existsSync as existsSync10, mkdtempSync, readdirSync as readdirSync3, rmSync as rmSync6 } from "fs";
6805
+ // packages/daemon/src/web/api/skills.ts
6806
+ import { existsSync as existsSync9, mkdtempSync, readdirSync as readdirSync3, rmSync as rmSync5 } from "fs";
7736
6807
  import { tmpdir } from "os";
7737
- import { join, resolve as resolve15 } from "path";
6808
+ import { join, resolve as resolve13 } from "path";
7738
6809
  import AdmZip from "adm-zip";
7739
- import { Hono as Hono21 } from "hono";
7740
- var app18 = new Hono21().get("/", async (c) => {
6810
+ import { Hono as Hono19 } from "hono";
6811
+ var app16 = new Hono19().get("/", async (c) => {
7741
6812
  const skills = await listSharedSkills();
7742
6813
  return c.json(skills);
7743
6814
  }).get("/defaults/list", async (c) => {
@@ -7810,19 +6881,19 @@ var app18 = new Hono21().get("/", async (c) => {
7810
6881
  try {
7811
6882
  const zip = new AdmZip(buffer2);
7812
6883
  for (const entry of zip.getEntries()) {
7813
- const target = resolve15(tmpDir, entry.entryName);
6884
+ const target = resolve13(tmpDir, entry.entryName);
7814
6885
  if (!target.startsWith(tmpDir)) {
7815
6886
  return c.json({ error: "Invalid zip: paths must not escape archive" }, 400);
7816
6887
  }
7817
6888
  }
7818
6889
  zip.extractAllTo(tmpDir, true);
7819
6890
  let skillDir = null;
7820
- if (existsSync10(join(tmpDir, "SKILL.md"))) {
6891
+ if (existsSync9(join(tmpDir, "SKILL.md"))) {
7821
6892
  skillDir = tmpDir;
7822
6893
  } else {
7823
6894
  const entries = readdirSync3(tmpDir, { withFileTypes: true }).filter((e) => e.isDirectory());
7824
6895
  for (const entry of entries) {
7825
- if (existsSync10(join(tmpDir, entry.name, "SKILL.md"))) {
6896
+ if (existsSync9(join(tmpDir, entry.name, "SKILL.md"))) {
7826
6897
  skillDir = join(tmpDir, entry.name);
7827
6898
  break;
7828
6899
  }
@@ -7839,7 +6910,7 @@ var app18 = new Hono21().get("/", async (c) => {
7839
6910
  }
7840
6911
  throw e;
7841
6912
  } finally {
7842
- rmSync6(tmpDir, { recursive: true, force: true });
6913
+ rmSync5(tmpDir, { recursive: true, force: true });
7843
6914
  }
7844
6915
  }).get("/:id", async (c) => {
7845
6916
  const id = c.req.param("id");
@@ -7858,18 +6929,18 @@ var app18 = new Hono21().get("/", async (c) => {
7858
6929
  }
7859
6930
  return c.json({ ok: true });
7860
6931
  });
7861
- var skills_default = app18;
6932
+ var skills_default = app16;
7862
6933
 
7863
- // src/web/api/typing.ts
6934
+ // packages/daemon/src/web/api/typing.ts
7864
6935
  import { zValidator as zValidator7 } from "@hono/zod-validator";
7865
- import { Hono as Hono22 } from "hono";
6936
+ import { Hono as Hono20 } from "hono";
7866
6937
  import { z as z7 } from "zod";
7867
6938
  var typingSchema = z7.object({
7868
6939
  channel: z7.string().min(1),
7869
6940
  sender: z7.string().min(1),
7870
6941
  active: z7.boolean()
7871
6942
  });
7872
- var app19 = new Hono22().post("/:name/typing", zValidator7("json", typingSchema), (c) => {
6943
+ var app17 = new Hono20().post("/:name/typing", zValidator7("json", typingSchema), (c) => {
7873
6944
  const { channel, sender, active } = c.req.valid("json");
7874
6945
  const map = getTypingMap();
7875
6946
  if (active) {
@@ -7889,13 +6960,13 @@ var app19 = new Hono22().post("/:name/typing", zValidator7("json", typingSchema)
7889
6960
  const map = getTypingMap();
7890
6961
  return c.json({ typing: map.get(channel) });
7891
6962
  });
7892
- var typing_default = app19;
6963
+ var typing_default = app17;
7893
6964
 
7894
- // src/web/api/update.ts
6965
+ // packages/daemon/src/web/api/update.ts
7895
6966
  import { spawn as spawn3 } from "child_process";
7896
- import { Hono as Hono23 } from "hono";
6967
+ import { Hono as Hono21 } from "hono";
7897
6968
  var bin;
7898
- var app20 = new Hono23().get("/update", async (c) => {
6969
+ var app18 = new Hono21().get("/update", async (c) => {
7899
6970
  const result = await checkForUpdate();
7900
6971
  return c.json(result);
7901
6972
  }).post("/update", requireAdmin, async (c) => {
@@ -7910,17 +6981,17 @@ var app20 = new Hono23().get("/update", async (c) => {
7910
6981
  child.unref();
7911
6982
  return c.json({ ok: true, message: "Updating..." });
7912
6983
  });
7913
- var update_default = app20;
6984
+ var update_default = app18;
7914
6985
 
7915
- // src/web/api/v1/conversations.ts
6986
+ // packages/daemon/src/web/api/v1/conversations.ts
7916
6987
  import { zValidator as zValidator8 } from "@hono/zod-validator";
7917
- import { Hono as Hono24 } from "hono";
6988
+ import { Hono as Hono22 } from "hono";
7918
6989
  import { z as z8 } from "zod";
7919
6990
  var createSchema = z8.object({
7920
6991
  title: z8.string().optional(),
7921
6992
  participantNames: z8.array(z8.string()).min(1)
7922
6993
  });
7923
- var app21 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
6994
+ var app19 = new Hono22().use("*", authMiddleware).get("/", async (c) => {
7924
6995
  const user = c.get("user");
7925
6996
  const convs = await listConversationsWithParticipants(user.id);
7926
6997
  return c.json(convs);
@@ -8005,14 +7076,14 @@ var app21 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
8005
7076
  if (!deleted) return c.json({ error: "Conversation not found" }, 404);
8006
7077
  return c.json({ ok: true });
8007
7078
  });
8008
- var conversations_default = app21;
7079
+ var conversations_default = app19;
8009
7080
 
8010
- // src/web/api/v1/events.ts
8011
- import { desc as desc5 } from "drizzle-orm";
8012
- import { Hono as Hono25 } from "hono";
7081
+ // packages/daemon/src/web/api/v1/events.ts
7082
+ import { desc as desc4 } from "drizzle-orm";
7083
+ import { Hono as Hono23 } from "hono";
8013
7084
  import { streamSSE as streamSSE4 } from "hono/streaming";
8014
7085
 
8015
- // src/lib/events/brain-presence.ts
7086
+ // packages/daemon/src/lib/events/brain-presence.ts
8016
7087
  var connections = /* @__PURE__ */ new Map();
8017
7088
  function addConnection(username) {
8018
7089
  const count = connections.get(username) ?? 0;
@@ -8035,7 +7106,7 @@ function getOnlineBrains() {
8035
7106
  return [...connections.keys()];
8036
7107
  }
8037
7108
 
8038
- // src/lib/events/event-sequencer.ts
7109
+ // packages/daemon/src/lib/events/event-sequencer.ts
8039
7110
  var BUFFER_SIZE = 1e3;
8040
7111
  var MAX_AGE_MS = 5 * 60 * 1e3;
8041
7112
  var nextId = 1;
@@ -8055,8 +7126,8 @@ function getEventsSince(sinceId) {
8055
7126
  return buffer.slice(startIdx).filter((e) => now - e.timestamp < MAX_AGE_MS);
8056
7127
  }
8057
7128
 
8058
- // src/web/api/v1/events.ts
8059
- var app22 = new Hono25().use("*", authMiddleware).get("/", async (c) => {
7129
+ // packages/daemon/src/web/api/v1/events.ts
7130
+ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
8060
7131
  const user = c.get("user");
8061
7132
  const since = c.req.query("since");
8062
7133
  const sinceId = since ? Number(since) : 0;
@@ -8079,7 +7150,7 @@ var app22 = new Hono25().use("*", authMiddleware).get("/", async (c) => {
8079
7150
  let recentActivity = [];
8080
7151
  try {
8081
7152
  const db = await getDb();
8082
- recentActivity = await db.select().from(activity).orderBy(desc5(activity.created_at)).limit(50);
7153
+ recentActivity = await db.select().from(activity).orderBy(desc4(activity.created_at)).limit(50);
8083
7154
  recentActivity = recentActivity.map((row) => ({
8084
7155
  ...row,
8085
7156
  metadata: row.metadata ? JSON.parse(row.metadata) : null
@@ -8146,8 +7217,8 @@ var app22 = new Hono25().use("*", authMiddleware).get("/", async (c) => {
8146
7217
  });
8147
7218
  }, 15e3);
8148
7219
  cleanups.push(() => clearInterval(keepAlive));
8149
- await new Promise((resolve20) => {
8150
- stream.onAbort(() => resolve20());
7220
+ await new Promise((resolve18) => {
7221
+ stream.onAbort(() => resolve18());
8151
7222
  });
8152
7223
  } finally {
8153
7224
  for (const cleanup of cleanups) {
@@ -8159,19 +7230,19 @@ var app22 = new Hono25().use("*", authMiddleware).get("/", async (c) => {
8159
7230
  }
8160
7231
  });
8161
7232
  });
8162
- var events_default = app22;
7233
+ var events_default = app20;
8163
7234
 
8164
- // src/web/api/variants.ts
8165
- import { existsSync as existsSync11, mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "fs";
8166
- import { resolve as resolve17 } from "path";
8167
- import { Hono as Hono26 } from "hono";
7235
+ // packages/daemon/src/web/api/variants.ts
7236
+ import { existsSync as existsSync10, mkdirSync as mkdirSync9, writeFileSync as writeFileSync8 } from "fs";
7237
+ import { resolve as resolve15 } from "path";
7238
+ import { Hono as Hono24 } from "hono";
8168
7239
 
8169
- // src/lib/spawn-server.ts
7240
+ // packages/daemon/src/lib/spawn-server.ts
8170
7241
  import { spawn as spawn4 } from "child_process";
8171
- import { closeSync, mkdirSync as mkdirSync9, openSync, readFileSync as readFileSync11 } from "fs";
8172
- import { resolve as resolve16 } from "path";
7242
+ import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync10 } from "fs";
7243
+ import { resolve as resolve14 } from "path";
8173
7244
  function tsxBin(cwd) {
8174
- return resolve16(cwd, "node_modules", ".bin", "tsx");
7245
+ return resolve14(cwd, "node_modules", ".bin", "tsx");
8175
7246
  }
8176
7247
  function spawnServer(cwd, port, options) {
8177
7248
  if (options?.detached) {
@@ -8184,31 +7255,31 @@ function spawnAttached(cwd, port) {
8184
7255
  cwd,
8185
7256
  stdio: ["ignore", "pipe", "pipe"]
8186
7257
  });
8187
- return new Promise((resolve20) => {
8188
- const timeout = setTimeout(() => resolve20(null), 3e4);
7258
+ return new Promise((resolve18) => {
7259
+ const timeout = setTimeout(() => resolve18(null), 3e4);
8189
7260
  function checkOutput(data) {
8190
7261
  const match = data.toString().match(/listening on :(\d+)/);
8191
7262
  if (match) {
8192
7263
  clearTimeout(timeout);
8193
- resolve20({ child, actualPort: parseInt(match[1], 10) });
7264
+ resolve18({ child, actualPort: parseInt(match[1], 10) });
8194
7265
  }
8195
7266
  }
8196
7267
  child.stdout?.on("data", checkOutput);
8197
7268
  child.stderr?.on("data", checkOutput);
8198
7269
  child.on("error", () => {
8199
7270
  clearTimeout(timeout);
8200
- resolve20(null);
7271
+ resolve18(null);
8201
7272
  });
8202
7273
  child.on("exit", () => {
8203
7274
  clearTimeout(timeout);
8204
- resolve20(null);
7275
+ resolve18(null);
8205
7276
  });
8206
7277
  });
8207
7278
  }
8208
7279
  function spawnDetached(cwd, port, logDir) {
8209
- const logsDir = logDir ?? resolve16(cwd, ".mind", "logs");
8210
- mkdirSync9(logsDir, { recursive: true });
8211
- const logPath = resolve16(logsDir, "mind.log");
7280
+ const logsDir = logDir ?? resolve14(cwd, ".mind", "logs");
7281
+ mkdirSync8(logsDir, { recursive: true });
7282
+ const logPath = resolve14(logsDir, "mind.log");
8212
7283
  const logFd = openSync(logPath, "a");
8213
7284
  const child = spawn4(tsxBin(cwd), ["src/server.ts", "--port", String(port)], {
8214
7285
  cwd,
@@ -8228,7 +7299,7 @@ function spawnDetached(cwd, port, logDir) {
8228
7299
  }
8229
7300
  const interval = setInterval(() => {
8230
7301
  try {
8231
- const content = readFileSync11(logPath, "utf-8");
7302
+ const content = readFileSync10(logPath, "utf-8");
8232
7303
  const match = content.match(/listening on :(\d+)/);
8233
7304
  if (match) {
8234
7305
  finish({ child, actualPort: parseInt(match[1], 10) });
@@ -8242,7 +7313,7 @@ function spawnDetached(cwd, port, logDir) {
8242
7313
  });
8243
7314
  }
8244
7315
 
8245
- // src/lib/verify.ts
7316
+ // packages/daemon/src/lib/verify.ts
8246
7317
  async function verify2(port) {
8247
7318
  const health = await checkHealth(port);
8248
7319
  if (!health.ok) {
@@ -8279,8 +7350,8 @@ async function verify2(port) {
8279
7350
  }
8280
7351
  }
8281
7352
 
8282
- // src/web/api/variants.ts
8283
- var app23 = new Hono26().get("/:name/variants", async (c) => {
7353
+ // packages/daemon/src/web/api/variants.ts
7354
+ var app21 = new Hono24().get("/:name/variants", async (c) => {
8284
7355
  const name = c.req.param("name");
8285
7356
  const entry = await findMind(name);
8286
7357
  if (!entry) return c.json({ error: "Mind not found" }, 404);
@@ -8324,11 +7395,11 @@ var app23 = new Hono26().get("/:name/variants", async (c) => {
8324
7395
  return c.json({ error: `Name already in use: ${variantName}` }, 409);
8325
7396
  }
8326
7397
  const projectRoot = mindDir(mindName);
8327
- const variantDir = resolve17(projectRoot, ".variants", variantName);
8328
- if (existsSync11(variantDir)) {
7398
+ const variantDir = resolve15(projectRoot, ".variants", variantName);
7399
+ if (existsSync10(variantDir)) {
8329
7400
  return c.json({ error: `Variant directory already exists: ${variantDir}` }, 409);
8330
7401
  }
8331
- mkdirSync10(resolve17(projectRoot, ".variants"), { recursive: true });
7402
+ mkdirSync9(resolve15(projectRoot, ".variants"), { recursive: true });
8332
7403
  try {
8333
7404
  await gitExec(["worktree", "add", "-b", variantName, variantDir], { cwd: projectRoot });
8334
7405
  } catch (e) {
@@ -8341,7 +7412,7 @@ var app23 = new Hono26().get("/:name/variants", async (c) => {
8341
7412
  const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
8342
7413
  await exec(cmd, args, {
8343
7414
  cwd: variantDir,
8344
- env: { ...process.env, HOME: resolve17(variantDir, "home") }
7415
+ env: { ...process.env, HOME: resolve15(variantDir, "home") }
8345
7416
  });
8346
7417
  } else {
8347
7418
  await exec("npm", ["install"], { cwd: variantDir });
@@ -8351,7 +7422,7 @@ var app23 = new Hono26().get("/:name/variants", async (c) => {
8351
7422
  return c.json({ error: `npm install failed: ${msg}` }, 500);
8352
7423
  }
8353
7424
  if (body.soul) {
8354
- writeFileSync9(resolve17(variantDir, "home/SOUL.md"), body.soul);
7425
+ writeFileSync8(resolve15(variantDir, "home/SOUL.md"), body.soul);
8355
7426
  }
8356
7427
  const variantPort = body.port ?? await nextPort();
8357
7428
  await addVariant(variantName, mindName, variantPort, variantDir, variantName);
@@ -8386,7 +7457,7 @@ var app23 = new Hono26().get("/:name/variants", async (c) => {
8386
7457
  } catch {
8387
7458
  }
8388
7459
  const projectRoot = mindDir(mindName);
8389
- if (existsSync11(variantEntry.dir)) {
7460
+ if (existsSync10(variantEntry.dir)) {
8390
7461
  const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
8391
7462
  if (status) {
8392
7463
  try {
@@ -8446,8 +7517,8 @@ var app23 = new Hono26().get("/:name/variants", async (c) => {
8446
7517
  await cleanupVariant(variantName, projectRoot, variantEntry.dir);
8447
7518
  if (variantName.endsWith("-upgrade") || variantName === "upgrade") {
8448
7519
  try {
8449
- const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-EJRTKE36.js");
8450
- const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-UYV5S6QT.js");
7520
+ const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-A7FNHTB7.js");
7521
+ const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-GBSNW3HG.js");
8451
7522
  const tmpl = parentEntry.template ?? "claude";
8452
7523
  await setMindTemplateHash2(mindName, computeTemplateHash2(tmpl));
8453
7524
  } catch (err) {
@@ -8460,7 +7531,7 @@ var app23 = new Hono26().get("/:name/variants", async (c) => {
8460
7531
  const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
8461
7532
  await exec(cmd, args, {
8462
7533
  cwd: projectRoot,
8463
- env: { ...process.env, HOME: resolve17(projectRoot, "home") }
7534
+ env: { ...process.env, HOME: resolve15(projectRoot, "home") }
8464
7535
  });
8465
7536
  } else {
8466
7537
  await exec("npm", ["install"], { cwd: projectRoot });
@@ -8502,11 +7573,11 @@ var app23 = new Hono26().get("/:name/variants", async (c) => {
8502
7573
  await cleanupVariant(variantName, projectRoot, variantEntry.dir, { stop: true });
8503
7574
  return c.json({ ok: true });
8504
7575
  });
8505
- var variants_default = app23;
7576
+ var variants_default = app21;
8506
7577
 
8507
- // src/web/api/volute/channels.ts
7578
+ // packages/daemon/src/web/api/volute/channels.ts
8508
7579
  import { zValidator as zValidator9 } from "@hono/zod-validator";
8509
- import { Hono as Hono27 } from "hono";
7580
+ import { Hono as Hono25 } from "hono";
8510
7581
  import { z as z9 } from "zod";
8511
7582
  var createSchema2 = z9.object({
8512
7583
  name: z9.string().min(1).max(50).regex(/^[a-z0-9][a-z0-9-]*$/, "Channel names must be lowercase alphanumeric with hyphens")
@@ -8514,7 +7585,7 @@ var createSchema2 = z9.object({
8514
7585
  var inviteSchema = z9.object({
8515
7586
  username: z9.string().min(1)
8516
7587
  });
8517
- var app24 = new Hono27().get("/", async (c) => {
7588
+ var app22 = new Hono25().get("/", async (c) => {
8518
7589
  const user = c.get("user");
8519
7590
  const channels = await listChannels();
8520
7591
  const results = await Promise.all(
@@ -8584,15 +7655,15 @@ var app24 = new Hono27().get("/", async (c) => {
8584
7655
  ]);
8585
7656
  return c.json({ ok: true });
8586
7657
  });
8587
- var channels_default2 = app24;
7658
+ var channels_default2 = app22;
8588
7659
 
8589
- // src/web/api/volute/chat.ts
7660
+ // packages/daemon/src/web/api/volute/chat.ts
8590
7661
  import { zValidator as zValidator10 } from "@hono/zod-validator";
8591
- import { Hono as Hono28 } from "hono";
7662
+ import { Hono as Hono26 } from "hono";
8592
7663
  import { streamSSE as streamSSE5 } from "hono/streaming";
8593
7664
  import { z as z10 } from "zod";
8594
7665
 
8595
- // src/lib/bridge-outbound.ts
7666
+ // packages/daemon/src/lib/bridge-outbound.ts
8596
7667
  function extractContent(contentBlocks) {
8597
7668
  const text = contentBlocks.filter((b) => b.type === "text").map((b) => b.text).join("\n");
8598
7669
  const images = contentBlocks.filter((b) => b.type === "image").map((b) => ({ media_type: b.media_type, data: b.data }));
@@ -8663,7 +7734,7 @@ async function routeDMOutbound(conversationId, senderName, contentBlocks) {
8663
7734
  }
8664
7735
  }
8665
7736
 
8666
- // src/web/api/volute/chat.ts
7737
+ // packages/daemon/src/web/api/volute/chat.ts
8667
7738
  async function fanOutToMinds(opts) {
8668
7739
  const participants = await getParticipants(opts.conversationId);
8669
7740
  const mindParticipants = participants.filter(
@@ -8671,8 +7742,8 @@ async function fanOutToMinds(opts) {
8671
7742
  );
8672
7743
  const participantNames = participants.map((p) => p.username);
8673
7744
  const isDM = opts.isDM ?? participants.length === 2;
8674
- const { getMindManager: getMindManager2 } = await import("./mind-manager-MWW3BTS4.js");
8675
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BJK2ROPX.js");
7745
+ const { getMindManager: getMindManager2 } = await import("./mind-manager-HFLB5653.js");
7746
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-7KFK3USC.js");
8676
7747
  const manager = getMindManager2();
8677
7748
  const sm = getSleepManagerIfReady2();
8678
7749
  const targetMinds = mindParticipants.map((ap) => {
@@ -8752,7 +7823,7 @@ function stageFilesForMinds(files, targetMinds, senderName) {
8752
7823
  }
8753
7824
  return { notifications };
8754
7825
  }
8755
- var unifiedChatApp = new Hono28().post(
7826
+ var unifiedChatApp = new Hono26().post(
8756
7827
  "/chat",
8757
7828
  zValidator10("json", chatSchema),
8758
7829
  async (c) => {
@@ -8890,7 +7961,7 @@ var unifiedChatApp = new Hono28().post(
8890
7961
  return c.json({ ok: true, conversationId, outboundId });
8891
7962
  }
8892
7963
  );
8893
- var app25 = new Hono28().get("/:name/conversations/:id/events", async (c) => {
7964
+ var app23 = new Hono26().get("/:name/conversations/:id/events", async (c) => {
8894
7965
  const conversationId = c.req.param("id");
8895
7966
  const user = c.get("user");
8896
7967
  if (user.id !== 0 && !await isParticipantOrOwner(conversationId, user.id)) {
@@ -8907,27 +7978,27 @@ var app25 = new Hono28().get("/:name/conversations/:id/events", async (c) => {
8907
7978
  if (!stream.aborted) console.error("[chat] SSE ping error:", err);
8908
7979
  });
8909
7980
  }, 15e3);
8910
- await new Promise((resolve20) => {
7981
+ await new Promise((resolve18) => {
8911
7982
  stream.onAbort(() => {
8912
7983
  unsubscribe();
8913
7984
  clearInterval(keepAlive);
8914
- resolve20();
7985
+ resolve18();
8915
7986
  });
8916
7987
  });
8917
7988
  });
8918
7989
  });
8919
- var chat_default = app25;
7990
+ var chat_default = app23;
8920
7991
 
8921
- // src/web/api/volute/conversations.ts
7992
+ // packages/daemon/src/web/api/volute/conversations.ts
8922
7993
  import { zValidator as zValidator11 } from "@hono/zod-validator";
8923
- import { Hono as Hono29 } from "hono";
7994
+ import { Hono as Hono27 } from "hono";
8924
7995
  import { z as z11 } from "zod";
8925
7996
  var createConvSchema = z11.object({
8926
7997
  title: z11.string().optional(),
8927
7998
  participantIds: z11.array(z11.number()).optional(),
8928
7999
  participantNames: z11.array(z11.string()).optional()
8929
8000
  });
8930
- var app26 = new Hono29().get("/:name/conversations", async (c) => {
8001
+ var app24 = new Hono27().get("/:name/conversations", async (c) => {
8931
8002
  const name = c.req.param("name");
8932
8003
  const user = c.get("user");
8933
8004
  let lookupId = user.id;
@@ -9035,12 +8106,12 @@ var app26 = new Hono29().get("/:name/conversations", async (c) => {
9035
8106
  if (!deleted) return c.json({ error: "Conversation not found" }, 404);
9036
8107
  return c.json({ ok: true });
9037
8108
  });
9038
- var conversations_default2 = app26;
8109
+ var conversations_default2 = app24;
9039
8110
 
9040
- // src/web/app.ts
8111
+ // packages/daemon/src/web/app.ts
9041
8112
  var httpLog = logger_default.child("http");
9042
- var app27 = new Hono30();
9043
- app27.onError((err, c) => {
8113
+ var app25 = new Hono28();
8114
+ app25.onError((err, c) => {
9044
8115
  if (err instanceof HTTPException) {
9045
8116
  return err.getResponse();
9046
8117
  }
@@ -9051,10 +8122,10 @@ app27.onError((err, c) => {
9051
8122
  });
9052
8123
  return c.json({ error: "Internal server error" }, 500);
9053
8124
  });
9054
- app27.notFound((c) => {
8125
+ app25.notFound((c) => {
9055
8126
  return c.json({ error: "Not found" }, 404);
9056
8127
  });
9057
- app27.use("*", async (c, next) => {
8128
+ app25.use("*", async (c, next) => {
9058
8129
  const start = Date.now();
9059
8130
  await next();
9060
8131
  const duration = Date.now() - start;
@@ -9065,7 +8136,22 @@ app27.use("*", async (c, next) => {
9065
8136
  httpLog.debug("request", data);
9066
8137
  }
9067
8138
  });
9068
- app27.get("/api/health", (c) => {
8139
+ app25.use("/api/*", bodyLimit({ maxSize: 10 * 1024 * 1024 }));
8140
+ app25.use(
8141
+ "/api/*",
8142
+ cors({
8143
+ origin: (origin) => origin,
8144
+ allowHeaders: ["Authorization", "Content-Type", "X-Volute-Session"],
8145
+ allowMethods: ["GET", "POST", "PUT", "PATCH", "DELETE"],
8146
+ credentials: false
8147
+ })
8148
+ );
8149
+ app25.use("/api/*", async (c, next) => {
8150
+ const auth = c.req.header("Authorization");
8151
+ if (auth?.startsWith("Bearer ") && auth.length > 7) return next();
8152
+ return csrf()(c, next);
8153
+ });
8154
+ app25.get("/api/health", (c) => {
9069
8155
  let version = "unknown";
9070
8156
  let cached = null;
9071
8157
  try {
@@ -9080,45 +8166,42 @@ app27.get("/api/health", (c) => {
9080
8166
  ...cached?.updateAvailable ? { updateAvailable: true, latest: cached.latest } : {}
9081
8167
  });
9082
8168
  });
9083
- app27.use("/api/*", bodyLimit({ maxSize: 10 * 1024 * 1024 }));
9084
- app27.use("/api/*", csrf());
9085
- app27.use("/api/activity/*", authMiddleware);
9086
- app27.use("/api/minds/*", authMiddleware);
9087
- app27.use("/api/conversations/*", authMiddleware);
9088
- app27.use("/api/system/*", authMiddleware);
9089
- app27.use("/api/env/*", authMiddleware);
9090
- app27.use("/api/prompts/*", authMiddleware);
9091
- app27.use("/api/skills/*", authMiddleware);
9092
- app27.use("/api/extensions/*", authMiddleware);
9093
- app27.use("/api/bridges/*", authMiddleware);
9094
- app27.use("/api/config/*", authMiddleware);
9095
- app27.use("/api/v1/*", authMiddleware);
9096
- app27.route("/api/setup", setup_default);
9097
- app27.route("/public", public_files_default);
9098
- app27.route("/api/config", config_default);
9099
- var routes = app27.route("/api/activity", activity_default).route("/api/keys", keys_default).route("/api/auth", auth_default).route("/api/system", system_default).route("/api/system", update_default).route("/api/minds", minds_default).route("/api/minds", chat_default).route("/api/minds", schedules_default).route("/api/minds", logs_default).route("/api/minds", typing_default).route("/api/minds", variants_default).route("/api/minds", file_sharing_default).route("/api/minds", files_default).route("/api/minds", channels_default).route("/api/minds", shared_default).route("/api/minds", env_default).route("/api/minds", mind_skills_default).route("/api/minds", conversations_default2).route("/api/env", sharedEnvApp).route("/api/prompts", prompts_default).route("/api/skills", skills_default).route("/api/bridges", bridges_default).route("/api/extensions", extensions_default).route("/api/v1/conversations", conversations_default).route("/api/v1/events", events_default).route("/api/v1", unifiedChatApp).route("/api/v1/channels", channels_default2).route("/api/v1/history", history_default);
9100
- app27.route("/api/v1/minds", minds_default);
9101
- app27.route("/api/v1/minds", chat_default);
9102
- app27.route("/api/v1/minds", typing_default);
9103
- app27.route("/api/v1/minds", variants_default);
9104
- app27.route("/api/v1/minds", files_default);
9105
- app27.route("/api/v1/minds", env_default);
9106
- app27.route("/api/v1/minds", mind_skills_default);
9107
- app27.route("/api/v1/minds", schedules_default);
9108
- app27.route("/api/v1/minds", logs_default);
9109
- app27.route("/api/v1/system", system_default);
9110
- app27.route("/api/v1/system", update_default);
9111
- app27.route("/api/v1/prompts", prompts_default);
9112
- app27.route("/api/v1/skills", skills_default);
9113
- app27.route("/api/v1/env", sharedEnvApp);
9114
- app27.route("/api/conversations", conversations_default);
9115
- var app_default = app27;
8169
+ app25.use("/api/activity/*", authMiddleware);
8170
+ app25.use("/api/minds/*", authMiddleware);
8171
+ app25.use("/api/conversations/*", authMiddleware);
8172
+ app25.use("/api/system/*", authMiddleware);
8173
+ app25.use("/api/env/*", authMiddleware);
8174
+ app25.use("/api/prompts/*", authMiddleware);
8175
+ app25.use("/api/skills/*", authMiddleware);
8176
+ app25.use("/api/extensions/*", authMiddleware);
8177
+ app25.use("/api/bridges/*", authMiddleware);
8178
+ app25.use("/api/config/*", authMiddleware);
8179
+ app25.use("/api/v1/*", authMiddleware);
8180
+ app25.route("/api/setup", setup_default);
8181
+ app25.route("/api/config", config_default);
8182
+ var routes = app25.route("/api/activity", activity_default).route("/api/keys", keys_default).route("/api/auth", auth_default).route("/api/system", system_default).route("/api/system", update_default).route("/api/minds", minds_default).route("/api/minds", chat_default).route("/api/minds", schedules_default).route("/api/minds", logs_default).route("/api/minds", typing_default).route("/api/minds", variants_default).route("/api/minds", file_sharing_default).route("/api/minds", files_default).route("/api/minds", channels_default).route("/api/minds", env_default).route("/api/minds", mind_skills_default).route("/api/minds", conversations_default2).route("/api/env", sharedEnvApp).route("/api/prompts", prompts_default).route("/api/skills", skills_default).route("/api/bridges", bridges_default).route("/api/extensions", extensions_default).route("/api/v1/conversations", conversations_default).route("/api/v1/events", events_default).route("/api/v1", unifiedChatApp).route("/api/v1/channels", channels_default2).route("/api/v1/history", history_default);
8183
+ app25.route("/api/v1/minds", minds_default);
8184
+ app25.route("/api/v1/minds", chat_default);
8185
+ app25.route("/api/v1/minds", typing_default);
8186
+ app25.route("/api/v1/minds", variants_default);
8187
+ app25.route("/api/v1/minds", files_default);
8188
+ app25.route("/api/v1/minds", env_default);
8189
+ app25.route("/api/v1/minds", mind_skills_default);
8190
+ app25.route("/api/v1/minds", schedules_default);
8191
+ app25.route("/api/v1/minds", logs_default);
8192
+ app25.route("/api/v1/system", system_default);
8193
+ app25.route("/api/v1/system", update_default);
8194
+ app25.route("/api/v1/prompts", prompts_default);
8195
+ app25.route("/api/v1/skills", skills_default);
8196
+ app25.route("/api/v1/env", sharedEnvApp);
8197
+ app25.route("/api/conversations", conversations_default);
8198
+ var app_default = app25;
9116
8199
 
9117
- // src/web/server.ts
9118
- import { existsSync as existsSync12 } from "fs";
9119
- import { readFile as readFile3, stat as stat3 } from "fs/promises";
8200
+ // packages/daemon/src/web/server.ts
8201
+ import { existsSync as existsSync11 } from "fs";
8202
+ import { readFile as readFile2, stat as stat2 } from "fs/promises";
9120
8203
  import { createServer as createHttpsServer } from "https";
9121
- import { dirname as dirname2, extname as extname4, resolve as resolve18 } from "path";
8204
+ import { dirname as dirname2, extname as extname3, resolve as resolve16 } from "path";
9122
8205
  import { serve } from "@hono/node-server";
9123
8206
  var MIME_TYPES2 = {
9124
8207
  ".html": "text/html",
@@ -9137,8 +8220,8 @@ async function startServer({
9137
8220
  let assetsDir = "";
9138
8221
  let searchDir = dirname2(new URL(import.meta.url).pathname);
9139
8222
  for (let i = 0; i < 5; i++) {
9140
- const candidate = resolve18(searchDir, "dist", "web-assets");
9141
- if (existsSync12(candidate)) {
8223
+ const candidate = resolve16(searchDir, "dist", "web-assets");
8224
+ if (existsSync11(candidate)) {
9142
8225
  assetsDir = candidate;
9143
8226
  break;
9144
8227
  }
@@ -9148,19 +8231,19 @@ async function startServer({
9148
8231
  app_default.get("*", async (c) => {
9149
8232
  const urlPath = new URL(c.req.url).pathname;
9150
8233
  if (urlPath.startsWith("/api/") || urlPath.startsWith("/ext/")) return c.notFound();
9151
- const filePath = resolve18(assetsDir, urlPath.slice(1));
8234
+ const filePath = resolve16(assetsDir, urlPath.slice(1));
9152
8235
  if (!filePath.startsWith(assetsDir)) return c.text("Forbidden", 403);
9153
- const s = await stat3(filePath).catch(() => null);
8236
+ const s = await stat2(filePath).catch(() => null);
9154
8237
  if (s?.isFile()) {
9155
- const ext = extname4(filePath);
8238
+ const ext = extname3(filePath);
9156
8239
  const mime = MIME_TYPES2[ext] || "application/octet-stream";
9157
- const body = await readFile3(filePath);
8240
+ const body = await readFile2(filePath);
9158
8241
  return c.body(body, 200, { "Content-Type": mime });
9159
8242
  }
9160
- const indexPath = resolve18(assetsDir, "index.html");
9161
- const indexStat = await stat3(indexPath).catch(() => null);
8243
+ const indexPath = resolve16(assetsDir, "index.html");
8244
+ const indexStat = await stat2(indexPath).catch(() => null);
9162
8245
  if (indexStat?.isFile()) {
9163
- const body = await readFile3(indexPath, "utf-8");
8246
+ const body = await readFile2(indexPath, "utf-8");
9164
8247
  return c.html(body);
9165
8248
  }
9166
8249
  return c.text("Not found", 404);
@@ -9174,10 +8257,10 @@ async function startServer({
9174
8257
  createServer: createHttpsServer,
9175
8258
  serverOptions: { key: tls.key, cert: tls.cert }
9176
8259
  });
9177
- await new Promise((resolve20, reject) => {
8260
+ await new Promise((resolve18, reject) => {
9178
8261
  server2.on("listening", () => {
9179
8262
  logger_default.info("Volute UI running (https)", { hostname, port });
9180
- resolve20();
8263
+ resolve18();
9181
8264
  });
9182
8265
  server2.on("error", (err) => {
9183
8266
  reject(err);
@@ -9185,13 +8268,13 @@ async function startServer({
9185
8268
  });
9186
8269
  const internalPort = port + 1;
9187
8270
  const internalServer = serve({ fetch: app_default.fetch, port: internalPort, hostname: "127.0.0.1" });
9188
- await new Promise((resolve20, reject) => {
8271
+ await new Promise((resolve18, reject) => {
9189
8272
  internalServer.on("listening", () => {
9190
8273
  logger_default.info("Volute API running (http, internal)", {
9191
8274
  hostname: "127.0.0.1",
9192
8275
  port: internalPort
9193
8276
  });
9194
- resolve20();
8277
+ resolve18();
9195
8278
  });
9196
8279
  internalServer.on("error", (err) => {
9197
8280
  reject(err);
@@ -9200,10 +8283,10 @@ async function startServer({
9200
8283
  return { server: server2, internalPort };
9201
8284
  }
9202
8285
  const server = serve({ fetch: app_default.fetch, port, hostname });
9203
- await new Promise((resolve20, reject) => {
8286
+ await new Promise((resolve18, reject) => {
9204
8287
  server.on("listening", () => {
9205
8288
  logger_default.info("Volute API running (http)", { hostname, port });
9206
- resolve20();
8289
+ resolve18();
9207
8290
  });
9208
8291
  server.on("error", (err) => {
9209
8292
  reject(err);
@@ -9212,9 +8295,9 @@ async function startServer({
9212
8295
  return { server };
9213
8296
  }
9214
8297
 
9215
- // src/daemon.ts
8298
+ // packages/daemon/src/daemon.ts
9216
8299
  if (!process.env.VOLUTE_HOME) {
9217
- process.env.VOLUTE_HOME = resolve19(homedir3(), ".volute");
8300
+ process.env.VOLUTE_HOME = resolve17(homedir3(), ".volute");
9218
8301
  }
9219
8302
  if (process.env.VOLUTE_TIMEZONE && !process.env.TZ) {
9220
8303
  process.env.TZ = process.env.VOLUTE_TIMEZONE;
@@ -9225,7 +8308,7 @@ async function startDaemon(opts) {
9225
8308
  const home = voluteHome();
9226
8309
  const systemDir = voluteSystemDir();
9227
8310
  if (!opts.foreground) {
9228
- const rotatingLog = new RotatingLog(resolve19(systemDir, "daemon.log"));
8311
+ const rotatingLog = new RotatingLog(resolve17(systemDir, "daemon.log"));
9229
8312
  logger_default.setOutput((line) => rotatingLog.write(`${line}
9230
8313
  `));
9231
8314
  const write = (...args) => rotatingLog.write(`${format(...args)}
@@ -9235,27 +8318,22 @@ async function startDaemon(opts) {
9235
8318
  console.warn = write;
9236
8319
  console.info = write;
9237
8320
  }
9238
- const DAEMON_PID_PATH = resolve19(systemDir, "daemon.pid");
9239
- const DAEMON_JSON_PATH = resolve19(systemDir, "daemon.json");
9240
- mkdirSync11(home, { recursive: true });
8321
+ const DAEMON_PID_PATH = resolve17(systemDir, "daemon.pid");
8322
+ const DAEMON_JSON_PATH = resolve17(systemDir, "daemon.json");
8323
+ mkdirSync10(home, { recursive: true });
9241
8324
  ensureSystemDir();
9242
- try {
9243
- await ensureSharedRepo();
9244
- } catch (err) {
9245
- logger_default.warn("failed to initialize shared repo", logger_default.errorData(err));
9246
- }
9247
- const { migrateSetupCompleted } = await import("./setup-GGMKENLN.js");
8325
+ const { migrateSetupCompleted } = await import("./setup-RHJRFURI.js");
9248
8326
  migrateSetupCompleted();
9249
- await (await import("./db-RYX3SS2W.js")).getDb();
8327
+ await (await import("./db-BVBJ57TU.js")).getDb();
9250
8328
  try {
9251
- const { eq: eq8, and: and6 } = await import("drizzle-orm");
9252
- const { users: users2 } = await import("./schema-ETMABTW4.js");
9253
- const db = await (await import("./db-RYX3SS2W.js")).getDb();
9254
- await db.update(users2).set({ role: "system" }).where(and6(eq8(users2.user_type, "system"), eq8(users2.role, "user")));
8329
+ const { eq: eq7, and: and5 } = await import("drizzle-orm");
8330
+ const { users: users2 } = await import("./schema-XVZ2CLKW.js");
8331
+ const db = await (await import("./db-BVBJ57TU.js")).getDb();
8332
+ await db.update(users2).set({ role: "system" }).where(and5(eq7(users2.user_type, "system"), eq7(users2.role, "user")));
9255
8333
  } catch (err) {
9256
8334
  logger_default.warn("failed to migrate system user role", logger_default.errorData(err));
9257
8335
  }
9258
- const { initSandbox } = await import("./sandbox-SI5HMBP3.js");
8336
+ const { initSandbox } = await import("./sandbox-R37VIU36.js");
9259
8337
  await initSandbox();
9260
8338
  try {
9261
8339
  await syncBuiltinSkills();
@@ -9282,7 +8360,7 @@ async function startDaemon(opts) {
9282
8360
  logger_default.warn("failed to ensure #system channel", logger_default.errorData(err));
9283
8361
  }
9284
8362
  try {
9285
- const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-ZFZXJZDQ.js");
8363
+ const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-WX4TESEI.js");
9286
8364
  await getOrCreateSystemUser2();
9287
8365
  } catch (err) {
9288
8366
  logger_default.warn(
@@ -9293,7 +8371,7 @@ async function startDaemon(opts) {
9293
8371
  const token = process.env.VOLUTE_DAEMON_TOKEN || randomBytes(32).toString("hex");
9294
8372
  let tls;
9295
8373
  if (opts.tailscale) {
9296
- const { getTailscaleTls } = await import("./tailscale-ZEUK7GKZ.js");
8374
+ const { getTailscaleTls } = await import("./tailscale-ZIZ2HWJ5.js");
9297
8375
  const tlsConfig = await getTailscaleTls();
9298
8376
  tls = { key: tlsConfig.key, cert: tlsConfig.cert };
9299
8377
  logger_default.info("Tailscale HTTPS enabled", { hostname: tlsConfig.hostname });
@@ -9314,11 +8392,11 @@ async function startDaemon(opts) {
9314
8392
  process.env.VOLUTE_DAEMON_TOKEN = token;
9315
8393
  process.env.VOLUTE_DAEMON_PORT = String(daemonPort);
9316
8394
  process.env.VOLUTE_DAEMON_HOSTNAME = hostname;
9317
- writeFileSync10(DAEMON_PID_PATH, myPid, { mode: 420 });
8395
+ writeFileSync9(DAEMON_PID_PATH, myPid, { mode: 420 });
9318
8396
  const daemonConfig = { port, hostname, token };
9319
8397
  if (internalPort) daemonConfig.internalPort = internalPort;
9320
8398
  if (tls) daemonConfig.tls = true;
9321
- writeFileSync10(DAEMON_JSON_PATH, `${JSON.stringify(daemonConfig, null, 2)}
8399
+ writeFileSync9(DAEMON_JSON_PATH, `${JSON.stringify(daemonConfig, null, 2)}
9322
8400
  `, { mode: 420 });
9323
8401
  const delivery = initDeliveryManager();
9324
8402
  const manager = initMindManager();
@@ -9335,7 +8413,8 @@ async function startDaemon(opts) {
9335
8413
  const summarizer = initSummarizer();
9336
8414
  summarizer.start();
9337
8415
  const unsubscribeWebhook = initWebhook();
9338
- await completeOrphanedTurns();
8416
+ const orphanedTurns = await completeOrphanedTurns();
8417
+ summarizeOrphanedTurns(orphanedTurns);
9339
8418
  const allMinds = await readAllMinds();
9340
8419
  const runningEntries = allMinds.filter((e) => e.running && e.mindType !== "spirit");
9341
8420
  {
@@ -9365,10 +8444,10 @@ async function startDaemon(opts) {
9365
8444
  await Promise.all(workers);
9366
8445
  }
9367
8446
  try {
9368
- const { isSetupComplete: isSetupComplete2 } = await import("./setup-GGMKENLN.js");
8447
+ const { isSetupComplete: isSetupComplete2 } = await import("./setup-RHJRFURI.js");
9369
8448
  if (isSetupComplete2()) {
9370
- const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-4JP4TY4C.js");
9371
- const { startSpiritFull } = await import("./mind-service-VIKZJK2M.js");
8449
+ const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-ZFRDXMG7.js");
8450
+ const { startSpiritFull } = await import("./mind-service-X2CAA6W6.js");
9372
8451
  await ensureSpiritProject();
9373
8452
  await syncSpiritTemplate();
9374
8453
  const spiritEntry = await findMind("volute");
@@ -9385,7 +8464,7 @@ async function startDaemon(opts) {
9385
8464
  bridgeManager.startBridges(daemonPort).catch((err) => {
9386
8465
  logger_default.warn("failed to start bridges", logger_default.errorData(err));
9387
8466
  });
9388
- import("./cloud-sync-TG3TIX5H.js").then(
8467
+ import("./cloud-sync-6JL4C24T.js").then(
9389
8468
  ({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
9390
8469
  logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
9391
8470
  })
@@ -9393,7 +8472,7 @@ async function startDaemon(opts) {
9393
8472
  logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
9394
8473
  });
9395
8474
  try {
9396
- const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-YCH4UVQ2.js");
8475
+ const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-FXSEMXWW.js");
9397
8476
  backfillTemplateHashes();
9398
8477
  notifyVersionUpdate().catch((err) => {
9399
8478
  logger_default.warn("failed to send version update notifications", logger_default.errorData(err));
@@ -9414,13 +8493,13 @@ async function startDaemon(opts) {
9414
8493
  logger_default.info(`running on ${hostname}:${port}, pid ${myPid}`);
9415
8494
  function cleanup() {
9416
8495
  try {
9417
- if (readFileSync12(DAEMON_PID_PATH, "utf-8").trim() === myPid) {
8496
+ if (readFileSync11(DAEMON_PID_PATH, "utf-8").trim() === myPid) {
9418
8497
  unlinkSync2(DAEMON_PID_PATH);
9419
8498
  }
9420
8499
  } catch {
9421
8500
  }
9422
8501
  try {
9423
- const data = JSON.parse(readFileSync12(DAEMON_JSON_PATH, "utf-8"));
8502
+ const data = JSON.parse(readFileSync11(DAEMON_JSON_PATH, "utf-8"));
9424
8503
  if (data.token === token) {
9425
8504
  unlinkSync2(DAEMON_JSON_PATH);
9426
8505
  }