volute 0.45.1 → 0.46.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 +3 -3
- package/dist/{activity-events-OMCSM7XW.js → activity-events-NF6VWTJQ.js} +2 -2
- package/dist/{ai-service-534WUSDL.js → ai-service-UODCCE4O.js} +3 -3
- package/dist/{archive-6R4TZMYI.js → archive-WS2L2VIQ.js} +2 -2
- package/dist/{auth-FRZJVQCS.js → auth-CCFAU4GQ.js} +3 -3
- package/dist/{avatar-image-BNWEXSA2.js → avatar-image-6KY6UU4D.js} +3 -3
- package/dist/{backup-OZXHL3JS.js → backup-TST5C2YN.js} +7 -7
- package/dist/{chat-I4EDDIQC.js → chat-ZIQQS25U.js} +2 -2
- package/dist/{chunk-ZIR7HSAX.js → chunk-4JOQZPCE.js} +1 -1
- package/dist/chunk-4YU7HF4L.js +237 -0
- package/dist/{chunk-JSRMEY52.js → chunk-5ZQZDDIK.js} +10 -5
- package/dist/{chunk-2BONPXAF.js → chunk-6EMWJZBK.js} +1 -1
- package/dist/{chunk-LAXUUY7O.js → chunk-A7WQZKOU.js} +2 -2
- package/dist/{chunk-H7IYFRAL.js → chunk-ALKYQULU.js} +10 -5
- package/dist/{chunk-5AUKCNPE.js → chunk-BJZ4PV7R.js} +8 -8
- package/dist/{chunk-KP3KWNG6.js → chunk-CDPBTTZO.js} +2 -2
- package/dist/{chunk-SQL7M4HJ.js → chunk-DRJ24GXK.js} +2 -2
- package/dist/{chunk-77BVGCTZ.js → chunk-E3DA4HYV.js} +9 -9
- package/dist/{chunk-322KE457.js → chunk-F7H6ATM4.js} +1 -1
- package/dist/{chunk-KVKP6VQ5.js → chunk-FXORA5JG.js} +12 -3
- package/dist/{chunk-3ERIL673.js → chunk-H2X54EHC.js} +1 -1
- package/dist/{chunk-TSK5PI4L.js → chunk-IHKGWTGT.js} +1 -1
- package/dist/{chunk-U4FNXDEJ.js → chunk-JO5IO4FH.js} +422 -168
- package/dist/{chunk-OXXTPILE.js → chunk-JZ62SYWR.js} +1 -1
- package/dist/{chunk-IUXTYXFI.js → chunk-K6T43YBD.js} +3 -3
- package/dist/{chunk-Y6OPHHGM.js → chunk-KGIXX4NM.js} +4 -4
- package/dist/{chunk-HVU45COX.js → chunk-KQSFTPIM.js} +1 -1
- package/dist/{chunk-CYI534DJ.js → chunk-OV7ZQ2GH.js} +2 -2
- package/dist/{chunk-CU6OFXMM.js → chunk-PFZBNKUH.js} +9 -0
- package/dist/{clock-K43IMROX.js → chunk-PJ45FQPT.js} +21 -16
- package/dist/{chunk-QMJJWTNL.js → chunk-QCN24XEN.js} +1 -1
- package/dist/{chunk-UMI4UIJG.js → chunk-R77O2WMK.js} +1 -1
- package/dist/{chunk-IEWZ7VD7.js → chunk-RRNXJOKB.js} +2 -2
- package/dist/{chunk-FHWUQZXE.js → chunk-RXEEYDIB.js} +1 -1
- package/dist/{chunk-Q2XBKQ2D.js → chunk-TQJ6ZYVY.js} +2 -2
- package/dist/{chunk-V4GYPD5L.js → chunk-YXSUMLTC.js} +46 -269
- package/dist/{chunk-5GT7URXJ.js → chunk-ZDZISKCL.js} +1 -1
- package/dist/{chunk-ZMIMSIIT.js → chunk-ZNMCCHCP.js} +48 -2
- package/dist/cli.js +20 -20
- package/dist/clock-RHS2JEDL.js +16 -0
- package/dist/{cloud-sync-Y7LQPRE3.js → cloud-sync-46RS4SDA.js} +17 -16
- package/dist/{conversations-G4LYMHAA.js → conversations-CJOOCGNW.js} +3 -3
- package/dist/{create-2YY7IPMS.js → create-IOV4GCRX.js} +1 -1
- package/dist/{daemon-restart-ABP54YN6.js → daemon-restart-VFEI57UO.js} +6 -6
- package/dist/daemon.js +392 -270
- package/dist/{db-JFLCJCUG.js → db-MF2JNRUW.js} +1 -1
- package/dist/{delete-BFMIGAIB.js → delete-HPLC7ETU.js} +1 -1
- package/dist/delivery-manager-JINZRG2W.js +33 -0
- package/dist/{delivery-router-6DE3BPHO.js → delivery-router-N4A7ZC5T.js} +2 -2
- package/dist/{down-XCAZXWLB.js → down-U2CZ23M4.js} +4 -4
- package/dist/echo-text-VQPB5L2X.js +33 -0
- package/dist/{exec-4GWHAHS3.js → exec-G3ZRST4Z.js} +2 -2
- package/dist/{export-ID7YUSLZ.js → export-LY723I3Z.js} +5 -5
- package/dist/{extensions-AYSPKE33.js → extensions-ZELQLTSR.js} +17 -16
- package/dist/{files-BQ2WB5KC.js → files-4LN3EN7Q.js} +2 -2
- package/dist/{import-SKID37QX.js → import-42YNQBF4.js} +5 -5
- package/dist/{isolation-5MB3J73F.js → isolation-YMGZZ4E5.js} +2 -2
- package/dist/{join-RXPXGV4L.js → join-ZJV7W6MO.js} +4 -0
- package/dist/{login-LM4NF4ZB.js → login-M6OJUPQ2.js} +1 -1
- package/dist/{logout-CTJVIZGA.js → logout-WQBWO77G.js} +1 -1
- package/dist/message-delivery-R7JSQGYX.js +37 -0
- package/dist/{mind-KLHC7XYR.js → mind-LHKS55DI.js} +12 -12
- package/dist/{mind-activity-tracker-BGHJE7XA.js → mind-activity-tracker-3QRNJVR4.js} +3 -3
- package/dist/mind-service-NB2JMWQZ.js +39 -0
- package/dist/mind-sleep-74TGOQBC.js +83 -0
- package/dist/{package-BMHV7UHN.js → package-DOD6CPO6.js} +2 -1
- package/dist/{registry-NUJAGLQJ.js → registry-OUZBZ3Q4.js} +5 -1
- package/dist/{sandbox-72MWV4JL.js → sandbox-ZJ7QA6Z6.js} +3 -3
- package/dist/scheduler-WVKII3LA.js +31 -0
- package/dist/{seed-4MKQ5QKG.js → seed-CNYIHPOH.js} +1 -1
- package/dist/{seed-cmd-LCXMR7VV.js → seed-cmd-AVNUNLZV.js} +2 -2
- package/dist/{seed-create-N2BF5LQX.js → seed-create-ANXGYSCC.js} +5 -5
- package/dist/{seed-sprout-6ZDP23YI.js → seed-sprout-NIUFTX32.js} +10 -8
- package/dist/{send-O6W53VBM.js → send-SPE6DVNJ.js} +8 -2
- package/dist/{service-AQVPUANO.js → service-UOCLXDWR.js} +3 -3
- package/dist/{service-install-4QNUDKLM.js → service-install-4HHFDDWY.js} +4 -4
- package/dist/{setup-3O6O2JZ7.js → setup-QT2A25SY.js} +6 -6
- package/dist/{setup-73YBJZQL.js → setup-Y2EJI3GG.js} +2 -2
- package/dist/skills/imagegen/scripts/imagegen.ts +100 -40
- package/dist/skills/orientation/SKILL.md +1 -1
- package/dist/skills/volute-mind/SKILL.md +13 -9
- package/dist/skills/volute-mind/references/sleep.md +8 -1
- package/dist/{skills-ND4ZFYUW.js → skills-AKCFA7BN.js} +4 -4
- package/dist/sleep-manager-G6TXSDP7.js +35 -0
- package/dist/{spirit-II3HOERM.js → spirit-RPBLLUQ5.js} +7 -7
- package/dist/{sprout-4KUG76AQ.js → sprout-SMX42ZBP.js} +1 -1
- package/dist/{src-XFY3XDD6.js → src-OJHARHTF.js} +28 -17
- package/dist/{status-E5DQNCAO.js → status-SWRVGXBI.js} +4 -4
- package/dist/system-chat-NDAW6YP7.js +37 -0
- package/dist/{tailscale-QAWVKQKU.js → tailscale-3XOKOW7T.js} +1 -1
- package/dist/{turn-tracker-QQIVVXBI.js → turn-tracker-FOIBNUUA.js} +5 -4
- package/dist/{up-LG56MPBI.js → up-PS6PFS75.js} +5 -5
- package/dist/{update-7TYVH5FM.js → update-SWAYZRWJ.js} +4 -4
- package/dist/{update-check-VSCSJ7KX.js → update-check-PQ2MZ47K.js} +2 -2
- package/dist/{version-notify-CODJOUW2.js → version-notify-C5CH7CVP.js} +24 -19
- package/dist/{volute-config-TS62GS6A.js → volute-config-A52FHWKM.js} +5 -1
- package/dist/web-assets/assets/{index-Dac11sKB.js → index-CU6XWICM.js} +15 -15
- package/dist/web-assets/index.html +1 -1
- package/package.json +2 -1
- package/templates/_base/home/VOLUTE.md +6 -2
- package/templates/_base/src/lib/context-breakdown.ts +57 -67
- package/templates/_base/src/lib/file-handler.ts +3 -3
- package/templates/_base/src/lib/router.ts +21 -25
- package/templates/_base/src/lib/startup.ts +2 -0
- package/templates/_base/src/lib/types.ts +2 -2
- package/templates/_base/src/lib/volute-server.ts +2 -2
- package/templates/claude/src/agent.ts +147 -46
- package/templates/claude/src/lib/message-channel.ts +23 -0
- package/templates/claude/src/lib/session-reaper.ts +68 -0
- package/templates/claude/src/server.ts +1 -0
- package/templates/codex/src/agent.ts +80 -46
- package/templates/pi/src/agent.ts +73 -45
- package/dist/delivery-manager-R5STGLXB.js +0 -32
- package/dist/echo-text-NQXYYYCU.js +0 -32
- package/dist/message-delivery-IUAXRPFE.js +0 -34
- package/dist/mind-service-BF2LUQMH.js +0 -36
- package/dist/mind-sleep-YMBR3I35.js +0 -47
- package/dist/scheduler-YHJRRV6E.js +0 -30
- package/dist/sleep-manager-YAHDOIU5.js +0 -34
- package/dist/system-chat-E65T2HSW.js +0 -34
package/dist/daemon.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
readBackupState,
|
|
7
7
|
resticVersion,
|
|
8
8
|
runBackup
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-FXORA5JG.js";
|
|
10
10
|
import {
|
|
11
11
|
acceptPending,
|
|
12
12
|
formatFileSize,
|
|
@@ -14,25 +14,25 @@ import {
|
|
|
14
14
|
rejectPending,
|
|
15
15
|
stageFile,
|
|
16
16
|
validateFilePath
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-R77O2WMK.js";
|
|
18
18
|
import {
|
|
19
19
|
findOpenClawSession,
|
|
20
20
|
importOpenClawConnectors,
|
|
21
21
|
importPiSession,
|
|
22
22
|
parseNameFromIdentity
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-A7WQZKOU.js";
|
|
24
24
|
import {
|
|
25
25
|
checkForUpdate,
|
|
26
26
|
checkForUpdateCached,
|
|
27
27
|
getCurrentVersion
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-6EMWJZBK.js";
|
|
29
29
|
import {
|
|
30
30
|
normalizeAvatar,
|
|
31
31
|
safeResolveWithinBase
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-DRJ24GXK.js";
|
|
33
33
|
import {
|
|
34
34
|
isHomeOnlyArchive
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-QCN24XEN.js";
|
|
36
36
|
import {
|
|
37
37
|
computeTemplateHash
|
|
38
38
|
} from "./chunk-QMJCNZ6C.js";
|
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
fixModelEscapes,
|
|
43
43
|
getPlatformDriver,
|
|
44
44
|
routeOutboundBridge
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-E3DA4HYV.js";
|
|
46
46
|
import {
|
|
47
47
|
getBridgeConfig,
|
|
48
48
|
readBridgesConfig,
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
resolveChannelMapping,
|
|
52
52
|
setBridgeConfig,
|
|
53
53
|
setChannelMapping
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-RXEEYDIB.js";
|
|
55
55
|
import {
|
|
56
56
|
MindStartupError,
|
|
57
57
|
RestartTracker,
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
ensureSystemChannel,
|
|
72
72
|
formatHoldNotice,
|
|
73
73
|
formatNotices,
|
|
74
|
-
|
|
74
|
+
generateSystemFallbackReply,
|
|
75
75
|
getAllDiscoveredExtensions,
|
|
76
76
|
getAllDiscoveredExtensionsDetailed,
|
|
77
77
|
getDeliveryManager,
|
|
@@ -107,20 +107,21 @@ import {
|
|
|
107
107
|
requireAdminOrSystem,
|
|
108
108
|
requireSelf,
|
|
109
109
|
setExtensionEnabled,
|
|
110
|
+
shouldGenerateSystemFallback,
|
|
110
111
|
startMindFull,
|
|
111
112
|
stopMindFull,
|
|
112
113
|
syncProviderToMinds,
|
|
113
114
|
uninstallNpmExtension,
|
|
114
115
|
writeSystemsConfig
|
|
115
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-JO5IO4FH.js";
|
|
116
117
|
import {
|
|
117
118
|
loadMergedEnv,
|
|
118
119
|
mindEnvPath,
|
|
119
120
|
readEnv,
|
|
120
121
|
sharedEnvPath,
|
|
121
122
|
writeEnv
|
|
122
|
-
} from "./chunk-
|
|
123
|
-
import "./chunk-
|
|
123
|
+
} from "./chunk-ZDZISKCL.js";
|
|
124
|
+
import "./chunk-BJZ4PV7R.js";
|
|
124
125
|
import {
|
|
125
126
|
applyInitFiles,
|
|
126
127
|
applyTemplateHomeFiles,
|
|
@@ -149,7 +150,7 @@ import {
|
|
|
149
150
|
syncBuiltinSkills,
|
|
150
151
|
uninstallSkill,
|
|
151
152
|
updateSkill
|
|
152
|
-
} from "./chunk-
|
|
153
|
+
} from "./chunk-KGIXX4NM.js";
|
|
153
154
|
import {
|
|
154
155
|
addMessage,
|
|
155
156
|
createChannel,
|
|
@@ -177,51 +178,54 @@ import {
|
|
|
177
178
|
listConversationsForUser,
|
|
178
179
|
listConversationsWithParticipants,
|
|
179
180
|
markConversationRead,
|
|
180
|
-
publish,
|
|
181
|
+
publish as publish2,
|
|
181
182
|
setConversationPrivate,
|
|
182
183
|
subscribe as subscribe2,
|
|
183
184
|
updateChannelSettings
|
|
184
|
-
} from "./chunk-
|
|
185
|
+
} from "./chunk-5ZQZDDIK.js";
|
|
185
186
|
import {
|
|
186
187
|
readVoluteConfig,
|
|
187
188
|
writeVoluteConfig
|
|
188
|
-
} from "./chunk-
|
|
189
|
+
} from "./chunk-PFZBNKUH.js";
|
|
189
190
|
import {
|
|
190
191
|
isSandboxEnabled,
|
|
191
192
|
wrapForSandbox
|
|
192
|
-
} from "./chunk-
|
|
193
|
+
} from "./chunk-JZ62SYWR.js";
|
|
193
194
|
import {
|
|
194
195
|
getActiveMinds,
|
|
195
196
|
onMindEvent,
|
|
196
197
|
stopAll
|
|
197
|
-
} from "./chunk-
|
|
198
|
+
} from "./chunk-KQSFTPIM.js";
|
|
198
199
|
import {
|
|
199
200
|
extractTextContent
|
|
200
|
-
} from "./chunk-
|
|
201
|
+
} from "./chunk-4JOQZPCE.js";
|
|
201
202
|
import {
|
|
202
|
-
PROMPT_DEFAULTS,
|
|
203
|
-
PROMPT_KEYS,
|
|
204
203
|
assignSession,
|
|
205
204
|
completeOrphanedTurns,
|
|
206
205
|
completeTurn,
|
|
207
206
|
createTurn,
|
|
208
207
|
getActiveTurnId,
|
|
209
|
-
getMindPromptDefaults,
|
|
210
|
-
getPrompt,
|
|
211
|
-
getPromptIfCustom,
|
|
212
208
|
getToolUseEventId,
|
|
213
209
|
initSummarizer,
|
|
214
210
|
markErrored,
|
|
215
|
-
publish as
|
|
211
|
+
publish as publish3,
|
|
216
212
|
subscribe as subscribe3,
|
|
217
213
|
subscribeAll,
|
|
218
|
-
substitute,
|
|
219
214
|
summarizeOrphanedTurns,
|
|
220
215
|
summarizeTurn,
|
|
221
216
|
takeErrored,
|
|
222
217
|
trackToolUse
|
|
223
|
-
} from "./chunk-
|
|
224
|
-
import
|
|
218
|
+
} from "./chunk-YXSUMLTC.js";
|
|
219
|
+
import {
|
|
220
|
+
ORIENTATION_MARKER,
|
|
221
|
+
PROMPT_DEFAULTS,
|
|
222
|
+
PROMPT_KEYS,
|
|
223
|
+
getMindPromptDefaults,
|
|
224
|
+
getPrompt,
|
|
225
|
+
getPromptIfCustom,
|
|
226
|
+
substitute
|
|
227
|
+
} from "./chunk-4YU7HF4L.js";
|
|
228
|
+
import "./chunk-TQJ6ZYVY.js";
|
|
225
229
|
import {
|
|
226
230
|
chownMindDir,
|
|
227
231
|
createMindUser,
|
|
@@ -232,9 +236,10 @@ import {
|
|
|
232
236
|
isIsolationEnabled,
|
|
233
237
|
resolveVoluteBin,
|
|
234
238
|
wrapForIsolation
|
|
235
|
-
} from "./chunk-
|
|
239
|
+
} from "./chunk-H2X54EHC.js";
|
|
236
240
|
import {
|
|
237
241
|
addCustomModel,
|
|
242
|
+
aiCompleteUtility,
|
|
238
243
|
buildCustomModel,
|
|
239
244
|
getAiConfig,
|
|
240
245
|
getAvailableModels,
|
|
@@ -253,12 +258,12 @@ import {
|
|
|
253
258
|
setProviderRefreshHook,
|
|
254
259
|
setUtilityModel,
|
|
255
260
|
unqualifyModelId
|
|
256
|
-
} from "./chunk-
|
|
261
|
+
} from "./chunk-IHKGWTGT.js";
|
|
257
262
|
import {
|
|
258
263
|
isSetupComplete,
|
|
259
264
|
readGlobalConfig,
|
|
260
265
|
writeGlobalConfig
|
|
261
|
-
} from "./chunk-
|
|
266
|
+
} from "./chunk-F7H6ATM4.js";
|
|
262
267
|
import {
|
|
263
268
|
approveUser,
|
|
264
269
|
changePassword,
|
|
@@ -277,11 +282,14 @@ import {
|
|
|
277
282
|
syncMindProfile,
|
|
278
283
|
updateUserProfile,
|
|
279
284
|
verifyUser
|
|
280
|
-
} from "./chunk-
|
|
285
|
+
} from "./chunk-OV7ZQ2GH.js";
|
|
281
286
|
import {
|
|
282
287
|
broadcast,
|
|
288
|
+
getEventsSince,
|
|
289
|
+
nextEventId,
|
|
290
|
+
publish,
|
|
283
291
|
subscribe
|
|
284
|
-
} from "./chunk-
|
|
292
|
+
} from "./chunk-ZNMCCHCP.js";
|
|
285
293
|
import {
|
|
286
294
|
logBuffer,
|
|
287
295
|
logger_default
|
|
@@ -290,6 +298,7 @@ import {
|
|
|
290
298
|
buildVoluteSlug
|
|
291
299
|
} from "./chunk-LGNUFVMR.js";
|
|
292
300
|
import {
|
|
301
|
+
SPIRIT_NAME,
|
|
293
302
|
addMind,
|
|
294
303
|
addVariant,
|
|
295
304
|
daemonLoopback,
|
|
@@ -305,6 +314,7 @@ import {
|
|
|
305
314
|
readAllMinds,
|
|
306
315
|
readRegistry,
|
|
307
316
|
removeMind,
|
|
317
|
+
resolveMindDir,
|
|
308
318
|
setMindRunning,
|
|
309
319
|
setMindStage,
|
|
310
320
|
setMindTemplate,
|
|
@@ -313,7 +323,7 @@ import {
|
|
|
313
323
|
validateMindName,
|
|
314
324
|
voluteHome,
|
|
315
325
|
voluteSystemDir
|
|
316
|
-
} from "./chunk-
|
|
326
|
+
} from "./chunk-ALKYQULU.js";
|
|
317
327
|
import {
|
|
318
328
|
activity,
|
|
319
329
|
channels,
|
|
@@ -338,9 +348,12 @@ import { format } from "util";
|
|
|
338
348
|
import { CronExpressionParser } from "cron-parser";
|
|
339
349
|
var blog = logger_default.child("backup");
|
|
340
350
|
var DEFAULT_BACKUP_SCHEDULE = "0 3 * * *";
|
|
351
|
+
var NOTIFY_EVERY_N_FAILURES = 5;
|
|
341
352
|
var BackupManager = class {
|
|
342
353
|
interval = null;
|
|
343
|
-
|
|
354
|
+
/** Epoch-ms of the most recent scheduled fire this process has serviced. */
|
|
355
|
+
lastServicedFireMs = -1;
|
|
356
|
+
consecutiveFailures = 0;
|
|
344
357
|
warnedUnconfigured = false;
|
|
345
358
|
start() {
|
|
346
359
|
this.interval = setInterval(() => {
|
|
@@ -352,9 +365,16 @@ var BackupManager = class {
|
|
|
352
365
|
this.interval = null;
|
|
353
366
|
}
|
|
354
367
|
/**
|
|
355
|
-
* True at most once per scheduled fire
|
|
356
|
-
*
|
|
357
|
-
*
|
|
368
|
+
* True at most once per scheduled fire (records the fire it consumed), and
|
|
369
|
+
* only when backups are enabled and runnable. Not a pure predicate — a second
|
|
370
|
+
* call for the same fire returns false.
|
|
371
|
+
*
|
|
372
|
+
* Catch-up: if the machine was asleep or the daemon was down across a
|
|
373
|
+
* scheduled fire (a laptop at 3am), the fire is picked up on the next tick so
|
|
374
|
+
* long as it falls after the last successful run (`lastRun` in
|
|
375
|
+
* backup-state.json). Without an anchor (no successful backup yet) only the
|
|
376
|
+
* exact on-time minute fires, so freshly enabling backups doesn't trigger an
|
|
377
|
+
* immediate run.
|
|
358
378
|
*/
|
|
359
379
|
isDue(now = /* @__PURE__ */ new Date()) {
|
|
360
380
|
const config2 = readGlobalConfig().backup;
|
|
@@ -369,28 +389,82 @@ var BackupManager = class {
|
|
|
369
389
|
this.warnedUnconfigured = false;
|
|
370
390
|
const cron = config2.schedule || DEFAULT_BACKUP_SCHEDULE;
|
|
371
391
|
const epochMinute = Math.floor(now.getTime() / 6e4);
|
|
372
|
-
|
|
373
|
-
let prevMinute;
|
|
392
|
+
let prevFireMs;
|
|
374
393
|
try {
|
|
375
394
|
const interval = CronExpressionParser.parse(cron, { currentDate: now });
|
|
376
|
-
|
|
395
|
+
prevFireMs = interval.prev().toDate().getTime();
|
|
377
396
|
} catch (err) {
|
|
378
397
|
blog.warn(`invalid backup cron "${cron}"`, logger_default.errorData(err));
|
|
379
398
|
return false;
|
|
380
399
|
}
|
|
381
|
-
if (
|
|
382
|
-
|
|
400
|
+
if (prevFireMs <= this.lastServicedFireMs) return false;
|
|
401
|
+
const lastRunMs = this.readLastRunMs();
|
|
402
|
+
if (lastRunMs !== null && prevFireMs <= lastRunMs) return false;
|
|
403
|
+
const onTime = Math.floor(prevFireMs / 6e4) === epochMinute;
|
|
404
|
+
if (!onTime) {
|
|
405
|
+
if (lastRunMs === null) return false;
|
|
406
|
+
blog.warn(
|
|
407
|
+
`missed scheduled backup fire at ${new Date(prevFireMs).toISOString()}; running catch-up`
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
this.lastServicedFireMs = prevFireMs;
|
|
383
411
|
return true;
|
|
384
412
|
}
|
|
413
|
+
readLastRunMs() {
|
|
414
|
+
const lastRun = readBackupState().lastRun;
|
|
415
|
+
if (!lastRun) return null;
|
|
416
|
+
const ms = Date.parse(lastRun);
|
|
417
|
+
return Number.isNaN(ms) ? null : ms;
|
|
418
|
+
}
|
|
385
419
|
async tick() {
|
|
386
420
|
if (!this.isDue()) return;
|
|
387
421
|
blog.info("scheduled backup starting");
|
|
388
422
|
try {
|
|
389
423
|
await runBackup();
|
|
424
|
+
this.recordSuccess();
|
|
390
425
|
} catch (err) {
|
|
391
426
|
blog.error("scheduled backup failed", logger_default.errorData(err));
|
|
427
|
+
await this.recordFailure(err);
|
|
392
428
|
}
|
|
393
429
|
}
|
|
430
|
+
recordSuccess() {
|
|
431
|
+
this.consecutiveFailures = 0;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Track consecutive scheduled-backup failures and actively notify the operator
|
|
435
|
+
* on the 1st and then every Nth. Returns whether it notified (for tests).
|
|
436
|
+
* Notification failures are swallowed — surfacing a backup failure must never
|
|
437
|
+
* take the daemon's backup loop down with it.
|
|
438
|
+
*/
|
|
439
|
+
async recordFailure(err) {
|
|
440
|
+
this.consecutiveFailures += 1;
|
|
441
|
+
const n = this.consecutiveFailures;
|
|
442
|
+
if (n !== 1 && n % NOTIFY_EVERY_N_FAILURES !== 0) return false;
|
|
443
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
444
|
+
const summary = n === 1 ? `Scheduled backup failed: ${reason}` : `Scheduled backup has failed ${n} times in a row: ${reason}`;
|
|
445
|
+
try {
|
|
446
|
+
await publish({
|
|
447
|
+
type: "backup_failed",
|
|
448
|
+
mind: SPIRIT_NAME,
|
|
449
|
+
summary,
|
|
450
|
+
metadata: { consecutiveFailures: n, error: reason }
|
|
451
|
+
});
|
|
452
|
+
} catch (pubErr) {
|
|
453
|
+
blog.error("failed to publish backup-failure activity", logger_default.errorData(pubErr));
|
|
454
|
+
}
|
|
455
|
+
try {
|
|
456
|
+
const { sendSystemMessage } = await import("./system-chat-NDAW6YP7.js");
|
|
457
|
+
await sendSystemMessage(
|
|
458
|
+
SPIRIT_NAME,
|
|
459
|
+
`${summary}
|
|
460
|
+
|
|
461
|
+
Backups are not being saved. Check \`volute backup status\` and the Backups settings tab.`
|
|
462
|
+
);
|
|
463
|
+
} catch (msgErr) {
|
|
464
|
+
blog.error("failed to send backup-failure system message", logger_default.errorData(msgErr));
|
|
465
|
+
}
|
|
466
|
+
return true;
|
|
467
|
+
}
|
|
394
468
|
};
|
|
395
469
|
var backupManager = null;
|
|
396
470
|
function initBackupManager() {
|
|
@@ -725,6 +799,26 @@ async function cleanExpiredLogs() {
|
|
|
725
799
|
await db.delete(mindHistory).where(and(eq(mindHistory.type, "log"), lt(mindHistory.created_at, cutoff)));
|
|
726
800
|
}
|
|
727
801
|
|
|
802
|
+
// packages/daemon/src/lib/daemon/maintenance.ts
|
|
803
|
+
var MAINTENANCE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
804
|
+
async function runMaintenance() {
|
|
805
|
+
try {
|
|
806
|
+
await cleanExpiredSessions();
|
|
807
|
+
} catch (err) {
|
|
808
|
+
logger_default.warn("maintenance: failed to clean expired sessions", logger_default.errorData(err));
|
|
809
|
+
}
|
|
810
|
+
try {
|
|
811
|
+
await cleanExpiredLogs();
|
|
812
|
+
} catch (err) {
|
|
813
|
+
logger_default.warn("maintenance: failed to clean expired logs", logger_default.errorData(err));
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
function startMaintenanceInterval(intervalMs = MAINTENANCE_INTERVAL_MS, task = runMaintenance) {
|
|
817
|
+
const handle = setInterval(() => void task(), intervalMs);
|
|
818
|
+
handle.unref?.();
|
|
819
|
+
return handle;
|
|
820
|
+
}
|
|
821
|
+
|
|
728
822
|
// packages/daemon/src/web/api/system.ts
|
|
729
823
|
import { getOAuthProvider, getOAuthProviders } from "@earendil-works/pi-ai/oauth";
|
|
730
824
|
import { getBuiltinProviders } from "@earendil-works/pi-ai/providers/all";
|
|
@@ -1472,10 +1566,10 @@ function getCachedApiKey(provider) {
|
|
|
1472
1566
|
var keyRefreshTimer = null;
|
|
1473
1567
|
var slog = logger_default.child("ai-keys");
|
|
1474
1568
|
var oauthHealth = /* @__PURE__ */ new Map();
|
|
1475
|
-
function needsRefresh(oauth) {
|
|
1569
|
+
function needsRefresh(oauth, now = Date.now()) {
|
|
1476
1570
|
const expires = oauth.expires;
|
|
1477
|
-
if (!expires ||
|
|
1478
|
-
return expires -
|
|
1571
|
+
if (!expires || now >= expires) return true;
|
|
1572
|
+
return expires - now < 15 * 60 * 1e3;
|
|
1479
1573
|
}
|
|
1480
1574
|
async function refreshApiKeyCache() {
|
|
1481
1575
|
const ai = getAiConfig();
|
|
@@ -1693,17 +1787,17 @@ var authenticated = new Hono3().use(authMiddleware).post("/change-password", zVa
|
|
|
1693
1787
|
if (!AVATAR_MIME[ext]) {
|
|
1694
1788
|
return c.json({ error: "Invalid file type (png, jpg, gif, webp only)" }, 400);
|
|
1695
1789
|
}
|
|
1696
|
-
let
|
|
1790
|
+
let buffer = Buffer.from(await file.arrayBuffer());
|
|
1697
1791
|
let finalExt = ext;
|
|
1698
|
-
const normalized = await normalizeAvatar(
|
|
1792
|
+
const normalized = await normalizeAvatar(buffer);
|
|
1699
1793
|
if (normalized) {
|
|
1700
|
-
|
|
1794
|
+
buffer = normalized.buffer;
|
|
1701
1795
|
finalExt = normalized.ext;
|
|
1702
1796
|
}
|
|
1703
1797
|
const dir = avatarsDir();
|
|
1704
1798
|
mkdirSync2(dir, { recursive: true });
|
|
1705
1799
|
const filename = `avatar-${user.id}${finalExt}`;
|
|
1706
|
-
writeFileSync2(resolve3(dir, filename),
|
|
1800
|
+
writeFileSync2(resolve3(dir, filename), buffer);
|
|
1707
1801
|
if (user.avatar && user.avatar !== filename) {
|
|
1708
1802
|
const oldPath = resolve3(dir, user.avatar);
|
|
1709
1803
|
rmSync(oldPath, { force: true });
|
|
@@ -2165,7 +2259,7 @@ var app4 = new Hono5().post("/:platform/inbound", zValidator4("json", inboundSch
|
|
|
2165
2259
|
}
|
|
2166
2260
|
const participants = await getParticipants(channel.id);
|
|
2167
2261
|
if (!participants.some((p) => p.userId === puppet.id)) {
|
|
2168
|
-
const { addParticipant } = await import("./conversations-
|
|
2262
|
+
const { addParticipant } = await import("./conversations-CJOOCGNW.js");
|
|
2169
2263
|
await addParticipant(channel.id, puppet.id);
|
|
2170
2264
|
}
|
|
2171
2265
|
const contentBlocks = body.content;
|
|
@@ -2449,7 +2543,7 @@ async function notifyMind(mindName, message) {
|
|
|
2449
2543
|
const entry = await findMind(mindName);
|
|
2450
2544
|
if (!entry) return;
|
|
2451
2545
|
try {
|
|
2452
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
2546
|
+
const { sendSystemMessage } = await import("./system-chat-NDAW6YP7.js");
|
|
2453
2547
|
await sendSystemMessage(mindName, message);
|
|
2454
2548
|
} catch (err) {
|
|
2455
2549
|
logger_default.warn(`[file-sharing] notify mind ${mindName} failed`, logger_default.errorData(err));
|
|
@@ -2618,11 +2712,11 @@ var app9 = new Hono11().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
2618
2712
|
if (!AVATAR_MIME2[ext]) {
|
|
2619
2713
|
return c.json({ error: "Invalid file type (png, jpg, gif, webp only)" }, 400);
|
|
2620
2714
|
}
|
|
2621
|
-
let
|
|
2715
|
+
let buffer = Buffer.from(await file.arrayBuffer());
|
|
2622
2716
|
let finalExt = ext;
|
|
2623
|
-
const normalized = await normalizeAvatar(
|
|
2717
|
+
const normalized = await normalizeAvatar(buffer);
|
|
2624
2718
|
if (normalized) {
|
|
2625
|
-
|
|
2719
|
+
buffer = normalized.buffer;
|
|
2626
2720
|
finalExt = normalized.ext;
|
|
2627
2721
|
}
|
|
2628
2722
|
const dir = entry.dir ?? mindDir(name);
|
|
@@ -2636,7 +2730,7 @@ var app9 = new Hono11().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
2636
2730
|
if (oldAvatarPath) rmSync2(oldAvatarPath, { force: true });
|
|
2637
2731
|
}
|
|
2638
2732
|
mkdirSync3(homeDir, { recursive: true });
|
|
2639
|
-
writeFileSync3(avatarPath,
|
|
2733
|
+
writeFileSync3(avatarPath, buffer);
|
|
2640
2734
|
const profile = config2.profile ?? {};
|
|
2641
2735
|
profile.avatar = filename;
|
|
2642
2736
|
config2.profile = profile;
|
|
@@ -3301,6 +3395,7 @@ var app12 = new Hono15().get("/:name/skills", async (c) => {
|
|
|
3301
3395
|
const dir = entry.dir ?? mindDir(name);
|
|
3302
3396
|
try {
|
|
3303
3397
|
const result = await installSkill(name, dir, skillId);
|
|
3398
|
+
await chownMindDir(dir, name);
|
|
3304
3399
|
return c.json({ ok: true, ...result });
|
|
3305
3400
|
} catch (e) {
|
|
3306
3401
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -3319,6 +3414,7 @@ var app12 = new Hono15().get("/:name/skills", async (c) => {
|
|
|
3319
3414
|
const dir = entry.dir ?? mindDir(name);
|
|
3320
3415
|
try {
|
|
3321
3416
|
const result = await updateSkill(name, dir, skillId);
|
|
3417
|
+
await chownMindDir(dir, name);
|
|
3322
3418
|
return c.json(result);
|
|
3323
3419
|
} catch (e) {
|
|
3324
3420
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -3351,6 +3447,7 @@ var app12 = new Hono15().get("/:name/skills", async (c) => {
|
|
|
3351
3447
|
const dir = entry.dir ?? mindDir(name);
|
|
3352
3448
|
try {
|
|
3353
3449
|
await uninstallSkill(name, dir, skillName);
|
|
3450
|
+
await chownMindDir(dir, name);
|
|
3354
3451
|
} catch (e) {
|
|
3355
3452
|
const msg = e instanceof Error ? e.message : String(e);
|
|
3356
3453
|
return c.json({ error: msg }, 400);
|
|
@@ -3462,7 +3559,7 @@ async function handleMindEvent(mind, event) {
|
|
|
3462
3559
|
if (!turnId) {
|
|
3463
3560
|
llog.warn(`skipping turn tracking for ${mind}: createTurn failed`);
|
|
3464
3561
|
} else {
|
|
3465
|
-
|
|
3562
|
+
publish3(mind, { mind, type: "turn_created", turnId });
|
|
3466
3563
|
if (event.session) await assignSession(mind, turnId, event.session);
|
|
3467
3564
|
try {
|
|
3468
3565
|
await linkPendingInbound(mind, turnId, event.channel);
|
|
@@ -3508,7 +3605,7 @@ async function handleMindEvent(mind, event) {
|
|
|
3508
3605
|
llog.error("failed to link tool_result to turn", logger_default.errorData(err));
|
|
3509
3606
|
}
|
|
3510
3607
|
}
|
|
3511
|
-
|
|
3608
|
+
publish3(mind, {
|
|
3512
3609
|
mind,
|
|
3513
3610
|
type: event.type,
|
|
3514
3611
|
session: event.session,
|
|
@@ -3595,35 +3692,50 @@ async function completeTurnAndSummarize(mind, event, insertedId) {
|
|
|
3595
3692
|
// packages/daemon/src/lib/mind/consolidate.ts
|
|
3596
3693
|
import { readdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
3597
3694
|
import { resolve as resolve8 } from "path";
|
|
3598
|
-
|
|
3695
|
+
var cLog = logger_default.child("consolidate");
|
|
3696
|
+
var MAX_CONSOLIDATION_INPUT_CHARS = 2e5;
|
|
3697
|
+
function readDailyLogs(memoryDir) {
|
|
3698
|
+
let files;
|
|
3699
|
+
try {
|
|
3700
|
+
files = readdirSync(memoryDir).filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)).sort();
|
|
3701
|
+
} catch {
|
|
3702
|
+
return [];
|
|
3703
|
+
}
|
|
3704
|
+
const logs = [];
|
|
3705
|
+
for (const filename of files) {
|
|
3706
|
+
const date = filename.replace(".md", "");
|
|
3707
|
+
const content = readFileSync6(resolve8(memoryDir, filename), "utf-8").trim();
|
|
3708
|
+
if (content) logs.push(`### ${date}
|
|
3709
|
+
|
|
3710
|
+
${content}`);
|
|
3711
|
+
}
|
|
3712
|
+
return logs;
|
|
3713
|
+
}
|
|
3714
|
+
function boundLogText(logs, maxChars = MAX_CONSOLIDATION_INPUT_CHARS) {
|
|
3715
|
+
const kept = [];
|
|
3716
|
+
let total = 0;
|
|
3717
|
+
for (let i = logs.length - 1; i >= 0; i--) {
|
|
3718
|
+
const len = logs[i].length + (kept.length > 0 ? 2 : 0);
|
|
3719
|
+
if (total + len > maxChars) break;
|
|
3720
|
+
kept.unshift(logs[i]);
|
|
3721
|
+
total += len;
|
|
3722
|
+
}
|
|
3723
|
+
if (kept.length === 0 && logs.length > 0) {
|
|
3724
|
+
return logs[logs.length - 1].slice(-maxChars);
|
|
3725
|
+
}
|
|
3726
|
+
return kept.join("\n\n");
|
|
3727
|
+
}
|
|
3728
|
+
async function consolidateMemory(mindDir2, complete = aiCompleteUtility) {
|
|
3599
3729
|
const soulPath = resolve8(mindDir2, "home/SOUL.md");
|
|
3600
3730
|
const memoryPath = resolve8(mindDir2, "home/MEMORY.md");
|
|
3601
3731
|
const memoryDir = resolve8(mindDir2, "home/memory");
|
|
3602
3732
|
const soul = readFileSync6(soulPath, "utf-8");
|
|
3603
|
-
const logs =
|
|
3604
|
-
try {
|
|
3605
|
-
const files = readdirSync(memoryDir).filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)).sort();
|
|
3606
|
-
for (const filename of files) {
|
|
3607
|
-
const date = filename.replace(".md", "");
|
|
3608
|
-
const content2 = readFileSync6(resolve8(memoryDir, filename), "utf-8").trim();
|
|
3609
|
-
if (content2) {
|
|
3610
|
-
logs.push(`### ${date}
|
|
3611
|
-
|
|
3612
|
-
${content2}`);
|
|
3613
|
-
}
|
|
3614
|
-
}
|
|
3615
|
-
} catch {
|
|
3616
|
-
}
|
|
3733
|
+
const logs = readDailyLogs(memoryDir);
|
|
3617
3734
|
if (logs.length === 0) {
|
|
3618
|
-
|
|
3735
|
+
cLog.info("No daily logs found; skipping memory consolidation.");
|
|
3619
3736
|
return;
|
|
3620
3737
|
}
|
|
3621
|
-
|
|
3622
|
-
if (!apiKey) {
|
|
3623
|
-
console.error("ANTHROPIC_API_KEY not set, skipping memory consolidation.");
|
|
3624
|
-
return;
|
|
3625
|
-
}
|
|
3626
|
-
console.log("Consolidating memory from daily logs...");
|
|
3738
|
+
cLog.info("Consolidating memory from daily logs...");
|
|
3627
3739
|
const userMessage = [
|
|
3628
3740
|
"You have daily logs from a previous environment but no long-term memory file yet.",
|
|
3629
3741
|
"Please review the daily logs below and produce consolidated MEMORY.md content.",
|
|
@@ -3631,35 +3743,15 @@ ${content2}`);
|
|
|
3631
3743
|
"",
|
|
3632
3744
|
"## Daily logs",
|
|
3633
3745
|
"",
|
|
3634
|
-
logs
|
|
3746
|
+
boundLogText(logs)
|
|
3635
3747
|
].join("\n");
|
|
3636
|
-
const
|
|
3637
|
-
method: "POST",
|
|
3638
|
-
headers: {
|
|
3639
|
-
"Content-Type": "application/json",
|
|
3640
|
-
"x-api-key": apiKey,
|
|
3641
|
-
"anthropic-version": "2023-06-01"
|
|
3642
|
-
},
|
|
3643
|
-
body: JSON.stringify({
|
|
3644
|
-
model: "claude-sonnet-4-20250514",
|
|
3645
|
-
max_tokens: 4096,
|
|
3646
|
-
system: soul,
|
|
3647
|
-
messages: [{ role: "user", content: userMessage }]
|
|
3648
|
-
})
|
|
3649
|
-
});
|
|
3650
|
-
if (!res.ok) {
|
|
3651
|
-
const body = await res.text();
|
|
3652
|
-
console.error(`Anthropic API error (${res.status}): ${body}`);
|
|
3653
|
-
return;
|
|
3654
|
-
}
|
|
3655
|
-
const data = await res.json();
|
|
3656
|
-
const content = data.content.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("").trim();
|
|
3748
|
+
const content = (await complete(soul, userMessage))?.trim();
|
|
3657
3749
|
if (content) {
|
|
3658
3750
|
writeFileSync5(memoryPath, `${content}
|
|
3659
3751
|
`);
|
|
3660
|
-
|
|
3752
|
+
cLog.info("MEMORY.md created successfully.");
|
|
3661
3753
|
} else {
|
|
3662
|
-
|
|
3754
|
+
cLog.warn("No content produced; skipping memory consolidation.");
|
|
3663
3755
|
}
|
|
3664
3756
|
}
|
|
3665
3757
|
|
|
@@ -3706,7 +3798,7 @@ async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
|
|
|
3706
3798
|
logger_default.warn(`failed to stop variant ${variantName}`, logger_default.errorData(err));
|
|
3707
3799
|
}
|
|
3708
3800
|
}
|
|
3709
|
-
const { findMind: findMind2 } = await import("./registry-
|
|
3801
|
+
const { findMind: findMind2 } = await import("./registry-OUZBZ3Q4.js");
|
|
3710
3802
|
const variantEntry = await findMind2(variantName);
|
|
3711
3803
|
const branchName = variantEntry?.branch ?? variantName;
|
|
3712
3804
|
if (existsSync6(variantPath)) {
|
|
@@ -3935,7 +4027,7 @@ async function getMindStatus(name, port, registryRunning) {
|
|
|
3935
4027
|
const manager = getMindManager();
|
|
3936
4028
|
let status = "stopped";
|
|
3937
4029
|
try {
|
|
3938
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4030
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-G6TXSDP7.js");
|
|
3939
4031
|
if (getSleepManagerIfReady2()?.isSleeping(name)) {
|
|
3940
4032
|
status = "sleeping";
|
|
3941
4033
|
}
|
|
@@ -4430,7 +4522,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
4430
4522
|
applyInitFiles(dest);
|
|
4431
4523
|
const { publicKeyPem } = generateIdentity(dest);
|
|
4432
4524
|
{
|
|
4433
|
-
const { readGlobalConfig: readGlobal } = await import("./setup-
|
|
4525
|
+
const { readGlobalConfig: readGlobal } = await import("./setup-Y2EJI3GG.js");
|
|
4434
4526
|
const mindDefaults = readGlobal().mindDefaults;
|
|
4435
4527
|
const config2 = readVoluteConfig(dest);
|
|
4436
4528
|
if (!config2) throw new Error("Failed to read volute.json after identity generation");
|
|
@@ -4510,10 +4602,9 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
4510
4602
|
rmSync4(resolve10(dest, ".git"), { recursive: true, force: true });
|
|
4511
4603
|
gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
|
|
4512
4604
|
}
|
|
4513
|
-
await chownMindDir(dest, name);
|
|
4514
4605
|
if (body.stage === "seed") {
|
|
4515
4606
|
const descLine = body.description ? `
|
|
4516
|
-
|
|
4607
|
+
Your creator described you as: "${body.description}"
|
|
4517
4608
|
` : "";
|
|
4518
4609
|
const seedSoulRaw = body.seedSoul ?? await getPrompt("seed_soul", { name, description: descLine });
|
|
4519
4610
|
const seedSoul = body.seedSoul ? substitute(seedSoulRaw, { name, description: descLine }) : seedSoulRaw;
|
|
@@ -4521,7 +4612,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4521
4612
|
}
|
|
4522
4613
|
let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
|
|
4523
4614
|
if (body.stage === "seed" && !body.skills) {
|
|
4524
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
4615
|
+
const { isImagegenEnabled } = await import("./setup-Y2EJI3GG.js");
|
|
4525
4616
|
if (isImagegenEnabled()) {
|
|
4526
4617
|
skillSet = [...skillSet, "imagegen"];
|
|
4527
4618
|
}
|
|
@@ -4539,7 +4630,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4539
4630
|
try {
|
|
4540
4631
|
const spiritEntry = await findMind("volute");
|
|
4541
4632
|
if (spiritEntry) {
|
|
4542
|
-
const { spiritDir } = await import("./spirit-
|
|
4633
|
+
const { spiritDir } = await import("./spirit-RPBLLUQ5.js");
|
|
4543
4634
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
4544
4635
|
const spiritConfig = readVoluteConfig(sDir) ?? {};
|
|
4545
4636
|
const schedules = spiritConfig.schedules ?? [];
|
|
@@ -4554,7 +4645,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4554
4645
|
});
|
|
4555
4646
|
spiritConfig.schedules = schedules;
|
|
4556
4647
|
writeVoluteConfig(sDir, spiritConfig);
|
|
4557
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
4648
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-WVKII3LA.js");
|
|
4558
4649
|
getScheduler2().loadSchedules("volute", sDir);
|
|
4559
4650
|
}
|
|
4560
4651
|
}
|
|
@@ -4572,6 +4663,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4572
4663
|
writeFileSync7(resolve10(dest, "home/MEMORY.md"), customMemory);
|
|
4573
4664
|
}
|
|
4574
4665
|
}
|
|
4666
|
+
await chownMindDir(dest, name);
|
|
4575
4667
|
publishPublicKey(name, publicKeyPem).catch(
|
|
4576
4668
|
(err) => logger_default.warn(`failed to publish key for ${name}`, { error: err.message })
|
|
4577
4669
|
);
|
|
@@ -4819,7 +4911,7 @@ ${user.trimEnd()}
|
|
|
4819
4911
|
const manager = getMindManager();
|
|
4820
4912
|
try {
|
|
4821
4913
|
if (context?.type === "reload") {
|
|
4822
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4914
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-G6TXSDP7.js");
|
|
4823
4915
|
const sleepState = getSleepManagerIfReady2()?.getState(name);
|
|
4824
4916
|
if (sleepState?.sleeping) {
|
|
4825
4917
|
logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
|
|
@@ -4946,7 +5038,7 @@ ${user.trimEnd()}
|
|
|
4946
5038
|
const name = c.req.param("name");
|
|
4947
5039
|
const entry = await findMind(name);
|
|
4948
5040
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4949
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5041
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-G6TXSDP7.js");
|
|
4950
5042
|
const sm = getSleepManagerIfReady2();
|
|
4951
5043
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4952
5044
|
return c.json(sm.getState(name));
|
|
@@ -4954,7 +5046,7 @@ ${user.trimEnd()}
|
|
|
4954
5046
|
const name = c.req.param("name");
|
|
4955
5047
|
const entry = await findMind(name);
|
|
4956
5048
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4957
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5049
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-G6TXSDP7.js");
|
|
4958
5050
|
const sm = getSleepManagerIfReady2();
|
|
4959
5051
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4960
5052
|
if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
|
|
@@ -4974,7 +5066,7 @@ ${user.trimEnd()}
|
|
|
4974
5066
|
const name = c.req.param("name");
|
|
4975
5067
|
const entry = await findMind(name);
|
|
4976
5068
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4977
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5069
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-G6TXSDP7.js");
|
|
4978
5070
|
const sm = getSleepManagerIfReady2();
|
|
4979
5071
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4980
5072
|
const sleepState = sm.getState(name);
|
|
@@ -4989,7 +5081,7 @@ ${user.trimEnd()}
|
|
|
4989
5081
|
const name = c.req.param("name");
|
|
4990
5082
|
const entry = await findMind(name);
|
|
4991
5083
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4992
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5084
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-G6TXSDP7.js");
|
|
4993
5085
|
const sm = getSleepManagerIfReady2();
|
|
4994
5086
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4995
5087
|
const flushed = await sm.flushQueuedMessages(name);
|
|
@@ -5017,7 +5109,7 @@ ${user.trimEnd()}
|
|
|
5017
5109
|
}
|
|
5018
5110
|
config2.profile = profile;
|
|
5019
5111
|
writeVoluteConfig(dir, config2);
|
|
5020
|
-
const { syncMindProfile: syncMindProfile2 } = await import("./auth-
|
|
5112
|
+
const { syncMindProfile: syncMindProfile2 } = await import("./auth-CCFAU4GQ.js");
|
|
5021
5113
|
await syncMindProfile2(name, profile);
|
|
5022
5114
|
broadcast({ type: "profile_updated", mind: name, summary: `${name} profile updated` });
|
|
5023
5115
|
return c.json({ ok: true });
|
|
@@ -5027,7 +5119,6 @@ ${user.trimEnd()}
|
|
|
5027
5119
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5028
5120
|
if (entry.stage !== "seed") return c.json({ output: "" });
|
|
5029
5121
|
const db = await getDb();
|
|
5030
|
-
const ORIENTATION_MARKER = "You don't have a soul yet";
|
|
5031
5122
|
const rawCreator = Number(process.env.VOLUTE_NURTURE_CREATOR_MINUTES);
|
|
5032
5123
|
const creatorThreshold = Number.isNaN(rawCreator) ? 5 : rawCreator;
|
|
5033
5124
|
const rawSpirit = Number(process.env.VOLUTE_NURTURE_SPIRIT_MINUTES);
|
|
@@ -5064,7 +5155,7 @@ ${user.trimEnd()}
|
|
|
5064
5155
|
const config2 = readVoluteConfig(dir);
|
|
5065
5156
|
const displayNameSet = !!config2?.profile?.displayName;
|
|
5066
5157
|
const avatarSet = !!config2?.profile?.avatar;
|
|
5067
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
5158
|
+
const { isImagegenEnabled } = await import("./setup-Y2EJI3GG.js");
|
|
5068
5159
|
const imagegenEnabled = isImagegenEnabled();
|
|
5069
5160
|
const done = [];
|
|
5070
5161
|
const remaining = [];
|
|
@@ -5102,7 +5193,7 @@ ${user.trimEnd()}
|
|
|
5102
5193
|
try {
|
|
5103
5194
|
const spiritEntry = await findMind("volute");
|
|
5104
5195
|
if (spiritEntry) {
|
|
5105
|
-
const { spiritDir } = await import("./spirit-
|
|
5196
|
+
const { spiritDir } = await import("./spirit-RPBLLUQ5.js");
|
|
5106
5197
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
5107
5198
|
const spiritConfig = readVoluteConfig(sDir);
|
|
5108
5199
|
if (spiritConfig?.schedules) {
|
|
@@ -5110,7 +5201,7 @@ ${user.trimEnd()}
|
|
|
5110
5201
|
spiritConfig.schedules = spiritConfig.schedules.filter((s) => s.id !== nurtureId);
|
|
5111
5202
|
if (spiritConfig.schedules.length === 0) spiritConfig.schedules = void 0;
|
|
5112
5203
|
writeVoluteConfig(sDir, spiritConfig);
|
|
5113
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
5204
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-WVKII3LA.js");
|
|
5114
5205
|
getScheduler2().loadSchedules("volute", sDir);
|
|
5115
5206
|
}
|
|
5116
5207
|
}
|
|
@@ -5545,7 +5636,7 @@ ${user.trimEnd()}
|
|
|
5545
5636
|
}
|
|
5546
5637
|
writeVoluteConfig(dir, existing);
|
|
5547
5638
|
if (body.unescapeNewlines !== void 0) {
|
|
5548
|
-
const { clearEchoTextCache } = await import("./echo-text-
|
|
5639
|
+
const { clearEchoTextCache } = await import("./echo-text-VQPB5L2X.js");
|
|
5549
5640
|
clearEchoTextCache(name);
|
|
5550
5641
|
}
|
|
5551
5642
|
const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.maxThinkingTokens !== void 0 || body.compaction !== void 0;
|
|
@@ -5622,7 +5713,7 @@ ${user.trimEnd()}
|
|
|
5622
5713
|
}
|
|
5623
5714
|
if (entry.mindType === "spirit" && body.model !== void 0) {
|
|
5624
5715
|
try {
|
|
5625
|
-
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-
|
|
5716
|
+
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-Y2EJI3GG.js");
|
|
5626
5717
|
const globalConfig = readGlobalConfig2();
|
|
5627
5718
|
globalConfig.spiritModel = body.model;
|
|
5628
5719
|
writeGlobalConfig2(globalConfig);
|
|
@@ -5650,7 +5741,7 @@ ${user.trimEnd()}
|
|
|
5650
5741
|
if (!body.systemPrompt || !body.message) {
|
|
5651
5742
|
return c.json({ error: "systemPrompt and message required" }, 400);
|
|
5652
5743
|
}
|
|
5653
|
-
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-
|
|
5744
|
+
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-UODCCE4O.js");
|
|
5654
5745
|
if (!isAiConfigured()) {
|
|
5655
5746
|
return c.json({ error: "AI service not configured" }, 503);
|
|
5656
5747
|
}
|
|
@@ -5999,76 +6090,93 @@ var slog2 = logger_default.child("schedules");
|
|
|
5999
6090
|
function readSchedules(dir) {
|
|
6000
6091
|
return readVoluteConfig(dir)?.schedules ?? [];
|
|
6001
6092
|
}
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
config2.schedules = schedules.length > 0 ? schedules : void 0;
|
|
6005
|
-
writeVoluteConfig(dir, config2);
|
|
6006
|
-
getScheduler().loadSchedules(name, dir);
|
|
6007
|
-
getSleepManagerIfReady()?.invalidateSleepConfig(name);
|
|
6008
|
-
fireWebhook({
|
|
6009
|
-
event: "schedule_changed",
|
|
6010
|
-
mind: name,
|
|
6011
|
-
data: { schedules }
|
|
6012
|
-
});
|
|
6013
|
-
}
|
|
6014
|
-
var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) => {
|
|
6015
|
-
const name = c.req.param("name");
|
|
6016
|
-
const entry = await findMind(name);
|
|
6017
|
-
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
6018
|
-
const dir = entry.dir ?? mindDir(name);
|
|
6019
|
-
const sleepManager = getSleepManagerIfReady();
|
|
6020
|
-
const sleepState = sleepManager?.getState(name) ?? null;
|
|
6021
|
-
const sleepConfig = sleepManager?.getSleepConfig(name) ?? null;
|
|
6022
|
-
const schedules = readSchedules(dir);
|
|
6023
|
-
const now = /* @__PURE__ */ new Date();
|
|
6093
|
+
var UPCOMING_HORIZON_MS = 24 * 60 * 60 * 1e3;
|
|
6094
|
+
function computeClockEvents(schedules, sleepState, sleepConfig, now) {
|
|
6024
6095
|
const upcoming = [];
|
|
6025
6096
|
const previous = [];
|
|
6097
|
+
const effectiveWake = sleepState?.sleeping ? sleepState.scheduledWakeAt ?? sleepState.voluntaryWakeAt : null;
|
|
6098
|
+
const effectiveWakeDate = effectiveWake ? new Date(effectiveWake) : null;
|
|
6099
|
+
const sleepFate = (s, fireDate) => {
|
|
6100
|
+
if (!effectiveWakeDate || fireDate >= effectiveWakeDate) return {};
|
|
6101
|
+
const ws = s.whileSleeping ?? "queue";
|
|
6102
|
+
if (ws === "skip") return { willSkip: true };
|
|
6103
|
+
if (ws === "trigger-wake") return {};
|
|
6104
|
+
return { willQueue: true };
|
|
6105
|
+
};
|
|
6026
6106
|
for (const s of schedules) {
|
|
6027
6107
|
if (!s.enabled) continue;
|
|
6028
6108
|
if (s.fireAt) {
|
|
6029
6109
|
const fireDate = new Date(s.fireAt);
|
|
6030
6110
|
if (fireDate >= now) {
|
|
6031
|
-
upcoming.push({
|
|
6111
|
+
upcoming.push({
|
|
6112
|
+
id: s.id,
|
|
6113
|
+
at: fireDate.toISOString(),
|
|
6114
|
+
type: "timer",
|
|
6115
|
+
...sleepFate(s, fireDate)
|
|
6116
|
+
});
|
|
6032
6117
|
}
|
|
6033
6118
|
} else if (s.cron) {
|
|
6034
6119
|
try {
|
|
6035
|
-
const
|
|
6036
|
-
|
|
6037
|
-
upcoming.push({ id: s.id, at: next.toISOString(), type: "cron" });
|
|
6120
|
+
const next = CronExpressionParser3.parse(s.cron, { currentDate: now }).next().toDate();
|
|
6121
|
+
upcoming.push({ id: s.id, at: next.toISOString(), type: "cron", ...sleepFate(s, next) });
|
|
6038
6122
|
} catch {
|
|
6039
|
-
slog2.warn(`invalid cron "${s.cron}" for schedule "${s.id}"
|
|
6123
|
+
slog2.warn(`invalid cron "${s.cron}" for schedule "${s.id}"`);
|
|
6040
6124
|
}
|
|
6041
6125
|
try {
|
|
6042
|
-
const
|
|
6043
|
-
const prev = prevInterval.prev().toDate();
|
|
6126
|
+
const prev = CronExpressionParser3.parse(s.cron, { currentDate: now }).prev().toDate();
|
|
6044
6127
|
previous.push({ id: s.id, at: prev.toISOString() });
|
|
6045
6128
|
} catch {
|
|
6046
6129
|
}
|
|
6047
6130
|
}
|
|
6048
6131
|
}
|
|
6049
6132
|
if (sleepState?.sleeping) {
|
|
6050
|
-
if (
|
|
6051
|
-
upcoming.push({ id: "
|
|
6133
|
+
if (effectiveWake) {
|
|
6134
|
+
upcoming.push({ id: "wake", at: effectiveWake, type: "cron" });
|
|
6052
6135
|
}
|
|
6053
6136
|
if (sleepState.sleepingSince) {
|
|
6054
6137
|
previous.push({ id: "sleep", at: sleepState.sleepingSince });
|
|
6055
6138
|
}
|
|
6056
6139
|
} else if (sleepConfig?.enabled && sleepConfig.schedule) {
|
|
6057
6140
|
try {
|
|
6058
|
-
const
|
|
6059
|
-
const nextSleep = sleepInterval.next().toDate();
|
|
6141
|
+
const nextSleep = CronExpressionParser3.parse(sleepConfig.schedule.sleep, { currentDate: now }).next().toDate();
|
|
6060
6142
|
upcoming.push({ id: "sleep", at: nextSleep.toISOString(), type: "cron" });
|
|
6061
6143
|
} catch {
|
|
6062
6144
|
}
|
|
6063
6145
|
try {
|
|
6064
|
-
const
|
|
6065
|
-
|
|
6066
|
-
previous.push({ id: "sleep", at: prevWake.toISOString() });
|
|
6146
|
+
const prevWake = CronExpressionParser3.parse(sleepConfig.schedule.wake, { currentDate: now }).prev().toDate();
|
|
6147
|
+
previous.push({ id: "wake", at: prevWake.toISOString() });
|
|
6067
6148
|
} catch {
|
|
6068
6149
|
}
|
|
6069
6150
|
}
|
|
6070
|
-
|
|
6151
|
+
const horizon = now.getTime() + UPCOMING_HORIZON_MS;
|
|
6152
|
+
const withinHorizon = upcoming.filter((e) => new Date(e.at).getTime() <= horizon);
|
|
6153
|
+
withinHorizon.sort((a, b) => a.at.localeCompare(b.at));
|
|
6071
6154
|
previous.sort((a, b) => b.at.localeCompare(a.at));
|
|
6155
|
+
return { upcoming: withinHorizon, previous };
|
|
6156
|
+
}
|
|
6157
|
+
function writeSchedules(name, dir, schedules) {
|
|
6158
|
+
const config2 = readVoluteConfig(dir) ?? {};
|
|
6159
|
+
config2.schedules = schedules.length > 0 ? schedules : void 0;
|
|
6160
|
+
writeVoluteConfig(dir, config2);
|
|
6161
|
+
getScheduler().loadSchedules(name, dir);
|
|
6162
|
+
getSleepManagerIfReady()?.invalidateSleepConfig(name);
|
|
6163
|
+
fireWebhook({
|
|
6164
|
+
event: "schedule_changed",
|
|
6165
|
+
mind: name,
|
|
6166
|
+
data: { schedules }
|
|
6167
|
+
});
|
|
6168
|
+
}
|
|
6169
|
+
var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) => {
|
|
6170
|
+
const name = c.req.param("name");
|
|
6171
|
+
const entry = await findMind(name);
|
|
6172
|
+
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
6173
|
+
const dir = entry.dir ?? mindDir(name);
|
|
6174
|
+
const sleepManager = getSleepManagerIfReady();
|
|
6175
|
+
const sleepState = sleepManager?.getState(name) ?? null;
|
|
6176
|
+
const sleepConfig = sleepManager?.getSleepConfig(name) ?? null;
|
|
6177
|
+
const schedules = readSchedules(dir);
|
|
6178
|
+
const now = /* @__PURE__ */ new Date();
|
|
6179
|
+
const { upcoming, previous } = computeClockEvents(schedules, sleepState, sleepConfig, now);
|
|
6072
6180
|
return c.json({ sleep: sleepState, sleepConfig, schedules, upcoming, previous });
|
|
6073
6181
|
}).get("/:name/sleep/config", requireSelf(), async (c) => {
|
|
6074
6182
|
const name = c.req.param("name");
|
|
@@ -6235,7 +6343,7 @@ var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
6235
6343
|
const body = await c.req.text();
|
|
6236
6344
|
const message = `[webhook: ${event}] ${body}`;
|
|
6237
6345
|
try {
|
|
6238
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
6346
|
+
const { sendSystemMessage } = await import("./system-chat-NDAW6YP7.js");
|
|
6239
6347
|
await sendSystemMessage(name, message);
|
|
6240
6348
|
return c.json({ ok: true });
|
|
6241
6349
|
} catch (err) {
|
|
@@ -6289,7 +6397,7 @@ setup.get("/status", async (c) => {
|
|
|
6289
6397
|
let hasAccount = false;
|
|
6290
6398
|
if (hasSystem) {
|
|
6291
6399
|
try {
|
|
6292
|
-
const { listUsersByType: listUsersByType2 } = await import("./auth-
|
|
6400
|
+
const { listUsersByType: listUsersByType2 } = await import("./auth-CCFAU4GQ.js");
|
|
6293
6401
|
const brains = await listUsersByType2("brain");
|
|
6294
6402
|
hasAccount = brains.length > 0;
|
|
6295
6403
|
} catch (err) {
|
|
@@ -6500,7 +6608,7 @@ setup.post("/account", async (c) => {
|
|
|
6500
6608
|
}
|
|
6501
6609
|
}
|
|
6502
6610
|
try {
|
|
6503
|
-
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-
|
|
6611
|
+
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-CCFAU4GQ.js");
|
|
6504
6612
|
const user = await createUser2(body.username.trim(), body.password);
|
|
6505
6613
|
if (body.displayName?.trim()) {
|
|
6506
6614
|
await updateUserProfile2(user.id, { display_name: body.displayName.trim() });
|
|
@@ -6546,7 +6654,7 @@ setup.post("/models", async (c) => {
|
|
|
6546
6654
|
return c.json({ error: "Spirit model is required" }, 400);
|
|
6547
6655
|
}
|
|
6548
6656
|
try {
|
|
6549
|
-
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-
|
|
6657
|
+
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-UODCCE4O.js");
|
|
6550
6658
|
setEnabledModels3(body.models);
|
|
6551
6659
|
const config2 = readGlobalConfig();
|
|
6552
6660
|
config2.spiritModel = body.spiritModel.trim();
|
|
@@ -6564,15 +6672,15 @@ setup.post("/complete", async (c) => {
|
|
|
6564
6672
|
return c.json({ error: "Setup already complete" }, 400);
|
|
6565
6673
|
}
|
|
6566
6674
|
try {
|
|
6567
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
6568
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
6675
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-RPBLLUQ5.js");
|
|
6676
|
+
const { startSpiritFull } = await import("./mind-service-NB2JMWQZ.js");
|
|
6569
6677
|
await ensureSpiritProject();
|
|
6570
6678
|
await syncSpiritTemplate();
|
|
6571
6679
|
const warnings = [];
|
|
6572
6680
|
const config2 = readGlobalConfig();
|
|
6573
6681
|
if (config2.setup?.service && config2.setup?.type === "local") {
|
|
6574
6682
|
try {
|
|
6575
|
-
const { installUserService } = await import("./service-install-
|
|
6683
|
+
const { installUserService } = await import("./service-install-4HHFDDWY.js");
|
|
6576
6684
|
const installed = await installUserService(config2.port, config2.hostname);
|
|
6577
6685
|
if (!installed) {
|
|
6578
6686
|
warnings.push("Service installation is not supported on this platform.");
|
|
@@ -6600,8 +6708,8 @@ setup.post("/complete", async (c) => {
|
|
|
6600
6708
|
}
|
|
6601
6709
|
let spiritConversationId;
|
|
6602
6710
|
try {
|
|
6603
|
-
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-
|
|
6604
|
-
const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-
|
|
6711
|
+
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-CCFAU4GQ.js");
|
|
6712
|
+
const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-CJOOCGNW.js");
|
|
6605
6713
|
const spiritUser = await getOrCreateMindUser2("volute");
|
|
6606
6714
|
const brains = await listUsersByType2("brain");
|
|
6607
6715
|
const admin2 = brains.find((u) => u.role === "admin");
|
|
@@ -6623,21 +6731,23 @@ setup.post("/complete", async (c) => {
|
|
|
6623
6731
|
logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
|
|
6624
6732
|
if (spiritConversationId && spiritStarted) {
|
|
6625
6733
|
try {
|
|
6626
|
-
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-
|
|
6627
|
-
const { listUsersByType: listUsers2 } = await import("./auth-
|
|
6734
|
+
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-R7JSQGYX.js");
|
|
6735
|
+
const { listUsersByType: listUsers2 } = await import("./auth-CCFAU4GQ.js");
|
|
6628
6736
|
const admins = await listUsers2("brain");
|
|
6629
6737
|
const admin2 = admins.find((u) => u.role === "admin");
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6738
|
+
if (admin2) {
|
|
6739
|
+
const adminName = admin2.display_name || admin2.username;
|
|
6740
|
+
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.`;
|
|
6741
|
+
await deliverMessage2(SPIRIT_NAME, {
|
|
6742
|
+
content: [{ type: "text", text: welcomePrompt }],
|
|
6743
|
+
channel: `@${admin2.username}`,
|
|
6744
|
+
conversationId: spiritConversationId,
|
|
6745
|
+
sender: admin2.username,
|
|
6746
|
+
isDM: true,
|
|
6747
|
+
participants: [SPIRIT_NAME, admin2.username],
|
|
6748
|
+
participantCount: 2
|
|
6749
|
+
});
|
|
6750
|
+
}
|
|
6641
6751
|
} catch (err) {
|
|
6642
6752
|
logger_default.warn("failed to send welcome prompt to spirit (non-fatal)", logger_default.errorData(err));
|
|
6643
6753
|
warnings.push(
|
|
@@ -6734,10 +6844,10 @@ var app16 = new Hono20().get("/", async (c) => {
|
|
|
6734
6844
|
if (!file.name.endsWith(".zip")) {
|
|
6735
6845
|
return c.json({ error: "Only .zip files are accepted" }, 400);
|
|
6736
6846
|
}
|
|
6737
|
-
const
|
|
6847
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
6738
6848
|
const tmpDir = mkdtempSync(join(tmpdir(), "volute-skill-upload-"));
|
|
6739
6849
|
try {
|
|
6740
|
-
const zip = new AdmZip(
|
|
6850
|
+
const zip = new AdmZip(buffer);
|
|
6741
6851
|
for (const entry of zip.getEntries()) {
|
|
6742
6852
|
const target = resolve12(tmpDir, entry.entryName);
|
|
6743
6853
|
if (!target.startsWith(tmpDir)) {
|
|
@@ -6807,7 +6917,7 @@ var app17 = new Hono21().post("/:name/typing", zValidator8("json", typingSchema)
|
|
|
6807
6917
|
map.delete(channel, sender);
|
|
6808
6918
|
}
|
|
6809
6919
|
if (isConversationId(channel)) {
|
|
6810
|
-
|
|
6920
|
+
publish2(channel, { type: "typing", senders: map.get(channel) });
|
|
6811
6921
|
}
|
|
6812
6922
|
return c.json({ ok: true });
|
|
6813
6923
|
}).get("/:name/typing", (c) => {
|
|
@@ -6970,42 +7080,6 @@ function getOnlineBrains() {
|
|
|
6970
7080
|
return [...connections.keys()];
|
|
6971
7081
|
}
|
|
6972
7082
|
|
|
6973
|
-
// packages/daemon/src/lib/events/event-sequencer.ts
|
|
6974
|
-
var BUFFER_SIZE = 1e3;
|
|
6975
|
-
var MAX_AGE_MS = 5 * 60 * 1e3;
|
|
6976
|
-
var nextId = 1;
|
|
6977
|
-
var buffer = [];
|
|
6978
|
-
function bufferEvent(data) {
|
|
6979
|
-
const id = nextId++;
|
|
6980
|
-
buffer.push({ id, data, timestamp: Date.now() });
|
|
6981
|
-
while (buffer.length > BUFFER_SIZE) {
|
|
6982
|
-
buffer.shift();
|
|
6983
|
-
}
|
|
6984
|
-
return id;
|
|
6985
|
-
}
|
|
6986
|
-
function nextEventId() {
|
|
6987
|
-
return nextId++;
|
|
6988
|
-
}
|
|
6989
|
-
function getEventsSince(sinceId, allowedConversationIds, allowedActivityMind) {
|
|
6990
|
-
const now = Date.now();
|
|
6991
|
-
const startIdx = buffer.findIndex((e) => e.id > sinceId);
|
|
6992
|
-
if (startIdx === -1) return [];
|
|
6993
|
-
return buffer.slice(startIdx).filter((e) => {
|
|
6994
|
-
if (now - e.timestamp >= MAX_AGE_MS) return false;
|
|
6995
|
-
const data = e.data;
|
|
6996
|
-
switch (data.event) {
|
|
6997
|
-
case "snapshot":
|
|
6998
|
-
return false;
|
|
6999
|
-
case "conversation":
|
|
7000
|
-
return allowedConversationIds.has(data.conversationId);
|
|
7001
|
-
case "activity":
|
|
7002
|
-
return allowedActivityMind === void 0 || data.mind === allowedActivityMind;
|
|
7003
|
-
default:
|
|
7004
|
-
return false;
|
|
7005
|
-
}
|
|
7006
|
-
});
|
|
7007
|
-
}
|
|
7008
|
-
|
|
7009
7083
|
// packages/daemon/src/web/api/v1/events.ts
|
|
7010
7084
|
var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
|
|
7011
7085
|
const user = c.get("user");
|
|
@@ -7067,15 +7141,15 @@ var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
|
|
|
7067
7141
|
data: JSON.stringify(snapshotData)
|
|
7068
7142
|
});
|
|
7069
7143
|
const unsubActivity = subscribe((event) => {
|
|
7144
|
+
if (activityMind !== void 0 && event.mind !== activityMind) return;
|
|
7145
|
+
const { seq, ...rest } = event;
|
|
7070
7146
|
const data = {
|
|
7071
7147
|
event: "activity",
|
|
7072
|
-
...
|
|
7073
|
-
metadata:
|
|
7148
|
+
...rest,
|
|
7149
|
+
metadata: rest.metadata ?? null
|
|
7074
7150
|
};
|
|
7075
|
-
const eventId = bufferEvent(data);
|
|
7076
|
-
if (activityMind !== void 0 && event.mind !== activityMind) return;
|
|
7077
7151
|
stream.writeSSE({
|
|
7078
|
-
id: String(
|
|
7152
|
+
id: String(seq),
|
|
7079
7153
|
data: JSON.stringify(data)
|
|
7080
7154
|
}).catch((err) => {
|
|
7081
7155
|
if (!stream.aborted) logger_default.error("[v1-events] write error:", logger_default.errorData(err));
|
|
@@ -7084,10 +7158,10 @@ var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
|
|
|
7084
7158
|
cleanups.push(unsubActivity);
|
|
7085
7159
|
for (const conv of conversations2) {
|
|
7086
7160
|
const unsubConv = subscribe2(conv.id, (event) => {
|
|
7087
|
-
const
|
|
7088
|
-
const
|
|
7161
|
+
const { seq, ...rest } = event;
|
|
7162
|
+
const data = { event: "conversation", conversationId: conv.id, ...rest };
|
|
7089
7163
|
stream.writeSSE({
|
|
7090
|
-
id: String(
|
|
7164
|
+
id: String(seq),
|
|
7091
7165
|
data: JSON.stringify(data)
|
|
7092
7166
|
}).catch((err) => {
|
|
7093
7167
|
if (!stream.aborted) logger_default.error("[v1-events] write error:", logger_default.errorData(err));
|
|
@@ -7125,12 +7199,9 @@ import { Hono as Hono25 } from "hono";
|
|
|
7125
7199
|
import { spawn as spawn4 } from "child_process";
|
|
7126
7200
|
import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync9 } from "fs";
|
|
7127
7201
|
import { resolve as resolve13 } from "path";
|
|
7128
|
-
function tsxBin(cwd) {
|
|
7129
|
-
return resolve13(cwd, "node_modules", ".bin", "tsx");
|
|
7130
|
-
}
|
|
7131
7202
|
async function spawnServer(cwd, port, options) {
|
|
7132
|
-
let cmd =
|
|
7133
|
-
let args = ["src/server.ts", "--port", String(port)];
|
|
7203
|
+
let cmd = process.env.VOLUTE_NODE_PATH ?? process.execPath;
|
|
7204
|
+
let args = ["--import", "tsx", "src/server.ts", "--port", String(port)];
|
|
7134
7205
|
if (options?.mindName) {
|
|
7135
7206
|
if (isIsolationEnabled()) {
|
|
7136
7207
|
[cmd, args] = await wrapForIsolation(cmd, args, options.mindName);
|
|
@@ -7274,6 +7345,11 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
|
7274
7345
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
7275
7346
|
if (entry.stage === "seed")
|
|
7276
7347
|
return c.json({ error: "Seed minds cannot create variants \u2014 sprout first" }, 403);
|
|
7348
|
+
if (entry.parent)
|
|
7349
|
+
return c.json(
|
|
7350
|
+
{ error: "Cannot split from a variant \u2014 split from the base mind instead" },
|
|
7351
|
+
403
|
|
7352
|
+
);
|
|
7277
7353
|
let body;
|
|
7278
7354
|
try {
|
|
7279
7355
|
body = await c.req.json();
|
|
@@ -7287,7 +7363,7 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
|
7287
7363
|
if (await findMind(variantName)) {
|
|
7288
7364
|
return c.json({ error: `Name already in use: ${variantName}` }, 409);
|
|
7289
7365
|
}
|
|
7290
|
-
const projectRoot = mindDir(mindName);
|
|
7366
|
+
const projectRoot = entry.dir ?? mindDir(mindName);
|
|
7291
7367
|
const variantDir = resolve14(projectRoot, ".variants", variantName);
|
|
7292
7368
|
if (existsSync9(variantDir)) {
|
|
7293
7369
|
return c.json({ error: `Variant directory already exists: ${variantDir}` }, 409);
|
|
@@ -7351,7 +7427,7 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
|
7351
7427
|
body = await c.req.json();
|
|
7352
7428
|
} catch {
|
|
7353
7429
|
}
|
|
7354
|
-
const projectRoot = mindDir(mindName);
|
|
7430
|
+
const projectRoot = parentEntry.dir ?? mindDir(mindName);
|
|
7355
7431
|
if (existsSync9(variantEntry.dir)) {
|
|
7356
7432
|
const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
|
|
7357
7433
|
if (status) {
|
|
@@ -7384,7 +7460,7 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
|
7384
7460
|
}
|
|
7385
7461
|
const verified = await verify2(result.actualPort);
|
|
7386
7462
|
try {
|
|
7387
|
-
process.kill(result.child.pid);
|
|
7463
|
+
process.kill(-result.child.pid, "SIGTERM");
|
|
7388
7464
|
} catch {
|
|
7389
7465
|
}
|
|
7390
7466
|
if (!verified) {
|
|
@@ -7411,13 +7487,47 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
|
7411
7487
|
try {
|
|
7412
7488
|
await gitExec(["merge", variantEntry.branch], { cwd: projectRoot });
|
|
7413
7489
|
} catch (_e) {
|
|
7414
|
-
|
|
7490
|
+
let conflicts = [];
|
|
7491
|
+
try {
|
|
7492
|
+
const out = (await gitExec(["diff", "--name-only", "--diff-filter=U"], { cwd: projectRoot })).trim();
|
|
7493
|
+
conflicts = out ? out.split("\n") : [];
|
|
7494
|
+
} catch (err) {
|
|
7495
|
+
logger_default.warn(`failed to list merge conflicts for ${mindName}`, logger_default.errorData(err));
|
|
7496
|
+
}
|
|
7497
|
+
try {
|
|
7498
|
+
await gitExec(["merge", "--abort"], { cwd: projectRoot });
|
|
7499
|
+
} catch (err) {
|
|
7500
|
+
logger_default.warn(`failed to abort merge for ${mindName}`, logger_default.errorData(err));
|
|
7501
|
+
}
|
|
7502
|
+
try {
|
|
7503
|
+
await chownMindDir(projectRoot, mindName);
|
|
7504
|
+
} catch (err) {
|
|
7505
|
+
logger_default.warn(
|
|
7506
|
+
`failed to restore ownership after aborted merge for ${mindName}`,
|
|
7507
|
+
logger_default.errorData(err)
|
|
7508
|
+
);
|
|
7509
|
+
return c.json(
|
|
7510
|
+
{
|
|
7511
|
+
error: `Merge failed and restoring parent ownership failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
7512
|
+
conflicts
|
|
7513
|
+
},
|
|
7514
|
+
500
|
|
7515
|
+
);
|
|
7516
|
+
}
|
|
7517
|
+
return c.json(
|
|
7518
|
+
{
|
|
7519
|
+
error: "Merge failed. Resolve conflicts in the variant and retry the join.",
|
|
7520
|
+
conflicts
|
|
7521
|
+
},
|
|
7522
|
+
500
|
|
7523
|
+
);
|
|
7415
7524
|
}
|
|
7416
|
-
await cleanupVariant(variantName, projectRoot, variantEntry.dir);
|
|
7525
|
+
await cleanupVariant(variantName, projectRoot, variantEntry.dir, { stop: true });
|
|
7526
|
+
await chownMindDir(projectRoot, mindName);
|
|
7417
7527
|
if (variantName.endsWith("-upgrade") || variantName === "upgrade") {
|
|
7418
7528
|
try {
|
|
7419
7529
|
const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-446HHH5V.js");
|
|
7420
|
-
const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-
|
|
7530
|
+
const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-OUZBZ3Q4.js");
|
|
7421
7531
|
const tmpl = parentEntry.template ?? "claude";
|
|
7422
7532
|
await setMindTemplateHash2(mindName, computeTemplateHash2(tmpl));
|
|
7423
7533
|
} catch (err) {
|
|
@@ -7468,7 +7578,7 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
|
7468
7578
|
return c.json({ error: `Unknown variant: ${variantName}` }, 404);
|
|
7469
7579
|
}
|
|
7470
7580
|
if (!variantEntry.dir) return c.json({ error: `Variant ${variantName} has no directory` }, 500);
|
|
7471
|
-
const projectRoot = mindDir(mindName);
|
|
7581
|
+
const projectRoot = parentEntry.dir ?? mindDir(mindName);
|
|
7472
7582
|
await cleanupVariant(variantName, projectRoot, variantEntry.dir, { stop: true });
|
|
7473
7583
|
return c.json({ ok: true });
|
|
7474
7584
|
});
|
|
@@ -7648,7 +7758,7 @@ var unifiedChatApp = new Hono27().post(
|
|
|
7648
7758
|
return c.json({ error: "conversationId or targetMind required" }, 400);
|
|
7649
7759
|
}
|
|
7650
7760
|
const senderName = user.id === 0 && body.sender ? body.sender : user.username;
|
|
7651
|
-
const senderIsMind = user.id === 0 && body.sender && await findMind(body.sender) || user.user_type === "mind";
|
|
7761
|
+
const senderIsMind = user.id === 0 && body.sender && await findMind(body.sender) || user.user_type === "mind" || user.user_type === "system" && !!await findMind(user.username);
|
|
7652
7762
|
let baseName;
|
|
7653
7763
|
let variantName;
|
|
7654
7764
|
let conversationId = body.conversationId;
|
|
@@ -7725,7 +7835,7 @@ var unifiedChatApp = new Hono27().post(
|
|
|
7725
7835
|
}
|
|
7726
7836
|
}
|
|
7727
7837
|
if (senderIsMind) {
|
|
7728
|
-
const vCfg = readVoluteConfig(
|
|
7838
|
+
const vCfg = readVoluteConfig(await resolveMindDir(baseName ?? senderName));
|
|
7729
7839
|
const shouldUnescapeNewlines = vCfg?.unescapeNewlines === true;
|
|
7730
7840
|
for (const block of contentBlocks) {
|
|
7731
7841
|
if (block.type === "text") {
|
|
@@ -7794,7 +7904,7 @@ var unifiedChatApp = new Hono27().post(
|
|
|
7794
7904
|
});
|
|
7795
7905
|
if (outboundTurnId) {
|
|
7796
7906
|
const mindKey = senderBase ?? senderName;
|
|
7797
|
-
|
|
7907
|
+
publish3(mindKey, {
|
|
7798
7908
|
mind: mindKey,
|
|
7799
7909
|
type: "outbound",
|
|
7800
7910
|
channel,
|
|
@@ -7818,13 +7928,16 @@ var unifiedChatApp = new Hono27().post(
|
|
|
7818
7928
|
targetName: baseName ? (username) => username === baseName ? variantName : username : void 0
|
|
7819
7929
|
});
|
|
7820
7930
|
const systemReplyTarget = baseName ?? senderName;
|
|
7821
|
-
if (
|
|
7822
|
-
|
|
7823
|
-
|
|
7824
|
-
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7931
|
+
if (shouldGenerateSystemFallback({
|
|
7932
|
+
senderIsMind: !!senderIsMind,
|
|
7933
|
+
hasMessage: !!body.message,
|
|
7934
|
+
convType: conv.type,
|
|
7935
|
+
participants,
|
|
7936
|
+
replyTarget: systemReplyTarget
|
|
7937
|
+
})) {
|
|
7938
|
+
generateSystemFallbackReply(conversationId, systemReplyTarget, body.message).catch(
|
|
7939
|
+
(err) => logger_default.error(`system reply generation failed for ${systemReplyTarget}`, logger_default.errorData(err))
|
|
7940
|
+
);
|
|
7828
7941
|
}
|
|
7829
7942
|
return c.json({ ok: true, conversationId, outboundId });
|
|
7830
7943
|
}
|
|
@@ -7917,6 +8030,9 @@ var app24 = new Hono28().get("/:name/conversations", async (c) => {
|
|
|
7917
8030
|
if (!u) return c.json({ error: `User ${id} not found` }, 400);
|
|
7918
8031
|
}
|
|
7919
8032
|
const participantIds = [...participantSet];
|
|
8033
|
+
if (participantIds.length < 2) {
|
|
8034
|
+
return c.json({ error: "a conversation needs at least two distinct participants" }, 400);
|
|
8035
|
+
}
|
|
7920
8036
|
if (participantIds.length > 2) {
|
|
7921
8037
|
return c.json({ error: "Use channels for multi-participant conversations" }, 400);
|
|
7922
8038
|
}
|
|
@@ -8200,27 +8316,27 @@ async function startDaemon(opts) {
|
|
|
8200
8316
|
const DAEMON_TOKEN_PATH = resolve16(systemDir, "daemon-token");
|
|
8201
8317
|
mkdirSync10(home, { recursive: true });
|
|
8202
8318
|
ensureSystemDir();
|
|
8203
|
-
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-
|
|
8319
|
+
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-Y2EJI3GG.js");
|
|
8204
8320
|
migrateConfigSecrets();
|
|
8205
8321
|
migrateSetupCompleted();
|
|
8206
|
-
const { migrateAiModelQualification } = await import("./ai-service-
|
|
8322
|
+
const { migrateAiModelQualification } = await import("./ai-service-UODCCE4O.js");
|
|
8207
8323
|
migrateAiModelQualification();
|
|
8208
|
-
await (await import("./db-
|
|
8324
|
+
await (await import("./db-MF2JNRUW.js")).getDb();
|
|
8209
8325
|
try {
|
|
8210
8326
|
const { eq: eq8, and: and6 } = await import("drizzle-orm");
|
|
8211
8327
|
const { users: users2 } = await import("./schema-PVNG3PQM.js");
|
|
8212
|
-
const db = await (await import("./db-
|
|
8328
|
+
const db = await (await import("./db-MF2JNRUW.js")).getDb();
|
|
8213
8329
|
await db.update(users2).set({ role: "system" }).where(and6(eq8(users2.user_type, "system"), eq8(users2.role, "user")));
|
|
8214
8330
|
} catch (err) {
|
|
8215
8331
|
logger_default.warn("failed to migrate system user role", logger_default.errorData(err));
|
|
8216
8332
|
}
|
|
8217
8333
|
try {
|
|
8218
|
-
const { migrateAvatarSizes } = await import("./avatar-image-
|
|
8334
|
+
const { migrateAvatarSizes } = await import("./avatar-image-6KY6UU4D.js");
|
|
8219
8335
|
await migrateAvatarSizes();
|
|
8220
8336
|
} catch (err) {
|
|
8221
8337
|
logger_default.warn("avatar size migration failed", logger_default.errorData(err));
|
|
8222
8338
|
}
|
|
8223
|
-
const { initSandbox } = await import("./sandbox-
|
|
8339
|
+
const { initSandbox } = await import("./sandbox-ZJ7QA6Z6.js");
|
|
8224
8340
|
await initSandbox();
|
|
8225
8341
|
try {
|
|
8226
8342
|
await syncBuiltinSkills();
|
|
@@ -8247,7 +8363,7 @@ async function startDaemon(opts) {
|
|
|
8247
8363
|
logger_default.warn("failed to ensure #system channel", logger_default.errorData(err));
|
|
8248
8364
|
}
|
|
8249
8365
|
try {
|
|
8250
|
-
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-
|
|
8366
|
+
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-CCFAU4GQ.js");
|
|
8251
8367
|
await getOrCreateSystemUser2();
|
|
8252
8368
|
} catch (err) {
|
|
8253
8369
|
logger_default.warn(
|
|
@@ -8256,12 +8372,12 @@ async function startDaemon(opts) {
|
|
|
8256
8372
|
);
|
|
8257
8373
|
}
|
|
8258
8374
|
const token = process.env.VOLUTE_DAEMON_TOKEN || randomBytes3(32).toString("hex");
|
|
8259
|
-
const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-
|
|
8375
|
+
const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-Y2EJI3GG.js");
|
|
8260
8376
|
const globalCfg = readGlobalConfig2();
|
|
8261
8377
|
let tls;
|
|
8262
8378
|
if (opts.tailscale || globalCfg.tailscale) {
|
|
8263
8379
|
try {
|
|
8264
|
-
const { getTailscaleTls } = await import("./tailscale-
|
|
8380
|
+
const { getTailscaleTls } = await import("./tailscale-3XOKOW7T.js");
|
|
8265
8381
|
const tlsConfig = await getTailscaleTls();
|
|
8266
8382
|
tls = { key: tlsConfig.key, cert: tlsConfig.cert };
|
|
8267
8383
|
logger_default.info("Tailscale HTTPS enabled", { hostname: tlsConfig.hostname });
|
|
@@ -8341,15 +8457,19 @@ async function startDaemon(opts) {
|
|
|
8341
8457
|
await Promise.all(workers);
|
|
8342
8458
|
}
|
|
8343
8459
|
try {
|
|
8344
|
-
const { isSetupComplete: isSetupComplete2 } = await import("./setup-
|
|
8460
|
+
const { isSetupComplete: isSetupComplete2 } = await import("./setup-Y2EJI3GG.js");
|
|
8345
8461
|
if (isSetupComplete2()) {
|
|
8346
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
8347
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
8462
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-RPBLLUQ5.js");
|
|
8463
|
+
const { startSpiritFull } = await import("./mind-service-NB2JMWQZ.js");
|
|
8348
8464
|
await ensureSpiritProject();
|
|
8465
|
+
const spiritEntry = await findMind(SPIRIT_NAME);
|
|
8466
|
+
if (spiritEntry?.dir) {
|
|
8467
|
+
const { registerMindDir } = await import("./delivery-router-N4A7ZC5T.js");
|
|
8468
|
+
registerMindDir(SPIRIT_NAME, spiritEntry.dir);
|
|
8469
|
+
}
|
|
8349
8470
|
await syncSpiritTemplate();
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
await startSpiritFull("volute");
|
|
8471
|
+
if (spiritEntry && !manager.isRunning(SPIRIT_NAME)) {
|
|
8472
|
+
await startSpiritFull(SPIRIT_NAME);
|
|
8353
8473
|
}
|
|
8354
8474
|
}
|
|
8355
8475
|
} catch (err) {
|
|
@@ -8361,7 +8481,7 @@ async function startDaemon(opts) {
|
|
|
8361
8481
|
bridgeManager.startBridges(daemonPort).catch((err) => {
|
|
8362
8482
|
logger_default.warn("failed to start bridges", logger_default.errorData(err));
|
|
8363
8483
|
});
|
|
8364
|
-
import("./cloud-sync-
|
|
8484
|
+
import("./cloud-sync-46RS4SDA.js").then(
|
|
8365
8485
|
({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
|
|
8366
8486
|
logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
|
|
8367
8487
|
})
|
|
@@ -8369,7 +8489,7 @@ async function startDaemon(opts) {
|
|
|
8369
8489
|
logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
|
|
8370
8490
|
});
|
|
8371
8491
|
try {
|
|
8372
|
-
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-
|
|
8492
|
+
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-C5CH7CVP.js");
|
|
8373
8493
|
backfillTemplateHashes();
|
|
8374
8494
|
notifyVersionUpdate().catch((err) => {
|
|
8375
8495
|
logger_default.warn("failed to send version update notifications", logger_default.errorData(err));
|
|
@@ -8387,6 +8507,7 @@ async function startDaemon(opts) {
|
|
|
8387
8507
|
cleanExpiredLogs().catch((err) => {
|
|
8388
8508
|
logger_default.warn("failed to clean expired logs", logger_default.errorData(err));
|
|
8389
8509
|
});
|
|
8510
|
+
const maintenanceInterval = startMaintenanceInterval();
|
|
8390
8511
|
setProviderRefreshHook((provider) => {
|
|
8391
8512
|
void syncProviderToMinds(provider, {
|
|
8392
8513
|
listRunning: () => getMindManager().getRunningMinds()
|
|
@@ -8439,6 +8560,7 @@ async function startDaemon(opts) {
|
|
|
8439
8560
|
safe("summarizer.stop", () => summarizer.stop());
|
|
8440
8561
|
safe("backupManager.stop", () => backupManager2.stop());
|
|
8441
8562
|
safe("stopApiKeyRefresh", stopApiKeyRefresh);
|
|
8563
|
+
safe("maintenanceInterval", () => clearInterval(maintenanceInterval));
|
|
8442
8564
|
safe("delivery.dispose", () => delivery.dispose());
|
|
8443
8565
|
await safe("bridgeManager.stopAll", () => bridgeManager.stopAll());
|
|
8444
8566
|
await safe("manager.stopAll", () => manager.stopAll());
|