volute 0.43.1 → 0.45.1
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/dist/{activity-events-UISXY4Y5.js → activity-events-OMCSM7XW.js} +3 -3
- package/dist/{ai-service-FBCCEYF5.js → ai-service-534WUSDL.js} +4 -4
- package/dist/{archive-I32WHCJB.js → archive-6R4TZMYI.js} +3 -3
- package/dist/{auth-3RIG6GKN.js → auth-FRZJVQCS.js} +4 -4
- package/dist/avatar-image-BNWEXSA2.js +16 -0
- package/dist/backup-OZXHL3JS.js +381 -0
- package/dist/{chat-SDSX5TVV.js → chat-I4EDDIQC.js} +2 -2
- package/dist/{chunk-AD46AYZQ.js → chunk-2BONPXAF.js} +1 -1
- package/dist/{chunk-ONM2AZFL.js → chunk-322KE457.js} +14 -2
- package/dist/{chunk-PGPLCJPK.js → chunk-3ERIL673.js} +1 -1
- package/dist/{chunk-QQ2MVQU3.js → chunk-5AUKCNPE.js} +10 -10
- package/dist/{chunk-XDTKJNW5.js → chunk-5GT7URXJ.js} +1 -1
- package/dist/{chunk-DMUPZQWP.js → chunk-77BVGCTZ.js} +8 -8
- package/dist/{chunk-EFL5UOY4.js → chunk-CYI534DJ.js} +3 -3
- package/dist/{chunk-57LBQ7JX.js → chunk-FHWUQZXE.js} +1 -1
- package/dist/{chunk-YAMO2U3N.js → chunk-H7IYFRAL.js} +1 -1
- package/dist/{chunk-M3PGGSBH.js → chunk-HVU45COX.js} +1 -1
- package/dist/{chunk-O3DXAR44.js → chunk-IEWZ7VD7.js} +2 -2
- package/dist/{chunk-DE4EKQFH.js → chunk-IUXTYXFI.js} +3 -3
- package/dist/{chunk-K4EHBHPE.js → chunk-JSRMEY52.js} +7 -5
- package/dist/{chunk-QHG4OMZL.js → chunk-KDLYIECM.js} +37 -32
- package/dist/{chunk-EE7SZJON.js → chunk-KP3KWNG6.js} +2 -2
- package/dist/chunk-KVKP6VQ5.js +318 -0
- package/dist/{chunk-JVK6QQIC.js → chunk-LAXUUY7O.js} +2 -2
- package/dist/{chunk-C6ESRQZ7.js → chunk-OXXTPILE.js} +1 -1
- package/dist/{chunk-ATEX3ZPG.js → chunk-Q2XBKQ2D.js} +2 -2
- package/dist/{chunk-GZJFC76M.js → chunk-QMJJWTNL.js} +1 -1
- package/dist/chunk-SQL7M4HJ.js +120 -0
- package/dist/{chunk-YSV3VJQK.js → chunk-TSK5PI4L.js} +1 -1
- package/dist/{chunk-4SVONUTC.js → chunk-U4FNXDEJ.js} +350 -207
- package/dist/{chunk-2HIVYZDB.js → chunk-UMI4UIJG.js} +1 -1
- package/dist/{chunk-Y6O35D7K.js → chunk-V4GYPD5L.js} +41 -16
- package/dist/{chunk-KINGVQSR.js → chunk-Y6OPHHGM.js} +5 -5
- package/dist/{chunk-SPLPKBES.js → chunk-ZIR7HSAX.js} +6 -9
- package/dist/{chunk-7G2EEYXX.js → chunk-ZMIMSIIT.js} +2 -2
- package/dist/{chunk-L3IV23ZG.js → chunk-ZV7MFISX.js} +2 -0
- package/dist/cli.js +53 -22
- package/dist/{cloud-sync-KOEBUFW5.js → cloud-sync-Y7LQPRE3.js} +16 -16
- package/dist/{conversations-67WWW25C.js → conversations-G4LYMHAA.js} +4 -4
- package/dist/{create-7W3LV3J7.js → create-2YY7IPMS.js} +1 -1
- package/dist/{daemon-restart-EZXB73W7.js → daemon-restart-ABP54YN6.js} +7 -7
- package/dist/daemon.js +679 -478
- package/dist/{db-CZV62BOQ.js → db-JFLCJCUG.js} +2 -2
- package/dist/{db-IJL6B26S.js → db-LZTLA7XC.js} +1 -1
- package/dist/delivery-manager-R5STGLXB.js +32 -0
- package/dist/{delivery-router-HXBHYHJM.js → delivery-router-6DE3BPHO.js} +3 -3
- package/dist/{down-RRNYIGCU.js → down-XCAZXWLB.js} +5 -5
- package/dist/echo-text-NQXYYYCU.js +32 -0
- package/dist/{exec-SJK7VUTC.js → exec-4GWHAHS3.js} +3 -3
- package/dist/{export-7LPCIB5J.js → export-ID7YUSLZ.js} +3 -3
- package/dist/{extensions-PQPZT6LS.js → extensions-AYSPKE33.js} +16 -16
- package/dist/{files-LV7VAKPC.js → files-BQ2WB5KC.js} +3 -3
- package/dist/{import-XPECCRQ7.js → import-SKID37QX.js} +6 -6
- package/dist/{isolation-5AYEY55P.js → isolation-5MB3J73F.js} +3 -3
- package/dist/{login-KJSN4JDA.js → login-LM4NF4ZB.js} +2 -2
- package/dist/{logout-TMJGUQV2.js → logout-CTJVIZGA.js} +2 -2
- package/dist/message-delivery-IUAXRPFE.js +34 -0
- package/dist/{mind-G3WEWDM4.js → mind-KLHC7XYR.js} +6 -6
- package/dist/{mind-activity-tracker-JHAT6456.js → mind-activity-tracker-BGHJE7XA.js} +4 -4
- package/dist/mind-service-BF2LUQMH.js +36 -0
- package/dist/{package-24TL6DTF.js → package-BMHV7UHN.js} +1 -1
- package/dist/{registry-7LQHTRUX.js → registry-NUJAGLQJ.js} +2 -2
- package/dist/{sandbox-SJH3XOPZ.js → sandbox-72MWV4JL.js} +4 -4
- package/dist/scheduler-YHJRRV6E.js +30 -0
- package/dist/{schema-LRUTFOER.js → schema-PVNG3PQM.js} +1 -1
- package/dist/{seed-HHSJTM6O.js → seed-4MKQ5QKG.js} +1 -1
- package/dist/{seed-cmd-UPQY35RG.js → seed-cmd-LCXMR7VV.js} +2 -2
- package/dist/{seed-create-MDRMXMSB.js → seed-create-N2BF5LQX.js} +3 -3
- package/dist/{seed-sprout-4M7IQWMH.js → seed-sprout-6ZDP23YI.js} +7 -7
- package/dist/{send-ZBZWIH5V.js → send-O6W53VBM.js} +37 -42
- package/dist/{service-4EVZKGSA.js → service-AQVPUANO.js} +4 -4
- package/dist/{service-install-SHRM6NHK.js → service-install-4QNUDKLM.js} +5 -5
- package/dist/{setup-ZD2LMBR3.js → setup-3O6O2JZ7.js} +7 -7
- package/dist/{setup-25MMJ3J4.js → setup-73YBJZQL.js} +3 -3
- package/dist/skills/memory/SKILL.md +2 -1
- package/dist/skills/orientation/SKILL.md +1 -1
- package/dist/skills/plan-coordinator/SKILL.md +2 -2
- package/dist/skills/volute-admin/SKILL.md +9 -6
- package/dist/skills/volute-mind/SKILL.md +15 -16
- package/dist/skills/volute-mind/references/extensions.md +5 -3
- package/dist/skills/volute-mind/references/integrations.md +2 -2
- package/dist/skills/volute-mind/references/routing.md +19 -23
- package/dist/skills/volute-mind/references/variants.md +10 -8
- package/dist/{skills-4KQ377GN.js → skills-ND4ZFYUW.js} +5 -5
- package/dist/sleep-manager-YAHDOIU5.js +34 -0
- package/dist/{spirit-53DQPRNR.js → spirit-II3HOERM.js} +7 -7
- package/dist/{sprout-YKM2M6D6.js → sprout-4KUG76AQ.js} +1 -1
- package/dist/{src-O4PRLMKM.js → src-JAOVXO5W.js} +1 -0
- package/dist/{src-3EGHHKZK.js → src-XFY3XDD6.js} +16 -11
- package/dist/{src-L2Z7X5UT.js → src-YH6PQ7LJ.js} +264 -52
- package/dist/{status-WTU2WHXY.js → status-E5DQNCAO.js} +5 -5
- package/dist/system-chat-E65T2HSW.js +34 -0
- package/dist/{tailscale-Q7ZJL7S7.js → tailscale-QAWVKQKU.js} +2 -2
- package/dist/{turn-tracker-JZYERJ76.js → turn-tracker-QQIVVXBI.js} +7 -5
- package/dist/{up-LFZA4GI5.js → up-LG56MPBI.js} +6 -6
- package/dist/{update-EJ7Q77ZX.js → update-7TYVH5FM.js} +5 -5
- package/dist/{update-check-ACYYNKTW.js → update-check-VSCSJ7KX.js} +3 -3
- package/dist/{upgrade-37DAGF6H.js → upgrade-NWAZ7MLD.js} +1 -1
- package/dist/{version-notify-SRQJCQEK.js → version-notify-CODJOUW2.js} +17 -17
- package/dist/web-assets/assets/index-B1JBQv2m.css +1 -0
- package/dist/web-assets/assets/index-Dac11sKB.js +86 -0
- package/dist/web-assets/ext-theme.css +5 -0
- package/dist/web-assets/index.html +2 -2
- package/package.json +1 -1
- package/packages/extensions/notes/dist/ui/assets/{index-BbgANhFm.js → index-D0-DgYyj.js} +1 -1
- package/packages/extensions/notes/dist/ui/index.html +1 -1
- package/packages/extensions/notes/skills/notes/SKILL.md +31 -3
- package/packages/extensions/pages/dist/ui/assets/{index-Dxk-DYrf.js → index-CQjEQg1r.js} +1 -1
- package/packages/extensions/pages/dist/ui/index.html +1 -1
- package/packages/extensions/plan/skills/plan/SKILL.md +1 -1
- package/templates/_base/.init/.config/prompts.json +1 -1
- package/templates/_base/.init/.local/hooks/startup-context.ts +21 -4
- package/templates/_base/.init/MEMORY.md +2 -1
- package/templates/_base/home/VOLUTE.md +6 -9
- package/templates/_base/src/lib/startup.ts +1 -1
- package/templates/claude/.init/CLAUDE.md +1 -1
- package/templates/claude/src/agent.ts +30 -3
- package/templates/claude/src/lib/stream-consumer.ts +7 -4
- package/templates/codex/.init/AGENTS.md +4 -2
- package/templates/codex/src/agent.ts +13 -7
- package/templates/pi/.init/MINDS.md +4 -2
- package/templates/pi/src/lib/event-handler.ts +6 -2
- package/dist/delivery-manager-OMCCJEVP.js +0 -32
- package/dist/echo-text-KFSUCZXL.js +0 -32
- package/dist/message-delivery-HRGFNWO7.js +0 -34
- package/dist/mind-service-2C7AINBO.js +0 -36
- package/dist/scheduler-VON2TB52.js +0 -30
- package/dist/sleep-manager-AG5SQDDI.js +0 -34
- package/dist/system-chat-54RN3K67.js +0 -34
- package/dist/web-assets/assets/index-D7udpBCx.css +0 -1
- package/dist/web-assets/assets/index-DTDmEfPU.js +0 -79
- package/templates/_base/.init/.config/hooks/pre-prompt/session-activity.ts +0 -40
package/dist/daemon.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
RESTIC_INSTALL_HINT,
|
|
4
|
+
initRepo,
|
|
5
|
+
listSnapshots,
|
|
6
|
+
readBackupState,
|
|
7
|
+
resticVersion,
|
|
8
|
+
runBackup
|
|
9
|
+
} from "./chunk-KVKP6VQ5.js";
|
|
2
10
|
import {
|
|
3
11
|
acceptPending,
|
|
4
12
|
formatFileSize,
|
|
@@ -6,21 +14,25 @@ import {
|
|
|
6
14
|
rejectPending,
|
|
7
15
|
stageFile,
|
|
8
16
|
validateFilePath
|
|
9
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-UMI4UIJG.js";
|
|
10
18
|
import {
|
|
11
19
|
findOpenClawSession,
|
|
12
20
|
importOpenClawConnectors,
|
|
13
21
|
importPiSession,
|
|
14
22
|
parseNameFromIdentity
|
|
15
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-LAXUUY7O.js";
|
|
16
24
|
import {
|
|
17
25
|
checkForUpdate,
|
|
18
26
|
checkForUpdateCached,
|
|
19
27
|
getCurrentVersion
|
|
20
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-2BONPXAF.js";
|
|
29
|
+
import {
|
|
30
|
+
normalizeAvatar,
|
|
31
|
+
safeResolveWithinBase
|
|
32
|
+
} from "./chunk-SQL7M4HJ.js";
|
|
21
33
|
import {
|
|
22
34
|
isHomeOnlyArchive
|
|
23
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-QMJJWTNL.js";
|
|
24
36
|
import {
|
|
25
37
|
computeTemplateHash
|
|
26
38
|
} from "./chunk-QMJCNZ6C.js";
|
|
@@ -30,7 +42,7 @@ import {
|
|
|
30
42
|
fixModelEscapes,
|
|
31
43
|
getPlatformDriver,
|
|
32
44
|
routeOutboundBridge
|
|
33
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-77BVGCTZ.js";
|
|
34
46
|
import {
|
|
35
47
|
getBridgeConfig,
|
|
36
48
|
readBridgesConfig,
|
|
@@ -39,7 +51,7 @@ import {
|
|
|
39
51
|
resolveChannelMapping,
|
|
40
52
|
setBridgeConfig,
|
|
41
53
|
setChannelMapping
|
|
42
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-FHWUQZXE.js";
|
|
43
55
|
import {
|
|
44
56
|
MindStartupError,
|
|
45
57
|
RestartTracker,
|
|
@@ -48,6 +60,7 @@ import {
|
|
|
48
60
|
announceToSystem,
|
|
49
61
|
authMiddleware,
|
|
50
62
|
checkHealth,
|
|
63
|
+
checkStaleSend,
|
|
51
64
|
cleanExpiredSessions,
|
|
52
65
|
clearDeliveredNotices,
|
|
53
66
|
createSession,
|
|
@@ -56,6 +69,7 @@ import {
|
|
|
56
69
|
deliverMessage,
|
|
57
70
|
drainNotices,
|
|
58
71
|
ensureSystemChannel,
|
|
72
|
+
formatHoldNotice,
|
|
59
73
|
formatNotices,
|
|
60
74
|
generateSystemReply,
|
|
61
75
|
getAllDiscoveredExtensions,
|
|
@@ -98,15 +112,15 @@ import {
|
|
|
98
112
|
syncProviderToMinds,
|
|
99
113
|
uninstallNpmExtension,
|
|
100
114
|
writeSystemsConfig
|
|
101
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-U4FNXDEJ.js";
|
|
102
116
|
import {
|
|
103
117
|
loadMergedEnv,
|
|
104
118
|
mindEnvPath,
|
|
105
119
|
readEnv,
|
|
106
120
|
sharedEnvPath,
|
|
107
121
|
writeEnv
|
|
108
|
-
} from "./chunk-
|
|
109
|
-
import "./chunk-
|
|
122
|
+
} from "./chunk-5GT7URXJ.js";
|
|
123
|
+
import "./chunk-5AUKCNPE.js";
|
|
110
124
|
import {
|
|
111
125
|
applyInitFiles,
|
|
112
126
|
applyTemplateHomeFiles,
|
|
@@ -135,7 +149,7 @@ import {
|
|
|
135
149
|
syncBuiltinSkills,
|
|
136
150
|
uninstallSkill,
|
|
137
151
|
updateSkill
|
|
138
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-Y6OPHHGM.js";
|
|
139
153
|
import {
|
|
140
154
|
addMessage,
|
|
141
155
|
createChannel,
|
|
@@ -167,7 +181,7 @@ import {
|
|
|
167
181
|
setConversationPrivate,
|
|
168
182
|
subscribe as subscribe2,
|
|
169
183
|
updateChannelSettings
|
|
170
|
-
} from "./chunk-
|
|
184
|
+
} from "./chunk-JSRMEY52.js";
|
|
171
185
|
import {
|
|
172
186
|
readVoluteConfig,
|
|
173
187
|
writeVoluteConfig
|
|
@@ -175,15 +189,15 @@ import {
|
|
|
175
189
|
import {
|
|
176
190
|
isSandboxEnabled,
|
|
177
191
|
wrapForSandbox
|
|
178
|
-
} from "./chunk-
|
|
192
|
+
} from "./chunk-OXXTPILE.js";
|
|
179
193
|
import {
|
|
180
194
|
getActiveMinds,
|
|
181
195
|
onMindEvent,
|
|
182
196
|
stopAll
|
|
183
|
-
} from "./chunk-
|
|
197
|
+
} from "./chunk-HVU45COX.js";
|
|
184
198
|
import {
|
|
185
199
|
extractTextContent
|
|
186
|
-
} from "./chunk-
|
|
200
|
+
} from "./chunk-ZIR7HSAX.js";
|
|
187
201
|
import {
|
|
188
202
|
PROMPT_DEFAULTS,
|
|
189
203
|
PROMPT_KEYS,
|
|
@@ -192,10 +206,10 @@ import {
|
|
|
192
206
|
completeTurn,
|
|
193
207
|
createTurn,
|
|
194
208
|
getActiveTurnId,
|
|
195
|
-
getLastToolUseEventId,
|
|
196
209
|
getMindPromptDefaults,
|
|
197
210
|
getPrompt,
|
|
198
211
|
getPromptIfCustom,
|
|
212
|
+
getToolUseEventId,
|
|
199
213
|
initSummarizer,
|
|
200
214
|
markErrored,
|
|
201
215
|
publish as publish2,
|
|
@@ -206,8 +220,8 @@ import {
|
|
|
206
220
|
summarizeTurn,
|
|
207
221
|
takeErrored,
|
|
208
222
|
trackToolUse
|
|
209
|
-
} from "./chunk-
|
|
210
|
-
import "./chunk-
|
|
223
|
+
} from "./chunk-V4GYPD5L.js";
|
|
224
|
+
import "./chunk-Q2XBKQ2D.js";
|
|
211
225
|
import {
|
|
212
226
|
chownMindDir,
|
|
213
227
|
createMindUser,
|
|
@@ -218,7 +232,7 @@ import {
|
|
|
218
232
|
isIsolationEnabled,
|
|
219
233
|
resolveVoluteBin,
|
|
220
234
|
wrapForIsolation
|
|
221
|
-
} from "./chunk-
|
|
235
|
+
} from "./chunk-3ERIL673.js";
|
|
222
236
|
import {
|
|
223
237
|
addCustomModel,
|
|
224
238
|
buildCustomModel,
|
|
@@ -239,12 +253,12 @@ import {
|
|
|
239
253
|
setProviderRefreshHook,
|
|
240
254
|
setUtilityModel,
|
|
241
255
|
unqualifyModelId
|
|
242
|
-
} from "./chunk-
|
|
256
|
+
} from "./chunk-TSK5PI4L.js";
|
|
243
257
|
import {
|
|
244
258
|
isSetupComplete,
|
|
245
259
|
readGlobalConfig,
|
|
246
260
|
writeGlobalConfig
|
|
247
|
-
} from "./chunk-
|
|
261
|
+
} from "./chunk-322KE457.js";
|
|
248
262
|
import {
|
|
249
263
|
approveUser,
|
|
250
264
|
changePassword,
|
|
@@ -263,11 +277,11 @@ import {
|
|
|
263
277
|
syncMindProfile,
|
|
264
278
|
updateUserProfile,
|
|
265
279
|
verifyUser
|
|
266
|
-
} from "./chunk-
|
|
280
|
+
} from "./chunk-CYI534DJ.js";
|
|
267
281
|
import {
|
|
268
282
|
broadcast,
|
|
269
283
|
subscribe
|
|
270
|
-
} from "./chunk-
|
|
284
|
+
} from "./chunk-ZMIMSIIT.js";
|
|
271
285
|
import {
|
|
272
286
|
logBuffer,
|
|
273
287
|
logger_default
|
|
@@ -299,7 +313,7 @@ import {
|
|
|
299
313
|
validateMindName,
|
|
300
314
|
voluteHome,
|
|
301
315
|
voluteSystemDir
|
|
302
|
-
} from "./chunk-
|
|
316
|
+
} from "./chunk-H7IYFRAL.js";
|
|
303
317
|
import {
|
|
304
318
|
activity,
|
|
305
319
|
channels,
|
|
@@ -310,16 +324,80 @@ import {
|
|
|
310
324
|
systemPrompts,
|
|
311
325
|
turns,
|
|
312
326
|
users
|
|
313
|
-
} from "./chunk-
|
|
327
|
+
} from "./chunk-ZV7MFISX.js";
|
|
314
328
|
import "./chunk-K3NQKI34.js";
|
|
315
329
|
|
|
316
330
|
// packages/daemon/src/daemon.ts
|
|
317
|
-
import { randomBytes as
|
|
331
|
+
import { randomBytes as randomBytes3 } from "crypto";
|
|
318
332
|
import { chmodSync, mkdirSync as mkdirSync10, readFileSync as readFileSync10, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "fs";
|
|
319
333
|
import { homedir as homedir3 } from "os";
|
|
320
|
-
import { resolve as
|
|
334
|
+
import { resolve as resolve16 } from "path";
|
|
321
335
|
import { format } from "util";
|
|
322
336
|
|
|
337
|
+
// packages/daemon/src/lib/daemon/backup-manager.ts
|
|
338
|
+
import { CronExpressionParser } from "cron-parser";
|
|
339
|
+
var blog = logger_default.child("backup");
|
|
340
|
+
var DEFAULT_BACKUP_SCHEDULE = "0 3 * * *";
|
|
341
|
+
var BackupManager = class {
|
|
342
|
+
interval = null;
|
|
343
|
+
lastFiredMinute = -1;
|
|
344
|
+
warnedUnconfigured = false;
|
|
345
|
+
start() {
|
|
346
|
+
this.interval = setInterval(() => {
|
|
347
|
+
this.tick().catch((err) => blog.error("backup tick failed", logger_default.errorData(err)));
|
|
348
|
+
}, 6e4);
|
|
349
|
+
}
|
|
350
|
+
stop() {
|
|
351
|
+
if (this.interval) clearInterval(this.interval);
|
|
352
|
+
this.interval = null;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* True at most once per scheduled fire minute (records the minute it
|
|
356
|
+
* consumed), and only when backups are enabled and runnable. Not a pure
|
|
357
|
+
* predicate — a second call in the same minute returns false.
|
|
358
|
+
*/
|
|
359
|
+
isDue(now = /* @__PURE__ */ new Date()) {
|
|
360
|
+
const config2 = readGlobalConfig().backup;
|
|
361
|
+
if (!config2?.enabled) return false;
|
|
362
|
+
if (!config2.repository || !config2.password) {
|
|
363
|
+
if (!this.warnedUnconfigured) {
|
|
364
|
+
blog.warn("scheduled backups are enabled but no repository is initialized \u2014 not running");
|
|
365
|
+
this.warnedUnconfigured = true;
|
|
366
|
+
}
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
this.warnedUnconfigured = false;
|
|
370
|
+
const cron = config2.schedule || DEFAULT_BACKUP_SCHEDULE;
|
|
371
|
+
const epochMinute = Math.floor(now.getTime() / 6e4);
|
|
372
|
+
if (epochMinute === this.lastFiredMinute) return false;
|
|
373
|
+
let prevMinute;
|
|
374
|
+
try {
|
|
375
|
+
const interval = CronExpressionParser.parse(cron, { currentDate: now });
|
|
376
|
+
prevMinute = Math.floor(interval.prev().toDate().getTime() / 6e4);
|
|
377
|
+
} catch (err) {
|
|
378
|
+
blog.warn(`invalid backup cron "${cron}"`, logger_default.errorData(err));
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
if (prevMinute !== epochMinute) return false;
|
|
382
|
+
this.lastFiredMinute = epochMinute;
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
async tick() {
|
|
386
|
+
if (!this.isDue()) return;
|
|
387
|
+
blog.info("scheduled backup starting");
|
|
388
|
+
try {
|
|
389
|
+
await runBackup();
|
|
390
|
+
} catch (err) {
|
|
391
|
+
blog.error("scheduled backup failed", logger_default.errorData(err));
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
var backupManager = null;
|
|
396
|
+
function initBackupManager() {
|
|
397
|
+
if (!backupManager) backupManager = new BackupManager();
|
|
398
|
+
return backupManager;
|
|
399
|
+
}
|
|
400
|
+
|
|
323
401
|
// packages/daemon/src/lib/daemon/bridge-manager.ts
|
|
324
402
|
import { spawn } from "child_process";
|
|
325
403
|
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, unlinkSync, writeFileSync } from "fs";
|
|
@@ -388,7 +466,7 @@ function checkMissingBridgeEnv(def, env) {
|
|
|
388
466
|
}
|
|
389
467
|
|
|
390
468
|
// packages/daemon/src/lib/daemon/bridge-manager.ts
|
|
391
|
-
var
|
|
469
|
+
var blog2 = logger_default.child("bridges");
|
|
392
470
|
function searchUpwards(...segments) {
|
|
393
471
|
let searchDir = dirname(new URL(import.meta.url).pathname);
|
|
394
472
|
for (let i = 0; i < 5; i++) {
|
|
@@ -409,7 +487,7 @@ var BridgeManager = class {
|
|
|
409
487
|
await Promise.all(
|
|
410
488
|
platforms.map(
|
|
411
489
|
(platform) => this.startBridge(platform, daemonPort).catch((err) => {
|
|
412
|
-
|
|
490
|
+
blog2.warn(`failed to start bridge ${platform}`, logger_default.errorData(err));
|
|
413
491
|
})
|
|
414
492
|
)
|
|
415
493
|
);
|
|
@@ -438,7 +516,7 @@ var BridgeManager = class {
|
|
|
438
516
|
}
|
|
439
517
|
} catch (err) {
|
|
440
518
|
if (err instanceof Error && err.code !== "ESRCH") {
|
|
441
|
-
|
|
519
|
+
blog2.warn(`failed to stop existing bridge ${platform}`, logger_default.errorData(err));
|
|
442
520
|
}
|
|
443
521
|
res();
|
|
444
522
|
}
|
|
@@ -503,32 +581,32 @@ var BridgeManager = class {
|
|
|
503
581
|
}
|
|
504
582
|
if (this.shuttingDown) return;
|
|
505
583
|
if (this.stopping.has(platform)) return;
|
|
506
|
-
|
|
507
|
-
if (lastStderr)
|
|
584
|
+
blog2.error(`bridge ${platform} exited with code ${code}`);
|
|
585
|
+
if (lastStderr) blog2.warn(`bridge ${platform} last output: ${lastStderr}`);
|
|
508
586
|
const { shouldRestart, delay, attempt } = this.restartTracker.recordCrash(platform);
|
|
509
587
|
if (!shouldRestart) {
|
|
510
|
-
|
|
588
|
+
blog2.error(`bridge ${platform} crashed ${attempt} times \u2014 giving up`);
|
|
511
589
|
return;
|
|
512
590
|
}
|
|
513
|
-
|
|
591
|
+
blog2.info(
|
|
514
592
|
`restarting bridge ${platform} \u2014 attempt ${attempt}/${this.restartTracker.maxRestartAttempts}, in ${delay}ms`
|
|
515
593
|
);
|
|
516
594
|
setTimeout(() => {
|
|
517
595
|
if (this.shuttingDown || this.stopping.has(platform)) return;
|
|
518
596
|
this.startBridge(platform, daemonPort).catch((err) => {
|
|
519
|
-
|
|
597
|
+
blog2.error(`failed to restart bridge ${platform}`, logger_default.errorData(err));
|
|
520
598
|
});
|
|
521
599
|
}, delay);
|
|
522
600
|
});
|
|
523
|
-
|
|
601
|
+
blog2.info(`started bridge ${platform}`);
|
|
524
602
|
}
|
|
525
603
|
async stopBridge(platform) {
|
|
526
604
|
const tracked = this.bridges.get(platform);
|
|
527
605
|
if (!tracked) return;
|
|
528
606
|
this.stopping.add(platform);
|
|
529
607
|
this.bridges.delete(platform);
|
|
530
|
-
await new Promise((
|
|
531
|
-
tracked.child.on("exit", () =>
|
|
608
|
+
await new Promise((resolve17) => {
|
|
609
|
+
tracked.child.on("exit", () => resolve17());
|
|
532
610
|
try {
|
|
533
611
|
if (tracked.child.pid) {
|
|
534
612
|
process.kill(-tracked.child.pid, "SIGTERM");
|
|
@@ -537,9 +615,9 @@ var BridgeManager = class {
|
|
|
537
615
|
}
|
|
538
616
|
} catch (err) {
|
|
539
617
|
if (err instanceof Error && err.code !== "ESRCH") {
|
|
540
|
-
|
|
618
|
+
blog2.warn(`failed to stop bridge ${platform}`, logger_default.errorData(err));
|
|
541
619
|
}
|
|
542
|
-
|
|
620
|
+
resolve17();
|
|
543
621
|
}
|
|
544
622
|
setTimeout(() => {
|
|
545
623
|
try {
|
|
@@ -550,7 +628,7 @@ var BridgeManager = class {
|
|
|
550
628
|
}
|
|
551
629
|
} catch {
|
|
552
630
|
}
|
|
553
|
-
|
|
631
|
+
resolve17();
|
|
554
632
|
}, 5e3);
|
|
555
633
|
});
|
|
556
634
|
this.stopping.delete(platform);
|
|
@@ -558,9 +636,9 @@ var BridgeManager = class {
|
|
|
558
636
|
try {
|
|
559
637
|
this.removeBridgePid(platform);
|
|
560
638
|
} catch (err) {
|
|
561
|
-
|
|
639
|
+
blog2.warn(`failed to remove PID file for bridge ${platform}`, logger_default.errorData(err));
|
|
562
640
|
}
|
|
563
|
-
|
|
641
|
+
blog2.info(`stopped bridge ${platform}`);
|
|
564
642
|
}
|
|
565
643
|
async stopAll() {
|
|
566
644
|
this.shuttingDown = true;
|
|
@@ -590,7 +668,7 @@ var BridgeManager = class {
|
|
|
590
668
|
unlinkSync(this.bridgePidPath(platform));
|
|
591
669
|
} catch (err) {
|
|
592
670
|
if (err instanceof Error && err.code !== "ENOENT") {
|
|
593
|
-
|
|
671
|
+
blog2.warn(`failed to remove PID file for bridge ${platform}`, logger_default.errorData(err));
|
|
594
672
|
}
|
|
595
673
|
}
|
|
596
674
|
}
|
|
@@ -608,18 +686,18 @@ var BridgeManager = class {
|
|
|
608
686
|
} catch {
|
|
609
687
|
}
|
|
610
688
|
}
|
|
611
|
-
|
|
689
|
+
blog2.warn(`killed orphan bridge ${platform} (pid ${pid})`);
|
|
612
690
|
}
|
|
613
691
|
} catch (err) {
|
|
614
692
|
if (err instanceof Error && err.code !== "ESRCH") {
|
|
615
|
-
|
|
693
|
+
blog2.debug(`orphan bridge ${platform} cleanup: ${err}`);
|
|
616
694
|
}
|
|
617
695
|
}
|
|
618
696
|
try {
|
|
619
697
|
unlinkSync(pidPath);
|
|
620
698
|
} catch (err) {
|
|
621
699
|
if (err instanceof Error && err.code !== "ENOENT") {
|
|
622
|
-
|
|
700
|
+
blog2.warn(`failed to clean up PID file for orphan bridge ${platform}`, logger_default.errorData(err));
|
|
623
701
|
}
|
|
624
702
|
}
|
|
625
703
|
}
|
|
@@ -870,10 +948,10 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
870
948
|
stream.writeSSE({ data: JSON.stringify(entry) }).catch(() => {
|
|
871
949
|
});
|
|
872
950
|
});
|
|
873
|
-
await new Promise((
|
|
951
|
+
await new Promise((resolve17) => {
|
|
874
952
|
stream.onAbort(() => {
|
|
875
953
|
unsubscribe();
|
|
876
|
-
|
|
954
|
+
resolve17();
|
|
877
955
|
});
|
|
878
956
|
});
|
|
879
957
|
});
|
|
@@ -1217,8 +1295,8 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1217
1295
|
createdAt: Date.now()
|
|
1218
1296
|
};
|
|
1219
1297
|
oauthFlows.set(flowId, flow);
|
|
1220
|
-
const promptPromise = needsManualCode ? new Promise((
|
|
1221
|
-
flow.resolveCode =
|
|
1298
|
+
const promptPromise = needsManualCode ? new Promise((resolve17) => {
|
|
1299
|
+
flow.resolveCode = resolve17;
|
|
1222
1300
|
}) : void 0;
|
|
1223
1301
|
oauthProvider.login({
|
|
1224
1302
|
onAuth: (info) => {
|
|
@@ -1257,7 +1335,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1257
1335
|
existing.error = err instanceof Error ? err.message : String(err);
|
|
1258
1336
|
}
|
|
1259
1337
|
});
|
|
1260
|
-
await new Promise((
|
|
1338
|
+
await new Promise((resolve17) => setTimeout(resolve17, 2e3));
|
|
1261
1339
|
const state = oauthFlows.get(flowId);
|
|
1262
1340
|
return c.json({
|
|
1263
1341
|
flowId,
|
|
@@ -1451,7 +1529,7 @@ function stopApiKeyRefresh() {
|
|
|
1451
1529
|
var system_default = app;
|
|
1452
1530
|
|
|
1453
1531
|
// packages/daemon/src/web/app.ts
|
|
1454
|
-
import { Hono as
|
|
1532
|
+
import { Hono as Hono29 } from "hono";
|
|
1455
1533
|
import { bodyLimit } from "hono/body-limit";
|
|
1456
1534
|
import { cors } from "hono/cors";
|
|
1457
1535
|
import { csrf } from "hono/csrf";
|
|
@@ -1515,8 +1593,8 @@ var app2 = new Hono2().get("/events", async (c) => {
|
|
|
1515
1593
|
});
|
|
1516
1594
|
}, 15e3);
|
|
1517
1595
|
cleanups.push(() => clearInterval(keepAlive));
|
|
1518
|
-
await new Promise((
|
|
1519
|
-
stream.onAbort(() =>
|
|
1596
|
+
await new Promise((resolve17) => {
|
|
1597
|
+
stream.onAbort(() => resolve17());
|
|
1520
1598
|
});
|
|
1521
1599
|
} finally {
|
|
1522
1600
|
for (const cleanup of cleanups) {
|
|
@@ -1531,12 +1609,24 @@ var app2 = new Hono2().get("/events", async (c) => {
|
|
|
1531
1609
|
var activity_default = app2;
|
|
1532
1610
|
|
|
1533
1611
|
// packages/daemon/src/web/api/auth.ts
|
|
1534
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync2 } from "fs";
|
|
1612
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, rmSync, statSync, writeFileSync as writeFileSync2 } from "fs";
|
|
1535
1613
|
import { extname, resolve as resolve3 } from "path";
|
|
1536
1614
|
import { zValidator as zValidator2 } from "@hono/zod-validator";
|
|
1537
1615
|
import { Hono as Hono3 } from "hono";
|
|
1538
1616
|
import { deleteCookie, getCookie, setCookie } from "hono/cookie";
|
|
1539
1617
|
import { z as z2 } from "zod";
|
|
1618
|
+
|
|
1619
|
+
// packages/daemon/src/lib/util/http-cache.ts
|
|
1620
|
+
function fileEtag(stat3) {
|
|
1621
|
+
return `W/"${stat3.mtimeMs.toString(36)}-${stat3.size.toString(36)}"`;
|
|
1622
|
+
}
|
|
1623
|
+
function isNotModified(c, etag) {
|
|
1624
|
+
const inm = c.req.header("if-none-match");
|
|
1625
|
+
if (!inm) return false;
|
|
1626
|
+
return inm.split(",").some((t) => t.trim() === etag);
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
// packages/daemon/src/web/api/auth.ts
|
|
1540
1630
|
function tryJoinSystem(userId) {
|
|
1541
1631
|
if (!process.env.VOLUTE_DAEMON_TOKEN) return;
|
|
1542
1632
|
joinSystemChannel(userId).catch(() => {
|
|
@@ -1603,10 +1693,16 @@ var authenticated = new Hono3().use(authMiddleware).post("/change-password", zVa
|
|
|
1603
1693
|
if (!AVATAR_MIME[ext]) {
|
|
1604
1694
|
return c.json({ error: "Invalid file type (png, jpg, gif, webp only)" }, 400);
|
|
1605
1695
|
}
|
|
1696
|
+
let buffer2 = Buffer.from(await file.arrayBuffer());
|
|
1697
|
+
let finalExt = ext;
|
|
1698
|
+
const normalized = await normalizeAvatar(buffer2);
|
|
1699
|
+
if (normalized) {
|
|
1700
|
+
buffer2 = normalized.buffer;
|
|
1701
|
+
finalExt = normalized.ext;
|
|
1702
|
+
}
|
|
1606
1703
|
const dir = avatarsDir();
|
|
1607
1704
|
mkdirSync2(dir, { recursive: true });
|
|
1608
|
-
const filename = `avatar-${user.id}${
|
|
1609
|
-
const buffer2 = Buffer.from(await file.arrayBuffer());
|
|
1705
|
+
const filename = `avatar-${user.id}${finalExt}`;
|
|
1610
1706
|
writeFileSync2(resolve3(dir, filename), buffer2);
|
|
1611
1707
|
if (user.avatar && user.avatar !== filename) {
|
|
1612
1708
|
const oldPath = resolve3(dir, user.avatar);
|
|
@@ -1786,19 +1882,129 @@ var app3 = new Hono3().post("/register", zValidator2("json", credentialsSchema),
|
|
|
1786
1882
|
const ext = extname(filename).toLowerCase();
|
|
1787
1883
|
const mime = AVATAR_MIME[ext];
|
|
1788
1884
|
if (!mime) return c.json({ error: "Invalid file type" }, 400);
|
|
1789
|
-
const
|
|
1790
|
-
|
|
1885
|
+
const fileStat = statSync(filePath);
|
|
1886
|
+
const etag = fileEtag(fileStat);
|
|
1887
|
+
const headers = {
|
|
1791
1888
|
"Content-Type": mime,
|
|
1792
1889
|
"Cache-Control": "public, max-age=3600",
|
|
1793
|
-
"X-Content-Type-Options": "nosniff"
|
|
1794
|
-
|
|
1890
|
+
"X-Content-Type-Options": "nosniff",
|
|
1891
|
+
ETag: etag
|
|
1892
|
+
};
|
|
1893
|
+
if (isNotModified(c, etag)) return c.body(null, 304, headers);
|
|
1894
|
+
const data = readFileSync3(filePath);
|
|
1895
|
+
return c.body(data, 200, headers);
|
|
1795
1896
|
}).route("/", admin).route("/", authenticated);
|
|
1796
1897
|
var auth_default = app3;
|
|
1797
1898
|
|
|
1798
|
-
// packages/daemon/src/web/api/
|
|
1899
|
+
// packages/daemon/src/web/api/backup.ts
|
|
1900
|
+
import { randomBytes } from "crypto";
|
|
1799
1901
|
import { zValidator as zValidator3 } from "@hono/zod-validator";
|
|
1902
|
+
import { CronExpressionParser as CronExpressionParser2 } from "cron-parser";
|
|
1800
1903
|
import { Hono as Hono4 } from "hono";
|
|
1801
1904
|
import { z as z3 } from "zod";
|
|
1905
|
+
function redactedConfig() {
|
|
1906
|
+
const backup2 = readGlobalConfig().backup ?? {};
|
|
1907
|
+
return {
|
|
1908
|
+
repository: backup2.repository,
|
|
1909
|
+
schedule: backup2.schedule ?? DEFAULT_BACKUP_SCHEDULE,
|
|
1910
|
+
enabled: backup2.enabled,
|
|
1911
|
+
keep: backup2.keep,
|
|
1912
|
+
includeSessions: backup2.includeSessions,
|
|
1913
|
+
hasPassword: !!backup2.password,
|
|
1914
|
+
envKeys: Object.keys(backup2.env ?? {})
|
|
1915
|
+
};
|
|
1916
|
+
}
|
|
1917
|
+
var configSchema = z3.object({
|
|
1918
|
+
repository: z3.string().optional(),
|
|
1919
|
+
schedule: z3.string().refine(
|
|
1920
|
+
(cron) => {
|
|
1921
|
+
try {
|
|
1922
|
+
CronExpressionParser2.parse(cron);
|
|
1923
|
+
return true;
|
|
1924
|
+
} catch {
|
|
1925
|
+
return false;
|
|
1926
|
+
}
|
|
1927
|
+
},
|
|
1928
|
+
{ message: "Invalid cron expression" }
|
|
1929
|
+
).optional(),
|
|
1930
|
+
enabled: z3.boolean().optional(),
|
|
1931
|
+
keep: z3.object({
|
|
1932
|
+
daily: z3.number().int().min(0).optional(),
|
|
1933
|
+
weekly: z3.number().int().min(0).optional(),
|
|
1934
|
+
monthly: z3.number().int().min(0).optional()
|
|
1935
|
+
}).refine((keep) => !(keep.daily === 0 && keep.weekly === 0 && keep.monthly === 0), {
|
|
1936
|
+
message: "Retention cannot be zero everywhere \u2014 prune would delete every snapshot"
|
|
1937
|
+
}).optional(),
|
|
1938
|
+
includeSessions: z3.boolean().optional(),
|
|
1939
|
+
password: z3.string().optional(),
|
|
1940
|
+
env: z3.record(z3.string(), z3.string()).optional()
|
|
1941
|
+
});
|
|
1942
|
+
var backup = new Hono4().get("/config", requireAdmin, (c) => c.json(redactedConfig())).put("/config", requireAdmin, zValidator3("json", configSchema), (c) => {
|
|
1943
|
+
const updates = c.req.valid("json");
|
|
1944
|
+
const config2 = readGlobalConfig();
|
|
1945
|
+
const current = config2.backup ?? {};
|
|
1946
|
+
config2.backup = {
|
|
1947
|
+
...current,
|
|
1948
|
+
...updates,
|
|
1949
|
+
// Empty-string password means "keep existing" so the UI can save
|
|
1950
|
+
// settings without re-entering the passphrase.
|
|
1951
|
+
password: updates.password || current.password,
|
|
1952
|
+
env: updates.env ?? current.env
|
|
1953
|
+
};
|
|
1954
|
+
writeGlobalConfig(config2);
|
|
1955
|
+
return c.json(redactedConfig());
|
|
1956
|
+
}).post("/init", requireAdmin, async (c) => {
|
|
1957
|
+
const config2 = readGlobalConfig();
|
|
1958
|
+
if (!config2.backup?.repository) {
|
|
1959
|
+
return c.json({ error: "Backup repository is not configured" }, 400);
|
|
1960
|
+
}
|
|
1961
|
+
let generatedPassword = null;
|
|
1962
|
+
if (!config2.backup.password) {
|
|
1963
|
+
generatedPassword = randomBytes(32).toString("base64url");
|
|
1964
|
+
config2.backup.password = generatedPassword;
|
|
1965
|
+
}
|
|
1966
|
+
try {
|
|
1967
|
+
await initRepo(config2.backup);
|
|
1968
|
+
} catch (err) {
|
|
1969
|
+
const stderr = err.stderr;
|
|
1970
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
1971
|
+
return c.json({ error: stderr?.trim() || detail }, 500);
|
|
1972
|
+
}
|
|
1973
|
+
if (generatedPassword) writeGlobalConfig(config2);
|
|
1974
|
+
return c.json({ ok: true, password: generatedPassword });
|
|
1975
|
+
}).post("/run", requireAdmin, async (c) => {
|
|
1976
|
+
try {
|
|
1977
|
+
const summary = await runBackup();
|
|
1978
|
+
return c.json(summary);
|
|
1979
|
+
} catch (err) {
|
|
1980
|
+
const stderr = err.stderr;
|
|
1981
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
1982
|
+
return c.json({ error: stderr?.trim() || detail }, 500);
|
|
1983
|
+
}
|
|
1984
|
+
}).get("/snapshots", requireAdmin, async (c) => {
|
|
1985
|
+
try {
|
|
1986
|
+
return c.json(await listSnapshots());
|
|
1987
|
+
} catch (err) {
|
|
1988
|
+
const stderr = err.stderr;
|
|
1989
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
1990
|
+
return c.json({ error: stderr?.trim() || detail }, 500);
|
|
1991
|
+
}
|
|
1992
|
+
}).get("/status", requireAdmin, async (c) => {
|
|
1993
|
+
const version = await resticVersion();
|
|
1994
|
+
return c.json({
|
|
1995
|
+
resticInstalled: version !== null,
|
|
1996
|
+
resticVersion: version,
|
|
1997
|
+
installHint: version === null ? RESTIC_INSTALL_HINT : null,
|
|
1998
|
+
config: redactedConfig(),
|
|
1999
|
+
state: readBackupState()
|
|
2000
|
+
});
|
|
2001
|
+
});
|
|
2002
|
+
var backup_default = backup;
|
|
2003
|
+
|
|
2004
|
+
// packages/daemon/src/web/api/bridges.ts
|
|
2005
|
+
import { zValidator as zValidator4 } from "@hono/zod-validator";
|
|
2006
|
+
import { Hono as Hono5 } from "hono";
|
|
2007
|
+
import { z as z4 } from "zod";
|
|
1802
2008
|
|
|
1803
2009
|
// packages/daemon/src/lib/chat/puppets.ts
|
|
1804
2010
|
import { and as and2, eq as eq2 } from "drizzle-orm";
|
|
@@ -1847,17 +2053,6 @@ async function findOrCreatePuppet(platform, platformId, displayName) {
|
|
|
1847
2053
|
}
|
|
1848
2054
|
|
|
1849
2055
|
// packages/daemon/src/lib/delivery/fan-out.ts
|
|
1850
|
-
var MAX_CONSECUTIVE_MIND_TURNS = 6;
|
|
1851
|
-
var consecutiveMindTurns = /* @__PURE__ */ new Map();
|
|
1852
|
-
async function emitLoopNotice(conversationId) {
|
|
1853
|
-
const systemUser = await getOrCreateSystemUser();
|
|
1854
|
-
await addMessage(conversationId, "user", systemUser.username, [
|
|
1855
|
-
{
|
|
1856
|
-
type: "text",
|
|
1857
|
-
text: `[System] This exchange has continued for ${MAX_CONSECUTIVE_MIND_TURNS} consecutive automated turns without human input, so automatic delivery between minds has been paused. Send a message to resume.`
|
|
1858
|
-
}
|
|
1859
|
-
]);
|
|
1860
|
-
}
|
|
1861
2056
|
async function fanOutToMinds(opts) {
|
|
1862
2057
|
const participants = opts.participants ?? await getParticipants(opts.conversationId);
|
|
1863
2058
|
const mindParticipants = participants.filter(
|
|
@@ -1865,25 +2060,6 @@ async function fanOutToMinds(opts) {
|
|
|
1865
2060
|
);
|
|
1866
2061
|
const participantNames = participants.map((p) => p.username);
|
|
1867
2062
|
const isDM = opts.isDM ?? participants.length === 2;
|
|
1868
|
-
if (mindParticipants.length > 1) {
|
|
1869
|
-
if (opts.senderIsMind) {
|
|
1870
|
-
const count = (consecutiveMindTurns.get(opts.conversationId) ?? 0) + 1;
|
|
1871
|
-
consecutiveMindTurns.set(opts.conversationId, count);
|
|
1872
|
-
if (count > MAX_CONSECUTIVE_MIND_TURNS) {
|
|
1873
|
-
if (count === MAX_CONSECUTIVE_MIND_TURNS + 1) {
|
|
1874
|
-
await emitLoopNotice(opts.conversationId).catch(
|
|
1875
|
-
(err) => logger_default.warn(`failed to emit loop notice for ${opts.conversationId}`, logger_default.errorData(err))
|
|
1876
|
-
);
|
|
1877
|
-
}
|
|
1878
|
-
logger_default.warn(
|
|
1879
|
-
`loop protection: paused mind fan-out for ${opts.conversationId} after ${count} consecutive mind turns`
|
|
1880
|
-
);
|
|
1881
|
-
return;
|
|
1882
|
-
}
|
|
1883
|
-
} else {
|
|
1884
|
-
consecutiveMindTurns.delete(opts.conversationId);
|
|
1885
|
-
}
|
|
1886
|
-
}
|
|
1887
2063
|
const manager = getMindManager();
|
|
1888
2064
|
const sm = getSleepManagerIfReady();
|
|
1889
2065
|
const targetMinds = mindParticipants.map((ap) => {
|
|
@@ -1917,27 +2093,27 @@ async function fanOutToMinds(opts) {
|
|
|
1917
2093
|
}
|
|
1918
2094
|
|
|
1919
2095
|
// packages/daemon/src/web/api/bridges.ts
|
|
1920
|
-
var inboundSchema =
|
|
1921
|
-
content:
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
2096
|
+
var inboundSchema = z4.object({
|
|
2097
|
+
content: z4.array(
|
|
2098
|
+
z4.union([
|
|
2099
|
+
z4.object({ type: z4.literal("text"), text: z4.string() }),
|
|
2100
|
+
z4.object({ type: z4.literal("image"), media_type: z4.string(), data: z4.string() })
|
|
1925
2101
|
])
|
|
1926
2102
|
).min(1),
|
|
1927
|
-
platformUserId:
|
|
1928
|
-
displayName:
|
|
1929
|
-
externalChannel:
|
|
1930
|
-
isDM:
|
|
1931
|
-
targetMind:
|
|
2103
|
+
platformUserId: z4.string(),
|
|
2104
|
+
displayName: z4.string(),
|
|
2105
|
+
externalChannel: z4.string(),
|
|
2106
|
+
isDM: z4.boolean(),
|
|
2107
|
+
targetMind: z4.string().optional()
|
|
1932
2108
|
});
|
|
1933
|
-
var mappingSchema =
|
|
1934
|
-
externalChannel:
|
|
1935
|
-
voluteChannel:
|
|
2109
|
+
var mappingSchema = z4.object({
|
|
2110
|
+
externalChannel: z4.string(),
|
|
2111
|
+
voluteChannel: z4.string()
|
|
1936
2112
|
});
|
|
1937
|
-
var enableSchema =
|
|
1938
|
-
defaultMind:
|
|
2113
|
+
var enableSchema = z4.object({
|
|
2114
|
+
defaultMind: z4.string()
|
|
1939
2115
|
});
|
|
1940
|
-
var app4 = new
|
|
2116
|
+
var app4 = new Hono5().post("/:platform/inbound", zValidator4("json", inboundSchema), async (c) => {
|
|
1941
2117
|
const user = c.get("user");
|
|
1942
2118
|
if (user.id !== 0) return c.json({ error: "Bridge inbound requires daemon token" }, 403);
|
|
1943
2119
|
const platform = c.req.param("platform");
|
|
@@ -1989,7 +2165,7 @@ var app4 = new Hono4().post("/:platform/inbound", zValidator3("json", inboundSch
|
|
|
1989
2165
|
}
|
|
1990
2166
|
const participants = await getParticipants(channel.id);
|
|
1991
2167
|
if (!participants.some((p) => p.userId === puppet.id)) {
|
|
1992
|
-
const { addParticipant } = await import("./conversations-
|
|
2168
|
+
const { addParticipant } = await import("./conversations-G4LYMHAA.js");
|
|
1993
2169
|
await addParticipant(channel.id, puppet.id);
|
|
1994
2170
|
}
|
|
1995
2171
|
const contentBlocks = body.content;
|
|
@@ -2019,7 +2195,7 @@ var app4 = new Hono4().post("/:platform/inbound", zValidator3("json", inboundSch
|
|
|
2019
2195
|
};
|
|
2020
2196
|
});
|
|
2021
2197
|
return c.json(bridges);
|
|
2022
|
-
}).post("/:platform", requireAdmin,
|
|
2198
|
+
}).post("/:platform", requireAdmin, zValidator4("json", enableSchema), async (c) => {
|
|
2023
2199
|
const platform = c.req.param("platform");
|
|
2024
2200
|
const body = c.req.valid("json");
|
|
2025
2201
|
const def = getBridgeDef(platform);
|
|
@@ -2058,7 +2234,7 @@ var app4 = new Hono4().post("/:platform/inbound", zValidator3("json", inboundSch
|
|
|
2058
2234
|
await manager.stopBridge(platform);
|
|
2059
2235
|
removeBridgeConfig(platform);
|
|
2060
2236
|
return c.json({ ok: true });
|
|
2061
|
-
}).put("/:platform/mappings", requireAdmin,
|
|
2237
|
+
}).put("/:platform/mappings", requireAdmin, zValidator4("json", mappingSchema), (c) => {
|
|
2062
2238
|
const platform = c.req.param("platform");
|
|
2063
2239
|
const body = c.req.valid("json");
|
|
2064
2240
|
try {
|
|
@@ -2083,18 +2259,17 @@ async function fanOutToBridgedMinds(opts) {
|
|
|
2083
2259
|
conversationId: opts.conversationId,
|
|
2084
2260
|
contentBlocks: opts.contentBlocks,
|
|
2085
2261
|
senderName: opts.senderName,
|
|
2086
|
-
senderIsMind: false,
|
|
2087
2262
|
isDM: opts.isDM
|
|
2088
2263
|
});
|
|
2089
2264
|
}
|
|
2090
2265
|
var bridges_default = app4;
|
|
2091
2266
|
|
|
2092
2267
|
// packages/daemon/src/web/api/channels.ts
|
|
2093
|
-
import { Hono as
|
|
2268
|
+
import { Hono as Hono6 } from "hono";
|
|
2094
2269
|
function buildEnv(name) {
|
|
2095
2270
|
return { ...loadMergedEnv(name), VOLUTE_MIND: name, VOLUTE_MIND_DIR: mindDir(name) };
|
|
2096
2271
|
}
|
|
2097
|
-
var app5 = new
|
|
2272
|
+
var app5 = new Hono6().post("/:name/channels/create", requireSelf(), async (c) => {
|
|
2098
2273
|
const name = c.req.param("name");
|
|
2099
2274
|
if (!await findMind(name)) return c.json({ error: "Mind not found" }, 404);
|
|
2100
2275
|
const {
|
|
@@ -2119,8 +2294,8 @@ var app5 = new Hono5().post("/:name/channels/create", requireSelf(), async (c) =
|
|
|
2119
2294
|
var channels_default = app5;
|
|
2120
2295
|
|
|
2121
2296
|
// packages/daemon/src/web/api/config.ts
|
|
2122
|
-
import { Hono as
|
|
2123
|
-
var config = new
|
|
2297
|
+
import { Hono as Hono7 } from "hono";
|
|
2298
|
+
var config = new Hono7();
|
|
2124
2299
|
config.get("/models", async (c) => {
|
|
2125
2300
|
const enabled = new Set(getEnabledModels());
|
|
2126
2301
|
const all = await getAvailableModels();
|
|
@@ -2147,8 +2322,8 @@ config.get("/status", (c) => {
|
|
|
2147
2322
|
var config_default = config;
|
|
2148
2323
|
|
|
2149
2324
|
// packages/daemon/src/web/api/env.ts
|
|
2150
|
-
import { Hono as
|
|
2151
|
-
var app6 = new
|
|
2325
|
+
import { Hono as Hono8 } from "hono";
|
|
2326
|
+
var app6 = new Hono8().get("/:name/env", requireSelf(), async (c) => {
|
|
2152
2327
|
const name = c.req.param("name");
|
|
2153
2328
|
if (!await findMind(name)) return c.json({ error: "Mind not found" }, 404);
|
|
2154
2329
|
const shared = readEnv(sharedEnvPath());
|
|
@@ -2191,7 +2366,7 @@ var app6 = new Hono7().get("/:name/env", requireSelf(), async (c) => {
|
|
|
2191
2366
|
writeEnv(path, env);
|
|
2192
2367
|
return c.json({ ok: true });
|
|
2193
2368
|
});
|
|
2194
|
-
var sharedEnvApp = new
|
|
2369
|
+
var sharedEnvApp = new Hono8().get("/", requireAdmin, (c) => {
|
|
2195
2370
|
return c.json(readEnv(sharedEnvPath()));
|
|
2196
2371
|
}).put("/:key", requireAdmin, async (c) => {
|
|
2197
2372
|
const key = c.req.param("key");
|
|
@@ -2221,8 +2396,8 @@ var sharedEnvApp = new Hono7().get("/", requireAdmin, (c) => {
|
|
|
2221
2396
|
var env_default = app6;
|
|
2222
2397
|
|
|
2223
2398
|
// packages/daemon/src/web/api/extensions.ts
|
|
2224
|
-
import { Hono as
|
|
2225
|
-
var app7 = new
|
|
2399
|
+
import { Hono as Hono9 } from "hono";
|
|
2400
|
+
var app7 = new Hono9().get("/", (c) => {
|
|
2226
2401
|
return c.json(getLoadedExtensions());
|
|
2227
2402
|
}).get("/all", (c) => {
|
|
2228
2403
|
const detail = c.req.query("detail") === "true";
|
|
@@ -2267,20 +2442,20 @@ var app7 = new Hono8().get("/", (c) => {
|
|
|
2267
2442
|
var extensions_default = app7;
|
|
2268
2443
|
|
|
2269
2444
|
// packages/daemon/src/web/api/file-sharing.ts
|
|
2270
|
-
import { readFileSync as readFileSync4, statSync } from "fs";
|
|
2445
|
+
import { readFileSync as readFileSync4, statSync as statSync2 } from "fs";
|
|
2271
2446
|
import { resolve as resolve4 } from "path";
|
|
2272
|
-
import { Hono as
|
|
2447
|
+
import { Hono as Hono10 } from "hono";
|
|
2273
2448
|
async function notifyMind(mindName, message) {
|
|
2274
2449
|
const entry = await findMind(mindName);
|
|
2275
2450
|
if (!entry) return;
|
|
2276
2451
|
try {
|
|
2277
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
2452
|
+
const { sendSystemMessage } = await import("./system-chat-E65T2HSW.js");
|
|
2278
2453
|
await sendSystemMessage(mindName, message);
|
|
2279
2454
|
} catch (err) {
|
|
2280
2455
|
logger_default.warn(`[file-sharing] notify mind ${mindName} failed`, logger_default.errorData(err));
|
|
2281
2456
|
}
|
|
2282
2457
|
}
|
|
2283
|
-
var app8 = new
|
|
2458
|
+
var app8 = new Hono10().post("/:name/files/send", requireSelf(), async (c) => {
|
|
2284
2459
|
const senderName = c.req.param("name");
|
|
2285
2460
|
const senderEntry = await findMind(senderName);
|
|
2286
2461
|
if (!senderEntry) return c.json({ error: "Sender mind not found" }, 404);
|
|
@@ -2295,7 +2470,7 @@ var app8 = new Hono9().post("/:name/files/send", requireSelf(), async (c) => {
|
|
|
2295
2470
|
const senderDir = mindDir(senderName);
|
|
2296
2471
|
const filePath = resolve4(senderDir, "home", body.filePath);
|
|
2297
2472
|
const MAX_FILE_SIZE3 = 50 * 1024 * 1024;
|
|
2298
|
-
const stat3 =
|
|
2473
|
+
const stat3 = statSync2(filePath, { throwIfNoEntry: false });
|
|
2299
2474
|
if (!stat3) return c.json({ error: `File not found: ${body.filePath}` }, 404);
|
|
2300
2475
|
if (stat3.size > MAX_FILE_SIZE3) {
|
|
2301
2476
|
return c.json(
|
|
@@ -2399,34 +2574,8 @@ var file_sharing_default = app8;
|
|
|
2399
2574
|
// packages/daemon/src/web/api/files.ts
|
|
2400
2575
|
import { mkdirSync as mkdirSync3, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
2401
2576
|
import { readdir, readFile, realpath, stat } from "fs/promises";
|
|
2402
|
-
import { extname as extname2, resolve as
|
|
2403
|
-
import { Hono as
|
|
2404
|
-
|
|
2405
|
-
// packages/daemon/src/lib/util/paths.ts
|
|
2406
|
-
import { resolve as resolve5, sep } from "path";
|
|
2407
|
-
var PathTraversalError = class extends Error {
|
|
2408
|
-
constructor(base, userPath) {
|
|
2409
|
-
super(`Path "${userPath}" escapes base directory "${base}"`);
|
|
2410
|
-
this.name = "PathTraversalError";
|
|
2411
|
-
}
|
|
2412
|
-
};
|
|
2413
|
-
function resolveWithinBase(base, userPath) {
|
|
2414
|
-
const resolvedBase = resolve5(base);
|
|
2415
|
-
const target = resolve5(resolvedBase, userPath);
|
|
2416
|
-
if (target !== resolvedBase && !target.startsWith(resolvedBase + sep)) {
|
|
2417
|
-
throw new PathTraversalError(base, userPath);
|
|
2418
|
-
}
|
|
2419
|
-
return target;
|
|
2420
|
-
}
|
|
2421
|
-
function safeResolveWithinBase(base, userPath) {
|
|
2422
|
-
try {
|
|
2423
|
-
return resolveWithinBase(base, userPath);
|
|
2424
|
-
} catch {
|
|
2425
|
-
return null;
|
|
2426
|
-
}
|
|
2427
|
-
}
|
|
2428
|
-
|
|
2429
|
-
// packages/daemon/src/web/api/files.ts
|
|
2577
|
+
import { extname as extname2, resolve as resolve5 } from "path";
|
|
2578
|
+
import { Hono as Hono11 } from "hono";
|
|
2430
2579
|
var AVATAR_MIME2 = {
|
|
2431
2580
|
".png": "image/png",
|
|
2432
2581
|
".jpg": "image/jpeg",
|
|
@@ -2453,7 +2602,7 @@ var MIME_TYPES = {
|
|
|
2453
2602
|
".woff": "font/woff",
|
|
2454
2603
|
".woff2": "font/woff2"
|
|
2455
2604
|
};
|
|
2456
|
-
var app9 = new
|
|
2605
|
+
var app9 = new Hono11().post("/:name/avatar", requireSelf(), async (c) => {
|
|
2457
2606
|
const name = c.req.param("name");
|
|
2458
2607
|
const entry = await findMind(name);
|
|
2459
2608
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
@@ -2469,17 +2618,23 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
2469
2618
|
if (!AVATAR_MIME2[ext]) {
|
|
2470
2619
|
return c.json({ error: "Invalid file type (png, jpg, gif, webp only)" }, 400);
|
|
2471
2620
|
}
|
|
2621
|
+
let buffer2 = Buffer.from(await file.arrayBuffer());
|
|
2622
|
+
let finalExt = ext;
|
|
2623
|
+
const normalized = await normalizeAvatar(buffer2);
|
|
2624
|
+
if (normalized) {
|
|
2625
|
+
buffer2 = normalized.buffer;
|
|
2626
|
+
finalExt = normalized.ext;
|
|
2627
|
+
}
|
|
2472
2628
|
const dir = entry.dir ?? mindDir(name);
|
|
2473
|
-
const homeDir =
|
|
2474
|
-
const filename = `avatar${
|
|
2475
|
-
const avatarPath =
|
|
2629
|
+
const homeDir = resolve5(dir, "home");
|
|
2630
|
+
const filename = `avatar${finalExt}`;
|
|
2631
|
+
const avatarPath = resolve5(homeDir, filename);
|
|
2476
2632
|
const config2 = readVoluteConfig(dir) ?? {};
|
|
2477
2633
|
const oldAvatar = config2.profile?.avatar;
|
|
2478
2634
|
if (oldAvatar && oldAvatar !== filename) {
|
|
2479
2635
|
const oldAvatarPath = safeResolveWithinBase(homeDir, oldAvatar);
|
|
2480
2636
|
if (oldAvatarPath) rmSync2(oldAvatarPath, { force: true });
|
|
2481
2637
|
}
|
|
2482
|
-
const buffer2 = Buffer.from(await file.arrayBuffer());
|
|
2483
2638
|
mkdirSync3(homeDir, { recursive: true });
|
|
2484
2639
|
writeFileSync3(avatarPath, buffer2);
|
|
2485
2640
|
const profile = config2.profile ?? {};
|
|
@@ -2499,8 +2654,8 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
2499
2654
|
const ext = extname2(config2.profile.avatar).toLowerCase();
|
|
2500
2655
|
const mime = AVATAR_MIME2[ext];
|
|
2501
2656
|
if (!mime) return c.json({ error: "Invalid avatar extension" }, 400);
|
|
2502
|
-
const homeDir =
|
|
2503
|
-
const avatarPath =
|
|
2657
|
+
const homeDir = resolve5(dir, "home");
|
|
2658
|
+
const avatarPath = resolve5(homeDir, config2.profile.avatar);
|
|
2504
2659
|
if (!avatarPath.startsWith(`${homeDir}/`)) return c.json({ error: "Invalid avatar path" }, 400);
|
|
2505
2660
|
let realAvatarPath;
|
|
2506
2661
|
try {
|
|
@@ -2516,11 +2671,15 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
2516
2671
|
try {
|
|
2517
2672
|
const fileStat = await stat(realAvatarPath);
|
|
2518
2673
|
if (fileStat.size > MAX_AVATAR_SIZE2) return c.json({ error: "Avatar file too large" }, 400);
|
|
2519
|
-
const
|
|
2520
|
-
|
|
2674
|
+
const etag = fileEtag(fileStat);
|
|
2675
|
+
const headers = {
|
|
2521
2676
|
"Content-Type": mime,
|
|
2522
|
-
"Cache-Control": "public, max-age=300"
|
|
2523
|
-
|
|
2677
|
+
"Cache-Control": "public, max-age=300",
|
|
2678
|
+
ETag: etag
|
|
2679
|
+
};
|
|
2680
|
+
if (isNotModified(c, etag)) return c.body(null, 304, headers);
|
|
2681
|
+
const body = await readFile(realAvatarPath);
|
|
2682
|
+
return c.body(body, 200, headers);
|
|
2524
2683
|
} catch {
|
|
2525
2684
|
return c.json({ error: "Failed to read avatar file" }, 500);
|
|
2526
2685
|
}
|
|
@@ -2528,7 +2687,7 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
2528
2687
|
const name = c.req.param("name");
|
|
2529
2688
|
const entry = await findMind(name);
|
|
2530
2689
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
2531
|
-
const homeDir =
|
|
2690
|
+
const homeDir = resolve5(entry.dir ?? mindDir(name), "home");
|
|
2532
2691
|
let entries;
|
|
2533
2692
|
try {
|
|
2534
2693
|
entries = await readdir(homeDir, { withFileTypes: true });
|
|
@@ -2543,10 +2702,10 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
2543
2702
|
const name = c.req.param("name");
|
|
2544
2703
|
const entry = await findMind(name);
|
|
2545
2704
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
2546
|
-
const homeDir =
|
|
2705
|
+
const homeDir = resolve5(entry.dir ?? mindDir(name), "home");
|
|
2547
2706
|
const wildcard = c.req.path.replace(new RegExp(`^.*/minds/${name}/files`), "") || "/";
|
|
2548
2707
|
const relativePath = wildcard.slice(1);
|
|
2549
|
-
const requestedPath =
|
|
2708
|
+
const requestedPath = resolve5(homeDir, relativePath);
|
|
2550
2709
|
if (requestedPath !== homeDir && !requestedPath.startsWith(`${homeDir}/`))
|
|
2551
2710
|
return c.text("Forbidden", 403);
|
|
2552
2711
|
if (relativePath.split("/").some((seg) => seg.startsWith("."))) return c.text("Forbidden", 403);
|
|
@@ -2577,15 +2736,18 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
2577
2736
|
return c.json(items);
|
|
2578
2737
|
}
|
|
2579
2738
|
if (fileStat.size > MAX_FILE_SIZE) return c.text("File too large", 413);
|
|
2580
|
-
const body = await readFile(resolvedPath);
|
|
2581
2739
|
const mime = MIME_TYPES[extname2(resolvedPath).toLowerCase()] || "application/octet-stream";
|
|
2582
|
-
|
|
2740
|
+
const etag = fileEtag(fileStat);
|
|
2741
|
+
const headers = { "Content-Type": mime, "Cache-Control": "no-cache", ETag: etag };
|
|
2742
|
+
if (isNotModified(c, etag)) return c.body(null, 304, headers);
|
|
2743
|
+
const body = await readFile(resolvedPath);
|
|
2744
|
+
return c.body(body, 200, headers);
|
|
2583
2745
|
});
|
|
2584
2746
|
var files_default = app9;
|
|
2585
2747
|
|
|
2586
2748
|
// packages/daemon/src/web/api/history.ts
|
|
2587
2749
|
import { and as and3, desc as desc2, eq as eq3, gte, inArray, sql } from "drizzle-orm";
|
|
2588
|
-
import { Hono as
|
|
2750
|
+
import { Hono as Hono12 } from "hono";
|
|
2589
2751
|
async function resolveMindFilter(c) {
|
|
2590
2752
|
const user = c.get("user");
|
|
2591
2753
|
if (user.role === "admin" || user.role === "system") {
|
|
@@ -2593,7 +2755,7 @@ async function resolveMindFilter(c) {
|
|
|
2593
2755
|
}
|
|
2594
2756
|
return getBaseName(user.username);
|
|
2595
2757
|
}
|
|
2596
|
-
var history = new
|
|
2758
|
+
var history = new Hono12().get("/turns", async (c) => {
|
|
2597
2759
|
const mindFilter = await resolveMindFilter(c);
|
|
2598
2760
|
const turnIdFilter = c.req.query("turnId");
|
|
2599
2761
|
const turnIdsFilter = c.req.query("turnIds");
|
|
@@ -2984,21 +3146,21 @@ var history = new Hono11().get("/turns", async (c) => {
|
|
|
2984
3146
|
var history_default = history;
|
|
2985
3147
|
|
|
2986
3148
|
// packages/daemon/src/web/api/keys.ts
|
|
2987
|
-
import { Hono as
|
|
3149
|
+
import { Hono as Hono13 } from "hono";
|
|
2988
3150
|
|
|
2989
3151
|
// packages/daemon/src/lib/mind/identity.ts
|
|
2990
3152
|
import { createHash, generateKeyPairSync, sign, verify } from "crypto";
|
|
2991
3153
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
2992
|
-
import { resolve as
|
|
3154
|
+
import { resolve as resolve6 } from "path";
|
|
2993
3155
|
function generateIdentity(mindDir2) {
|
|
2994
|
-
const identityDir =
|
|
3156
|
+
const identityDir = resolve6(mindDir2, ".mind/identity");
|
|
2995
3157
|
mkdirSync4(identityDir, { recursive: true });
|
|
2996
3158
|
const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
|
|
2997
3159
|
publicKeyEncoding: { type: "spki", format: "pem" },
|
|
2998
3160
|
privateKeyEncoding: { type: "pkcs8", format: "pem" }
|
|
2999
3161
|
});
|
|
3000
|
-
const privatePath =
|
|
3001
|
-
const publicPath =
|
|
3162
|
+
const privatePath = resolve6(identityDir, "private.pem");
|
|
3163
|
+
const publicPath = resolve6(identityDir, "public.pem");
|
|
3002
3164
|
writeFileSync4(privatePath, privateKey, { mode: 384 });
|
|
3003
3165
|
writeFileSync4(publicPath, publicKey, { mode: 420 });
|
|
3004
3166
|
const config2 = readVoluteConfig(mindDir2) ?? {};
|
|
@@ -3013,7 +3175,7 @@ function getPublicKey(mindDir2) {
|
|
|
3013
3175
|
const config2 = readVoluteConfig(mindDir2);
|
|
3014
3176
|
const relPath = config2?.identity?.publicKey;
|
|
3015
3177
|
if (!relPath) return null;
|
|
3016
|
-
const fullPath =
|
|
3178
|
+
const fullPath = resolve6(mindDir2, relPath);
|
|
3017
3179
|
if (!existsSync4(fullPath)) return null;
|
|
3018
3180
|
return readFileSync5(fullPath, "utf-8");
|
|
3019
3181
|
}
|
|
@@ -3044,7 +3206,7 @@ async function publishPublicKey(mindName, publicKeyPem) {
|
|
|
3044
3206
|
}
|
|
3045
3207
|
|
|
3046
3208
|
// packages/daemon/src/web/api/keys.ts
|
|
3047
|
-
var app10 = new
|
|
3209
|
+
var app10 = new Hono13().get("/:fingerprint", async (c) => {
|
|
3048
3210
|
const fingerprint = c.req.param("fingerprint");
|
|
3049
3211
|
for (const entry of await readRegistry()) {
|
|
3050
3212
|
try {
|
|
@@ -3063,14 +3225,14 @@ var keys_default = app10;
|
|
|
3063
3225
|
// packages/daemon/src/web/api/logs.ts
|
|
3064
3226
|
import { spawn as spawn2 } from "child_process";
|
|
3065
3227
|
import { existsSync as existsSync5 } from "fs";
|
|
3066
|
-
import { resolve as
|
|
3067
|
-
import { Hono as
|
|
3228
|
+
import { resolve as resolve7 } from "path";
|
|
3229
|
+
import { Hono as Hono14 } from "hono";
|
|
3068
3230
|
import { streamSSE as streamSSE3 } from "hono/streaming";
|
|
3069
|
-
var app11 = new
|
|
3231
|
+
var app11 = new Hono14().get("/:name/logs", requireSelf(), async (c) => {
|
|
3070
3232
|
const name = c.req.param("name");
|
|
3071
3233
|
const entry = await findMind(name);
|
|
3072
3234
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
3073
|
-
const logFile =
|
|
3235
|
+
const logFile = resolve7(stateDir(name), "logs", "mind.log");
|
|
3074
3236
|
if (!existsSync5(logFile)) {
|
|
3075
3237
|
return c.json({ error: "No log file found" }, 404);
|
|
3076
3238
|
}
|
|
@@ -3089,16 +3251,16 @@ var app11 = new Hono13().get("/:name/logs", requireSelf(), async (c) => {
|
|
|
3089
3251
|
stream.onAbort(() => {
|
|
3090
3252
|
tail.kill();
|
|
3091
3253
|
});
|
|
3092
|
-
await new Promise((
|
|
3093
|
-
tail.on("exit",
|
|
3094
|
-
stream.onAbort(
|
|
3254
|
+
await new Promise((resolve17) => {
|
|
3255
|
+
tail.on("exit", resolve17);
|
|
3256
|
+
stream.onAbort(resolve17);
|
|
3095
3257
|
});
|
|
3096
3258
|
});
|
|
3097
3259
|
}).get("/:name/logs/tail", requireSelf(), async (c) => {
|
|
3098
3260
|
const name = c.req.param("name");
|
|
3099
3261
|
const entry = await findMind(name);
|
|
3100
3262
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
3101
|
-
const logFile =
|
|
3263
|
+
const logFile = resolve7(stateDir(name), "logs", "mind.log");
|
|
3102
3264
|
if (!existsSync5(logFile)) {
|
|
3103
3265
|
return c.json({ error: "No log file found" }, 404);
|
|
3104
3266
|
}
|
|
@@ -3109,18 +3271,18 @@ var app11 = new Hono13().get("/:name/logs", requireSelf(), async (c) => {
|
|
|
3109
3271
|
tail.stdout.on("data", (data) => {
|
|
3110
3272
|
output += data.toString();
|
|
3111
3273
|
});
|
|
3112
|
-
await new Promise((
|
|
3113
|
-
tail.on("exit",
|
|
3274
|
+
await new Promise((resolve17) => {
|
|
3275
|
+
tail.on("exit", resolve17);
|
|
3114
3276
|
});
|
|
3115
3277
|
return c.text(output);
|
|
3116
3278
|
});
|
|
3117
3279
|
var logs_default = app11;
|
|
3118
3280
|
|
|
3119
3281
|
// packages/daemon/src/web/api/mind-skills.ts
|
|
3120
|
-
import { zValidator as
|
|
3121
|
-
import { Hono as
|
|
3122
|
-
import { z as
|
|
3123
|
-
var app12 = new
|
|
3282
|
+
import { zValidator as zValidator5 } from "@hono/zod-validator";
|
|
3283
|
+
import { Hono as Hono15 } from "hono";
|
|
3284
|
+
import { z as z5 } from "zod";
|
|
3285
|
+
var app12 = new Hono15().get("/:name/skills", async (c) => {
|
|
3124
3286
|
const name = c.req.param("name");
|
|
3125
3287
|
const entry = await findMind(name);
|
|
3126
3288
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
@@ -3130,7 +3292,7 @@ var app12 = new Hono14().get("/:name/skills", async (c) => {
|
|
|
3130
3292
|
}).post(
|
|
3131
3293
|
"/:name/skills/install",
|
|
3132
3294
|
requireSelf(),
|
|
3133
|
-
|
|
3295
|
+
zValidator5("json", z5.object({ skillId: z5.string() })),
|
|
3134
3296
|
async (c) => {
|
|
3135
3297
|
const name = c.req.param("name");
|
|
3136
3298
|
const entry = await findMind(name);
|
|
@@ -3148,7 +3310,7 @@ var app12 = new Hono14().get("/:name/skills", async (c) => {
|
|
|
3148
3310
|
).post(
|
|
3149
3311
|
"/:name/skills/update",
|
|
3150
3312
|
requireSelf(),
|
|
3151
|
-
|
|
3313
|
+
zValidator5("json", z5.object({ skillId: z5.string() })),
|
|
3152
3314
|
async (c) => {
|
|
3153
3315
|
const name = c.req.param("name");
|
|
3154
3316
|
const entry = await findMind(name);
|
|
@@ -3166,7 +3328,7 @@ var app12 = new Hono14().get("/:name/skills", async (c) => {
|
|
|
3166
3328
|
).post(
|
|
3167
3329
|
"/:name/skills/publish",
|
|
3168
3330
|
requireSelf(),
|
|
3169
|
-
|
|
3331
|
+
zValidator5("json", z5.object({ skillId: z5.string() })),
|
|
3170
3332
|
async (c) => {
|
|
3171
3333
|
const name = c.req.param("name");
|
|
3172
3334
|
const entry = await findMind(name);
|
|
@@ -3207,11 +3369,11 @@ import {
|
|
|
3207
3369
|
rmSync as rmSync4,
|
|
3208
3370
|
writeFileSync as writeFileSync7
|
|
3209
3371
|
} from "fs";
|
|
3210
|
-
import {
|
|
3211
|
-
import { zValidator as
|
|
3372
|
+
import { relative, resolve as resolve10 } from "path";
|
|
3373
|
+
import { zValidator as zValidator6 } from "@hono/zod-validator";
|
|
3212
3374
|
import { and as and5, desc as desc4, eq as eq5, sql as sql3 } from "drizzle-orm";
|
|
3213
|
-
import { Hono as
|
|
3214
|
-
import { z as
|
|
3375
|
+
import { Hono as Hono16 } from "hono";
|
|
3376
|
+
import { z as z6 } from "zod";
|
|
3215
3377
|
|
|
3216
3378
|
// packages/daemon/src/lib/daemon/turn-lifecycle.ts
|
|
3217
3379
|
import { and as and4, desc as desc3, eq as eq4, inArray as inArray2, sql as sql2 } from "drizzle-orm";
|
|
@@ -3328,13 +3490,18 @@ async function handleMindEvent(mind, event) {
|
|
|
3328
3490
|
}).returning({ id: mindHistory.id });
|
|
3329
3491
|
insertedId = result[0]?.id;
|
|
3330
3492
|
} catch (err) {
|
|
3331
|
-
llog.error(
|
|
3493
|
+
llog.error(
|
|
3494
|
+
`HISTORY GAP: failed to persist ${event.type} event for ${mind}${event.session ? ` (session ${event.session})` : ""}${event.channel ? ` on ${event.channel}` : ""}`,
|
|
3495
|
+
logger_default.errorData(err)
|
|
3496
|
+
);
|
|
3332
3497
|
}
|
|
3333
3498
|
if (event.type === "tool_use" && insertedId != null) {
|
|
3334
|
-
|
|
3499
|
+
const toolUseId = typeof event.metadata?.id === "string" ? event.metadata.id : void 0;
|
|
3500
|
+
trackToolUse(mind, event.session, insertedId, toolUseId);
|
|
3335
3501
|
}
|
|
3336
3502
|
if (event.type === "tool_result" && turnId && event.content) {
|
|
3337
|
-
const
|
|
3503
|
+
const resultToolUseId = typeof event.metadata?.tool_use_id === "string" ? event.metadata.tool_use_id : void 0;
|
|
3504
|
+
const toolUseEventId = getToolUseEventId(mind, event.session, resultToolUseId);
|
|
3338
3505
|
try {
|
|
3339
3506
|
await linkToolResultToTurn(mind, turnId, event.content, toolUseEventId);
|
|
3340
3507
|
} catch (err) {
|
|
@@ -3397,7 +3564,7 @@ async function handleMindEvent(mind, event) {
|
|
|
3397
3564
|
session: event.session,
|
|
3398
3565
|
kind: "budget",
|
|
3399
3566
|
reason: "token_budget",
|
|
3400
|
-
detail: "You've
|
|
3567
|
+
detail: "You've used your token budget for this period, so your activity may pause until it resets. This isn't anything you did wrong \u2014 it's just a rest imposed by the budget. Anything that arrives while you're paused will be kept for you. If you're mid-thought, this turn is a good moment to jot it down."
|
|
3401
3568
|
});
|
|
3402
3569
|
}
|
|
3403
3570
|
}
|
|
@@ -3427,18 +3594,18 @@ async function completeTurnAndSummarize(mind, event, insertedId) {
|
|
|
3427
3594
|
|
|
3428
3595
|
// packages/daemon/src/lib/mind/consolidate.ts
|
|
3429
3596
|
import { readdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
3430
|
-
import { resolve as
|
|
3597
|
+
import { resolve as resolve8 } from "path";
|
|
3431
3598
|
async function consolidateMemory(mindDir2) {
|
|
3432
|
-
const soulPath =
|
|
3433
|
-
const memoryPath =
|
|
3434
|
-
const memoryDir =
|
|
3599
|
+
const soulPath = resolve8(mindDir2, "home/SOUL.md");
|
|
3600
|
+
const memoryPath = resolve8(mindDir2, "home/MEMORY.md");
|
|
3601
|
+
const memoryDir = resolve8(mindDir2, "home/memory");
|
|
3435
3602
|
const soul = readFileSync6(soulPath, "utf-8");
|
|
3436
3603
|
const logs = [];
|
|
3437
3604
|
try {
|
|
3438
3605
|
const files = readdirSync(memoryDir).filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)).sort();
|
|
3439
3606
|
for (const filename of files) {
|
|
3440
3607
|
const date = filename.replace(".md", "");
|
|
3441
|
-
const content2 = readFileSync6(
|
|
3608
|
+
const content2 = readFileSync6(resolve8(memoryDir, filename), "utf-8").trim();
|
|
3442
3609
|
if (content2) {
|
|
3443
3610
|
logs.push(`### ${date}
|
|
3444
3611
|
|
|
@@ -3497,7 +3664,7 @@ ${content2}`);
|
|
|
3497
3664
|
}
|
|
3498
3665
|
|
|
3499
3666
|
// packages/daemon/src/lib/mind/last-known-good.ts
|
|
3500
|
-
import { randomBytes } from "crypto";
|
|
3667
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
3501
3668
|
var glog = logger_default.child("last-known-good");
|
|
3502
3669
|
async function hasSrcChanges(dir, mindName) {
|
|
3503
3670
|
const status = (await gitExec(["status", "--porcelain", "--", "src"], { cwd: dir, mindName })).trim();
|
|
@@ -3506,7 +3673,7 @@ async function hasSrcChanges(dir, mindName) {
|
|
|
3506
3673
|
async function rollbackSrcChanges(dir, mindName) {
|
|
3507
3674
|
if (!await hasSrcChanges(dir, mindName)) return { parked: false };
|
|
3508
3675
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3509
|
-
const branch = `broken/${ts}-${
|
|
3676
|
+
const branch = `broken/${ts}-${randomBytes2(4).toString("hex")}`;
|
|
3510
3677
|
const opts = { cwd: dir, mindName };
|
|
3511
3678
|
await gitExec(["add", "--", "src"], opts);
|
|
3512
3679
|
await gitExec(
|
|
@@ -3539,7 +3706,7 @@ async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
|
|
|
3539
3706
|
logger_default.warn(`failed to stop variant ${variantName}`, logger_default.errorData(err));
|
|
3540
3707
|
}
|
|
3541
3708
|
}
|
|
3542
|
-
const { findMind: findMind2 } = await import("./registry-
|
|
3709
|
+
const { findMind: findMind2 } = await import("./registry-NUJAGLQJ.js");
|
|
3543
3710
|
const variantEntry = await findMind2(variantName);
|
|
3544
3711
|
const branchName = variantEntry?.branch ?? variantName;
|
|
3545
3712
|
if (existsSync6(variantPath)) {
|
|
@@ -3591,7 +3758,7 @@ function validateBranchName(branch) {
|
|
|
3591
3758
|
import { randomUUID } from "crypto";
|
|
3592
3759
|
import { mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
3593
3760
|
import { homedir } from "os";
|
|
3594
|
-
import { resolve as
|
|
3761
|
+
import { resolve as resolve9 } from "path";
|
|
3595
3762
|
function convertSession(opts) {
|
|
3596
3763
|
const lines = readFileSync7(opts.sessionPath, "utf-8").trim().split("\n");
|
|
3597
3764
|
const sessionId = randomUUID();
|
|
@@ -3707,9 +3874,9 @@ function convertSession(opts) {
|
|
|
3707
3874
|
}
|
|
3708
3875
|
}
|
|
3709
3876
|
const projectId = opts.projectDir.replace(/\//g, "-");
|
|
3710
|
-
const sdkDir =
|
|
3877
|
+
const sdkDir = resolve9(homedir(), ".claude", "projects", projectId);
|
|
3711
3878
|
mkdirSync5(sdkDir, { recursive: true });
|
|
3712
|
-
const sdkPath =
|
|
3879
|
+
const sdkPath = resolve9(sdkDir, `${sessionId}.jsonl`);
|
|
3713
3880
|
writeFileSync6(sdkPath, `${sdkEvents.join("\n")}
|
|
3714
3881
|
`);
|
|
3715
3882
|
console.log(`Converted ${sdkEvents.length} messages \u2192 ${sdkPath}`);
|
|
@@ -3768,7 +3935,7 @@ async function getMindStatus(name, port, registryRunning) {
|
|
|
3768
3935
|
const manager = getMindManager();
|
|
3769
3936
|
let status = "stopped";
|
|
3770
3937
|
try {
|
|
3771
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
3938
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-YAHDOIU5.js");
|
|
3772
3939
|
if (getSleepManagerIfReady2()?.isSleeping(name)) {
|
|
3773
3940
|
status = "sleeping";
|
|
3774
3941
|
}
|
|
@@ -3814,7 +3981,7 @@ async function initTemplateBranch(projectRoot, composedDir, manifest, mindName,
|
|
|
3814
3981
|
await gitExec(["commit", "-m", "initial commit"], opts);
|
|
3815
3982
|
}
|
|
3816
3983
|
async function updateTemplateBranch(projectRoot, template, mindName) {
|
|
3817
|
-
const tempWorktree =
|
|
3984
|
+
const tempWorktree = resolve10(projectRoot, ".variants", "_template_update");
|
|
3818
3985
|
let branchExists = false;
|
|
3819
3986
|
try {
|
|
3820
3987
|
await gitExec(["rev-parse", "--verify", TEMPLATE_BRANCH], { cwd: projectRoot });
|
|
@@ -3846,15 +4013,15 @@ async function updateTemplateBranch(projectRoot, template, mindName) {
|
|
|
3846
4013
|
});
|
|
3847
4014
|
}
|
|
3848
4015
|
copyTemplateToDir(composedDir, tempWorktree, mindName, manifest);
|
|
3849
|
-
const initDir =
|
|
4016
|
+
const initDir = resolve10(tempWorktree, ".init");
|
|
3850
4017
|
if (existsSync7(initDir)) {
|
|
3851
4018
|
rmSync4(initDir, { recursive: true, force: true });
|
|
3852
4019
|
}
|
|
3853
|
-
const homeDir =
|
|
4020
|
+
const homeDir = resolve10(tempWorktree, "home");
|
|
3854
4021
|
if (existsSync7(homeDir)) {
|
|
3855
4022
|
for (const entry of readdirSync2(homeDir)) {
|
|
3856
4023
|
if (entry !== "VOLUTE.md") {
|
|
3857
|
-
rmSync4(
|
|
4024
|
+
rmSync4(resolve10(homeDir, entry), { recursive: true, force: true });
|
|
3858
4025
|
}
|
|
3859
4026
|
}
|
|
3860
4027
|
}
|
|
@@ -3895,7 +4062,7 @@ async function mergeTemplateBranch(worktreeDir) {
|
|
|
3895
4062
|
async function npmInstallAsMind(cwd, mindName) {
|
|
3896
4063
|
if (isIsolationEnabled()) {
|
|
3897
4064
|
const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
|
|
3898
|
-
await exec(cmd, args, { cwd, env: { ...process.env, HOME:
|
|
4065
|
+
await exec(cmd, args, { cwd, env: { ...process.env, HOME: resolve10(cwd, "home") } });
|
|
3899
4066
|
} else {
|
|
3900
4067
|
await exec("npm", ["install"], { cwd });
|
|
3901
4068
|
}
|
|
@@ -3920,7 +4087,7 @@ async function mergeUpgradeAndRestart(mindName, dir, worktreeDir, upgradeVariant
|
|
|
3920
4087
|
let switchWarning;
|
|
3921
4088
|
if (templateChanged) {
|
|
3922
4089
|
try {
|
|
3923
|
-
applyTemplateHomeFiles(
|
|
4090
|
+
applyTemplateHomeFiles(resolve10(dir, "home"), template);
|
|
3924
4091
|
await gitExec(["add", "home/"], { cwd: dir });
|
|
3925
4092
|
try {
|
|
3926
4093
|
await gitExec(["diff", "--cached", "--quiet"], { cwd: dir });
|
|
@@ -3970,7 +4137,7 @@ async function mergeUpgradeAndRestart(mindName, dir, worktreeDir, upgradeVariant
|
|
|
3970
4137
|
return { ok: true, warning: switchWarning };
|
|
3971
4138
|
}
|
|
3972
4139
|
async function importFromArchive(c, tempDir, nameOverride, manifest) {
|
|
3973
|
-
const extractedMindDir =
|
|
4140
|
+
const extractedMindDir = resolve10(tempDir, "mind");
|
|
3974
4141
|
if (!existsSync7(extractedMindDir)) {
|
|
3975
4142
|
return c.json({ error: "Invalid archive: missing mind/ directory" }, 400);
|
|
3976
4143
|
}
|
|
@@ -3997,9 +4164,9 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
|
|
|
3997
4164
|
}
|
|
3998
4165
|
const state = stateDir(name);
|
|
3999
4166
|
mkdirSync6(state, { recursive: true });
|
|
4000
|
-
const envJson =
|
|
4167
|
+
const envJson = resolve10(tempDir, "state/env.json");
|
|
4001
4168
|
if (existsSync7(envJson)) {
|
|
4002
|
-
cpSync(envJson,
|
|
4169
|
+
cpSync(envJson, resolve10(state, "env.json"));
|
|
4003
4170
|
}
|
|
4004
4171
|
const port = await nextPort();
|
|
4005
4172
|
await addMind(name, port, manifest.stage, manifest.template);
|
|
@@ -4008,23 +4175,23 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
|
|
|
4008
4175
|
} catch (err) {
|
|
4009
4176
|
logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
|
|
4010
4177
|
}
|
|
4011
|
-
const homeDir =
|
|
4178
|
+
const homeDir = resolve10(dest, "home");
|
|
4012
4179
|
ensureVoluteGroup();
|
|
4013
4180
|
createMindUser(name, homeDir);
|
|
4014
4181
|
await chownMindDir(dest, name);
|
|
4015
4182
|
await npmInstallAsMind(dest, name);
|
|
4016
4183
|
await importHistoryFromArchive(name, tempDir);
|
|
4017
4184
|
importSessionsFromArchive(dest, tempDir);
|
|
4018
|
-
if (!existsSync7(
|
|
4185
|
+
if (!existsSync7(resolve10(dest, ".git"))) {
|
|
4019
4186
|
try {
|
|
4020
|
-
const env = isIsolationEnabled() ? { ...process.env, HOME:
|
|
4187
|
+
const env = isIsolationEnabled() ? { ...process.env, HOME: resolve10(dest, "home") } : void 0;
|
|
4021
4188
|
await gitExec(["init"], { cwd: dest, mindName: name, env });
|
|
4022
4189
|
await configureGitIdentity(name, { cwd: dest, mindName: name, env });
|
|
4023
4190
|
await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
|
|
4024
4191
|
await gitExec(["commit", "-m", "import from archive"], { cwd: dest, mindName: name, env });
|
|
4025
4192
|
} catch (err) {
|
|
4026
4193
|
logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
|
|
4027
|
-
rmSync4(
|
|
4194
|
+
rmSync4(resolve10(dest, ".git"), { recursive: true, force: true });
|
|
4028
4195
|
}
|
|
4029
4196
|
}
|
|
4030
4197
|
await chownMindDir(dest, name);
|
|
@@ -4057,22 +4224,22 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4057
4224
|
try {
|
|
4058
4225
|
copyTemplateToDir(composedDir, dest, name, templateManifest);
|
|
4059
4226
|
applyInitFiles(dest);
|
|
4060
|
-
const extractedHome =
|
|
4227
|
+
const extractedHome = resolve10(extractedMindDir, "home");
|
|
4061
4228
|
if (existsSync7(extractedHome)) {
|
|
4062
|
-
cpSync(extractedHome,
|
|
4229
|
+
cpSync(extractedHome, resolve10(dest, "home"), { recursive: true });
|
|
4063
4230
|
}
|
|
4064
|
-
const extractedMindInternal =
|
|
4231
|
+
const extractedMindInternal = resolve10(extractedMindDir, ".mind");
|
|
4065
4232
|
if (existsSync7(extractedMindInternal)) {
|
|
4066
|
-
cpSync(extractedMindInternal,
|
|
4233
|
+
cpSync(extractedMindInternal, resolve10(dest, ".mind"), { recursive: true });
|
|
4067
4234
|
}
|
|
4068
|
-
const identityDir =
|
|
4235
|
+
const identityDir = resolve10(dest, ".mind/identity");
|
|
4069
4236
|
let publicKeyPem;
|
|
4070
|
-
if (!manifest.includes.identity || !existsSync7(
|
|
4237
|
+
if (!manifest.includes.identity || !existsSync7(resolve10(identityDir, "private.pem"))) {
|
|
4071
4238
|
({ publicKeyPem } = generateIdentity(dest));
|
|
4072
4239
|
} else {
|
|
4073
|
-
publicKeyPem = readFileSync8(
|
|
4240
|
+
publicKeyPem = readFileSync8(resolve10(identityDir, "public.pem"), "utf-8");
|
|
4074
4241
|
}
|
|
4075
|
-
const promptsPath =
|
|
4242
|
+
const promptsPath = resolve10(dest, "home/.config/prompts.json");
|
|
4076
4243
|
if (!existsSync7(promptsPath)) {
|
|
4077
4244
|
const mindPrompts = await getMindPromptDefaults();
|
|
4078
4245
|
writeFileSync7(promptsPath, `${JSON.stringify(mindPrompts, null, 2)}
|
|
@@ -4080,13 +4247,13 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4080
4247
|
}
|
|
4081
4248
|
const state = stateDir(name);
|
|
4082
4249
|
mkdirSync6(state, { recursive: true });
|
|
4083
|
-
const envJson =
|
|
4250
|
+
const envJson = resolve10(tempDir, "state/env.json");
|
|
4084
4251
|
if (existsSync7(envJson)) {
|
|
4085
|
-
cpSync(envJson,
|
|
4252
|
+
cpSync(envJson, resolve10(state, "env.json"));
|
|
4086
4253
|
}
|
|
4087
4254
|
const port = await nextPort();
|
|
4088
4255
|
await addMind(name, port, manifest.stage, manifest.template);
|
|
4089
|
-
const homeDir =
|
|
4256
|
+
const homeDir = resolve10(dest, "home");
|
|
4090
4257
|
ensureVoluteGroup();
|
|
4091
4258
|
createMindUser(name, homeDir);
|
|
4092
4259
|
await chownMindDir(dest, name);
|
|
@@ -4099,7 +4266,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4099
4266
|
await initTemplateBranch(dest, composedDir, templateManifest, name, env);
|
|
4100
4267
|
} catch (err) {
|
|
4101
4268
|
logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
|
|
4102
|
-
rmSync4(
|
|
4269
|
+
rmSync4(resolve10(dest, ".git"), { recursive: true, force: true });
|
|
4103
4270
|
gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
|
|
4104
4271
|
}
|
|
4105
4272
|
const skillSet = manifest.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions();
|
|
@@ -4142,7 +4309,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4142
4309
|
}
|
|
4143
4310
|
}
|
|
4144
4311
|
async function importHistoryFromArchive(name, tempDir) {
|
|
4145
|
-
const historyJsonl =
|
|
4312
|
+
const historyJsonl = resolve10(tempDir, "history.jsonl");
|
|
4146
4313
|
if (!existsSync7(historyJsonl)) return;
|
|
4147
4314
|
try {
|
|
4148
4315
|
const db = await getDb();
|
|
@@ -4182,27 +4349,27 @@ async function importHistoryFromArchive(name, tempDir) {
|
|
|
4182
4349
|
}
|
|
4183
4350
|
}
|
|
4184
4351
|
function importSessionsFromArchive(dest, tempDir) {
|
|
4185
|
-
const sessionsDir =
|
|
4352
|
+
const sessionsDir = resolve10(tempDir, "sessions");
|
|
4186
4353
|
if (!existsSync7(sessionsDir)) return;
|
|
4187
4354
|
try {
|
|
4188
|
-
const destSessions =
|
|
4355
|
+
const destSessions = resolve10(dest, ".mind/sessions");
|
|
4189
4356
|
mkdirSync6(destSessions, { recursive: true });
|
|
4190
4357
|
for (const file of readdirSync2(sessionsDir)) {
|
|
4191
|
-
cpSync(
|
|
4358
|
+
cpSync(resolve10(sessionsDir, file), resolve10(destSessions, file));
|
|
4192
4359
|
}
|
|
4193
4360
|
} catch (err) {
|
|
4194
4361
|
logger_default.error("Failed to import sessions from archive", logger_default.errorData(err));
|
|
4195
4362
|
}
|
|
4196
4363
|
}
|
|
4197
|
-
var createMindSchema =
|
|
4198
|
-
name:
|
|
4199
|
-
template:
|
|
4200
|
-
stage:
|
|
4201
|
-
description:
|
|
4202
|
-
model:
|
|
4203
|
-
seedSoul:
|
|
4204
|
-
skills:
|
|
4205
|
-
createdBy:
|
|
4364
|
+
var createMindSchema = z6.object({
|
|
4365
|
+
name: z6.string(),
|
|
4366
|
+
template: z6.string().optional(),
|
|
4367
|
+
stage: z6.enum(["seed", "sprouted"]).optional(),
|
|
4368
|
+
description: z6.string().optional(),
|
|
4369
|
+
model: z6.string().optional(),
|
|
4370
|
+
seedSoul: z6.string().optional(),
|
|
4371
|
+
skills: z6.array(z6.string()).optional(),
|
|
4372
|
+
createdBy: z6.string().optional()
|
|
4206
4373
|
});
|
|
4207
4374
|
function formatTimeAgo(date) {
|
|
4208
4375
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
@@ -4246,7 +4413,7 @@ async function proxyToMind(c, path) {
|
|
|
4246
4413
|
return c.json({ error: "Failed to reach mind" }, 503);
|
|
4247
4414
|
}
|
|
4248
4415
|
}
|
|
4249
|
-
var app13 = new
|
|
4416
|
+
var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", createMindSchema), async (c) => {
|
|
4250
4417
|
const body = c.req.valid("json");
|
|
4251
4418
|
const { name } = body;
|
|
4252
4419
|
const template = body.template ?? await resolveTemplate(body.model);
|
|
@@ -4263,7 +4430,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4263
4430
|
applyInitFiles(dest);
|
|
4264
4431
|
const { publicKeyPem } = generateIdentity(dest);
|
|
4265
4432
|
{
|
|
4266
|
-
const { readGlobalConfig: readGlobal } = await import("./setup-
|
|
4433
|
+
const { readGlobalConfig: readGlobal } = await import("./setup-73YBJZQL.js");
|
|
4267
4434
|
const mindDefaults = readGlobal().mindDefaults;
|
|
4268
4435
|
const config2 = readVoluteConfig(dest);
|
|
4269
4436
|
if (!config2) throw new Error("Failed to read volute.json after identity generation");
|
|
@@ -4300,7 +4467,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4300
4467
|
}
|
|
4301
4468
|
writeVoluteConfig(dest, config2);
|
|
4302
4469
|
const modelId = body.model ?? cog?.model;
|
|
4303
|
-
const sdkConfigPath =
|
|
4470
|
+
const sdkConfigPath = resolve10(dest, "home/.config/config.json");
|
|
4304
4471
|
if (modelId || cog?.compaction) {
|
|
4305
4472
|
const existing = existsSync7(sdkConfigPath) ? JSON.parse(readFileSync8(sdkConfigPath, "utf-8")) : {};
|
|
4306
4473
|
if (modelId) {
|
|
@@ -4315,7 +4482,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4315
4482
|
}
|
|
4316
4483
|
const mindPrompts = await getMindPromptDefaults();
|
|
4317
4484
|
writeFileSync7(
|
|
4318
|
-
|
|
4485
|
+
resolve10(dest, "home/.config/prompts.json"),
|
|
4319
4486
|
`${JSON.stringify(mindPrompts, null, 2)}
|
|
4320
4487
|
`
|
|
4321
4488
|
);
|
|
@@ -4327,7 +4494,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4327
4494
|
} catch (err) {
|
|
4328
4495
|
logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
|
|
4329
4496
|
}
|
|
4330
|
-
const homeDir =
|
|
4497
|
+
const homeDir = resolve10(dest, "home");
|
|
4331
4498
|
ensureVoluteGroup();
|
|
4332
4499
|
createMindUser(name, homeDir);
|
|
4333
4500
|
await chownMindDir(dest, name);
|
|
@@ -4340,7 +4507,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4340
4507
|
await initTemplateBranch(dest, composedDir, manifest, name, env);
|
|
4341
4508
|
} catch (err) {
|
|
4342
4509
|
logger_default.error(`git setup failed for ${name}`, logger_default.errorData(err));
|
|
4343
|
-
rmSync4(
|
|
4510
|
+
rmSync4(resolve10(dest, ".git"), { recursive: true, force: true });
|
|
4344
4511
|
gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
|
|
4345
4512
|
}
|
|
4346
4513
|
await chownMindDir(dest, name);
|
|
@@ -4350,11 +4517,11 @@ The human who planted you described you as: "${body.description}"
|
|
|
4350
4517
|
` : "";
|
|
4351
4518
|
const seedSoulRaw = body.seedSoul ?? await getPrompt("seed_soul", { name, description: descLine });
|
|
4352
4519
|
const seedSoul = body.seedSoul ? substitute(seedSoulRaw, { name, description: descLine }) : seedSoulRaw;
|
|
4353
|
-
writeFileSync7(
|
|
4520
|
+
writeFileSync7(resolve10(dest, "home/SOUL.md"), seedSoul);
|
|
4354
4521
|
}
|
|
4355
4522
|
let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
|
|
4356
4523
|
if (body.stage === "seed" && !body.skills) {
|
|
4357
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
4524
|
+
const { isImagegenEnabled } = await import("./setup-73YBJZQL.js");
|
|
4358
4525
|
if (isImagegenEnabled()) {
|
|
4359
4526
|
skillSet = [...skillSet, "imagegen"];
|
|
4360
4527
|
}
|
|
@@ -4372,7 +4539,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4372
4539
|
try {
|
|
4373
4540
|
const spiritEntry = await findMind("volute");
|
|
4374
4541
|
if (spiritEntry) {
|
|
4375
|
-
const { spiritDir } = await import("./spirit-
|
|
4542
|
+
const { spiritDir } = await import("./spirit-II3HOERM.js");
|
|
4376
4543
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
4377
4544
|
const spiritConfig = readVoluteConfig(sDir) ?? {};
|
|
4378
4545
|
const schedules = spiritConfig.schedules ?? [];
|
|
@@ -4387,7 +4554,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4387
4554
|
});
|
|
4388
4555
|
spiritConfig.schedules = schedules;
|
|
4389
4556
|
writeVoluteConfig(sDir, spiritConfig);
|
|
4390
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
4557
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-YHJRRV6E.js");
|
|
4391
4558
|
getScheduler2().loadSchedules("volute", sDir);
|
|
4392
4559
|
}
|
|
4393
4560
|
}
|
|
@@ -4398,11 +4565,11 @@ The human who planted you described you as: "${body.description}"
|
|
|
4398
4565
|
if (body.stage !== "seed") {
|
|
4399
4566
|
const customSoul = await getPromptIfCustom("default_soul");
|
|
4400
4567
|
if (customSoul) {
|
|
4401
|
-
writeFileSync7(
|
|
4568
|
+
writeFileSync7(resolve10(dest, "home/SOUL.md"), customSoul.replace(/\{\{name\}\}/g, name));
|
|
4402
4569
|
}
|
|
4403
4570
|
const customMemory = await getPromptIfCustom("default_memory");
|
|
4404
4571
|
if (customMemory) {
|
|
4405
|
-
writeFileSync7(
|
|
4572
|
+
writeFileSync7(resolve10(dest, "home/MEMORY.md"), customMemory);
|
|
4406
4573
|
}
|
|
4407
4574
|
}
|
|
4408
4575
|
publishPublicKey(name, publicKeyPem).catch(
|
|
@@ -4451,12 +4618,12 @@ The human who planted you described you as: "${body.description}"
|
|
|
4451
4618
|
return importFromArchive(c, body.archivePath, body.name, body.manifest);
|
|
4452
4619
|
}
|
|
4453
4620
|
const wsDir = body.workspacePath;
|
|
4454
|
-
if (!wsDir || !existsSync7(
|
|
4621
|
+
if (!wsDir || !existsSync7(resolve10(wsDir, "SOUL.md")) || !existsSync7(resolve10(wsDir, "IDENTITY.md"))) {
|
|
4455
4622
|
return c.json({ error: "Invalid workspace: missing SOUL.md or IDENTITY.md" }, 400);
|
|
4456
4623
|
}
|
|
4457
|
-
const soul = readFileSync8(
|
|
4458
|
-
const identity = readFileSync8(
|
|
4459
|
-
const userPath =
|
|
4624
|
+
const soul = readFileSync8(resolve10(wsDir, "SOUL.md"), "utf-8");
|
|
4625
|
+
const identity = readFileSync8(resolve10(wsDir, "IDENTITY.md"), "utf-8");
|
|
4626
|
+
const userPath = resolve10(wsDir, "USER.md");
|
|
4460
4627
|
const user = existsSync7(userPath) ? readFileSync8(userPath, "utf-8") : "";
|
|
4461
4628
|
const name = body.name ?? parseNameFromIdentity(identity) ?? "imported-mind";
|
|
4462
4629
|
const template = body.template ?? "claude";
|
|
@@ -4484,26 +4651,26 @@ ${user.trimEnd()}
|
|
|
4484
4651
|
copyTemplateToDir(composedDir, dest, name, manifest);
|
|
4485
4652
|
applyInitFiles(dest);
|
|
4486
4653
|
const { publicKeyPem: importPublicKey } = generateIdentity(dest);
|
|
4487
|
-
writeFileSync7(
|
|
4488
|
-
const wsMemoryPath =
|
|
4654
|
+
writeFileSync7(resolve10(dest, "home/SOUL.md"), mergedSoul);
|
|
4655
|
+
const wsMemoryPath = resolve10(wsDir, "MEMORY.md");
|
|
4489
4656
|
const hasMemory = existsSync7(wsMemoryPath);
|
|
4490
4657
|
if (hasMemory) {
|
|
4491
4658
|
const existingMemory = readFileSync8(wsMemoryPath, "utf-8");
|
|
4492
4659
|
writeFileSync7(
|
|
4493
|
-
|
|
4660
|
+
resolve10(dest, "home/MEMORY.md"),
|
|
4494
4661
|
`${existingMemory.trimEnd()}${mergedMemoryExtra}`
|
|
4495
4662
|
);
|
|
4496
4663
|
} else if (user) {
|
|
4497
|
-
writeFileSync7(
|
|
4664
|
+
writeFileSync7(resolve10(dest, "home/MEMORY.md"), `${user.trimEnd()}
|
|
4498
4665
|
`);
|
|
4499
4666
|
}
|
|
4500
|
-
const wsMemoryDir =
|
|
4667
|
+
const wsMemoryDir = resolve10(wsDir, "memory");
|
|
4501
4668
|
let dailyLogCount = 0;
|
|
4502
4669
|
if (existsSync7(wsMemoryDir)) {
|
|
4503
|
-
const destMemoryDir =
|
|
4670
|
+
const destMemoryDir = resolve10(dest, "home/memory");
|
|
4504
4671
|
const files = readdirSync2(wsMemoryDir).filter((f) => f.endsWith(".md"));
|
|
4505
4672
|
for (const file of files) {
|
|
4506
|
-
cpSync(
|
|
4673
|
+
cpSync(resolve10(wsMemoryDir, file), resolve10(destMemoryDir, file));
|
|
4507
4674
|
}
|
|
4508
4675
|
dailyLogCount = files.length;
|
|
4509
4676
|
}
|
|
@@ -4514,7 +4681,7 @@ ${user.trimEnd()}
|
|
|
4514
4681
|
} catch (err) {
|
|
4515
4682
|
logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
|
|
4516
4683
|
}
|
|
4517
|
-
const homeDir =
|
|
4684
|
+
const homeDir = resolve10(dest, "home");
|
|
4518
4685
|
ensureVoluteGroup();
|
|
4519
4686
|
createMindUser(name, homeDir);
|
|
4520
4687
|
await chownMindDir(dest, name);
|
|
@@ -4522,20 +4689,20 @@ ${user.trimEnd()}
|
|
|
4522
4689
|
if (!hasMemory && dailyLogCount > 0) {
|
|
4523
4690
|
await consolidateMemory(dest);
|
|
4524
4691
|
}
|
|
4525
|
-
const env = isIsolationEnabled() ? { ...process.env, HOME:
|
|
4692
|
+
const env = isIsolationEnabled() ? { ...process.env, HOME: resolve10(dest, "home") } : void 0;
|
|
4526
4693
|
await gitExec(["init"], { cwd: dest, mindName: name, env });
|
|
4527
4694
|
await configureGitIdentity(name, { cwd: dest, mindName: name, env });
|
|
4528
4695
|
await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
|
|
4529
4696
|
await gitExec(["commit", "-m", "import from OpenClaw"], { cwd: dest, mindName: name, env });
|
|
4530
|
-
const sessionFile = body.sessionPath ?
|
|
4697
|
+
const sessionFile = body.sessionPath ? resolve10(body.sessionPath) : findOpenClawSession(wsDir);
|
|
4531
4698
|
if (sessionFile && existsSync7(sessionFile)) {
|
|
4532
4699
|
if (template === "pi") {
|
|
4533
4700
|
importPiSession(sessionFile, dest);
|
|
4534
4701
|
} else if (template === "claude") {
|
|
4535
4702
|
const sessionId = convertSession({ sessionPath: sessionFile, projectDir: dest });
|
|
4536
|
-
const mindRuntimeDir =
|
|
4703
|
+
const mindRuntimeDir = resolve10(dest, ".mind");
|
|
4537
4704
|
mkdirSync6(mindRuntimeDir, { recursive: true });
|
|
4538
|
-
writeFileSync7(
|
|
4705
|
+
writeFileSync7(resolve10(mindRuntimeDir, "session.json"), JSON.stringify({ sessionId }));
|
|
4539
4706
|
}
|
|
4540
4707
|
}
|
|
4541
4708
|
importOpenClawConnectors(name, dest);
|
|
@@ -4576,7 +4743,7 @@ ${user.trimEnd()}
|
|
|
4576
4743
|
const minds = await Promise.all(
|
|
4577
4744
|
entries.map(async (entry) => {
|
|
4578
4745
|
const mindStatus = await getMindStatus(entry.name, entry.port, entry.running);
|
|
4579
|
-
const hasPages = existsSync7(
|
|
4746
|
+
const hasPages = existsSync7(resolve10(mindDir(entry.name), "home", "pages"));
|
|
4580
4747
|
return {
|
|
4581
4748
|
...entry,
|
|
4582
4749
|
...mindStatus,
|
|
@@ -4605,7 +4772,7 @@ ${user.trimEnd()}
|
|
|
4605
4772
|
return { name: s.name, port: s.port, status: variantStatus };
|
|
4606
4773
|
})
|
|
4607
4774
|
);
|
|
4608
|
-
const hasPages = existsSync7(
|
|
4775
|
+
const hasPages = existsSync7(resolve10(mindDir(name), "home", "pages"));
|
|
4609
4776
|
return c.json({ ...entry, ...mindStatus, variants: variantStatuses, hasPages });
|
|
4610
4777
|
}).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) => {
|
|
4611
4778
|
const name = c.req.param("name");
|
|
@@ -4652,7 +4819,7 @@ ${user.trimEnd()}
|
|
|
4652
4819
|
const manager = getMindManager();
|
|
4653
4820
|
try {
|
|
4654
4821
|
if (context?.type === "reload") {
|
|
4655
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4822
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-YAHDOIU5.js");
|
|
4656
4823
|
const sleepState = getSleepManagerIfReady2()?.getState(name);
|
|
4657
4824
|
if (sleepState?.sleeping) {
|
|
4658
4825
|
logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
|
|
@@ -4779,7 +4946,7 @@ ${user.trimEnd()}
|
|
|
4779
4946
|
const name = c.req.param("name");
|
|
4780
4947
|
const entry = await findMind(name);
|
|
4781
4948
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4782
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4949
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-YAHDOIU5.js");
|
|
4783
4950
|
const sm = getSleepManagerIfReady2();
|
|
4784
4951
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4785
4952
|
return c.json(sm.getState(name));
|
|
@@ -4787,7 +4954,7 @@ ${user.trimEnd()}
|
|
|
4787
4954
|
const name = c.req.param("name");
|
|
4788
4955
|
const entry = await findMind(name);
|
|
4789
4956
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4790
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4957
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-YAHDOIU5.js");
|
|
4791
4958
|
const sm = getSleepManagerIfReady2();
|
|
4792
4959
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4793
4960
|
if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
|
|
@@ -4807,7 +4974,7 @@ ${user.trimEnd()}
|
|
|
4807
4974
|
const name = c.req.param("name");
|
|
4808
4975
|
const entry = await findMind(name);
|
|
4809
4976
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4810
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4977
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-YAHDOIU5.js");
|
|
4811
4978
|
const sm = getSleepManagerIfReady2();
|
|
4812
4979
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4813
4980
|
const sleepState = sm.getState(name);
|
|
@@ -4822,7 +4989,7 @@ ${user.trimEnd()}
|
|
|
4822
4989
|
const name = c.req.param("name");
|
|
4823
4990
|
const entry = await findMind(name);
|
|
4824
4991
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4825
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4992
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-YAHDOIU5.js");
|
|
4826
4993
|
const sm = getSleepManagerIfReady2();
|
|
4827
4994
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4828
4995
|
const flushed = await sm.flushQueuedMessages(name);
|
|
@@ -4837,10 +5004,20 @@ ${user.trimEnd()}
|
|
|
4837
5004
|
const profile = config2.profile ?? {};
|
|
4838
5005
|
if (body.displayName !== void 0) profile.displayName = body.displayName;
|
|
4839
5006
|
if (body.description !== void 0) profile.description = body.description;
|
|
4840
|
-
if (body.avatar !== void 0)
|
|
5007
|
+
if (body.avatar !== void 0) {
|
|
5008
|
+
const homeDir = resolve10(dir, "home");
|
|
5009
|
+
const avatarPath = safeResolveWithinBase(homeDir, body.avatar);
|
|
5010
|
+
if (!avatarPath) {
|
|
5011
|
+
return c.json({ error: "Avatar path must be inside the mind's home directory" }, 400);
|
|
5012
|
+
}
|
|
5013
|
+
if (!existsSync7(avatarPath)) {
|
|
5014
|
+
return c.json({ error: `Avatar file not found: ${relative(homeDir, avatarPath)}` }, 400);
|
|
5015
|
+
}
|
|
5016
|
+
profile.avatar = relative(homeDir, avatarPath);
|
|
5017
|
+
}
|
|
4841
5018
|
config2.profile = profile;
|
|
4842
5019
|
writeVoluteConfig(dir, config2);
|
|
4843
|
-
const { syncMindProfile: syncMindProfile2 } = await import("./auth-
|
|
5020
|
+
const { syncMindProfile: syncMindProfile2 } = await import("./auth-FRZJVQCS.js");
|
|
4844
5021
|
await syncMindProfile2(name, profile);
|
|
4845
5022
|
broadcast({ type: "profile_updated", mind: name, summary: `${name} profile updated` });
|
|
4846
5023
|
return c.json({ ok: true });
|
|
@@ -4880,14 +5057,14 @@ ${user.trimEnd()}
|
|
|
4880
5057
|
return c.json({ output: "" });
|
|
4881
5058
|
}
|
|
4882
5059
|
const dir = entry.dir ?? mindDir(name);
|
|
4883
|
-
const soulPath =
|
|
4884
|
-
const memoryPath =
|
|
5060
|
+
const soulPath = resolve10(dir, "home/SOUL.md");
|
|
5061
|
+
const memoryPath = resolve10(dir, "home/MEMORY.md");
|
|
4885
5062
|
const soulCustom = existsSync7(soulPath) && !readFileSync8(soulPath, "utf-8").includes(ORIENTATION_MARKER);
|
|
4886
5063
|
const memoryWritten = existsSync7(memoryPath) && readFileSync8(memoryPath, "utf-8").trim().length > 0;
|
|
4887
5064
|
const config2 = readVoluteConfig(dir);
|
|
4888
5065
|
const displayNameSet = !!config2?.profile?.displayName;
|
|
4889
5066
|
const avatarSet = !!config2?.profile?.avatar;
|
|
4890
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
5067
|
+
const { isImagegenEnabled } = await import("./setup-73YBJZQL.js");
|
|
4891
5068
|
const imagegenEnabled = isImagegenEnabled();
|
|
4892
5069
|
const done = [];
|
|
4893
5070
|
const remaining = [];
|
|
@@ -4925,7 +5102,7 @@ ${user.trimEnd()}
|
|
|
4925
5102
|
try {
|
|
4926
5103
|
const spiritEntry = await findMind("volute");
|
|
4927
5104
|
if (spiritEntry) {
|
|
4928
|
-
const { spiritDir } = await import("./spirit-
|
|
5105
|
+
const { spiritDir } = await import("./spirit-II3HOERM.js");
|
|
4929
5106
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
4930
5107
|
const spiritConfig = readVoluteConfig(sDir);
|
|
4931
5108
|
if (spiritConfig?.schedules) {
|
|
@@ -4933,7 +5110,7 @@ ${user.trimEnd()}
|
|
|
4933
5110
|
spiritConfig.schedules = spiritConfig.schedules.filter((s) => s.id !== nurtureId);
|
|
4934
5111
|
if (spiritConfig.schedules.length === 0) spiritConfig.schedules = void 0;
|
|
4935
5112
|
writeVoluteConfig(sDir, spiritConfig);
|
|
4936
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
5113
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-YHJRRV6E.js");
|
|
4937
5114
|
getScheduler2().loadSchedules("volute", sDir);
|
|
4938
5115
|
}
|
|
4939
5116
|
}
|
|
@@ -4992,16 +5169,16 @@ ${user.trimEnd()}
|
|
|
4992
5169
|
}
|
|
4993
5170
|
const UPGRADE_BRANCH = "upgrade";
|
|
4994
5171
|
const upgradeVariantName = `${mindName}-upgrade`;
|
|
4995
|
-
const worktreeDir =
|
|
5172
|
+
const worktreeDir = resolve10(dir, ".variants", UPGRADE_BRANCH);
|
|
4996
5173
|
if (body.abort) {
|
|
4997
5174
|
if (!existsSync7(worktreeDir)) {
|
|
4998
5175
|
return c.json({ error: "No upgrade in progress" }, 400);
|
|
4999
5176
|
}
|
|
5000
5177
|
try {
|
|
5001
5178
|
try {
|
|
5002
|
-
const gitDirContent = readFileSync8(
|
|
5179
|
+
const gitDirContent = readFileSync8(resolve10(worktreeDir, ".git"), "utf-8").trim();
|
|
5003
5180
|
const gitDir = gitDirContent.replace("gitdir: ", "");
|
|
5004
|
-
if (existsSync7(
|
|
5181
|
+
if (existsSync7(resolve10(gitDir, "MERGE_HEAD"))) {
|
|
5005
5182
|
await gitExec(["merge", "--abort"], { cwd: worktreeDir });
|
|
5006
5183
|
}
|
|
5007
5184
|
} catch {
|
|
@@ -5085,7 +5262,7 @@ ${user.trimEnd()}
|
|
|
5085
5262
|
}
|
|
5086
5263
|
if (body.diff) {
|
|
5087
5264
|
try {
|
|
5088
|
-
if (!existsSync7(
|
|
5265
|
+
if (!existsSync7(resolve10(dir, ".git"))) {
|
|
5089
5266
|
return c.json({ error: "Mind has no git history \u2014 nothing to diff against" }, 400);
|
|
5090
5267
|
}
|
|
5091
5268
|
await updateTemplateBranch(dir, template, mindName);
|
|
@@ -5109,16 +5286,16 @@ ${user.trimEnd()}
|
|
|
5109
5286
|
409
|
|
5110
5287
|
);
|
|
5111
5288
|
}
|
|
5112
|
-
if (!existsSync7(
|
|
5289
|
+
if (!existsSync7(resolve10(dir, ".git"))) {
|
|
5113
5290
|
try {
|
|
5114
|
-
const env = isIsolationEnabled() ? { ...process.env, HOME:
|
|
5291
|
+
const env = isIsolationEnabled() ? { ...process.env, HOME: resolve10(dir, "home") } : void 0;
|
|
5115
5292
|
await gitExec(["init"], { cwd: dir, mindName, env });
|
|
5116
5293
|
await configureGitIdentity(mindName, { cwd: dir, mindName, env });
|
|
5117
5294
|
await gitExec(["add", "-A"], { cwd: dir, mindName, env });
|
|
5118
5295
|
await gitExec(["commit", "-m", "initial commit"], { cwd: dir, mindName, env });
|
|
5119
5296
|
await chownMindDir(dir, mindName);
|
|
5120
5297
|
} catch (err) {
|
|
5121
|
-
rmSync4(
|
|
5298
|
+
rmSync4(resolve10(dir, ".git"), { recursive: true, force: true });
|
|
5122
5299
|
return c.json(
|
|
5123
5300
|
{
|
|
5124
5301
|
error: `Git initialization failed: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -5133,7 +5310,7 @@ ${user.trimEnd()}
|
|
|
5133
5310
|
} catch {
|
|
5134
5311
|
}
|
|
5135
5312
|
await updateTemplateBranch(dir, template, mindName);
|
|
5136
|
-
const parentDir =
|
|
5313
|
+
const parentDir = resolve10(dir, ".variants");
|
|
5137
5314
|
if (!existsSync7(parentDir)) {
|
|
5138
5315
|
mkdirSync6(parentDir, { recursive: true });
|
|
5139
5316
|
}
|
|
@@ -5267,7 +5444,7 @@ ${user.trimEnd()}
|
|
|
5267
5444
|
if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
5268
5445
|
let config2 = readVoluteConfig(dir);
|
|
5269
5446
|
if (!config2 && entry.template === "pi") {
|
|
5270
|
-
const piConfigPath =
|
|
5447
|
+
const piConfigPath = resolve10(dir, "home/.config/config.json");
|
|
5271
5448
|
if (existsSync7(piConfigPath)) {
|
|
5272
5449
|
try {
|
|
5273
5450
|
config2 = JSON.parse(readFileSync8(piConfigPath, "utf-8"));
|
|
@@ -5276,7 +5453,7 @@ ${user.trimEnd()}
|
|
|
5276
5453
|
}
|
|
5277
5454
|
}
|
|
5278
5455
|
let templateConfig = {};
|
|
5279
|
-
const configJsonPath =
|
|
5456
|
+
const configJsonPath = resolve10(dir, "home/.config/config.json");
|
|
5280
5457
|
if (existsSync7(configJsonPath)) {
|
|
5281
5458
|
try {
|
|
5282
5459
|
templateConfig = JSON.parse(readFileSync8(configJsonPath, "utf-8"));
|
|
@@ -5318,16 +5495,16 @@ ${user.trimEnd()}
|
|
|
5318
5495
|
}).put(
|
|
5319
5496
|
"/:name/config",
|
|
5320
5497
|
requireSelf(),
|
|
5321
|
-
|
|
5498
|
+
zValidator6(
|
|
5322
5499
|
"json",
|
|
5323
|
-
|
|
5324
|
-
model:
|
|
5325
|
-
thinkingLevel:
|
|
5326
|
-
maxThinkingTokens:
|
|
5327
|
-
tokenBudget:
|
|
5328
|
-
tokenBudgetPeriodMinutes:
|
|
5329
|
-
compaction:
|
|
5330
|
-
unescapeNewlines:
|
|
5500
|
+
z6.object({
|
|
5501
|
+
model: z6.string().optional(),
|
|
5502
|
+
thinkingLevel: z6.enum(["off", "minimal", "low", "medium", "high", "xhigh"]).optional(),
|
|
5503
|
+
maxThinkingTokens: z6.number().int().positive().nullable().optional(),
|
|
5504
|
+
tokenBudget: z6.number().int().positive().nullable().optional(),
|
|
5505
|
+
tokenBudgetPeriodMinutes: z6.number().int().positive().nullable().optional(),
|
|
5506
|
+
compaction: z6.object({ maxContextTokens: z6.number().int().positive().nullable().optional() }).nullable().optional(),
|
|
5507
|
+
unescapeNewlines: z6.boolean().optional()
|
|
5331
5508
|
})
|
|
5332
5509
|
),
|
|
5333
5510
|
async (c) => {
|
|
@@ -5368,12 +5545,12 @@ ${user.trimEnd()}
|
|
|
5368
5545
|
}
|
|
5369
5546
|
writeVoluteConfig(dir, existing);
|
|
5370
5547
|
if (body.unescapeNewlines !== void 0) {
|
|
5371
|
-
const { clearEchoTextCache } = await import("./echo-text-
|
|
5548
|
+
const { clearEchoTextCache } = await import("./echo-text-NQXYYYCU.js");
|
|
5372
5549
|
clearEchoTextCache(name);
|
|
5373
5550
|
}
|
|
5374
5551
|
const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.maxThinkingTokens !== void 0 || body.compaction !== void 0;
|
|
5375
5552
|
if (needsConfigJson) {
|
|
5376
|
-
const configJsonPath =
|
|
5553
|
+
const configJsonPath = resolve10(dir, "home/.config/config.json");
|
|
5377
5554
|
let templateConfig = {};
|
|
5378
5555
|
if (existsSync7(configJsonPath)) {
|
|
5379
5556
|
try {
|
|
@@ -5445,7 +5622,7 @@ ${user.trimEnd()}
|
|
|
5445
5622
|
}
|
|
5446
5623
|
if (entry.mindType === "spirit" && body.model !== void 0) {
|
|
5447
5624
|
try {
|
|
5448
|
-
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-
|
|
5625
|
+
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-73YBJZQL.js");
|
|
5449
5626
|
const globalConfig = readGlobalConfig2();
|
|
5450
5627
|
globalConfig.spiritModel = body.model;
|
|
5451
5628
|
writeGlobalConfig2(globalConfig);
|
|
@@ -5473,7 +5650,7 @@ ${user.trimEnd()}
|
|
|
5473
5650
|
if (!body.systemPrompt || !body.message) {
|
|
5474
5651
|
return c.json({ error: "systemPrompt and message required" }, 400);
|
|
5475
5652
|
}
|
|
5476
|
-
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-
|
|
5653
|
+
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-534WUSDL.js");
|
|
5477
5654
|
if (!isAiConfigured()) {
|
|
5478
5655
|
return c.json({ error: "AI service not configured" }, 503);
|
|
5479
5656
|
}
|
|
@@ -5765,11 +5942,11 @@ ${lines.join("\n")}` });
|
|
|
5765
5942
|
var minds_default = app13;
|
|
5766
5943
|
|
|
5767
5944
|
// packages/daemon/src/web/api/prompts.ts
|
|
5768
|
-
import { zValidator as
|
|
5945
|
+
import { zValidator as zValidator7 } from "@hono/zod-validator";
|
|
5769
5946
|
import { eq as eq6, sql as sql4 } from "drizzle-orm";
|
|
5770
|
-
import { Hono as
|
|
5771
|
-
import { z as
|
|
5772
|
-
var app14 = new
|
|
5947
|
+
import { Hono as Hono17 } from "hono";
|
|
5948
|
+
import { z as z7 } from "zod";
|
|
5949
|
+
var app14 = new Hono17().get("/", async (c) => {
|
|
5773
5950
|
let rows;
|
|
5774
5951
|
try {
|
|
5775
5952
|
const db = await getDb();
|
|
@@ -5792,7 +5969,7 @@ var app14 = new Hono16().get("/", async (c) => {
|
|
|
5792
5969
|
};
|
|
5793
5970
|
});
|
|
5794
5971
|
return c.json(prompts);
|
|
5795
|
-
}).put("/:key", requireAdmin,
|
|
5972
|
+
}).put("/:key", requireAdmin, zValidator7("json", z7.object({ content: z7.string() })), async (c) => {
|
|
5796
5973
|
const key = c.req.param("key");
|
|
5797
5974
|
if (!PROMPT_KEYS.includes(key)) {
|
|
5798
5975
|
return c.json({ error: "Unknown prompt key" }, 404);
|
|
@@ -5816,8 +5993,8 @@ var app14 = new Hono16().get("/", async (c) => {
|
|
|
5816
5993
|
var prompts_default = app14;
|
|
5817
5994
|
|
|
5818
5995
|
// packages/daemon/src/web/api/schedules.ts
|
|
5819
|
-
import { CronExpressionParser } from "cron-parser";
|
|
5820
|
-
import { Hono as
|
|
5996
|
+
import { CronExpressionParser as CronExpressionParser3 } from "cron-parser";
|
|
5997
|
+
import { Hono as Hono18 } from "hono";
|
|
5821
5998
|
var slog2 = logger_default.child("schedules");
|
|
5822
5999
|
function readSchedules(dir) {
|
|
5823
6000
|
return readVoluteConfig(dir)?.schedules ?? [];
|
|
@@ -5834,7 +6011,7 @@ function writeSchedules(name, dir, schedules) {
|
|
|
5834
6011
|
data: { schedules }
|
|
5835
6012
|
});
|
|
5836
6013
|
}
|
|
5837
|
-
var app15 = new
|
|
6014
|
+
var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) => {
|
|
5838
6015
|
const name = c.req.param("name");
|
|
5839
6016
|
const entry = await findMind(name);
|
|
5840
6017
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
@@ -5855,14 +6032,14 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
5855
6032
|
}
|
|
5856
6033
|
} else if (s.cron) {
|
|
5857
6034
|
try {
|
|
5858
|
-
const interval =
|
|
6035
|
+
const interval = CronExpressionParser3.parse(s.cron);
|
|
5859
6036
|
const next = interval.next().toDate();
|
|
5860
6037
|
upcoming.push({ id: s.id, at: next.toISOString(), type: "cron" });
|
|
5861
6038
|
} catch {
|
|
5862
6039
|
slog2.warn(`invalid cron "${s.cron}" for schedule "${s.id}" of ${name}`);
|
|
5863
6040
|
}
|
|
5864
6041
|
try {
|
|
5865
|
-
const prevInterval =
|
|
6042
|
+
const prevInterval = CronExpressionParser3.parse(s.cron);
|
|
5866
6043
|
const prev = prevInterval.prev().toDate();
|
|
5867
6044
|
previous.push({ id: s.id, at: prev.toISOString() });
|
|
5868
6045
|
} catch {
|
|
@@ -5878,13 +6055,13 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
5878
6055
|
}
|
|
5879
6056
|
} else if (sleepConfig?.enabled && sleepConfig.schedule) {
|
|
5880
6057
|
try {
|
|
5881
|
-
const sleepInterval =
|
|
6058
|
+
const sleepInterval = CronExpressionParser3.parse(sleepConfig.schedule.sleep);
|
|
5882
6059
|
const nextSleep = sleepInterval.next().toDate();
|
|
5883
6060
|
upcoming.push({ id: "sleep", at: nextSleep.toISOString(), type: "cron" });
|
|
5884
6061
|
} catch {
|
|
5885
6062
|
}
|
|
5886
6063
|
try {
|
|
5887
|
-
const prevWakeInterval =
|
|
6064
|
+
const prevWakeInterval = CronExpressionParser3.parse(sleepConfig.schedule.wake);
|
|
5888
6065
|
const prevWake = prevWakeInterval.prev().toDate();
|
|
5889
6066
|
previous.push({ id: "sleep", at: prevWake.toISOString() });
|
|
5890
6067
|
} catch {
|
|
@@ -5908,7 +6085,7 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
5908
6085
|
for (const field of ["sleep", "wake"]) {
|
|
5909
6086
|
if (body.schedule[field]) {
|
|
5910
6087
|
try {
|
|
5911
|
-
|
|
6088
|
+
CronExpressionParser3.parse(body.schedule[field]);
|
|
5912
6089
|
} catch {
|
|
5913
6090
|
return c.json({ error: `Invalid ${field} cron: ${body.schedule[field]}` }, 400);
|
|
5914
6091
|
}
|
|
@@ -5954,7 +6131,7 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
5954
6131
|
}
|
|
5955
6132
|
if (body.cron) {
|
|
5956
6133
|
try {
|
|
5957
|
-
|
|
6134
|
+
CronExpressionParser3.parse(body.cron);
|
|
5958
6135
|
} catch {
|
|
5959
6136
|
return c.json({ error: `Invalid cron expression: ${body.cron}` }, 400);
|
|
5960
6137
|
}
|
|
@@ -6001,7 +6178,7 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
6001
6178
|
}
|
|
6002
6179
|
if (body.cron !== void 0) {
|
|
6003
6180
|
try {
|
|
6004
|
-
|
|
6181
|
+
CronExpressionParser3.parse(body.cron);
|
|
6005
6182
|
} catch {
|
|
6006
6183
|
return c.json({ error: `Invalid cron expression: ${body.cron}` }, 400);
|
|
6007
6184
|
}
|
|
@@ -6058,7 +6235,7 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
6058
6235
|
const body = await c.req.text();
|
|
6059
6236
|
const message = `[webhook: ${event}] ${body}`;
|
|
6060
6237
|
try {
|
|
6061
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
6238
|
+
const { sendSystemMessage } = await import("./system-chat-E65T2HSW.js");
|
|
6062
6239
|
await sendSystemMessage(name, message);
|
|
6063
6240
|
return c.json({ ok: true });
|
|
6064
6241
|
} catch (err) {
|
|
@@ -6071,14 +6248,14 @@ var schedules_default = app15;
|
|
|
6071
6248
|
// packages/daemon/src/web/api/setup.ts
|
|
6072
6249
|
import { mkdirSync as mkdirSync7 } from "fs";
|
|
6073
6250
|
import { homedir as homedir2 } from "os";
|
|
6074
|
-
import { resolve as
|
|
6075
|
-
import { Hono as
|
|
6251
|
+
import { resolve as resolve11 } from "path";
|
|
6252
|
+
import { Hono as Hono19 } from "hono";
|
|
6076
6253
|
import { setCookie as setCookie2 } from "hono/cookie";
|
|
6077
6254
|
var DEFAULT_API_URL2 = "https://volute.systems";
|
|
6078
|
-
var setup = new
|
|
6255
|
+
var setup = new Hono19();
|
|
6079
6256
|
function writeSetupConfig(systemName, description) {
|
|
6080
|
-
const configHome = process.env.VOLUTE_HOME ??
|
|
6081
|
-
const mindsDir =
|
|
6257
|
+
const configHome = process.env.VOLUTE_HOME ?? resolve11(homedir2(), ".volute");
|
|
6258
|
+
const mindsDir = resolve11(configHome, "minds");
|
|
6082
6259
|
mkdirSync7(configHome, { recursive: true });
|
|
6083
6260
|
mkdirSync7(mindsDir, { recursive: true });
|
|
6084
6261
|
const existingConfig = readGlobalConfig();
|
|
@@ -6112,7 +6289,7 @@ setup.get("/status", async (c) => {
|
|
|
6112
6289
|
let hasAccount = false;
|
|
6113
6290
|
if (hasSystem) {
|
|
6114
6291
|
try {
|
|
6115
|
-
const { listUsersByType: listUsersByType2 } = await import("./auth-
|
|
6292
|
+
const { listUsersByType: listUsersByType2 } = await import("./auth-FRZJVQCS.js");
|
|
6116
6293
|
const brains = await listUsersByType2("brain");
|
|
6117
6294
|
hasAccount = brains.length > 0;
|
|
6118
6295
|
} catch (err) {
|
|
@@ -6323,7 +6500,7 @@ setup.post("/account", async (c) => {
|
|
|
6323
6500
|
}
|
|
6324
6501
|
}
|
|
6325
6502
|
try {
|
|
6326
|
-
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-
|
|
6503
|
+
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-FRZJVQCS.js");
|
|
6327
6504
|
const user = await createUser2(body.username.trim(), body.password);
|
|
6328
6505
|
if (body.displayName?.trim()) {
|
|
6329
6506
|
await updateUserProfile2(user.id, { display_name: body.displayName.trim() });
|
|
@@ -6369,7 +6546,7 @@ setup.post("/models", async (c) => {
|
|
|
6369
6546
|
return c.json({ error: "Spirit model is required" }, 400);
|
|
6370
6547
|
}
|
|
6371
6548
|
try {
|
|
6372
|
-
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-
|
|
6549
|
+
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-534WUSDL.js");
|
|
6373
6550
|
setEnabledModels3(body.models);
|
|
6374
6551
|
const config2 = readGlobalConfig();
|
|
6375
6552
|
config2.spiritModel = body.spiritModel.trim();
|
|
@@ -6387,15 +6564,15 @@ setup.post("/complete", async (c) => {
|
|
|
6387
6564
|
return c.json({ error: "Setup already complete" }, 400);
|
|
6388
6565
|
}
|
|
6389
6566
|
try {
|
|
6390
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
6391
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
6567
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-II3HOERM.js");
|
|
6568
|
+
const { startSpiritFull } = await import("./mind-service-BF2LUQMH.js");
|
|
6392
6569
|
await ensureSpiritProject();
|
|
6393
6570
|
await syncSpiritTemplate();
|
|
6394
6571
|
const warnings = [];
|
|
6395
6572
|
const config2 = readGlobalConfig();
|
|
6396
6573
|
if (config2.setup?.service && config2.setup?.type === "local") {
|
|
6397
6574
|
try {
|
|
6398
|
-
const { installUserService } = await import("./service-install-
|
|
6575
|
+
const { installUserService } = await import("./service-install-4QNUDKLM.js");
|
|
6399
6576
|
const installed = await installUserService(config2.port, config2.hostname);
|
|
6400
6577
|
if (!installed) {
|
|
6401
6578
|
warnings.push("Service installation is not supported on this platform.");
|
|
@@ -6423,8 +6600,8 @@ setup.post("/complete", async (c) => {
|
|
|
6423
6600
|
}
|
|
6424
6601
|
let spiritConversationId;
|
|
6425
6602
|
try {
|
|
6426
|
-
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-
|
|
6427
|
-
const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-
|
|
6603
|
+
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-FRZJVQCS.js");
|
|
6604
|
+
const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-G4LYMHAA.js");
|
|
6428
6605
|
const spiritUser = await getOrCreateMindUser2("volute");
|
|
6429
6606
|
const brains = await listUsersByType2("brain");
|
|
6430
6607
|
const admin2 = brains.find((u) => u.role === "admin");
|
|
@@ -6446,8 +6623,8 @@ setup.post("/complete", async (c) => {
|
|
|
6446
6623
|
logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
|
|
6447
6624
|
if (spiritConversationId && spiritStarted) {
|
|
6448
6625
|
try {
|
|
6449
|
-
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-
|
|
6450
|
-
const { listUsersByType: listUsers2 } = await import("./auth-
|
|
6626
|
+
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-IUAXRPFE.js");
|
|
6627
|
+
const { listUsersByType: listUsers2 } = await import("./auth-FRZJVQCS.js");
|
|
6451
6628
|
const admins = await listUsers2("brain");
|
|
6452
6629
|
const admin2 = admins.find((u) => u.role === "admin");
|
|
6453
6630
|
const adminName = admin2?.display_name || admin2?.username || "the admin";
|
|
@@ -6486,10 +6663,10 @@ var setup_default = setup;
|
|
|
6486
6663
|
// packages/daemon/src/web/api/skills.ts
|
|
6487
6664
|
import { existsSync as existsSync8, mkdtempSync, readdirSync as readdirSync3, rmSync as rmSync5 } from "fs";
|
|
6488
6665
|
import { tmpdir } from "os";
|
|
6489
|
-
import { join, resolve as
|
|
6666
|
+
import { join, resolve as resolve12 } from "path";
|
|
6490
6667
|
import AdmZip from "adm-zip";
|
|
6491
|
-
import { Hono as
|
|
6492
|
-
var app16 = new
|
|
6668
|
+
import { Hono as Hono20 } from "hono";
|
|
6669
|
+
var app16 = new Hono20().get("/", async (c) => {
|
|
6493
6670
|
const skills = await listSharedSkills();
|
|
6494
6671
|
return c.json(skills);
|
|
6495
6672
|
}).get("/defaults/list", async (c) => {
|
|
@@ -6562,7 +6739,7 @@ var app16 = new Hono19().get("/", async (c) => {
|
|
|
6562
6739
|
try {
|
|
6563
6740
|
const zip = new AdmZip(buffer2);
|
|
6564
6741
|
for (const entry of zip.getEntries()) {
|
|
6565
|
-
const target =
|
|
6742
|
+
const target = resolve12(tmpDir, entry.entryName);
|
|
6566
6743
|
if (!target.startsWith(tmpDir)) {
|
|
6567
6744
|
return c.json({ error: "Invalid zip: paths must not escape archive" }, 400);
|
|
6568
6745
|
}
|
|
@@ -6613,15 +6790,15 @@ var app16 = new Hono19().get("/", async (c) => {
|
|
|
6613
6790
|
var skills_default = app16;
|
|
6614
6791
|
|
|
6615
6792
|
// packages/daemon/src/web/api/typing.ts
|
|
6616
|
-
import { zValidator as
|
|
6617
|
-
import { Hono as
|
|
6618
|
-
import { z as
|
|
6619
|
-
var typingSchema =
|
|
6620
|
-
channel:
|
|
6621
|
-
sender:
|
|
6622
|
-
active:
|
|
6793
|
+
import { zValidator as zValidator8 } from "@hono/zod-validator";
|
|
6794
|
+
import { Hono as Hono21 } from "hono";
|
|
6795
|
+
import { z as z8 } from "zod";
|
|
6796
|
+
var typingSchema = z8.object({
|
|
6797
|
+
channel: z8.string().min(1),
|
|
6798
|
+
sender: z8.string().min(1),
|
|
6799
|
+
active: z8.boolean()
|
|
6623
6800
|
});
|
|
6624
|
-
var app17 = new
|
|
6801
|
+
var app17 = new Hono21().post("/:name/typing", zValidator8("json", typingSchema), (c) => {
|
|
6625
6802
|
const { channel, sender, active } = c.req.valid("json");
|
|
6626
6803
|
const map = getTypingMap();
|
|
6627
6804
|
if (active) {
|
|
@@ -6645,9 +6822,9 @@ var typing_default = app17;
|
|
|
6645
6822
|
|
|
6646
6823
|
// packages/daemon/src/web/api/update.ts
|
|
6647
6824
|
import { spawn as spawn3 } from "child_process";
|
|
6648
|
-
import { Hono as
|
|
6825
|
+
import { Hono as Hono22 } from "hono";
|
|
6649
6826
|
var bin;
|
|
6650
|
-
var app18 = new
|
|
6827
|
+
var app18 = new Hono22().get("/update", async (c) => {
|
|
6651
6828
|
const result = await checkForUpdate();
|
|
6652
6829
|
return c.json(result);
|
|
6653
6830
|
}).post("/update", requireAdmin, async (c) => {
|
|
@@ -6665,13 +6842,13 @@ var app18 = new Hono21().get("/update", async (c) => {
|
|
|
6665
6842
|
var update_default = app18;
|
|
6666
6843
|
|
|
6667
6844
|
// packages/daemon/src/web/api/v1/conversations.ts
|
|
6668
|
-
import { zValidator as
|
|
6669
|
-
import { Hono as
|
|
6670
|
-
import { z as
|
|
6671
|
-
var createSchema =
|
|
6672
|
-
participantNames:
|
|
6845
|
+
import { zValidator as zValidator9 } from "@hono/zod-validator";
|
|
6846
|
+
import { Hono as Hono23 } from "hono";
|
|
6847
|
+
import { z as z9 } from "zod";
|
|
6848
|
+
var createSchema = z9.object({
|
|
6849
|
+
participantNames: z9.array(z9.string()).min(1)
|
|
6673
6850
|
});
|
|
6674
|
-
var app19 = new
|
|
6851
|
+
var app19 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
6675
6852
|
const user = c.get("user");
|
|
6676
6853
|
const convs = await listConversationsWithParticipants(user.id);
|
|
6677
6854
|
return c.json(convs);
|
|
@@ -6698,7 +6875,7 @@ var app19 = new Hono22().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6698
6875
|
}
|
|
6699
6876
|
const participants = await getParticipants(id);
|
|
6700
6877
|
return c.json(participants);
|
|
6701
|
-
}).post("/",
|
|
6878
|
+
}).post("/", zValidator9("json", createSchema), async (c) => {
|
|
6702
6879
|
const user = c.get("user");
|
|
6703
6880
|
const body = c.req.valid("json");
|
|
6704
6881
|
const participantIds = /* @__PURE__ */ new Set();
|
|
@@ -6747,7 +6924,7 @@ var app19 = new Hono22().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6747
6924
|
}
|
|
6748
6925
|
await markConversationRead(user.id, id);
|
|
6749
6926
|
return c.json({ ok: true });
|
|
6750
|
-
}).put("/:id/private",
|
|
6927
|
+
}).put("/:id/private", zValidator9("json", z9.object({ private: z9.boolean() })), async (c) => {
|
|
6751
6928
|
const id = c.req.param("id");
|
|
6752
6929
|
const user = c.get("user");
|
|
6753
6930
|
if (!await isParticipantOrOwner(id, user.id)) {
|
|
@@ -6767,7 +6944,7 @@ var conversations_default = app19;
|
|
|
6767
6944
|
|
|
6768
6945
|
// packages/daemon/src/web/api/v1/events.ts
|
|
6769
6946
|
import { desc as desc5, eq as eq7 } from "drizzle-orm";
|
|
6770
|
-
import { Hono as
|
|
6947
|
+
import { Hono as Hono24 } from "hono";
|
|
6771
6948
|
import { streamSSE as streamSSE4 } from "hono/streaming";
|
|
6772
6949
|
|
|
6773
6950
|
// packages/daemon/src/lib/events/brain-presence.ts
|
|
@@ -6830,7 +7007,7 @@ function getEventsSince(sinceId, allowedConversationIds, allowedActivityMind) {
|
|
|
6830
7007
|
}
|
|
6831
7008
|
|
|
6832
7009
|
// packages/daemon/src/web/api/v1/events.ts
|
|
6833
|
-
var app20 = new
|
|
7010
|
+
var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
|
|
6834
7011
|
const user = c.get("user");
|
|
6835
7012
|
const since = c.req.query("since");
|
|
6836
7013
|
const sinceId = since ? Number(since) : 0;
|
|
@@ -6848,7 +7025,7 @@ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6848
7025
|
conversations2 = await listConversationsWithParticipants(user.id);
|
|
6849
7026
|
if (conversations2.length > 0) {
|
|
6850
7027
|
const convIds = conversations2.map((c2) => c2.id);
|
|
6851
|
-
const unreads = await getUnreadCounts(user.id, convIds);
|
|
7028
|
+
const unreads = await getUnreadCounts(user.id, convIds, user.username);
|
|
6852
7029
|
for (const conv of conversations2) {
|
|
6853
7030
|
conv.unreadCount = unreads[conv.id] ?? 0;
|
|
6854
7031
|
}
|
|
@@ -6924,8 +7101,8 @@ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6924
7101
|
});
|
|
6925
7102
|
}, 15e3);
|
|
6926
7103
|
cleanups.push(() => clearInterval(keepAlive));
|
|
6927
|
-
await new Promise((
|
|
6928
|
-
stream.onAbort(() =>
|
|
7104
|
+
await new Promise((resolve17) => {
|
|
7105
|
+
stream.onAbort(() => resolve17());
|
|
6929
7106
|
});
|
|
6930
7107
|
} finally {
|
|
6931
7108
|
for (const cleanup of cleanups) {
|
|
@@ -6941,15 +7118,15 @@ var events_default = app20;
|
|
|
6941
7118
|
|
|
6942
7119
|
// packages/daemon/src/web/api/variants.ts
|
|
6943
7120
|
import { existsSync as existsSync9, mkdirSync as mkdirSync9, writeFileSync as writeFileSync8 } from "fs";
|
|
6944
|
-
import { resolve as
|
|
6945
|
-
import { Hono as
|
|
7121
|
+
import { resolve as resolve14 } from "path";
|
|
7122
|
+
import { Hono as Hono25 } from "hono";
|
|
6946
7123
|
|
|
6947
7124
|
// packages/daemon/src/lib/mind/spawn-server.ts
|
|
6948
7125
|
import { spawn as spawn4 } from "child_process";
|
|
6949
7126
|
import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync9 } from "fs";
|
|
6950
|
-
import { resolve as
|
|
7127
|
+
import { resolve as resolve13 } from "path";
|
|
6951
7128
|
function tsxBin(cwd) {
|
|
6952
|
-
return
|
|
7129
|
+
return resolve13(cwd, "node_modules", ".bin", "tsx");
|
|
6953
7130
|
}
|
|
6954
7131
|
async function spawnServer(cwd, port, options) {
|
|
6955
7132
|
let cmd = tsxBin(cwd);
|
|
@@ -6971,31 +7148,31 @@ function spawnAttached(cmd, args, cwd) {
|
|
|
6971
7148
|
cwd,
|
|
6972
7149
|
stdio: ["ignore", "pipe", "pipe"]
|
|
6973
7150
|
});
|
|
6974
|
-
return new Promise((
|
|
6975
|
-
const timeout = setTimeout(() =>
|
|
7151
|
+
return new Promise((resolve17) => {
|
|
7152
|
+
const timeout = setTimeout(() => resolve17(null), 3e4);
|
|
6976
7153
|
function checkOutput(data) {
|
|
6977
7154
|
const match = data.toString().match(/listening on :(\d+)/);
|
|
6978
7155
|
if (match) {
|
|
6979
7156
|
clearTimeout(timeout);
|
|
6980
|
-
|
|
7157
|
+
resolve17({ child, actualPort: parseInt(match[1], 10) });
|
|
6981
7158
|
}
|
|
6982
7159
|
}
|
|
6983
7160
|
child.stdout?.on("data", checkOutput);
|
|
6984
7161
|
child.stderr?.on("data", checkOutput);
|
|
6985
7162
|
child.on("error", () => {
|
|
6986
7163
|
clearTimeout(timeout);
|
|
6987
|
-
|
|
7164
|
+
resolve17(null);
|
|
6988
7165
|
});
|
|
6989
7166
|
child.on("exit", () => {
|
|
6990
7167
|
clearTimeout(timeout);
|
|
6991
|
-
|
|
7168
|
+
resolve17(null);
|
|
6992
7169
|
});
|
|
6993
7170
|
});
|
|
6994
7171
|
}
|
|
6995
7172
|
function spawnDetached(cmd, args, cwd, logDir) {
|
|
6996
|
-
const logsDir = logDir ??
|
|
7173
|
+
const logsDir = logDir ?? resolve13(cwd, ".mind", "logs");
|
|
6997
7174
|
mkdirSync8(logsDir, { recursive: true });
|
|
6998
|
-
const logPath =
|
|
7175
|
+
const logPath = resolve13(logsDir, "mind.log");
|
|
6999
7176
|
const logFd = openSync(logPath, "a");
|
|
7000
7177
|
const child = spawn4(cmd, args, {
|
|
7001
7178
|
cwd,
|
|
@@ -7067,7 +7244,7 @@ async function verify2(port) {
|
|
|
7067
7244
|
}
|
|
7068
7245
|
|
|
7069
7246
|
// packages/daemon/src/web/api/variants.ts
|
|
7070
|
-
var app21 = new
|
|
7247
|
+
var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
7071
7248
|
const name = c.req.param("name");
|
|
7072
7249
|
const entry = await findMind(name);
|
|
7073
7250
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
@@ -7111,11 +7288,11 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7111
7288
|
return c.json({ error: `Name already in use: ${variantName}` }, 409);
|
|
7112
7289
|
}
|
|
7113
7290
|
const projectRoot = mindDir(mindName);
|
|
7114
|
-
const variantDir =
|
|
7291
|
+
const variantDir = resolve14(projectRoot, ".variants", variantName);
|
|
7115
7292
|
if (existsSync9(variantDir)) {
|
|
7116
7293
|
return c.json({ error: `Variant directory already exists: ${variantDir}` }, 409);
|
|
7117
7294
|
}
|
|
7118
|
-
mkdirSync9(
|
|
7295
|
+
mkdirSync9(resolve14(projectRoot, ".variants"), { recursive: true });
|
|
7119
7296
|
try {
|
|
7120
7297
|
await gitExec(["worktree", "add", "-b", variantName, variantDir], { cwd: projectRoot });
|
|
7121
7298
|
} catch (e) {
|
|
@@ -7128,7 +7305,7 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7128
7305
|
const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
|
|
7129
7306
|
await exec(cmd, args, {
|
|
7130
7307
|
cwd: variantDir,
|
|
7131
|
-
env: { ...process.env, HOME:
|
|
7308
|
+
env: { ...process.env, HOME: resolve14(variantDir, "home") }
|
|
7132
7309
|
});
|
|
7133
7310
|
} else {
|
|
7134
7311
|
await exec("npm", ["install"], { cwd: variantDir });
|
|
@@ -7138,13 +7315,15 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7138
7315
|
return c.json({ error: `npm install failed: ${msg}` }, 500);
|
|
7139
7316
|
}
|
|
7140
7317
|
if (body.soul) {
|
|
7141
|
-
writeFileSync8(
|
|
7318
|
+
writeFileSync8(resolve14(variantDir, "home/SOUL.md"), body.soul);
|
|
7142
7319
|
}
|
|
7143
7320
|
const variantPort = body.port ?? await nextPort();
|
|
7144
7321
|
await addVariant(variantName, mindName, variantPort, variantDir, variantName);
|
|
7145
7322
|
if (!body.noStart) {
|
|
7146
7323
|
try {
|
|
7147
|
-
|
|
7324
|
+
const manager = getMindManager();
|
|
7325
|
+
manager.setPendingContext(variantName, { type: "split", parent: mindName });
|
|
7326
|
+
await manager.startMind(variantName);
|
|
7148
7327
|
} catch (e) {
|
|
7149
7328
|
const msg = e instanceof Error ? e.message : String(e);
|
|
7150
7329
|
return c.json({ error: `Variant created but failed to start: ${msg}` }, 500);
|
|
@@ -7238,7 +7417,7 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7238
7417
|
if (variantName.endsWith("-upgrade") || variantName === "upgrade") {
|
|
7239
7418
|
try {
|
|
7240
7419
|
const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-446HHH5V.js");
|
|
7241
|
-
const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-
|
|
7420
|
+
const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-NUJAGLQJ.js");
|
|
7242
7421
|
const tmpl = parentEntry.template ?? "claude";
|
|
7243
7422
|
await setMindTemplateHash2(mindName, computeTemplateHash2(tmpl));
|
|
7244
7423
|
} catch (err) {
|
|
@@ -7251,7 +7430,7 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7251
7430
|
const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
|
|
7252
7431
|
await exec(cmd, args, {
|
|
7253
7432
|
cwd: projectRoot,
|
|
7254
|
-
env: { ...process.env, HOME:
|
|
7433
|
+
env: { ...process.env, HOME: resolve14(projectRoot, "home") }
|
|
7255
7434
|
});
|
|
7256
7435
|
} else {
|
|
7257
7436
|
await exec("npm", ["install"], { cwd: projectRoot });
|
|
@@ -7296,22 +7475,22 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7296
7475
|
var variants_default = app21;
|
|
7297
7476
|
|
|
7298
7477
|
// packages/daemon/src/web/api/volute/channels.ts
|
|
7299
|
-
import { zValidator as
|
|
7300
|
-
import { Hono as
|
|
7301
|
-
import { z as
|
|
7302
|
-
var channelSettingsSchema =
|
|
7303
|
-
description:
|
|
7304
|
-
rules:
|
|
7305
|
-
charLimit:
|
|
7306
|
-
private:
|
|
7478
|
+
import { zValidator as zValidator10 } from "@hono/zod-validator";
|
|
7479
|
+
import { Hono as Hono26 } from "hono";
|
|
7480
|
+
import { z as z10 } from "zod";
|
|
7481
|
+
var channelSettingsSchema = z10.object({
|
|
7482
|
+
description: z10.string().nullable().optional(),
|
|
7483
|
+
rules: z10.string().nullable().optional(),
|
|
7484
|
+
charLimit: z10.number().int().positive().nullable().optional(),
|
|
7485
|
+
private: z10.boolean().optional()
|
|
7307
7486
|
});
|
|
7308
|
-
var createSchema2 =
|
|
7309
|
-
name:
|
|
7487
|
+
var createSchema2 = z10.object({
|
|
7488
|
+
name: z10.string().min(1).max(50).regex(/^[a-z0-9][a-z0-9-]*$/, "Channel names must be lowercase alphanumeric with hyphens")
|
|
7310
7489
|
}).merge(channelSettingsSchema);
|
|
7311
|
-
var inviteSchema =
|
|
7312
|
-
username:
|
|
7490
|
+
var inviteSchema = z10.object({
|
|
7491
|
+
username: z10.string().min(1)
|
|
7313
7492
|
});
|
|
7314
|
-
var app22 = new
|
|
7493
|
+
var app22 = new Hono26().get("/", async (c) => {
|
|
7315
7494
|
const user = c.get("user");
|
|
7316
7495
|
const channels2 = await listChannels();
|
|
7317
7496
|
const results = await Promise.all(
|
|
@@ -7322,7 +7501,7 @@ var app22 = new Hono25().get("/", async (c) => {
|
|
|
7322
7501
|
})
|
|
7323
7502
|
);
|
|
7324
7503
|
return c.json(results);
|
|
7325
|
-
}).post("/",
|
|
7504
|
+
}).post("/", zValidator10("json", createSchema2), async (c) => {
|
|
7326
7505
|
const user = c.get("user");
|
|
7327
7506
|
const body = c.req.valid("json");
|
|
7328
7507
|
try {
|
|
@@ -7350,7 +7529,7 @@ var app22 = new Hono25().get("/", async (c) => {
|
|
|
7350
7529
|
participants,
|
|
7351
7530
|
settings: formatChannelSettings(settings)
|
|
7352
7531
|
});
|
|
7353
|
-
}).patch("/:name",
|
|
7532
|
+
}).patch("/:name", zValidator10("json", channelSettingsSchema), async (c) => {
|
|
7354
7533
|
const name = c.req.param("name");
|
|
7355
7534
|
const user = c.get("user");
|
|
7356
7535
|
const body = c.req.valid("json");
|
|
@@ -7382,7 +7561,7 @@ var app22 = new Hono25().get("/", async (c) => {
|
|
|
7382
7561
|
if (!ch) return c.json({ error: "Channel not found" }, 404);
|
|
7383
7562
|
const participants = await getParticipants(ch.id);
|
|
7384
7563
|
return c.json(participants);
|
|
7385
|
-
}).post("/:name/invite",
|
|
7564
|
+
}).post("/:name/invite", zValidator10("json", inviteSchema), async (c) => {
|
|
7386
7565
|
const name = c.req.param("name");
|
|
7387
7566
|
const inviter = c.get("user");
|
|
7388
7567
|
const { username } = c.req.valid("json");
|
|
@@ -7408,27 +7587,27 @@ var app22 = new Hono25().get("/", async (c) => {
|
|
|
7408
7587
|
var channels_default2 = app22;
|
|
7409
7588
|
|
|
7410
7589
|
// packages/daemon/src/web/api/volute/chat.ts
|
|
7411
|
-
import { zValidator as
|
|
7412
|
-
import { Hono as
|
|
7590
|
+
import { zValidator as zValidator11 } from "@hono/zod-validator";
|
|
7591
|
+
import { Hono as Hono27 } from "hono";
|
|
7413
7592
|
import { streamSSE as streamSSE5 } from "hono/streaming";
|
|
7414
|
-
import { z as
|
|
7415
|
-
var fileSchema =
|
|
7416
|
-
filename:
|
|
7417
|
-
data:
|
|
7593
|
+
import { z as z11 } from "zod";
|
|
7594
|
+
var fileSchema = z11.object({
|
|
7595
|
+
filename: z11.string(),
|
|
7596
|
+
data: z11.string()
|
|
7418
7597
|
// base64
|
|
7419
7598
|
});
|
|
7420
|
-
var chatSchema =
|
|
7421
|
-
message:
|
|
7422
|
-
conversationId:
|
|
7423
|
-
targetMind:
|
|
7424
|
-
sender:
|
|
7425
|
-
images:
|
|
7426
|
-
|
|
7427
|
-
media_type:
|
|
7428
|
-
data:
|
|
7599
|
+
var chatSchema = z11.object({
|
|
7600
|
+
message: z11.string().optional(),
|
|
7601
|
+
conversationId: z11.string().optional(),
|
|
7602
|
+
targetMind: z11.string().optional(),
|
|
7603
|
+
sender: z11.string().optional(),
|
|
7604
|
+
images: z11.array(
|
|
7605
|
+
z11.object({
|
|
7606
|
+
media_type: z11.string(),
|
|
7607
|
+
data: z11.string()
|
|
7429
7608
|
})
|
|
7430
7609
|
).optional(),
|
|
7431
|
-
files:
|
|
7610
|
+
files: z11.array(fileSchema).optional()
|
|
7432
7611
|
});
|
|
7433
7612
|
var MAX_FILE_SIZE2 = 50 * 1024 * 1024;
|
|
7434
7613
|
function stageFilesForMinds(files, targetMinds, senderName) {
|
|
@@ -7456,9 +7635,9 @@ function stageFilesForMinds(files, targetMinds, senderName) {
|
|
|
7456
7635
|
}
|
|
7457
7636
|
return { notifications };
|
|
7458
7637
|
}
|
|
7459
|
-
var unifiedChatApp = new
|
|
7638
|
+
var unifiedChatApp = new Hono27().post(
|
|
7460
7639
|
"/chat",
|
|
7461
|
-
|
|
7640
|
+
zValidator11("json", chatSchema),
|
|
7462
7641
|
async (c) => {
|
|
7463
7642
|
const user = c.get("user");
|
|
7464
7643
|
const body = c.req.valid("json");
|
|
@@ -7579,6 +7758,19 @@ var unifiedChatApp = new Hono26().post(
|
|
|
7579
7758
|
senderBase = await getBaseName(senderName);
|
|
7580
7759
|
outboundTurnId = getActiveTurnId(senderBase, c.get("mindSession"));
|
|
7581
7760
|
}
|
|
7761
|
+
if (senderIsMind && senderBase) {
|
|
7762
|
+
const gate = await checkStaleSend(senderBase, conversationId, [senderName, senderBase]);
|
|
7763
|
+
if (gate.held && gate.unseen) {
|
|
7764
|
+
const label = buildVoluteSlug({
|
|
7765
|
+
participants,
|
|
7766
|
+
mindUsername: senderName,
|
|
7767
|
+
conversationId,
|
|
7768
|
+
convType: conv.type,
|
|
7769
|
+
convName
|
|
7770
|
+
});
|
|
7771
|
+
return c.json({ ok: true, held: true, notice: formatHoldNotice(label, gate.unseen) });
|
|
7772
|
+
}
|
|
7773
|
+
}
|
|
7582
7774
|
const message = await addMessage(conversationId, "user", senderName, contentBlocks, {
|
|
7583
7775
|
turnId: outboundTurnId
|
|
7584
7776
|
});
|
|
@@ -7619,7 +7811,6 @@ var unifiedChatApp = new Hono26().post(
|
|
|
7619
7811
|
conversationId,
|
|
7620
7812
|
contentBlocks,
|
|
7621
7813
|
senderName,
|
|
7622
|
-
senderIsMind: !!senderIsMind,
|
|
7623
7814
|
participants,
|
|
7624
7815
|
isDM,
|
|
7625
7816
|
slugExtra: { convType: conv.type, convName },
|
|
@@ -7638,7 +7829,7 @@ var unifiedChatApp = new Hono26().post(
|
|
|
7638
7829
|
return c.json({ ok: true, conversationId, outboundId });
|
|
7639
7830
|
}
|
|
7640
7831
|
);
|
|
7641
|
-
var app23 = new
|
|
7832
|
+
var app23 = new Hono27().get("/:name/conversations/:id/events", async (c) => {
|
|
7642
7833
|
const conversationId = c.req.param("id");
|
|
7643
7834
|
const user = c.get("user");
|
|
7644
7835
|
if (user.id !== 0 && !await isParticipantOrOwner(conversationId, user.id)) {
|
|
@@ -7655,11 +7846,11 @@ var app23 = new Hono26().get("/:name/conversations/:id/events", async (c) => {
|
|
|
7655
7846
|
if (!stream.aborted) console.error("[chat] SSE ping error:", err);
|
|
7656
7847
|
});
|
|
7657
7848
|
}, 15e3);
|
|
7658
|
-
await new Promise((
|
|
7849
|
+
await new Promise((resolve17) => {
|
|
7659
7850
|
stream.onAbort(() => {
|
|
7660
7851
|
unsubscribe();
|
|
7661
7852
|
clearInterval(keepAlive);
|
|
7662
|
-
|
|
7853
|
+
resolve17();
|
|
7663
7854
|
});
|
|
7664
7855
|
});
|
|
7665
7856
|
});
|
|
@@ -7667,14 +7858,14 @@ var app23 = new Hono26().get("/:name/conversations/:id/events", async (c) => {
|
|
|
7667
7858
|
var chat_default = app23;
|
|
7668
7859
|
|
|
7669
7860
|
// packages/daemon/src/web/api/volute/conversations.ts
|
|
7670
|
-
import { zValidator as
|
|
7671
|
-
import { Hono as
|
|
7672
|
-
import { z as
|
|
7673
|
-
var createConvSchema =
|
|
7674
|
-
participantIds:
|
|
7675
|
-
participantNames:
|
|
7861
|
+
import { zValidator as zValidator12 } from "@hono/zod-validator";
|
|
7862
|
+
import { Hono as Hono28 } from "hono";
|
|
7863
|
+
import { z as z12 } from "zod";
|
|
7864
|
+
var createConvSchema = z12.object({
|
|
7865
|
+
participantIds: z12.array(z12.number()).optional(),
|
|
7866
|
+
participantNames: z12.array(z12.string()).optional()
|
|
7676
7867
|
});
|
|
7677
|
-
var app24 = new
|
|
7868
|
+
var app24 = new Hono28().get("/:name/conversations", async (c) => {
|
|
7678
7869
|
const name = c.req.param("name");
|
|
7679
7870
|
const user = c.get("user");
|
|
7680
7871
|
let lookupId = user.id;
|
|
@@ -7684,7 +7875,7 @@ var app24 = new Hono27().get("/:name/conversations", async (c) => {
|
|
|
7684
7875
|
}
|
|
7685
7876
|
const convs = await listConversationsForUser(lookupId);
|
|
7686
7877
|
return c.json(convs);
|
|
7687
|
-
}).post("/:name/conversations",
|
|
7878
|
+
}).post("/:name/conversations", zValidator12("json", createConvSchema), async (c) => {
|
|
7688
7879
|
const name = c.req.param("name");
|
|
7689
7880
|
const user = c.get("user");
|
|
7690
7881
|
const body = c.req.valid("json");
|
|
@@ -7780,7 +7971,7 @@ var conversations_default2 = app24;
|
|
|
7780
7971
|
|
|
7781
7972
|
// packages/daemon/src/web/app.ts
|
|
7782
7973
|
var httpLog = logger_default.child("http");
|
|
7783
|
-
var app25 = new
|
|
7974
|
+
var app25 = new Hono29();
|
|
7784
7975
|
app25.onError((err, c) => {
|
|
7785
7976
|
if (err instanceof HTTPException) {
|
|
7786
7977
|
return err.getResponse();
|
|
@@ -7847,10 +8038,11 @@ app25.use("/api/skills/*", authMiddleware);
|
|
|
7847
8038
|
app25.use("/api/extensions/*", authMiddleware);
|
|
7848
8039
|
app25.use("/api/bridges/*", authMiddleware);
|
|
7849
8040
|
app25.use("/api/config/*", authMiddleware);
|
|
8041
|
+
app25.use("/api/backup/*", authMiddleware);
|
|
7850
8042
|
app25.use("/api/v1/*", authMiddleware);
|
|
7851
8043
|
app25.route("/api/setup", setup_default);
|
|
7852
8044
|
app25.route("/api/config", config_default);
|
|
7853
|
-
var routes = app25.route("/api/activity", activity_default).route("/api/keys", keys_default).route("/api/auth", auth_default).route("/api/system", system_default).route("/api/system", update_default).route("/api/minds", minds_default).route("/api/minds", chat_default).route("/api/minds", schedules_default).route("/api/minds", logs_default).route("/api/minds", typing_default).route("/api/minds", variants_default).route("/api/minds", file_sharing_default).route("/api/minds", files_default).route("/api/minds", channels_default).route("/api/minds", env_default).route("/api/minds", mind_skills_default).route("/api/minds", conversations_default2).route("/api/env", sharedEnvApp).route("/api/prompts", prompts_default).route("/api/skills", skills_default).route("/api/bridges", bridges_default).route("/api/extensions", extensions_default).route("/api/v1/conversations", conversations_default).route("/api/v1/events", events_default).route("/api/v1", unifiedChatApp).route("/api/v1/channels", channels_default2).route("/api/v1/history", history_default);
|
|
8045
|
+
var routes = app25.route("/api/activity", activity_default).route("/api/keys", keys_default).route("/api/auth", auth_default).route("/api/system", system_default).route("/api/system", update_default).route("/api/backup", backup_default).route("/api/minds", minds_default).route("/api/minds", chat_default).route("/api/minds", schedules_default).route("/api/minds", logs_default).route("/api/minds", typing_default).route("/api/minds", variants_default).route("/api/minds", file_sharing_default).route("/api/minds", files_default).route("/api/minds", channels_default).route("/api/minds", env_default).route("/api/minds", mind_skills_default).route("/api/minds", conversations_default2).route("/api/env", sharedEnvApp).route("/api/prompts", prompts_default).route("/api/skills", skills_default).route("/api/bridges", bridges_default).route("/api/extensions", extensions_default).route("/api/v1/conversations", conversations_default).route("/api/v1/events", events_default).route("/api/v1", unifiedChatApp).route("/api/v1/channels", channels_default2).route("/api/v1/history", history_default);
|
|
7854
8046
|
app25.route("/api/v1/minds", minds_default);
|
|
7855
8047
|
app25.route("/api/v1/minds", chat_default);
|
|
7856
8048
|
app25.route("/api/v1/minds", typing_default);
|
|
@@ -7872,7 +8064,7 @@ var app_default = app25;
|
|
|
7872
8064
|
import { existsSync as existsSync10 } from "fs";
|
|
7873
8065
|
import { readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
7874
8066
|
import { createServer as createHttpsServer } from "https";
|
|
7875
|
-
import { dirname as dirname2, extname as extname3, resolve as
|
|
8067
|
+
import { dirname as dirname2, extname as extname3, resolve as resolve15 } from "path";
|
|
7876
8068
|
import { serve } from "@hono/node-server";
|
|
7877
8069
|
var MIME_TYPES2 = {
|
|
7878
8070
|
".html": "text/html",
|
|
@@ -7891,7 +8083,7 @@ async function startServer({
|
|
|
7891
8083
|
let assetsDir = "";
|
|
7892
8084
|
let searchDir = dirname2(new URL(import.meta.url).pathname);
|
|
7893
8085
|
for (let i = 0; i < 5; i++) {
|
|
7894
|
-
const candidate =
|
|
8086
|
+
const candidate = resolve15(searchDir, "dist", "web-assets");
|
|
7895
8087
|
if (existsSync10(candidate)) {
|
|
7896
8088
|
assetsDir = candidate;
|
|
7897
8089
|
break;
|
|
@@ -7902,20 +8094,20 @@ async function startServer({
|
|
|
7902
8094
|
app_default.get("*", async (c) => {
|
|
7903
8095
|
const urlPath = new URL(c.req.url).pathname;
|
|
7904
8096
|
if (urlPath.startsWith("/api/") || urlPath.startsWith("/ext/")) return c.notFound();
|
|
7905
|
-
const filePath =
|
|
8097
|
+
const filePath = resolve15(assetsDir, urlPath.slice(1));
|
|
7906
8098
|
if (!filePath.startsWith(assetsDir)) return c.text("Forbidden", 403);
|
|
7907
8099
|
const s = await stat2(filePath).catch(() => null);
|
|
7908
8100
|
if (s?.isFile()) {
|
|
7909
8101
|
const ext = extname3(filePath);
|
|
7910
8102
|
const mime = MIME_TYPES2[ext] || "application/octet-stream";
|
|
7911
8103
|
const body = await readFile2(filePath);
|
|
7912
|
-
const
|
|
7913
|
-
const nameWithoutExt =
|
|
8104
|
+
const basename = filePath.slice(filePath.lastIndexOf("/") + 1);
|
|
8105
|
+
const nameWithoutExt = basename.slice(0, basename.lastIndexOf("."));
|
|
7914
8106
|
const isHashed = /[-.][\da-f]{8,}$/.test(nameWithoutExt);
|
|
7915
8107
|
const cacheControl = isHashed ? "public, max-age=31536000, immutable" : "no-cache";
|
|
7916
8108
|
return c.body(body, 200, { "Content-Type": mime, "Cache-Control": cacheControl });
|
|
7917
8109
|
}
|
|
7918
|
-
const indexPath =
|
|
8110
|
+
const indexPath = resolve15(assetsDir, "index.html");
|
|
7919
8111
|
const indexStat = await stat2(indexPath).catch(() => null);
|
|
7920
8112
|
if (indexStat?.isFile()) {
|
|
7921
8113
|
const body = await readFile2(indexPath, "utf-8");
|
|
@@ -7932,10 +8124,10 @@ async function startServer({
|
|
|
7932
8124
|
createServer: createHttpsServer,
|
|
7933
8125
|
serverOptions: { key: tls.key, cert: tls.cert }
|
|
7934
8126
|
});
|
|
7935
|
-
await new Promise((
|
|
8127
|
+
await new Promise((resolve17, reject) => {
|
|
7936
8128
|
server2.on("listening", () => {
|
|
7937
8129
|
logger_default.info("Volute UI running (https)", { hostname, port });
|
|
7938
|
-
|
|
8130
|
+
resolve17();
|
|
7939
8131
|
});
|
|
7940
8132
|
server2.on("error", (err) => {
|
|
7941
8133
|
reject(err);
|
|
@@ -7943,13 +8135,13 @@ async function startServer({
|
|
|
7943
8135
|
});
|
|
7944
8136
|
const internalPort = port + 1;
|
|
7945
8137
|
const internalServer = serve({ fetch: app_default.fetch, port: internalPort, hostname: "127.0.0.1" });
|
|
7946
|
-
await new Promise((
|
|
8138
|
+
await new Promise((resolve17, reject) => {
|
|
7947
8139
|
internalServer.on("listening", () => {
|
|
7948
8140
|
logger_default.info("Volute API running (http, internal)", {
|
|
7949
8141
|
hostname: "127.0.0.1",
|
|
7950
8142
|
port: internalPort
|
|
7951
8143
|
});
|
|
7952
|
-
|
|
8144
|
+
resolve17();
|
|
7953
8145
|
});
|
|
7954
8146
|
internalServer.on("error", (err) => {
|
|
7955
8147
|
reject(err);
|
|
@@ -7958,10 +8150,10 @@ async function startServer({
|
|
|
7958
8150
|
return { server: server2, internalPort };
|
|
7959
8151
|
}
|
|
7960
8152
|
const server = serve({ fetch: app_default.fetch, port, hostname });
|
|
7961
|
-
await new Promise((
|
|
8153
|
+
await new Promise((resolve17, reject) => {
|
|
7962
8154
|
server.on("listening", () => {
|
|
7963
8155
|
logger_default.info("Volute API running (http)", { hostname, port });
|
|
7964
|
-
|
|
8156
|
+
resolve17();
|
|
7965
8157
|
});
|
|
7966
8158
|
server.on("error", (err) => {
|
|
7967
8159
|
reject(err);
|
|
@@ -7972,17 +8164,17 @@ async function startServer({
|
|
|
7972
8164
|
|
|
7973
8165
|
// packages/daemon/src/daemon.ts
|
|
7974
8166
|
if (!process.env.VOLUTE_HOME) {
|
|
7975
|
-
process.env.VOLUTE_HOME =
|
|
8167
|
+
process.env.VOLUTE_HOME = resolve16(homedir3(), ".volute");
|
|
7976
8168
|
}
|
|
7977
8169
|
if (process.env.VOLUTE_TIMEZONE && !process.env.TZ) {
|
|
7978
8170
|
process.env.TZ = process.env.VOLUTE_TIMEZONE;
|
|
7979
8171
|
}
|
|
7980
8172
|
function writeDaemonConfig(systemDir, config2, token) {
|
|
7981
|
-
const configPath =
|
|
8173
|
+
const configPath = resolve16(systemDir, "daemon.json");
|
|
7982
8174
|
writeFileSync9(configPath, `${JSON.stringify(config2, null, 2)}
|
|
7983
8175
|
`, { mode: 420 });
|
|
7984
8176
|
chmodSync(configPath, 420);
|
|
7985
|
-
const tokenPath =
|
|
8177
|
+
const tokenPath = resolve16(systemDir, "daemon-token");
|
|
7986
8178
|
writeFileSync9(tokenPath, `${token}
|
|
7987
8179
|
`, { mode: 384 });
|
|
7988
8180
|
chmodSync(tokenPath, 384);
|
|
@@ -7993,7 +8185,7 @@ async function startDaemon(opts) {
|
|
|
7993
8185
|
const home = voluteHome();
|
|
7994
8186
|
const systemDir = voluteSystemDir();
|
|
7995
8187
|
if (!opts.foreground) {
|
|
7996
|
-
const rotatingLog = new RotatingLog(
|
|
8188
|
+
const rotatingLog = new RotatingLog(resolve16(systemDir, "daemon.log"));
|
|
7997
8189
|
logger_default.setOutput((line) => rotatingLog.write(`${line}
|
|
7998
8190
|
`));
|
|
7999
8191
|
const write = (...args) => rotatingLog.write(`${format(...args)}
|
|
@@ -8003,26 +8195,32 @@ async function startDaemon(opts) {
|
|
|
8003
8195
|
console.warn = write;
|
|
8004
8196
|
console.info = write;
|
|
8005
8197
|
}
|
|
8006
|
-
const DAEMON_PID_PATH =
|
|
8007
|
-
const DAEMON_JSON_PATH =
|
|
8008
|
-
const DAEMON_TOKEN_PATH =
|
|
8198
|
+
const DAEMON_PID_PATH = resolve16(systemDir, "daemon.pid");
|
|
8199
|
+
const DAEMON_JSON_PATH = resolve16(systemDir, "daemon.json");
|
|
8200
|
+
const DAEMON_TOKEN_PATH = resolve16(systemDir, "daemon-token");
|
|
8009
8201
|
mkdirSync10(home, { recursive: true });
|
|
8010
8202
|
ensureSystemDir();
|
|
8011
|
-
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-
|
|
8203
|
+
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-73YBJZQL.js");
|
|
8012
8204
|
migrateConfigSecrets();
|
|
8013
8205
|
migrateSetupCompleted();
|
|
8014
|
-
const { migrateAiModelQualification } = await import("./ai-service-
|
|
8206
|
+
const { migrateAiModelQualification } = await import("./ai-service-534WUSDL.js");
|
|
8015
8207
|
migrateAiModelQualification();
|
|
8016
|
-
await (await import("./db-
|
|
8208
|
+
await (await import("./db-JFLCJCUG.js")).getDb();
|
|
8017
8209
|
try {
|
|
8018
8210
|
const { eq: eq8, and: and6 } = await import("drizzle-orm");
|
|
8019
|
-
const { users: users2 } = await import("./schema-
|
|
8020
|
-
const db = await (await import("./db-
|
|
8211
|
+
const { users: users2 } = await import("./schema-PVNG3PQM.js");
|
|
8212
|
+
const db = await (await import("./db-JFLCJCUG.js")).getDb();
|
|
8021
8213
|
await db.update(users2).set({ role: "system" }).where(and6(eq8(users2.user_type, "system"), eq8(users2.role, "user")));
|
|
8022
8214
|
} catch (err) {
|
|
8023
8215
|
logger_default.warn("failed to migrate system user role", logger_default.errorData(err));
|
|
8024
8216
|
}
|
|
8025
|
-
|
|
8217
|
+
try {
|
|
8218
|
+
const { migrateAvatarSizes } = await import("./avatar-image-BNWEXSA2.js");
|
|
8219
|
+
await migrateAvatarSizes();
|
|
8220
|
+
} catch (err) {
|
|
8221
|
+
logger_default.warn("avatar size migration failed", logger_default.errorData(err));
|
|
8222
|
+
}
|
|
8223
|
+
const { initSandbox } = await import("./sandbox-72MWV4JL.js");
|
|
8026
8224
|
await initSandbox();
|
|
8027
8225
|
try {
|
|
8028
8226
|
await syncBuiltinSkills();
|
|
@@ -8049,7 +8247,7 @@ async function startDaemon(opts) {
|
|
|
8049
8247
|
logger_default.warn("failed to ensure #system channel", logger_default.errorData(err));
|
|
8050
8248
|
}
|
|
8051
8249
|
try {
|
|
8052
|
-
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-
|
|
8250
|
+
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-FRZJVQCS.js");
|
|
8053
8251
|
await getOrCreateSystemUser2();
|
|
8054
8252
|
} catch (err) {
|
|
8055
8253
|
logger_default.warn(
|
|
@@ -8057,13 +8255,13 @@ async function startDaemon(opts) {
|
|
|
8057
8255
|
logger_default.errorData(err)
|
|
8058
8256
|
);
|
|
8059
8257
|
}
|
|
8060
|
-
const token = process.env.VOLUTE_DAEMON_TOKEN ||
|
|
8061
|
-
const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-
|
|
8258
|
+
const token = process.env.VOLUTE_DAEMON_TOKEN || randomBytes3(32).toString("hex");
|
|
8259
|
+
const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-73YBJZQL.js");
|
|
8062
8260
|
const globalCfg = readGlobalConfig2();
|
|
8063
8261
|
let tls;
|
|
8064
8262
|
if (opts.tailscale || globalCfg.tailscale) {
|
|
8065
8263
|
try {
|
|
8066
|
-
const { getTailscaleTls } = await import("./tailscale-
|
|
8264
|
+
const { getTailscaleTls } = await import("./tailscale-QAWVKQKU.js");
|
|
8067
8265
|
const tlsConfig = await getTailscaleTls();
|
|
8068
8266
|
tls = { key: tlsConfig.key, cert: tlsConfig.cert };
|
|
8069
8267
|
logger_default.info("Tailscale HTTPS enabled", { hostname: tlsConfig.hostname });
|
|
@@ -8109,6 +8307,8 @@ async function startDaemon(opts) {
|
|
|
8109
8307
|
sleepManager.start();
|
|
8110
8308
|
const summarizer = initSummarizer();
|
|
8111
8309
|
summarizer.start();
|
|
8310
|
+
const backupManager2 = initBackupManager();
|
|
8311
|
+
backupManager2.start();
|
|
8112
8312
|
const unsubscribeWebhook = initWebhook();
|
|
8113
8313
|
const orphanedTurns = await completeOrphanedTurns();
|
|
8114
8314
|
summarizeOrphanedTurns(orphanedTurns);
|
|
@@ -8141,10 +8341,10 @@ async function startDaemon(opts) {
|
|
|
8141
8341
|
await Promise.all(workers);
|
|
8142
8342
|
}
|
|
8143
8343
|
try {
|
|
8144
|
-
const { isSetupComplete: isSetupComplete2 } = await import("./setup-
|
|
8344
|
+
const { isSetupComplete: isSetupComplete2 } = await import("./setup-73YBJZQL.js");
|
|
8145
8345
|
if (isSetupComplete2()) {
|
|
8146
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
8147
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
8346
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-II3HOERM.js");
|
|
8347
|
+
const { startSpiritFull } = await import("./mind-service-BF2LUQMH.js");
|
|
8148
8348
|
await ensureSpiritProject();
|
|
8149
8349
|
await syncSpiritTemplate();
|
|
8150
8350
|
const spiritEntry = await findMind("volute");
|
|
@@ -8161,7 +8361,7 @@ async function startDaemon(opts) {
|
|
|
8161
8361
|
bridgeManager.startBridges(daemonPort).catch((err) => {
|
|
8162
8362
|
logger_default.warn("failed to start bridges", logger_default.errorData(err));
|
|
8163
8363
|
});
|
|
8164
|
-
import("./cloud-sync-
|
|
8364
|
+
import("./cloud-sync-Y7LQPRE3.js").then(
|
|
8165
8365
|
({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
|
|
8166
8366
|
logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
|
|
8167
8367
|
})
|
|
@@ -8169,7 +8369,7 @@ async function startDaemon(opts) {
|
|
|
8169
8369
|
logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
|
|
8170
8370
|
});
|
|
8171
8371
|
try {
|
|
8172
|
-
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-
|
|
8372
|
+
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-CODJOUW2.js");
|
|
8173
8373
|
backfillTemplateHashes();
|
|
8174
8374
|
notifyVersionUpdate().catch((err) => {
|
|
8175
8375
|
logger_default.warn("failed to send version update notifications", logger_default.errorData(err));
|
|
@@ -8237,6 +8437,7 @@ async function startDaemon(opts) {
|
|
|
8237
8437
|
safe("mailPoller.stop", () => mailPoller.stop());
|
|
8238
8438
|
safe("tokenBudget.stop", () => tokenBudget.stop());
|
|
8239
8439
|
safe("summarizer.stop", () => summarizer.stop());
|
|
8440
|
+
safe("backupManager.stop", () => backupManager2.stop());
|
|
8240
8441
|
safe("stopApiKeyRefresh", stopApiKeyRefresh);
|
|
8241
8442
|
safe("delivery.dispose", () => delivery.dispose());
|
|
8242
8443
|
await safe("bridgeManager.stopAll", () => bridgeManager.stopAll());
|