volute 0.42.0 → 0.43.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/dist/{accept-7YVHZKRD.js → accept-N5XULCXK.js} +1 -1
- package/dist/{activity-events-KFKVRZE3.js → activity-events-UISXY4Y5.js} +3 -3
- package/dist/{ai-service-3GBOJGUA.js → ai-service-FBCCEYF5.js} +8 -4
- package/dist/{archive-4PPYF7LL.js → archive-I32WHCJB.js} +3 -3
- package/dist/{auth-EAASQPTN.js → auth-3RIG6GKN.js} +4 -4
- package/dist/{bridge-WPYSOQKR.js → bridge-2PO3AI5D.js} +1 -1
- package/dist/{chat-7DOENBY2.js → chat-SDSX5TVV.js} +8 -8
- package/dist/{chunk-M2YMNTHK.js → chunk-2HIVYZDB.js} +1 -1
- package/dist/{chunk-TKOWXAHG.js → chunk-3WLWKOGM.js} +21 -6
- package/dist/{chunk-QPTQKGGF.js → chunk-57LBQ7JX.js} +1 -1
- package/dist/{chunk-VSUZE2PD.js → chunk-65OLHBCL.js} +13 -12
- package/dist/{chunk-K547QOCM.js → chunk-7G2EEYXX.js} +2 -2
- package/dist/{chunk-E7XWFDZL.js → chunk-AD46AYZQ.js} +1 -1
- package/dist/{chunk-CGPESELY.js → chunk-ATEX3ZPG.js} +21 -5
- package/dist/{chunk-WR7CSHQ4.js → chunk-C6ESRQZ7.js} +1 -1
- package/dist/{chunk-OSUF75I7.js → chunk-EE7SZJON.js} +2 -2
- package/dist/{chunk-5QG36RV7.js → chunk-EFL5UOY4.js} +3 -3
- package/dist/{chunk-JLX3GC7T.js → chunk-FSSUANZJ.js} +5 -5
- package/dist/{chunk-2YRTSK5K.js → chunk-FZ5TH5PF.js} +14 -11
- package/dist/{chunk-OEJFZHZZ.js → chunk-GZJFC76M.js} +1 -1
- package/dist/{chunk-KUJVCDWT.js → chunk-JVK6QQIC.js} +2 -2
- package/dist/{chunk-YLTIEEVL.js → chunk-K4EHBHPE.js} +3 -3
- package/dist/{chunk-MHFAWJCC.js → chunk-L3IV23ZG.js} +12 -1
- package/dist/{chunk-VBKRZCR7.js → chunk-M3PGGSBH.js} +1 -1
- package/dist/{chunk-G777ME4L.js → chunk-O3DXAR44.js} +2 -2
- package/dist/{chunk-KZAL7HEQ.js → chunk-ONM2AZFL.js} +1 -1
- package/dist/{chunk-52NMCDBS.js → chunk-PF2AB7VJ.js} +568 -378
- package/dist/chunk-PGPLCJPK.js +272 -0
- package/dist/{chunk-IFNSAOA4.js → chunk-RBNMDAKB.js} +4 -0
- package/dist/{chunk-62ICA2FF.js → chunk-SPLPKBES.js} +17 -1
- package/dist/{chunk-BLOAJLGI.js → chunk-XDTKJNW5.js} +1 -1
- package/dist/{chunk-IUZ3EV2D.js → chunk-YAMO2U3N.js} +1 -1
- package/dist/{chunk-4ZSUUBG5.js → chunk-YSV3VJQK.js} +55 -2
- package/dist/{chunk-RKBYFLOR.js → chunk-ZO7IQJKO.js} +3 -3
- package/dist/cli.js +22 -22
- package/dist/{clock-HP2TGMG5.js → clock-K43IMROX.js} +3 -3
- package/dist/{cloud-sync-3OPHFOYQ.js → cloud-sync-FRYNWKCR.js} +16 -17
- package/dist/{config-W7MS3PWY.js → config-TJLYUV3U.js} +3 -3
- package/dist/{conversations-FSZCUUYO.js → conversations-67WWW25C.js} +4 -4
- package/dist/{create-YNBZWD34.js → create-7W3LV3J7.js} +2 -2
- package/dist/{create-CJ2SR4EU.js → create-DF3KISTW.js} +1 -1
- package/dist/{daemon-client-EWDPOOHC.js → daemon-client-IYR4KCPU.js} +3 -1
- package/dist/{daemon-restart-RAKGR56L.js → daemon-restart-5GVZ5V3X.js} +7 -8
- package/dist/daemon.js +541 -440
- package/dist/{db-ZJJJYJBU.js → db-CZV62BOQ.js} +2 -2
- package/dist/{delete-4ND5PLE7.js → delete-BFMIGAIB.js} +1 -1
- package/dist/delivery-manager-5J2BE22P.js +32 -0
- package/dist/{delivery-router-FDBZJQOY.js → delivery-router-HXBHYHJM.js} +7 -5
- package/dist/down-RRNYIGCU.js +16 -0
- package/dist/echo-text-XKBJM6RV.js +32 -0
- package/dist/{env-XX2MBZCZ.js → env-VZ4MLFQW.js} +1 -1
- package/dist/{exec-ZDD7NEB4.js → exec-SJK7VUTC.js} +3 -4
- package/dist/{export-5DOQV2WM.js → export-7LPCIB5J.js} +4 -4
- package/dist/{extension-BCFYXI7A.js → extension-SEID47SR.js} +1 -1
- package/dist/{extensions-BTNIUS5J.js → extensions-76EGTMFY.js} +16 -17
- package/dist/{files-K2MEMV3W.js → files-LV7VAKPC.js} +4 -4
- package/dist/{import-V6QEHMPQ.js → import-XPECCRQ7.js} +8 -8
- package/dist/{isolation-F7ABZMDA.js → isolation-5AYEY55P.js} +5 -3
- package/dist/{join-4S3KT7NE.js → join-RXPXGV4L.js} +1 -1
- package/dist/{list-XJB5WII6.js → list-OXIAY3W7.js} +1 -1
- package/dist/{login-PHMTLNUF.js → login-KJSN4JDA.js} +3 -3
- package/dist/{login-YWD6PUOT.js → login-MY6ETFYB.js} +1 -1
- package/dist/{logout-Q2WICH4V.js → logout-NCG3TMDL.js} +1 -1
- package/dist/{logout-BP3R3CAA.js → logout-TMJGUQV2.js} +3 -3
- package/dist/message-delivery-WJBZFALY.js +34 -0
- package/dist/{mind-VXV6ZYZY.js → mind-QEWCR7FA.js} +18 -18
- package/dist/{mind-activity-tracker-HWVFE533.js → mind-activity-tracker-JHAT6456.js} +4 -4
- package/dist/{mind-history-TDUQFYAG.js → mind-history-VRO5A76U.js} +1 -1
- package/dist/{mind-list-2T353Q5G.js → mind-list-4D7J4CHD.js} +1 -1
- package/dist/{mind-profile-2HHR7LZ7.js → mind-profile-PEQYASQX.js} +1 -1
- package/dist/mind-service-ZBVUMJ5H.js +36 -0
- package/dist/{mind-sleep-4NXV4J4U.js → mind-sleep-YMBR3I35.js} +1 -1
- package/dist/{mind-status-CG66OXDK.js → mind-status-UO34ASXZ.js} +1 -1
- package/dist/{mind-wake-TNB54DBR.js → mind-wake-LCLGTXA2.js} +1 -1
- package/dist/{package-UWH5IM76.js → package-ZOI2KAYC.js} +1 -1
- package/dist/{read-JLR4NQXU.js → read-QVAXMTPV.js} +1 -1
- package/dist/{register-IQ2M4UO6.js → register-Y2H4PY5R.js} +1 -1
- package/dist/{registry-MDLNPTTI.js → registry-7LQHTRUX.js} +2 -2
- package/dist/{reject-N2D4CZND.js → reject-EV35X64Y.js} +1 -1
- package/dist/{restart-43A5MBGV.js → restart-FJQ662XJ.js} +1 -1
- package/dist/{sandbox-E7RWZDVG.js → sandbox-SJH3XOPZ.js} +4 -4
- package/dist/scheduler-BR6C6B3E.js +30 -0
- package/dist/{schema-HHYJDG7B.js → schema-LRUTFOER.js} +1 -1
- package/dist/{seed-YQAOIXIY.js → seed-KOG6KJAO.js} +1 -1
- package/dist/{seed-check-N5ALJBT6.js → seed-check-VLTVILOV.js} +1 -1
- package/dist/{seed-cmd-7KJS4LCA.js → seed-cmd-GJFENEJH.js} +3 -3
- package/dist/{seed-create-Z7NDRRGP.js → seed-create-YXO6R4KE.js} +4 -4
- package/dist/{seed-sprout-PYDMVVUL.js → seed-sprout-BBU64QXP.js} +8 -9
- package/dist/{send-KQECN2EL.js → send-ZBZWIH5V.js} +4 -4
- package/dist/{service-Q5OVY5AK.js → service-4EVZKGSA.js} +4 -5
- package/dist/{service-install-GTDUHP6R.js → service-install-SHRM6NHK.js} +5 -6
- package/dist/{setup-IYOUPCIK.js → setup-25MMJ3J4.js} +3 -3
- package/dist/{setup-VARJ7N6Z.js → setup-354PDHUF.js} +8 -10
- package/dist/{skill-E43BI34Y.js → skill-FKFHIJRR.js} +1 -1
- package/dist/{skills-YBCYVOPQ.js → skills-DPI3WZPQ.js} +5 -6
- package/dist/sleep-manager-BVU5D2AE.js +34 -0
- package/dist/{spirit-NJFAY5CZ.js → spirit-JQQHUVWR.js} +7 -8
- package/dist/{split-5IBUODEE.js → split-WBMZXBHF.js} +1 -1
- package/dist/{sprout-B27C2WGE.js → sprout-4WAYBUVV.js} +1 -1
- package/dist/{start-5AYFGNS7.js → start-5JE3TV66.js} +1 -1
- package/dist/{status-ECZHHSY5.js → status-WTU2WHXY.js} +12 -9
- package/dist/{stop-WJ6IG6OK.js → stop-AAMTG3TU.js} +1 -1
- package/dist/system-chat-KMQIP7VH.js +34 -0
- package/dist/{systems-5MA57Q7G.js → systems-VNB5WKSS.js} +4 -4
- package/dist/{tailscale-TIRTGM6E.js → tailscale-Q7ZJL7S7.js} +2 -2
- package/dist/{turn-tracker-W4TASMR7.js → turn-tracker-2GMKJQTN.js} +7 -5
- package/dist/up-7RSBEKW6.js +18 -0
- package/dist/{update-OPR4KU4M.js → update-EJ7Q77ZX.js} +9 -10
- package/dist/{update-check-OG27AL4Z.js → update-check-ACYYNKTW.js} +3 -3
- package/dist/{upgrade-QB7AHIKX.js → upgrade-37DAGF6H.js} +1 -1
- package/dist/{version-notify-TCKAX7ZA.js → version-notify-DCAIXXZB.js} +17 -18
- package/dist/web-assets/assets/{index-CrFAsfiE.js → index-DTDmEfPU.js} +2 -2
- package/dist/web-assets/index.html +1 -1
- package/drizzle/0010_delivery_queue_redrive.sql +10 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +1 -1
- package/templates/codex/src/server.ts +2 -8
- package/dist/chunk-GN52E2DP.js +0 -59
- package/dist/chunk-TFBQESH7.js +0 -179
- package/dist/delivery-manager-5Y35DOX3.js +0 -33
- package/dist/down-DS6WCT34.js +0 -17
- package/dist/echo-text-YP3JVLNA.js +0 -32
- package/dist/message-delivery-FPIL26WV.js +0 -41
- package/dist/mind-manager-OYOIBGK6.js +0 -33
- package/dist/mind-service-PR4PR4XI.js +0 -37
- package/dist/scheduler-KXUY2I7W.js +0 -31
- package/dist/sleep-manager-FJLASHHW.js +0 -35
- package/dist/system-chat-P6KVGW4T.js +0 -35
- package/dist/up-POJX6S5Y.js +0 -19
package/dist/daemon.js
CHANGED
|
@@ -6,21 +6,21 @@ import {
|
|
|
6
6
|
rejectPending,
|
|
7
7
|
stageFile,
|
|
8
8
|
validateFilePath
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2HIVYZDB.js";
|
|
10
10
|
import {
|
|
11
11
|
findOpenClawSession,
|
|
12
12
|
importOpenClawConnectors,
|
|
13
13
|
importPiSession,
|
|
14
14
|
parseNameFromIdentity
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-JVK6QQIC.js";
|
|
16
16
|
import {
|
|
17
17
|
checkForUpdate,
|
|
18
18
|
checkForUpdateCached,
|
|
19
19
|
getCurrentVersion
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-AD46AYZQ.js";
|
|
21
21
|
import {
|
|
22
22
|
isHomeOnlyArchive
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-GZJFC76M.js";
|
|
24
24
|
import {
|
|
25
25
|
computeTemplateHash
|
|
26
26
|
} from "./chunk-QMJCNZ6C.js";
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
fixModelEscapes,
|
|
31
31
|
getPlatformDriver,
|
|
32
32
|
routeOutboundBridge
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-FZ5TH5PF.js";
|
|
34
34
|
import {
|
|
35
35
|
getBridgeConfig,
|
|
36
36
|
readBridgesConfig,
|
|
@@ -39,13 +39,15 @@ import {
|
|
|
39
39
|
resolveChannelMapping,
|
|
40
40
|
setBridgeConfig,
|
|
41
41
|
setChannelMapping
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-57LBQ7JX.js";
|
|
43
43
|
import {
|
|
44
|
+
MindStartupError,
|
|
44
45
|
RestartTracker,
|
|
45
46
|
RotatingLog,
|
|
46
47
|
SESSION_MAX_AGE,
|
|
47
48
|
announceToSystem,
|
|
48
49
|
authMiddleware,
|
|
50
|
+
checkHealth,
|
|
49
51
|
cleanExpiredSessions,
|
|
50
52
|
clearDeliveredNotices,
|
|
51
53
|
createSession,
|
|
@@ -94,19 +96,17 @@ import {
|
|
|
94
96
|
startMindFull,
|
|
95
97
|
stopMindFull,
|
|
96
98
|
syncProviderToMinds,
|
|
97
|
-
tagUntaggedInbound,
|
|
98
|
-
tagUntaggedOutbound,
|
|
99
99
|
uninstallNpmExtension,
|
|
100
100
|
writeSystemsConfig
|
|
101
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-PF2AB7VJ.js";
|
|
102
102
|
import {
|
|
103
103
|
loadMergedEnv,
|
|
104
104
|
mindEnvPath,
|
|
105
105
|
readEnv,
|
|
106
106
|
sharedEnvPath,
|
|
107
107
|
writeEnv
|
|
108
|
-
} from "./chunk-
|
|
109
|
-
import "./chunk-
|
|
108
|
+
} from "./chunk-XDTKJNW5.js";
|
|
109
|
+
import "./chunk-65OLHBCL.js";
|
|
110
110
|
import {
|
|
111
111
|
applyInitFiles,
|
|
112
112
|
applyTemplateHomeFiles,
|
|
@@ -135,7 +135,7 @@ import {
|
|
|
135
135
|
syncBuiltinSkills,
|
|
136
136
|
uninstallSkill,
|
|
137
137
|
updateSkill
|
|
138
|
-
} from "./chunk-
|
|
138
|
+
} from "./chunk-FSSUANZJ.js";
|
|
139
139
|
import {
|
|
140
140
|
addMessage,
|
|
141
141
|
createChannel,
|
|
@@ -167,7 +167,7 @@ import {
|
|
|
167
167
|
setConversationPrivate,
|
|
168
168
|
subscribe as subscribe2,
|
|
169
169
|
updateChannelSettings
|
|
170
|
-
} from "./chunk-
|
|
170
|
+
} from "./chunk-K4EHBHPE.js";
|
|
171
171
|
import {
|
|
172
172
|
readVoluteConfig,
|
|
173
173
|
writeVoluteConfig
|
|
@@ -175,15 +175,15 @@ import {
|
|
|
175
175
|
import {
|
|
176
176
|
isSandboxEnabled,
|
|
177
177
|
wrapForSandbox
|
|
178
|
-
} from "./chunk-
|
|
178
|
+
} from "./chunk-C6ESRQZ7.js";
|
|
179
179
|
import {
|
|
180
180
|
getActiveMinds,
|
|
181
181
|
onMindEvent,
|
|
182
182
|
stopAll
|
|
183
|
-
} from "./chunk-
|
|
183
|
+
} from "./chunk-M3PGGSBH.js";
|
|
184
184
|
import {
|
|
185
185
|
extractTextContent
|
|
186
|
-
} from "./chunk-
|
|
186
|
+
} from "./chunk-SPLPKBES.js";
|
|
187
187
|
import {
|
|
188
188
|
PROMPT_DEFAULTS,
|
|
189
189
|
PROMPT_KEYS,
|
|
@@ -206,20 +206,19 @@ import {
|
|
|
206
206
|
summarizeTurn,
|
|
207
207
|
takeErrored,
|
|
208
208
|
trackToolUse
|
|
209
|
-
} from "./chunk-
|
|
210
|
-
import
|
|
211
|
-
exec,
|
|
212
|
-
gitExec,
|
|
213
|
-
resolveVoluteBin
|
|
214
|
-
} from "./chunk-GN52E2DP.js";
|
|
209
|
+
} from "./chunk-3WLWKOGM.js";
|
|
210
|
+
import "./chunk-ATEX3ZPG.js";
|
|
215
211
|
import {
|
|
216
212
|
chownMindDir,
|
|
217
213
|
createMindUser,
|
|
218
214
|
deleteMindUser,
|
|
219
215
|
ensureVoluteGroup,
|
|
216
|
+
exec,
|
|
217
|
+
gitExec,
|
|
220
218
|
isIsolationEnabled,
|
|
219
|
+
resolveVoluteBin,
|
|
221
220
|
wrapForIsolation
|
|
222
|
-
} from "./chunk-
|
|
221
|
+
} from "./chunk-PGPLCJPK.js";
|
|
223
222
|
import {
|
|
224
223
|
addCustomModel,
|
|
225
224
|
buildCustomModel,
|
|
@@ -240,12 +239,12 @@ import {
|
|
|
240
239
|
setProviderRefreshHook,
|
|
241
240
|
setUtilityModel,
|
|
242
241
|
unqualifyModelId
|
|
243
|
-
} from "./chunk-
|
|
242
|
+
} from "./chunk-YSV3VJQK.js";
|
|
244
243
|
import {
|
|
245
244
|
isSetupComplete,
|
|
246
245
|
readGlobalConfig,
|
|
247
246
|
writeGlobalConfig
|
|
248
|
-
} from "./chunk-
|
|
247
|
+
} from "./chunk-ONM2AZFL.js";
|
|
249
248
|
import {
|
|
250
249
|
approveUser,
|
|
251
250
|
changePassword,
|
|
@@ -264,11 +263,11 @@ import {
|
|
|
264
263
|
syncMindProfile,
|
|
265
264
|
updateUserProfile,
|
|
266
265
|
verifyUser
|
|
267
|
-
} from "./chunk-
|
|
266
|
+
} from "./chunk-EFL5UOY4.js";
|
|
268
267
|
import {
|
|
269
268
|
broadcast,
|
|
270
269
|
subscribe
|
|
271
|
-
} from "./chunk-
|
|
270
|
+
} from "./chunk-7G2EEYXX.js";
|
|
272
271
|
import {
|
|
273
272
|
logBuffer,
|
|
274
273
|
logger_default
|
|
@@ -300,7 +299,7 @@ import {
|
|
|
300
299
|
validateMindName,
|
|
301
300
|
voluteHome,
|
|
302
301
|
voluteSystemDir
|
|
303
|
-
} from "./chunk-
|
|
302
|
+
} from "./chunk-YAMO2U3N.js";
|
|
304
303
|
import {
|
|
305
304
|
activity,
|
|
306
305
|
channels,
|
|
@@ -311,11 +310,11 @@ import {
|
|
|
311
310
|
systemPrompts,
|
|
312
311
|
turns,
|
|
313
312
|
users
|
|
314
|
-
} from "./chunk-
|
|
313
|
+
} from "./chunk-L3IV23ZG.js";
|
|
315
314
|
import "./chunk-K3NQKI34.js";
|
|
316
315
|
|
|
317
316
|
// packages/daemon/src/daemon.ts
|
|
318
|
-
import { randomBytes } from "crypto";
|
|
317
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
319
318
|
import { chmodSync, mkdirSync as mkdirSync10, readFileSync as readFileSync10, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "fs";
|
|
320
319
|
import { homedir as homedir3 } from "os";
|
|
321
320
|
import { resolve as resolve17 } from "path";
|
|
@@ -1104,17 +1103,21 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1104
1103
|
}).get("/ai/models", requireAdmin, async (c) => {
|
|
1105
1104
|
const models = await getAvailableModels();
|
|
1106
1105
|
const enabled = new Set(getEnabledModels());
|
|
1107
|
-
const customIds = new Set(getCustomModels().map((m) => m.id));
|
|
1106
|
+
const customIds = new Set(getCustomModels().map((m) => `${m.provider}:${m.id}`));
|
|
1108
1107
|
return c.json(
|
|
1109
|
-
models.map((m) =>
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1108
|
+
models.map((m) => {
|
|
1109
|
+
const qualifiedId = `${m.provider}:${m.id}`;
|
|
1110
|
+
return {
|
|
1111
|
+
id: m.id,
|
|
1112
|
+
qualifiedId,
|
|
1113
|
+
name: m.name,
|
|
1114
|
+
provider: m.provider,
|
|
1115
|
+
contextWindow: m.contextWindow,
|
|
1116
|
+
maxTokens: m.maxTokens,
|
|
1117
|
+
enabled: enabled.has(qualifiedId),
|
|
1118
|
+
custom: customIds.has(qualifiedId)
|
|
1119
|
+
};
|
|
1120
|
+
})
|
|
1118
1121
|
);
|
|
1119
1122
|
}).put(
|
|
1120
1123
|
"/ai/models",
|
|
@@ -1140,14 +1143,8 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1140
1143
|
400
|
|
1141
1144
|
);
|
|
1142
1145
|
}
|
|
1143
|
-
if (getCustomModels().some((m) => m.id === id && m.provider !== provider)) {
|
|
1144
|
-
return c.json(
|
|
1145
|
-
{ error: `A custom model "${id}" is already registered under another provider` },
|
|
1146
|
-
400
|
|
1147
|
-
);
|
|
1148
|
-
}
|
|
1149
1146
|
addCustomModel(provider, id, name);
|
|
1150
|
-
setEnabledModels([.../* @__PURE__ */ new Set([...getEnabledModels(), id])]);
|
|
1147
|
+
setEnabledModels([.../* @__PURE__ */ new Set([...getEnabledModels(), `${provider}:${id}`])]);
|
|
1151
1148
|
return c.json({ ok: true });
|
|
1152
1149
|
}
|
|
1153
1150
|
).delete("/ai/models/custom", requireAdmin, (c) => {
|
|
@@ -1849,6 +1846,76 @@ async function findOrCreatePuppet(platform, platformId, displayName) {
|
|
|
1849
1846
|
}
|
|
1850
1847
|
}
|
|
1851
1848
|
|
|
1849
|
+
// packages/daemon/src/lib/delivery/fan-out.ts
|
|
1850
|
+
var MAX_CONSECUTIVE_MIND_TURNS = 6;
|
|
1851
|
+
var consecutiveMindTurns = /* @__PURE__ */ new Map();
|
|
1852
|
+
async function emitLoopNotice(conversationId) {
|
|
1853
|
+
const systemUser = await getOrCreateSystemUser();
|
|
1854
|
+
await addMessage(conversationId, "user", systemUser.username, [
|
|
1855
|
+
{
|
|
1856
|
+
type: "text",
|
|
1857
|
+
text: `[System] This exchange has continued for ${MAX_CONSECUTIVE_MIND_TURNS} consecutive automated turns without human input, so automatic delivery between minds has been paused. Send a message to resume.`
|
|
1858
|
+
}
|
|
1859
|
+
]);
|
|
1860
|
+
}
|
|
1861
|
+
async function fanOutToMinds(opts) {
|
|
1862
|
+
const participants = opts.participants ?? await getParticipants(opts.conversationId);
|
|
1863
|
+
const mindParticipants = participants.filter(
|
|
1864
|
+
(p) => p.userType === "mind" || p.userType === "system"
|
|
1865
|
+
);
|
|
1866
|
+
const participantNames = participants.map((p) => p.username);
|
|
1867
|
+
const isDM = opts.isDM ?? participants.length === 2;
|
|
1868
|
+
if (mindParticipants.length > 1) {
|
|
1869
|
+
if (opts.senderIsMind) {
|
|
1870
|
+
const count = (consecutiveMindTurns.get(opts.conversationId) ?? 0) + 1;
|
|
1871
|
+
consecutiveMindTurns.set(opts.conversationId, count);
|
|
1872
|
+
if (count > MAX_CONSECUTIVE_MIND_TURNS) {
|
|
1873
|
+
if (count === MAX_CONSECUTIVE_MIND_TURNS + 1) {
|
|
1874
|
+
await emitLoopNotice(opts.conversationId).catch(
|
|
1875
|
+
(err) => logger_default.warn(`failed to emit loop notice for ${opts.conversationId}`, logger_default.errorData(err))
|
|
1876
|
+
);
|
|
1877
|
+
}
|
|
1878
|
+
logger_default.warn(
|
|
1879
|
+
`loop protection: paused mind fan-out for ${opts.conversationId} after ${count} consecutive mind turns`
|
|
1880
|
+
);
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
1883
|
+
} else {
|
|
1884
|
+
consecutiveMindTurns.delete(opts.conversationId);
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
const manager = getMindManager();
|
|
1888
|
+
const sm = getSleepManagerIfReady();
|
|
1889
|
+
const targetMinds = mindParticipants.map((ap) => {
|
|
1890
|
+
const key = opts.targetName ? opts.targetName(ap.username) : ap.username;
|
|
1891
|
+
if (manager.isRunning(key) || sm?.isSleeping(ap.username)) return ap.username;
|
|
1892
|
+
return null;
|
|
1893
|
+
}).filter((n) => n !== null && n !== opts.senderName);
|
|
1894
|
+
for (const mindName of targetMinds) {
|
|
1895
|
+
const target = opts.targetName ? opts.targetName(mindName) : mindName;
|
|
1896
|
+
const channel = buildVoluteSlug({
|
|
1897
|
+
participants,
|
|
1898
|
+
mindUsername: mindName,
|
|
1899
|
+
conversationId: opts.conversationId,
|
|
1900
|
+
...opts.slugExtra
|
|
1901
|
+
});
|
|
1902
|
+
const typingMap = getTypingMap();
|
|
1903
|
+
const currentlyTyping = typingMap.get(channel).filter((name) => participantNames.includes(name));
|
|
1904
|
+
deliverMessage(target, {
|
|
1905
|
+
content: opts.contentBlocks,
|
|
1906
|
+
channel,
|
|
1907
|
+
conversationId: opts.conversationId,
|
|
1908
|
+
sender: opts.senderName,
|
|
1909
|
+
participants: participantNames,
|
|
1910
|
+
participantCount: participants.length,
|
|
1911
|
+
isDM,
|
|
1912
|
+
...currentlyTyping.length > 0 ? { typing: currentlyTyping } : {}
|
|
1913
|
+
}).catch((err) => {
|
|
1914
|
+
logger_default.warn(`fan-out delivery failed for ${target}`, logger_default.errorData(err));
|
|
1915
|
+
});
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1852
1919
|
// packages/daemon/src/web/api/bridges.ts
|
|
1853
1920
|
var inboundSchema = z3.object({
|
|
1854
1921
|
content: z3.array(
|
|
@@ -1922,7 +1989,7 @@ var app4 = new Hono4().post("/:platform/inbound", zValidator3("json", inboundSch
|
|
|
1922
1989
|
}
|
|
1923
1990
|
const participants = await getParticipants(channel.id);
|
|
1924
1991
|
if (!participants.some((p) => p.userId === puppet.id)) {
|
|
1925
|
-
const { addParticipant } = await import("./conversations-
|
|
1992
|
+
const { addParticipant } = await import("./conversations-67WWW25C.js");
|
|
1926
1993
|
await addParticipant(channel.id, puppet.id);
|
|
1927
1994
|
}
|
|
1928
1995
|
const contentBlocks = body.content;
|
|
@@ -2012,34 +2079,13 @@ var app4 = new Hono4().post("/:platform/inbound", zValidator3("json", inboundSch
|
|
|
2012
2079
|
return c.json(config2.channelMappings);
|
|
2013
2080
|
});
|
|
2014
2081
|
async function fanOutToBridgedMinds(opts) {
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
const targetMinds = mindParticipants.filter((ap) => {
|
|
2023
|
-
return (manager.isRunning(ap.username) || sm?.isSleeping(ap.username)) && ap.username !== opts.senderName;
|
|
2024
|
-
}).map((ap) => ap.username);
|
|
2025
|
-
for (const mindName of targetMinds) {
|
|
2026
|
-
const channel = buildVoluteSlug({
|
|
2027
|
-
participants,
|
|
2028
|
-
mindUsername: mindName,
|
|
2029
|
-
conversationId: opts.conversationId
|
|
2030
|
-
});
|
|
2031
|
-
deliverMessage(mindName, {
|
|
2032
|
-
content: opts.contentBlocks,
|
|
2033
|
-
channel,
|
|
2034
|
-
conversationId: opts.conversationId,
|
|
2035
|
-
sender: opts.senderName,
|
|
2036
|
-
participants: participantNames,
|
|
2037
|
-
participantCount: participants.length,
|
|
2038
|
-
isDM: opts.isDM
|
|
2039
|
-
}).catch((err) => {
|
|
2040
|
-
logger_default.warn(`bridge fan-out delivery failed for ${mindName}`, logger_default.errorData(err));
|
|
2041
|
-
});
|
|
2042
|
-
}
|
|
2082
|
+
await fanOutToMinds({
|
|
2083
|
+
conversationId: opts.conversationId,
|
|
2084
|
+
contentBlocks: opts.contentBlocks,
|
|
2085
|
+
senderName: opts.senderName,
|
|
2086
|
+
senderIsMind: false,
|
|
2087
|
+
isDM: opts.isDM
|
|
2088
|
+
});
|
|
2043
2089
|
}
|
|
2044
2090
|
var bridges_default = app4;
|
|
2045
2091
|
|
|
@@ -2082,7 +2128,7 @@ config.get("/models", async (c) => {
|
|
|
2082
2128
|
id: m.id,
|
|
2083
2129
|
name: m.name,
|
|
2084
2130
|
provider: m.provider,
|
|
2085
|
-
enabled: enabled.has(m.id)
|
|
2131
|
+
enabled: enabled.has(`${m.provider}:${m.id}`)
|
|
2086
2132
|
}));
|
|
2087
2133
|
return c.json(models);
|
|
2088
2134
|
});
|
|
@@ -2228,7 +2274,7 @@ async function notifyMind(mindName, message) {
|
|
|
2228
2274
|
const entry = await findMind(mindName);
|
|
2229
2275
|
if (!entry) return;
|
|
2230
2276
|
try {
|
|
2231
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
2277
|
+
const { sendSystemMessage } = await import("./system-chat-KMQIP7VH.js");
|
|
2232
2278
|
await sendSystemMessage(mindName, message);
|
|
2233
2279
|
} catch (err) {
|
|
2234
2280
|
logger_default.warn(`[file-sharing] notify mind ${mindName} failed`, logger_default.errorData(err));
|
|
@@ -3163,10 +3209,13 @@ import {
|
|
|
3163
3209
|
} from "fs";
|
|
3164
3210
|
import { basename, resolve as resolve11 } from "path";
|
|
3165
3211
|
import { zValidator as zValidator5 } from "@hono/zod-validator";
|
|
3166
|
-
import { and as
|
|
3212
|
+
import { and as and5, desc as desc4, eq as eq5, sql as sql3 } from "drizzle-orm";
|
|
3167
3213
|
import { Hono as Hono15 } from "hono";
|
|
3168
3214
|
import { z as z5 } from "zod";
|
|
3169
3215
|
|
|
3216
|
+
// packages/daemon/src/lib/daemon/turn-lifecycle.ts
|
|
3217
|
+
import { and as and4, desc as desc3, eq as eq4, inArray as inArray2, sql as sql2 } from "drizzle-orm";
|
|
3218
|
+
|
|
3170
3219
|
// packages/daemon/src/lib/daemon/error-classify.ts
|
|
3171
3220
|
function classify(raw) {
|
|
3172
3221
|
const s = (raw ?? "").toLowerCase();
|
|
@@ -3204,6 +3253,178 @@ function classify(raw) {
|
|
|
3204
3253
|
};
|
|
3205
3254
|
}
|
|
3206
3255
|
|
|
3256
|
+
// packages/daemon/src/lib/daemon/turn-lifecycle.ts
|
|
3257
|
+
var llog = logger_default.child("turn-lifecycle");
|
|
3258
|
+
var SUBSTANTIVE_TYPES = /* @__PURE__ */ new Set(["thinking", "text", "tool_use", "tool_result", "outbound"]);
|
|
3259
|
+
var MARKER_RE = /\[volute:(?:outbound|activity):\d+\]/g;
|
|
3260
|
+
var noticeDrainWatermarks = /* @__PURE__ */ new Map();
|
|
3261
|
+
function setNoticeDrainWatermark(mind, session, id) {
|
|
3262
|
+
noticeDrainWatermarks.set(`${mind}:${session}`, id);
|
|
3263
|
+
}
|
|
3264
|
+
function markDeliveredOnCleanTurn(mind, session) {
|
|
3265
|
+
if (!session) return;
|
|
3266
|
+
const wmKey = `${mind}:${session}`;
|
|
3267
|
+
const watermark = noticeDrainWatermarks.get(wmKey);
|
|
3268
|
+
noticeDrainWatermarks.delete(wmKey);
|
|
3269
|
+
const errored = takeErrored(mind, session);
|
|
3270
|
+
if (!errored && watermark != null) {
|
|
3271
|
+
clearDeliveredNotices(mind, session, watermark).catch(
|
|
3272
|
+
(err) => llog.warn(`failed to clear delivered notices for ${mind}:${session}`, logger_default.errorData(err))
|
|
3273
|
+
);
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
async function linkPendingInbound(mind, turnId, channel) {
|
|
3277
|
+
if (!channel) return;
|
|
3278
|
+
const db = await getDb();
|
|
3279
|
+
const recent = await db.select({ id: mindHistory.id }).from(mindHistory).where(
|
|
3280
|
+
and4(
|
|
3281
|
+
eq4(mindHistory.mind, mind),
|
|
3282
|
+
eq4(mindHistory.type, "inbound"),
|
|
3283
|
+
sql2`${mindHistory.turn_id} IS NULL`,
|
|
3284
|
+
eq4(mindHistory.channel, channel)
|
|
3285
|
+
)
|
|
3286
|
+
).orderBy(desc3(mindHistory.id)).limit(5);
|
|
3287
|
+
if (recent.length === 0) return;
|
|
3288
|
+
const ids = recent.map((r) => r.id);
|
|
3289
|
+
await db.update(mindHistory).set({ turn_id: turnId }).where(inArray2(mindHistory.id, ids));
|
|
3290
|
+
await db.update(turns).set({ trigger_event_id: recent[0].id }).where(eq4(turns.id, turnId));
|
|
3291
|
+
}
|
|
3292
|
+
async function handleMindEvent(mind, event) {
|
|
3293
|
+
if (event.type === "session_start" && event.session) {
|
|
3294
|
+
const activeTurnId = getActiveTurnId(mind);
|
|
3295
|
+
if (activeTurnId) await assignSession(mind, activeTurnId, event.session);
|
|
3296
|
+
}
|
|
3297
|
+
let turnId = getActiveTurnId(mind, event.session);
|
|
3298
|
+
if (!turnId && SUBSTANTIVE_TYPES.has(event.type)) {
|
|
3299
|
+
turnId = await createTurn(mind);
|
|
3300
|
+
if (!turnId) {
|
|
3301
|
+
llog.warn(`skipping turn tracking for ${mind}: createTurn failed`);
|
|
3302
|
+
} else {
|
|
3303
|
+
publish2(mind, { mind, type: "turn_created", turnId });
|
|
3304
|
+
if (event.session) await assignSession(mind, turnId, event.session);
|
|
3305
|
+
try {
|
|
3306
|
+
await linkPendingInbound(mind, turnId, event.channel);
|
|
3307
|
+
} catch (err) {
|
|
3308
|
+
llog.warn(
|
|
3309
|
+
`failed to link trigger inbound for turn ${turnId} (mind: ${mind})`,
|
|
3310
|
+
logger_default.errorData(err)
|
|
3311
|
+
);
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
const cleanContent = event.type === "tool_result" && event.content ? event.content.replace(MARKER_RE, "").trimEnd() : event.content;
|
|
3316
|
+
const db = await getDb();
|
|
3317
|
+
let insertedId;
|
|
3318
|
+
try {
|
|
3319
|
+
const result = await db.insert(mindHistory).values({
|
|
3320
|
+
mind,
|
|
3321
|
+
type: event.type,
|
|
3322
|
+
session: event.session ?? null,
|
|
3323
|
+
channel: event.channel ?? null,
|
|
3324
|
+
message_id: event.messageId ?? null,
|
|
3325
|
+
content: cleanContent ?? null,
|
|
3326
|
+
metadata: event.metadata ? JSON.stringify(event.metadata) : null,
|
|
3327
|
+
turn_id: turnId ?? null
|
|
3328
|
+
}).returning({ id: mindHistory.id });
|
|
3329
|
+
insertedId = result[0]?.id;
|
|
3330
|
+
} catch (err) {
|
|
3331
|
+
llog.error(`failed to persist event for ${mind}`, logger_default.errorData(err));
|
|
3332
|
+
}
|
|
3333
|
+
if (event.type === "tool_use" && insertedId != null) {
|
|
3334
|
+
trackToolUse(mind, event.session, insertedId);
|
|
3335
|
+
}
|
|
3336
|
+
if (event.type === "tool_result" && turnId && event.content) {
|
|
3337
|
+
const toolUseEventId = getLastToolUseEventId(mind, event.session);
|
|
3338
|
+
try {
|
|
3339
|
+
await linkToolResultToTurn(mind, turnId, event.content, toolUseEventId);
|
|
3340
|
+
} catch (err) {
|
|
3341
|
+
llog.error("failed to link tool_result to turn", logger_default.errorData(err));
|
|
3342
|
+
}
|
|
3343
|
+
}
|
|
3344
|
+
publish2(mind, {
|
|
3345
|
+
mind,
|
|
3346
|
+
type: event.type,
|
|
3347
|
+
session: event.session,
|
|
3348
|
+
channel: event.channel,
|
|
3349
|
+
messageId: event.messageId,
|
|
3350
|
+
content: cleanContent,
|
|
3351
|
+
metadata: event.metadata,
|
|
3352
|
+
turnId: turnId ?? void 0
|
|
3353
|
+
});
|
|
3354
|
+
if (event.type === "text" && event.channel && cleanContent) {
|
|
3355
|
+
echoTextToChannel(mind, event.channel, cleanContent, turnId ?? void 0, insertedId).catch(
|
|
3356
|
+
(err) => llog.error(`echo-text failed for ${mind} on ${event.channel}`, logger_default.errorData(err))
|
|
3357
|
+
);
|
|
3358
|
+
}
|
|
3359
|
+
onMindEvent(mind, event.type, event.channel);
|
|
3360
|
+
if ((event.type === "text" || event.type === "outbound") && event.channel) {
|
|
3361
|
+
const map = getTypingMap();
|
|
3362
|
+
publishTypingForChannels(map.deleteSender(mind), map);
|
|
3363
|
+
}
|
|
3364
|
+
if (event.type === "error" && event.session) {
|
|
3365
|
+
markErrored(mind, event.session);
|
|
3366
|
+
const { reason, detail } = classify(event.content ?? "");
|
|
3367
|
+
await recordNotice({
|
|
3368
|
+
mind,
|
|
3369
|
+
session: event.session,
|
|
3370
|
+
kind: "turn_error",
|
|
3371
|
+
reason,
|
|
3372
|
+
detail,
|
|
3373
|
+
raw: event.content ?? null
|
|
3374
|
+
});
|
|
3375
|
+
}
|
|
3376
|
+
if (event.type === "done") {
|
|
3377
|
+
const map = getTypingMap();
|
|
3378
|
+
publishTypingForChannels(map.deleteSender(mind), map);
|
|
3379
|
+
broadcast({ type: "mind_done", mind, summary: "Finished processing" });
|
|
3380
|
+
try {
|
|
3381
|
+
getDeliveryManager().sessionDone(mind, event.session);
|
|
3382
|
+
} catch (err) {
|
|
3383
|
+
if (!(err instanceof Error && err.message.includes("not initialized"))) {
|
|
3384
|
+
llog.error(`delivery manager sessionDone failed for ${mind}`, logger_default.errorData(err));
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
await completeTurnAndSummarize(mind, event, insertedId);
|
|
3388
|
+
}
|
|
3389
|
+
if (event.type === "usage" && event.metadata) {
|
|
3390
|
+
const inputTokens = event.metadata.input_tokens ?? 0;
|
|
3391
|
+
const outputTokens = event.metadata.output_tokens ?? 0;
|
|
3392
|
+
const tb = getTokenBudget();
|
|
3393
|
+
tb.recordUsage(mind, inputTokens, outputTokens);
|
|
3394
|
+
if (event.session && tb.noteExceeded(mind)) {
|
|
3395
|
+
void recordNotice({
|
|
3396
|
+
mind,
|
|
3397
|
+
session: event.session,
|
|
3398
|
+
kind: "budget",
|
|
3399
|
+
reason: "token_budget",
|
|
3400
|
+
detail: "You've reached your token budget for this period. Further activity may be paused until the budget resets \u2014 wrap up or prioritize accordingly."
|
|
3401
|
+
});
|
|
3402
|
+
}
|
|
3403
|
+
}
|
|
3404
|
+
return { turnId: turnId ?? void 0, insertedId };
|
|
3405
|
+
}
|
|
3406
|
+
async function completeTurnAndSummarize(mind, event, insertedId) {
|
|
3407
|
+
const finish = async () => {
|
|
3408
|
+
const completedTurnId = await completeTurn(mind, event.session);
|
|
3409
|
+
markDeliveredOnCleanTurn(mind, event.session);
|
|
3410
|
+
if (insertedId != null) {
|
|
3411
|
+
summarizeTurn(mind, event.session, event.channel, insertedId, completedTurnId).catch(
|
|
3412
|
+
(err) => llog.error("turn summarization failed", logger_default.errorData(err))
|
|
3413
|
+
);
|
|
3414
|
+
}
|
|
3415
|
+
};
|
|
3416
|
+
try {
|
|
3417
|
+
const dm = getDeliveryManager();
|
|
3418
|
+
const busy = event.session ? dm.isSessionBusy(mind, event.session) : false;
|
|
3419
|
+
if (!busy) await finish();
|
|
3420
|
+
} catch (err) {
|
|
3421
|
+
if (!(err instanceof Error && err.message.includes("not initialized"))) {
|
|
3422
|
+
llog.error("turn completion check failed", logger_default.errorData(err));
|
|
3423
|
+
}
|
|
3424
|
+
await finish();
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
|
|
3207
3428
|
// packages/daemon/src/lib/mind/consolidate.ts
|
|
3208
3429
|
import { readdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
3209
3430
|
import { resolve as resolve9 } from "path";
|
|
@@ -3275,6 +3496,39 @@ ${content2}`);
|
|
|
3275
3496
|
}
|
|
3276
3497
|
}
|
|
3277
3498
|
|
|
3499
|
+
// packages/daemon/src/lib/mind/last-known-good.ts
|
|
3500
|
+
import { randomBytes } from "crypto";
|
|
3501
|
+
var glog = logger_default.child("last-known-good");
|
|
3502
|
+
async function hasSrcChanges(dir, mindName) {
|
|
3503
|
+
const status = (await gitExec(["status", "--porcelain", "--", "src"], { cwd: dir, mindName })).trim();
|
|
3504
|
+
return status.length > 0;
|
|
3505
|
+
}
|
|
3506
|
+
async function rollbackSrcChanges(dir, mindName) {
|
|
3507
|
+
if (!await hasSrcChanges(dir, mindName)) return { parked: false };
|
|
3508
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3509
|
+
const branch = `broken/${ts}-${randomBytes(4).toString("hex")}`;
|
|
3510
|
+
const opts = { cwd: dir, mindName };
|
|
3511
|
+
await gitExec(["add", "--", "src"], opts);
|
|
3512
|
+
await gitExec(
|
|
3513
|
+
["commit", "--only", "-m", `Parked broken src changes (${branch})`, "--", "src"],
|
|
3514
|
+
opts
|
|
3515
|
+
);
|
|
3516
|
+
const brokenHash = (await gitExec(["rev-parse", "HEAD"], opts)).trim();
|
|
3517
|
+
await gitExec(["reset", "--mixed", "HEAD~1"], opts);
|
|
3518
|
+
await gitExec(["branch", branch, brokenHash], opts);
|
|
3519
|
+
await gitExec(["checkout", "--", "src"], opts);
|
|
3520
|
+
await gitExec(["clean", "-fdq", "--", "src"], opts);
|
|
3521
|
+
glog.info(`parked broken src changes on ${branch} (${dir})`);
|
|
3522
|
+
return { parked: true, branch };
|
|
3523
|
+
}
|
|
3524
|
+
async function commitSrcChanges(dir, mindName) {
|
|
3525
|
+
if (!await hasSrcChanges(dir, mindName)) return;
|
|
3526
|
+
const opts = { cwd: dir, mindName };
|
|
3527
|
+
await gitExec(["add", "--", "src"], opts);
|
|
3528
|
+
await gitExec(["commit", "--only", "-m", "Update src (self-edit)", "--", "src"], opts);
|
|
3529
|
+
glog.info(`committed known-good src changes (${dir})`);
|
|
3530
|
+
}
|
|
3531
|
+
|
|
3278
3532
|
// packages/daemon/src/lib/mind/variant-cleanup.ts
|
|
3279
3533
|
import { existsSync as existsSync6, rmSync as rmSync3 } from "fs";
|
|
3280
3534
|
async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
|
|
@@ -3285,7 +3539,7 @@ async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
|
|
|
3285
3539
|
logger_default.warn(`failed to stop variant ${variantName}`, logger_default.errorData(err));
|
|
3286
3540
|
}
|
|
3287
3541
|
}
|
|
3288
|
-
const { findMind: findMind2 } = await import("./registry-
|
|
3542
|
+
const { findMind: findMind2 } = await import("./registry-7LQHTRUX.js");
|
|
3289
3543
|
const variantEntry = await findMind2(variantName);
|
|
3290
3544
|
const branchName = variantEntry?.branch ?? variantName;
|
|
3291
3545
|
if (existsSync6(variantPath)) {
|
|
@@ -3312,7 +3566,7 @@ async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
|
|
|
3312
3566
|
logger_default.warn(`failed to remove variant ${variantName} from DB`, logger_default.errorData(err));
|
|
3313
3567
|
}
|
|
3314
3568
|
try {
|
|
3315
|
-
chownMindDir(projectRoot, baseName);
|
|
3569
|
+
await chownMindDir(projectRoot, baseName);
|
|
3316
3570
|
} catch (err) {
|
|
3317
3571
|
logger_default.error(
|
|
3318
3572
|
`failed to fix ownership during variant cleanup for ${variantName}`,
|
|
@@ -3507,42 +3761,14 @@ function convertAssistantContent(content) {
|
|
|
3507
3761
|
return result;
|
|
3508
3762
|
}
|
|
3509
3763
|
|
|
3510
|
-
// packages/daemon/src/lib/util/health.ts
|
|
3511
|
-
async function checkHealth(port) {
|
|
3512
|
-
try {
|
|
3513
|
-
const res = await fetch(`http://127.0.0.1:${port}/health`, {
|
|
3514
|
-
signal: AbortSignal.timeout(2e3)
|
|
3515
|
-
});
|
|
3516
|
-
if (!res.ok) return { ok: false };
|
|
3517
|
-
const data = await res.json();
|
|
3518
|
-
return { ok: true, name: data.name };
|
|
3519
|
-
} catch {
|
|
3520
|
-
return { ok: false };
|
|
3521
|
-
}
|
|
3522
|
-
}
|
|
3523
|
-
|
|
3524
3764
|
// packages/daemon/src/web/api/minds.ts
|
|
3525
|
-
var SUBSTANTIVE_TYPES = /* @__PURE__ */ new Set(["thinking", "text", "tool_use", "tool_result", "outbound"]);
|
|
3526
|
-
var noticeDrainWatermarks = /* @__PURE__ */ new Map();
|
|
3527
|
-
function markDeliveredOnCleanTurn(mind, session) {
|
|
3528
|
-
if (!session) return;
|
|
3529
|
-
const wmKey = `${mind}:${session}`;
|
|
3530
|
-
const watermark = noticeDrainWatermarks.get(wmKey);
|
|
3531
|
-
noticeDrainWatermarks.delete(wmKey);
|
|
3532
|
-
const errored = takeErrored(mind, session);
|
|
3533
|
-
if (!errored && watermark != null) {
|
|
3534
|
-
clearDeliveredNotices(mind, session, watermark).catch(
|
|
3535
|
-
(err) => logger_default.warn(`failed to clear delivered notices for ${mind}:${session}`, logger_default.errorData(err))
|
|
3536
|
-
);
|
|
3537
|
-
}
|
|
3538
|
-
}
|
|
3539
3765
|
var _lastActiveCache = { map: /* @__PURE__ */ new Map(), ts: 0 };
|
|
3540
3766
|
var _LAST_ACTIVE_TTL = 6e4;
|
|
3541
3767
|
async function getMindStatus(name, port, registryRunning) {
|
|
3542
3768
|
const manager = getMindManager();
|
|
3543
3769
|
let status = "stopped";
|
|
3544
3770
|
try {
|
|
3545
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
3771
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BVU5D2AE.js");
|
|
3546
3772
|
if (getSleepManagerIfReady2()?.isSleeping(name)) {
|
|
3547
3773
|
status = "sleeping";
|
|
3548
3774
|
}
|
|
@@ -3703,7 +3929,7 @@ async function mergeUpgradeAndRestart(mindName, dir, worktreeDir, upgradeVariant
|
|
|
3703
3929
|
cwd: dir
|
|
3704
3930
|
});
|
|
3705
3931
|
}
|
|
3706
|
-
chownMindDir(dir, mindName);
|
|
3932
|
+
await chownMindDir(dir, mindName);
|
|
3707
3933
|
switchWarning = `Switched ${oldTemplate}\u2192${template}: config reset to ${template} defaults, mechanics doc replaced, conversation starts fresh (sessions aren't portable across runtimes).`;
|
|
3708
3934
|
} catch (err) {
|
|
3709
3935
|
logger_default.warn(`failed to swap template home files for ${mindName}`, logger_default.errorData(err));
|
|
@@ -3785,7 +4011,7 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
|
|
|
3785
4011
|
const homeDir = resolve11(dest, "home");
|
|
3786
4012
|
ensureVoluteGroup();
|
|
3787
4013
|
createMindUser(name, homeDir);
|
|
3788
|
-
chownMindDir(dest, name);
|
|
4014
|
+
await chownMindDir(dest, name);
|
|
3789
4015
|
await npmInstallAsMind(dest, name);
|
|
3790
4016
|
await importHistoryFromArchive(name, tempDir);
|
|
3791
4017
|
importSessionsFromArchive(dest, tempDir);
|
|
@@ -3801,7 +4027,7 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
|
|
|
3801
4027
|
rmSync4(resolve11(dest, ".git"), { recursive: true, force: true });
|
|
3802
4028
|
}
|
|
3803
4029
|
}
|
|
3804
|
-
chownMindDir(dest, name);
|
|
4030
|
+
await chownMindDir(dest, name);
|
|
3805
4031
|
rmSync4(tempDir, { recursive: true, force: true });
|
|
3806
4032
|
return c.json({ ok: true, name, port, message: `Imported mind: ${name} (port ${port})` });
|
|
3807
4033
|
} catch (err) {
|
|
@@ -3863,7 +4089,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
3863
4089
|
const homeDir = resolve11(dest, "home");
|
|
3864
4090
|
ensureVoluteGroup();
|
|
3865
4091
|
createMindUser(name, homeDir);
|
|
3866
|
-
chownMindDir(dest, name);
|
|
4092
|
+
await chownMindDir(dest, name);
|
|
3867
4093
|
await npmInstallAsMind(dest, name);
|
|
3868
4094
|
let gitWarning;
|
|
3869
4095
|
try {
|
|
@@ -3888,7 +4114,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
3888
4114
|
}
|
|
3889
4115
|
await importHistoryFromArchive(name, tempDir);
|
|
3890
4116
|
importSessionsFromArchive(dest, tempDir);
|
|
3891
|
-
chownMindDir(dest, name);
|
|
4117
|
+
await chownMindDir(dest, name);
|
|
3892
4118
|
publishPublicKey(name, publicKeyPem).catch(
|
|
3893
4119
|
(err) => logger_default.warn(`failed to publish key for ${name}`, { error: err.message })
|
|
3894
4120
|
);
|
|
@@ -4037,7 +4263,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4037
4263
|
applyInitFiles(dest);
|
|
4038
4264
|
const { publicKeyPem } = generateIdentity(dest);
|
|
4039
4265
|
{
|
|
4040
|
-
const { readGlobalConfig: readGlobal } = await import("./setup-
|
|
4266
|
+
const { readGlobalConfig: readGlobal } = await import("./setup-25MMJ3J4.js");
|
|
4041
4267
|
const mindDefaults = readGlobal().mindDefaults;
|
|
4042
4268
|
const config2 = readVoluteConfig(dest);
|
|
4043
4269
|
if (!config2) throw new Error("Failed to read volute.json after identity generation");
|
|
@@ -4104,7 +4330,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4104
4330
|
const homeDir = resolve11(dest, "home");
|
|
4105
4331
|
ensureVoluteGroup();
|
|
4106
4332
|
createMindUser(name, homeDir);
|
|
4107
|
-
chownMindDir(dest, name);
|
|
4333
|
+
await chownMindDir(dest, name);
|
|
4108
4334
|
await npmInstallAsMind(dest, name);
|
|
4109
4335
|
let gitWarning;
|
|
4110
4336
|
try {
|
|
@@ -4117,7 +4343,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4117
4343
|
rmSync4(resolve11(dest, ".git"), { recursive: true, force: true });
|
|
4118
4344
|
gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
|
|
4119
4345
|
}
|
|
4120
|
-
chownMindDir(dest, name);
|
|
4346
|
+
await chownMindDir(dest, name);
|
|
4121
4347
|
if (body.stage === "seed") {
|
|
4122
4348
|
const descLine = body.description ? `
|
|
4123
4349
|
The human who planted you described you as: "${body.description}"
|
|
@@ -4128,7 +4354,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4128
4354
|
}
|
|
4129
4355
|
let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
|
|
4130
4356
|
if (body.stage === "seed" && !body.skills) {
|
|
4131
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
4357
|
+
const { isImagegenEnabled } = await import("./setup-25MMJ3J4.js");
|
|
4132
4358
|
if (isImagegenEnabled()) {
|
|
4133
4359
|
skillSet = [...skillSet, "imagegen"];
|
|
4134
4360
|
}
|
|
@@ -4146,7 +4372,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4146
4372
|
try {
|
|
4147
4373
|
const spiritEntry = await findMind("volute");
|
|
4148
4374
|
if (spiritEntry) {
|
|
4149
|
-
const { spiritDir } = await import("./spirit-
|
|
4375
|
+
const { spiritDir } = await import("./spirit-JQQHUVWR.js");
|
|
4150
4376
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
4151
4377
|
const spiritConfig = readVoluteConfig(sDir) ?? {};
|
|
4152
4378
|
const schedules = spiritConfig.schedules ?? [];
|
|
@@ -4161,7 +4387,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4161
4387
|
});
|
|
4162
4388
|
spiritConfig.schedules = schedules;
|
|
4163
4389
|
writeVoluteConfig(sDir, spiritConfig);
|
|
4164
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
4390
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-BR6C6B3E.js");
|
|
4165
4391
|
getScheduler2().loadSchedules("volute", sDir);
|
|
4166
4392
|
}
|
|
4167
4393
|
}
|
|
@@ -4291,7 +4517,7 @@ ${user.trimEnd()}
|
|
|
4291
4517
|
const homeDir = resolve11(dest, "home");
|
|
4292
4518
|
ensureVoluteGroup();
|
|
4293
4519
|
createMindUser(name, homeDir);
|
|
4294
|
-
chownMindDir(dest, name);
|
|
4520
|
+
await chownMindDir(dest, name);
|
|
4295
4521
|
await npmInstallAsMind(dest, name);
|
|
4296
4522
|
if (!hasMemory && dailyLogCount > 0) {
|
|
4297
4523
|
await consolidateMemory(dest);
|
|
@@ -4313,7 +4539,7 @@ ${user.trimEnd()}
|
|
|
4313
4539
|
}
|
|
4314
4540
|
}
|
|
4315
4541
|
importOpenClawConnectors(name, dest);
|
|
4316
|
-
chownMindDir(dest, name);
|
|
4542
|
+
await chownMindDir(dest, name);
|
|
4317
4543
|
publishPublicKey(name, importPublicKey).catch(
|
|
4318
4544
|
(err) => logger_default.warn(`failed to publish key for ${name}`, { error: err.message })
|
|
4319
4545
|
);
|
|
@@ -4339,7 +4565,7 @@ ${user.trimEnd()}
|
|
|
4339
4565
|
const db = await getDb();
|
|
4340
4566
|
const lastActiveRows = await db.select({
|
|
4341
4567
|
mind: mindHistory.mind,
|
|
4342
|
-
lastActiveAt:
|
|
4568
|
+
lastActiveAt: sql3`MAX(${mindHistory.created_at})`
|
|
4343
4569
|
}).from(mindHistory).groupBy(mindHistory.mind);
|
|
4344
4570
|
lastActiveMap = new Map(lastActiveRows.map((r) => [r.mind, r.lastActiveAt]));
|
|
4345
4571
|
_lastActiveCache.map = lastActiveMap;
|
|
@@ -4426,7 +4652,7 @@ ${user.trimEnd()}
|
|
|
4426
4652
|
const manager = getMindManager();
|
|
4427
4653
|
try {
|
|
4428
4654
|
if (context?.type === "reload") {
|
|
4429
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4655
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BVU5D2AE.js");
|
|
4430
4656
|
const sleepState = getSleepManagerIfReady2()?.getState(name);
|
|
4431
4657
|
if (sleepState?.sleeping) {
|
|
4432
4658
|
logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
|
|
@@ -4498,7 +4724,39 @@ ${user.trimEnd()}
|
|
|
4498
4724
|
logger_default.error(`failed to inject sprouted message for ${baseName}`, logger_default.errorData(err));
|
|
4499
4725
|
}
|
|
4500
4726
|
}
|
|
4501
|
-
|
|
4727
|
+
const repoDir = entry.parent ? entry.dir : mindDir(name);
|
|
4728
|
+
try {
|
|
4729
|
+
await startMindFull(name);
|
|
4730
|
+
} catch (startErr) {
|
|
4731
|
+
const stderr = startErr instanceof MindStartupError ? startErr.stderr : void 0;
|
|
4732
|
+
let rollback = { parked: false };
|
|
4733
|
+
try {
|
|
4734
|
+
rollback = await rollbackSrcChanges(repoDir, name);
|
|
4735
|
+
} catch (rbErr) {
|
|
4736
|
+
logger_default.error(`failed to roll back src changes for ${name}`, logger_default.errorData(rbErr));
|
|
4737
|
+
}
|
|
4738
|
+
if (!rollback.parked) throw startErr;
|
|
4739
|
+
await startMindFull(name);
|
|
4740
|
+
const startMsg = startErr instanceof Error ? startErr.message : String(startErr);
|
|
4741
|
+
const errLine = (stderr ?? startMsg).trim().split("\n").filter(Boolean).pop() ?? "";
|
|
4742
|
+
await recordNotice({
|
|
4743
|
+
mind: name,
|
|
4744
|
+
session: "main",
|
|
4745
|
+
kind: "startup",
|
|
4746
|
+
reason: "startup_failed",
|
|
4747
|
+
detail: `Your last change to src/ broke startup, so it was rolled back and your previous working code was restored. The broken change is preserved on branch \`${rollback.branch}\` \u2014 check it out to inspect and fix it. Error: ${errLine}`,
|
|
4748
|
+
raw: stderr ?? null
|
|
4749
|
+
});
|
|
4750
|
+
return c.json({
|
|
4751
|
+
ok: true,
|
|
4752
|
+
recovered: true,
|
|
4753
|
+
brokenBranch: rollback.branch,
|
|
4754
|
+
port: targetPort
|
|
4755
|
+
});
|
|
4756
|
+
}
|
|
4757
|
+
await commitSrcChanges(repoDir, name).catch(
|
|
4758
|
+
(e) => logger_default.error(`failed to commit known-good src for ${name}`, logger_default.errorData(e))
|
|
4759
|
+
);
|
|
4502
4760
|
return c.json({ ok: true, port: targetPort });
|
|
4503
4761
|
} catch (err) {
|
|
4504
4762
|
return c.json({ error: err instanceof Error ? err.message : "Failed to restart mind" }, 500);
|
|
@@ -4521,7 +4779,7 @@ ${user.trimEnd()}
|
|
|
4521
4779
|
const name = c.req.param("name");
|
|
4522
4780
|
const entry = await findMind(name);
|
|
4523
4781
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4524
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4782
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BVU5D2AE.js");
|
|
4525
4783
|
const sm = getSleepManagerIfReady2();
|
|
4526
4784
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4527
4785
|
return c.json(sm.getState(name));
|
|
@@ -4529,7 +4787,7 @@ ${user.trimEnd()}
|
|
|
4529
4787
|
const name = c.req.param("name");
|
|
4530
4788
|
const entry = await findMind(name);
|
|
4531
4789
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4532
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4790
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BVU5D2AE.js");
|
|
4533
4791
|
const sm = getSleepManagerIfReady2();
|
|
4534
4792
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4535
4793
|
if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
|
|
@@ -4549,7 +4807,7 @@ ${user.trimEnd()}
|
|
|
4549
4807
|
const name = c.req.param("name");
|
|
4550
4808
|
const entry = await findMind(name);
|
|
4551
4809
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4552
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4810
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BVU5D2AE.js");
|
|
4553
4811
|
const sm = getSleepManagerIfReady2();
|
|
4554
4812
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4555
4813
|
const sleepState = sm.getState(name);
|
|
@@ -4564,7 +4822,7 @@ ${user.trimEnd()}
|
|
|
4564
4822
|
const name = c.req.param("name");
|
|
4565
4823
|
const entry = await findMind(name);
|
|
4566
4824
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4567
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4825
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-BVU5D2AE.js");
|
|
4568
4826
|
const sm = getSleepManagerIfReady2();
|
|
4569
4827
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4570
4828
|
const flushed = await sm.flushQueuedMessages(name);
|
|
@@ -4582,7 +4840,7 @@ ${user.trimEnd()}
|
|
|
4582
4840
|
if (body.avatar !== void 0) profile.avatar = basename(body.avatar);
|
|
4583
4841
|
config2.profile = profile;
|
|
4584
4842
|
writeVoluteConfig(dir, config2);
|
|
4585
|
-
const { syncMindProfile: syncMindProfile2 } = await import("./auth-
|
|
4843
|
+
const { syncMindProfile: syncMindProfile2 } = await import("./auth-3RIG6GKN.js");
|
|
4586
4844
|
await syncMindProfile2(name, profile);
|
|
4587
4845
|
broadcast({ type: "profile_updated", mind: name, summary: `${name} profile updated` });
|
|
4588
4846
|
return c.json({ ok: true });
|
|
@@ -4598,21 +4856,21 @@ ${user.trimEnd()}
|
|
|
4598
4856
|
const rawSpirit = Number(process.env.VOLUTE_NURTURE_SPIRIT_MINUTES);
|
|
4599
4857
|
const spiritThreshold = Number.isNaN(rawSpirit) ? 15 : rawSpirit;
|
|
4600
4858
|
const lastCreatorMsg = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4859
|
+
and5(
|
|
4860
|
+
eq5(mindHistory.mind, name),
|
|
4861
|
+
eq5(mindHistory.type, "inbound"),
|
|
4862
|
+
sql3`${mindHistory.sender} != 'volute'`,
|
|
4863
|
+
sql3`${mindHistory.sender} != ${name}`,
|
|
4864
|
+
sql3`${mindHistory.sender} IS NOT NULL`
|
|
4607
4865
|
)
|
|
4608
|
-
).orderBy(
|
|
4866
|
+
).orderBy(desc4(mindHistory.created_at)).limit(1);
|
|
4609
4867
|
const lastSpiritMsg = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4868
|
+
and5(
|
|
4869
|
+
eq5(mindHistory.mind, name),
|
|
4870
|
+
eq5(mindHistory.type, "inbound"),
|
|
4871
|
+
eq5(mindHistory.sender, "volute")
|
|
4614
4872
|
)
|
|
4615
|
-
).orderBy(
|
|
4873
|
+
).orderBy(desc4(mindHistory.created_at)).limit(1);
|
|
4616
4874
|
const now = Date.now();
|
|
4617
4875
|
const creatorTime = lastCreatorMsg[0] ? new Date(lastCreatorMsg[0].created_at).getTime() : 0;
|
|
4618
4876
|
const spiritTime = lastSpiritMsg[0] ? new Date(lastSpiritMsg[0].created_at).getTime() : 0;
|
|
@@ -4629,7 +4887,7 @@ ${user.trimEnd()}
|
|
|
4629
4887
|
const config2 = readVoluteConfig(dir);
|
|
4630
4888
|
const displayNameSet = !!config2?.profile?.displayName;
|
|
4631
4889
|
const avatarSet = !!config2?.profile?.avatar;
|
|
4632
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
4890
|
+
const { isImagegenEnabled } = await import("./setup-25MMJ3J4.js");
|
|
4633
4891
|
const imagegenEnabled = isImagegenEnabled();
|
|
4634
4892
|
const done = [];
|
|
4635
4893
|
const remaining = [];
|
|
@@ -4667,7 +4925,7 @@ ${user.trimEnd()}
|
|
|
4667
4925
|
try {
|
|
4668
4926
|
const spiritEntry = await findMind("volute");
|
|
4669
4927
|
if (spiritEntry) {
|
|
4670
|
-
const { spiritDir } = await import("./spirit-
|
|
4928
|
+
const { spiritDir } = await import("./spirit-JQQHUVWR.js");
|
|
4671
4929
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
4672
4930
|
const spiritConfig = readVoluteConfig(sDir);
|
|
4673
4931
|
if (spiritConfig?.schedules) {
|
|
@@ -4675,7 +4933,7 @@ ${user.trimEnd()}
|
|
|
4675
4933
|
spiritConfig.schedules = spiritConfig.schedules.filter((s) => s.id !== nurtureId);
|
|
4676
4934
|
if (spiritConfig.schedules.length === 0) spiritConfig.schedules = void 0;
|
|
4677
4935
|
writeVoluteConfig(sDir, spiritConfig);
|
|
4678
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
4936
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-BR6C6B3E.js");
|
|
4679
4937
|
getScheduler2().loadSchedules("volute", sDir);
|
|
4680
4938
|
}
|
|
4681
4939
|
}
|
|
@@ -4792,7 +5050,7 @@ ${user.trimEnd()}
|
|
|
4792
5050
|
cwd: worktreeDir
|
|
4793
5051
|
});
|
|
4794
5052
|
}
|
|
4795
|
-
chownMindDir(dir, mindName);
|
|
5053
|
+
await chownMindDir(dir, mindName);
|
|
4796
5054
|
try {
|
|
4797
5055
|
const result = await mergeUpgradeAndRestart(
|
|
4798
5056
|
mindName,
|
|
@@ -4858,7 +5116,7 @@ ${user.trimEnd()}
|
|
|
4858
5116
|
await configureGitIdentity(mindName, { cwd: dir, mindName, env });
|
|
4859
5117
|
await gitExec(["add", "-A"], { cwd: dir, mindName, env });
|
|
4860
5118
|
await gitExec(["commit", "-m", "initial commit"], { cwd: dir, mindName, env });
|
|
4861
|
-
chownMindDir(dir, mindName);
|
|
5119
|
+
await chownMindDir(dir, mindName);
|
|
4862
5120
|
} catch (err) {
|
|
4863
5121
|
rmSync4(resolve11(dir, ".git"), { recursive: true, force: true });
|
|
4864
5122
|
return c.json(
|
|
@@ -4917,7 +5175,7 @@ ${user.trimEnd()}
|
|
|
4917
5175
|
});
|
|
4918
5176
|
}
|
|
4919
5177
|
}
|
|
4920
|
-
chownMindDir(dir, mindName);
|
|
5178
|
+
await chownMindDir(dir, mindName);
|
|
4921
5179
|
if (hasConflicts) {
|
|
4922
5180
|
return c.json({
|
|
4923
5181
|
ok: false,
|
|
@@ -5110,7 +5368,7 @@ ${user.trimEnd()}
|
|
|
5110
5368
|
}
|
|
5111
5369
|
writeVoluteConfig(dir, existing);
|
|
5112
5370
|
if (body.unescapeNewlines !== void 0) {
|
|
5113
|
-
const { clearEchoTextCache } = await import("./echo-text-
|
|
5371
|
+
const { clearEchoTextCache } = await import("./echo-text-XKBJM6RV.js");
|
|
5114
5372
|
clearEchoTextCache(name);
|
|
5115
5373
|
}
|
|
5116
5374
|
const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.maxThinkingTokens !== void 0 || body.compaction !== void 0;
|
|
@@ -5187,7 +5445,7 @@ ${user.trimEnd()}
|
|
|
5187
5445
|
}
|
|
5188
5446
|
if (entry.mindType === "spirit" && body.model !== void 0) {
|
|
5189
5447
|
try {
|
|
5190
|
-
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-
|
|
5448
|
+
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-25MMJ3J4.js");
|
|
5191
5449
|
const globalConfig = readGlobalConfig2();
|
|
5192
5450
|
globalConfig.spiritModel = body.model;
|
|
5193
5451
|
writeGlobalConfig2(globalConfig);
|
|
@@ -5215,7 +5473,7 @@ ${user.trimEnd()}
|
|
|
5215
5473
|
if (!body.systemPrompt || !body.message) {
|
|
5216
5474
|
return c.json({ error: "systemPrompt and message required" }, 400);
|
|
5217
5475
|
}
|
|
5218
|
-
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-
|
|
5476
|
+
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-FBCCEYF5.js");
|
|
5219
5477
|
if (!isAiConfigured()) {
|
|
5220
5478
|
return c.json({ error: "AI service not configured" }, 503);
|
|
5221
5479
|
}
|
|
@@ -5236,166 +5494,7 @@ ${user.trimEnd()}
|
|
|
5236
5494
|
if (!body.type) {
|
|
5237
5495
|
return c.json({ error: "type required" }, 400);
|
|
5238
5496
|
}
|
|
5239
|
-
|
|
5240
|
-
const activeTurnId = getActiveTurnId(baseName);
|
|
5241
|
-
if (activeTurnId) {
|
|
5242
|
-
await assignSession(baseName, activeTurnId, body.session);
|
|
5243
|
-
}
|
|
5244
|
-
}
|
|
5245
|
-
let turnId = getActiveTurnId(baseName, body.session);
|
|
5246
|
-
if (!turnId && SUBSTANTIVE_TYPES.has(body.type)) {
|
|
5247
|
-
turnId = await createTurn(baseName);
|
|
5248
|
-
if (!turnId) {
|
|
5249
|
-
logger_default.warn(`skipping turn tracking for ${baseName}: createTurn failed`);
|
|
5250
|
-
} else {
|
|
5251
|
-
publish2(baseName, { mind: baseName, type: "turn_created", turnId });
|
|
5252
|
-
if (body.session) {
|
|
5253
|
-
await assignSession(baseName, turnId, body.session);
|
|
5254
|
-
}
|
|
5255
|
-
try {
|
|
5256
|
-
await tagUntaggedInbound(baseName, turnId, {
|
|
5257
|
-
setTrigger: true,
|
|
5258
|
-
channel: body.channel
|
|
5259
|
-
});
|
|
5260
|
-
} catch (err) {
|
|
5261
|
-
logger_default.warn(
|
|
5262
|
-
`failed to link trigger/tag inbounds for turn ${turnId} (mind: ${baseName})`,
|
|
5263
|
-
logger_default.errorData(err)
|
|
5264
|
-
);
|
|
5265
|
-
}
|
|
5266
|
-
}
|
|
5267
|
-
}
|
|
5268
|
-
const MARKER_RE = /\[volute:(?:outbound|activity):\d+\]/g;
|
|
5269
|
-
const cleanContent = body.type === "tool_result" && body.content ? body.content.replace(MARKER_RE, "").trimEnd() : body.content;
|
|
5270
|
-
const db = await getDb();
|
|
5271
|
-
let insertedId;
|
|
5272
|
-
try {
|
|
5273
|
-
const result = await db.insert(mindHistory).values({
|
|
5274
|
-
mind: baseName,
|
|
5275
|
-
type: body.type,
|
|
5276
|
-
session: body.session ?? null,
|
|
5277
|
-
channel: body.channel ?? null,
|
|
5278
|
-
message_id: body.messageId ?? null,
|
|
5279
|
-
content: cleanContent ?? null,
|
|
5280
|
-
metadata: body.metadata ? JSON.stringify(body.metadata) : null,
|
|
5281
|
-
turn_id: turnId ?? null
|
|
5282
|
-
}).returning({ id: mindHistory.id });
|
|
5283
|
-
insertedId = result[0]?.id;
|
|
5284
|
-
} catch (err) {
|
|
5285
|
-
logger_default.error(`failed to persist event for ${baseName}`, logger_default.errorData(err));
|
|
5286
|
-
}
|
|
5287
|
-
if (body.type === "tool_use" && insertedId != null) {
|
|
5288
|
-
trackToolUse(baseName, body.session, insertedId);
|
|
5289
|
-
}
|
|
5290
|
-
if (body.type === "tool_result" && turnId && body.content) {
|
|
5291
|
-
const toolUseEventId = getLastToolUseEventId(baseName, body.session);
|
|
5292
|
-
try {
|
|
5293
|
-
await linkToolResultToTurn(baseName, turnId, body.content, toolUseEventId);
|
|
5294
|
-
} catch (err) {
|
|
5295
|
-
logger_default.error("failed to link outbound to turn", logger_default.errorData(err));
|
|
5296
|
-
}
|
|
5297
|
-
}
|
|
5298
|
-
publish2(baseName, {
|
|
5299
|
-
mind: baseName,
|
|
5300
|
-
type: body.type,
|
|
5301
|
-
session: body.session,
|
|
5302
|
-
channel: body.channel,
|
|
5303
|
-
messageId: body.messageId,
|
|
5304
|
-
content: cleanContent,
|
|
5305
|
-
metadata: body.metadata,
|
|
5306
|
-
turnId: turnId ?? void 0
|
|
5307
|
-
});
|
|
5308
|
-
if (body.type === "text" && body.channel && cleanContent) {
|
|
5309
|
-
echoTextToChannel(
|
|
5310
|
-
baseName,
|
|
5311
|
-
body.channel,
|
|
5312
|
-
cleanContent,
|
|
5313
|
-
turnId ?? void 0,
|
|
5314
|
-
insertedId
|
|
5315
|
-
).catch(
|
|
5316
|
-
(err) => logger_default.error(`echo-text failed for ${baseName} on ${body.channel}`, logger_default.errorData(err))
|
|
5317
|
-
);
|
|
5318
|
-
}
|
|
5319
|
-
onMindEvent(baseName, body.type, body.channel);
|
|
5320
|
-
if ((body.type === "text" || body.type === "outbound") && body.channel) {
|
|
5321
|
-
const map = getTypingMap();
|
|
5322
|
-
const affected = map.deleteSender(baseName);
|
|
5323
|
-
publishTypingForChannels(affected, map);
|
|
5324
|
-
}
|
|
5325
|
-
if (body.type === "error" && body.session) {
|
|
5326
|
-
markErrored(baseName, body.session);
|
|
5327
|
-
const { reason, detail } = classify(body.content ?? "");
|
|
5328
|
-
await recordNotice({
|
|
5329
|
-
mind: baseName,
|
|
5330
|
-
session: body.session,
|
|
5331
|
-
kind: "turn_error",
|
|
5332
|
-
reason,
|
|
5333
|
-
detail,
|
|
5334
|
-
raw: body.content ?? null
|
|
5335
|
-
});
|
|
5336
|
-
}
|
|
5337
|
-
if (body.type === "done") {
|
|
5338
|
-
const map = getTypingMap();
|
|
5339
|
-
const affected = map.deleteSender(baseName);
|
|
5340
|
-
publishTypingForChannels(affected, map);
|
|
5341
|
-
broadcast({ type: "mind_done", mind: baseName, summary: "Finished processing" });
|
|
5342
|
-
try {
|
|
5343
|
-
getDeliveryManager().sessionDone(baseName, body.session);
|
|
5344
|
-
} catch (err) {
|
|
5345
|
-
if (!(err instanceof Error && err.message.includes("not initialized"))) {
|
|
5346
|
-
logger_default.error(`delivery manager sessionDone failed for ${baseName}`, logger_default.errorData(err));
|
|
5347
|
-
}
|
|
5348
|
-
}
|
|
5349
|
-
try {
|
|
5350
|
-
const dm = getDeliveryManager();
|
|
5351
|
-
const busy = body.session ? dm.isSessionBusy(baseName, body.session) : false;
|
|
5352
|
-
if (!busy) {
|
|
5353
|
-
const completedTurnId = await completeTurn(baseName, body.session);
|
|
5354
|
-
if (completedTurnId) {
|
|
5355
|
-
tagUntaggedOutbound(baseName, completedTurnId).catch(
|
|
5356
|
-
(err) => logger_default.warn("failed to tag orphaned outbound records", logger_default.errorData(err))
|
|
5357
|
-
);
|
|
5358
|
-
}
|
|
5359
|
-
markDeliveredOnCleanTurn(baseName, body.session);
|
|
5360
|
-
if (insertedId != null) {
|
|
5361
|
-
summarizeTurn(baseName, body.session, body.channel, insertedId, completedTurnId).catch(
|
|
5362
|
-
(err) => logger_default.error("turn summarization failed", logger_default.errorData(err))
|
|
5363
|
-
);
|
|
5364
|
-
}
|
|
5365
|
-
}
|
|
5366
|
-
} catch (err) {
|
|
5367
|
-
if (!(err instanceof Error && err.message.includes("not initialized"))) {
|
|
5368
|
-
logger_default.error("turn completion check failed", logger_default.errorData(err));
|
|
5369
|
-
}
|
|
5370
|
-
const completedTurnId = await completeTurn(baseName, body.session);
|
|
5371
|
-
if (completedTurnId) {
|
|
5372
|
-
tagUntaggedOutbound(baseName, completedTurnId).catch(
|
|
5373
|
-
(err2) => logger_default.warn("failed to tag orphaned outbound records", logger_default.errorData(err2))
|
|
5374
|
-
);
|
|
5375
|
-
}
|
|
5376
|
-
markDeliveredOnCleanTurn(baseName, body.session);
|
|
5377
|
-
if (insertedId != null) {
|
|
5378
|
-
summarizeTurn(baseName, body.session, body.channel, insertedId, completedTurnId).catch(
|
|
5379
|
-
(err2) => logger_default.error("turn summarization failed", logger_default.errorData(err2))
|
|
5380
|
-
);
|
|
5381
|
-
}
|
|
5382
|
-
}
|
|
5383
|
-
}
|
|
5384
|
-
if (body.type === "usage" && body.metadata) {
|
|
5385
|
-
const inputTokens = body.metadata.input_tokens ?? 0;
|
|
5386
|
-
const outputTokens = body.metadata.output_tokens ?? 0;
|
|
5387
|
-
const tb = getTokenBudget();
|
|
5388
|
-
tb.recordUsage(baseName, inputTokens, outputTokens);
|
|
5389
|
-
if (body.session && tb.noteExceeded(baseName)) {
|
|
5390
|
-
void recordNotice({
|
|
5391
|
-
mind: baseName,
|
|
5392
|
-
session: body.session,
|
|
5393
|
-
kind: "budget",
|
|
5394
|
-
reason: "token_budget",
|
|
5395
|
-
detail: "You've reached your token budget for this period. Further activity may be paused until the budget resets \u2014 wrap up or prioritize accordingly."
|
|
5396
|
-
});
|
|
5397
|
-
}
|
|
5398
|
-
}
|
|
5497
|
+
await handleMindEvent(baseName, body);
|
|
5399
5498
|
return c.json({ ok: true });
|
|
5400
5499
|
}).get("/:name/events", requireSelf(), async (c) => {
|
|
5401
5500
|
const name = c.req.param("name");
|
|
@@ -5484,32 +5583,32 @@ ${user.trimEnd()}
|
|
|
5484
5583
|
const db = await getDb();
|
|
5485
5584
|
const rows = await db.select({
|
|
5486
5585
|
session: mindHistory.session,
|
|
5487
|
-
started_at:
|
|
5488
|
-
event_count:
|
|
5489
|
-
message_count:
|
|
5490
|
-
tool_count:
|
|
5491
|
-
}).from(mindHistory).where(
|
|
5586
|
+
started_at: sql3`MIN(${mindHistory.created_at})`,
|
|
5587
|
+
event_count: sql3`COUNT(*)`,
|
|
5588
|
+
message_count: sql3`SUM(CASE WHEN ${mindHistory.type} IN ('inbound','outbound') THEN 1 ELSE 0 END)`,
|
|
5589
|
+
tool_count: sql3`SUM(CASE WHEN ${mindHistory.type}='tool_use' THEN 1 ELSE 0 END)`
|
|
5590
|
+
}).from(mindHistory).where(and5(eq5(mindHistory.mind, name), sql3`${mindHistory.session} IS NOT NULL`)).groupBy(mindHistory.session).orderBy(sql3`MIN(${mindHistory.created_at}) DESC`);
|
|
5492
5591
|
return c.json(rows);
|
|
5493
5592
|
}).get("/:name/history/channels", requireSelf(), async (c) => {
|
|
5494
5593
|
const name = c.req.param("name");
|
|
5495
5594
|
const db = await getDb();
|
|
5496
|
-
const rows = await db.selectDistinct({ channel: mindHistory.channel }).from(mindHistory).where(
|
|
5595
|
+
const rows = await db.selectDistinct({ channel: mindHistory.channel }).from(mindHistory).where(eq5(mindHistory.mind, name));
|
|
5497
5596
|
return c.json(rows.map((r) => r.channel));
|
|
5498
5597
|
}).get("/:name/history/export", requireSelf(), async (c) => {
|
|
5499
5598
|
const name = c.req.param("name");
|
|
5500
5599
|
if (!await findMind(name)) return c.json({ error: "Mind not found" }, 404);
|
|
5501
5600
|
const db = await getDb();
|
|
5502
|
-
const rows = await db.select().from(mindHistory).where(
|
|
5601
|
+
const rows = await db.select().from(mindHistory).where(eq5(mindHistory.mind, name));
|
|
5503
5602
|
return c.json(rows);
|
|
5504
5603
|
}).get("/:name/history/turn", requireSelf(), async (c) => {
|
|
5505
5604
|
const name = c.req.param("name");
|
|
5506
5605
|
const turnId = c.req.query("turn_id");
|
|
5507
5606
|
const detail = c.req.query("detail") === "1";
|
|
5508
5607
|
const db = await getDb();
|
|
5509
|
-
const typeFilter = detail ? void 0 :
|
|
5608
|
+
const typeFilter = detail ? void 0 : sql3`${mindHistory.type} IN ('inbound','outbound','tool_use','tool_result','text','thinking','activity')`;
|
|
5510
5609
|
let rows;
|
|
5511
5610
|
if (turnId) {
|
|
5512
|
-
rows = await db.select().from(mindHistory).where(
|
|
5611
|
+
rows = await db.select().from(mindHistory).where(and5(eq5(mindHistory.mind, name), eq5(mindHistory.turn_id, turnId), typeFilter)).orderBy(mindHistory.id);
|
|
5513
5612
|
} else {
|
|
5514
5613
|
const session = c.req.query("session");
|
|
5515
5614
|
const fromId = parseInt(c.req.query("from_id") ?? "", 10);
|
|
@@ -5518,11 +5617,11 @@ ${user.trimEnd()}
|
|
|
5518
5617
|
return c.json({ error: "turn_id, or session with from_id and to_id, required" }, 400);
|
|
5519
5618
|
}
|
|
5520
5619
|
rows = await db.select().from(mindHistory).where(
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5620
|
+
and5(
|
|
5621
|
+
eq5(mindHistory.mind, name),
|
|
5622
|
+
eq5(mindHistory.session, session),
|
|
5623
|
+
sql3`${mindHistory.id} >= ${fromId}`,
|
|
5624
|
+
sql3`${mindHistory.id} <= ${toId}`,
|
|
5526
5625
|
typeFilter
|
|
5527
5626
|
)
|
|
5528
5627
|
).orderBy(mindHistory.id);
|
|
@@ -5535,14 +5634,14 @@ ${user.trimEnd()}
|
|
|
5535
5634
|
let sinceTimestamp = null;
|
|
5536
5635
|
if (currentSession) {
|
|
5537
5636
|
const lastTurn = await db.select({ turn_id: mindHistory.turn_id }).from(mindHistory).where(
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5637
|
+
and5(
|
|
5638
|
+
eq5(mindHistory.mind, name),
|
|
5639
|
+
eq5(mindHistory.session, currentSession),
|
|
5640
|
+
sql3`${mindHistory.turn_id} IS NOT NULL`
|
|
5542
5641
|
)
|
|
5543
|
-
).orderBy(
|
|
5642
|
+
).orderBy(desc4(mindHistory.created_at)).limit(1);
|
|
5544
5643
|
if (lastTurn.length > 0 && lastTurn[0].turn_id) {
|
|
5545
|
-
const firstEvent = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(
|
|
5644
|
+
const firstEvent = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(eq5(mindHistory.turn_id, lastTurn[0].turn_id)).orderBy(mindHistory.created_at).limit(1);
|
|
5546
5645
|
if (firstEvent.length > 0) {
|
|
5547
5646
|
sinceTimestamp = firstEvent[0].created_at;
|
|
5548
5647
|
}
|
|
@@ -5552,18 +5651,18 @@ ${user.trimEnd()}
|
|
|
5552
5651
|
sinceTimestamp = new Date(Date.now() - 36e5).toISOString().replace("T", " ").slice(0, 19);
|
|
5553
5652
|
}
|
|
5554
5653
|
const conditions = [
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5654
|
+
eq5(summaries.mind, name),
|
|
5655
|
+
eq5(summaries.period, "turn"),
|
|
5656
|
+
sql3`${summaries.created_at} > ${sinceTimestamp}`
|
|
5558
5657
|
];
|
|
5559
5658
|
if (currentSession) {
|
|
5560
|
-
conditions.push(
|
|
5659
|
+
conditions.push(sql3`${turns.session} != ${currentSession}`);
|
|
5561
5660
|
}
|
|
5562
5661
|
const rows = await db.select({
|
|
5563
5662
|
session: turns.session,
|
|
5564
5663
|
content: summaries.content,
|
|
5565
5664
|
created_at: summaries.created_at
|
|
5566
|
-
}).from(summaries).innerJoin(turns,
|
|
5665
|
+
}).from(summaries).innerJoin(turns, eq5(turns.id, summaries.period_key)).where(and5(...conditions)).orderBy(desc4(summaries.created_at)).limit(50);
|
|
5567
5666
|
if (rows.length === 0) {
|
|
5568
5667
|
return c.json({ context: null });
|
|
5569
5668
|
}
|
|
@@ -5582,7 +5681,7 @@ ${lines.join("\n")}` });
|
|
|
5582
5681
|
const notices = await drainNotices(baseName, session);
|
|
5583
5682
|
if (notices.length === 0) return c.json({ context: null, notices: [] });
|
|
5584
5683
|
const maxId = notices.reduce((m, n) => Math.max(m, n.id), 0);
|
|
5585
|
-
|
|
5684
|
+
setNoticeDrainWatermark(baseName, session, maxId);
|
|
5586
5685
|
return c.json({ context: formatNotices(notices), notices });
|
|
5587
5686
|
}).get("/:name/history", requireSelf(), async (c) => {
|
|
5588
5687
|
const name = c.req.param("name");
|
|
@@ -5593,18 +5692,18 @@ ${lines.join("\n")}` });
|
|
|
5593
5692
|
const limit = Math.min(Math.max(parseInt(c.req.query("limit") ?? "50", 10) || 50, 1), 200);
|
|
5594
5693
|
const offset = Math.max(parseInt(c.req.query("offset") ?? "0", 10) || 0, 0);
|
|
5595
5694
|
const db = await getDb();
|
|
5596
|
-
const conditions = [
|
|
5695
|
+
const conditions = [eq5(mindHistory.mind, name)];
|
|
5597
5696
|
if (channel) {
|
|
5598
|
-
conditions.push(
|
|
5697
|
+
conditions.push(eq5(mindHistory.channel, channel));
|
|
5599
5698
|
}
|
|
5600
5699
|
if (session) {
|
|
5601
|
-
conditions.push(
|
|
5700
|
+
conditions.push(eq5(mindHistory.session, session));
|
|
5602
5701
|
}
|
|
5603
5702
|
const effectivePreset = full ? "all" : preset;
|
|
5604
5703
|
if (!effectivePreset || effectivePreset === "summary") {
|
|
5605
|
-
const sumConditions = [
|
|
5704
|
+
const sumConditions = [eq5(summaries.mind, name), eq5(summaries.period, "turn")];
|
|
5606
5705
|
if (session) {
|
|
5607
|
-
sumConditions.push(
|
|
5706
|
+
sumConditions.push(eq5(turns.session, session));
|
|
5608
5707
|
const sumRows2 = await db.select({
|
|
5609
5708
|
id: summaries.id,
|
|
5610
5709
|
mind: summaries.mind,
|
|
@@ -5614,7 +5713,7 @@ ${lines.join("\n")}` });
|
|
|
5614
5713
|
metadata: summaries.metadata,
|
|
5615
5714
|
created_at: summaries.created_at,
|
|
5616
5715
|
session: turns.session
|
|
5617
|
-
}).from(summaries).innerJoin(turns,
|
|
5716
|
+
}).from(summaries).innerJoin(turns, eq5(turns.id, summaries.period_key)).where(and5(...sumConditions)).orderBy(desc4(summaries.created_at)).limit(limit).offset(offset);
|
|
5618
5717
|
return c.json(
|
|
5619
5718
|
sumRows2.map((r) => ({
|
|
5620
5719
|
id: r.id,
|
|
@@ -5631,7 +5730,7 @@ ${lines.join("\n")}` });
|
|
|
5631
5730
|
}))
|
|
5632
5731
|
);
|
|
5633
5732
|
}
|
|
5634
|
-
const sumRows = await db.select().from(summaries).where(
|
|
5733
|
+
const sumRows = await db.select().from(summaries).where(and5(...sumConditions)).orderBy(desc4(summaries.created_at)).limit(limit).offset(offset);
|
|
5635
5734
|
return c.json(
|
|
5636
5735
|
sumRows.map((r) => ({
|
|
5637
5736
|
id: r.id,
|
|
@@ -5652,22 +5751,22 @@ ${lines.join("\n")}` });
|
|
|
5652
5751
|
case "all":
|
|
5653
5752
|
break;
|
|
5654
5753
|
case "conversation":
|
|
5655
|
-
conditions.push(
|
|
5754
|
+
conditions.push(sql3`${mindHistory.type} IN ('inbound','outbound','tool_use')`);
|
|
5656
5755
|
break;
|
|
5657
5756
|
case "detailed":
|
|
5658
5757
|
conditions.push(
|
|
5659
|
-
|
|
5758
|
+
sql3`${mindHistory.type} IN ('inbound','outbound','tool_use','tool_result','text','thinking')`
|
|
5660
5759
|
);
|
|
5661
5760
|
break;
|
|
5662
5761
|
}
|
|
5663
|
-
const rows = await db.select().from(mindHistory).where(
|
|
5762
|
+
const rows = await db.select().from(mindHistory).where(and5(...conditions)).orderBy(desc4(mindHistory.created_at)).limit(limit).offset(offset);
|
|
5664
5763
|
return c.json(rows);
|
|
5665
5764
|
});
|
|
5666
5765
|
var minds_default = app13;
|
|
5667
5766
|
|
|
5668
5767
|
// packages/daemon/src/web/api/prompts.ts
|
|
5669
5768
|
import { zValidator as zValidator6 } from "@hono/zod-validator";
|
|
5670
|
-
import { eq as
|
|
5769
|
+
import { eq as eq6, sql as sql4 } from "drizzle-orm";
|
|
5671
5770
|
import { Hono as Hono16 } from "hono";
|
|
5672
5771
|
import { z as z6 } from "zod";
|
|
5673
5772
|
var app14 = new Hono16().get("/", async (c) => {
|
|
@@ -5700,9 +5799,9 @@ var app14 = new Hono16().get("/", async (c) => {
|
|
|
5700
5799
|
}
|
|
5701
5800
|
const { content } = c.req.valid("json");
|
|
5702
5801
|
const db = await getDb();
|
|
5703
|
-
await db.insert(systemPrompts).values({ key, content, updated_at:
|
|
5802
|
+
await db.insert(systemPrompts).values({ key, content, updated_at: sql4`(datetime('now'))` }).onConflictDoUpdate({
|
|
5704
5803
|
target: systemPrompts.key,
|
|
5705
|
-
set: { content, updated_at:
|
|
5804
|
+
set: { content, updated_at: sql4`(datetime('now'))` }
|
|
5706
5805
|
});
|
|
5707
5806
|
return c.json({ ok: true });
|
|
5708
5807
|
}).delete("/:key", requireAdmin, async (c) => {
|
|
@@ -5711,7 +5810,7 @@ var app14 = new Hono16().get("/", async (c) => {
|
|
|
5711
5810
|
return c.json({ error: "Unknown prompt key" }, 404);
|
|
5712
5811
|
}
|
|
5713
5812
|
const db = await getDb();
|
|
5714
|
-
await db.delete(systemPrompts).where(
|
|
5813
|
+
await db.delete(systemPrompts).where(eq6(systemPrompts.key, key));
|
|
5715
5814
|
return c.json({ ok: true });
|
|
5716
5815
|
});
|
|
5717
5816
|
var prompts_default = app14;
|
|
@@ -5959,7 +6058,7 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
5959
6058
|
const body = await c.req.text();
|
|
5960
6059
|
const message = `[webhook: ${event}] ${body}`;
|
|
5961
6060
|
try {
|
|
5962
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
6061
|
+
const { sendSystemMessage } = await import("./system-chat-KMQIP7VH.js");
|
|
5963
6062
|
await sendSystemMessage(name, message);
|
|
5964
6063
|
return c.json({ ok: true });
|
|
5965
6064
|
} catch (err) {
|
|
@@ -6013,7 +6112,7 @@ setup.get("/status", async (c) => {
|
|
|
6013
6112
|
let hasAccount = false;
|
|
6014
6113
|
if (hasSystem) {
|
|
6015
6114
|
try {
|
|
6016
|
-
const { listUsersByType: listUsersByType2 } = await import("./auth-
|
|
6115
|
+
const { listUsersByType: listUsersByType2 } = await import("./auth-3RIG6GKN.js");
|
|
6017
6116
|
const brains = await listUsersByType2("brain");
|
|
6018
6117
|
hasAccount = brains.length > 0;
|
|
6019
6118
|
} catch (err) {
|
|
@@ -6224,7 +6323,7 @@ setup.post("/account", async (c) => {
|
|
|
6224
6323
|
}
|
|
6225
6324
|
}
|
|
6226
6325
|
try {
|
|
6227
|
-
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-
|
|
6326
|
+
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-3RIG6GKN.js");
|
|
6228
6327
|
const user = await createUser2(body.username.trim(), body.password);
|
|
6229
6328
|
if (body.displayName?.trim()) {
|
|
6230
6329
|
await updateUserProfile2(user.id, { display_name: body.displayName.trim() });
|
|
@@ -6270,7 +6369,7 @@ setup.post("/models", async (c) => {
|
|
|
6270
6369
|
return c.json({ error: "Spirit model is required" }, 400);
|
|
6271
6370
|
}
|
|
6272
6371
|
try {
|
|
6273
|
-
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-
|
|
6372
|
+
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-FBCCEYF5.js");
|
|
6274
6373
|
setEnabledModels3(body.models);
|
|
6275
6374
|
const config2 = readGlobalConfig();
|
|
6276
6375
|
config2.spiritModel = body.spiritModel.trim();
|
|
@@ -6288,15 +6387,15 @@ setup.post("/complete", async (c) => {
|
|
|
6288
6387
|
return c.json({ error: "Setup already complete" }, 400);
|
|
6289
6388
|
}
|
|
6290
6389
|
try {
|
|
6291
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
6292
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
6390
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-JQQHUVWR.js");
|
|
6391
|
+
const { startSpiritFull } = await import("./mind-service-ZBVUMJ5H.js");
|
|
6293
6392
|
await ensureSpiritProject();
|
|
6294
6393
|
await syncSpiritTemplate();
|
|
6295
6394
|
const warnings = [];
|
|
6296
6395
|
const config2 = readGlobalConfig();
|
|
6297
6396
|
if (config2.setup?.service && config2.setup?.type === "local") {
|
|
6298
6397
|
try {
|
|
6299
|
-
const { installUserService } = await import("./service-install-
|
|
6398
|
+
const { installUserService } = await import("./service-install-SHRM6NHK.js");
|
|
6300
6399
|
const installed = await installUserService(config2.port, config2.hostname);
|
|
6301
6400
|
if (!installed) {
|
|
6302
6401
|
warnings.push("Service installation is not supported on this platform.");
|
|
@@ -6324,8 +6423,8 @@ setup.post("/complete", async (c) => {
|
|
|
6324
6423
|
}
|
|
6325
6424
|
let spiritConversationId;
|
|
6326
6425
|
try {
|
|
6327
|
-
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-
|
|
6328
|
-
const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-
|
|
6426
|
+
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-3RIG6GKN.js");
|
|
6427
|
+
const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-67WWW25C.js");
|
|
6329
6428
|
const spiritUser = await getOrCreateMindUser2("volute");
|
|
6330
6429
|
const brains = await listUsersByType2("brain");
|
|
6331
6430
|
const admin2 = brains.find((u) => u.role === "admin");
|
|
@@ -6347,8 +6446,8 @@ setup.post("/complete", async (c) => {
|
|
|
6347
6446
|
logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
|
|
6348
6447
|
if (spiritConversationId && spiritStarted) {
|
|
6349
6448
|
try {
|
|
6350
|
-
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-
|
|
6351
|
-
const { listUsersByType: listUsers2 } = await import("./auth-
|
|
6449
|
+
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-WJBZFALY.js");
|
|
6450
|
+
const { listUsersByType: listUsers2 } = await import("./auth-3RIG6GKN.js");
|
|
6352
6451
|
const admins = await listUsers2("brain");
|
|
6353
6452
|
const admin2 = admins.find((u) => u.role === "admin");
|
|
6354
6453
|
const adminName = admin2?.display_name || admin2?.username || "the admin";
|
|
@@ -6667,7 +6766,7 @@ var app19 = new Hono22().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6667
6766
|
var conversations_default = app19;
|
|
6668
6767
|
|
|
6669
6768
|
// packages/daemon/src/web/api/v1/events.ts
|
|
6670
|
-
import { desc as
|
|
6769
|
+
import { desc as desc5, eq as eq7 } from "drizzle-orm";
|
|
6671
6770
|
import { Hono as Hono23 } from "hono";
|
|
6672
6771
|
import { streamSSE as streamSSE4 } from "hono/streaming";
|
|
6673
6772
|
|
|
@@ -6710,16 +6809,23 @@ function bufferEvent(data) {
|
|
|
6710
6809
|
function nextEventId() {
|
|
6711
6810
|
return nextId++;
|
|
6712
6811
|
}
|
|
6713
|
-
function getEventsSince(sinceId, allowedConversationIds) {
|
|
6812
|
+
function getEventsSince(sinceId, allowedConversationIds, allowedActivityMind) {
|
|
6714
6813
|
const now = Date.now();
|
|
6715
6814
|
const startIdx = buffer.findIndex((e) => e.id > sinceId);
|
|
6716
6815
|
if (startIdx === -1) return [];
|
|
6717
6816
|
return buffer.slice(startIdx).filter((e) => {
|
|
6718
6817
|
if (now - e.timestamp >= MAX_AGE_MS) return false;
|
|
6719
6818
|
const data = e.data;
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6819
|
+
switch (data.event) {
|
|
6820
|
+
case "snapshot":
|
|
6821
|
+
return false;
|
|
6822
|
+
case "conversation":
|
|
6823
|
+
return allowedConversationIds.has(data.conversationId);
|
|
6824
|
+
case "activity":
|
|
6825
|
+
return allowedActivityMind === void 0 || data.mind === allowedActivityMind;
|
|
6826
|
+
default:
|
|
6827
|
+
return false;
|
|
6828
|
+
}
|
|
6723
6829
|
});
|
|
6724
6830
|
}
|
|
6725
6831
|
|
|
@@ -6728,6 +6834,8 @@ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6728
6834
|
const user = c.get("user");
|
|
6729
6835
|
const since = c.req.query("since");
|
|
6730
6836
|
const sinceId = since ? Number(since) : 0;
|
|
6837
|
+
const privileged = user.role === "admin" || user.role === "system";
|
|
6838
|
+
const activityMind = privileged ? void 0 : await getBaseName(user.username);
|
|
6731
6839
|
return streamSSE4(c, async (stream) => {
|
|
6732
6840
|
const cleanups = [];
|
|
6733
6841
|
if (user.user_type === "brain") {
|
|
@@ -6750,7 +6858,7 @@ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6750
6858
|
}
|
|
6751
6859
|
const allowedConversationIds = new Set(conversations2.map((c2) => c2.id));
|
|
6752
6860
|
if (sinceId > 0) {
|
|
6753
|
-
const missed = getEventsSince(sinceId, allowedConversationIds);
|
|
6861
|
+
const missed = getEventsSince(sinceId, allowedConversationIds, activityMind);
|
|
6754
6862
|
for (const event of missed) {
|
|
6755
6863
|
await stream.writeSSE({
|
|
6756
6864
|
id: String(event.id),
|
|
@@ -6761,7 +6869,7 @@ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6761
6869
|
let recentActivity = [];
|
|
6762
6870
|
try {
|
|
6763
6871
|
const db = await getDb();
|
|
6764
|
-
recentActivity = await db.select().from(activity).orderBy(
|
|
6872
|
+
recentActivity = await db.select().from(activity).where(activityMind ? eq7(activity.mind, activityMind) : void 0).orderBy(desc5(activity.created_at)).limit(50);
|
|
6765
6873
|
recentActivity = recentActivity.map((row) => ({
|
|
6766
6874
|
...row,
|
|
6767
6875
|
metadata: row.metadata ? JSON.parse(row.metadata) : null
|
|
@@ -6788,6 +6896,7 @@ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6788
6896
|
metadata: event.metadata ?? null
|
|
6789
6897
|
};
|
|
6790
6898
|
const eventId = bufferEvent(data);
|
|
6899
|
+
if (activityMind !== void 0 && event.mind !== activityMind) return;
|
|
6791
6900
|
stream.writeSSE({
|
|
6792
6901
|
id: String(eventId),
|
|
6793
6902
|
data: JSON.stringify(data)
|
|
@@ -7013,7 +7122,7 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7013
7122
|
const msg = e instanceof Error ? e.message : String(e);
|
|
7014
7123
|
return c.json({ error: `Failed to create worktree: ${msg}` }, 500);
|
|
7015
7124
|
}
|
|
7016
|
-
chownMindDir(projectRoot, mindName);
|
|
7125
|
+
await chownMindDir(projectRoot, mindName);
|
|
7017
7126
|
try {
|
|
7018
7127
|
if (isIsolationEnabled()) {
|
|
7019
7128
|
const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
|
|
@@ -7129,7 +7238,7 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7129
7238
|
if (variantName.endsWith("-upgrade") || variantName === "upgrade") {
|
|
7130
7239
|
try {
|
|
7131
7240
|
const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-446HHH5V.js");
|
|
7132
|
-
const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-
|
|
7241
|
+
const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-7LQHTRUX.js");
|
|
7133
7242
|
const tmpl = parentEntry.template ?? "claude";
|
|
7134
7243
|
await setMindTemplateHash2(mindName, computeTemplateHash2(tmpl));
|
|
7135
7244
|
} catch (err) {
|
|
@@ -7303,47 +7412,6 @@ import { zValidator as zValidator10 } from "@hono/zod-validator";
|
|
|
7303
7412
|
import { Hono as Hono26 } from "hono";
|
|
7304
7413
|
import { streamSSE as streamSSE5 } from "hono/streaming";
|
|
7305
7414
|
import { z as z10 } from "zod";
|
|
7306
|
-
async function fanOutToMinds(opts) {
|
|
7307
|
-
const participants = opts.participants;
|
|
7308
|
-
const mindParticipants = participants.filter(
|
|
7309
|
-
(p) => p.userType === "mind" || p.userType === "system"
|
|
7310
|
-
);
|
|
7311
|
-
const participantNames = participants.map((p) => p.username);
|
|
7312
|
-
const isDM = opts.isDM ?? participants.length === 2;
|
|
7313
|
-
const manager = getMindManager();
|
|
7314
|
-
const sm = getSleepManagerIfReady();
|
|
7315
|
-
const targetMinds = mindParticipants.map((ap) => {
|
|
7316
|
-
const key = opts.targetName ? opts.targetName(ap.username) : ap.username;
|
|
7317
|
-
if (manager.isRunning(key) || sm?.isSleeping(ap.username)) return ap.username;
|
|
7318
|
-
return null;
|
|
7319
|
-
}).filter((n) => n !== null && n !== opts.senderName);
|
|
7320
|
-
function slugForMind(mindUsername) {
|
|
7321
|
-
return buildVoluteSlug({
|
|
7322
|
-
participants,
|
|
7323
|
-
mindUsername,
|
|
7324
|
-
conversationId: opts.conversationId,
|
|
7325
|
-
...opts.slugExtra
|
|
7326
|
-
});
|
|
7327
|
-
}
|
|
7328
|
-
for (const mindName of targetMinds) {
|
|
7329
|
-
const target = opts.targetName ? opts.targetName(mindName) : mindName;
|
|
7330
|
-
const channel = slugForMind(mindName);
|
|
7331
|
-
const typingMap = getTypingMap();
|
|
7332
|
-
const currentlyTyping = typingMap.get(channel).filter((name) => participantNames.includes(name));
|
|
7333
|
-
deliverMessage(target, {
|
|
7334
|
-
content: opts.contentBlocks,
|
|
7335
|
-
channel,
|
|
7336
|
-
conversationId: opts.conversationId,
|
|
7337
|
-
sender: opts.senderName,
|
|
7338
|
-
participants: participantNames,
|
|
7339
|
-
participantCount: participants.length,
|
|
7340
|
-
isDM,
|
|
7341
|
-
...currentlyTyping.length > 0 ? { typing: currentlyTyping } : {}
|
|
7342
|
-
}).catch((err) => {
|
|
7343
|
-
logger_default.warn(`fan-out delivery failed for ${target}`, logger_default.errorData(err));
|
|
7344
|
-
});
|
|
7345
|
-
}
|
|
7346
|
-
}
|
|
7347
7415
|
var fileSchema = z10.object({
|
|
7348
7416
|
filename: z10.string(),
|
|
7349
7417
|
data: z10.string()
|
|
@@ -7505,7 +7573,15 @@ var unifiedChatApp = new Hono26().post(
|
|
|
7505
7573
|
logger_default.warn("failed to look up channel char_limit, skipping enforcement", logger_default.errorData(err));
|
|
7506
7574
|
}
|
|
7507
7575
|
}
|
|
7508
|
-
|
|
7576
|
+
let outboundTurnId;
|
|
7577
|
+
let senderBase;
|
|
7578
|
+
if (senderIsMind) {
|
|
7579
|
+
senderBase = await getBaseName(senderName);
|
|
7580
|
+
outboundTurnId = getActiveTurnId(senderBase, c.get("mindSession"));
|
|
7581
|
+
}
|
|
7582
|
+
const message = await addMessage(conversationId, "user", senderName, contentBlocks, {
|
|
7583
|
+
turnId: outboundTurnId
|
|
7584
|
+
});
|
|
7509
7585
|
let outboundId;
|
|
7510
7586
|
if (senderIsMind) {
|
|
7511
7587
|
routeOutboundBridge(conversationId, senderName, contentBlocks).catch((err) => {
|
|
@@ -7518,10 +7594,22 @@ var unifiedChatApp = new Hono26().post(
|
|
|
7518
7594
|
convType: conv.type,
|
|
7519
7595
|
convName
|
|
7520
7596
|
});
|
|
7597
|
+
const text = extractTextContent(contentBlocks);
|
|
7521
7598
|
try {
|
|
7522
|
-
outboundId = await recordOutbound(senderName, channel,
|
|
7523
|
-
messageId: message?.id != null ? String(message.id) : void 0
|
|
7599
|
+
outboundId = await recordOutbound(senderName, channel, text, {
|
|
7600
|
+
messageId: message?.id != null ? String(message.id) : void 0,
|
|
7601
|
+
turnId: outboundTurnId
|
|
7524
7602
|
});
|
|
7603
|
+
if (outboundTurnId) {
|
|
7604
|
+
const mindKey = senderBase ?? senderName;
|
|
7605
|
+
publish2(mindKey, {
|
|
7606
|
+
mind: mindKey,
|
|
7607
|
+
type: "outbound",
|
|
7608
|
+
channel,
|
|
7609
|
+
content: text,
|
|
7610
|
+
turnId: outboundTurnId
|
|
7611
|
+
});
|
|
7612
|
+
}
|
|
7525
7613
|
} catch (err) {
|
|
7526
7614
|
logger_default.warn(`recordOutbound failed for ${senderName}`, logger_default.errorData(err));
|
|
7527
7615
|
}
|
|
@@ -7531,6 +7619,7 @@ var unifiedChatApp = new Hono26().post(
|
|
|
7531
7619
|
conversationId,
|
|
7532
7620
|
contentBlocks,
|
|
7533
7621
|
senderName,
|
|
7622
|
+
senderIsMind: !!senderIsMind,
|
|
7534
7623
|
participants,
|
|
7535
7624
|
isDM,
|
|
7536
7625
|
slugExtra: { convType: conv.type, convName },
|
|
@@ -7888,10 +7977,15 @@ if (!process.env.VOLUTE_HOME) {
|
|
|
7888
7977
|
if (process.env.VOLUTE_TIMEZONE && !process.env.TZ) {
|
|
7889
7978
|
process.env.TZ = process.env.VOLUTE_TIMEZONE;
|
|
7890
7979
|
}
|
|
7891
|
-
function writeDaemonConfig(
|
|
7892
|
-
|
|
7980
|
+
function writeDaemonConfig(systemDir, config2, token) {
|
|
7981
|
+
const configPath = resolve17(systemDir, "daemon.json");
|
|
7982
|
+
writeFileSync9(configPath, `${JSON.stringify(config2, null, 2)}
|
|
7983
|
+
`, { mode: 420 });
|
|
7984
|
+
chmodSync(configPath, 420);
|
|
7985
|
+
const tokenPath = resolve17(systemDir, "daemon-token");
|
|
7986
|
+
writeFileSync9(tokenPath, `${token}
|
|
7893
7987
|
`, { mode: 384 });
|
|
7894
|
-
chmodSync(
|
|
7988
|
+
chmodSync(tokenPath, 384);
|
|
7895
7989
|
}
|
|
7896
7990
|
async function startDaemon(opts) {
|
|
7897
7991
|
const { port, hostname } = opts;
|
|
@@ -7911,21 +8005,24 @@ async function startDaemon(opts) {
|
|
|
7911
8005
|
}
|
|
7912
8006
|
const DAEMON_PID_PATH = resolve17(systemDir, "daemon.pid");
|
|
7913
8007
|
const DAEMON_JSON_PATH = resolve17(systemDir, "daemon.json");
|
|
8008
|
+
const DAEMON_TOKEN_PATH = resolve17(systemDir, "daemon-token");
|
|
7914
8009
|
mkdirSync10(home, { recursive: true });
|
|
7915
8010
|
ensureSystemDir();
|
|
7916
|
-
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-
|
|
8011
|
+
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-25MMJ3J4.js");
|
|
7917
8012
|
migrateConfigSecrets();
|
|
7918
8013
|
migrateSetupCompleted();
|
|
7919
|
-
|
|
8014
|
+
const { migrateAiModelQualification } = await import("./ai-service-FBCCEYF5.js");
|
|
8015
|
+
migrateAiModelQualification();
|
|
8016
|
+
await (await import("./db-CZV62BOQ.js")).getDb();
|
|
7920
8017
|
try {
|
|
7921
|
-
const { eq:
|
|
7922
|
-
const { users: users2 } = await import("./schema-
|
|
7923
|
-
const db = await (await import("./db-
|
|
7924
|
-
await db.update(users2).set({ role: "system" }).where(
|
|
8018
|
+
const { eq: eq8, and: and6 } = await import("drizzle-orm");
|
|
8019
|
+
const { users: users2 } = await import("./schema-LRUTFOER.js");
|
|
8020
|
+
const db = await (await import("./db-CZV62BOQ.js")).getDb();
|
|
8021
|
+
await db.update(users2).set({ role: "system" }).where(and6(eq8(users2.user_type, "system"), eq8(users2.role, "user")));
|
|
7925
8022
|
} catch (err) {
|
|
7926
8023
|
logger_default.warn("failed to migrate system user role", logger_default.errorData(err));
|
|
7927
8024
|
}
|
|
7928
|
-
const { initSandbox } = await import("./sandbox-
|
|
8025
|
+
const { initSandbox } = await import("./sandbox-SJH3XOPZ.js");
|
|
7929
8026
|
await initSandbox();
|
|
7930
8027
|
try {
|
|
7931
8028
|
await syncBuiltinSkills();
|
|
@@ -7952,7 +8049,7 @@ async function startDaemon(opts) {
|
|
|
7952
8049
|
logger_default.warn("failed to ensure #system channel", logger_default.errorData(err));
|
|
7953
8050
|
}
|
|
7954
8051
|
try {
|
|
7955
|
-
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-
|
|
8052
|
+
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-3RIG6GKN.js");
|
|
7956
8053
|
await getOrCreateSystemUser2();
|
|
7957
8054
|
} catch (err) {
|
|
7958
8055
|
logger_default.warn(
|
|
@@ -7960,13 +8057,13 @@ async function startDaemon(opts) {
|
|
|
7960
8057
|
logger_default.errorData(err)
|
|
7961
8058
|
);
|
|
7962
8059
|
}
|
|
7963
|
-
const token = process.env.VOLUTE_DAEMON_TOKEN ||
|
|
7964
|
-
const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-
|
|
8060
|
+
const token = process.env.VOLUTE_DAEMON_TOKEN || randomBytes2(32).toString("hex");
|
|
8061
|
+
const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-25MMJ3J4.js");
|
|
7965
8062
|
const globalCfg = readGlobalConfig2();
|
|
7966
8063
|
let tls;
|
|
7967
8064
|
if (opts.tailscale || globalCfg.tailscale) {
|
|
7968
8065
|
try {
|
|
7969
|
-
const { getTailscaleTls } = await import("./tailscale-
|
|
8066
|
+
const { getTailscaleTls } = await import("./tailscale-Q7ZJL7S7.js");
|
|
7970
8067
|
const tlsConfig = await getTailscaleTls();
|
|
7971
8068
|
tls = { key: tlsConfig.key, cert: tlsConfig.cert };
|
|
7972
8069
|
logger_default.info("Tailscale HTTPS enabled", { hostname: tlsConfig.hostname });
|
|
@@ -7994,10 +8091,10 @@ async function startDaemon(opts) {
|
|
|
7994
8091
|
process.env.VOLUTE_DAEMON_PORT = String(daemonPort);
|
|
7995
8092
|
process.env.VOLUTE_DAEMON_HOSTNAME = hostname;
|
|
7996
8093
|
writeFileSync9(DAEMON_PID_PATH, myPid, { mode: 420 });
|
|
7997
|
-
const daemonConfig = { port, hostname
|
|
8094
|
+
const daemonConfig = { port, hostname };
|
|
7998
8095
|
if (internalPort) daemonConfig.internalPort = internalPort;
|
|
7999
8096
|
if (tls) daemonConfig.tls = true;
|
|
8000
|
-
writeDaemonConfig(
|
|
8097
|
+
writeDaemonConfig(systemDir, daemonConfig, token);
|
|
8001
8098
|
const delivery = initDeliveryManager();
|
|
8002
8099
|
const manager = initMindManager();
|
|
8003
8100
|
manager.loadCrashAttempts();
|
|
@@ -8044,10 +8141,10 @@ async function startDaemon(opts) {
|
|
|
8044
8141
|
await Promise.all(workers);
|
|
8045
8142
|
}
|
|
8046
8143
|
try {
|
|
8047
|
-
const { isSetupComplete: isSetupComplete2 } = await import("./setup-
|
|
8144
|
+
const { isSetupComplete: isSetupComplete2 } = await import("./setup-25MMJ3J4.js");
|
|
8048
8145
|
if (isSetupComplete2()) {
|
|
8049
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
8050
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
8146
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-JQQHUVWR.js");
|
|
8147
|
+
const { startSpiritFull } = await import("./mind-service-ZBVUMJ5H.js");
|
|
8051
8148
|
await ensureSpiritProject();
|
|
8052
8149
|
await syncSpiritTemplate();
|
|
8053
8150
|
const spiritEntry = await findMind("volute");
|
|
@@ -8064,7 +8161,7 @@ async function startDaemon(opts) {
|
|
|
8064
8161
|
bridgeManager.startBridges(daemonPort).catch((err) => {
|
|
8065
8162
|
logger_default.warn("failed to start bridges", logger_default.errorData(err));
|
|
8066
8163
|
});
|
|
8067
|
-
import("./cloud-sync-
|
|
8164
|
+
import("./cloud-sync-FRYNWKCR.js").then(
|
|
8068
8165
|
({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
|
|
8069
8166
|
logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
|
|
8070
8167
|
})
|
|
@@ -8072,7 +8169,7 @@ async function startDaemon(opts) {
|
|
|
8072
8169
|
logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
|
|
8073
8170
|
});
|
|
8074
8171
|
try {
|
|
8075
|
-
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-
|
|
8172
|
+
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-DCAIXXZB.js");
|
|
8076
8173
|
backfillTemplateHashes();
|
|
8077
8174
|
notifyVersionUpdate().catch((err) => {
|
|
8078
8175
|
logger_default.warn("failed to send version update notifications", logger_default.errorData(err));
|
|
@@ -8083,6 +8180,7 @@ async function startDaemon(opts) {
|
|
|
8083
8180
|
delivery.restoreFromDb().catch((err) => {
|
|
8084
8181
|
logger_default.warn("failed to restore delivery queue", logger_default.errorData(err));
|
|
8085
8182
|
});
|
|
8183
|
+
delivery.startRedrive();
|
|
8086
8184
|
cleanExpiredSessions().catch((err) => {
|
|
8087
8185
|
logger_default.warn("failed to clean expired sessions", logger_default.errorData(err));
|
|
8088
8186
|
});
|
|
@@ -8104,9 +8202,12 @@ async function startDaemon(opts) {
|
|
|
8104
8202
|
} catch {
|
|
8105
8203
|
}
|
|
8106
8204
|
try {
|
|
8107
|
-
|
|
8108
|
-
|
|
8109
|
-
|
|
8205
|
+
if (readFileSync10(DAEMON_TOKEN_PATH, "utf-8").trim() === token) {
|
|
8206
|
+
unlinkSync2(DAEMON_TOKEN_PATH);
|
|
8207
|
+
try {
|
|
8208
|
+
unlinkSync2(DAEMON_JSON_PATH);
|
|
8209
|
+
} catch {
|
|
8210
|
+
}
|
|
8110
8211
|
}
|
|
8111
8212
|
} catch {
|
|
8112
8213
|
}
|