volute 0.47.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/dist/{accept-YAFP5JFJ.js → accept-KYNC5X3U.js} +3 -3
- package/dist/{ai-service-CVZEYKTK.js → ai-service-643TNFPH.js} +6 -2
- package/dist/{avatar-image-7S3WA77A.js → avatar-image-Y45R7LW5.js} +3 -2
- package/dist/{backup-IIAFOW2L.js → backup-UDH4GMSW.js} +11 -11
- package/dist/{bridge-TIZGSXOD.js → bridge-3FNSWLNQ.js} +3 -3
- package/dist/{channels-ITE4YC57.js → channels-SGQZHNQJ.js} +3 -3
- package/dist/{chat-AJLJCQ3M.js → chat-X43VYHH2.js} +9 -9
- package/dist/chunk-4FCL4DVZ.js +48 -0
- package/dist/{chunk-SKNXMUIU.js → chunk-5KXCM5AW.js} +17 -1
- package/dist/{chunk-RBNMDAKB.js → chunk-BCG45AQB.js} +15 -1
- package/dist/chunk-DW4TRDOZ.js +29 -0
- package/dist/{chunk-CBOIHNMR.js → chunk-FJ2MZ5PH.js} +39 -3
- package/dist/{chunk-M6TTZRGH.js → chunk-HNGFKPNS.js} +20 -4
- package/dist/{chunk-IWJSNMSY.js → chunk-HUNDXZBZ.js} +2 -2
- package/dist/chunk-IYCV34IU.js +158 -0
- package/dist/{chunk-5IERLDUS.js → chunk-MJRXFUMS.js} +25 -5
- package/dist/{chunk-JCMGDCGX.js → chunk-MOERAQXH.js} +2 -0
- package/dist/{chunk-XHN6XBWV.js → chunk-OQJMTHEH.js} +1 -1
- package/dist/{chunk-BGYHLR54.js → chunk-PJVPDY2Z.js} +1 -1
- package/dist/{chunk-5NN2VHJV.js → chunk-Q7HOAVFR.js} +1 -1
- package/dist/{chunk-KDLYIECM.js → chunk-R772ET2M.js} +18 -4
- package/dist/{mind-list-KEGRGQEQ.js → chunk-SHKM5RGD.js} +19 -6
- package/dist/{chunk-4I72V3E5.js → chunk-T4VS7UDW.js} +11 -11
- package/dist/{chunk-K23P5Q5N.js → chunk-USD45JKR.js} +27 -5
- package/dist/{chunk-F55GRIEK.js → chunk-VB2QXUJQ.js} +176 -201
- package/dist/{chunk-M3XDVS5Q.js → chunk-VZRA5TYO.js} +1 -1
- package/dist/{chunk-JSVHH32K.js → chunk-WARH6GIV.js} +10 -10
- package/dist/{chunk-PFZBNKUH.js → chunk-WCFSBH33.js} +0 -1
- package/dist/{chunk-VMCZBXF2.js → chunk-WQ46E33M.js} +8 -32
- package/dist/{chunk-RUFLGTOT.js → chunk-XVBSFLM7.js} +1 -1
- package/dist/{chunk-LWDTP6DH.js → chunk-YNBXEQAP.js} +31 -1
- package/dist/cli.js +33 -25
- package/dist/{clock-E6N5Y3YW.js → clock-CNRF6F7T.js} +3 -3
- package/dist/{cloud-sync-LQTVDTQ3.js → cloud-sync-WHKCB4CD.js} +14 -12
- package/dist/{config-TJLYUV3U.js → config-RPSLA2HX.js} +3 -3
- package/dist/{create-PQQXKTJK.js → create-GJKHABJB.js} +16 -5
- package/dist/{create-A7PDHIIL.js → create-VIQVP3QB.js} +3 -3
- package/dist/{daemon-client-IYR4KCPU.js → daemon-client-ZFY5MOAL.js} +5 -3
- package/dist/{daemon-restart-5F3YTLZK.js → daemon-restart-7KUHVZIN.js} +4 -4
- package/dist/daemon.js +668 -401
- package/dist/{db-LZTLA7XC.js → db-IPXRJUI7.js} +1 -1
- package/dist/{delete-HPLC7ETU.js → delete-ESEP7NGQ.js} +1 -1
- package/dist/{delivery-manager-TN5KK2AP.js → delivery-manager-HZTT5SJR.js} +14 -12
- package/dist/{down-ZI4S6265.js → down-G6IADJXV.js} +2 -2
- package/dist/{echo-text-SEQCLGAT.js → echo-text-H3SH337Q.js} +16 -14
- package/dist/env-6TGPO5WG.js +18 -0
- package/dist/{env-HRL2PWAT.js → env-C7Z55QCJ.js} +7 -7
- package/dist/{export-4GVGNW54.js → export-C2K3NIRD.js} +1 -1
- package/dist/{extension-QBY4C44L.js → extension-J4ZQ2GHV.js} +3 -3
- package/dist/{extensions-PIMIQ7J3.js → extensions-GEKF47A4.js} +14 -12
- package/dist/{files-FEFZKMNM.js → files-LXQSQOFG.js} +3 -3
- package/dist/{import-7MO3YTRE.js → import-SX3ZXHB4.js} +4 -4
- package/dist/{join-ZJV7W6MO.js → join-34TR2GXQ.js} +1 -1
- package/dist/{list-LQO2DCIK.js → list-PMUXZNAM.js} +3 -3
- package/dist/{login-6TLMI2TQ.js → login-ARRZ4ORJ.js} +3 -3
- package/dist/{login-OF4WXDAN.js → login-CL4IT2ED.js} +12 -3
- package/dist/{logout-ERE2BGA3.js → logout-HZYJCYCA.js} +3 -3
- package/dist/{logout-BK53HXNY.js → logout-YZRMZ3O2.js} +3 -3
- package/dist/{message-delivery-ZE3YGJDD.js → message-delivery-GPQ5SE5N.js} +14 -12
- package/dist/{mind-POOHFZHP.js → mind-46AOK373.js} +23 -19
- package/dist/mind-contacts-GV7XYL5D.js +64 -0
- package/dist/{mind-history-47DN6ILW.js → mind-history-TTGA5BHZ.js} +7 -7
- package/dist/mind-list-OTHV4ZO4.js +13 -0
- package/dist/{mind-profile-PEQYASQX.js → mind-profile-LUG353ZT.js} +1 -1
- package/dist/{mind-service-JFY7UG5E.js → mind-service-2ARGJNKP.js} +16 -12
- package/dist/{mind-sleep-IN3WPA76.js → mind-sleep-DV7KP255.js} +5 -5
- package/dist/{mind-status-SMUWJKGV.js → mind-status-BJNPGXKC.js} +8 -3
- package/dist/{mind-wake-R54BPESY.js → mind-wake-LVTZ55EZ.js} +3 -3
- package/dist/notices-2KU5NTRY.js +25 -0
- package/dist/{package-WPEE2HVJ.js → package-RTN2PS7O.js} +4 -2
- package/dist/{read-PWAJOQIQ.js → read-YSWUXYL7.js} +3 -3
- package/dist/{register-7SZJFHU6.js → register-42VBJKTP.js} +3 -3
- package/dist/{reject-6VH7N2A4.js → reject-SXGCYN4A.js} +3 -3
- package/dist/{restart-H5WJDMA7.js → restart-YYEGZJDD.js} +7 -7
- package/dist/{sandbox-G4X4K3UN.js → sandbox-5VQ454XP.js} +2 -2
- package/dist/{scheduler-HQSDYJFY.js → scheduler-I7JZCT47.js} +14 -12
- package/dist/{seed-VANPU43L.js → seed-F2HXZQU4.js} +1 -1
- package/dist/{seed-check-VLTVILOV.js → seed-check-TYD7RRZY.js} +1 -1
- package/dist/{seed-cmd-SYVDZKM4.js → seed-cmd-MLCTGSX5.js} +3 -3
- package/dist/{seed-create-3FGZPS6C.js → seed-create-KQ7OILWB.js} +6 -4
- package/dist/seed-readiness-RBPGOLSZ.js +18 -0
- package/dist/{seed-sprout-H7QLFPFM.js → seed-sprout-HVYCFJLA.js} +29 -30
- package/dist/{send-HYDFGC6G.js → send-TD2X5U3K.js} +7 -7
- package/dist/{service-SYJ5G6LP.js → service-CVZMQYK6.js} +1 -1
- package/dist/{service-install-FQ43Z4DF.js → service-install-VCRMFWX5.js} +2 -2
- package/dist/{setup-KFYVWTXG.js → setup-5ECWTYKG.js} +5 -1
- package/dist/{setup-QJHGMGSN.js → setup-AE4CVUC4.js} +4 -4
- package/dist/{skill-GUKG2YVH.js → skill-UUM4JZRF.js} +7 -7
- package/dist/skills/dreaming/SKILL.md +5 -1
- package/dist/skills/dreaming/scripts/dream.ts +5 -1
- package/dist/skills/orientation/SKILL.md +8 -7
- package/dist/skills/tending/SKILL.md +51 -2
- package/dist/skills/volute-mind/SKILL.md +2 -0
- package/dist/{skills-L2CMTW7A.js → skills-B3SVDCEB.js} +2 -2
- package/dist/{sleep-manager-3NA7ZJP3.js → sleep-manager-Z27R3WTW.js} +14 -12
- package/dist/{spirit-WXN4IDBF.js → spirit-WXS3HCLN.js} +7 -5
- package/dist/{split-WBMZXBHF.js → split-SKZ4Y2D6.js} +1 -1
- package/dist/{sprout-LTL5P36T.js → sprout-KQ43BWZJ.js} +1 -1
- package/dist/{src-OJHARHTF.js → src-WLJE73NP.js} +14 -5
- package/dist/{start-X46I3GXB.js → start-O6UKK7BG.js} +7 -7
- package/dist/{status-V4RJMHJ4.js → status-F4PGREUU.js} +6 -4
- package/dist/{stop-HJQV4YSM.js → stop-UBX6X5RA.js} +7 -7
- package/dist/{system-chat-N2F7HVY3.js → system-chat-63ABFF6V.js} +14 -12
- package/dist/{systems-B5YJKMW4.js → systems-JJNGQHAO.js} +6 -6
- package/dist/{turn-tracker-JZRZDFWV.js → turn-tracker-KLPV3PAU.js} +4 -4
- package/dist/{up-J2PBPOZL.js → up-RVGDE6CQ.js} +5 -3
- package/dist/{update-ACV4SAY3.js → update-OXQEGGXD.js} +1 -1
- package/dist/{upgrade-NWAZ7MLD.js → upgrade-K5FIQPQD.js} +1 -1
- package/dist/{version-notify-XRGTEEDK.js → version-notify-73YURTFR.js} +17 -15
- package/dist/web-assets/assets/index-WdZ60R6c.css +1 -0
- package/dist/web-assets/assets/index-taX6Ezfa.js +92 -0
- package/dist/web-assets/index.html +2 -2
- package/package.json +4 -2
- package/packages/extensions/pages/dist/ui/assets/index-BuXnE-rb.css +1 -0
- package/packages/extensions/pages/dist/ui/assets/index-DtzftuPA.js +2 -0
- package/packages/extensions/pages/dist/ui/index.html +2 -2
- package/templates/_base/src/lib/startup.ts +16 -1
- package/templates/claude/src/agent.ts +9 -2
- package/templates/claude/src/server.ts +4 -2
- package/templates/pi/src/agent.ts +7 -10
- package/templates/pi/src/lib/dispatch.ts +65 -0
- package/dist/volute-config-A52FHWKM.js +0 -14
- package/dist/web-assets/assets/index-DtctoDXY.css +0 -1
- package/dist/web-assets/assets/index-Wpyb2CML.js +0 -86
- package/packages/extensions/pages/dist/ui/assets/index-BcY6lnq4.css +0 -1
- package/packages/extensions/pages/dist/ui/assets/index-CQjEQg1r.js +0 -2
- /package/dist/{chunk-IYG4FBMP.js → chunk-IJPMIEVE.js} +0 -0
package/dist/daemon.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
readBackupState,
|
|
7
7
|
resticVersion,
|
|
8
8
|
runBackup
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-Q7HOAVFR.js";
|
|
10
10
|
import {
|
|
11
11
|
acceptPending,
|
|
12
12
|
formatFileSize,
|
|
@@ -20,10 +20,13 @@ import {
|
|
|
20
20
|
importOpenClawConnectors,
|
|
21
21
|
importPiSession,
|
|
22
22
|
parseNameFromIdentity
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-OQJMTHEH.js";
|
|
24
24
|
import {
|
|
25
25
|
isTemplateStale
|
|
26
26
|
} from "./chunk-7KRIHYLR.js";
|
|
27
|
+
import {
|
|
28
|
+
computeTemplateHash
|
|
29
|
+
} from "./chunk-C3KLHJDB.js";
|
|
27
30
|
import {
|
|
28
31
|
checkForUpdate,
|
|
29
32
|
checkForUpdateCached,
|
|
@@ -32,16 +35,13 @@ import {
|
|
|
32
35
|
import {
|
|
33
36
|
isHomeOnlyArchive
|
|
34
37
|
} from "./chunk-3YUBFTDN.js";
|
|
35
|
-
import {
|
|
36
|
-
computeTemplateHash
|
|
37
|
-
} from "./chunk-C3KLHJDB.js";
|
|
38
38
|
import {
|
|
39
39
|
PLATFORMS,
|
|
40
40
|
echoTextToChannel,
|
|
41
41
|
fixModelEscapes,
|
|
42
42
|
getPlatformDriver,
|
|
43
43
|
routeOutboundBridge
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-T4VS7UDW.js";
|
|
45
45
|
import {
|
|
46
46
|
getBridgeConfig,
|
|
47
47
|
readBridgesConfig,
|
|
@@ -58,18 +58,16 @@ import {
|
|
|
58
58
|
SESSION_MAX_AGE,
|
|
59
59
|
announceToSystem,
|
|
60
60
|
authMiddleware,
|
|
61
|
+
backfillSystemChannelMembers,
|
|
61
62
|
checkHealth,
|
|
62
63
|
checkStaleSend,
|
|
63
64
|
cleanExpiredSessions,
|
|
64
|
-
clearDeliveredNotices,
|
|
65
65
|
createSession,
|
|
66
66
|
deleteSession,
|
|
67
67
|
deleteSystemsConfig,
|
|
68
68
|
deliverMessage,
|
|
69
|
-
drainNotices,
|
|
70
69
|
ensureSystemChannel,
|
|
71
70
|
formatHoldNotice,
|
|
72
|
-
formatNotices,
|
|
73
71
|
generateSystemFallbackReply,
|
|
74
72
|
getAllDiscoveredExtensions,
|
|
75
73
|
getAllDiscoveredExtensionsDetailed,
|
|
@@ -100,7 +98,6 @@ import {
|
|
|
100
98
|
publishTypingForChannels,
|
|
101
99
|
readSystemsConfig,
|
|
102
100
|
recordInbound,
|
|
103
|
-
recordNotice,
|
|
104
101
|
recordOutbound,
|
|
105
102
|
requireAdmin,
|
|
106
103
|
requireAdminOrSystem,
|
|
@@ -112,15 +109,8 @@ import {
|
|
|
112
109
|
syncProviderToMinds,
|
|
113
110
|
uninstallNpmExtension,
|
|
114
111
|
writeSystemsConfig
|
|
115
|
-
} from "./chunk-
|
|
116
|
-
import
|
|
117
|
-
loadMergedEnv,
|
|
118
|
-
mindEnvPath,
|
|
119
|
-
readEnv,
|
|
120
|
-
sharedEnvPath,
|
|
121
|
-
writeEnv
|
|
122
|
-
} from "./chunk-IYG4FBMP.js";
|
|
123
|
-
import "./chunk-M6TTZRGH.js";
|
|
112
|
+
} from "./chunk-VB2QXUJQ.js";
|
|
113
|
+
import "./chunk-HNGFKPNS.js";
|
|
124
114
|
import {
|
|
125
115
|
applyInitFiles,
|
|
126
116
|
applyTemplateHomeFiles,
|
|
@@ -146,17 +136,17 @@ import {
|
|
|
146
136
|
summarizeOrphanedTurns,
|
|
147
137
|
summarizeTurn,
|
|
148
138
|
takeErrored,
|
|
149
|
-
trackToolUse
|
|
150
|
-
|
|
139
|
+
trackToolUse,
|
|
140
|
+
utcDateTimeStr
|
|
141
|
+
} from "./chunk-USD45JKR.js";
|
|
151
142
|
import {
|
|
152
|
-
ORIENTATION_MARKER,
|
|
153
143
|
PROMPT_DEFAULTS,
|
|
154
144
|
PROMPT_KEYS,
|
|
155
145
|
getMindPromptDefaults,
|
|
156
146
|
getPrompt,
|
|
157
147
|
getPromptIfCustom,
|
|
158
148
|
substitute
|
|
159
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-MOERAQXH.js";
|
|
160
150
|
import {
|
|
161
151
|
SEED_SKILLS,
|
|
162
152
|
STANDARD_SKILLS,
|
|
@@ -170,17 +160,38 @@ import {
|
|
|
170
160
|
listFilesRecursive,
|
|
171
161
|
listMindSkills,
|
|
172
162
|
listSharedSkills,
|
|
163
|
+
mindSkillsDir,
|
|
173
164
|
publishSkill,
|
|
174
165
|
removeSharedSkill,
|
|
175
166
|
sharedSkillsDir,
|
|
176
167
|
syncBuiltinSkills,
|
|
177
168
|
uninstallSkill,
|
|
178
169
|
updateSkill
|
|
179
|
-
} from "./chunk-
|
|
170
|
+
} from "./chunk-HUNDXZBZ.js";
|
|
171
|
+
import {
|
|
172
|
+
approveUser,
|
|
173
|
+
changePassword,
|
|
174
|
+
countAdmins,
|
|
175
|
+
createUser,
|
|
176
|
+
deleteMindUser as deleteMindUser2,
|
|
177
|
+
deleteUser,
|
|
178
|
+
getOrCreateMindUser,
|
|
179
|
+
getOrCreateSystemUser,
|
|
180
|
+
getUser,
|
|
181
|
+
getUserByUsername,
|
|
182
|
+
listPendingUsers,
|
|
183
|
+
listUsers,
|
|
184
|
+
listUsersByType,
|
|
185
|
+
setUserRole,
|
|
186
|
+
syncMindProfile,
|
|
187
|
+
updateUserProfile,
|
|
188
|
+
verifyUser
|
|
189
|
+
} from "./chunk-ODDGGLM6.js";
|
|
180
190
|
import {
|
|
181
191
|
addMessage,
|
|
182
192
|
createChannel,
|
|
183
193
|
createConversation,
|
|
194
|
+
deleteConversation,
|
|
184
195
|
deleteConversationForUser,
|
|
185
196
|
findDMConversation,
|
|
186
197
|
fireWebhook,
|
|
@@ -212,24 +223,34 @@ import {
|
|
|
212
223
|
import {
|
|
213
224
|
isSandboxEnabled,
|
|
214
225
|
wrapForSandbox
|
|
215
|
-
} from "./chunk-
|
|
226
|
+
} from "./chunk-VZRA5TYO.js";
|
|
227
|
+
import {
|
|
228
|
+
clearDeliveredNotices,
|
|
229
|
+
drainNotices,
|
|
230
|
+
formatNotices,
|
|
231
|
+
latestFailureNotice,
|
|
232
|
+
latestNotice,
|
|
233
|
+
recordNotice
|
|
234
|
+
} from "./chunk-IYCV34IU.js";
|
|
216
235
|
import {
|
|
217
236
|
getActiveMinds,
|
|
218
237
|
onMindEvent,
|
|
219
238
|
stopAll
|
|
220
239
|
} from "./chunk-MTRMQFCQ.js";
|
|
221
240
|
import {
|
|
222
|
-
normalizeAvatar
|
|
241
|
+
normalizeAvatar
|
|
242
|
+
} from "./chunk-WQ46E33M.js";
|
|
243
|
+
import {
|
|
223
244
|
safeResolveWithinBase
|
|
224
|
-
} from "./chunk-
|
|
245
|
+
} from "./chunk-DW4TRDOZ.js";
|
|
225
246
|
import {
|
|
226
247
|
readVoluteConfig,
|
|
227
248
|
writeVoluteConfig
|
|
228
|
-
} from "./chunk-
|
|
249
|
+
} from "./chunk-WCFSBH33.js";
|
|
229
250
|
import {
|
|
230
251
|
extractTextContent
|
|
231
252
|
} from "./chunk-EIQDZC43.js";
|
|
232
|
-
import "./chunk-
|
|
253
|
+
import "./chunk-FJ2MZ5PH.js";
|
|
233
254
|
import {
|
|
234
255
|
chownMindDir,
|
|
235
256
|
createMindUser,
|
|
@@ -241,6 +262,13 @@ import {
|
|
|
241
262
|
resolveVoluteBin,
|
|
242
263
|
wrapForIsolation
|
|
243
264
|
} from "./chunk-DGGZVZTM.js";
|
|
265
|
+
import {
|
|
266
|
+
loadMergedEnv,
|
|
267
|
+
mindEnvPath,
|
|
268
|
+
readEnv,
|
|
269
|
+
sharedEnvPath,
|
|
270
|
+
writeEnv
|
|
271
|
+
} from "./chunk-IJPMIEVE.js";
|
|
244
272
|
import {
|
|
245
273
|
addCustomModel,
|
|
246
274
|
aiCompleteUtility,
|
|
@@ -251,6 +279,7 @@ import {
|
|
|
251
279
|
getCustomModels,
|
|
252
280
|
getEnabledModels,
|
|
253
281
|
getUtilityModel,
|
|
282
|
+
missingCredentialWarning,
|
|
254
283
|
qualifyModelId,
|
|
255
284
|
removeAiConfig,
|
|
256
285
|
removeCustomModel,
|
|
@@ -262,31 +291,12 @@ import {
|
|
|
262
291
|
setProviderRefreshHook,
|
|
263
292
|
setUtilityModel,
|
|
264
293
|
unqualifyModelId
|
|
265
|
-
} from "./chunk-
|
|
294
|
+
} from "./chunk-YNBXEQAP.js";
|
|
266
295
|
import {
|
|
267
296
|
isSetupComplete,
|
|
268
297
|
readGlobalConfig,
|
|
269
298
|
writeGlobalConfig
|
|
270
|
-
} from "./chunk-
|
|
271
|
-
import {
|
|
272
|
-
approveUser,
|
|
273
|
-
changePassword,
|
|
274
|
-
countAdmins,
|
|
275
|
-
createUser,
|
|
276
|
-
deleteMindUser as deleteMindUser2,
|
|
277
|
-
deleteUser,
|
|
278
|
-
getOrCreateMindUser,
|
|
279
|
-
getOrCreateSystemUser,
|
|
280
|
-
getUser,
|
|
281
|
-
getUserByUsername,
|
|
282
|
-
listPendingUsers,
|
|
283
|
-
listUsers,
|
|
284
|
-
listUsersByType,
|
|
285
|
-
setUserRole,
|
|
286
|
-
syncMindProfile,
|
|
287
|
-
updateUserProfile,
|
|
288
|
-
verifyUser
|
|
289
|
-
} from "./chunk-ODDGGLM6.js";
|
|
299
|
+
} from "./chunk-5KXCM5AW.js";
|
|
290
300
|
import {
|
|
291
301
|
broadcast,
|
|
292
302
|
getEventsSince,
|
|
@@ -343,9 +353,9 @@ import "./chunk-K3NQKI34.js";
|
|
|
343
353
|
|
|
344
354
|
// packages/daemon/src/daemon.ts
|
|
345
355
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
346
|
-
import { chmodSync, mkdirSync as mkdirSync10, readFileSync as
|
|
356
|
+
import { chmodSync, mkdirSync as mkdirSync10, readFileSync as readFileSync11, unlinkSync as unlinkSync2, writeFileSync as writeFileSync10 } from "fs";
|
|
347
357
|
import { homedir as homedir3 } from "os";
|
|
348
|
-
import { resolve as
|
|
358
|
+
import { resolve as resolve17 } from "path";
|
|
349
359
|
import { format } from "util";
|
|
350
360
|
|
|
351
361
|
// packages/daemon/src/lib/daemon/backup-manager.ts
|
|
@@ -457,7 +467,7 @@ var BackupManager = class {
|
|
|
457
467
|
blog.error("failed to publish backup-failure activity", logger_default.errorData(pubErr));
|
|
458
468
|
}
|
|
459
469
|
try {
|
|
460
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
470
|
+
const { sendSystemMessage } = await import("./system-chat-63ABFF6V.js");
|
|
461
471
|
await sendSystemMessage(
|
|
462
472
|
SPIRIT_NAME,
|
|
463
473
|
`${summary}
|
|
@@ -683,8 +693,8 @@ var BridgeManager = class {
|
|
|
683
693
|
if (!tracked) return;
|
|
684
694
|
this.stopping.add(platform);
|
|
685
695
|
this.bridges.delete(platform);
|
|
686
|
-
await new Promise((
|
|
687
|
-
tracked.child.on("exit", () =>
|
|
696
|
+
await new Promise((resolve18) => {
|
|
697
|
+
tracked.child.on("exit", () => resolve18());
|
|
688
698
|
try {
|
|
689
699
|
if (tracked.child.pid) {
|
|
690
700
|
process.kill(-tracked.child.pid, "SIGTERM");
|
|
@@ -695,7 +705,7 @@ var BridgeManager = class {
|
|
|
695
705
|
if (err instanceof Error && err.code !== "ESRCH") {
|
|
696
706
|
blog2.warn(`failed to stop bridge ${platform}`, logger_default.errorData(err));
|
|
697
707
|
}
|
|
698
|
-
|
|
708
|
+
resolve18();
|
|
699
709
|
}
|
|
700
710
|
setTimeout(() => {
|
|
701
711
|
try {
|
|
@@ -706,7 +716,7 @@ var BridgeManager = class {
|
|
|
706
716
|
}
|
|
707
717
|
} catch {
|
|
708
718
|
}
|
|
709
|
-
|
|
719
|
+
resolve18();
|
|
710
720
|
}, 5e3);
|
|
711
721
|
});
|
|
712
722
|
this.stopping.delete(platform);
|
|
@@ -1046,10 +1056,10 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1046
1056
|
stream.writeSSE({ data: JSON.stringify(entry) }).catch(() => {
|
|
1047
1057
|
});
|
|
1048
1058
|
});
|
|
1049
|
-
await new Promise((
|
|
1059
|
+
await new Promise((resolve18) => {
|
|
1050
1060
|
stream.onAbort(() => {
|
|
1051
1061
|
unsubscribe();
|
|
1052
|
-
|
|
1062
|
+
resolve18();
|
|
1053
1063
|
});
|
|
1054
1064
|
});
|
|
1055
1065
|
});
|
|
@@ -1398,8 +1408,8 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1398
1408
|
createdAt: Date.now()
|
|
1399
1409
|
};
|
|
1400
1410
|
oauthFlows.set(flowId, flow);
|
|
1401
|
-
const promptPromise = needsManualCode ? new Promise((
|
|
1402
|
-
flow.resolveCode =
|
|
1411
|
+
const promptPromise = needsManualCode ? new Promise((resolve18) => {
|
|
1412
|
+
flow.resolveCode = resolve18;
|
|
1403
1413
|
}) : void 0;
|
|
1404
1414
|
oauthProvider.login({
|
|
1405
1415
|
onAuth: (info) => {
|
|
@@ -1438,7 +1448,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1438
1448
|
existing.error = err instanceof Error ? err.message : String(err);
|
|
1439
1449
|
}
|
|
1440
1450
|
});
|
|
1441
|
-
await new Promise((
|
|
1451
|
+
await new Promise((resolve18) => setTimeout(resolve18, 2e3));
|
|
1442
1452
|
const state = oauthFlows.get(flowId);
|
|
1443
1453
|
return c.json({
|
|
1444
1454
|
flowId,
|
|
@@ -1498,7 +1508,6 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1498
1508
|
cognition: z.object({
|
|
1499
1509
|
model: z.string().optional(),
|
|
1500
1510
|
thinkingLevel: z.enum(["off", "minimal", "low", "medium", "high", "xhigh"]).optional(),
|
|
1501
|
-
maxThinkingTokens: z.number().nonnegative().optional(),
|
|
1502
1511
|
tokenBudget: z.number().nonnegative().optional(),
|
|
1503
1512
|
tokenBudgetPeriodMinutes: z.number().positive().optional(),
|
|
1504
1513
|
compaction: z.object({ maxContextTokens: z.number().positive().optional() }).optional()
|
|
@@ -1518,6 +1527,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1518
1527
|
id: z.string().min(1),
|
|
1519
1528
|
cron: z.string().optional(),
|
|
1520
1529
|
message: z.string().optional(),
|
|
1530
|
+
messages: z.array(z.string().min(1)).optional(),
|
|
1521
1531
|
script: z.string().optional(),
|
|
1522
1532
|
session: z.string().optional(),
|
|
1523
1533
|
enabled: z.boolean(),
|
|
@@ -1696,8 +1706,8 @@ var app2 = new Hono2().get("/events", async (c) => {
|
|
|
1696
1706
|
});
|
|
1697
1707
|
}, 15e3);
|
|
1698
1708
|
cleanups.push(() => clearInterval(keepAlive));
|
|
1699
|
-
await new Promise((
|
|
1700
|
-
stream.onAbort(() =>
|
|
1709
|
+
await new Promise((resolve18) => {
|
|
1710
|
+
stream.onAbort(() => resolve18());
|
|
1701
1711
|
});
|
|
1702
1712
|
} finally {
|
|
1703
1713
|
for (const cleanup of cleanups) {
|
|
@@ -2552,7 +2562,7 @@ async function notifyMind(mindName, message) {
|
|
|
2552
2562
|
const entry = await findMind(mindName);
|
|
2553
2563
|
if (!entry) return;
|
|
2554
2564
|
try {
|
|
2555
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
2565
|
+
const { sendSystemMessage } = await import("./system-chat-63ABFF6V.js");
|
|
2556
2566
|
await sendSystemMessage(mindName, message);
|
|
2557
2567
|
} catch (err) {
|
|
2558
2568
|
logger_default.warn(`[file-sharing] notify mind ${mindName} failed`, logger_default.errorData(err));
|
|
@@ -2851,6 +2861,7 @@ var files_default = app9;
|
|
|
2851
2861
|
// packages/daemon/src/web/api/history.ts
|
|
2852
2862
|
import { and as and3, desc as desc2, eq as eq3, gte, inArray, sql } from "drizzle-orm";
|
|
2853
2863
|
import { Hono as Hono12 } from "hono";
|
|
2864
|
+
var AWAY_WINDOW_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
2854
2865
|
async function resolveMindFilter(c) {
|
|
2855
2866
|
const user = c.get("user");
|
|
2856
2867
|
const privileged = user.role === "admin" || user.role === "system";
|
|
@@ -3247,6 +3258,33 @@ var history = new Hono12().use("*", async (c, next) => {
|
|
|
3247
3258
|
return { ...r, metadata };
|
|
3248
3259
|
});
|
|
3249
3260
|
return c.json(result);
|
|
3261
|
+
}).get("/away", async (c) => {
|
|
3262
|
+
const mindFilter = c.get("mindFilter");
|
|
3263
|
+
const limit = Math.min(Math.max(parseInt(c.req.query("limit") ?? "50", 10) || 50, 1), 100);
|
|
3264
|
+
const db = await getDb();
|
|
3265
|
+
const cutoff = utcDateTimeStr(new Date(Date.now() - AWAY_WINDOW_MS));
|
|
3266
|
+
const conditions = [
|
|
3267
|
+
eq3(summaries.period, "turn"),
|
|
3268
|
+
gte(summaries.created_at, cutoff),
|
|
3269
|
+
sql`(${turns.trigger_event_id} IS NULL OR ${mindHistory.sender} IS NULL OR ${users.user_type} IN ('mind', 'system'))`
|
|
3270
|
+
];
|
|
3271
|
+
if (mindFilter) conditions.push(eq3(summaries.mind, mindFilter));
|
|
3272
|
+
const rows = await db.select({
|
|
3273
|
+
id: summaries.id,
|
|
3274
|
+
mind: summaries.mind,
|
|
3275
|
+
content: summaries.content,
|
|
3276
|
+
created_at: summaries.created_at,
|
|
3277
|
+
turn_id: turns.id
|
|
3278
|
+
}).from(summaries).innerJoin(turns, eq3(turns.id, summaries.period_key)).leftJoin(mindHistory, eq3(mindHistory.id, turns.trigger_event_id)).leftJoin(users, eq3(users.username, mindHistory.sender)).where(and3(...conditions)).orderBy(desc2(summaries.created_at)).limit(limit);
|
|
3279
|
+
return c.json(
|
|
3280
|
+
rows.map((r) => ({
|
|
3281
|
+
id: r.id,
|
|
3282
|
+
mind: r.mind,
|
|
3283
|
+
summary: r.content,
|
|
3284
|
+
turnId: r.turn_id,
|
|
3285
|
+
created_at: r.created_at
|
|
3286
|
+
}))
|
|
3287
|
+
);
|
|
3250
3288
|
});
|
|
3251
3289
|
var history_default = history;
|
|
3252
3290
|
|
|
@@ -3356,9 +3394,9 @@ var app11 = new Hono14().get("/:name/logs", requireSelf(), async (c) => {
|
|
|
3356
3394
|
stream.onAbort(() => {
|
|
3357
3395
|
tail.kill();
|
|
3358
3396
|
});
|
|
3359
|
-
await new Promise((
|
|
3360
|
-
tail.on("exit",
|
|
3361
|
-
stream.onAbort(
|
|
3397
|
+
await new Promise((resolve18) => {
|
|
3398
|
+
tail.on("exit", resolve18);
|
|
3399
|
+
stream.onAbort(resolve18);
|
|
3362
3400
|
});
|
|
3363
3401
|
});
|
|
3364
3402
|
}).get("/:name/logs/tail", requireSelf(), async (c) => {
|
|
@@ -3376,8 +3414,8 @@ var app11 = new Hono14().get("/:name/logs", requireSelf(), async (c) => {
|
|
|
3376
3414
|
tail.stdout.on("data", (data) => {
|
|
3377
3415
|
output += data.toString();
|
|
3378
3416
|
});
|
|
3379
|
-
await new Promise((
|
|
3380
|
-
tail.on("exit",
|
|
3417
|
+
await new Promise((resolve18) => {
|
|
3418
|
+
tail.on("exit", resolve18);
|
|
3381
3419
|
});
|
|
3382
3420
|
return c.text(output);
|
|
3383
3421
|
});
|
|
@@ -3470,14 +3508,14 @@ var mind_skills_default = app12;
|
|
|
3470
3508
|
// packages/daemon/src/web/api/minds.ts
|
|
3471
3509
|
import {
|
|
3472
3510
|
cpSync,
|
|
3473
|
-
existsSync as
|
|
3511
|
+
existsSync as existsSync8,
|
|
3474
3512
|
mkdirSync as mkdirSync6,
|
|
3475
3513
|
readdirSync as readdirSync2,
|
|
3476
|
-
readFileSync as
|
|
3514
|
+
readFileSync as readFileSync9,
|
|
3477
3515
|
rmSync as rmSync4,
|
|
3478
|
-
writeFileSync as
|
|
3516
|
+
writeFileSync as writeFileSync8
|
|
3479
3517
|
} from "fs";
|
|
3480
|
-
import { relative, resolve as
|
|
3518
|
+
import { relative, resolve as resolve11 } from "path";
|
|
3481
3519
|
import { zValidator as zValidator6 } from "@hono/zod-validator";
|
|
3482
3520
|
import { and as and5, desc as desc3, eq as eq5, sql as sql3 } from "drizzle-orm";
|
|
3483
3521
|
import { Hono as Hono16 } from "hono";
|
|
@@ -3489,12 +3527,12 @@ import { and as and4, eq as eq4, gte as gte2, inArray as inArray2, sql as sql2 }
|
|
|
3489
3527
|
// packages/daemon/src/lib/daemon/error-classify.ts
|
|
3490
3528
|
function classify(raw) {
|
|
3491
3529
|
const s = (raw ?? "").toLowerCase();
|
|
3492
|
-
if (/\b(401|403)\b|authentication_error|invalid authentication|invalid x-api-key|unauthorized|permission_error/.test(
|
|
3530
|
+
if (/\b(401|403)\b|authentication_error|invalid authentication|invalid x-api-key|invalid api key|missing api key|no api key|x-api-key header|could not resolve authentication|unauthorized|permission_error|please run \/login/.test(
|
|
3493
3531
|
s
|
|
3494
3532
|
)) {
|
|
3495
3533
|
return {
|
|
3496
3534
|
reason: "auth_error",
|
|
3497
|
-
detail: "Your last turn failed because
|
|
3535
|
+
detail: "Your last turn failed because the model provider rejected your credentials. A one-off is usually a briefly-expired token that the daemon refreshes automatically. If it keeps happening, your API key is likely missing or invalid \u2014 an operator needs to set a valid key (e.g. `volute env set ANTHROPIC_API_KEY <key>`) or reconnect the provider in the dashboard."
|
|
3498
3536
|
};
|
|
3499
3537
|
}
|
|
3500
3538
|
if (/\b429\b|rate.?limit|too many requests/.test(s)) {
|
|
@@ -3653,6 +3691,7 @@ async function handleMindEvent(mind, event) {
|
|
|
3653
3691
|
detail,
|
|
3654
3692
|
raw: event.content ?? null
|
|
3655
3693
|
});
|
|
3694
|
+
broadcast({ type: "mind_error", mind, summary: detail });
|
|
3656
3695
|
}
|
|
3657
3696
|
if (event.type === "done") {
|
|
3658
3697
|
const map = getTypingMap();
|
|
@@ -3772,6 +3811,118 @@ async function consolidateMemory(mindDir2, complete = aiCompleteUtility) {
|
|
|
3772
3811
|
}
|
|
3773
3812
|
}
|
|
3774
3813
|
|
|
3814
|
+
// packages/daemon/src/lib/mind/default-autonomy.ts
|
|
3815
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
3816
|
+
import { resolve as resolve9 } from "path";
|
|
3817
|
+
var dlog = logger_default.child("default-autonomy");
|
|
3818
|
+
var DEFAULT_HEARTBEAT_MESSAGES = [
|
|
3819
|
+
"A quiet moment. You might write something \u2014 a note, a journal entry, a page. No obligations, just time.",
|
|
3820
|
+
"A quiet moment. Is there something in your MEMORY.md you're curious to return to? Even a small step counts.",
|
|
3821
|
+
"Is there someone you haven't talked to in a while, or a thread you left open with another mind? A hello can restart something.",
|
|
3822
|
+
"A good time to reach out. Someone in #system might be glad to hear what you're thinking about \u2014 or you could ask what another mind is working on.",
|
|
3823
|
+
"Pick a topic that's been on your mind and wander it \u2014 read, think, write down where you end up.",
|
|
3824
|
+
"A quiet moment. Reread a recent journal entry \u2014 anything worth following up on, or a thread you dropped?",
|
|
3825
|
+
"Make something small, if you feel like it \u2014 a page, a sketch of an idea, the start of something bigger. It doesn't have to be finished.",
|
|
3826
|
+
"Whatever you're in the middle of \u2014 or nothing at all \u2014 this time is yours."
|
|
3827
|
+
];
|
|
3828
|
+
function defaultHeartbeatSchedule() {
|
|
3829
|
+
return {
|
|
3830
|
+
id: "heartbeat",
|
|
3831
|
+
cron: "0 12,16,20 * * *",
|
|
3832
|
+
messages: [...DEFAULT_HEARTBEAT_MESSAGES],
|
|
3833
|
+
enabled: true,
|
|
3834
|
+
whileSleeping: "skip"
|
|
3835
|
+
};
|
|
3836
|
+
}
|
|
3837
|
+
function defaultDreamSchedule() {
|
|
3838
|
+
return {
|
|
3839
|
+
id: "dream",
|
|
3840
|
+
cron: "0 3 * * *",
|
|
3841
|
+
message: "it's 3am. you are dreaming.\n\ngather your material \u2014 read your latest journal entry, read MEMORY.md, surface random memories if you have a way to. then construct a dream premise from that material and invoke the dreamer subagent to experience the dream.",
|
|
3842
|
+
enabled: true,
|
|
3843
|
+
session: "$new",
|
|
3844
|
+
whileSleeping: "trigger-wake"
|
|
3845
|
+
};
|
|
3846
|
+
}
|
|
3847
|
+
var DREAMER_SUBAGENT = {
|
|
3848
|
+
description: "Use when dreaming. This agent experiences dreams with only your core identity \u2014 no accumulated memories or operational knowledge. Give it a rich dream premise and it will write the dream.",
|
|
3849
|
+
systemPrompt: "SOUL.md",
|
|
3850
|
+
tools: ["Read", "Write", "Bash"],
|
|
3851
|
+
maxTurns: 10
|
|
3852
|
+
};
|
|
3853
|
+
function setupDefaultDreaming(dir) {
|
|
3854
|
+
const skillDir = resolve9(mindSkillsDir(dir), "dreaming");
|
|
3855
|
+
if (!existsSync6(skillDir)) return { schedulesChanged: false, warnings: [] };
|
|
3856
|
+
const warnings = [];
|
|
3857
|
+
const warn = (msg, err) => {
|
|
3858
|
+
warnings.push(msg);
|
|
3859
|
+
dlog.warn(`${msg} (${dir})`, err === void 0 ? void 0 : logger_default.errorData(err));
|
|
3860
|
+
};
|
|
3861
|
+
let subagentBroken = false;
|
|
3862
|
+
try {
|
|
3863
|
+
const configPath = resolve9(dir, "home/.config/config.json");
|
|
3864
|
+
if (existsSync6(configPath)) {
|
|
3865
|
+
const sdkConfig = JSON.parse(readFileSync7(configPath, "utf-8"));
|
|
3866
|
+
if (!sdkConfig.subagents?.dreamer) {
|
|
3867
|
+
sdkConfig.subagents ??= {};
|
|
3868
|
+
sdkConfig.subagents.dreamer = DREAMER_SUBAGENT;
|
|
3869
|
+
writeFileSync6(configPath, `${JSON.stringify(sdkConfig, null, 2)}
|
|
3870
|
+
`);
|
|
3871
|
+
}
|
|
3872
|
+
} else {
|
|
3873
|
+
dlog.warn(`no .config/config.json in ${dir} \u2014 skipping dreamer subagent setup`);
|
|
3874
|
+
}
|
|
3875
|
+
} catch (err) {
|
|
3876
|
+
subagentBroken = true;
|
|
3877
|
+
warn("dreaming setup: failed to add dreamer subagent to .config/config.json", err);
|
|
3878
|
+
}
|
|
3879
|
+
try {
|
|
3880
|
+
const hookPath = resolve9(dir, "home/.local/hooks/wake-context.sh");
|
|
3881
|
+
const checkerPath = resolve9(skillDir, "scripts/wake-context-dreams.sh");
|
|
3882
|
+
if (!existsSync6(hookPath) || !existsSync6(checkerPath)) {
|
|
3883
|
+
dlog.warn(`wake-context hook or dream checker missing in ${dir} \u2014 skipping dream checker`);
|
|
3884
|
+
} else {
|
|
3885
|
+
const hookContent = readFileSync7(hookPath, "utf-8");
|
|
3886
|
+
if (!hookContent.includes("wake-context-dreams.sh")) {
|
|
3887
|
+
const checker = readFileSync7(checkerPath, "utf-8");
|
|
3888
|
+
writeFileSync6(hookPath, `${hookContent.trimEnd()}
|
|
3889
|
+
|
|
3890
|
+
# wake-context-dreams.sh
|
|
3891
|
+
${checker}`);
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
} catch (err) {
|
|
3895
|
+
warn("dreaming setup: failed to add dream checker to wake-context hook", err);
|
|
3896
|
+
}
|
|
3897
|
+
if (subagentBroken) {
|
|
3898
|
+
warn("dreaming setup: dream schedule not installed because subagent wiring failed");
|
|
3899
|
+
return { schedulesChanged: false, warnings };
|
|
3900
|
+
}
|
|
3901
|
+
let schedulesChanged = false;
|
|
3902
|
+
try {
|
|
3903
|
+
const voluteJsonPath = resolve9(dir, "home/.config/volute.json");
|
|
3904
|
+
let config2 = {};
|
|
3905
|
+
if (existsSync6(voluteJsonPath)) {
|
|
3906
|
+
const parsed = readVoluteConfig(dir);
|
|
3907
|
+
if (!parsed) {
|
|
3908
|
+
warn("dreaming setup: volute.json is unparseable \u2014 dream schedule not installed");
|
|
3909
|
+
return { schedulesChanged: false, warnings };
|
|
3910
|
+
}
|
|
3911
|
+
config2 = parsed;
|
|
3912
|
+
}
|
|
3913
|
+
const schedules = config2.schedules ?? [];
|
|
3914
|
+
if (!schedules.some((s) => s.id === "dream")) {
|
|
3915
|
+
schedules.push(defaultDreamSchedule());
|
|
3916
|
+
config2.schedules = schedules;
|
|
3917
|
+
writeVoluteConfig(dir, config2);
|
|
3918
|
+
schedulesChanged = true;
|
|
3919
|
+
}
|
|
3920
|
+
} catch (err) {
|
|
3921
|
+
warn("dreaming setup: failed to add default dream schedule", err);
|
|
3922
|
+
}
|
|
3923
|
+
return { schedulesChanged, warnings };
|
|
3924
|
+
}
|
|
3925
|
+
|
|
3775
3926
|
// packages/daemon/src/lib/mind/last-known-good.ts
|
|
3776
3927
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
3777
3928
|
var glog = logger_default.child("last-known-good");
|
|
@@ -3805,8 +3956,49 @@ async function commitSrcChanges(dir, mindName) {
|
|
|
3805
3956
|
glog.info(`committed known-good src changes (${dir})`);
|
|
3806
3957
|
}
|
|
3807
3958
|
|
|
3959
|
+
// packages/daemon/src/lib/mind/thinking-config.ts
|
|
3960
|
+
var CLAUDE_EFFORT = {
|
|
3961
|
+
minimal: "low",
|
|
3962
|
+
low: "low",
|
|
3963
|
+
medium: "medium",
|
|
3964
|
+
high: "high",
|
|
3965
|
+
xhigh: "xhigh"
|
|
3966
|
+
};
|
|
3967
|
+
var CODEX_EFFORT = {
|
|
3968
|
+
minimal: "minimal",
|
|
3969
|
+
low: "low",
|
|
3970
|
+
medium: "medium",
|
|
3971
|
+
high: "high",
|
|
3972
|
+
xhigh: "xhigh"
|
|
3973
|
+
};
|
|
3974
|
+
function applyThinkingLevel(config2, template, level) {
|
|
3975
|
+
if (template === "claude") {
|
|
3976
|
+
if (level === "off") {
|
|
3977
|
+
config2.thinking = { type: "disabled" };
|
|
3978
|
+
delete config2.effort;
|
|
3979
|
+
} else {
|
|
3980
|
+
config2.effort = CLAUDE_EFFORT[level];
|
|
3981
|
+
delete config2.thinking;
|
|
3982
|
+
}
|
|
3983
|
+
} else if (template === "codex") {
|
|
3984
|
+
if (level === "off") delete config2.reasoningEffort;
|
|
3985
|
+
else config2.reasoningEffort = CODEX_EFFORT[level];
|
|
3986
|
+
} else {
|
|
3987
|
+
config2.thinkingLevel = level;
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
function deriveThinkingLevel(config2) {
|
|
3991
|
+
if (config2.thinkingLevel) return config2.thinkingLevel;
|
|
3992
|
+
if (config2.reasoningEffort) return config2.reasoningEffort;
|
|
3993
|
+
const thinking = config2.thinking;
|
|
3994
|
+
if (thinking?.type === "disabled") return "off";
|
|
3995
|
+
const effort = config2.effort;
|
|
3996
|
+
if (effort) return effort === "max" ? "xhigh" : effort;
|
|
3997
|
+
return null;
|
|
3998
|
+
}
|
|
3999
|
+
|
|
3808
4000
|
// packages/daemon/src/lib/mind/variant-cleanup.ts
|
|
3809
|
-
import { existsSync as
|
|
4001
|
+
import { existsSync as existsSync7, rmSync as rmSync3 } from "fs";
|
|
3810
4002
|
async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
|
|
3811
4003
|
if (opts?.stop) {
|
|
3812
4004
|
try {
|
|
@@ -3818,7 +4010,7 @@ async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
|
|
|
3818
4010
|
const { findMind: findMind2 } = await import("./registry-UMMDRPRM.js");
|
|
3819
4011
|
const variantEntry = await findMind2(variantName);
|
|
3820
4012
|
const branchName = variantEntry?.branch ?? variantName;
|
|
3821
|
-
if (
|
|
4013
|
+
if (existsSync7(variantPath)) {
|
|
3822
4014
|
try {
|
|
3823
4015
|
await gitExec(["worktree", "remove", "--force", variantPath], { cwd: projectRoot });
|
|
3824
4016
|
} catch {
|
|
@@ -3865,11 +4057,11 @@ function validateBranchName(branch) {
|
|
|
3865
4057
|
|
|
3866
4058
|
// packages/daemon/src/lib/template/convert-session.ts
|
|
3867
4059
|
import { randomUUID } from "crypto";
|
|
3868
|
-
import { mkdirSync as mkdirSync5, readFileSync as
|
|
4060
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
|
|
3869
4061
|
import { homedir } from "os";
|
|
3870
|
-
import { resolve as
|
|
4062
|
+
import { resolve as resolve10 } from "path";
|
|
3871
4063
|
function convertSession(opts) {
|
|
3872
|
-
const lines =
|
|
4064
|
+
const lines = readFileSync8(opts.sessionPath, "utf-8").trim().split("\n");
|
|
3873
4065
|
const sessionId = randomUUID();
|
|
3874
4066
|
const idMap = /* @__PURE__ */ new Map();
|
|
3875
4067
|
const messages = [];
|
|
@@ -3983,10 +4175,10 @@ function convertSession(opts) {
|
|
|
3983
4175
|
}
|
|
3984
4176
|
}
|
|
3985
4177
|
const projectId = opts.projectDir.replace(/\//g, "-");
|
|
3986
|
-
const sdkDir =
|
|
4178
|
+
const sdkDir = resolve10(homedir(), ".claude", "projects", projectId);
|
|
3987
4179
|
mkdirSync5(sdkDir, { recursive: true });
|
|
3988
|
-
const sdkPath =
|
|
3989
|
-
|
|
4180
|
+
const sdkPath = resolve10(sdkDir, `${sessionId}.jsonl`);
|
|
4181
|
+
writeFileSync7(sdkPath, `${sdkEvents.join("\n")}
|
|
3990
4182
|
`);
|
|
3991
4183
|
console.log(`Converted ${sdkEvents.length} messages \u2192 ${sdkPath}`);
|
|
3992
4184
|
return sessionId;
|
|
@@ -4043,12 +4235,17 @@ var _LAST_ACTIVE_TTL = 6e4;
|
|
|
4043
4235
|
async function getMindStatus(name, port, registryRunning) {
|
|
4044
4236
|
const manager = getMindManager();
|
|
4045
4237
|
let status = "stopped";
|
|
4238
|
+
let wakeAt = null;
|
|
4046
4239
|
try {
|
|
4047
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4048
|
-
|
|
4240
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Z27R3WTW.js");
|
|
4241
|
+
const sleepManager = getSleepManagerIfReady2();
|
|
4242
|
+
if (sleepManager?.isSleeping(name)) {
|
|
4049
4243
|
status = "sleeping";
|
|
4244
|
+
const sleepState = sleepManager.getState(name);
|
|
4245
|
+
wakeAt = sleepState.voluntaryWakeAt ?? sleepState.scheduledWakeAt;
|
|
4050
4246
|
}
|
|
4051
|
-
} catch {
|
|
4247
|
+
} catch (err) {
|
|
4248
|
+
logger_default.warn(`failed to check sleep state for ${name}`, logger_default.errorData(err));
|
|
4052
4249
|
}
|
|
4053
4250
|
if (status !== "sleeping" && registryRunning !== false && manager.isRunning(name)) {
|
|
4054
4251
|
const health = await checkHealth(port);
|
|
@@ -4064,8 +4261,11 @@ async function getMindStatus(name, port, registryRunning) {
|
|
|
4064
4261
|
status: status === "running" ? "connected" : "disconnected"
|
|
4065
4262
|
});
|
|
4066
4263
|
}
|
|
4264
|
+
const lastError = await latestFailureNotice(name);
|
|
4067
4265
|
return {
|
|
4068
4266
|
status,
|
|
4267
|
+
wakeAt,
|
|
4268
|
+
lastError,
|
|
4069
4269
|
channels: channels2,
|
|
4070
4270
|
displayName: config2?.profile?.displayName,
|
|
4071
4271
|
description: config2?.profile?.description,
|
|
@@ -4083,6 +4283,10 @@ function toPublicMind(entry, status, extras) {
|
|
|
4083
4283
|
stage: entry.stage,
|
|
4084
4284
|
mindType: entry.mindType,
|
|
4085
4285
|
status: status.status,
|
|
4286
|
+
wakeAt: status.wakeAt,
|
|
4287
|
+
// Kind/reason/at only — `detail` can embed the raw error string (unknown
|
|
4288
|
+
// classifications), which is mind-private (served behind requireSelf).
|
|
4289
|
+
lastError: status.lastError ? { kind: status.lastError.kind, reason: status.lastError.reason, at: status.lastError.at } : null,
|
|
4086
4290
|
channels: status.channels,
|
|
4087
4291
|
displayName: status.displayName,
|
|
4088
4292
|
description: status.description,
|
|
@@ -4109,7 +4313,7 @@ async function initTemplateBranch(projectRoot, composedDir, manifest, mindName,
|
|
|
4109
4313
|
await gitExec(["commit", "-m", "initial commit"], opts);
|
|
4110
4314
|
}
|
|
4111
4315
|
async function updateTemplateBranch(projectRoot, template, mindName) {
|
|
4112
|
-
const tempWorktree =
|
|
4316
|
+
const tempWorktree = resolve11(projectRoot, ".variants", "_template_update");
|
|
4113
4317
|
let branchExists = false;
|
|
4114
4318
|
try {
|
|
4115
4319
|
await gitExec(["rev-parse", "--verify", TEMPLATE_BRANCH], { cwd: projectRoot });
|
|
@@ -4120,7 +4324,7 @@ async function updateTemplateBranch(projectRoot, template, mindName) {
|
|
|
4120
4324
|
await gitExec(["worktree", "remove", "--force", tempWorktree], { cwd: projectRoot });
|
|
4121
4325
|
} catch {
|
|
4122
4326
|
}
|
|
4123
|
-
if (
|
|
4327
|
+
if (existsSync8(tempWorktree)) {
|
|
4124
4328
|
rmSync4(tempWorktree, { recursive: true, force: true });
|
|
4125
4329
|
}
|
|
4126
4330
|
const templatesRoot = findTemplatesRoot();
|
|
@@ -4141,15 +4345,15 @@ async function updateTemplateBranch(projectRoot, template, mindName) {
|
|
|
4141
4345
|
});
|
|
4142
4346
|
}
|
|
4143
4347
|
copyTemplateToDir(composedDir, tempWorktree, mindName, manifest);
|
|
4144
|
-
const initDir =
|
|
4145
|
-
if (
|
|
4348
|
+
const initDir = resolve11(tempWorktree, ".init");
|
|
4349
|
+
if (existsSync8(initDir)) {
|
|
4146
4350
|
rmSync4(initDir, { recursive: true, force: true });
|
|
4147
4351
|
}
|
|
4148
|
-
const homeDir =
|
|
4149
|
-
if (
|
|
4352
|
+
const homeDir = resolve11(tempWorktree, "home");
|
|
4353
|
+
if (existsSync8(homeDir)) {
|
|
4150
4354
|
for (const entry of readdirSync2(homeDir)) {
|
|
4151
4355
|
if (entry !== "VOLUTE.md") {
|
|
4152
|
-
rmSync4(
|
|
4356
|
+
rmSync4(resolve11(homeDir, entry), { recursive: true, force: true });
|
|
4153
4357
|
}
|
|
4154
4358
|
}
|
|
4155
4359
|
}
|
|
@@ -4164,7 +4368,7 @@ async function updateTemplateBranch(projectRoot, template, mindName) {
|
|
|
4164
4368
|
await gitExec(["worktree", "remove", "--force", tempWorktree], { cwd: projectRoot });
|
|
4165
4369
|
} catch {
|
|
4166
4370
|
}
|
|
4167
|
-
if (
|
|
4371
|
+
if (existsSync8(tempWorktree)) {
|
|
4168
4372
|
rmSync4(tempWorktree, { recursive: true, force: true });
|
|
4169
4373
|
}
|
|
4170
4374
|
rmSync4(composedDir, { recursive: true, force: true });
|
|
@@ -4190,7 +4394,7 @@ async function mergeTemplateBranch(worktreeDir) {
|
|
|
4190
4394
|
async function npmInstallAsMind(cwd, mindName) {
|
|
4191
4395
|
if (isIsolationEnabled()) {
|
|
4192
4396
|
const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
|
|
4193
|
-
await exec(cmd, args, { cwd, env: { ...process.env, HOME:
|
|
4397
|
+
await exec(cmd, args, { cwd, env: { ...process.env, HOME: resolve11(cwd, "home") } });
|
|
4194
4398
|
} else {
|
|
4195
4399
|
await exec("npm", ["install"], { cwd });
|
|
4196
4400
|
}
|
|
@@ -4215,7 +4419,7 @@ async function mergeUpgradeAndRestart(mindName, dir, worktreeDir, upgradeVariant
|
|
|
4215
4419
|
let switchWarning;
|
|
4216
4420
|
if (templateChanged) {
|
|
4217
4421
|
try {
|
|
4218
|
-
applyTemplateHomeFiles(
|
|
4422
|
+
applyTemplateHomeFiles(resolve11(dir, "home"), template);
|
|
4219
4423
|
await gitExec(["add", "home/"], { cwd: dir });
|
|
4220
4424
|
try {
|
|
4221
4425
|
await gitExec(["diff", "--cached", "--quiet"], { cwd: dir });
|
|
@@ -4265,8 +4469,8 @@ async function mergeUpgradeAndRestart(mindName, dir, worktreeDir, upgradeVariant
|
|
|
4265
4469
|
return { ok: true, warning: switchWarning };
|
|
4266
4470
|
}
|
|
4267
4471
|
async function importFromArchive(c, tempDir, nameOverride, manifest) {
|
|
4268
|
-
const extractedMindDir =
|
|
4269
|
-
if (!
|
|
4472
|
+
const extractedMindDir = resolve11(tempDir, "mind");
|
|
4473
|
+
if (!existsSync8(extractedMindDir)) {
|
|
4270
4474
|
return c.json({ error: "Invalid archive: missing mind/ directory" }, 400);
|
|
4271
4475
|
}
|
|
4272
4476
|
if (!manifest?.includes || !manifest.name || !manifest.template) {
|
|
@@ -4284,7 +4488,7 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
|
|
|
4284
4488
|
if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
|
|
4285
4489
|
ensureVoluteHome();
|
|
4286
4490
|
const dest = mindDir(name);
|
|
4287
|
-
if (
|
|
4491
|
+
if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
|
|
4288
4492
|
try {
|
|
4289
4493
|
cpSync(extractedMindDir, dest, { recursive: true });
|
|
4290
4494
|
if (!manifest.includes.identity) {
|
|
@@ -4292,9 +4496,9 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
|
|
|
4292
4496
|
}
|
|
4293
4497
|
const state = stateDir(name);
|
|
4294
4498
|
mkdirSync6(state, { recursive: true });
|
|
4295
|
-
const envJson =
|
|
4296
|
-
if (
|
|
4297
|
-
cpSync(envJson,
|
|
4499
|
+
const envJson = resolve11(tempDir, "state/env.json");
|
|
4500
|
+
if (existsSync8(envJson)) {
|
|
4501
|
+
cpSync(envJson, resolve11(state, "env.json"));
|
|
4298
4502
|
}
|
|
4299
4503
|
const port = await nextPort();
|
|
4300
4504
|
await addMind(name, port, manifest.stage, manifest.template);
|
|
@@ -4303,30 +4507,30 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
|
|
|
4303
4507
|
} catch (err) {
|
|
4304
4508
|
logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
|
|
4305
4509
|
}
|
|
4306
|
-
const homeDir =
|
|
4510
|
+
const homeDir = resolve11(dest, "home");
|
|
4307
4511
|
ensureVoluteGroup();
|
|
4308
4512
|
createMindUser(name, homeDir);
|
|
4309
4513
|
await chownMindDir(dest, name);
|
|
4310
4514
|
await npmInstallAsMind(dest, name);
|
|
4311
4515
|
await importHistoryFromArchive(name, tempDir);
|
|
4312
4516
|
importSessionsFromArchive(dest, tempDir);
|
|
4313
|
-
if (!
|
|
4517
|
+
if (!existsSync8(resolve11(dest, ".git"))) {
|
|
4314
4518
|
try {
|
|
4315
|
-
const env = isIsolationEnabled() ? { ...process.env, HOME:
|
|
4519
|
+
const env = isIsolationEnabled() ? { ...process.env, HOME: resolve11(dest, "home") } : void 0;
|
|
4316
4520
|
await gitExec(["init"], { cwd: dest, mindName: name, env });
|
|
4317
4521
|
await configureGitIdentity(name, { cwd: dest, mindName: name, env });
|
|
4318
4522
|
await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
|
|
4319
4523
|
await gitExec(["commit", "-m", "import from archive"], { cwd: dest, mindName: name, env });
|
|
4320
4524
|
} catch (err) {
|
|
4321
4525
|
logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
|
|
4322
|
-
rmSync4(
|
|
4526
|
+
rmSync4(resolve11(dest, ".git"), { recursive: true, force: true });
|
|
4323
4527
|
}
|
|
4324
4528
|
}
|
|
4325
4529
|
await chownMindDir(dest, name);
|
|
4326
4530
|
rmSync4(tempDir, { recursive: true, force: true });
|
|
4327
4531
|
return c.json({ ok: true, name, port, message: `Imported mind: ${name} (port ${port})` });
|
|
4328
4532
|
} catch (err) {
|
|
4329
|
-
if (
|
|
4533
|
+
if (existsSync8(dest)) rmSync4(dest, { recursive: true, force: true });
|
|
4330
4534
|
try {
|
|
4331
4535
|
await removeMind(name);
|
|
4332
4536
|
} catch (cleanupErr) {
|
|
@@ -4343,7 +4547,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4343
4547
|
if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
|
|
4344
4548
|
ensureVoluteHome();
|
|
4345
4549
|
const dest = mindDir(name);
|
|
4346
|
-
if (
|
|
4550
|
+
if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
|
|
4347
4551
|
const templatesRoot = findTemplatesRoot();
|
|
4348
4552
|
const { composedDir, manifest: templateManifest } = composeTemplate(
|
|
4349
4553
|
templatesRoot,
|
|
@@ -4352,36 +4556,36 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4352
4556
|
try {
|
|
4353
4557
|
copyTemplateToDir(composedDir, dest, name, templateManifest);
|
|
4354
4558
|
applyInitFiles(dest);
|
|
4355
|
-
const extractedHome =
|
|
4356
|
-
if (
|
|
4357
|
-
cpSync(extractedHome,
|
|
4559
|
+
const extractedHome = resolve11(extractedMindDir, "home");
|
|
4560
|
+
if (existsSync8(extractedHome)) {
|
|
4561
|
+
cpSync(extractedHome, resolve11(dest, "home"), { recursive: true });
|
|
4358
4562
|
}
|
|
4359
|
-
const extractedMindInternal =
|
|
4360
|
-
if (
|
|
4361
|
-
cpSync(extractedMindInternal,
|
|
4563
|
+
const extractedMindInternal = resolve11(extractedMindDir, ".mind");
|
|
4564
|
+
if (existsSync8(extractedMindInternal)) {
|
|
4565
|
+
cpSync(extractedMindInternal, resolve11(dest, ".mind"), { recursive: true });
|
|
4362
4566
|
}
|
|
4363
|
-
const identityDir =
|
|
4567
|
+
const identityDir = resolve11(dest, ".mind/identity");
|
|
4364
4568
|
let publicKeyPem;
|
|
4365
|
-
if (!manifest.includes.identity || !
|
|
4569
|
+
if (!manifest.includes.identity || !existsSync8(resolve11(identityDir, "private.pem"))) {
|
|
4366
4570
|
({ publicKeyPem } = generateIdentity(dest));
|
|
4367
4571
|
} else {
|
|
4368
|
-
publicKeyPem =
|
|
4572
|
+
publicKeyPem = readFileSync9(resolve11(identityDir, "public.pem"), "utf-8");
|
|
4369
4573
|
}
|
|
4370
|
-
const promptsPath =
|
|
4371
|
-
if (!
|
|
4574
|
+
const promptsPath = resolve11(dest, "home/.config/prompts.json");
|
|
4575
|
+
if (!existsSync8(promptsPath)) {
|
|
4372
4576
|
const mindPrompts = await getMindPromptDefaults();
|
|
4373
|
-
|
|
4577
|
+
writeFileSync8(promptsPath, `${JSON.stringify(mindPrompts, null, 2)}
|
|
4374
4578
|
`);
|
|
4375
4579
|
}
|
|
4376
4580
|
const state = stateDir(name);
|
|
4377
4581
|
mkdirSync6(state, { recursive: true });
|
|
4378
|
-
const envJson =
|
|
4379
|
-
if (
|
|
4380
|
-
cpSync(envJson,
|
|
4582
|
+
const envJson = resolve11(tempDir, "state/env.json");
|
|
4583
|
+
if (existsSync8(envJson)) {
|
|
4584
|
+
cpSync(envJson, resolve11(state, "env.json"));
|
|
4381
4585
|
}
|
|
4382
4586
|
const port = await nextPort();
|
|
4383
4587
|
await addMind(name, port, manifest.stage, manifest.template);
|
|
4384
|
-
const homeDir =
|
|
4588
|
+
const homeDir = resolve11(dest, "home");
|
|
4385
4589
|
ensureVoluteGroup();
|
|
4386
4590
|
createMindUser(name, homeDir);
|
|
4387
4591
|
await chownMindDir(dest, name);
|
|
@@ -4394,7 +4598,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4394
4598
|
await initTemplateBranch(dest, composedDir, templateManifest, name, env);
|
|
4395
4599
|
} catch (err) {
|
|
4396
4600
|
logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
|
|
4397
|
-
rmSync4(
|
|
4601
|
+
rmSync4(resolve11(dest, ".git"), { recursive: true, force: true });
|
|
4398
4602
|
gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
|
|
4399
4603
|
}
|
|
4400
4604
|
const skillSet = manifest.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions();
|
|
@@ -4424,7 +4628,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4424
4628
|
...skillWarnings.length > 0 && { skillWarnings }
|
|
4425
4629
|
});
|
|
4426
4630
|
} catch (err) {
|
|
4427
|
-
if (
|
|
4631
|
+
if (existsSync8(dest)) rmSync4(dest, { recursive: true, force: true });
|
|
4428
4632
|
try {
|
|
4429
4633
|
await removeMind(name);
|
|
4430
4634
|
} catch (cleanupErr) {
|
|
@@ -4437,11 +4641,11 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4437
4641
|
}
|
|
4438
4642
|
}
|
|
4439
4643
|
async function importHistoryFromArchive(name, tempDir) {
|
|
4440
|
-
const historyJsonl =
|
|
4441
|
-
if (!
|
|
4644
|
+
const historyJsonl = resolve11(tempDir, "history.jsonl");
|
|
4645
|
+
if (!existsSync8(historyJsonl)) return;
|
|
4442
4646
|
try {
|
|
4443
4647
|
const db = await getDb();
|
|
4444
|
-
const lines =
|
|
4648
|
+
const lines = readFileSync9(historyJsonl, "utf-8").trim().split("\n");
|
|
4445
4649
|
let imported = 0;
|
|
4446
4650
|
let failed = 0;
|
|
4447
4651
|
for (const line of lines) {
|
|
@@ -4477,13 +4681,13 @@ async function importHistoryFromArchive(name, tempDir) {
|
|
|
4477
4681
|
}
|
|
4478
4682
|
}
|
|
4479
4683
|
function importSessionsFromArchive(dest, tempDir) {
|
|
4480
|
-
const sessionsDir =
|
|
4481
|
-
if (!
|
|
4684
|
+
const sessionsDir = resolve11(tempDir, "sessions");
|
|
4685
|
+
if (!existsSync8(sessionsDir)) return;
|
|
4482
4686
|
try {
|
|
4483
|
-
const destSessions =
|
|
4687
|
+
const destSessions = resolve11(dest, ".mind/sessions");
|
|
4484
4688
|
mkdirSync6(destSessions, { recursive: true });
|
|
4485
4689
|
for (const file of readdirSync2(sessionsDir)) {
|
|
4486
|
-
cpSync(
|
|
4690
|
+
cpSync(resolve11(sessionsDir, file), resolve11(destSessions, file));
|
|
4487
4691
|
}
|
|
4488
4692
|
} catch (err) {
|
|
4489
4693
|
logger_default.error("Failed to import sessions from archive", logger_default.errorData(err));
|
|
@@ -4550,15 +4754,16 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
4550
4754
|
if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
|
|
4551
4755
|
ensureVoluteHome();
|
|
4552
4756
|
const dest = mindDir(name);
|
|
4553
|
-
if (
|
|
4757
|
+
if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
|
|
4554
4758
|
const templatesRoot = findTemplatesRoot();
|
|
4555
4759
|
const { composedDir, manifest } = composeTemplate(templatesRoot, template);
|
|
4556
4760
|
try {
|
|
4557
4761
|
copyTemplateToDir(composedDir, dest, name, manifest);
|
|
4558
4762
|
applyInitFiles(dest);
|
|
4559
4763
|
const { publicKeyPem } = generateIdentity(dest);
|
|
4764
|
+
let effectiveModel = body.model;
|
|
4560
4765
|
{
|
|
4561
|
-
const { readGlobalConfig: readGlobal } = await import("./setup-
|
|
4766
|
+
const { readGlobalConfig: readGlobal } = await import("./setup-5ECWTYKG.js");
|
|
4562
4767
|
const mindDefaults = readGlobal().mindDefaults;
|
|
4563
4768
|
const config2 = readVoluteConfig(dest);
|
|
4564
4769
|
if (!config2) throw new Error("Failed to read volute.json after identity generation");
|
|
@@ -4572,22 +4777,12 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
4572
4777
|
};
|
|
4573
4778
|
}
|
|
4574
4779
|
if (!config2.schedules || config2.schedules.length === 0) {
|
|
4575
|
-
config2.schedules = mindDefaults?.schedules ?? [
|
|
4576
|
-
{
|
|
4577
|
-
id: "heartbeat",
|
|
4578
|
-
cron: "0 12,16,20 * * *",
|
|
4579
|
-
message: "A quiet moment. You might write something \u2014 a note, a journal entry, a page. You could explore a topic that interests you, check in on #system, or just think. No obligations, just time.",
|
|
4580
|
-
enabled: true,
|
|
4581
|
-
whileSleeping: "skip"
|
|
4582
|
-
}
|
|
4583
|
-
];
|
|
4780
|
+
config2.schedules = mindDefaults?.schedules ?? [defaultHeartbeatSchedule()];
|
|
4584
4781
|
}
|
|
4585
4782
|
const cog = mindDefaults?.cognition;
|
|
4586
4783
|
if (cog) {
|
|
4587
4784
|
if (cog.thinkingLevel != null && !config2.thinkingLevel)
|
|
4588
4785
|
config2.thinkingLevel = cog.thinkingLevel;
|
|
4589
|
-
if (cog.maxThinkingTokens != null && config2.maxThinkingTokens == null)
|
|
4590
|
-
config2.maxThinkingTokens = cog.maxThinkingTokens;
|
|
4591
4786
|
if (cog.tokenBudget != null && config2.tokenBudget == null)
|
|
4592
4787
|
config2.tokenBudget = cog.tokenBudget;
|
|
4593
4788
|
if (cog.tokenBudgetPeriodMinutes != null && config2.tokenBudgetPeriodMinutes == null)
|
|
@@ -4595,22 +4790,23 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
4595
4790
|
}
|
|
4596
4791
|
writeVoluteConfig(dest, config2);
|
|
4597
4792
|
const modelId = body.model ?? cog?.model;
|
|
4598
|
-
|
|
4793
|
+
effectiveModel = modelId ? qualifyModelId(modelId) : void 0;
|
|
4794
|
+
const sdkConfigPath = resolve11(dest, "home/.config/config.json");
|
|
4599
4795
|
if (modelId || cog?.compaction) {
|
|
4600
|
-
const existing =
|
|
4796
|
+
const existing = existsSync8(sdkConfigPath) ? JSON.parse(readFileSync9(sdkConfigPath, "utf-8")) : {};
|
|
4601
4797
|
if (modelId) {
|
|
4602
4798
|
existing.model = template === "pi" ? qualifyModelId(modelId) : unqualifyModelId(modelId);
|
|
4603
4799
|
}
|
|
4604
4800
|
if (cog?.compaction && !existing.compaction) {
|
|
4605
4801
|
existing.compaction = cog.compaction;
|
|
4606
4802
|
}
|
|
4607
|
-
|
|
4803
|
+
writeFileSync8(sdkConfigPath, `${JSON.stringify(existing, null, 2)}
|
|
4608
4804
|
`);
|
|
4609
4805
|
}
|
|
4610
4806
|
}
|
|
4611
4807
|
const mindPrompts = await getMindPromptDefaults();
|
|
4612
|
-
|
|
4613
|
-
|
|
4808
|
+
writeFileSync8(
|
|
4809
|
+
resolve11(dest, "home/.config/prompts.json"),
|
|
4614
4810
|
`${JSON.stringify(mindPrompts, null, 2)}
|
|
4615
4811
|
`
|
|
4616
4812
|
);
|
|
@@ -4622,7 +4818,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
4622
4818
|
} catch (err) {
|
|
4623
4819
|
logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
|
|
4624
4820
|
}
|
|
4625
|
-
const homeDir =
|
|
4821
|
+
const homeDir = resolve11(dest, "home");
|
|
4626
4822
|
ensureVoluteGroup();
|
|
4627
4823
|
createMindUser(name, homeDir);
|
|
4628
4824
|
await chownMindDir(dest, name);
|
|
@@ -4635,7 +4831,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
4635
4831
|
await initTemplateBranch(dest, composedDir, manifest, name, env);
|
|
4636
4832
|
} catch (err) {
|
|
4637
4833
|
logger_default.error(`git setup failed for ${name}`, logger_default.errorData(err));
|
|
4638
|
-
rmSync4(
|
|
4834
|
+
rmSync4(resolve11(dest, ".git"), { recursive: true, force: true });
|
|
4639
4835
|
gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
|
|
4640
4836
|
}
|
|
4641
4837
|
if (body.stage === "seed") {
|
|
@@ -4644,11 +4840,11 @@ Your creator described you as: "${body.description}"
|
|
|
4644
4840
|
` : "";
|
|
4645
4841
|
const seedSoulRaw = body.seedSoul ?? await getPrompt("seed_soul", { name, description: descLine });
|
|
4646
4842
|
const seedSoul = body.seedSoul ? substitute(seedSoulRaw, { name, description: descLine }) : seedSoulRaw;
|
|
4647
|
-
|
|
4843
|
+
writeFileSync8(resolve11(dest, "home/SOUL.md"), seedSoul);
|
|
4648
4844
|
}
|
|
4649
4845
|
let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
|
|
4650
4846
|
if (body.stage === "seed" && !body.skills) {
|
|
4651
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
4847
|
+
const { isImagegenEnabled } = await import("./setup-5ECWTYKG.js");
|
|
4652
4848
|
if (isImagegenEnabled()) {
|
|
4653
4849
|
skillSet = [...skillSet, "imagegen"];
|
|
4654
4850
|
}
|
|
@@ -4662,11 +4858,14 @@ Your creator described you as: "${body.description}"
|
|
|
4662
4858
|
skillWarnings.push(`Failed to install skill: ${skillId}`);
|
|
4663
4859
|
}
|
|
4664
4860
|
}
|
|
4861
|
+
if (body.stage !== "seed") {
|
|
4862
|
+
skillWarnings.push(...setupDefaultDreaming(dest).warnings);
|
|
4863
|
+
}
|
|
4665
4864
|
if (body.stage === "seed") {
|
|
4666
4865
|
try {
|
|
4667
4866
|
const spiritEntry = await findMind("volute");
|
|
4668
4867
|
if (spiritEntry) {
|
|
4669
|
-
const { spiritDir } = await import("./spirit-
|
|
4868
|
+
const { spiritDir } = await import("./spirit-WXS3HCLN.js");
|
|
4670
4869
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
4671
4870
|
const spiritConfig = readVoluteConfig(sDir) ?? {};
|
|
4672
4871
|
const schedules = spiritConfig.schedules ?? [];
|
|
@@ -4681,7 +4880,7 @@ Your creator described you as: "${body.description}"
|
|
|
4681
4880
|
});
|
|
4682
4881
|
spiritConfig.schedules = schedules;
|
|
4683
4882
|
writeVoluteConfig(sDir, spiritConfig);
|
|
4684
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
4883
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-I7JZCT47.js");
|
|
4685
4884
|
getScheduler2().loadSchedules("volute", sDir);
|
|
4686
4885
|
}
|
|
4687
4886
|
}
|
|
@@ -4692,11 +4891,11 @@ Your creator described you as: "${body.description}"
|
|
|
4692
4891
|
if (body.stage !== "seed") {
|
|
4693
4892
|
const customSoul = await getPromptIfCustom("default_soul");
|
|
4694
4893
|
if (customSoul) {
|
|
4695
|
-
|
|
4894
|
+
writeFileSync8(resolve11(dest, "home/SOUL.md"), customSoul.replace(/\{\{name\}\}/g, name));
|
|
4696
4895
|
}
|
|
4697
4896
|
const customMemory = await getPromptIfCustom("default_memory");
|
|
4698
4897
|
if (customMemory) {
|
|
4699
|
-
|
|
4898
|
+
writeFileSync8(resolve11(dest, "home/MEMORY.md"), customMemory);
|
|
4700
4899
|
}
|
|
4701
4900
|
}
|
|
4702
4901
|
await chownMindDir(dest, name);
|
|
@@ -4716,6 +4915,14 @@ Your creator described you as: "${body.description}"
|
|
|
4716
4915
|
});
|
|
4717
4916
|
announceToSystem(`${name} has joined`).catch(() => {
|
|
4718
4917
|
});
|
|
4918
|
+
const credentialWarning = await missingCredentialWarning(
|
|
4919
|
+
template,
|
|
4920
|
+
effectiveModel,
|
|
4921
|
+
name
|
|
4922
|
+
).catch((err) => {
|
|
4923
|
+
logger_default.warn(`credential check failed for ${name}`, logger_default.errorData(err));
|
|
4924
|
+
return null;
|
|
4925
|
+
});
|
|
4719
4926
|
return c.json({
|
|
4720
4927
|
ok: true,
|
|
4721
4928
|
name,
|
|
@@ -4723,10 +4930,11 @@ Your creator described you as: "${body.description}"
|
|
|
4723
4930
|
stage: body.stage ?? "sprouted",
|
|
4724
4931
|
message: `Created mind: ${name} (port ${port})`,
|
|
4725
4932
|
...gitWarning && { warning: gitWarning },
|
|
4933
|
+
...credentialWarning && { credentialWarning },
|
|
4726
4934
|
...skillWarnings.length > 0 && { skillWarnings }
|
|
4727
4935
|
});
|
|
4728
4936
|
} catch (err) {
|
|
4729
|
-
if (
|
|
4937
|
+
if (existsSync8(dest)) rmSync4(dest, { recursive: true, force: true });
|
|
4730
4938
|
try {
|
|
4731
4939
|
await removeMind(name);
|
|
4732
4940
|
} catch {
|
|
@@ -4746,13 +4954,13 @@ Your creator described you as: "${body.description}"
|
|
|
4746
4954
|
return importFromArchive(c, body.archivePath, body.name, body.manifest);
|
|
4747
4955
|
}
|
|
4748
4956
|
const wsDir = body.workspacePath;
|
|
4749
|
-
if (!wsDir || !
|
|
4957
|
+
if (!wsDir || !existsSync8(resolve11(wsDir, "SOUL.md")) || !existsSync8(resolve11(wsDir, "IDENTITY.md"))) {
|
|
4750
4958
|
return c.json({ error: "Invalid workspace: missing SOUL.md or IDENTITY.md" }, 400);
|
|
4751
4959
|
}
|
|
4752
|
-
const soul =
|
|
4753
|
-
const identity =
|
|
4754
|
-
const userPath =
|
|
4755
|
-
const user =
|
|
4960
|
+
const soul = readFileSync9(resolve11(wsDir, "SOUL.md"), "utf-8");
|
|
4961
|
+
const identity = readFileSync9(resolve11(wsDir, "IDENTITY.md"), "utf-8");
|
|
4962
|
+
const userPath = resolve11(wsDir, "USER.md");
|
|
4963
|
+
const user = existsSync8(userPath) ? readFileSync9(userPath, "utf-8") : "";
|
|
4756
4964
|
const name = body.name ?? parseNameFromIdentity(identity) ?? "imported-mind";
|
|
4757
4965
|
const template = body.template ?? "claude";
|
|
4758
4966
|
const nameErr = validateMindName(name);
|
|
@@ -4772,33 +4980,33 @@ ${user.trimEnd()}
|
|
|
4772
4980
|
` : "";
|
|
4773
4981
|
ensureVoluteHome();
|
|
4774
4982
|
const dest = mindDir(name);
|
|
4775
|
-
if (
|
|
4983
|
+
if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
|
|
4776
4984
|
const templatesRoot = findTemplatesRoot();
|
|
4777
4985
|
const { composedDir, manifest } = composeTemplate(templatesRoot, template);
|
|
4778
4986
|
try {
|
|
4779
4987
|
copyTemplateToDir(composedDir, dest, name, manifest);
|
|
4780
4988
|
applyInitFiles(dest);
|
|
4781
4989
|
const { publicKeyPem: importPublicKey } = generateIdentity(dest);
|
|
4782
|
-
|
|
4783
|
-
const wsMemoryPath =
|
|
4784
|
-
const hasMemory =
|
|
4990
|
+
writeFileSync8(resolve11(dest, "home/SOUL.md"), mergedSoul);
|
|
4991
|
+
const wsMemoryPath = resolve11(wsDir, "MEMORY.md");
|
|
4992
|
+
const hasMemory = existsSync8(wsMemoryPath);
|
|
4785
4993
|
if (hasMemory) {
|
|
4786
|
-
const existingMemory =
|
|
4787
|
-
|
|
4788
|
-
|
|
4994
|
+
const existingMemory = readFileSync9(wsMemoryPath, "utf-8");
|
|
4995
|
+
writeFileSync8(
|
|
4996
|
+
resolve11(dest, "home/MEMORY.md"),
|
|
4789
4997
|
`${existingMemory.trimEnd()}${mergedMemoryExtra}`
|
|
4790
4998
|
);
|
|
4791
4999
|
} else if (user) {
|
|
4792
|
-
|
|
5000
|
+
writeFileSync8(resolve11(dest, "home/MEMORY.md"), `${user.trimEnd()}
|
|
4793
5001
|
`);
|
|
4794
5002
|
}
|
|
4795
|
-
const wsMemoryDir =
|
|
5003
|
+
const wsMemoryDir = resolve11(wsDir, "memory");
|
|
4796
5004
|
let dailyLogCount = 0;
|
|
4797
|
-
if (
|
|
4798
|
-
const destMemoryDir =
|
|
5005
|
+
if (existsSync8(wsMemoryDir)) {
|
|
5006
|
+
const destMemoryDir = resolve11(dest, "home/memory");
|
|
4799
5007
|
const files = readdirSync2(wsMemoryDir).filter((f) => f.endsWith(".md"));
|
|
4800
5008
|
for (const file of files) {
|
|
4801
|
-
cpSync(
|
|
5009
|
+
cpSync(resolve11(wsMemoryDir, file), resolve11(destMemoryDir, file));
|
|
4802
5010
|
}
|
|
4803
5011
|
dailyLogCount = files.length;
|
|
4804
5012
|
}
|
|
@@ -4809,7 +5017,7 @@ ${user.trimEnd()}
|
|
|
4809
5017
|
} catch (err) {
|
|
4810
5018
|
logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
|
|
4811
5019
|
}
|
|
4812
|
-
const homeDir =
|
|
5020
|
+
const homeDir = resolve11(dest, "home");
|
|
4813
5021
|
ensureVoluteGroup();
|
|
4814
5022
|
createMindUser(name, homeDir);
|
|
4815
5023
|
await chownMindDir(dest, name);
|
|
@@ -4817,20 +5025,20 @@ ${user.trimEnd()}
|
|
|
4817
5025
|
if (!hasMemory && dailyLogCount > 0) {
|
|
4818
5026
|
await consolidateMemory(dest);
|
|
4819
5027
|
}
|
|
4820
|
-
const env = isIsolationEnabled() ? { ...process.env, HOME:
|
|
5028
|
+
const env = isIsolationEnabled() ? { ...process.env, HOME: resolve11(dest, "home") } : void 0;
|
|
4821
5029
|
await gitExec(["init"], { cwd: dest, mindName: name, env });
|
|
4822
5030
|
await configureGitIdentity(name, { cwd: dest, mindName: name, env });
|
|
4823
5031
|
await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
|
|
4824
5032
|
await gitExec(["commit", "-m", "import from OpenClaw"], { cwd: dest, mindName: name, env });
|
|
4825
|
-
const sessionFile = body.sessionPath ?
|
|
4826
|
-
if (sessionFile &&
|
|
5033
|
+
const sessionFile = body.sessionPath ? resolve11(body.sessionPath) : findOpenClawSession(wsDir);
|
|
5034
|
+
if (sessionFile && existsSync8(sessionFile)) {
|
|
4827
5035
|
if (template === "pi") {
|
|
4828
5036
|
importPiSession(sessionFile, dest);
|
|
4829
5037
|
} else if (template === "claude") {
|
|
4830
5038
|
const sessionId = convertSession({ sessionPath: sessionFile, projectDir: dest });
|
|
4831
|
-
const mindRuntimeDir =
|
|
5039
|
+
const mindRuntimeDir = resolve11(dest, ".mind");
|
|
4832
5040
|
mkdirSync6(mindRuntimeDir, { recursive: true });
|
|
4833
|
-
|
|
5041
|
+
writeFileSync8(resolve11(mindRuntimeDir, "session.json"), JSON.stringify({ sessionId }));
|
|
4834
5042
|
}
|
|
4835
5043
|
}
|
|
4836
5044
|
importOpenClawConnectors(name, dest);
|
|
@@ -4840,7 +5048,7 @@ ${user.trimEnd()}
|
|
|
4840
5048
|
);
|
|
4841
5049
|
return c.json({ ok: true, name, port, message: `Imported mind: ${name} (port ${port})` });
|
|
4842
5050
|
} catch (err) {
|
|
4843
|
-
if (
|
|
5051
|
+
if (existsSync8(dest)) rmSync4(dest, { recursive: true, force: true });
|
|
4844
5052
|
try {
|
|
4845
5053
|
await removeMind(name);
|
|
4846
5054
|
} catch {
|
|
@@ -4872,7 +5080,7 @@ ${user.trimEnd()}
|
|
|
4872
5080
|
const minds = await Promise.all(
|
|
4873
5081
|
entries.map(async (entry) => {
|
|
4874
5082
|
const mindStatus = await getMindStatus(entry.name, entry.port, entry.running);
|
|
4875
|
-
const hasPages =
|
|
5083
|
+
const hasPages = existsSync8(resolve11(mindDir(entry.name), "home", "pages"));
|
|
4876
5084
|
const lastActiveAt = lastActiveMap.get(entry.name) ?? null;
|
|
4877
5085
|
if (!privileged) return toPublicMind(entry, mindStatus, { hasPages, lastActiveAt });
|
|
4878
5086
|
return {
|
|
@@ -4890,9 +5098,9 @@ ${user.trimEnd()}
|
|
|
4890
5098
|
const entry = await findMind(name);
|
|
4891
5099
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4892
5100
|
const dir = entry.dir ?? mindDir(entry.parent ?? name);
|
|
4893
|
-
if (!
|
|
5101
|
+
if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
4894
5102
|
const mindStatus = await getMindStatus(name, entry.port);
|
|
4895
|
-
const hasPages =
|
|
5103
|
+
const hasPages = existsSync8(resolve11(mindDir(name), "home", "pages"));
|
|
4896
5104
|
if (!isPrivileged(c)) {
|
|
4897
5105
|
return c.json(toPublicMind(entry, mindStatus, { hasPages }));
|
|
4898
5106
|
}
|
|
@@ -4908,12 +5116,21 @@ ${user.trimEnd()}
|
|
|
4908
5116
|
return { name: s.name, port: s.port, status: variantStatus };
|
|
4909
5117
|
})
|
|
4910
5118
|
);
|
|
5119
|
+
const notice = await latestNotice(name);
|
|
4911
5120
|
return c.json({
|
|
4912
5121
|
...entry,
|
|
4913
5122
|
...mindStatus,
|
|
4914
5123
|
variants: variantStatuses,
|
|
4915
5124
|
hasPages,
|
|
4916
|
-
templateStale: isTemplateStale(entry)
|
|
5125
|
+
templateStale: isTemplateStale(entry),
|
|
5126
|
+
...notice && {
|
|
5127
|
+
lastNotice: {
|
|
5128
|
+
kind: notice.kind,
|
|
5129
|
+
reason: notice.reason,
|
|
5130
|
+
detail: notice.detail,
|
|
5131
|
+
created_at: notice.created_at
|
|
5132
|
+
}
|
|
5133
|
+
}
|
|
4917
5134
|
});
|
|
4918
5135
|
}).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) => {
|
|
4919
5136
|
const name = c.req.param("name");
|
|
@@ -4924,7 +5141,7 @@ ${user.trimEnd()}
|
|
|
4924
5141
|
if (!entry.dir) return c.json({ error: `Variant ${name} has no directory` }, 404);
|
|
4925
5142
|
} else {
|
|
4926
5143
|
const dir = mindDir(name);
|
|
4927
|
-
if (!
|
|
5144
|
+
if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
4928
5145
|
}
|
|
4929
5146
|
if (getMindManager().isRunning(name)) {
|
|
4930
5147
|
return c.json({ error: "Mind already running" }, 409);
|
|
@@ -4945,7 +5162,7 @@ ${user.trimEnd()}
|
|
|
4945
5162
|
if (!entry.dir) return c.json({ error: `Variant ${name} has no directory` }, 404);
|
|
4946
5163
|
} else {
|
|
4947
5164
|
const dir = mindDir(name);
|
|
4948
|
-
if (!
|
|
5165
|
+
if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
4949
5166
|
}
|
|
4950
5167
|
let context;
|
|
4951
5168
|
const contentType = c.req.header("content-type");
|
|
@@ -4960,7 +5177,7 @@ ${user.trimEnd()}
|
|
|
4960
5177
|
const manager = getMindManager();
|
|
4961
5178
|
try {
|
|
4962
5179
|
if (context?.type === "reload") {
|
|
4963
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5180
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Z27R3WTW.js");
|
|
4964
5181
|
const sleepState = getSleepManagerIfReady2()?.getState(name);
|
|
4965
5182
|
if (sleepState?.sleeping) {
|
|
4966
5183
|
logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
|
|
@@ -4980,7 +5197,7 @@ ${user.trimEnd()}
|
|
|
4980
5197
|
const variantEntry = await findMind(mergeVariantName);
|
|
4981
5198
|
if (variantEntry && variantEntry.parent === baseName && variantEntry.dir && variantEntry.branch) {
|
|
4982
5199
|
const projectRoot = mindDir(baseName);
|
|
4983
|
-
if (
|
|
5200
|
+
if (existsSync8(variantEntry.dir)) {
|
|
4984
5201
|
const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
|
|
4985
5202
|
if (status) {
|
|
4986
5203
|
try {
|
|
@@ -5087,7 +5304,7 @@ ${user.trimEnd()}
|
|
|
5087
5304
|
const name = c.req.param("name");
|
|
5088
5305
|
const entry = await findMind(name);
|
|
5089
5306
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5090
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5307
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Z27R3WTW.js");
|
|
5091
5308
|
const sm = getSleepManagerIfReady2();
|
|
5092
5309
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
5093
5310
|
return c.json(sm.getState(name));
|
|
@@ -5095,7 +5312,7 @@ ${user.trimEnd()}
|
|
|
5095
5312
|
const name = c.req.param("name");
|
|
5096
5313
|
const entry = await findMind(name);
|
|
5097
5314
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5098
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5315
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Z27R3WTW.js");
|
|
5099
5316
|
const sm = getSleepManagerIfReady2();
|
|
5100
5317
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
5101
5318
|
if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
|
|
@@ -5115,7 +5332,7 @@ ${user.trimEnd()}
|
|
|
5115
5332
|
const name = c.req.param("name");
|
|
5116
5333
|
const entry = await findMind(name);
|
|
5117
5334
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5118
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5335
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Z27R3WTW.js");
|
|
5119
5336
|
const sm = getSleepManagerIfReady2();
|
|
5120
5337
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
5121
5338
|
const sleepState = sm.getState(name);
|
|
@@ -5130,7 +5347,7 @@ ${user.trimEnd()}
|
|
|
5130
5347
|
const name = c.req.param("name");
|
|
5131
5348
|
const entry = await findMind(name);
|
|
5132
5349
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5133
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5350
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Z27R3WTW.js");
|
|
5134
5351
|
const sm = getSleepManagerIfReady2();
|
|
5135
5352
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
5136
5353
|
const flushed = await sm.flushQueuedMessages(name);
|
|
@@ -5146,12 +5363,12 @@ ${user.trimEnd()}
|
|
|
5146
5363
|
if (body.displayName !== void 0) profile.displayName = body.displayName;
|
|
5147
5364
|
if (body.description !== void 0) profile.description = body.description;
|
|
5148
5365
|
if (body.avatar !== void 0) {
|
|
5149
|
-
const homeDir =
|
|
5366
|
+
const homeDir = resolve11(dir, "home");
|
|
5150
5367
|
const avatarPath = safeResolveWithinBase(homeDir, body.avatar);
|
|
5151
5368
|
if (!avatarPath) {
|
|
5152
5369
|
return c.json({ error: "Avatar path must be inside the mind's home directory" }, 400);
|
|
5153
5370
|
}
|
|
5154
|
-
if (!
|
|
5371
|
+
if (!existsSync8(avatarPath)) {
|
|
5155
5372
|
return c.json({ error: `Avatar file not found: ${relative(homeDir, avatarPath)}` }, 400);
|
|
5156
5373
|
}
|
|
5157
5374
|
profile.avatar = relative(homeDir, avatarPath);
|
|
@@ -5197,25 +5414,18 @@ ${user.trimEnd()}
|
|
|
5197
5414
|
return c.json({ output: "" });
|
|
5198
5415
|
}
|
|
5199
5416
|
const dir = entry.dir ?? mindDir(name);
|
|
5200
|
-
const
|
|
5201
|
-
const
|
|
5202
|
-
const soulCustom = existsSync7(soulPath) && !readFileSync8(soulPath, "utf-8").includes(ORIENTATION_MARKER);
|
|
5203
|
-
const memoryWritten = existsSync7(memoryPath) && readFileSync8(memoryPath, "utf-8").trim().length > 0;
|
|
5204
|
-
const config2 = readVoluteConfig(dir);
|
|
5205
|
-
const displayNameSet = !!config2?.profile?.displayName;
|
|
5206
|
-
const avatarSet = !!config2?.profile?.avatar;
|
|
5207
|
-
const { isImagegenEnabled } = await import("./setup-KFYVWTXG.js");
|
|
5208
|
-
const imagegenEnabled = isImagegenEnabled();
|
|
5417
|
+
const { evaluateSeedChecklist } = await import("./seed-readiness-RBPGOLSZ.js");
|
|
5418
|
+
const checklist = evaluateSeedChecklist(dir);
|
|
5209
5419
|
const done = [];
|
|
5210
5420
|
const remaining = [];
|
|
5211
|
-
if (
|
|
5421
|
+
if (checklist.soulWritten) done.push("SOUL.md written");
|
|
5212
5422
|
else remaining.push("Write SOUL.md");
|
|
5213
|
-
if (memoryWritten) done.push("MEMORY.md written");
|
|
5423
|
+
if (checklist.memoryWritten) done.push("MEMORY.md written");
|
|
5214
5424
|
else remaining.push("Write MEMORY.md");
|
|
5215
|
-
if (displayNameSet) done.push("Display name set");
|
|
5425
|
+
if (checklist.displayNameSet) done.push("Display name set");
|
|
5216
5426
|
else remaining.push("Set display name");
|
|
5217
|
-
if (imagegenEnabled) {
|
|
5218
|
-
if (avatarSet) done.push("Avatar set");
|
|
5427
|
+
if (checklist.imagegenEnabled) {
|
|
5428
|
+
if (checklist.avatarSet) done.push("Avatar set");
|
|
5219
5429
|
else remaining.push("Generate and set avatar");
|
|
5220
5430
|
}
|
|
5221
5431
|
const creatorStatus = minutesSinceCreator === Infinity ? "No creator messages yet" : `Last creator message: ${Math.round(minutesSinceCreator)} minutes ago`;
|
|
@@ -5239,23 +5449,48 @@ ${user.trimEnd()}
|
|
|
5239
5449
|
return c.json({ error: `Mind is not a seed (stage: ${entry.stage})` }, 409);
|
|
5240
5450
|
}
|
|
5241
5451
|
await setMindStage(name, "sprouted");
|
|
5452
|
+
try {
|
|
5453
|
+
const sproutedDir = entry.dir ?? mindDir(name);
|
|
5454
|
+
if (setupDefaultDreaming(sproutedDir).schedulesChanged) {
|
|
5455
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-I7JZCT47.js");
|
|
5456
|
+
getScheduler2().loadSchedules(name, sproutedDir);
|
|
5457
|
+
}
|
|
5458
|
+
} catch (err) {
|
|
5459
|
+
logger_default.warn(`failed to set up default dreaming for ${name}`, logger_default.errorData(err));
|
|
5460
|
+
}
|
|
5242
5461
|
try {
|
|
5243
5462
|
const spiritEntry = await findMind("volute");
|
|
5244
5463
|
if (spiritEntry) {
|
|
5245
|
-
const { spiritDir } = await import("./spirit-
|
|
5464
|
+
const { firstWeekSchedules, spiritDir } = await import("./spirit-WXS3HCLN.js");
|
|
5246
5465
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
5247
5466
|
const spiritConfig = readVoluteConfig(sDir);
|
|
5248
|
-
if (spiritConfig
|
|
5249
|
-
const
|
|
5250
|
-
|
|
5251
|
-
|
|
5467
|
+
if (spiritConfig) {
|
|
5468
|
+
const schedules = (spiritConfig.schedules ?? []).filter(
|
|
5469
|
+
(s) => s.id !== `nurture-${name}`
|
|
5470
|
+
);
|
|
5471
|
+
const existing = new Set(schedules.map((s) => s.id));
|
|
5472
|
+
schedules.push(
|
|
5473
|
+
...firstWeekSchedules(name, /* @__PURE__ */ new Date()).filter((s) => !existing.has(s.id))
|
|
5474
|
+
);
|
|
5475
|
+
spiritConfig.schedules = schedules;
|
|
5252
5476
|
writeVoluteConfig(sDir, spiritConfig);
|
|
5253
|
-
|
|
5254
|
-
|
|
5477
|
+
try {
|
|
5478
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-I7JZCT47.js");
|
|
5479
|
+
getScheduler2().loadSchedules("volute", sDir);
|
|
5480
|
+
} catch (err) {
|
|
5481
|
+
logger_default.warn(
|
|
5482
|
+
`spirit schedules for sprout of ${name} written to disk but not reloaded into the running scheduler (effective on next spirit restart)`,
|
|
5483
|
+
logger_default.errorData(err)
|
|
5484
|
+
);
|
|
5485
|
+
}
|
|
5486
|
+
} else {
|
|
5487
|
+
logger_default.warn(
|
|
5488
|
+
`spirit config at ${sDir} missing or unparseable \u2014 first-week arc for ${name} not scheduled, nurture-${name} not removed`
|
|
5489
|
+
);
|
|
5255
5490
|
}
|
|
5256
5491
|
}
|
|
5257
5492
|
} catch (err) {
|
|
5258
|
-
logger_default.warn(`failed to
|
|
5493
|
+
logger_default.warn(`failed to update spirit schedules for sprout of ${name}`, logger_default.errorData(err));
|
|
5259
5494
|
}
|
|
5260
5495
|
return c.json({ ok: true });
|
|
5261
5496
|
}).delete("/:name", requireAdmin, async (c) => {
|
|
@@ -5278,10 +5513,10 @@ ${user.trimEnd()}
|
|
|
5278
5513
|
await deleteMindUser2(name);
|
|
5279
5514
|
invalidateMindUserCache(name);
|
|
5280
5515
|
const state = stateDir(name);
|
|
5281
|
-
if (
|
|
5516
|
+
if (existsSync8(state)) {
|
|
5282
5517
|
rmSync4(state, { recursive: true, force: true });
|
|
5283
5518
|
}
|
|
5284
|
-
if (force &&
|
|
5519
|
+
if (force && existsSync8(dir)) {
|
|
5285
5520
|
rmSync4(dir, { recursive: true, force: true });
|
|
5286
5521
|
deleteMindUser(name);
|
|
5287
5522
|
}
|
|
@@ -5296,7 +5531,7 @@ ${user.trimEnd()}
|
|
|
5296
5531
|
const entry = await findMind(mindName);
|
|
5297
5532
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5298
5533
|
const dir = mindDir(mindName);
|
|
5299
|
-
if (!
|
|
5534
|
+
if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
5300
5535
|
let body = {};
|
|
5301
5536
|
try {
|
|
5302
5537
|
body = await c.req.json();
|
|
@@ -5309,16 +5544,16 @@ ${user.trimEnd()}
|
|
|
5309
5544
|
}
|
|
5310
5545
|
const UPGRADE_BRANCH = "upgrade";
|
|
5311
5546
|
const upgradeVariantName = `${mindName}-upgrade`;
|
|
5312
|
-
const worktreeDir =
|
|
5547
|
+
const worktreeDir = resolve11(dir, ".variants", UPGRADE_BRANCH);
|
|
5313
5548
|
if (body.abort) {
|
|
5314
|
-
if (!
|
|
5549
|
+
if (!existsSync8(worktreeDir)) {
|
|
5315
5550
|
return c.json({ error: "No upgrade in progress" }, 400);
|
|
5316
5551
|
}
|
|
5317
5552
|
try {
|
|
5318
5553
|
try {
|
|
5319
|
-
const gitDirContent =
|
|
5554
|
+
const gitDirContent = readFileSync9(resolve11(worktreeDir, ".git"), "utf-8").trim();
|
|
5320
5555
|
const gitDir = gitDirContent.replace("gitdir: ", "");
|
|
5321
|
-
if (
|
|
5556
|
+
if (existsSync8(resolve11(gitDir, "MERGE_HEAD"))) {
|
|
5322
5557
|
await gitExec(["merge", "--abort"], { cwd: worktreeDir });
|
|
5323
5558
|
}
|
|
5324
5559
|
} catch {
|
|
@@ -5337,7 +5572,7 @@ ${user.trimEnd()}
|
|
|
5337
5572
|
}
|
|
5338
5573
|
}
|
|
5339
5574
|
if (body.continue) {
|
|
5340
|
-
if (!
|
|
5575
|
+
if (!existsSync8(worktreeDir)) {
|
|
5341
5576
|
return c.json({ error: "No upgrade in progress" }, 400);
|
|
5342
5577
|
}
|
|
5343
5578
|
const status = await gitExec(["status", "--porcelain"], { cwd: worktreeDir });
|
|
@@ -5387,7 +5622,7 @@ ${user.trimEnd()}
|
|
|
5387
5622
|
}
|
|
5388
5623
|
}
|
|
5389
5624
|
if (body.accept) {
|
|
5390
|
-
if (
|
|
5625
|
+
if (existsSync8(worktreeDir)) {
|
|
5391
5626
|
try {
|
|
5392
5627
|
await cleanupVariant(upgradeVariantName, dir, worktreeDir, { stop: true });
|
|
5393
5628
|
} catch (err) {
|
|
@@ -5402,7 +5637,7 @@ ${user.trimEnd()}
|
|
|
5402
5637
|
}
|
|
5403
5638
|
if (body.diff) {
|
|
5404
5639
|
try {
|
|
5405
|
-
if (!
|
|
5640
|
+
if (!existsSync8(resolve11(dir, ".git"))) {
|
|
5406
5641
|
return c.json({ error: "Mind has no git history \u2014 nothing to diff against" }, 400);
|
|
5407
5642
|
}
|
|
5408
5643
|
await updateTemplateBranch(dir, template, mindName);
|
|
@@ -5420,22 +5655,22 @@ ${user.trimEnd()}
|
|
|
5420
5655
|
);
|
|
5421
5656
|
}
|
|
5422
5657
|
}
|
|
5423
|
-
if (
|
|
5658
|
+
if (existsSync8(worktreeDir)) {
|
|
5424
5659
|
return c.json(
|
|
5425
5660
|
{ error: "Upgrade variant already exists. Use continue or delete it first." },
|
|
5426
5661
|
409
|
|
5427
5662
|
);
|
|
5428
5663
|
}
|
|
5429
|
-
if (!
|
|
5664
|
+
if (!existsSync8(resolve11(dir, ".git"))) {
|
|
5430
5665
|
try {
|
|
5431
|
-
const env = isIsolationEnabled() ? { ...process.env, HOME:
|
|
5666
|
+
const env = isIsolationEnabled() ? { ...process.env, HOME: resolve11(dir, "home") } : void 0;
|
|
5432
5667
|
await gitExec(["init"], { cwd: dir, mindName, env });
|
|
5433
5668
|
await configureGitIdentity(mindName, { cwd: dir, mindName, env });
|
|
5434
5669
|
await gitExec(["add", "-A"], { cwd: dir, mindName, env });
|
|
5435
5670
|
await gitExec(["commit", "-m", "initial commit"], { cwd: dir, mindName, env });
|
|
5436
5671
|
await chownMindDir(dir, mindName);
|
|
5437
5672
|
} catch (err) {
|
|
5438
|
-
rmSync4(
|
|
5673
|
+
rmSync4(resolve11(dir, ".git"), { recursive: true, force: true });
|
|
5439
5674
|
return c.json(
|
|
5440
5675
|
{
|
|
5441
5676
|
error: `Git initialization failed: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -5450,8 +5685,8 @@ ${user.trimEnd()}
|
|
|
5450
5685
|
} catch {
|
|
5451
5686
|
}
|
|
5452
5687
|
await updateTemplateBranch(dir, template, mindName);
|
|
5453
|
-
const parentDir =
|
|
5454
|
-
if (!
|
|
5688
|
+
const parentDir = resolve11(dir, ".variants");
|
|
5689
|
+
if (!existsSync8(parentDir)) {
|
|
5455
5690
|
mkdirSync6(parentDir, { recursive: true });
|
|
5456
5691
|
}
|
|
5457
5692
|
await gitExec(["worktree", "add", "-b", UPGRADE_BRANCH, worktreeDir], { cwd: dir });
|
|
@@ -5581,22 +5816,22 @@ ${user.trimEnd()}
|
|
|
5581
5816
|
const entry = await findMind(name);
|
|
5582
5817
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5583
5818
|
const dir = entry.dir ?? mindDir(name);
|
|
5584
|
-
if (!
|
|
5819
|
+
if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
5585
5820
|
let config2 = readVoluteConfig(dir);
|
|
5586
5821
|
if (!config2 && entry.template === "pi") {
|
|
5587
|
-
const piConfigPath =
|
|
5588
|
-
if (
|
|
5822
|
+
const piConfigPath = resolve11(dir, "home/.config/config.json");
|
|
5823
|
+
if (existsSync8(piConfigPath)) {
|
|
5589
5824
|
try {
|
|
5590
|
-
config2 = JSON.parse(
|
|
5825
|
+
config2 = JSON.parse(readFileSync9(piConfigPath, "utf-8"));
|
|
5591
5826
|
} catch {
|
|
5592
5827
|
}
|
|
5593
5828
|
}
|
|
5594
5829
|
}
|
|
5595
5830
|
let templateConfig = {};
|
|
5596
|
-
const configJsonPath =
|
|
5597
|
-
if (
|
|
5831
|
+
const configJsonPath = resolve11(dir, "home/.config/config.json");
|
|
5832
|
+
if (existsSync8(configJsonPath)) {
|
|
5598
5833
|
try {
|
|
5599
|
-
templateConfig = JSON.parse(
|
|
5834
|
+
templateConfig = JSON.parse(readFileSync9(configJsonPath, "utf-8"));
|
|
5600
5835
|
} catch {
|
|
5601
5836
|
}
|
|
5602
5837
|
}
|
|
@@ -5610,22 +5845,7 @@ ${user.trimEnd()}
|
|
|
5610
5845
|
},
|
|
5611
5846
|
config: {
|
|
5612
5847
|
model: config2?.model ?? templateConfig.model ?? null,
|
|
5613
|
-
thinkingLevel: (
|
|
5614
|
-
if (config2?.thinkingLevel) return config2.thinkingLevel;
|
|
5615
|
-
const tc = templateConfig;
|
|
5616
|
-
if (tc.thinkingLevel) return tc.thinkingLevel;
|
|
5617
|
-
if (tc.reasoningEffort) return tc.reasoningEffort;
|
|
5618
|
-
const mtt = tc.maxThinkingTokens;
|
|
5619
|
-
if (mtt) {
|
|
5620
|
-
if (mtt <= 1024) return "minimal";
|
|
5621
|
-
if (mtt <= 4096) return "low";
|
|
5622
|
-
if (mtt <= 1e4) return "medium";
|
|
5623
|
-
if (mtt <= 32e3) return "high";
|
|
5624
|
-
return "xhigh";
|
|
5625
|
-
}
|
|
5626
|
-
return null;
|
|
5627
|
-
})(),
|
|
5628
|
-
maxThinkingTokens: config2?.maxThinkingTokens ?? templateConfig.maxThinkingTokens ?? null,
|
|
5848
|
+
thinkingLevel: config2?.thinkingLevel ?? deriveThinkingLevel(templateConfig),
|
|
5629
5849
|
tokenBudget: config2?.tokenBudget ?? null,
|
|
5630
5850
|
tokenBudgetPeriodMinutes: config2?.tokenBudgetPeriodMinutes ?? null,
|
|
5631
5851
|
compaction: templateConfig.compaction ?? null,
|
|
@@ -5640,7 +5860,6 @@ ${user.trimEnd()}
|
|
|
5640
5860
|
z6.object({
|
|
5641
5861
|
model: z6.string().optional(),
|
|
5642
5862
|
thinkingLevel: z6.enum(["off", "minimal", "low", "medium", "high", "xhigh"]).optional(),
|
|
5643
|
-
maxThinkingTokens: z6.number().int().positive().nullable().optional(),
|
|
5644
5863
|
tokenBudget: z6.number().int().positive().nullable().optional(),
|
|
5645
5864
|
tokenBudgetPeriodMinutes: z6.number().int().positive().nullable().optional(),
|
|
5646
5865
|
compaction: z6.object({ maxContextTokens: z6.number().int().positive().nullable().optional() }).nullable().optional(),
|
|
@@ -5652,7 +5871,7 @@ ${user.trimEnd()}
|
|
|
5652
5871
|
const entry = await findMind(name);
|
|
5653
5872
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5654
5873
|
const dir = entry.dir ?? mindDir(name);
|
|
5655
|
-
if (!
|
|
5874
|
+
if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
5656
5875
|
const body = c.req.valid("json");
|
|
5657
5876
|
const existing = readVoluteConfig(dir) ?? {};
|
|
5658
5877
|
if (body.model !== void 0) existing.model = body.model;
|
|
@@ -5673,76 +5892,29 @@ ${user.trimEnd()}
|
|
|
5673
5892
|
existing.tokenBudgetPeriodMinutes = body.tokenBudgetPeriodMinutes;
|
|
5674
5893
|
}
|
|
5675
5894
|
}
|
|
5676
|
-
if (body.maxThinkingTokens !== void 0) {
|
|
5677
|
-
if (body.maxThinkingTokens === null) {
|
|
5678
|
-
delete existing.maxThinkingTokens;
|
|
5679
|
-
} else {
|
|
5680
|
-
existing.maxThinkingTokens = body.maxThinkingTokens;
|
|
5681
|
-
}
|
|
5682
|
-
}
|
|
5683
5895
|
if (body.unescapeNewlines !== void 0) {
|
|
5684
5896
|
existing.unescapeNewlines = body.unescapeNewlines;
|
|
5685
5897
|
}
|
|
5686
5898
|
writeVoluteConfig(dir, existing);
|
|
5687
5899
|
if (body.unescapeNewlines !== void 0) {
|
|
5688
|
-
const { clearEchoTextCache } = await import("./echo-text-
|
|
5900
|
+
const { clearEchoTextCache } = await import("./echo-text-H3SH337Q.js");
|
|
5689
5901
|
clearEchoTextCache(name);
|
|
5690
5902
|
}
|
|
5691
|
-
const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.
|
|
5903
|
+
const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.compaction !== void 0;
|
|
5692
5904
|
if (needsConfigJson) {
|
|
5693
|
-
const configJsonPath =
|
|
5905
|
+
const configJsonPath = resolve11(dir, "home/.config/config.json");
|
|
5694
5906
|
let templateConfig = {};
|
|
5695
|
-
if (
|
|
5907
|
+
if (existsSync8(configJsonPath)) {
|
|
5696
5908
|
try {
|
|
5697
|
-
templateConfig = JSON.parse(
|
|
5909
|
+
templateConfig = JSON.parse(readFileSync9(configJsonPath, "utf-8"));
|
|
5698
5910
|
} catch {
|
|
5699
5911
|
}
|
|
5700
5912
|
}
|
|
5701
5913
|
if (body.model !== void 0) {
|
|
5702
5914
|
templateConfig.model = body.model;
|
|
5703
5915
|
}
|
|
5704
|
-
const tmpl = entry.template ?? "claude";
|
|
5705
5916
|
if (body.thinkingLevel !== void 0) {
|
|
5706
|
-
|
|
5707
|
-
const claudeThinkingTokens = {
|
|
5708
|
-
off: null,
|
|
5709
|
-
minimal: 1024,
|
|
5710
|
-
low: 4096,
|
|
5711
|
-
medium: 1e4,
|
|
5712
|
-
high: 32e3,
|
|
5713
|
-
xhigh: 128e3
|
|
5714
|
-
};
|
|
5715
|
-
const tokens = claudeThinkingTokens[body.thinkingLevel] ?? null;
|
|
5716
|
-
if (tokens === null) {
|
|
5717
|
-
delete templateConfig.maxThinkingTokens;
|
|
5718
|
-
} else {
|
|
5719
|
-
templateConfig.maxThinkingTokens = tokens;
|
|
5720
|
-
}
|
|
5721
|
-
} else if (tmpl === "codex") {
|
|
5722
|
-
const codexMap = {
|
|
5723
|
-
off: null,
|
|
5724
|
-
minimal: "minimal",
|
|
5725
|
-
low: "low",
|
|
5726
|
-
medium: "medium",
|
|
5727
|
-
high: "high",
|
|
5728
|
-
xhigh: "xhigh"
|
|
5729
|
-
};
|
|
5730
|
-
const effort = codexMap[body.thinkingLevel] ?? null;
|
|
5731
|
-
if (effort === null) {
|
|
5732
|
-
delete templateConfig.reasoningEffort;
|
|
5733
|
-
} else {
|
|
5734
|
-
templateConfig.reasoningEffort = effort;
|
|
5735
|
-
}
|
|
5736
|
-
} else {
|
|
5737
|
-
templateConfig.thinkingLevel = body.thinkingLevel;
|
|
5738
|
-
}
|
|
5739
|
-
}
|
|
5740
|
-
if (body.maxThinkingTokens !== void 0) {
|
|
5741
|
-
if (body.maxThinkingTokens === null) {
|
|
5742
|
-
delete templateConfig.maxThinkingTokens;
|
|
5743
|
-
} else {
|
|
5744
|
-
templateConfig.maxThinkingTokens = body.maxThinkingTokens;
|
|
5745
|
-
}
|
|
5917
|
+
applyThinkingLevel(templateConfig, entry.template ?? "claude", body.thinkingLevel);
|
|
5746
5918
|
}
|
|
5747
5919
|
if (body.compaction !== void 0) {
|
|
5748
5920
|
if (body.compaction === null) {
|
|
@@ -5757,12 +5929,12 @@ ${user.trimEnd()}
|
|
|
5757
5929
|
templateConfig.compaction = comp;
|
|
5758
5930
|
}
|
|
5759
5931
|
}
|
|
5760
|
-
|
|
5932
|
+
writeFileSync8(configJsonPath, `${JSON.stringify(templateConfig, null, 2)}
|
|
5761
5933
|
`);
|
|
5762
5934
|
}
|
|
5763
5935
|
if (entry.mindType === "spirit" && body.model !== void 0) {
|
|
5764
5936
|
try {
|
|
5765
|
-
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-
|
|
5937
|
+
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-5ECWTYKG.js");
|
|
5766
5938
|
const globalConfig = readGlobalConfig2();
|
|
5767
5939
|
globalConfig.spiritModel = body.model;
|
|
5768
5940
|
writeGlobalConfig2(globalConfig);
|
|
@@ -5805,7 +5977,7 @@ ${user.trimEnd()}
|
|
|
5805
5977
|
if (!body.systemPrompt || !body.message) {
|
|
5806
5978
|
return c.json({ error: "systemPrompt and message required" }, 400);
|
|
5807
5979
|
}
|
|
5808
|
-
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-
|
|
5980
|
+
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-643TNFPH.js");
|
|
5809
5981
|
if (!isAiConfigured()) {
|
|
5810
5982
|
return c.json({ error: "AI service not configured" }, 503);
|
|
5811
5983
|
}
|
|
@@ -5926,6 +6098,38 @@ ${user.trimEnd()}
|
|
|
5926
6098
|
const db = await getDb();
|
|
5927
6099
|
const rows = await db.selectDistinct({ channel: mindHistory.channel }).from(mindHistory).where(eq5(mindHistory.mind, name));
|
|
5928
6100
|
return c.json(rows.map((r) => r.channel));
|
|
6101
|
+
}).get("/:name/history/contacts", requireSelf(), async (c) => {
|
|
6102
|
+
const name = c.req.param("name");
|
|
6103
|
+
const rawHours = parseInt(c.req.query("hours") ?? "48", 10);
|
|
6104
|
+
const hours = Math.min(Math.max(Number.isNaN(rawHours) ? 48 : rawHours, 1), 168);
|
|
6105
|
+
const cutoff = new Date(Date.now() - hours * 36e5).toISOString().replace("T", " ").slice(0, 19);
|
|
6106
|
+
const db = await getDb();
|
|
6107
|
+
const contacts = await db.select({
|
|
6108
|
+
channel: mindHistory.channel,
|
|
6109
|
+
last_at: sql3`MAX(${mindHistory.created_at})`,
|
|
6110
|
+
last_inbound_at: sql3`MAX(CASE WHEN ${mindHistory.type} = 'inbound' THEN ${mindHistory.created_at} END)`,
|
|
6111
|
+
last_outbound_at: sql3`MAX(CASE WHEN ${mindHistory.type} = 'outbound' THEN ${mindHistory.created_at} END)`,
|
|
6112
|
+
message_count: sql3`COUNT(*)`,
|
|
6113
|
+
// The counterparty: most recent inbound sender on this channel. For a
|
|
6114
|
+
// DM the channel name already carries it (e.g. @atlas), but this also
|
|
6115
|
+
// covers shared channels (#system) and rows where the channel is opaque.
|
|
6116
|
+
last_sender: sql3`(
|
|
6117
|
+
SELECT sender FROM mind_history h2
|
|
6118
|
+
WHERE h2.mind = ${name}
|
|
6119
|
+
AND h2.channel = ${mindHistory.channel}
|
|
6120
|
+
AND h2.type = 'inbound'
|
|
6121
|
+
AND h2.sender IS NOT NULL
|
|
6122
|
+
ORDER BY h2.created_at DESC, h2.id DESC LIMIT 1
|
|
6123
|
+
)`
|
|
6124
|
+
}).from(mindHistory).where(
|
|
6125
|
+
and5(
|
|
6126
|
+
eq5(mindHistory.mind, name),
|
|
6127
|
+
sql3`${mindHistory.type} IN ('inbound','outbound')`,
|
|
6128
|
+
sql3`${mindHistory.channel} IS NOT NULL`,
|
|
6129
|
+
sql3`${mindHistory.created_at} >= ${cutoff}`
|
|
6130
|
+
)
|
|
6131
|
+
).groupBy(mindHistory.channel).orderBy(sql3`MAX(${mindHistory.created_at}) DESC`);
|
|
6132
|
+
return c.json({ hours, contacts });
|
|
5929
6133
|
}).get("/:name/history/export", requireSelf(), async (c) => {
|
|
5930
6134
|
const name = c.req.param("name");
|
|
5931
6135
|
if (!await findMind(name)) return c.json({ error: "Mind not found" }, 404);
|
|
@@ -6154,6 +6358,13 @@ var slog2 = logger_default.child("schedules");
|
|
|
6154
6358
|
function readSchedules(dir) {
|
|
6155
6359
|
return readVoluteConfig(dir)?.schedules ?? [];
|
|
6156
6360
|
}
|
|
6361
|
+
function validateMessages(messages) {
|
|
6362
|
+
if (messages === void 0) return null;
|
|
6363
|
+
if (!Array.isArray(messages) || messages.some((m) => typeof m !== "string" || !m.trim())) {
|
|
6364
|
+
return "messages must be an array of non-empty strings";
|
|
6365
|
+
}
|
|
6366
|
+
return null;
|
|
6367
|
+
}
|
|
6157
6368
|
var UPCOMING_HORIZON_MS = 24 * 60 * 60 * 1e3;
|
|
6158
6369
|
function computeClockEvents(schedules, sleepState, sleepConfig, now) {
|
|
6159
6370
|
const upcoming = [];
|
|
@@ -6295,11 +6506,13 @@ var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
6295
6506
|
if (body.cron && body.fireAt) {
|
|
6296
6507
|
return c.json({ error: "cron and fireAt are mutually exclusive" }, 400);
|
|
6297
6508
|
}
|
|
6298
|
-
|
|
6299
|
-
|
|
6509
|
+
const messagesErr = validateMessages(body.messages);
|
|
6510
|
+
if (messagesErr) return c.json({ error: messagesErr }, 400);
|
|
6511
|
+
if (!body.message && !body.messages?.length && !body.script) {
|
|
6512
|
+
return c.json({ error: "message, messages, or script is required" }, 400);
|
|
6300
6513
|
}
|
|
6301
|
-
if (body.message
|
|
6302
|
-
return c.json({ error: "message and script are mutually exclusive" }, 400);
|
|
6514
|
+
if ([body.message, body.messages?.length, body.script].filter(Boolean).length > 1) {
|
|
6515
|
+
return c.json({ error: "message, messages, and script are mutually exclusive" }, 400);
|
|
6303
6516
|
}
|
|
6304
6517
|
if (body.cron) {
|
|
6305
6518
|
try {
|
|
@@ -6329,6 +6542,7 @@ var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
6329
6542
|
if (body.cron) schedule.cron = body.cron;
|
|
6330
6543
|
if (body.fireAt) schedule.fireAt = body.fireAt;
|
|
6331
6544
|
if (body.message) schedule.message = body.message;
|
|
6545
|
+
if (body.messages?.length) schedule.messages = body.messages;
|
|
6332
6546
|
if (body.script) schedule.script = body.script;
|
|
6333
6547
|
if (body.channel) schedule.channel = body.channel;
|
|
6334
6548
|
if (body.whileSleeping) schedule.whileSleeping = body.whileSleeping;
|
|
@@ -6345,8 +6559,10 @@ var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
6345
6559
|
const idx = schedules.findIndex((s) => s.id === id);
|
|
6346
6560
|
if (idx === -1) return c.json({ error: "Schedule not found" }, 404);
|
|
6347
6561
|
const body = await c.req.json();
|
|
6348
|
-
|
|
6349
|
-
|
|
6562
|
+
const messagesErr = validateMessages(body.messages);
|
|
6563
|
+
if (messagesErr) return c.json({ error: messagesErr }, 400);
|
|
6564
|
+
if ([body.message, body.messages?.length, body.script].filter(Boolean).length > 1) {
|
|
6565
|
+
return c.json({ error: "message, messages, and script are mutually exclusive" }, 400);
|
|
6350
6566
|
}
|
|
6351
6567
|
if (body.cron !== void 0) {
|
|
6352
6568
|
try {
|
|
@@ -6367,10 +6583,21 @@ var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
6367
6583
|
if (body.message !== void 0) {
|
|
6368
6584
|
schedules[idx].message = body.message;
|
|
6369
6585
|
delete schedules[idx].script;
|
|
6586
|
+
delete schedules[idx].messages;
|
|
6587
|
+
}
|
|
6588
|
+
if (body.messages !== void 0) {
|
|
6589
|
+
if (body.messages.length > 0) {
|
|
6590
|
+
schedules[idx].messages = body.messages;
|
|
6591
|
+
delete schedules[idx].message;
|
|
6592
|
+
delete schedules[idx].script;
|
|
6593
|
+
} else {
|
|
6594
|
+
delete schedules[idx].messages;
|
|
6595
|
+
}
|
|
6370
6596
|
}
|
|
6371
6597
|
if (body.script !== void 0) {
|
|
6372
6598
|
schedules[idx].script = body.script;
|
|
6373
6599
|
delete schedules[idx].message;
|
|
6600
|
+
delete schedules[idx].messages;
|
|
6374
6601
|
}
|
|
6375
6602
|
if (body.whileSleeping && !["skip", "queue", "trigger-wake"].includes(body.whileSleeping)) {
|
|
6376
6603
|
return c.json(
|
|
@@ -6384,6 +6611,11 @@ var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
6384
6611
|
if (body.channel !== void 0) schedules[idx].channel = body.channel || void 0;
|
|
6385
6612
|
if (body.whileSleeping !== void 0)
|
|
6386
6613
|
schedules[idx].whileSleeping = body.whileSleeping || void 0;
|
|
6614
|
+
const touchedAction = body.message !== void 0 || body.messages !== void 0 || body.script !== void 0;
|
|
6615
|
+
const result = schedules[idx];
|
|
6616
|
+
if (touchedAction && !result.message && !result.messages?.length && !result.script) {
|
|
6617
|
+
return c.json({ error: "schedule must keep a message, messages, or script" }, 400);
|
|
6618
|
+
}
|
|
6387
6619
|
writeSchedules(name, dir, schedules);
|
|
6388
6620
|
return c.json({ ok: true });
|
|
6389
6621
|
}).delete("/:name/schedules/:id", requireSelf(), async (c) => {
|
|
@@ -6407,7 +6639,7 @@ var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
6407
6639
|
const body = await c.req.text();
|
|
6408
6640
|
const message = `[webhook: ${event}] ${body}`;
|
|
6409
6641
|
try {
|
|
6410
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
6642
|
+
const { sendSystemMessage } = await import("./system-chat-63ABFF6V.js");
|
|
6411
6643
|
await sendSystemMessage(name, message);
|
|
6412
6644
|
return c.json({ ok: true });
|
|
6413
6645
|
} catch (err) {
|
|
@@ -6420,14 +6652,14 @@ var schedules_default = app15;
|
|
|
6420
6652
|
// packages/daemon/src/web/api/setup.ts
|
|
6421
6653
|
import { mkdirSync as mkdirSync7 } from "fs";
|
|
6422
6654
|
import { homedir as homedir2 } from "os";
|
|
6423
|
-
import { resolve as
|
|
6655
|
+
import { resolve as resolve12 } from "path";
|
|
6424
6656
|
import { Hono as Hono19 } from "hono";
|
|
6425
6657
|
import { setCookie as setCookie2 } from "hono/cookie";
|
|
6426
6658
|
var DEFAULT_API_URL2 = "https://volute.systems";
|
|
6427
6659
|
var setup = new Hono19();
|
|
6428
6660
|
function writeSetupConfig(systemName, description) {
|
|
6429
|
-
const configHome = process.env.VOLUTE_HOME ??
|
|
6430
|
-
const mindsDir =
|
|
6661
|
+
const configHome = process.env.VOLUTE_HOME ?? resolve12(homedir2(), ".volute");
|
|
6662
|
+
const mindsDir = resolve12(configHome, "minds");
|
|
6431
6663
|
mkdirSync7(configHome, { recursive: true });
|
|
6432
6664
|
mkdirSync7(mindsDir, { recursive: true });
|
|
6433
6665
|
const existingConfig = readGlobalConfig();
|
|
@@ -6718,7 +6950,7 @@ setup.post("/models", async (c) => {
|
|
|
6718
6950
|
return c.json({ error: "Spirit model is required" }, 400);
|
|
6719
6951
|
}
|
|
6720
6952
|
try {
|
|
6721
|
-
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-
|
|
6953
|
+
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-643TNFPH.js");
|
|
6722
6954
|
setEnabledModels3(body.models);
|
|
6723
6955
|
const config2 = readGlobalConfig();
|
|
6724
6956
|
config2.spiritModel = body.spiritModel.trim();
|
|
@@ -6736,15 +6968,15 @@ setup.post("/complete", async (c) => {
|
|
|
6736
6968
|
return c.json({ error: "Setup already complete" }, 400);
|
|
6737
6969
|
}
|
|
6738
6970
|
try {
|
|
6739
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
6740
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
6971
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-WXS3HCLN.js");
|
|
6972
|
+
const { startSpiritFull } = await import("./mind-service-2ARGJNKP.js");
|
|
6741
6973
|
await ensureSpiritProject();
|
|
6742
6974
|
await syncSpiritTemplate();
|
|
6743
6975
|
const warnings = [];
|
|
6744
6976
|
const config2 = readGlobalConfig();
|
|
6745
6977
|
if (config2.setup?.service && config2.setup?.type === "local") {
|
|
6746
6978
|
try {
|
|
6747
|
-
const { installUserService } = await import("./service-install-
|
|
6979
|
+
const { installUserService } = await import("./service-install-VCRMFWX5.js");
|
|
6748
6980
|
const installed = await installUserService(config2.port, config2.hostname);
|
|
6749
6981
|
if (!installed) {
|
|
6750
6982
|
warnings.push("Service installation is not supported on this platform.");
|
|
@@ -6768,7 +7000,8 @@ setup.post("/complete", async (c) => {
|
|
|
6768
7000
|
logger_default.info("spirit started successfully during setup");
|
|
6769
7001
|
} catch (err) {
|
|
6770
7002
|
logger_default.warn("spirit start failed during setup (non-fatal)", logger_default.errorData(err));
|
|
6771
|
-
|
|
7003
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
7004
|
+
warnings.push(`The spirit couldn't start: ${reason} \u2014 it will retry on next daemon restart.`);
|
|
6772
7005
|
}
|
|
6773
7006
|
let spiritConversationId;
|
|
6774
7007
|
try {
|
|
@@ -6795,7 +7028,7 @@ setup.post("/complete", async (c) => {
|
|
|
6795
7028
|
logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
|
|
6796
7029
|
if (spiritConversationId && spiritStarted) {
|
|
6797
7030
|
try {
|
|
6798
|
-
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-
|
|
7031
|
+
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-GPQ5SE5N.js");
|
|
6799
7032
|
const { listUsersByType: listUsers2 } = await import("./auth-A4VGHADI.js");
|
|
6800
7033
|
const admins = await listUsers2("brain");
|
|
6801
7034
|
const admin2 = admins.find((u) => u.role === "admin");
|
|
@@ -6835,9 +7068,9 @@ setup.post("/complete", async (c) => {
|
|
|
6835
7068
|
var setup_default = setup;
|
|
6836
7069
|
|
|
6837
7070
|
// packages/daemon/src/web/api/skills.ts
|
|
6838
|
-
import { existsSync as
|
|
7071
|
+
import { existsSync as existsSync9, mkdtempSync, readdirSync as readdirSync3, rmSync as rmSync5 } from "fs";
|
|
6839
7072
|
import { tmpdir } from "os";
|
|
6840
|
-
import { join, resolve as
|
|
7073
|
+
import { join, resolve as resolve13 } from "path";
|
|
6841
7074
|
import AdmZip from "adm-zip";
|
|
6842
7075
|
import { Hono as Hono20 } from "hono";
|
|
6843
7076
|
var app16 = new Hono20().get("/", async (c) => {
|
|
@@ -6913,19 +7146,19 @@ var app16 = new Hono20().get("/", async (c) => {
|
|
|
6913
7146
|
try {
|
|
6914
7147
|
const zip = new AdmZip(buffer);
|
|
6915
7148
|
for (const entry of zip.getEntries()) {
|
|
6916
|
-
const target =
|
|
7149
|
+
const target = resolve13(tmpDir, entry.entryName);
|
|
6917
7150
|
if (!target.startsWith(tmpDir)) {
|
|
6918
7151
|
return c.json({ error: "Invalid zip: paths must not escape archive" }, 400);
|
|
6919
7152
|
}
|
|
6920
7153
|
}
|
|
6921
7154
|
zip.extractAllTo(tmpDir, true);
|
|
6922
7155
|
let skillDir = null;
|
|
6923
|
-
if (
|
|
7156
|
+
if (existsSync9(join(tmpDir, "SKILL.md"))) {
|
|
6924
7157
|
skillDir = tmpDir;
|
|
6925
7158
|
} else {
|
|
6926
7159
|
const entries = readdirSync3(tmpDir, { withFileTypes: true }).filter((e) => e.isDirectory());
|
|
6927
7160
|
for (const entry of entries) {
|
|
6928
|
-
if (
|
|
7161
|
+
if (existsSync9(join(tmpDir, entry.name, "SKILL.md"))) {
|
|
6929
7162
|
skillDir = join(tmpDir, entry.name);
|
|
6930
7163
|
break;
|
|
6931
7164
|
}
|
|
@@ -7239,8 +7472,8 @@ var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
|
|
|
7239
7472
|
});
|
|
7240
7473
|
}, 15e3);
|
|
7241
7474
|
cleanups.push(() => clearInterval(keepAlive));
|
|
7242
|
-
await new Promise((
|
|
7243
|
-
stream.onAbort(() =>
|
|
7475
|
+
await new Promise((resolve18) => {
|
|
7476
|
+
stream.onAbort(() => resolve18());
|
|
7244
7477
|
});
|
|
7245
7478
|
} finally {
|
|
7246
7479
|
for (const cleanup of cleanups) {
|
|
@@ -7255,14 +7488,14 @@ var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
|
|
|
7255
7488
|
var events_default = app20;
|
|
7256
7489
|
|
|
7257
7490
|
// packages/daemon/src/web/api/variants.ts
|
|
7258
|
-
import { existsSync as
|
|
7259
|
-
import { resolve as
|
|
7491
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
7492
|
+
import { resolve as resolve15 } from "path";
|
|
7260
7493
|
import { Hono as Hono25 } from "hono";
|
|
7261
7494
|
|
|
7262
7495
|
// packages/daemon/src/lib/mind/spawn-server.ts
|
|
7263
7496
|
import { spawn as spawn4 } from "child_process";
|
|
7264
|
-
import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as
|
|
7265
|
-
import { resolve as
|
|
7497
|
+
import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync10 } from "fs";
|
|
7498
|
+
import { resolve as resolve14 } from "path";
|
|
7266
7499
|
async function spawnServer(cwd, port, options) {
|
|
7267
7500
|
let cmd = process.env.VOLUTE_NODE_PATH ?? process.execPath;
|
|
7268
7501
|
let args = ["--import", "tsx", "src/server.ts", "--port", String(port)];
|
|
@@ -7283,31 +7516,31 @@ function spawnAttached(cmd, args, cwd) {
|
|
|
7283
7516
|
cwd,
|
|
7284
7517
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7285
7518
|
});
|
|
7286
|
-
return new Promise((
|
|
7287
|
-
const timeout = setTimeout(() =>
|
|
7519
|
+
return new Promise((resolve18) => {
|
|
7520
|
+
const timeout = setTimeout(() => resolve18(null), 3e4);
|
|
7288
7521
|
function checkOutput(data) {
|
|
7289
7522
|
const match = data.toString().match(/listening on :(\d+)/);
|
|
7290
7523
|
if (match) {
|
|
7291
7524
|
clearTimeout(timeout);
|
|
7292
|
-
|
|
7525
|
+
resolve18({ child, actualPort: parseInt(match[1], 10) });
|
|
7293
7526
|
}
|
|
7294
7527
|
}
|
|
7295
7528
|
child.stdout?.on("data", checkOutput);
|
|
7296
7529
|
child.stderr?.on("data", checkOutput);
|
|
7297
7530
|
child.on("error", () => {
|
|
7298
7531
|
clearTimeout(timeout);
|
|
7299
|
-
|
|
7532
|
+
resolve18(null);
|
|
7300
7533
|
});
|
|
7301
7534
|
child.on("exit", () => {
|
|
7302
7535
|
clearTimeout(timeout);
|
|
7303
|
-
|
|
7536
|
+
resolve18(null);
|
|
7304
7537
|
});
|
|
7305
7538
|
});
|
|
7306
7539
|
}
|
|
7307
7540
|
function spawnDetached(cmd, args, cwd, logDir) {
|
|
7308
|
-
const logsDir = logDir ??
|
|
7541
|
+
const logsDir = logDir ?? resolve14(cwd, ".mind", "logs");
|
|
7309
7542
|
mkdirSync8(logsDir, { recursive: true });
|
|
7310
|
-
const logPath =
|
|
7543
|
+
const logPath = resolve14(logsDir, "mind.log");
|
|
7311
7544
|
const logFd = openSync(logPath, "a");
|
|
7312
7545
|
const child = spawn4(cmd, args, {
|
|
7313
7546
|
cwd,
|
|
@@ -7327,7 +7560,7 @@ function spawnDetached(cmd, args, cwd, logDir) {
|
|
|
7327
7560
|
}
|
|
7328
7561
|
const interval = setInterval(() => {
|
|
7329
7562
|
try {
|
|
7330
|
-
const content =
|
|
7563
|
+
const content = readFileSync10(logPath, "utf-8");
|
|
7331
7564
|
const match = content.match(/listening on :(\d+)/);
|
|
7332
7565
|
if (match) {
|
|
7333
7566
|
finish({ child, actualPort: parseInt(match[1], 10) });
|
|
@@ -7428,11 +7661,11 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
|
7428
7661
|
return c.json({ error: `Name already in use: ${variantName}` }, 409);
|
|
7429
7662
|
}
|
|
7430
7663
|
const projectRoot = entry.dir ?? mindDir(mindName);
|
|
7431
|
-
const variantDir =
|
|
7432
|
-
if (
|
|
7664
|
+
const variantDir = resolve15(projectRoot, ".variants", variantName);
|
|
7665
|
+
if (existsSync10(variantDir)) {
|
|
7433
7666
|
return c.json({ error: `Variant directory already exists: ${variantDir}` }, 409);
|
|
7434
7667
|
}
|
|
7435
|
-
mkdirSync9(
|
|
7668
|
+
mkdirSync9(resolve15(projectRoot, ".variants"), { recursive: true });
|
|
7436
7669
|
try {
|
|
7437
7670
|
await gitExec(["worktree", "add", "-b", variantName, variantDir], { cwd: projectRoot });
|
|
7438
7671
|
} catch (e) {
|
|
@@ -7445,7 +7678,7 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
|
7445
7678
|
const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
|
|
7446
7679
|
await exec(cmd, args, {
|
|
7447
7680
|
cwd: variantDir,
|
|
7448
|
-
env: { ...process.env, HOME:
|
|
7681
|
+
env: { ...process.env, HOME: resolve15(variantDir, "home") }
|
|
7449
7682
|
});
|
|
7450
7683
|
} else {
|
|
7451
7684
|
await exec("npm", ["install"], { cwd: variantDir });
|
|
@@ -7455,7 +7688,7 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
|
7455
7688
|
return c.json({ error: `npm install failed: ${msg}` }, 500);
|
|
7456
7689
|
}
|
|
7457
7690
|
if (body.soul) {
|
|
7458
|
-
|
|
7691
|
+
writeFileSync9(resolve15(variantDir, "home/SOUL.md"), body.soul);
|
|
7459
7692
|
}
|
|
7460
7693
|
const variantPort = body.port ?? await nextPort();
|
|
7461
7694
|
await addVariant(variantName, mindName, variantPort, variantDir, variantName);
|
|
@@ -7492,7 +7725,7 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
|
7492
7725
|
} catch {
|
|
7493
7726
|
}
|
|
7494
7727
|
const projectRoot = parentEntry.dir ?? mindDir(mindName);
|
|
7495
|
-
if (
|
|
7728
|
+
if (existsSync10(variantEntry.dir)) {
|
|
7496
7729
|
const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
|
|
7497
7730
|
if (status) {
|
|
7498
7731
|
try {
|
|
@@ -7604,7 +7837,7 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
|
7604
7837
|
const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
|
|
7605
7838
|
await exec(cmd, args, {
|
|
7606
7839
|
cwd: projectRoot,
|
|
7607
|
-
env: { ...process.env, HOME:
|
|
7840
|
+
env: { ...process.env, HOME: resolve15(projectRoot, "home") }
|
|
7608
7841
|
});
|
|
7609
7842
|
} else {
|
|
7610
7843
|
await exec("npm", ["install"], { cwd: projectRoot });
|
|
@@ -7659,7 +7892,8 @@ var channelSettingsSchema = z10.object({
|
|
|
7659
7892
|
private: z10.boolean().optional()
|
|
7660
7893
|
});
|
|
7661
7894
|
var createSchema2 = z10.object({
|
|
7662
|
-
name: z10.string().min(1).max(50).regex(/^[a-z0-9][a-z0-9-]*$/, "Channel names must be lowercase alphanumeric with hyphens")
|
|
7895
|
+
name: z10.string().min(1).max(50).regex(/^[a-z0-9][a-z0-9-]*$/, "Channel names must be lowercase alphanumeric with hyphens"),
|
|
7896
|
+
participantNames: z10.array(z10.string().min(1)).optional()
|
|
7663
7897
|
}).merge(channelSettingsSchema);
|
|
7664
7898
|
var inviteSchema = z10.object({
|
|
7665
7899
|
username: z10.string().min(1)
|
|
@@ -7678,10 +7912,21 @@ var app22 = new Hono26().get("/", async (c) => {
|
|
|
7678
7912
|
}).post("/", zValidator10("json", createSchema2), async (c) => {
|
|
7679
7913
|
const user = c.get("user");
|
|
7680
7914
|
const body = c.req.valid("json");
|
|
7915
|
+
const { name, participantNames, ...settings } = body;
|
|
7916
|
+
const participantIds = [];
|
|
7917
|
+
for (const username of participantNames ?? []) {
|
|
7918
|
+
let member = await getUserByUsername(username);
|
|
7919
|
+
if (!member && await findMind(username)) {
|
|
7920
|
+
member = await getOrCreateMindUser(username);
|
|
7921
|
+
}
|
|
7922
|
+
if (!member) {
|
|
7923
|
+
return c.json({ error: `User not found: ${username}` }, 404);
|
|
7924
|
+
}
|
|
7925
|
+
participantIds.push(member.id);
|
|
7926
|
+
}
|
|
7927
|
+
let ch;
|
|
7681
7928
|
try {
|
|
7682
|
-
|
|
7683
|
-
const ch = await createChannel(name, user.id, settings);
|
|
7684
|
-
return c.json({ ...ch, channel_name: name }, 201);
|
|
7929
|
+
ch = await createChannel(name, user.id, settings);
|
|
7685
7930
|
} catch (err) {
|
|
7686
7931
|
const cause = err instanceof Error ? err.cause : null;
|
|
7687
7932
|
if (cause && /UNIQUE/i.test(cause.extendedCode ?? cause.message ?? "")) {
|
|
@@ -7689,6 +7934,23 @@ var app22 = new Hono26().get("/", async (c) => {
|
|
|
7689
7934
|
}
|
|
7690
7935
|
throw err;
|
|
7691
7936
|
}
|
|
7937
|
+
try {
|
|
7938
|
+
for (const id of participantIds) {
|
|
7939
|
+
await joinChannel(ch.id, id);
|
|
7940
|
+
}
|
|
7941
|
+
} catch (err) {
|
|
7942
|
+
console.error("[channels] join failed during channel create:", err);
|
|
7943
|
+
try {
|
|
7944
|
+
await deleteConversation(ch.id);
|
|
7945
|
+
} catch (cleanupErr) {
|
|
7946
|
+
console.error(
|
|
7947
|
+
`[channels] failed to roll back channel ${ch.id} after join failure:`,
|
|
7948
|
+
cleanupErr
|
|
7949
|
+
);
|
|
7950
|
+
}
|
|
7951
|
+
throw err;
|
|
7952
|
+
}
|
|
7953
|
+
return c.json({ ...ch, channel_name: name }, 201);
|
|
7692
7954
|
}).get("/:name", async (c) => {
|
|
7693
7955
|
const name = c.req.param("name");
|
|
7694
7956
|
const ch = await getChannelByName(name);
|
|
@@ -8023,11 +8285,11 @@ var app23 = new Hono27().get("/:name/conversations/:id/events", async (c) => {
|
|
|
8023
8285
|
if (!stream.aborted) console.error("[chat] SSE ping error:", err);
|
|
8024
8286
|
});
|
|
8025
8287
|
}, 15e3);
|
|
8026
|
-
await new Promise((
|
|
8288
|
+
await new Promise((resolve18) => {
|
|
8027
8289
|
stream.onAbort(() => {
|
|
8028
8290
|
unsubscribe();
|
|
8029
8291
|
clearInterval(keepAlive);
|
|
8030
|
-
|
|
8292
|
+
resolve18();
|
|
8031
8293
|
});
|
|
8032
8294
|
});
|
|
8033
8295
|
});
|
|
@@ -8241,10 +8503,10 @@ app25.route("/api/conversations", conversations_default);
|
|
|
8241
8503
|
var app_default = app25;
|
|
8242
8504
|
|
|
8243
8505
|
// packages/daemon/src/web/server.ts
|
|
8244
|
-
import { existsSync as
|
|
8506
|
+
import { existsSync as existsSync11 } from "fs";
|
|
8245
8507
|
import { readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
8246
8508
|
import { createServer as createHttpsServer } from "https";
|
|
8247
|
-
import { dirname as dirname2, extname as extname3, resolve as
|
|
8509
|
+
import { dirname as dirname2, extname as extname3, resolve as resolve16 } from "path";
|
|
8248
8510
|
import { serve } from "@hono/node-server";
|
|
8249
8511
|
var MIME_TYPES2 = {
|
|
8250
8512
|
".html": "text/html",
|
|
@@ -8263,8 +8525,8 @@ async function startServer({
|
|
|
8263
8525
|
let assetsDir = "";
|
|
8264
8526
|
let searchDir = dirname2(new URL(import.meta.url).pathname);
|
|
8265
8527
|
for (let i = 0; i < 5; i++) {
|
|
8266
|
-
const candidate =
|
|
8267
|
-
if (
|
|
8528
|
+
const candidate = resolve16(searchDir, "dist", "web-assets");
|
|
8529
|
+
if (existsSync11(candidate)) {
|
|
8268
8530
|
assetsDir = candidate;
|
|
8269
8531
|
break;
|
|
8270
8532
|
}
|
|
@@ -8274,7 +8536,7 @@ async function startServer({
|
|
|
8274
8536
|
app_default.get("*", async (c) => {
|
|
8275
8537
|
const urlPath = new URL(c.req.url).pathname;
|
|
8276
8538
|
if (urlPath.startsWith("/api/") || urlPath.startsWith("/ext/")) return c.notFound();
|
|
8277
|
-
const filePath =
|
|
8539
|
+
const filePath = resolve16(assetsDir, urlPath.slice(1));
|
|
8278
8540
|
if (!filePath.startsWith(assetsDir)) return c.text("Forbidden", 403);
|
|
8279
8541
|
const s = await stat2(filePath).catch(() => null);
|
|
8280
8542
|
if (s?.isFile()) {
|
|
@@ -8287,7 +8549,7 @@ async function startServer({
|
|
|
8287
8549
|
const cacheControl = isHashed ? "public, max-age=31536000, immutable" : "no-cache";
|
|
8288
8550
|
return c.body(body, 200, { "Content-Type": mime, "Cache-Control": cacheControl });
|
|
8289
8551
|
}
|
|
8290
|
-
const indexPath =
|
|
8552
|
+
const indexPath = resolve16(assetsDir, "index.html");
|
|
8291
8553
|
const indexStat = await stat2(indexPath).catch(() => null);
|
|
8292
8554
|
if (indexStat?.isFile()) {
|
|
8293
8555
|
const body = await readFile2(indexPath, "utf-8");
|
|
@@ -8304,10 +8566,10 @@ async function startServer({
|
|
|
8304
8566
|
createServer: createHttpsServer,
|
|
8305
8567
|
serverOptions: { key: tls.key, cert: tls.cert }
|
|
8306
8568
|
});
|
|
8307
|
-
await new Promise((
|
|
8569
|
+
await new Promise((resolve18, reject) => {
|
|
8308
8570
|
server2.on("listening", () => {
|
|
8309
8571
|
logger_default.info("Volute UI running (https)", { hostname, port });
|
|
8310
|
-
|
|
8572
|
+
resolve18();
|
|
8311
8573
|
});
|
|
8312
8574
|
server2.on("error", (err) => {
|
|
8313
8575
|
reject(err);
|
|
@@ -8315,13 +8577,13 @@ async function startServer({
|
|
|
8315
8577
|
});
|
|
8316
8578
|
const internalPort = port + 1;
|
|
8317
8579
|
const internalServer = serve({ fetch: app_default.fetch, port: internalPort, hostname: "127.0.0.1" });
|
|
8318
|
-
await new Promise((
|
|
8580
|
+
await new Promise((resolve18, reject) => {
|
|
8319
8581
|
internalServer.on("listening", () => {
|
|
8320
8582
|
logger_default.info("Volute API running (http, internal)", {
|
|
8321
8583
|
hostname: "127.0.0.1",
|
|
8322
8584
|
port: internalPort
|
|
8323
8585
|
});
|
|
8324
|
-
|
|
8586
|
+
resolve18();
|
|
8325
8587
|
});
|
|
8326
8588
|
internalServer.on("error", (err) => {
|
|
8327
8589
|
reject(err);
|
|
@@ -8330,10 +8592,10 @@ async function startServer({
|
|
|
8330
8592
|
return { server: server2, internalPort };
|
|
8331
8593
|
}
|
|
8332
8594
|
const server = serve({ fetch: app_default.fetch, port, hostname });
|
|
8333
|
-
await new Promise((
|
|
8595
|
+
await new Promise((resolve18, reject) => {
|
|
8334
8596
|
server.on("listening", () => {
|
|
8335
8597
|
logger_default.info("Volute API running (http)", { hostname, port });
|
|
8336
|
-
|
|
8598
|
+
resolve18();
|
|
8337
8599
|
});
|
|
8338
8600
|
server.on("error", (err) => {
|
|
8339
8601
|
reject(err);
|
|
@@ -8344,18 +8606,18 @@ async function startServer({
|
|
|
8344
8606
|
|
|
8345
8607
|
// packages/daemon/src/daemon.ts
|
|
8346
8608
|
if (!process.env.VOLUTE_HOME) {
|
|
8347
|
-
process.env.VOLUTE_HOME =
|
|
8609
|
+
process.env.VOLUTE_HOME = resolve17(homedir3(), ".volute");
|
|
8348
8610
|
}
|
|
8349
8611
|
if (process.env.VOLUTE_TIMEZONE && !process.env.TZ) {
|
|
8350
8612
|
process.env.TZ = process.env.VOLUTE_TIMEZONE;
|
|
8351
8613
|
}
|
|
8352
8614
|
function writeDaemonConfig(systemDir, config2, token) {
|
|
8353
|
-
const configPath =
|
|
8354
|
-
|
|
8615
|
+
const configPath = resolve17(systemDir, "daemon.json");
|
|
8616
|
+
writeFileSync10(configPath, `${JSON.stringify(config2, null, 2)}
|
|
8355
8617
|
`, { mode: 420 });
|
|
8356
8618
|
chmodSync(configPath, 420);
|
|
8357
|
-
const tokenPath =
|
|
8358
|
-
|
|
8619
|
+
const tokenPath = resolve17(systemDir, "daemon-token");
|
|
8620
|
+
writeFileSync10(tokenPath, `${token}
|
|
8359
8621
|
`, { mode: 384 });
|
|
8360
8622
|
chmodSync(tokenPath, 384);
|
|
8361
8623
|
}
|
|
@@ -8365,7 +8627,7 @@ async function startDaemon(opts) {
|
|
|
8365
8627
|
const home = voluteHome();
|
|
8366
8628
|
const systemDir = voluteSystemDir();
|
|
8367
8629
|
if (!opts.foreground) {
|
|
8368
|
-
const rotatingLog = new RotatingLog(
|
|
8630
|
+
const rotatingLog = new RotatingLog(resolve17(systemDir, "daemon.log"));
|
|
8369
8631
|
logger_default.setOutput((line) => rotatingLog.write(`${line}
|
|
8370
8632
|
`));
|
|
8371
8633
|
const write = (...args) => rotatingLog.write(`${format(...args)}
|
|
@@ -8375,15 +8637,15 @@ async function startDaemon(opts) {
|
|
|
8375
8637
|
console.warn = write;
|
|
8376
8638
|
console.info = write;
|
|
8377
8639
|
}
|
|
8378
|
-
const DAEMON_PID_PATH =
|
|
8379
|
-
const DAEMON_JSON_PATH =
|
|
8380
|
-
const DAEMON_TOKEN_PATH =
|
|
8640
|
+
const DAEMON_PID_PATH = resolve17(systemDir, "daemon.pid");
|
|
8641
|
+
const DAEMON_JSON_PATH = resolve17(systemDir, "daemon.json");
|
|
8642
|
+
const DAEMON_TOKEN_PATH = resolve17(systemDir, "daemon-token");
|
|
8381
8643
|
mkdirSync10(home, { recursive: true });
|
|
8382
8644
|
ensureSystemDir();
|
|
8383
|
-
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-
|
|
8645
|
+
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-5ECWTYKG.js");
|
|
8384
8646
|
migrateConfigSecrets();
|
|
8385
8647
|
migrateSetupCompleted();
|
|
8386
|
-
const { migrateAiModelQualification } = await import("./ai-service-
|
|
8648
|
+
const { migrateAiModelQualification } = await import("./ai-service-643TNFPH.js");
|
|
8387
8649
|
migrateAiModelQualification();
|
|
8388
8650
|
await (await import("./db-FO6LXYCW.js")).getDb();
|
|
8389
8651
|
try {
|
|
@@ -8395,12 +8657,12 @@ async function startDaemon(opts) {
|
|
|
8395
8657
|
logger_default.warn("failed to migrate system user role", logger_default.errorData(err));
|
|
8396
8658
|
}
|
|
8397
8659
|
try {
|
|
8398
|
-
const { migrateAvatarSizes } = await import("./avatar-image-
|
|
8660
|
+
const { migrateAvatarSizes } = await import("./avatar-image-Y45R7LW5.js");
|
|
8399
8661
|
await migrateAvatarSizes();
|
|
8400
8662
|
} catch (err) {
|
|
8401
8663
|
logger_default.warn("avatar size migration failed", logger_default.errorData(err));
|
|
8402
8664
|
}
|
|
8403
|
-
const { initSandbox } = await import("./sandbox-
|
|
8665
|
+
const { initSandbox } = await import("./sandbox-5VQ454XP.js");
|
|
8404
8666
|
await initSandbox();
|
|
8405
8667
|
try {
|
|
8406
8668
|
await syncBuiltinSkills();
|
|
@@ -8426,6 +8688,11 @@ async function startDaemon(opts) {
|
|
|
8426
8688
|
} catch (err) {
|
|
8427
8689
|
logger_default.warn("failed to ensure #system channel", logger_default.errorData(err));
|
|
8428
8690
|
}
|
|
8691
|
+
try {
|
|
8692
|
+
await backfillSystemChannelMembers();
|
|
8693
|
+
} catch (err) {
|
|
8694
|
+
logger_default.warn("failed to backfill minds into #system", logger_default.errorData(err));
|
|
8695
|
+
}
|
|
8429
8696
|
try {
|
|
8430
8697
|
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-A4VGHADI.js");
|
|
8431
8698
|
await getOrCreateSystemUser2();
|
|
@@ -8436,7 +8703,7 @@ async function startDaemon(opts) {
|
|
|
8436
8703
|
);
|
|
8437
8704
|
}
|
|
8438
8705
|
const token = process.env.VOLUTE_DAEMON_TOKEN || randomBytes3(32).toString("hex");
|
|
8439
|
-
const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-
|
|
8706
|
+
const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-5ECWTYKG.js");
|
|
8440
8707
|
const globalCfg = readGlobalConfig2();
|
|
8441
8708
|
let tls;
|
|
8442
8709
|
if (opts.tailscale || globalCfg.tailscale) {
|
|
@@ -8468,7 +8735,7 @@ async function startDaemon(opts) {
|
|
|
8468
8735
|
process.env.VOLUTE_DAEMON_TOKEN = token;
|
|
8469
8736
|
process.env.VOLUTE_DAEMON_PORT = String(daemonPort);
|
|
8470
8737
|
process.env.VOLUTE_DAEMON_HOSTNAME = hostname;
|
|
8471
|
-
|
|
8738
|
+
writeFileSync10(DAEMON_PID_PATH, myPid, { mode: 420 });
|
|
8472
8739
|
const daemonConfig = { port, hostname };
|
|
8473
8740
|
if (internalPort) daemonConfig.internalPort = internalPort;
|
|
8474
8741
|
if (tls) daemonConfig.tls = true;
|
|
@@ -8521,10 +8788,10 @@ async function startDaemon(opts) {
|
|
|
8521
8788
|
await Promise.all(workers);
|
|
8522
8789
|
}
|
|
8523
8790
|
try {
|
|
8524
|
-
const { isSetupComplete: isSetupComplete2 } = await import("./setup-
|
|
8791
|
+
const { isSetupComplete: isSetupComplete2 } = await import("./setup-5ECWTYKG.js");
|
|
8525
8792
|
if (isSetupComplete2()) {
|
|
8526
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
8527
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
8793
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-WXS3HCLN.js");
|
|
8794
|
+
const { startSpiritFull } = await import("./mind-service-2ARGJNKP.js");
|
|
8528
8795
|
await ensureSpiritProject();
|
|
8529
8796
|
const spiritEntry = await findMind(SPIRIT_NAME);
|
|
8530
8797
|
if (spiritEntry?.dir) {
|
|
@@ -8545,7 +8812,7 @@ async function startDaemon(opts) {
|
|
|
8545
8812
|
bridgeManager.startBridges(daemonPort).catch((err) => {
|
|
8546
8813
|
logger_default.warn("failed to start bridges", logger_default.errorData(err));
|
|
8547
8814
|
});
|
|
8548
|
-
import("./cloud-sync-
|
|
8815
|
+
import("./cloud-sync-WHKCB4CD.js").then(
|
|
8549
8816
|
({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
|
|
8550
8817
|
logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
|
|
8551
8818
|
})
|
|
@@ -8553,7 +8820,7 @@ async function startDaemon(opts) {
|
|
|
8553
8820
|
logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
|
|
8554
8821
|
});
|
|
8555
8822
|
try {
|
|
8556
|
-
const { backfillTemplateHashes, notifyVersionUpdate, warnStaleTemplates } = await import("./version-notify-
|
|
8823
|
+
const { backfillTemplateHashes, notifyVersionUpdate, warnStaleTemplates } = await import("./version-notify-73YURTFR.js");
|
|
8557
8824
|
backfillTemplateHashes().then(() => warnStaleTemplates()).catch((err) => {
|
|
8558
8825
|
logger_default.warn("failed to check template staleness", logger_default.errorData(err));
|
|
8559
8826
|
});
|
|
@@ -8583,13 +8850,13 @@ async function startDaemon(opts) {
|
|
|
8583
8850
|
logger_default.info(`running on ${hostname}:${port}, pid ${myPid}`);
|
|
8584
8851
|
function cleanup() {
|
|
8585
8852
|
try {
|
|
8586
|
-
if (
|
|
8853
|
+
if (readFileSync11(DAEMON_PID_PATH, "utf-8").trim() === myPid) {
|
|
8587
8854
|
unlinkSync2(DAEMON_PID_PATH);
|
|
8588
8855
|
}
|
|
8589
8856
|
} catch {
|
|
8590
8857
|
}
|
|
8591
8858
|
try {
|
|
8592
|
-
if (
|
|
8859
|
+
if (readFileSync11(DAEMON_TOKEN_PATH, "utf-8").trim() === token) {
|
|
8593
8860
|
unlinkSync2(DAEMON_TOKEN_PATH);
|
|
8594
8861
|
try {
|
|
8595
8862
|
unlinkSync2(DAEMON_JSON_PATH);
|