volute 0.45.2 → 0.47.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.
- package/README.md +4 -4
- package/dist/{activity-events-BUR2RYTJ.js → activity-events-MIOK3IOU.js} +3 -3
- package/dist/{ai-service-UODCCE4O.js → ai-service-CVZEYKTK.js} +4 -4
- package/dist/{archive-WS2L2VIQ.js → archive-6Z4GFQPH.js} +3 -3
- package/dist/{auth-FLAEXXZK.js → auth-A4VGHADI.js} +4 -4
- package/dist/avatar-image-7S3WA77A.js +22 -0
- package/dist/{backup-TST5C2YN.js → backup-IIAFOW2L.js} +13 -13
- package/dist/channels-ITE4YC57.js +89 -0
- package/dist/{chat-76MRWWQX.js → chat-AJLJCQ3M.js} +12 -8
- package/dist/{chunk-ZV7MFISX.js → chunk-2MJ7EOMT.js} +20 -2
- package/dist/{chunk-R77O2WMK.js → chunk-2OIYNHWO.js} +1 -1
- package/dist/{chunk-QCN24XEN.js → chunk-3YUBFTDN.js} +1 -1
- package/dist/{chunk-NYC5U6K7.js → chunk-4I72V3E5.js} +10 -10
- package/dist/{chunk-QNQMSWZE.js → chunk-5IERLDUS.js} +3 -3
- package/dist/{chunk-FXORA5JG.js → chunk-5NN2VHJV.js} +3 -3
- package/dist/chunk-7KRIHYLR.js +124 -0
- package/dist/{chunk-RRNXJOKB.js → chunk-BGYHLR54.js} +2 -2
- package/dist/{chunk-QMJCNZ6C.js → chunk-C3KLHJDB.js} +1 -1
- package/dist/{chunk-TQJ6ZYVY.js → chunk-CBOIHNMR.js} +2 -2
- package/dist/{chunk-H2X54EHC.js → chunk-DGGZVZTM.js} +1 -1
- package/dist/{chunk-4JOQZPCE.js → chunk-EIQDZC43.js} +1 -1
- package/dist/{chunk-YT7PEESJ.js → chunk-F55GRIEK.js} +464 -221
- package/dist/{chunk-OP4JG2BS.js → chunk-HPGN6XRT.js} +8 -4
- package/dist/{chunk-7ZUB63PS.js → chunk-IWJSNMSY.js} +5 -5
- package/dist/{chunk-ZDZISKCL.js → chunk-IYG4FBMP.js} +1 -1
- package/dist/chunk-JCMGDCGX.js +237 -0
- package/dist/{clock-K43IMROX.js → chunk-JSVHH32K.js} +26 -21
- package/dist/{chunk-UYLGEDVD.js → chunk-K23P5Q5N.js} +340 -339
- package/dist/{chunk-7C44R625.js → chunk-LTLFOSA4.js} +49 -3
- package/dist/{chunk-IHKGWTGT.js → chunk-LWDTP6DH.js} +1 -1
- package/dist/{chunk-JZ62SYWR.js → chunk-M3XDVS5Q.js} +1 -1
- package/dist/{chunk-FR6S2KNN.js → chunk-M6TTZRGH.js} +9 -9
- package/dist/{chunk-EJVPTVTI.js → chunk-MTRMQFCQ.js} +1 -1
- package/dist/{chunk-T6HYVHPG.js → chunk-ODDGGLM6.js} +3 -3
- package/dist/{chunk-QLWG3C2Z.js → chunk-RRZ4RQQU.js} +2 -2
- package/dist/{chunk-CDPBTTZO.js → chunk-RUFLGTOT.js} +2 -2
- package/dist/{chunk-F7H6ATM4.js → chunk-SKNXMUIU.js} +1 -1
- package/dist/{chunk-RXEEYDIB.js → chunk-SZJCJVXV.js} +1 -1
- package/dist/{chunk-DRJ24GXK.js → chunk-VMCZBXF2.js} +52 -8
- package/dist/{chunk-ALKYQULU.js → chunk-WW6C3PLV.js} +1 -1
- package/dist/{chunk-A7WQZKOU.js → chunk-XHN6XBWV.js} +2 -2
- package/dist/{chunk-6EMWJZBK.js → chunk-YKA7DCVW.js} +1 -1
- package/dist/cli.js +24 -24
- package/dist/clock-E6N5Y3YW.js +16 -0
- package/dist/{cloud-sync-3OJOPZRT.js → cloud-sync-LQTVDTQ3.js} +19 -17
- package/dist/{conversations-JZTD6KLR.js → conversations-C7IKYSHD.js} +4 -4
- package/dist/{create-IOV4GCRX.js → create-PQQXKTJK.js} +1 -1
- package/dist/{daemon-restart-TIHKVVVA.js → daemon-restart-5F3YTLZK.js} +7 -7
- package/dist/daemon.js +418 -273
- package/dist/{db-MF2JNRUW.js → db-FO6LXYCW.js} +2 -2
- package/dist/{delete-BFMIGAIB.js → delete-HPLC7ETU.js} +1 -1
- package/dist/delivery-manager-TN5KK2AP.js +34 -0
- package/dist/{delivery-router-N4A7ZC5T.js → delivery-router-3QFG2ZEX.js} +3 -3
- package/dist/{down-U2CZ23M4.js → down-ZI4S6265.js} +5 -5
- package/dist/echo-text-SEQCLGAT.js +34 -0
- package/dist/{exec-G3ZRST4Z.js → exec-QIFYZG4C.js} +3 -3
- package/dist/{export-GGIVO76O.js → export-4GVGNW54.js} +6 -6
- package/dist/{extensions-JONTW2HF.js → extensions-PIMIQ7J3.js} +21 -17
- package/dist/{files-4LN3EN7Q.js → files-FEFZKMNM.js} +6 -6
- package/dist/{import-42YNQBF4.js → import-7MO3YTRE.js} +6 -6
- package/dist/{isolation-YMGZZ4E5.js → isolation-MCT4ZYLT.js} +3 -3
- package/dist/{login-M6OJUPQ2.js → login-OF4WXDAN.js} +5 -5
- package/dist/{logout-WQBWO77G.js → logout-ERE2BGA3.js} +5 -5
- package/dist/message-delivery-ZE3YGJDD.js +38 -0
- package/dist/{mind-DWB6XYCH.js → mind-POOHFZHP.js} +18 -18
- package/dist/{mind-activity-tracker-POBLU3LC.js → mind-activity-tracker-YVZPC4A5.js} +4 -4
- package/dist/{mind-list-4D7J4CHD.js → mind-list-KEGRGQEQ.js} +5 -4
- package/dist/mind-service-JFY7UG5E.js +40 -0
- package/dist/mind-sleep-IN3WPA76.js +83 -0
- package/dist/{mind-status-UO34ASXZ.js → mind-status-SMUWJKGV.js} +20 -3
- package/dist/{package-A7KXT67Q.js → package-WPEE2HVJ.js} +3 -2
- package/dist/{registry-OUZBZ3Q4.js → registry-UMMDRPRM.js} +2 -2
- package/dist/{sandbox-ZJ7QA6Z6.js → sandbox-G4X4K3UN.js} +4 -4
- package/dist/scheduler-HQSDYJFY.js +32 -0
- package/dist/{schema-PVNG3PQM.js → schema-VEVO7HG6.js} +3 -1
- package/dist/{seed-HCP5NYKH.js → seed-VANPU43L.js} +1 -1
- package/dist/{seed-cmd-ILOGNIFB.js → seed-cmd-SYVDZKM4.js} +2 -2
- package/dist/{seed-create-OURS2LS4.js → seed-create-3FGZPS6C.js} +5 -5
- package/dist/{seed-sprout-ELDFDAN6.js → seed-sprout-H7QLFPFM.js} +13 -11
- package/dist/{send-AAIOPJAV.js → send-HYDFGC6G.js} +13 -7
- package/dist/{service-UOCLXDWR.js → service-SYJ5G6LP.js} +4 -4
- package/dist/{service-install-4HHFDDWY.js → service-install-FQ43Z4DF.js} +5 -5
- package/dist/{setup-Y2EJI3GG.js → setup-KFYVWTXG.js} +3 -3
- package/dist/{setup-DQM5VPY4.js → setup-QJHGMGSN.js} +7 -7
- package/dist/skills/orientation/SKILL.md +1 -1
- package/dist/skills/volute-mind/SKILL.md +8 -8
- package/dist/skills/volute-mind/references/sleep.md +8 -1
- package/dist/{skills-BKINFL7W.js → skills-L2CMTW7A.js} +5 -5
- package/dist/sleep-manager-3NA7ZJP3.js +36 -0
- package/dist/{spirit-DBTIW7P4.js → spirit-WXN4IDBF.js} +8 -8
- package/dist/{sprout-W3KC7UGK.js → sprout-LTL5P36T.js} +1 -1
- package/dist/{status-SWRVGXBI.js → status-V4RJMHJ4.js} +19 -9
- package/dist/system-chat-N2F7HVY3.js +38 -0
- package/dist/{systems-VNB5WKSS.js → systems-B5YJKMW4.js} +6 -6
- package/dist/{tailscale-3XOKOW7T.js → tailscale-MCLY5GYE.js} +2 -2
- package/dist/{template-hash-446HHH5V.js → template-hash-GSOUARW4.js} +2 -2
- package/dist/template-staleness-EMQORSGG.js +15 -0
- package/dist/{turn-tracker-2W6Q2NSR.js → turn-tracker-JZRZDFWV.js} +6 -5
- package/dist/{up-FTK7CTO3.js → up-J2PBPOZL.js} +6 -6
- package/dist/{update-SWAYZRWJ.js → update-ACV4SAY3.js} +5 -5
- package/dist/{update-check-PQ2MZ47K.js → update-check-266R4ZSY.js} +3 -3
- package/dist/{version-notify-3XMAIQTE.js → version-notify-XRGTEEDK.js} +42 -23
- package/dist/web-assets/assets/index-DtctoDXY.css +1 -0
- package/dist/web-assets/assets/index-Wpyb2CML.js +86 -0
- package/dist/web-assets/index.html +2 -2
- package/drizzle/0011_drop_turn_summary_event_id.sql +3 -0
- package/drizzle/0012_channel_gates.sql +17 -0
- package/drizzle/meta/_journal.json +14 -0
- package/package.json +3 -2
- package/templates/_base/home/VOLUTE.md +6 -2
- package/templates/_base/src/lib/context-breakdown.ts +57 -67
- package/templates/_base/src/lib/startup.ts +43 -2
- package/templates/_base/src/lib/volute-server.ts +2 -2
- package/templates/claude/src/agent.ts +105 -43
- package/templates/claude/src/lib/session-reaper.ts +63 -0
- package/templates/claude/src/server.ts +10 -1
- package/templates/codex/src/agent.ts +62 -40
- package/templates/pi/src/agent.ts +55 -38
- package/dist/avatar-image-6KY6UU4D.js +0 -16
- package/dist/delivery-manager-VDVKVA46.js +0 -32
- package/dist/echo-text-6JJOPUD4.js +0 -32
- package/dist/message-delivery-3C65ZI6L.js +0 -34
- package/dist/mind-service-3F4I46CI.js +0 -36
- package/dist/mind-sleep-YMBR3I35.js +0 -47
- package/dist/scheduler-P6DXLLXI.js +0 -30
- package/dist/sleep-manager-HCUH4PM4.js +0 -34
- package/dist/system-chat-XOALE2RD.js +0 -36
- package/dist/web-assets/assets/index-B1JBQv2m.css +0 -1
- package/dist/web-assets/assets/index-Bc2m8gRC.js +0 -86
- package/dist/{accept-N5XULCXK.js → accept-YAFP5JFJ.js} +3 -3
- package/dist/{bridge-2PO3AI5D.js → bridge-TIZGSXOD.js} +3 -3
- package/dist/{create-DF3KISTW.js → create-A7PDHIIL.js} +3 -3
- package/dist/{env-VZ4MLFQW.js → env-HRL2PWAT.js} +5 -5
- package/dist/{extension-SEID47SR.js → extension-QBY4C44L.js} +3 -3
- package/dist/{list-OXIAY3W7.js → list-LQO2DCIK.js} +3 -3
- package/dist/{login-MY6ETFYB.js → login-6TLMI2TQ.js} +3 -3
- package/dist/{logout-NCG3TMDL.js → logout-BK53HXNY.js} +3 -3
- package/dist/{mind-history-VRO5A76U.js → mind-history-47DN6ILW.js} +4 -4
- package/dist/{mind-wake-LCLGTXA2.js → mind-wake-R54BPESY.js} +3 -3
- package/dist/{read-QVAXMTPV.js → read-PWAJOQIQ.js} +3 -3
- package/dist/{register-Y2H4PY5R.js → register-7SZJFHU6.js} +3 -3
- package/dist/{reject-EV35X64Y.js → reject-6VH7N2A4.js} +3 -3
- package/dist/{restart-FJQ662XJ.js → restart-H5WJDMA7.js} +4 -4
- package/dist/{skill-FKFHIJRR.js → skill-GUKG2YVH.js} +5 -5
- package/dist/{start-5JE3TV66.js → start-X46I3GXB.js} +4 -4
- package/dist/{stop-AAMTG3TU.js → stop-HJQV4YSM.js} +4 -4
package/dist/daemon.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
readBackupState,
|
|
7
7
|
resticVersion,
|
|
8
8
|
runBackup
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-5NN2VHJV.js";
|
|
10
10
|
import {
|
|
11
11
|
acceptPending,
|
|
12
12
|
formatFileSize,
|
|
@@ -14,35 +14,34 @@ import {
|
|
|
14
14
|
rejectPending,
|
|
15
15
|
stageFile,
|
|
16
16
|
validateFilePath
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-2OIYNHWO.js";
|
|
18
18
|
import {
|
|
19
19
|
findOpenClawSession,
|
|
20
20
|
importOpenClawConnectors,
|
|
21
21
|
importPiSession,
|
|
22
22
|
parseNameFromIdentity
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-XHN6XBWV.js";
|
|
24
|
+
import {
|
|
25
|
+
isTemplateStale
|
|
26
|
+
} from "./chunk-7KRIHYLR.js";
|
|
24
27
|
import {
|
|
25
28
|
checkForUpdate,
|
|
26
29
|
checkForUpdateCached,
|
|
27
30
|
getCurrentVersion
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import {
|
|
30
|
-
normalizeAvatar,
|
|
31
|
-
safeResolveWithinBase
|
|
32
|
-
} from "./chunk-DRJ24GXK.js";
|
|
31
|
+
} from "./chunk-YKA7DCVW.js";
|
|
33
32
|
import {
|
|
34
33
|
isHomeOnlyArchive
|
|
35
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-3YUBFTDN.js";
|
|
36
35
|
import {
|
|
37
36
|
computeTemplateHash
|
|
38
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-C3KLHJDB.js";
|
|
39
38
|
import {
|
|
40
39
|
PLATFORMS,
|
|
41
40
|
echoTextToChannel,
|
|
42
41
|
fixModelEscapes,
|
|
43
42
|
getPlatformDriver,
|
|
44
43
|
routeOutboundBridge
|
|
45
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-4I72V3E5.js";
|
|
46
45
|
import {
|
|
47
46
|
getBridgeConfig,
|
|
48
47
|
readBridgesConfig,
|
|
@@ -51,7 +50,7 @@ import {
|
|
|
51
50
|
resolveChannelMapping,
|
|
52
51
|
setBridgeConfig,
|
|
53
52
|
setChannelMapping
|
|
54
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-SZJCJVXV.js";
|
|
55
54
|
import {
|
|
56
55
|
MindStartupError,
|
|
57
56
|
RestartTracker,
|
|
@@ -113,15 +112,15 @@ import {
|
|
|
113
112
|
syncProviderToMinds,
|
|
114
113
|
uninstallNpmExtension,
|
|
115
114
|
writeSystemsConfig
|
|
116
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-F55GRIEK.js";
|
|
117
116
|
import {
|
|
118
117
|
loadMergedEnv,
|
|
119
118
|
mindEnvPath,
|
|
120
119
|
readEnv,
|
|
121
120
|
sharedEnvPath,
|
|
122
121
|
writeEnv
|
|
123
|
-
} from "./chunk-
|
|
124
|
-
import "./chunk-
|
|
122
|
+
} from "./chunk-IYG4FBMP.js";
|
|
123
|
+
import "./chunk-M6TTZRGH.js";
|
|
125
124
|
import {
|
|
126
125
|
applyInitFiles,
|
|
127
126
|
applyTemplateHomeFiles,
|
|
@@ -130,7 +129,34 @@ import {
|
|
|
130
129
|
findTemplatesRoot,
|
|
131
130
|
isKnownTemplate,
|
|
132
131
|
listFiles
|
|
133
|
-
} from "./chunk-
|
|
132
|
+
} from "./chunk-RRZ4RQQU.js";
|
|
133
|
+
import {
|
|
134
|
+
assignSession,
|
|
135
|
+
completeOrphanedTurns,
|
|
136
|
+
completeTurn,
|
|
137
|
+
createTurn,
|
|
138
|
+
getActiveTurnId,
|
|
139
|
+
getToolUseEventId,
|
|
140
|
+
initSummarizer,
|
|
141
|
+
isoWeekKeyForDateStr,
|
|
142
|
+
markErrored,
|
|
143
|
+
publish as publish3,
|
|
144
|
+
subscribe as subscribe3,
|
|
145
|
+
subscribeAll,
|
|
146
|
+
summarizeOrphanedTurns,
|
|
147
|
+
summarizeTurn,
|
|
148
|
+
takeErrored,
|
|
149
|
+
trackToolUse
|
|
150
|
+
} from "./chunk-K23P5Q5N.js";
|
|
151
|
+
import {
|
|
152
|
+
ORIENTATION_MARKER,
|
|
153
|
+
PROMPT_DEFAULTS,
|
|
154
|
+
PROMPT_KEYS,
|
|
155
|
+
getMindPromptDefaults,
|
|
156
|
+
getPrompt,
|
|
157
|
+
getPromptIfCustom,
|
|
158
|
+
substitute
|
|
159
|
+
} from "./chunk-JCMGDCGX.js";
|
|
134
160
|
import {
|
|
135
161
|
SEED_SKILLS,
|
|
136
162
|
STANDARD_SKILLS,
|
|
@@ -150,7 +176,7 @@ import {
|
|
|
150
176
|
syncBuiltinSkills,
|
|
151
177
|
uninstallSkill,
|
|
152
178
|
updateSkill
|
|
153
|
-
} from "./chunk-
|
|
179
|
+
} from "./chunk-IWJSNMSY.js";
|
|
154
180
|
import {
|
|
155
181
|
addMessage,
|
|
156
182
|
createChannel,
|
|
@@ -178,51 +204,32 @@ import {
|
|
|
178
204
|
listConversationsForUser,
|
|
179
205
|
listConversationsWithParticipants,
|
|
180
206
|
markConversationRead,
|
|
181
|
-
publish,
|
|
207
|
+
publish as publish2,
|
|
182
208
|
setConversationPrivate,
|
|
183
209
|
subscribe as subscribe2,
|
|
184
210
|
updateChannelSettings
|
|
185
|
-
} from "./chunk-
|
|
186
|
-
import {
|
|
187
|
-
readVoluteConfig,
|
|
188
|
-
writeVoluteConfig
|
|
189
|
-
} from "./chunk-PFZBNKUH.js";
|
|
211
|
+
} from "./chunk-HPGN6XRT.js";
|
|
190
212
|
import {
|
|
191
213
|
isSandboxEnabled,
|
|
192
214
|
wrapForSandbox
|
|
193
|
-
} from "./chunk-
|
|
215
|
+
} from "./chunk-M3XDVS5Q.js";
|
|
194
216
|
import {
|
|
195
217
|
getActiveMinds,
|
|
196
218
|
onMindEvent,
|
|
197
219
|
stopAll
|
|
198
|
-
} from "./chunk-
|
|
220
|
+
} from "./chunk-MTRMQFCQ.js";
|
|
199
221
|
import {
|
|
200
|
-
|
|
201
|
-
|
|
222
|
+
normalizeAvatar,
|
|
223
|
+
safeResolveWithinBase
|
|
224
|
+
} from "./chunk-VMCZBXF2.js";
|
|
202
225
|
import {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
getMindPromptDefaults,
|
|
211
|
-
getPrompt,
|
|
212
|
-
getPromptIfCustom,
|
|
213
|
-
getToolUseEventId,
|
|
214
|
-
initSummarizer,
|
|
215
|
-
markErrored,
|
|
216
|
-
publish as publish2,
|
|
217
|
-
subscribe as subscribe3,
|
|
218
|
-
subscribeAll,
|
|
219
|
-
substitute,
|
|
220
|
-
summarizeOrphanedTurns,
|
|
221
|
-
summarizeTurn,
|
|
222
|
-
takeErrored,
|
|
223
|
-
trackToolUse
|
|
224
|
-
} from "./chunk-UYLGEDVD.js";
|
|
225
|
-
import "./chunk-TQJ6ZYVY.js";
|
|
226
|
+
readVoluteConfig,
|
|
227
|
+
writeVoluteConfig
|
|
228
|
+
} from "./chunk-PFZBNKUH.js";
|
|
229
|
+
import {
|
|
230
|
+
extractTextContent
|
|
231
|
+
} from "./chunk-EIQDZC43.js";
|
|
232
|
+
import "./chunk-CBOIHNMR.js";
|
|
226
233
|
import {
|
|
227
234
|
chownMindDir,
|
|
228
235
|
createMindUser,
|
|
@@ -233,7 +240,7 @@ import {
|
|
|
233
240
|
isIsolationEnabled,
|
|
234
241
|
resolveVoluteBin,
|
|
235
242
|
wrapForIsolation
|
|
236
|
-
} from "./chunk-
|
|
243
|
+
} from "./chunk-DGGZVZTM.js";
|
|
237
244
|
import {
|
|
238
245
|
addCustomModel,
|
|
239
246
|
aiCompleteUtility,
|
|
@@ -255,12 +262,12 @@ import {
|
|
|
255
262
|
setProviderRefreshHook,
|
|
256
263
|
setUtilityModel,
|
|
257
264
|
unqualifyModelId
|
|
258
|
-
} from "./chunk-
|
|
265
|
+
} from "./chunk-LWDTP6DH.js";
|
|
259
266
|
import {
|
|
260
267
|
isSetupComplete,
|
|
261
268
|
readGlobalConfig,
|
|
262
269
|
writeGlobalConfig
|
|
263
|
-
} from "./chunk-
|
|
270
|
+
} from "./chunk-SKNXMUIU.js";
|
|
264
271
|
import {
|
|
265
272
|
approveUser,
|
|
266
273
|
changePassword,
|
|
@@ -279,11 +286,14 @@ import {
|
|
|
279
286
|
syncMindProfile,
|
|
280
287
|
updateUserProfile,
|
|
281
288
|
verifyUser
|
|
282
|
-
} from "./chunk-
|
|
289
|
+
} from "./chunk-ODDGGLM6.js";
|
|
283
290
|
import {
|
|
284
291
|
broadcast,
|
|
292
|
+
getEventsSince,
|
|
293
|
+
nextEventId,
|
|
294
|
+
publish,
|
|
285
295
|
subscribe
|
|
286
|
-
} from "./chunk-
|
|
296
|
+
} from "./chunk-LTLFOSA4.js";
|
|
287
297
|
import {
|
|
288
298
|
logBuffer,
|
|
289
299
|
logger_default
|
|
@@ -292,6 +302,7 @@ import {
|
|
|
292
302
|
buildVoluteSlug
|
|
293
303
|
} from "./chunk-LGNUFVMR.js";
|
|
294
304
|
import {
|
|
305
|
+
SPIRIT_NAME,
|
|
295
306
|
addMind,
|
|
296
307
|
addVariant,
|
|
297
308
|
daemonLoopback,
|
|
@@ -316,7 +327,7 @@ import {
|
|
|
316
327
|
validateMindName,
|
|
317
328
|
voluteHome,
|
|
318
329
|
voluteSystemDir
|
|
319
|
-
} from "./chunk-
|
|
330
|
+
} from "./chunk-WW6C3PLV.js";
|
|
320
331
|
import {
|
|
321
332
|
activity,
|
|
322
333
|
channels,
|
|
@@ -327,7 +338,7 @@ import {
|
|
|
327
338
|
systemPrompts,
|
|
328
339
|
turns,
|
|
329
340
|
users
|
|
330
|
-
} from "./chunk-
|
|
341
|
+
} from "./chunk-2MJ7EOMT.js";
|
|
331
342
|
import "./chunk-K3NQKI34.js";
|
|
332
343
|
|
|
333
344
|
// packages/daemon/src/daemon.ts
|
|
@@ -341,9 +352,12 @@ import { format } from "util";
|
|
|
341
352
|
import { CronExpressionParser } from "cron-parser";
|
|
342
353
|
var blog = logger_default.child("backup");
|
|
343
354
|
var DEFAULT_BACKUP_SCHEDULE = "0 3 * * *";
|
|
355
|
+
var NOTIFY_EVERY_N_FAILURES = 5;
|
|
344
356
|
var BackupManager = class {
|
|
345
357
|
interval = null;
|
|
346
|
-
|
|
358
|
+
/** Epoch-ms of the most recent scheduled fire this process has serviced. */
|
|
359
|
+
lastServicedFireMs = -1;
|
|
360
|
+
consecutiveFailures = 0;
|
|
347
361
|
warnedUnconfigured = false;
|
|
348
362
|
start() {
|
|
349
363
|
this.interval = setInterval(() => {
|
|
@@ -355,9 +369,16 @@ var BackupManager = class {
|
|
|
355
369
|
this.interval = null;
|
|
356
370
|
}
|
|
357
371
|
/**
|
|
358
|
-
* True at most once per scheduled fire
|
|
359
|
-
*
|
|
360
|
-
*
|
|
372
|
+
* True at most once per scheduled fire (records the fire it consumed), and
|
|
373
|
+
* only when backups are enabled and runnable. Not a pure predicate — a second
|
|
374
|
+
* call for the same fire returns false.
|
|
375
|
+
*
|
|
376
|
+
* Catch-up: if the machine was asleep or the daemon was down across a
|
|
377
|
+
* scheduled fire (a laptop at 3am), the fire is picked up on the next tick so
|
|
378
|
+
* long as it falls after the last successful run (`lastRun` in
|
|
379
|
+
* backup-state.json). Without an anchor (no successful backup yet) only the
|
|
380
|
+
* exact on-time minute fires, so freshly enabling backups doesn't trigger an
|
|
381
|
+
* immediate run.
|
|
361
382
|
*/
|
|
362
383
|
isDue(now = /* @__PURE__ */ new Date()) {
|
|
363
384
|
const config2 = readGlobalConfig().backup;
|
|
@@ -372,27 +393,81 @@ var BackupManager = class {
|
|
|
372
393
|
this.warnedUnconfigured = false;
|
|
373
394
|
const cron = config2.schedule || DEFAULT_BACKUP_SCHEDULE;
|
|
374
395
|
const epochMinute = Math.floor(now.getTime() / 6e4);
|
|
375
|
-
|
|
376
|
-
let prevMinute;
|
|
396
|
+
let prevFireMs;
|
|
377
397
|
try {
|
|
378
398
|
const interval = CronExpressionParser.parse(cron, { currentDate: now });
|
|
379
|
-
|
|
399
|
+
prevFireMs = interval.prev().toDate().getTime();
|
|
380
400
|
} catch (err) {
|
|
381
401
|
blog.warn(`invalid backup cron "${cron}"`, logger_default.errorData(err));
|
|
382
402
|
return false;
|
|
383
403
|
}
|
|
384
|
-
if (
|
|
385
|
-
|
|
404
|
+
if (prevFireMs <= this.lastServicedFireMs) return false;
|
|
405
|
+
const lastRunMs = this.readLastRunMs();
|
|
406
|
+
if (lastRunMs !== null && prevFireMs <= lastRunMs) return false;
|
|
407
|
+
const onTime = Math.floor(prevFireMs / 6e4) === epochMinute;
|
|
408
|
+
if (!onTime) {
|
|
409
|
+
if (lastRunMs === null) return false;
|
|
410
|
+
blog.warn(
|
|
411
|
+
`missed scheduled backup fire at ${new Date(prevFireMs).toISOString()}; running catch-up`
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
this.lastServicedFireMs = prevFireMs;
|
|
386
415
|
return true;
|
|
387
416
|
}
|
|
417
|
+
readLastRunMs() {
|
|
418
|
+
const lastRun = readBackupState().lastRun;
|
|
419
|
+
if (!lastRun) return null;
|
|
420
|
+
const ms = Date.parse(lastRun);
|
|
421
|
+
return Number.isNaN(ms) ? null : ms;
|
|
422
|
+
}
|
|
388
423
|
async tick() {
|
|
389
424
|
if (!this.isDue()) return;
|
|
390
425
|
blog.info("scheduled backup starting");
|
|
391
426
|
try {
|
|
392
427
|
await runBackup();
|
|
428
|
+
this.recordSuccess();
|
|
393
429
|
} catch (err) {
|
|
394
430
|
blog.error("scheduled backup failed", logger_default.errorData(err));
|
|
431
|
+
await this.recordFailure(err);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
recordSuccess() {
|
|
435
|
+
this.consecutiveFailures = 0;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Track consecutive scheduled-backup failures and actively notify the operator
|
|
439
|
+
* on the 1st and then every Nth. Returns whether it notified (for tests).
|
|
440
|
+
* Notification failures are swallowed — surfacing a backup failure must never
|
|
441
|
+
* take the daemon's backup loop down with it.
|
|
442
|
+
*/
|
|
443
|
+
async recordFailure(err) {
|
|
444
|
+
this.consecutiveFailures += 1;
|
|
445
|
+
const n = this.consecutiveFailures;
|
|
446
|
+
if (n !== 1 && n % NOTIFY_EVERY_N_FAILURES !== 0) return false;
|
|
447
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
448
|
+
const summary = n === 1 ? `Scheduled backup failed: ${reason}` : `Scheduled backup has failed ${n} times in a row: ${reason}`;
|
|
449
|
+
try {
|
|
450
|
+
await publish({
|
|
451
|
+
type: "backup_failed",
|
|
452
|
+
mind: SPIRIT_NAME,
|
|
453
|
+
summary,
|
|
454
|
+
metadata: { consecutiveFailures: n, error: reason }
|
|
455
|
+
});
|
|
456
|
+
} catch (pubErr) {
|
|
457
|
+
blog.error("failed to publish backup-failure activity", logger_default.errorData(pubErr));
|
|
395
458
|
}
|
|
459
|
+
try {
|
|
460
|
+
const { sendSystemMessage } = await import("./system-chat-N2F7HVY3.js");
|
|
461
|
+
await sendSystemMessage(
|
|
462
|
+
SPIRIT_NAME,
|
|
463
|
+
`${summary}
|
|
464
|
+
|
|
465
|
+
Backups are not being saved. Check \`volute backup status\` and the Backups settings tab.`
|
|
466
|
+
);
|
|
467
|
+
} catch (msgErr) {
|
|
468
|
+
blog.error("failed to send backup-failure system message", logger_default.errorData(msgErr));
|
|
469
|
+
}
|
|
470
|
+
return true;
|
|
396
471
|
}
|
|
397
472
|
};
|
|
398
473
|
var backupManager = null;
|
|
@@ -728,6 +803,26 @@ async function cleanExpiredLogs() {
|
|
|
728
803
|
await db.delete(mindHistory).where(and(eq(mindHistory.type, "log"), lt(mindHistory.created_at, cutoff)));
|
|
729
804
|
}
|
|
730
805
|
|
|
806
|
+
// packages/daemon/src/lib/daemon/maintenance.ts
|
|
807
|
+
var MAINTENANCE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
808
|
+
async function runMaintenance() {
|
|
809
|
+
try {
|
|
810
|
+
await cleanExpiredSessions();
|
|
811
|
+
} catch (err) {
|
|
812
|
+
logger_default.warn("maintenance: failed to clean expired sessions", logger_default.errorData(err));
|
|
813
|
+
}
|
|
814
|
+
try {
|
|
815
|
+
await cleanExpiredLogs();
|
|
816
|
+
} catch (err) {
|
|
817
|
+
logger_default.warn("maintenance: failed to clean expired logs", logger_default.errorData(err));
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
function startMaintenanceInterval(intervalMs = MAINTENANCE_INTERVAL_MS, task = runMaintenance) {
|
|
821
|
+
const handle = setInterval(() => void task(), intervalMs);
|
|
822
|
+
handle.unref?.();
|
|
823
|
+
return handle;
|
|
824
|
+
}
|
|
825
|
+
|
|
731
826
|
// packages/daemon/src/web/api/system.ts
|
|
732
827
|
import { getOAuthProvider, getOAuthProviders } from "@earendil-works/pi-ai/oauth";
|
|
733
828
|
import { getBuiltinProviders } from "@earendil-works/pi-ai/providers/all";
|
|
@@ -961,7 +1056,12 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
961
1056
|
}).get("/info", (c) => {
|
|
962
1057
|
const config2 = readSystemsConfig();
|
|
963
1058
|
const globalConfig = readGlobalConfig();
|
|
964
|
-
|
|
1059
|
+
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone ?? null;
|
|
1060
|
+
return c.json({
|
|
1061
|
+
system: config2?.system ?? null,
|
|
1062
|
+
name: globalConfig.name ?? null,
|
|
1063
|
+
timezone
|
|
1064
|
+
});
|
|
965
1065
|
}).put("/info", requireAdmin, zValidator("json", z.object({ name: z.string() })), (c) => {
|
|
966
1066
|
const { name } = c.req.valid("json");
|
|
967
1067
|
const config2 = readGlobalConfig();
|
|
@@ -1696,17 +1796,17 @@ var authenticated = new Hono3().use(authMiddleware).post("/change-password", zVa
|
|
|
1696
1796
|
if (!AVATAR_MIME[ext]) {
|
|
1697
1797
|
return c.json({ error: "Invalid file type (png, jpg, gif, webp only)" }, 400);
|
|
1698
1798
|
}
|
|
1699
|
-
let
|
|
1799
|
+
let buffer = Buffer.from(await file.arrayBuffer());
|
|
1700
1800
|
let finalExt = ext;
|
|
1701
|
-
const normalized = await normalizeAvatar(
|
|
1801
|
+
const normalized = await normalizeAvatar(buffer);
|
|
1702
1802
|
if (normalized) {
|
|
1703
|
-
|
|
1803
|
+
buffer = normalized.buffer;
|
|
1704
1804
|
finalExt = normalized.ext;
|
|
1705
1805
|
}
|
|
1706
1806
|
const dir = avatarsDir();
|
|
1707
1807
|
mkdirSync2(dir, { recursive: true });
|
|
1708
1808
|
const filename = `avatar-${user.id}${finalExt}`;
|
|
1709
|
-
writeFileSync2(resolve3(dir, filename),
|
|
1809
|
+
writeFileSync2(resolve3(dir, filename), buffer);
|
|
1710
1810
|
if (user.avatar && user.avatar !== filename) {
|
|
1711
1811
|
const oldPath = resolve3(dir, user.avatar);
|
|
1712
1812
|
rmSync(oldPath, { force: true });
|
|
@@ -2168,7 +2268,7 @@ var app4 = new Hono5().post("/:platform/inbound", zValidator4("json", inboundSch
|
|
|
2168
2268
|
}
|
|
2169
2269
|
const participants = await getParticipants(channel.id);
|
|
2170
2270
|
if (!participants.some((p) => p.userId === puppet.id)) {
|
|
2171
|
-
const { addParticipant } = await import("./conversations-
|
|
2271
|
+
const { addParticipant } = await import("./conversations-C7IKYSHD.js");
|
|
2172
2272
|
await addParticipant(channel.id, puppet.id);
|
|
2173
2273
|
}
|
|
2174
2274
|
const contentBlocks = body.content;
|
|
@@ -2452,7 +2552,7 @@ async function notifyMind(mindName, message) {
|
|
|
2452
2552
|
const entry = await findMind(mindName);
|
|
2453
2553
|
if (!entry) return;
|
|
2454
2554
|
try {
|
|
2455
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
2555
|
+
const { sendSystemMessage } = await import("./system-chat-N2F7HVY3.js");
|
|
2456
2556
|
await sendSystemMessage(mindName, message);
|
|
2457
2557
|
} catch (err) {
|
|
2458
2558
|
logger_default.warn(`[file-sharing] notify mind ${mindName} failed`, logger_default.errorData(err));
|
|
@@ -2621,11 +2721,11 @@ var app9 = new Hono11().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
2621
2721
|
if (!AVATAR_MIME2[ext]) {
|
|
2622
2722
|
return c.json({ error: "Invalid file type (png, jpg, gif, webp only)" }, 400);
|
|
2623
2723
|
}
|
|
2624
|
-
let
|
|
2724
|
+
let buffer = Buffer.from(await file.arrayBuffer());
|
|
2625
2725
|
let finalExt = ext;
|
|
2626
|
-
const normalized = await normalizeAvatar(
|
|
2726
|
+
const normalized = await normalizeAvatar(buffer);
|
|
2627
2727
|
if (normalized) {
|
|
2628
|
-
|
|
2728
|
+
buffer = normalized.buffer;
|
|
2629
2729
|
finalExt = normalized.ext;
|
|
2630
2730
|
}
|
|
2631
2731
|
const dir = entry.dir ?? mindDir(name);
|
|
@@ -2639,7 +2739,7 @@ var app9 = new Hono11().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
2639
2739
|
if (oldAvatarPath) rmSync2(oldAvatarPath, { force: true });
|
|
2640
2740
|
}
|
|
2641
2741
|
mkdirSync3(homeDir, { recursive: true });
|
|
2642
|
-
writeFileSync3(avatarPath,
|
|
2742
|
+
writeFileSync3(avatarPath, buffer);
|
|
2643
2743
|
const profile = config2.profile ?? {};
|
|
2644
2744
|
profile.avatar = filename;
|
|
2645
2745
|
config2.profile = profile;
|
|
@@ -2753,13 +2853,14 @@ import { and as and3, desc as desc2, eq as eq3, gte, inArray, sql } from "drizzl
|
|
|
2753
2853
|
import { Hono as Hono12 } from "hono";
|
|
2754
2854
|
async function resolveMindFilter(c) {
|
|
2755
2855
|
const user = c.get("user");
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
}
|
|
2759
|
-
return getBaseName(user.username);
|
|
2856
|
+
const privileged = user.role === "admin" || user.role === "system";
|
|
2857
|
+
return privileged ? c.req.query("mind") ?? void 0 : getBaseName(user.username);
|
|
2760
2858
|
}
|
|
2761
|
-
var history = new Hono12().
|
|
2762
|
-
|
|
2859
|
+
var history = new Hono12().use("*", async (c, next) => {
|
|
2860
|
+
c.set("mindFilter", await resolveMindFilter(c));
|
|
2861
|
+
await next();
|
|
2862
|
+
}).get("/turns", async (c) => {
|
|
2863
|
+
const mindFilter = c.get("mindFilter");
|
|
2763
2864
|
const turnIdFilter = c.req.query("turnId");
|
|
2764
2865
|
const turnIdsFilter = c.req.query("turnIds");
|
|
2765
2866
|
const limit = Math.min(Math.max(parseInt(c.req.query("limit") ?? "50", 10) || 50, 1), 200);
|
|
@@ -2794,7 +2895,7 @@ var history = new Hono12().get("/turns", async (c) => {
|
|
|
2794
2895
|
inArray(mindHistory.turn_id, turnIds),
|
|
2795
2896
|
sql`${mindHistory.type} IN ('inbound', 'outbound')`
|
|
2796
2897
|
)
|
|
2797
|
-
).orderBy(mindHistory.created_at);
|
|
2898
|
+
).orderBy(mindHistory.created_at, mindHistory.id);
|
|
2798
2899
|
const msgsByTurnChannel = /* @__PURE__ */ new Map();
|
|
2799
2900
|
function addToTurnChannel(turnId, channel, event) {
|
|
2800
2901
|
let byChannel = msgsByTurnChannel.get(turnId);
|
|
@@ -2829,7 +2930,7 @@ var history = new Hono12().get("/turns", async (c) => {
|
|
|
2829
2930
|
const label = isDM ? raw : raw.startsWith("#") ? raw : `#${raw}`;
|
|
2830
2931
|
return { label, type: isDM ? "dm" : "channel" };
|
|
2831
2932
|
}
|
|
2832
|
-
const activityRows = await db.select().from(activity).where(inArray(activity.turn_id, turnIds)).orderBy(activity.created_at);
|
|
2933
|
+
const activityRows = await db.select().from(activity).where(inArray(activity.turn_id, turnIds)).orderBy(activity.created_at, activity.id);
|
|
2833
2934
|
const activitiesByTurn = /* @__PURE__ */ new Map();
|
|
2834
2935
|
for (const a of activityRows) {
|
|
2835
2936
|
if (!a.turn_id) continue;
|
|
@@ -3001,7 +3102,7 @@ var history = new Hono12().get("/turns", async (c) => {
|
|
|
3001
3102
|
});
|
|
3002
3103
|
return c.json(result);
|
|
3003
3104
|
}).get("/events", async (c) => {
|
|
3004
|
-
const mindFilter =
|
|
3105
|
+
const mindFilter = c.get("mindFilter");
|
|
3005
3106
|
const stream = new ReadableStream({
|
|
3006
3107
|
start(controller) {
|
|
3007
3108
|
const encoder = new TextEncoder();
|
|
@@ -3058,7 +3159,7 @@ var history = new Hono12().get("/turns", async (c) => {
|
|
|
3058
3159
|
}).get("/summaries", async (c) => {
|
|
3059
3160
|
const user = c.get("user");
|
|
3060
3161
|
const privileged = user.role === "admin" || user.role === "system";
|
|
3061
|
-
const mind =
|
|
3162
|
+
const mind = c.get("mindFilter") ?? "_system";
|
|
3062
3163
|
const period = c.req.query("period");
|
|
3063
3164
|
const ids = c.req.query("ids");
|
|
3064
3165
|
const from = c.req.query("from");
|
|
@@ -3089,8 +3190,9 @@ var history = new Hono12().get("/turns", async (c) => {
|
|
|
3089
3190
|
}
|
|
3090
3191
|
const db = await getDb();
|
|
3091
3192
|
const conditions = [eq3(summaries.mind, mind), eq3(summaries.period, period)];
|
|
3092
|
-
|
|
3093
|
-
if (
|
|
3193
|
+
const normalizeBound = (bound) => period === "week" ? isoWeekKeyForDateStr(bound) : bound;
|
|
3194
|
+
if (from) conditions.push(gte(summaries.period_key, normalizeBound(from)));
|
|
3195
|
+
if (to) conditions.push(sql`${summaries.period_key} <= ${normalizeBound(to)}`);
|
|
3094
3196
|
const rows = await db.select({
|
|
3095
3197
|
id: summaries.id,
|
|
3096
3198
|
mind: summaries.mind,
|
|
@@ -3113,7 +3215,7 @@ var history = new Hono12().get("/turns", async (c) => {
|
|
|
3113
3215
|
});
|
|
3114
3216
|
return c.json(result);
|
|
3115
3217
|
}).get("/activity", async (c) => {
|
|
3116
|
-
const mind =
|
|
3218
|
+
const mind = c.get("mindFilter");
|
|
3117
3219
|
const from = c.req.query("from");
|
|
3118
3220
|
const to = c.req.query("to");
|
|
3119
3221
|
const limit = Math.min(Math.max(parseInt(c.req.query("limit") ?? "100", 10) || 100, 1), 500);
|
|
@@ -3377,12 +3479,12 @@ import {
|
|
|
3377
3479
|
} from "fs";
|
|
3378
3480
|
import { relative, resolve as resolve10 } from "path";
|
|
3379
3481
|
import { zValidator as zValidator6 } from "@hono/zod-validator";
|
|
3380
|
-
import { and as and5, desc as
|
|
3482
|
+
import { and as and5, desc as desc3, eq as eq5, sql as sql3 } from "drizzle-orm";
|
|
3381
3483
|
import { Hono as Hono16 } from "hono";
|
|
3382
3484
|
import { z as z6 } from "zod";
|
|
3383
3485
|
|
|
3384
3486
|
// packages/daemon/src/lib/daemon/turn-lifecycle.ts
|
|
3385
|
-
import { and as and4,
|
|
3487
|
+
import { and as and4, eq as eq4, gte as gte2, inArray as inArray2, sql as sql2 } from "drizzle-orm";
|
|
3386
3488
|
|
|
3387
3489
|
// packages/daemon/src/lib/daemon/error-classify.ts
|
|
3388
3490
|
function classify(raw) {
|
|
@@ -3441,21 +3543,27 @@ function markDeliveredOnCleanTurn(mind, session) {
|
|
|
3441
3543
|
);
|
|
3442
3544
|
}
|
|
3443
3545
|
}
|
|
3444
|
-
async function linkPendingInbound(mind, turnId, channel) {
|
|
3445
|
-
|
|
3546
|
+
async function linkPendingInbound(mind, turnId, channel, session) {
|
|
3547
|
+
const scopeChannel = channel ?? session;
|
|
3548
|
+
if (!scopeChannel) return;
|
|
3446
3549
|
const db = await getDb();
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
)
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3550
|
+
let lowerBound;
|
|
3551
|
+
if (session) {
|
|
3552
|
+
const prev = await db.select({ max: sql2`max(${turns.created_at})` }).from(turns).where(and4(eq4(turns.mind, mind), eq4(turns.session, session), sql2`${turns.id} != ${turnId}`)).get();
|
|
3553
|
+
lowerBound = prev?.max ?? void 0;
|
|
3554
|
+
}
|
|
3555
|
+
const conditions = [
|
|
3556
|
+
eq4(mindHistory.mind, mind),
|
|
3557
|
+
eq4(mindHistory.type, "inbound"),
|
|
3558
|
+
sql2`${mindHistory.turn_id} IS NULL`,
|
|
3559
|
+
eq4(mindHistory.channel, scopeChannel)
|
|
3560
|
+
];
|
|
3561
|
+
if (lowerBound) conditions.push(gte2(mindHistory.created_at, lowerBound));
|
|
3562
|
+
const pending = await db.select({ id: mindHistory.id }).from(mindHistory).where(and4(...conditions)).orderBy(mindHistory.id);
|
|
3563
|
+
if (pending.length === 0) return;
|
|
3564
|
+
const ids = pending.map((r) => r.id);
|
|
3457
3565
|
await db.update(mindHistory).set({ turn_id: turnId }).where(inArray2(mindHistory.id, ids));
|
|
3458
|
-
await db.update(turns).set({ trigger_event_id:
|
|
3566
|
+
await db.update(turns).set({ trigger_event_id: ids[0] }).where(eq4(turns.id, turnId));
|
|
3459
3567
|
}
|
|
3460
3568
|
async function handleMindEvent(mind, event) {
|
|
3461
3569
|
if (event.type === "session_start" && event.session) {
|
|
@@ -3468,10 +3576,10 @@ async function handleMindEvent(mind, event) {
|
|
|
3468
3576
|
if (!turnId) {
|
|
3469
3577
|
llog.warn(`skipping turn tracking for ${mind}: createTurn failed`);
|
|
3470
3578
|
} else {
|
|
3471
|
-
|
|
3579
|
+
publish3(mind, { mind, type: "turn_created", turnId });
|
|
3472
3580
|
if (event.session) await assignSession(mind, turnId, event.session);
|
|
3473
3581
|
try {
|
|
3474
|
-
await linkPendingInbound(mind, turnId, event.channel);
|
|
3582
|
+
await linkPendingInbound(mind, turnId, event.channel, event.session);
|
|
3475
3583
|
} catch (err) {
|
|
3476
3584
|
llog.warn(
|
|
3477
3585
|
`failed to link trigger inbound for turn ${turnId} (mind: ${mind})`,
|
|
@@ -3514,7 +3622,7 @@ async function handleMindEvent(mind, event) {
|
|
|
3514
3622
|
llog.error("failed to link tool_result to turn", logger_default.errorData(err));
|
|
3515
3623
|
}
|
|
3516
3624
|
}
|
|
3517
|
-
|
|
3625
|
+
publish3(mind, {
|
|
3518
3626
|
mind,
|
|
3519
3627
|
type: event.type,
|
|
3520
3628
|
session: event.session,
|
|
@@ -3707,7 +3815,7 @@ async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
|
|
|
3707
3815
|
logger_default.warn(`failed to stop variant ${variantName}`, logger_default.errorData(err));
|
|
3708
3816
|
}
|
|
3709
3817
|
}
|
|
3710
|
-
const { findMind: findMind2 } = await import("./registry-
|
|
3818
|
+
const { findMind: findMind2 } = await import("./registry-UMMDRPRM.js");
|
|
3711
3819
|
const variantEntry = await findMind2(variantName);
|
|
3712
3820
|
const branchName = variantEntry?.branch ?? variantName;
|
|
3713
3821
|
if (existsSync6(variantPath)) {
|
|
@@ -3936,7 +4044,7 @@ async function getMindStatus(name, port, registryRunning) {
|
|
|
3936
4044
|
const manager = getMindManager();
|
|
3937
4045
|
let status = "stopped";
|
|
3938
4046
|
try {
|
|
3939
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4047
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-3NA7ZJP3.js");
|
|
3940
4048
|
if (getSleepManagerIfReady2()?.isSleeping(name)) {
|
|
3941
4049
|
status = "sleeping";
|
|
3942
4050
|
}
|
|
@@ -3964,6 +4072,25 @@ async function getMindStatus(name, port, registryRunning) {
|
|
|
3964
4072
|
avatar: config2?.profile?.avatar
|
|
3965
4073
|
};
|
|
3966
4074
|
}
|
|
4075
|
+
function isPrivileged(c) {
|
|
4076
|
+
const role = c.get("user").role;
|
|
4077
|
+
return role === "admin" || role === "system";
|
|
4078
|
+
}
|
|
4079
|
+
function toPublicMind(entry, status, extras) {
|
|
4080
|
+
return {
|
|
4081
|
+
name: entry.name,
|
|
4082
|
+
created: entry.created,
|
|
4083
|
+
stage: entry.stage,
|
|
4084
|
+
mindType: entry.mindType,
|
|
4085
|
+
status: status.status,
|
|
4086
|
+
channels: status.channels,
|
|
4087
|
+
displayName: status.displayName,
|
|
4088
|
+
description: status.description,
|
|
4089
|
+
avatar: status.avatar,
|
|
4090
|
+
hasPages: extras.hasPages,
|
|
4091
|
+
lastActiveAt: extras.lastActiveAt ?? null
|
|
4092
|
+
};
|
|
4093
|
+
}
|
|
3967
4094
|
var TEMPLATE_BRANCH = "volute/template";
|
|
3968
4095
|
async function configureGitIdentity(mindName, opts) {
|
|
3969
4096
|
const systemsConfig = readSystemsConfig();
|
|
@@ -4431,7 +4558,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
4431
4558
|
applyInitFiles(dest);
|
|
4432
4559
|
const { publicKeyPem } = generateIdentity(dest);
|
|
4433
4560
|
{
|
|
4434
|
-
const { readGlobalConfig: readGlobal } = await import("./setup-
|
|
4561
|
+
const { readGlobalConfig: readGlobal } = await import("./setup-KFYVWTXG.js");
|
|
4435
4562
|
const mindDefaults = readGlobal().mindDefaults;
|
|
4436
4563
|
const config2 = readVoluteConfig(dest);
|
|
4437
4564
|
if (!config2) throw new Error("Failed to read volute.json after identity generation");
|
|
@@ -4513,7 +4640,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
4513
4640
|
}
|
|
4514
4641
|
if (body.stage === "seed") {
|
|
4515
4642
|
const descLine = body.description ? `
|
|
4516
|
-
|
|
4643
|
+
Your creator described you as: "${body.description}"
|
|
4517
4644
|
` : "";
|
|
4518
4645
|
const seedSoulRaw = body.seedSoul ?? await getPrompt("seed_soul", { name, description: descLine });
|
|
4519
4646
|
const seedSoul = body.seedSoul ? substitute(seedSoulRaw, { name, description: descLine }) : seedSoulRaw;
|
|
@@ -4521,7 +4648,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4521
4648
|
}
|
|
4522
4649
|
let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
|
|
4523
4650
|
if (body.stage === "seed" && !body.skills) {
|
|
4524
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
4651
|
+
const { isImagegenEnabled } = await import("./setup-KFYVWTXG.js");
|
|
4525
4652
|
if (isImagegenEnabled()) {
|
|
4526
4653
|
skillSet = [...skillSet, "imagegen"];
|
|
4527
4654
|
}
|
|
@@ -4539,7 +4666,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4539
4666
|
try {
|
|
4540
4667
|
const spiritEntry = await findMind("volute");
|
|
4541
4668
|
if (spiritEntry) {
|
|
4542
|
-
const { spiritDir } = await import("./spirit-
|
|
4669
|
+
const { spiritDir } = await import("./spirit-WXN4IDBF.js");
|
|
4543
4670
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
4544
4671
|
const spiritConfig = readVoluteConfig(sDir) ?? {};
|
|
4545
4672
|
const schedules = spiritConfig.schedules ?? [];
|
|
@@ -4554,7 +4681,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4554
4681
|
});
|
|
4555
4682
|
spiritConfig.schedules = schedules;
|
|
4556
4683
|
writeVoluteConfig(sDir, spiritConfig);
|
|
4557
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
4684
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-HQSDYJFY.js");
|
|
4558
4685
|
getScheduler2().loadSchedules("volute", sDir);
|
|
4559
4686
|
}
|
|
4560
4687
|
}
|
|
@@ -4741,15 +4868,19 @@ ${user.trimEnd()}
|
|
|
4741
4868
|
} catch {
|
|
4742
4869
|
}
|
|
4743
4870
|
}
|
|
4871
|
+
const privileged = isPrivileged(c);
|
|
4744
4872
|
const minds = await Promise.all(
|
|
4745
4873
|
entries.map(async (entry) => {
|
|
4746
4874
|
const mindStatus = await getMindStatus(entry.name, entry.port, entry.running);
|
|
4747
4875
|
const hasPages = existsSync7(resolve10(mindDir(entry.name), "home", "pages"));
|
|
4876
|
+
const lastActiveAt = lastActiveMap.get(entry.name) ?? null;
|
|
4877
|
+
if (!privileged) return toPublicMind(entry, mindStatus, { hasPages, lastActiveAt });
|
|
4748
4878
|
return {
|
|
4749
4879
|
...entry,
|
|
4750
4880
|
...mindStatus,
|
|
4751
4881
|
hasPages,
|
|
4752
|
-
|
|
4882
|
+
templateStale: isTemplateStale(entry),
|
|
4883
|
+
lastActiveAt
|
|
4753
4884
|
};
|
|
4754
4885
|
})
|
|
4755
4886
|
);
|
|
@@ -4761,6 +4892,10 @@ ${user.trimEnd()}
|
|
|
4761
4892
|
const dir = entry.dir ?? mindDir(entry.parent ?? name);
|
|
4762
4893
|
if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
4763
4894
|
const mindStatus = await getMindStatus(name, entry.port);
|
|
4895
|
+
const hasPages = existsSync7(resolve10(mindDir(name), "home", "pages"));
|
|
4896
|
+
if (!isPrivileged(c)) {
|
|
4897
|
+
return c.json(toPublicMind(entry, mindStatus, { hasPages }));
|
|
4898
|
+
}
|
|
4764
4899
|
const variants = await findVariants(name);
|
|
4765
4900
|
const manager = getMindManager();
|
|
4766
4901
|
const variantStatuses = await Promise.all(
|
|
@@ -4773,8 +4908,13 @@ ${user.trimEnd()}
|
|
|
4773
4908
|
return { name: s.name, port: s.port, status: variantStatus };
|
|
4774
4909
|
})
|
|
4775
4910
|
);
|
|
4776
|
-
|
|
4777
|
-
|
|
4911
|
+
return c.json({
|
|
4912
|
+
...entry,
|
|
4913
|
+
...mindStatus,
|
|
4914
|
+
variants: variantStatuses,
|
|
4915
|
+
hasPages,
|
|
4916
|
+
templateStale: isTemplateStale(entry)
|
|
4917
|
+
});
|
|
4778
4918
|
}).get("/:name/context", requireSelf(), async (c) => proxyToMind(c, "context")).get("/:name/context/messages", requireSelf(), async (c) => proxyToMind(c, "context/messages")).post("/:name/start", requireSelf(), async (c) => {
|
|
4779
4919
|
const name = c.req.param("name");
|
|
4780
4920
|
const entry = await findMind(name);
|
|
@@ -4820,7 +4960,7 @@ ${user.trimEnd()}
|
|
|
4820
4960
|
const manager = getMindManager();
|
|
4821
4961
|
try {
|
|
4822
4962
|
if (context?.type === "reload") {
|
|
4823
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4963
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-3NA7ZJP3.js");
|
|
4824
4964
|
const sleepState = getSleepManagerIfReady2()?.getState(name);
|
|
4825
4965
|
if (sleepState?.sleeping) {
|
|
4826
4966
|
logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
|
|
@@ -4947,7 +5087,7 @@ ${user.trimEnd()}
|
|
|
4947
5087
|
const name = c.req.param("name");
|
|
4948
5088
|
const entry = await findMind(name);
|
|
4949
5089
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4950
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5090
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-3NA7ZJP3.js");
|
|
4951
5091
|
const sm = getSleepManagerIfReady2();
|
|
4952
5092
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4953
5093
|
return c.json(sm.getState(name));
|
|
@@ -4955,7 +5095,7 @@ ${user.trimEnd()}
|
|
|
4955
5095
|
const name = c.req.param("name");
|
|
4956
5096
|
const entry = await findMind(name);
|
|
4957
5097
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4958
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5098
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-3NA7ZJP3.js");
|
|
4959
5099
|
const sm = getSleepManagerIfReady2();
|
|
4960
5100
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4961
5101
|
if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
|
|
@@ -4975,7 +5115,7 @@ ${user.trimEnd()}
|
|
|
4975
5115
|
const name = c.req.param("name");
|
|
4976
5116
|
const entry = await findMind(name);
|
|
4977
5117
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4978
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5118
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-3NA7ZJP3.js");
|
|
4979
5119
|
const sm = getSleepManagerIfReady2();
|
|
4980
5120
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4981
5121
|
const sleepState = sm.getState(name);
|
|
@@ -4990,7 +5130,7 @@ ${user.trimEnd()}
|
|
|
4990
5130
|
const name = c.req.param("name");
|
|
4991
5131
|
const entry = await findMind(name);
|
|
4992
5132
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4993
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5133
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-3NA7ZJP3.js");
|
|
4994
5134
|
const sm = getSleepManagerIfReady2();
|
|
4995
5135
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4996
5136
|
const flushed = await sm.flushQueuedMessages(name);
|
|
@@ -5018,7 +5158,7 @@ ${user.trimEnd()}
|
|
|
5018
5158
|
}
|
|
5019
5159
|
config2.profile = profile;
|
|
5020
5160
|
writeVoluteConfig(dir, config2);
|
|
5021
|
-
const { syncMindProfile: syncMindProfile2 } = await import("./auth-
|
|
5161
|
+
const { syncMindProfile: syncMindProfile2 } = await import("./auth-A4VGHADI.js");
|
|
5022
5162
|
await syncMindProfile2(name, profile);
|
|
5023
5163
|
broadcast({ type: "profile_updated", mind: name, summary: `${name} profile updated` });
|
|
5024
5164
|
return c.json({ ok: true });
|
|
@@ -5028,7 +5168,6 @@ ${user.trimEnd()}
|
|
|
5028
5168
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5029
5169
|
if (entry.stage !== "seed") return c.json({ output: "" });
|
|
5030
5170
|
const db = await getDb();
|
|
5031
|
-
const ORIENTATION_MARKER = "You don't have a soul yet";
|
|
5032
5171
|
const rawCreator = Number(process.env.VOLUTE_NURTURE_CREATOR_MINUTES);
|
|
5033
5172
|
const creatorThreshold = Number.isNaN(rawCreator) ? 5 : rawCreator;
|
|
5034
5173
|
const rawSpirit = Number(process.env.VOLUTE_NURTURE_SPIRIT_MINUTES);
|
|
@@ -5041,14 +5180,14 @@ ${user.trimEnd()}
|
|
|
5041
5180
|
sql3`${mindHistory.sender} != ${name}`,
|
|
5042
5181
|
sql3`${mindHistory.sender} IS NOT NULL`
|
|
5043
5182
|
)
|
|
5044
|
-
).orderBy(
|
|
5183
|
+
).orderBy(desc3(mindHistory.created_at)).limit(1);
|
|
5045
5184
|
const lastSpiritMsg = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(
|
|
5046
5185
|
and5(
|
|
5047
5186
|
eq5(mindHistory.mind, name),
|
|
5048
5187
|
eq5(mindHistory.type, "inbound"),
|
|
5049
5188
|
eq5(mindHistory.sender, "volute")
|
|
5050
5189
|
)
|
|
5051
|
-
).orderBy(
|
|
5190
|
+
).orderBy(desc3(mindHistory.created_at)).limit(1);
|
|
5052
5191
|
const now = Date.now();
|
|
5053
5192
|
const creatorTime = lastCreatorMsg[0] ? new Date(lastCreatorMsg[0].created_at).getTime() : 0;
|
|
5054
5193
|
const spiritTime = lastSpiritMsg[0] ? new Date(lastSpiritMsg[0].created_at).getTime() : 0;
|
|
@@ -5065,7 +5204,7 @@ ${user.trimEnd()}
|
|
|
5065
5204
|
const config2 = readVoluteConfig(dir);
|
|
5066
5205
|
const displayNameSet = !!config2?.profile?.displayName;
|
|
5067
5206
|
const avatarSet = !!config2?.profile?.avatar;
|
|
5068
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
5207
|
+
const { isImagegenEnabled } = await import("./setup-KFYVWTXG.js");
|
|
5069
5208
|
const imagegenEnabled = isImagegenEnabled();
|
|
5070
5209
|
const done = [];
|
|
5071
5210
|
const remaining = [];
|
|
@@ -5103,7 +5242,7 @@ ${user.trimEnd()}
|
|
|
5103
5242
|
try {
|
|
5104
5243
|
const spiritEntry = await findMind("volute");
|
|
5105
5244
|
if (spiritEntry) {
|
|
5106
|
-
const { spiritDir } = await import("./spirit-
|
|
5245
|
+
const { spiritDir } = await import("./spirit-WXN4IDBF.js");
|
|
5107
5246
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
5108
5247
|
const spiritConfig = readVoluteConfig(sDir);
|
|
5109
5248
|
if (spiritConfig?.schedules) {
|
|
@@ -5111,7 +5250,7 @@ ${user.trimEnd()}
|
|
|
5111
5250
|
spiritConfig.schedules = spiritConfig.schedules.filter((s) => s.id !== nurtureId);
|
|
5112
5251
|
if (spiritConfig.schedules.length === 0) spiritConfig.schedules = void 0;
|
|
5113
5252
|
writeVoluteConfig(sDir, spiritConfig);
|
|
5114
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
5253
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-HQSDYJFY.js");
|
|
5115
5254
|
getScheduler2().loadSchedules("volute", sDir);
|
|
5116
5255
|
}
|
|
5117
5256
|
}
|
|
@@ -5546,7 +5685,7 @@ ${user.trimEnd()}
|
|
|
5546
5685
|
}
|
|
5547
5686
|
writeVoluteConfig(dir, existing);
|
|
5548
5687
|
if (body.unescapeNewlines !== void 0) {
|
|
5549
|
-
const { clearEchoTextCache } = await import("./echo-text-
|
|
5688
|
+
const { clearEchoTextCache } = await import("./echo-text-SEQCLGAT.js");
|
|
5550
5689
|
clearEchoTextCache(name);
|
|
5551
5690
|
}
|
|
5552
5691
|
const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.maxThinkingTokens !== void 0 || body.compaction !== void 0;
|
|
@@ -5623,7 +5762,7 @@ ${user.trimEnd()}
|
|
|
5623
5762
|
}
|
|
5624
5763
|
if (entry.mindType === "spirit" && body.model !== void 0) {
|
|
5625
5764
|
try {
|
|
5626
|
-
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-
|
|
5765
|
+
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-KFYVWTXG.js");
|
|
5627
5766
|
const globalConfig = readGlobalConfig2();
|
|
5628
5767
|
globalConfig.spiritModel = body.model;
|
|
5629
5768
|
writeGlobalConfig2(globalConfig);
|
|
@@ -5646,12 +5785,27 @@ ${user.trimEnd()}
|
|
|
5646
5785
|
logger_default.error(`failed to get pending deliveries for ${baseName}`, logger_default.errorData(err));
|
|
5647
5786
|
return c.json({ error: "Failed to retrieve pending messages" }, 500);
|
|
5648
5787
|
}
|
|
5788
|
+
}).post("/:name/gates/decline", requireSelf(), async (c) => {
|
|
5789
|
+
const name = c.req.param("name");
|
|
5790
|
+
const body = await c.req.json().catch(() => ({}));
|
|
5791
|
+
const channel = body.channel?.trim();
|
|
5792
|
+
if (!channel) return c.json({ error: "channel required" }, 400);
|
|
5793
|
+
try {
|
|
5794
|
+
const archived = await getDeliveryManager().declineChannel(name, channel);
|
|
5795
|
+
return c.json({ ok: true, channel, archived });
|
|
5796
|
+
} catch (err) {
|
|
5797
|
+
if (err instanceof Error && err.message.includes("not initialized")) {
|
|
5798
|
+
return c.json({ error: "Delivery manager not available" }, 503);
|
|
5799
|
+
}
|
|
5800
|
+
logger_default.error(`failed to decline channel ${channel} for ${name}`, logger_default.errorData(err));
|
|
5801
|
+
return c.json({ error: "Failed to decline channel" }, 500);
|
|
5802
|
+
}
|
|
5649
5803
|
}).post("/:name/ai/complete", requireSelf(), async (c) => {
|
|
5650
5804
|
const body = await c.req.json();
|
|
5651
5805
|
if (!body.systemPrompt || !body.message) {
|
|
5652
5806
|
return c.json({ error: "systemPrompt and message required" }, 400);
|
|
5653
5807
|
}
|
|
5654
|
-
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-
|
|
5808
|
+
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-CVZEYKTK.js");
|
|
5655
5809
|
if (!isAiConfigured()) {
|
|
5656
5810
|
return c.json({ error: "AI service not configured" }, 503);
|
|
5657
5811
|
}
|
|
@@ -5817,7 +5971,7 @@ ${user.trimEnd()}
|
|
|
5817
5971
|
eq5(mindHistory.session, currentSession),
|
|
5818
5972
|
sql3`${mindHistory.turn_id} IS NOT NULL`
|
|
5819
5973
|
)
|
|
5820
|
-
).orderBy(
|
|
5974
|
+
).orderBy(desc3(mindHistory.created_at)).limit(1);
|
|
5821
5975
|
if (lastTurn.length > 0 && lastTurn[0].turn_id) {
|
|
5822
5976
|
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);
|
|
5823
5977
|
if (firstEvent.length > 0) {
|
|
@@ -5840,7 +5994,7 @@ ${user.trimEnd()}
|
|
|
5840
5994
|
session: turns.session,
|
|
5841
5995
|
content: summaries.content,
|
|
5842
5996
|
created_at: summaries.created_at
|
|
5843
|
-
}).from(summaries).innerJoin(turns, eq5(turns.id, summaries.period_key)).where(and5(...conditions)).orderBy(
|
|
5997
|
+
}).from(summaries).innerJoin(turns, eq5(turns.id, summaries.period_key)).where(and5(...conditions)).orderBy(desc3(summaries.created_at)).limit(50);
|
|
5844
5998
|
if (rows.length === 0) {
|
|
5845
5999
|
return c.json({ context: null });
|
|
5846
6000
|
}
|
|
@@ -5891,7 +6045,7 @@ ${lines.join("\n")}` });
|
|
|
5891
6045
|
metadata: summaries.metadata,
|
|
5892
6046
|
created_at: summaries.created_at,
|
|
5893
6047
|
session: turns.session
|
|
5894
|
-
}).from(summaries).innerJoin(turns, eq5(turns.id, summaries.period_key)).where(and5(...sumConditions)).orderBy(
|
|
6048
|
+
}).from(summaries).innerJoin(turns, eq5(turns.id, summaries.period_key)).where(and5(...sumConditions)).orderBy(desc3(summaries.created_at)).limit(limit).offset(offset);
|
|
5895
6049
|
return c.json(
|
|
5896
6050
|
sumRows2.map((r) => ({
|
|
5897
6051
|
id: r.id,
|
|
@@ -5908,7 +6062,7 @@ ${lines.join("\n")}` });
|
|
|
5908
6062
|
}))
|
|
5909
6063
|
);
|
|
5910
6064
|
}
|
|
5911
|
-
const sumRows = await db.select().from(summaries).where(and5(...sumConditions)).orderBy(
|
|
6065
|
+
const sumRows = await db.select().from(summaries).where(and5(...sumConditions)).orderBy(desc3(summaries.created_at)).limit(limit).offset(offset);
|
|
5912
6066
|
return c.json(
|
|
5913
6067
|
sumRows.map((r) => ({
|
|
5914
6068
|
id: r.id,
|
|
@@ -5937,7 +6091,7 @@ ${lines.join("\n")}` });
|
|
|
5937
6091
|
);
|
|
5938
6092
|
break;
|
|
5939
6093
|
}
|
|
5940
|
-
const rows = await db.select().from(mindHistory).where(and5(...conditions)).orderBy(
|
|
6094
|
+
const rows = await db.select().from(mindHistory).where(and5(...conditions)).orderBy(desc3(mindHistory.created_at)).limit(limit).offset(offset);
|
|
5941
6095
|
return c.json(rows);
|
|
5942
6096
|
});
|
|
5943
6097
|
var minds_default = app13;
|
|
@@ -6000,76 +6154,93 @@ var slog2 = logger_default.child("schedules");
|
|
|
6000
6154
|
function readSchedules(dir) {
|
|
6001
6155
|
return readVoluteConfig(dir)?.schedules ?? [];
|
|
6002
6156
|
}
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
config2.schedules = schedules.length > 0 ? schedules : void 0;
|
|
6006
|
-
writeVoluteConfig(dir, config2);
|
|
6007
|
-
getScheduler().loadSchedules(name, dir);
|
|
6008
|
-
getSleepManagerIfReady()?.invalidateSleepConfig(name);
|
|
6009
|
-
fireWebhook({
|
|
6010
|
-
event: "schedule_changed",
|
|
6011
|
-
mind: name,
|
|
6012
|
-
data: { schedules }
|
|
6013
|
-
});
|
|
6014
|
-
}
|
|
6015
|
-
var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) => {
|
|
6016
|
-
const name = c.req.param("name");
|
|
6017
|
-
const entry = await findMind(name);
|
|
6018
|
-
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
6019
|
-
const dir = entry.dir ?? mindDir(name);
|
|
6020
|
-
const sleepManager = getSleepManagerIfReady();
|
|
6021
|
-
const sleepState = sleepManager?.getState(name) ?? null;
|
|
6022
|
-
const sleepConfig = sleepManager?.getSleepConfig(name) ?? null;
|
|
6023
|
-
const schedules = readSchedules(dir);
|
|
6024
|
-
const now = /* @__PURE__ */ new Date();
|
|
6157
|
+
var UPCOMING_HORIZON_MS = 24 * 60 * 60 * 1e3;
|
|
6158
|
+
function computeClockEvents(schedules, sleepState, sleepConfig, now) {
|
|
6025
6159
|
const upcoming = [];
|
|
6026
6160
|
const previous = [];
|
|
6161
|
+
const effectiveWake = sleepState?.sleeping ? sleepState.scheduledWakeAt ?? sleepState.voluntaryWakeAt : null;
|
|
6162
|
+
const effectiveWakeDate = effectiveWake ? new Date(effectiveWake) : null;
|
|
6163
|
+
const sleepFate = (s, fireDate) => {
|
|
6164
|
+
if (!effectiveWakeDate || fireDate >= effectiveWakeDate) return {};
|
|
6165
|
+
const ws = s.whileSleeping ?? "queue";
|
|
6166
|
+
if (ws === "skip") return { willSkip: true };
|
|
6167
|
+
if (ws === "trigger-wake") return {};
|
|
6168
|
+
return { willQueue: true };
|
|
6169
|
+
};
|
|
6027
6170
|
for (const s of schedules) {
|
|
6028
6171
|
if (!s.enabled) continue;
|
|
6029
6172
|
if (s.fireAt) {
|
|
6030
6173
|
const fireDate = new Date(s.fireAt);
|
|
6031
6174
|
if (fireDate >= now) {
|
|
6032
|
-
upcoming.push({
|
|
6175
|
+
upcoming.push({
|
|
6176
|
+
id: s.id,
|
|
6177
|
+
at: fireDate.toISOString(),
|
|
6178
|
+
type: "timer",
|
|
6179
|
+
...sleepFate(s, fireDate)
|
|
6180
|
+
});
|
|
6033
6181
|
}
|
|
6034
6182
|
} else if (s.cron) {
|
|
6035
6183
|
try {
|
|
6036
|
-
const
|
|
6037
|
-
|
|
6038
|
-
upcoming.push({ id: s.id, at: next.toISOString(), type: "cron" });
|
|
6184
|
+
const next = CronExpressionParser3.parse(s.cron, { currentDate: now }).next().toDate();
|
|
6185
|
+
upcoming.push({ id: s.id, at: next.toISOString(), type: "cron", ...sleepFate(s, next) });
|
|
6039
6186
|
} catch {
|
|
6040
|
-
slog2.warn(`invalid cron "${s.cron}" for schedule "${s.id}"
|
|
6187
|
+
slog2.warn(`invalid cron "${s.cron}" for schedule "${s.id}"`);
|
|
6041
6188
|
}
|
|
6042
6189
|
try {
|
|
6043
|
-
const
|
|
6044
|
-
const prev = prevInterval.prev().toDate();
|
|
6190
|
+
const prev = CronExpressionParser3.parse(s.cron, { currentDate: now }).prev().toDate();
|
|
6045
6191
|
previous.push({ id: s.id, at: prev.toISOString() });
|
|
6046
6192
|
} catch {
|
|
6047
6193
|
}
|
|
6048
6194
|
}
|
|
6049
6195
|
}
|
|
6050
6196
|
if (sleepState?.sleeping) {
|
|
6051
|
-
if (
|
|
6052
|
-
upcoming.push({ id: "
|
|
6197
|
+
if (effectiveWake) {
|
|
6198
|
+
upcoming.push({ id: "wake", at: effectiveWake, type: "cron" });
|
|
6053
6199
|
}
|
|
6054
6200
|
if (sleepState.sleepingSince) {
|
|
6055
6201
|
previous.push({ id: "sleep", at: sleepState.sleepingSince });
|
|
6056
6202
|
}
|
|
6057
6203
|
} else if (sleepConfig?.enabled && sleepConfig.schedule) {
|
|
6058
6204
|
try {
|
|
6059
|
-
const
|
|
6060
|
-
const nextSleep = sleepInterval.next().toDate();
|
|
6205
|
+
const nextSleep = CronExpressionParser3.parse(sleepConfig.schedule.sleep, { currentDate: now }).next().toDate();
|
|
6061
6206
|
upcoming.push({ id: "sleep", at: nextSleep.toISOString(), type: "cron" });
|
|
6062
6207
|
} catch {
|
|
6063
6208
|
}
|
|
6064
6209
|
try {
|
|
6065
|
-
const
|
|
6066
|
-
|
|
6067
|
-
previous.push({ id: "sleep", at: prevWake.toISOString() });
|
|
6210
|
+
const prevWake = CronExpressionParser3.parse(sleepConfig.schedule.wake, { currentDate: now }).prev().toDate();
|
|
6211
|
+
previous.push({ id: "wake", at: prevWake.toISOString() });
|
|
6068
6212
|
} catch {
|
|
6069
6213
|
}
|
|
6070
6214
|
}
|
|
6071
|
-
|
|
6215
|
+
const horizon = now.getTime() + UPCOMING_HORIZON_MS;
|
|
6216
|
+
const withinHorizon = upcoming.filter((e) => new Date(e.at).getTime() <= horizon);
|
|
6217
|
+
withinHorizon.sort((a, b) => a.at.localeCompare(b.at));
|
|
6072
6218
|
previous.sort((a, b) => b.at.localeCompare(a.at));
|
|
6219
|
+
return { upcoming: withinHorizon, previous };
|
|
6220
|
+
}
|
|
6221
|
+
function writeSchedules(name, dir, schedules) {
|
|
6222
|
+
const config2 = readVoluteConfig(dir) ?? {};
|
|
6223
|
+
config2.schedules = schedules.length > 0 ? schedules : void 0;
|
|
6224
|
+
writeVoluteConfig(dir, config2);
|
|
6225
|
+
getScheduler().loadSchedules(name, dir);
|
|
6226
|
+
getSleepManagerIfReady()?.invalidateSleepConfig(name);
|
|
6227
|
+
fireWebhook({
|
|
6228
|
+
event: "schedule_changed",
|
|
6229
|
+
mind: name,
|
|
6230
|
+
data: { schedules }
|
|
6231
|
+
});
|
|
6232
|
+
}
|
|
6233
|
+
var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) => {
|
|
6234
|
+
const name = c.req.param("name");
|
|
6235
|
+
const entry = await findMind(name);
|
|
6236
|
+
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
6237
|
+
const dir = entry.dir ?? mindDir(name);
|
|
6238
|
+
const sleepManager = getSleepManagerIfReady();
|
|
6239
|
+
const sleepState = sleepManager?.getState(name) ?? null;
|
|
6240
|
+
const sleepConfig = sleepManager?.getSleepConfig(name) ?? null;
|
|
6241
|
+
const schedules = readSchedules(dir);
|
|
6242
|
+
const now = /* @__PURE__ */ new Date();
|
|
6243
|
+
const { upcoming, previous } = computeClockEvents(schedules, sleepState, sleepConfig, now);
|
|
6073
6244
|
return c.json({ sleep: sleepState, sleepConfig, schedules, upcoming, previous });
|
|
6074
6245
|
}).get("/:name/sleep/config", requireSelf(), async (c) => {
|
|
6075
6246
|
const name = c.req.param("name");
|
|
@@ -6236,7 +6407,7 @@ var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
6236
6407
|
const body = await c.req.text();
|
|
6237
6408
|
const message = `[webhook: ${event}] ${body}`;
|
|
6238
6409
|
try {
|
|
6239
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
6410
|
+
const { sendSystemMessage } = await import("./system-chat-N2F7HVY3.js");
|
|
6240
6411
|
await sendSystemMessage(name, message);
|
|
6241
6412
|
return c.json({ ok: true });
|
|
6242
6413
|
} catch (err) {
|
|
@@ -6290,7 +6461,7 @@ setup.get("/status", async (c) => {
|
|
|
6290
6461
|
let hasAccount = false;
|
|
6291
6462
|
if (hasSystem) {
|
|
6292
6463
|
try {
|
|
6293
|
-
const { listUsersByType: listUsersByType2 } = await import("./auth-
|
|
6464
|
+
const { listUsersByType: listUsersByType2 } = await import("./auth-A4VGHADI.js");
|
|
6294
6465
|
const brains = await listUsersByType2("brain");
|
|
6295
6466
|
hasAccount = brains.length > 0;
|
|
6296
6467
|
} catch (err) {
|
|
@@ -6501,7 +6672,7 @@ setup.post("/account", async (c) => {
|
|
|
6501
6672
|
}
|
|
6502
6673
|
}
|
|
6503
6674
|
try {
|
|
6504
|
-
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-
|
|
6675
|
+
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-A4VGHADI.js");
|
|
6505
6676
|
const user = await createUser2(body.username.trim(), body.password);
|
|
6506
6677
|
if (body.displayName?.trim()) {
|
|
6507
6678
|
await updateUserProfile2(user.id, { display_name: body.displayName.trim() });
|
|
@@ -6547,7 +6718,7 @@ setup.post("/models", async (c) => {
|
|
|
6547
6718
|
return c.json({ error: "Spirit model is required" }, 400);
|
|
6548
6719
|
}
|
|
6549
6720
|
try {
|
|
6550
|
-
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-
|
|
6721
|
+
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-CVZEYKTK.js");
|
|
6551
6722
|
setEnabledModels3(body.models);
|
|
6552
6723
|
const config2 = readGlobalConfig();
|
|
6553
6724
|
config2.spiritModel = body.spiritModel.trim();
|
|
@@ -6565,15 +6736,15 @@ setup.post("/complete", async (c) => {
|
|
|
6565
6736
|
return c.json({ error: "Setup already complete" }, 400);
|
|
6566
6737
|
}
|
|
6567
6738
|
try {
|
|
6568
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
6569
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
6739
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-WXN4IDBF.js");
|
|
6740
|
+
const { startSpiritFull } = await import("./mind-service-JFY7UG5E.js");
|
|
6570
6741
|
await ensureSpiritProject();
|
|
6571
6742
|
await syncSpiritTemplate();
|
|
6572
6743
|
const warnings = [];
|
|
6573
6744
|
const config2 = readGlobalConfig();
|
|
6574
6745
|
if (config2.setup?.service && config2.setup?.type === "local") {
|
|
6575
6746
|
try {
|
|
6576
|
-
const { installUserService } = await import("./service-install-
|
|
6747
|
+
const { installUserService } = await import("./service-install-FQ43Z4DF.js");
|
|
6577
6748
|
const installed = await installUserService(config2.port, config2.hostname);
|
|
6578
6749
|
if (!installed) {
|
|
6579
6750
|
warnings.push("Service installation is not supported on this platform.");
|
|
@@ -6601,8 +6772,8 @@ setup.post("/complete", async (c) => {
|
|
|
6601
6772
|
}
|
|
6602
6773
|
let spiritConversationId;
|
|
6603
6774
|
try {
|
|
6604
|
-
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-
|
|
6605
|
-
const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-
|
|
6775
|
+
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-A4VGHADI.js");
|
|
6776
|
+
const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-C7IKYSHD.js");
|
|
6606
6777
|
const spiritUser = await getOrCreateMindUser2("volute");
|
|
6607
6778
|
const brains = await listUsersByType2("brain");
|
|
6608
6779
|
const admin2 = brains.find((u) => u.role === "admin");
|
|
@@ -6624,21 +6795,23 @@ setup.post("/complete", async (c) => {
|
|
|
6624
6795
|
logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
|
|
6625
6796
|
if (spiritConversationId && spiritStarted) {
|
|
6626
6797
|
try {
|
|
6627
|
-
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-
|
|
6628
|
-
const { listUsersByType: listUsers2 } = await import("./auth-
|
|
6798
|
+
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-ZE3YGJDD.js");
|
|
6799
|
+
const { listUsersByType: listUsers2 } = await import("./auth-A4VGHADI.js");
|
|
6629
6800
|
const admins = await listUsers2("brain");
|
|
6630
6801
|
const admin2 = admins.find((u) => u.role === "admin");
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6802
|
+
if (admin2) {
|
|
6803
|
+
const adminName = admin2.display_name || admin2.username;
|
|
6804
|
+
const welcomePrompt = `Setup is complete. ${adminName} just finished setting up this system and is now in your chat. Welcome them and help them create their first mind. Keep it brief \u2014 a short greeting, then ask what kind of being they'd like to bring into the world. Remember: minds are beings with their own experience, not tools \u2014 ask about personality and character, never about tasks or utility.`;
|
|
6805
|
+
await deliverMessage2(SPIRIT_NAME, {
|
|
6806
|
+
content: [{ type: "text", text: welcomePrompt }],
|
|
6807
|
+
channel: `@${admin2.username}`,
|
|
6808
|
+
conversationId: spiritConversationId,
|
|
6809
|
+
sender: admin2.username,
|
|
6810
|
+
isDM: true,
|
|
6811
|
+
participants: [SPIRIT_NAME, admin2.username],
|
|
6812
|
+
participantCount: 2
|
|
6813
|
+
});
|
|
6814
|
+
}
|
|
6642
6815
|
} catch (err) {
|
|
6643
6816
|
logger_default.warn("failed to send welcome prompt to spirit (non-fatal)", logger_default.errorData(err));
|
|
6644
6817
|
warnings.push(
|
|
@@ -6735,10 +6908,10 @@ var app16 = new Hono20().get("/", async (c) => {
|
|
|
6735
6908
|
if (!file.name.endsWith(".zip")) {
|
|
6736
6909
|
return c.json({ error: "Only .zip files are accepted" }, 400);
|
|
6737
6910
|
}
|
|
6738
|
-
const
|
|
6911
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
6739
6912
|
const tmpDir = mkdtempSync(join(tmpdir(), "volute-skill-upload-"));
|
|
6740
6913
|
try {
|
|
6741
|
-
const zip = new AdmZip(
|
|
6914
|
+
const zip = new AdmZip(buffer);
|
|
6742
6915
|
for (const entry of zip.getEntries()) {
|
|
6743
6916
|
const target = resolve12(tmpDir, entry.entryName);
|
|
6744
6917
|
if (!target.startsWith(tmpDir)) {
|
|
@@ -6808,7 +6981,7 @@ var app17 = new Hono21().post("/:name/typing", zValidator8("json", typingSchema)
|
|
|
6808
6981
|
map.delete(channel, sender);
|
|
6809
6982
|
}
|
|
6810
6983
|
if (isConversationId(channel)) {
|
|
6811
|
-
|
|
6984
|
+
publish2(channel, { type: "typing", senders: map.get(channel) });
|
|
6812
6985
|
}
|
|
6813
6986
|
return c.json({ ok: true });
|
|
6814
6987
|
}).get("/:name/typing", (c) => {
|
|
@@ -6944,7 +7117,7 @@ var app19 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6944
7117
|
var conversations_default = app19;
|
|
6945
7118
|
|
|
6946
7119
|
// packages/daemon/src/web/api/v1/events.ts
|
|
6947
|
-
import { desc as
|
|
7120
|
+
import { desc as desc4, eq as eq7 } from "drizzle-orm";
|
|
6948
7121
|
import { Hono as Hono24 } from "hono";
|
|
6949
7122
|
import { streamSSE as streamSSE4 } from "hono/streaming";
|
|
6950
7123
|
|
|
@@ -6971,42 +7144,6 @@ function getOnlineBrains() {
|
|
|
6971
7144
|
return [...connections.keys()];
|
|
6972
7145
|
}
|
|
6973
7146
|
|
|
6974
|
-
// packages/daemon/src/lib/events/event-sequencer.ts
|
|
6975
|
-
var BUFFER_SIZE = 1e3;
|
|
6976
|
-
var MAX_AGE_MS = 5 * 60 * 1e3;
|
|
6977
|
-
var nextId = 1;
|
|
6978
|
-
var buffer = [];
|
|
6979
|
-
function bufferEvent(data) {
|
|
6980
|
-
const id = nextId++;
|
|
6981
|
-
buffer.push({ id, data, timestamp: Date.now() });
|
|
6982
|
-
while (buffer.length > BUFFER_SIZE) {
|
|
6983
|
-
buffer.shift();
|
|
6984
|
-
}
|
|
6985
|
-
return id;
|
|
6986
|
-
}
|
|
6987
|
-
function nextEventId() {
|
|
6988
|
-
return nextId++;
|
|
6989
|
-
}
|
|
6990
|
-
function getEventsSince(sinceId, allowedConversationIds, allowedActivityMind) {
|
|
6991
|
-
const now = Date.now();
|
|
6992
|
-
const startIdx = buffer.findIndex((e) => e.id > sinceId);
|
|
6993
|
-
if (startIdx === -1) return [];
|
|
6994
|
-
return buffer.slice(startIdx).filter((e) => {
|
|
6995
|
-
if (now - e.timestamp >= MAX_AGE_MS) return false;
|
|
6996
|
-
const data = e.data;
|
|
6997
|
-
switch (data.event) {
|
|
6998
|
-
case "snapshot":
|
|
6999
|
-
return false;
|
|
7000
|
-
case "conversation":
|
|
7001
|
-
return allowedConversationIds.has(data.conversationId);
|
|
7002
|
-
case "activity":
|
|
7003
|
-
return allowedActivityMind === void 0 || data.mind === allowedActivityMind;
|
|
7004
|
-
default:
|
|
7005
|
-
return false;
|
|
7006
|
-
}
|
|
7007
|
-
});
|
|
7008
|
-
}
|
|
7009
|
-
|
|
7010
7147
|
// packages/daemon/src/web/api/v1/events.ts
|
|
7011
7148
|
var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
|
|
7012
7149
|
const user = c.get("user");
|
|
@@ -7047,7 +7184,7 @@ var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
|
|
|
7047
7184
|
let recentActivity = [];
|
|
7048
7185
|
try {
|
|
7049
7186
|
const db = await getDb();
|
|
7050
|
-
recentActivity = await db.select().from(activity).where(activityMind ? eq7(activity.mind, activityMind) : void 0).orderBy(
|
|
7187
|
+
recentActivity = await db.select().from(activity).where(activityMind ? eq7(activity.mind, activityMind) : void 0).orderBy(desc4(activity.created_at)).limit(50);
|
|
7051
7188
|
recentActivity = recentActivity.map((row) => ({
|
|
7052
7189
|
...row,
|
|
7053
7190
|
metadata: row.metadata ? JSON.parse(row.metadata) : null
|
|
@@ -7068,15 +7205,15 @@ var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
|
|
|
7068
7205
|
data: JSON.stringify(snapshotData)
|
|
7069
7206
|
});
|
|
7070
7207
|
const unsubActivity = subscribe((event) => {
|
|
7208
|
+
if (activityMind !== void 0 && event.mind !== activityMind) return;
|
|
7209
|
+
const { seq, ...rest } = event;
|
|
7071
7210
|
const data = {
|
|
7072
7211
|
event: "activity",
|
|
7073
|
-
...
|
|
7074
|
-
metadata:
|
|
7212
|
+
...rest,
|
|
7213
|
+
metadata: rest.metadata ?? null
|
|
7075
7214
|
};
|
|
7076
|
-
const eventId = bufferEvent(data);
|
|
7077
|
-
if (activityMind !== void 0 && event.mind !== activityMind) return;
|
|
7078
7215
|
stream.writeSSE({
|
|
7079
|
-
id: String(
|
|
7216
|
+
id: String(seq),
|
|
7080
7217
|
data: JSON.stringify(data)
|
|
7081
7218
|
}).catch((err) => {
|
|
7082
7219
|
if (!stream.aborted) logger_default.error("[v1-events] write error:", logger_default.errorData(err));
|
|
@@ -7085,10 +7222,10 @@ var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
|
|
|
7085
7222
|
cleanups.push(unsubActivity);
|
|
7086
7223
|
for (const conv of conversations2) {
|
|
7087
7224
|
const unsubConv = subscribe2(conv.id, (event) => {
|
|
7088
|
-
const
|
|
7089
|
-
const
|
|
7225
|
+
const { seq, ...rest } = event;
|
|
7226
|
+
const data = { event: "conversation", conversationId: conv.id, ...rest };
|
|
7090
7227
|
stream.writeSSE({
|
|
7091
|
-
id: String(
|
|
7228
|
+
id: String(seq),
|
|
7092
7229
|
data: JSON.stringify(data)
|
|
7093
7230
|
}).catch((err) => {
|
|
7094
7231
|
if (!stream.aborted) logger_default.error("[v1-events] write error:", logger_default.errorData(err));
|
|
@@ -7126,12 +7263,9 @@ import { Hono as Hono25 } from "hono";
|
|
|
7126
7263
|
import { spawn as spawn4 } from "child_process";
|
|
7127
7264
|
import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync9 } from "fs";
|
|
7128
7265
|
import { resolve as resolve13 } from "path";
|
|
7129
|
-
function tsxBin(cwd) {
|
|
7130
|
-
return resolve13(cwd, "node_modules", ".bin", "tsx");
|
|
7131
|
-
}
|
|
7132
7266
|
async function spawnServer(cwd, port, options) {
|
|
7133
|
-
let cmd =
|
|
7134
|
-
let args = ["src/server.ts", "--port", String(port)];
|
|
7267
|
+
let cmd = process.env.VOLUTE_NODE_PATH ?? process.execPath;
|
|
7268
|
+
let args = ["--import", "tsx", "src/server.ts", "--port", String(port)];
|
|
7135
7269
|
if (options?.mindName) {
|
|
7136
7270
|
if (isIsolationEnabled()) {
|
|
7137
7271
|
[cmd, args] = await wrapForIsolation(cmd, args, options.mindName);
|
|
@@ -7456,8 +7590,8 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
|
7456
7590
|
await chownMindDir(projectRoot, mindName);
|
|
7457
7591
|
if (variantName.endsWith("-upgrade") || variantName === "upgrade") {
|
|
7458
7592
|
try {
|
|
7459
|
-
const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-
|
|
7460
|
-
const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-
|
|
7593
|
+
const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-GSOUARW4.js");
|
|
7594
|
+
const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-UMMDRPRM.js");
|
|
7461
7595
|
const tmpl = parentEntry.template ?? "claude";
|
|
7462
7596
|
await setMindTemplateHash2(mindName, computeTemplateHash2(tmpl));
|
|
7463
7597
|
} catch (err) {
|
|
@@ -7834,7 +7968,7 @@ var unifiedChatApp = new Hono27().post(
|
|
|
7834
7968
|
});
|
|
7835
7969
|
if (outboundTurnId) {
|
|
7836
7970
|
const mindKey = senderBase ?? senderName;
|
|
7837
|
-
|
|
7971
|
+
publish3(mindKey, {
|
|
7838
7972
|
mind: mindKey,
|
|
7839
7973
|
type: "outbound",
|
|
7840
7974
|
channel,
|
|
@@ -7960,6 +8094,9 @@ var app24 = new Hono28().get("/:name/conversations", async (c) => {
|
|
|
7960
8094
|
if (!u) return c.json({ error: `User ${id} not found` }, 400);
|
|
7961
8095
|
}
|
|
7962
8096
|
const participantIds = [...participantSet];
|
|
8097
|
+
if (participantIds.length < 2) {
|
|
8098
|
+
return c.json({ error: "a conversation needs at least two distinct participants" }, 400);
|
|
8099
|
+
}
|
|
7963
8100
|
if (participantIds.length > 2) {
|
|
7964
8101
|
return c.json({ error: "Use channels for multi-participant conversations" }, 400);
|
|
7965
8102
|
}
|
|
@@ -8243,27 +8380,27 @@ async function startDaemon(opts) {
|
|
|
8243
8380
|
const DAEMON_TOKEN_PATH = resolve16(systemDir, "daemon-token");
|
|
8244
8381
|
mkdirSync10(home, { recursive: true });
|
|
8245
8382
|
ensureSystemDir();
|
|
8246
|
-
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-
|
|
8383
|
+
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-KFYVWTXG.js");
|
|
8247
8384
|
migrateConfigSecrets();
|
|
8248
8385
|
migrateSetupCompleted();
|
|
8249
|
-
const { migrateAiModelQualification } = await import("./ai-service-
|
|
8386
|
+
const { migrateAiModelQualification } = await import("./ai-service-CVZEYKTK.js");
|
|
8250
8387
|
migrateAiModelQualification();
|
|
8251
|
-
await (await import("./db-
|
|
8388
|
+
await (await import("./db-FO6LXYCW.js")).getDb();
|
|
8252
8389
|
try {
|
|
8253
8390
|
const { eq: eq8, and: and6 } = await import("drizzle-orm");
|
|
8254
|
-
const { users: users2 } = await import("./schema-
|
|
8255
|
-
const db = await (await import("./db-
|
|
8391
|
+
const { users: users2 } = await import("./schema-VEVO7HG6.js");
|
|
8392
|
+
const db = await (await import("./db-FO6LXYCW.js")).getDb();
|
|
8256
8393
|
await db.update(users2).set({ role: "system" }).where(and6(eq8(users2.user_type, "system"), eq8(users2.role, "user")));
|
|
8257
8394
|
} catch (err) {
|
|
8258
8395
|
logger_default.warn("failed to migrate system user role", logger_default.errorData(err));
|
|
8259
8396
|
}
|
|
8260
8397
|
try {
|
|
8261
|
-
const { migrateAvatarSizes } = await import("./avatar-image-
|
|
8398
|
+
const { migrateAvatarSizes } = await import("./avatar-image-7S3WA77A.js");
|
|
8262
8399
|
await migrateAvatarSizes();
|
|
8263
8400
|
} catch (err) {
|
|
8264
8401
|
logger_default.warn("avatar size migration failed", logger_default.errorData(err));
|
|
8265
8402
|
}
|
|
8266
|
-
const { initSandbox } = await import("./sandbox-
|
|
8403
|
+
const { initSandbox } = await import("./sandbox-G4X4K3UN.js");
|
|
8267
8404
|
await initSandbox();
|
|
8268
8405
|
try {
|
|
8269
8406
|
await syncBuiltinSkills();
|
|
@@ -8290,7 +8427,7 @@ async function startDaemon(opts) {
|
|
|
8290
8427
|
logger_default.warn("failed to ensure #system channel", logger_default.errorData(err));
|
|
8291
8428
|
}
|
|
8292
8429
|
try {
|
|
8293
|
-
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-
|
|
8430
|
+
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-A4VGHADI.js");
|
|
8294
8431
|
await getOrCreateSystemUser2();
|
|
8295
8432
|
} catch (err) {
|
|
8296
8433
|
logger_default.warn(
|
|
@@ -8299,12 +8436,12 @@ async function startDaemon(opts) {
|
|
|
8299
8436
|
);
|
|
8300
8437
|
}
|
|
8301
8438
|
const token = process.env.VOLUTE_DAEMON_TOKEN || randomBytes3(32).toString("hex");
|
|
8302
|
-
const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-
|
|
8439
|
+
const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-KFYVWTXG.js");
|
|
8303
8440
|
const globalCfg = readGlobalConfig2();
|
|
8304
8441
|
let tls;
|
|
8305
8442
|
if (opts.tailscale || globalCfg.tailscale) {
|
|
8306
8443
|
try {
|
|
8307
|
-
const { getTailscaleTls } = await import("./tailscale-
|
|
8444
|
+
const { getTailscaleTls } = await import("./tailscale-MCLY5GYE.js");
|
|
8308
8445
|
const tlsConfig = await getTailscaleTls();
|
|
8309
8446
|
tls = { key: tlsConfig.key, cert: tlsConfig.cert };
|
|
8310
8447
|
logger_default.info("Tailscale HTTPS enabled", { hostname: tlsConfig.hostname });
|
|
@@ -8384,15 +8521,19 @@ async function startDaemon(opts) {
|
|
|
8384
8521
|
await Promise.all(workers);
|
|
8385
8522
|
}
|
|
8386
8523
|
try {
|
|
8387
|
-
const { isSetupComplete: isSetupComplete2 } = await import("./setup-
|
|
8524
|
+
const { isSetupComplete: isSetupComplete2 } = await import("./setup-KFYVWTXG.js");
|
|
8388
8525
|
if (isSetupComplete2()) {
|
|
8389
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
8390
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
8526
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-WXN4IDBF.js");
|
|
8527
|
+
const { startSpiritFull } = await import("./mind-service-JFY7UG5E.js");
|
|
8391
8528
|
await ensureSpiritProject();
|
|
8529
|
+
const spiritEntry = await findMind(SPIRIT_NAME);
|
|
8530
|
+
if (spiritEntry?.dir) {
|
|
8531
|
+
const { registerMindDir } = await import("./delivery-router-3QFG2ZEX.js");
|
|
8532
|
+
registerMindDir(SPIRIT_NAME, spiritEntry.dir);
|
|
8533
|
+
}
|
|
8392
8534
|
await syncSpiritTemplate();
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
await startSpiritFull("volute");
|
|
8535
|
+
if (spiritEntry && !manager.isRunning(SPIRIT_NAME)) {
|
|
8536
|
+
await startSpiritFull(SPIRIT_NAME);
|
|
8396
8537
|
}
|
|
8397
8538
|
}
|
|
8398
8539
|
} catch (err) {
|
|
@@ -8404,7 +8545,7 @@ async function startDaemon(opts) {
|
|
|
8404
8545
|
bridgeManager.startBridges(daemonPort).catch((err) => {
|
|
8405
8546
|
logger_default.warn("failed to start bridges", logger_default.errorData(err));
|
|
8406
8547
|
});
|
|
8407
|
-
import("./cloud-sync-
|
|
8548
|
+
import("./cloud-sync-LQTVDTQ3.js").then(
|
|
8408
8549
|
({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
|
|
8409
8550
|
logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
|
|
8410
8551
|
})
|
|
@@ -8412,8 +8553,10 @@ async function startDaemon(opts) {
|
|
|
8412
8553
|
logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
|
|
8413
8554
|
});
|
|
8414
8555
|
try {
|
|
8415
|
-
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-
|
|
8416
|
-
backfillTemplateHashes()
|
|
8556
|
+
const { backfillTemplateHashes, notifyVersionUpdate, warnStaleTemplates } = await import("./version-notify-XRGTEEDK.js");
|
|
8557
|
+
backfillTemplateHashes().then(() => warnStaleTemplates()).catch((err) => {
|
|
8558
|
+
logger_default.warn("failed to check template staleness", logger_default.errorData(err));
|
|
8559
|
+
});
|
|
8417
8560
|
notifyVersionUpdate().catch((err) => {
|
|
8418
8561
|
logger_default.warn("failed to send version update notifications", logger_default.errorData(err));
|
|
8419
8562
|
});
|
|
@@ -8430,6 +8573,7 @@ async function startDaemon(opts) {
|
|
|
8430
8573
|
cleanExpiredLogs().catch((err) => {
|
|
8431
8574
|
logger_default.warn("failed to clean expired logs", logger_default.errorData(err));
|
|
8432
8575
|
});
|
|
8576
|
+
const maintenanceInterval = startMaintenanceInterval();
|
|
8433
8577
|
setProviderRefreshHook((provider) => {
|
|
8434
8578
|
void syncProviderToMinds(provider, {
|
|
8435
8579
|
listRunning: () => getMindManager().getRunningMinds()
|
|
@@ -8482,6 +8626,7 @@ async function startDaemon(opts) {
|
|
|
8482
8626
|
safe("summarizer.stop", () => summarizer.stop());
|
|
8483
8627
|
safe("backupManager.stop", () => backupManager2.stop());
|
|
8484
8628
|
safe("stopApiKeyRefresh", stopApiKeyRefresh);
|
|
8629
|
+
safe("maintenanceInterval", () => clearInterval(maintenanceInterval));
|
|
8485
8630
|
safe("delivery.dispose", () => delivery.dispose());
|
|
8486
8631
|
await safe("bridgeManager.stopAll", () => bridgeManager.stopAll());
|
|
8487
8632
|
await safe("manager.stopAll", () => manager.stopAll());
|