volute 0.44.0 → 0.45.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{activity-events-OMCSM7XW.js → activity-events-BUR2RYTJ.js} +2 -2
- package/dist/{ai-service-7PHSRDMO.js → ai-service-UODCCE4O.js} +3 -3
- package/dist/{archive-6R4TZMYI.js → archive-WS2L2VIQ.js} +2 -2
- package/dist/{auth-FRZJVQCS.js → auth-FLAEXXZK.js} +3 -3
- package/dist/{avatar-image-BNWEXSA2.js → avatar-image-6KY6UU4D.js} +3 -3
- package/dist/backup-TST5C2YN.js +381 -0
- package/dist/{chat-I4EDDIQC.js → chat-76MRWWQX.js} +2 -2
- package/dist/{chunk-5AHYQHNT.js → chunk-4JOQZPCE.js} +3 -2
- package/dist/{chunk-2BONPXAF.js → chunk-6EMWJZBK.js} +1 -1
- package/dist/{chunk-ZMIMSIIT.js → chunk-7C44R625.js} +1 -1
- package/dist/{chunk-I2Y2YHIO.js → chunk-7ZUB63PS.js} +4 -4
- package/dist/{chunk-LAXUUY7O.js → chunk-A7WQZKOU.js} +2 -2
- package/dist/{chunk-H7IYFRAL.js → chunk-ALKYQULU.js} +10 -5
- package/dist/{chunk-KP3KWNG6.js → chunk-CDPBTTZO.js} +2 -2
- package/dist/{chunk-SQL7M4HJ.js → chunk-DRJ24GXK.js} +2 -2
- package/dist/{chunk-HVU45COX.js → chunk-EJVPTVTI.js} +1 -1
- package/dist/{chunk-PNV24SEP.js → chunk-F7H6ATM4.js} +14 -2
- package/dist/{chunk-7FT24JBQ.js → chunk-FR6S2KNN.js} +10 -10
- package/dist/chunk-FXORA5JG.js +327 -0
- package/dist/{chunk-3ERIL673.js → chunk-H2X54EHC.js} +1 -1
- package/dist/{chunk-J47TIYHA.js → chunk-IHKGWTGT.js} +1 -1
- package/dist/{chunk-3GYVW2X3.js → chunk-JZ62SYWR.js} +1 -1
- package/dist/{chunk-EQZD4YU3.js → chunk-NYC5U6K7.js} +9 -9
- package/dist/{chunk-FZMEVCWC.js → chunk-OP4JG2BS.js} +9 -6
- package/dist/{chunk-CU6OFXMM.js → chunk-PFZBNKUH.js} +9 -0
- package/dist/{chunk-QMJJWTNL.js → chunk-QCN24XEN.js} +1 -1
- package/dist/{chunk-7KWANSLX.js → chunk-QNQMSWZE.js} +3 -3
- package/dist/{chunk-UMI4UIJG.js → chunk-R77O2WMK.js} +1 -1
- package/dist/{chunk-IEWZ7VD7.js → chunk-RRNXJOKB.js} +2 -2
- package/dist/{chunk-FHWUQZXE.js → chunk-RXEEYDIB.js} +1 -1
- package/dist/{chunk-CYI534DJ.js → chunk-T6HYVHPG.js} +2 -2
- package/dist/{chunk-Q2XBKQ2D.js → chunk-TQJ6ZYVY.js} +2 -2
- package/dist/{chunk-NF75HPNR.js → chunk-UYLGEDVD.js} +40 -15
- package/dist/{chunk-OMETFX5H.js → chunk-YT7PEESJ.js} +261 -102
- package/dist/{chunk-5GT7URXJ.js → chunk-ZDZISKCL.js} +1 -1
- package/dist/cli.js +21 -15
- package/dist/{cloud-sync-6WJ7WFYD.js → cloud-sync-3OJOPZRT.js} +16 -16
- package/dist/{conversations-WAJYZKOC.js → conversations-JZTD6KLR.js} +3 -3
- package/dist/{create-YZIV5OJC.js → create-IOV4GCRX.js} +1 -1
- package/dist/{daemon-restart-OUJVINXV.js → daemon-restart-TIHKVVVA.js} +6 -6
- package/dist/daemon.js +562 -321
- package/dist/{db-JFLCJCUG.js → db-MF2JNRUW.js} +1 -1
- package/dist/delivery-manager-VDVKVA46.js +32 -0
- package/dist/{delivery-router-GODSIS62.js → delivery-router-N4A7ZC5T.js} +2 -2
- package/dist/{down-XCAZXWLB.js → down-U2CZ23M4.js} +4 -4
- package/dist/echo-text-6JJOPUD4.js +32 -0
- package/dist/{exec-4GWHAHS3.js → exec-G3ZRST4Z.js} +2 -2
- package/dist/{export-ID7YUSLZ.js → export-GGIVO76O.js} +2 -2
- package/dist/{extensions-3QNDGW5E.js → extensions-JONTW2HF.js} +16 -16
- package/dist/{files-BQ2WB5KC.js → files-4LN3EN7Q.js} +2 -2
- package/dist/{import-SKID37QX.js → import-42YNQBF4.js} +5 -5
- package/dist/{isolation-5MB3J73F.js → isolation-YMGZZ4E5.js} +2 -2
- package/dist/{join-RXPXGV4L.js → join-ZJV7W6MO.js} +4 -0
- package/dist/{login-LM4NF4ZB.js → login-M6OJUPQ2.js} +1 -1
- package/dist/{logout-CTJVIZGA.js → logout-WQBWO77G.js} +1 -1
- package/dist/message-delivery-3C65ZI6L.js +34 -0
- package/dist/{mind-MI7Z6KM2.js → mind-DWB6XYCH.js} +7 -7
- package/dist/{mind-activity-tracker-BGHJE7XA.js → mind-activity-tracker-POBLU3LC.js} +3 -3
- package/dist/mind-service-3F4I46CI.js +36 -0
- package/dist/{package-5B4XDTJH.js → package-A7KXT67Q.js} +1 -1
- package/dist/{registry-NUJAGLQJ.js → registry-OUZBZ3Q4.js} +5 -1
- package/dist/{sandbox-IOPWWILM.js → sandbox-ZJ7QA6Z6.js} +3 -3
- package/dist/scheduler-P6DXLLXI.js +30 -0
- package/dist/{seed-UUPVQWFB.js → seed-HCP5NYKH.js} +1 -1
- package/dist/{seed-cmd-7XPKDQUC.js → seed-cmd-ILOGNIFB.js} +2 -2
- package/dist/{seed-create-IZ4M5ESO.js → seed-create-OURS2LS4.js} +3 -3
- package/dist/{seed-sprout-POJXHJWV.js → seed-sprout-ELDFDAN6.js} +7 -7
- package/dist/{send-O6W53VBM.js → send-AAIOPJAV.js} +2 -2
- package/dist/{service-AQVPUANO.js → service-UOCLXDWR.js} +3 -3
- package/dist/{service-install-4QNUDKLM.js → service-install-4HHFDDWY.js} +4 -4
- package/dist/{setup-5GCO3CUB.js → setup-DQM5VPY4.js} +6 -6
- package/dist/{setup-MLRKNP7Y.js → setup-Y2EJI3GG.js} +2 -2
- package/dist/skills/imagegen/scripts/imagegen.ts +100 -40
- package/dist/skills/memory/SKILL.md +2 -1
- package/dist/skills/orientation/SKILL.md +1 -1
- package/dist/skills/plan-coordinator/SKILL.md +2 -2
- package/dist/skills/volute-admin/SKILL.md +9 -6
- package/dist/skills/volute-mind/SKILL.md +20 -17
- package/dist/skills/volute-mind/references/extensions.md +5 -3
- package/dist/skills/volute-mind/references/integrations.md +2 -2
- package/dist/skills/volute-mind/references/routing.md +19 -23
- package/dist/skills/volute-mind/references/variants.md +10 -8
- package/dist/{skills-775C7QFF.js → skills-BKINFL7W.js} +4 -4
- package/dist/sleep-manager-HCUH4PM4.js +34 -0
- package/dist/{spirit-IK5OYWMV.js → spirit-DBTIW7P4.js} +7 -7
- package/dist/{sprout-ZY5QGOEL.js → sprout-W3KC7UGK.js} +1 -1
- package/dist/{src-XFY3XDD6.js → src-OJHARHTF.js} +28 -17
- package/dist/{status-E5DQNCAO.js → status-SWRVGXBI.js} +4 -4
- package/dist/system-chat-XOALE2RD.js +36 -0
- package/dist/{tailscale-QAWVKQKU.js → tailscale-3XOKOW7T.js} +1 -1
- package/dist/{turn-tracker-RWZMY7M6.js → turn-tracker-2W6Q2NSR.js} +6 -4
- package/dist/{up-FLCDR2UB.js → up-FTK7CTO3.js} +5 -5
- package/dist/{update-7TYVH5FM.js → update-SWAYZRWJ.js} +4 -4
- package/dist/{update-check-VSCSJ7KX.js → update-check-PQ2MZ47K.js} +2 -2
- package/dist/{upgrade-37DAGF6H.js → upgrade-NWAZ7MLD.js} +1 -1
- package/dist/{version-notify-B67N35A3.js → version-notify-3XMAIQTE.js} +17 -17
- package/dist/{volute-config-TS62GS6A.js → volute-config-A52FHWKM.js} +5 -1
- package/dist/web-assets/assets/{index-dJdNzAPn.css → index-B1JBQv2m.css} +1 -1
- package/dist/web-assets/assets/index-Bc2m8gRC.js +86 -0
- package/dist/web-assets/index.html +2 -2
- package/package.json +1 -1
- package/packages/extensions/plan/skills/plan/SKILL.md +1 -1
- package/templates/_base/.init/.config/prompts.json +1 -1
- package/templates/_base/.init/.local/hooks/startup-context.ts +0 -8
- package/templates/_base/.init/MEMORY.md +2 -1
- package/templates/_base/home/VOLUTE.md +6 -9
- package/templates/_base/src/lib/file-handler.ts +3 -3
- package/templates/_base/src/lib/router.ts +21 -25
- package/templates/_base/src/lib/startup.ts +3 -1
- package/templates/_base/src/lib/types.ts +2 -2
- package/templates/claude/.init/CLAUDE.md +1 -1
- package/templates/claude/src/agent.ts +97 -12
- package/templates/claude/src/lib/message-channel.ts +23 -0
- package/templates/claude/src/lib/session-reaper.ts +37 -0
- package/templates/claude/src/lib/stream-consumer.ts +7 -4
- package/templates/claude/src/server.ts +1 -0
- package/templates/codex/.init/AGENTS.md +4 -2
- package/templates/codex/src/agent.ts +31 -13
- package/templates/pi/.init/MINDS.md +4 -2
- package/templates/pi/src/agent.ts +18 -7
- package/templates/pi/src/lib/event-handler.ts +6 -2
- package/dist/delivery-manager-TEVOHX5W.js +0 -32
- package/dist/echo-text-T7ZA5EYD.js +0 -32
- package/dist/message-delivery-2EA5LLMD.js +0 -34
- package/dist/mind-service-S3SY7HAM.js +0 -36
- package/dist/scheduler-CXWQ6Z4E.js +0 -30
- package/dist/sleep-manager-HINI6Y46.js +0 -34
- package/dist/system-chat-4DQZOEZI.js +0 -34
- package/dist/web-assets/assets/index-Domoz5Cg.js +0 -79
- package/templates/_base/.init/.config/hooks/pre-prompt/session-activity.ts +0 -40
package/dist/daemon.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
RESTIC_INSTALL_HINT,
|
|
4
|
+
initRepo,
|
|
5
|
+
listSnapshots,
|
|
6
|
+
readBackupState,
|
|
7
|
+
resticVersion,
|
|
8
|
+
runBackup
|
|
9
|
+
} from "./chunk-FXORA5JG.js";
|
|
2
10
|
import {
|
|
3
11
|
acceptPending,
|
|
4
12
|
formatFileSize,
|
|
@@ -6,25 +14,25 @@ import {
|
|
|
6
14
|
rejectPending,
|
|
7
15
|
stageFile,
|
|
8
16
|
validateFilePath
|
|
9
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-R77O2WMK.js";
|
|
10
18
|
import {
|
|
11
19
|
findOpenClawSession,
|
|
12
20
|
importOpenClawConnectors,
|
|
13
21
|
importPiSession,
|
|
14
22
|
parseNameFromIdentity
|
|
15
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-A7WQZKOU.js";
|
|
16
24
|
import {
|
|
17
25
|
checkForUpdate,
|
|
18
26
|
checkForUpdateCached,
|
|
19
27
|
getCurrentVersion
|
|
20
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-6EMWJZBK.js";
|
|
21
29
|
import {
|
|
22
30
|
normalizeAvatar,
|
|
23
31
|
safeResolveWithinBase
|
|
24
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-DRJ24GXK.js";
|
|
25
33
|
import {
|
|
26
34
|
isHomeOnlyArchive
|
|
27
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-QCN24XEN.js";
|
|
28
36
|
import {
|
|
29
37
|
computeTemplateHash
|
|
30
38
|
} from "./chunk-QMJCNZ6C.js";
|
|
@@ -34,7 +42,7 @@ import {
|
|
|
34
42
|
fixModelEscapes,
|
|
35
43
|
getPlatformDriver,
|
|
36
44
|
routeOutboundBridge
|
|
37
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-NYC5U6K7.js";
|
|
38
46
|
import {
|
|
39
47
|
getBridgeConfig,
|
|
40
48
|
readBridgesConfig,
|
|
@@ -43,7 +51,7 @@ import {
|
|
|
43
51
|
resolveChannelMapping,
|
|
44
52
|
setBridgeConfig,
|
|
45
53
|
setChannelMapping
|
|
46
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-RXEEYDIB.js";
|
|
47
55
|
import {
|
|
48
56
|
MindStartupError,
|
|
49
57
|
RestartTracker,
|
|
@@ -63,7 +71,7 @@ import {
|
|
|
63
71
|
ensureSystemChannel,
|
|
64
72
|
formatHoldNotice,
|
|
65
73
|
formatNotices,
|
|
66
|
-
|
|
74
|
+
generateSystemFallbackReply,
|
|
67
75
|
getAllDiscoveredExtensions,
|
|
68
76
|
getAllDiscoveredExtensionsDetailed,
|
|
69
77
|
getDeliveryManager,
|
|
@@ -99,20 +107,21 @@ import {
|
|
|
99
107
|
requireAdminOrSystem,
|
|
100
108
|
requireSelf,
|
|
101
109
|
setExtensionEnabled,
|
|
110
|
+
shouldGenerateSystemFallback,
|
|
102
111
|
startMindFull,
|
|
103
112
|
stopMindFull,
|
|
104
113
|
syncProviderToMinds,
|
|
105
114
|
uninstallNpmExtension,
|
|
106
115
|
writeSystemsConfig
|
|
107
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-YT7PEESJ.js";
|
|
108
117
|
import {
|
|
109
118
|
loadMergedEnv,
|
|
110
119
|
mindEnvPath,
|
|
111
120
|
readEnv,
|
|
112
121
|
sharedEnvPath,
|
|
113
122
|
writeEnv
|
|
114
|
-
} from "./chunk-
|
|
115
|
-
import "./chunk-
|
|
123
|
+
} from "./chunk-ZDZISKCL.js";
|
|
124
|
+
import "./chunk-FR6S2KNN.js";
|
|
116
125
|
import {
|
|
117
126
|
applyInitFiles,
|
|
118
127
|
applyTemplateHomeFiles,
|
|
@@ -141,7 +150,7 @@ import {
|
|
|
141
150
|
syncBuiltinSkills,
|
|
142
151
|
uninstallSkill,
|
|
143
152
|
updateSkill
|
|
144
|
-
} from "./chunk-
|
|
153
|
+
} from "./chunk-7ZUB63PS.js";
|
|
145
154
|
import {
|
|
146
155
|
addMessage,
|
|
147
156
|
createChannel,
|
|
@@ -173,23 +182,23 @@ import {
|
|
|
173
182
|
setConversationPrivate,
|
|
174
183
|
subscribe as subscribe2,
|
|
175
184
|
updateChannelSettings
|
|
176
|
-
} from "./chunk-
|
|
185
|
+
} from "./chunk-OP4JG2BS.js";
|
|
177
186
|
import {
|
|
178
187
|
readVoluteConfig,
|
|
179
188
|
writeVoluteConfig
|
|
180
|
-
} from "./chunk-
|
|
189
|
+
} from "./chunk-PFZBNKUH.js";
|
|
181
190
|
import {
|
|
182
191
|
isSandboxEnabled,
|
|
183
192
|
wrapForSandbox
|
|
184
|
-
} from "./chunk-
|
|
193
|
+
} from "./chunk-JZ62SYWR.js";
|
|
185
194
|
import {
|
|
186
195
|
getActiveMinds,
|
|
187
196
|
onMindEvent,
|
|
188
197
|
stopAll
|
|
189
|
-
} from "./chunk-
|
|
198
|
+
} from "./chunk-EJVPTVTI.js";
|
|
190
199
|
import {
|
|
191
200
|
extractTextContent
|
|
192
|
-
} from "./chunk-
|
|
201
|
+
} from "./chunk-4JOQZPCE.js";
|
|
193
202
|
import {
|
|
194
203
|
PROMPT_DEFAULTS,
|
|
195
204
|
PROMPT_KEYS,
|
|
@@ -198,10 +207,10 @@ import {
|
|
|
198
207
|
completeTurn,
|
|
199
208
|
createTurn,
|
|
200
209
|
getActiveTurnId,
|
|
201
|
-
getLastToolUseEventId,
|
|
202
210
|
getMindPromptDefaults,
|
|
203
211
|
getPrompt,
|
|
204
212
|
getPromptIfCustom,
|
|
213
|
+
getToolUseEventId,
|
|
205
214
|
initSummarizer,
|
|
206
215
|
markErrored,
|
|
207
216
|
publish as publish2,
|
|
@@ -212,8 +221,8 @@ import {
|
|
|
212
221
|
summarizeTurn,
|
|
213
222
|
takeErrored,
|
|
214
223
|
trackToolUse
|
|
215
|
-
} from "./chunk-
|
|
216
|
-
import "./chunk-
|
|
224
|
+
} from "./chunk-UYLGEDVD.js";
|
|
225
|
+
import "./chunk-TQJ6ZYVY.js";
|
|
217
226
|
import {
|
|
218
227
|
chownMindDir,
|
|
219
228
|
createMindUser,
|
|
@@ -224,9 +233,10 @@ import {
|
|
|
224
233
|
isIsolationEnabled,
|
|
225
234
|
resolveVoluteBin,
|
|
226
235
|
wrapForIsolation
|
|
227
|
-
} from "./chunk-
|
|
236
|
+
} from "./chunk-H2X54EHC.js";
|
|
228
237
|
import {
|
|
229
238
|
addCustomModel,
|
|
239
|
+
aiCompleteUtility,
|
|
230
240
|
buildCustomModel,
|
|
231
241
|
getAiConfig,
|
|
232
242
|
getAvailableModels,
|
|
@@ -245,12 +255,12 @@ import {
|
|
|
245
255
|
setProviderRefreshHook,
|
|
246
256
|
setUtilityModel,
|
|
247
257
|
unqualifyModelId
|
|
248
|
-
} from "./chunk-
|
|
258
|
+
} from "./chunk-IHKGWTGT.js";
|
|
249
259
|
import {
|
|
250
260
|
isSetupComplete,
|
|
251
261
|
readGlobalConfig,
|
|
252
262
|
writeGlobalConfig
|
|
253
|
-
} from "./chunk-
|
|
263
|
+
} from "./chunk-F7H6ATM4.js";
|
|
254
264
|
import {
|
|
255
265
|
approveUser,
|
|
256
266
|
changePassword,
|
|
@@ -269,11 +279,11 @@ import {
|
|
|
269
279
|
syncMindProfile,
|
|
270
280
|
updateUserProfile,
|
|
271
281
|
verifyUser
|
|
272
|
-
} from "./chunk-
|
|
282
|
+
} from "./chunk-T6HYVHPG.js";
|
|
273
283
|
import {
|
|
274
284
|
broadcast,
|
|
275
285
|
subscribe
|
|
276
|
-
} from "./chunk-
|
|
286
|
+
} from "./chunk-7C44R625.js";
|
|
277
287
|
import {
|
|
278
288
|
logBuffer,
|
|
279
289
|
logger_default
|
|
@@ -297,6 +307,7 @@ import {
|
|
|
297
307
|
readAllMinds,
|
|
298
308
|
readRegistry,
|
|
299
309
|
removeMind,
|
|
310
|
+
resolveMindDir,
|
|
300
311
|
setMindRunning,
|
|
301
312
|
setMindStage,
|
|
302
313
|
setMindTemplate,
|
|
@@ -305,7 +316,7 @@ import {
|
|
|
305
316
|
validateMindName,
|
|
306
317
|
voluteHome,
|
|
307
318
|
voluteSystemDir
|
|
308
|
-
} from "./chunk-
|
|
319
|
+
} from "./chunk-ALKYQULU.js";
|
|
309
320
|
import {
|
|
310
321
|
activity,
|
|
311
322
|
channels,
|
|
@@ -320,12 +331,76 @@ import {
|
|
|
320
331
|
import "./chunk-K3NQKI34.js";
|
|
321
332
|
|
|
322
333
|
// packages/daemon/src/daemon.ts
|
|
323
|
-
import { randomBytes as
|
|
334
|
+
import { randomBytes as randomBytes3 } from "crypto";
|
|
324
335
|
import { chmodSync, mkdirSync as mkdirSync10, readFileSync as readFileSync10, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "fs";
|
|
325
336
|
import { homedir as homedir3 } from "os";
|
|
326
337
|
import { resolve as resolve16 } from "path";
|
|
327
338
|
import { format } from "util";
|
|
328
339
|
|
|
340
|
+
// packages/daemon/src/lib/daemon/backup-manager.ts
|
|
341
|
+
import { CronExpressionParser } from "cron-parser";
|
|
342
|
+
var blog = logger_default.child("backup");
|
|
343
|
+
var DEFAULT_BACKUP_SCHEDULE = "0 3 * * *";
|
|
344
|
+
var BackupManager = class {
|
|
345
|
+
interval = null;
|
|
346
|
+
lastFiredMinute = -1;
|
|
347
|
+
warnedUnconfigured = false;
|
|
348
|
+
start() {
|
|
349
|
+
this.interval = setInterval(() => {
|
|
350
|
+
this.tick().catch((err) => blog.error("backup tick failed", logger_default.errorData(err)));
|
|
351
|
+
}, 6e4);
|
|
352
|
+
}
|
|
353
|
+
stop() {
|
|
354
|
+
if (this.interval) clearInterval(this.interval);
|
|
355
|
+
this.interval = null;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* True at most once per scheduled fire minute (records the minute it
|
|
359
|
+
* consumed), and only when backups are enabled and runnable. Not a pure
|
|
360
|
+
* predicate — a second call in the same minute returns false.
|
|
361
|
+
*/
|
|
362
|
+
isDue(now = /* @__PURE__ */ new Date()) {
|
|
363
|
+
const config2 = readGlobalConfig().backup;
|
|
364
|
+
if (!config2?.enabled) return false;
|
|
365
|
+
if (!config2.repository || !config2.password) {
|
|
366
|
+
if (!this.warnedUnconfigured) {
|
|
367
|
+
blog.warn("scheduled backups are enabled but no repository is initialized \u2014 not running");
|
|
368
|
+
this.warnedUnconfigured = true;
|
|
369
|
+
}
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
this.warnedUnconfigured = false;
|
|
373
|
+
const cron = config2.schedule || DEFAULT_BACKUP_SCHEDULE;
|
|
374
|
+
const epochMinute = Math.floor(now.getTime() / 6e4);
|
|
375
|
+
if (epochMinute === this.lastFiredMinute) return false;
|
|
376
|
+
let prevMinute;
|
|
377
|
+
try {
|
|
378
|
+
const interval = CronExpressionParser.parse(cron, { currentDate: now });
|
|
379
|
+
prevMinute = Math.floor(interval.prev().toDate().getTime() / 6e4);
|
|
380
|
+
} catch (err) {
|
|
381
|
+
blog.warn(`invalid backup cron "${cron}"`, logger_default.errorData(err));
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
if (prevMinute !== epochMinute) return false;
|
|
385
|
+
this.lastFiredMinute = epochMinute;
|
|
386
|
+
return true;
|
|
387
|
+
}
|
|
388
|
+
async tick() {
|
|
389
|
+
if (!this.isDue()) return;
|
|
390
|
+
blog.info("scheduled backup starting");
|
|
391
|
+
try {
|
|
392
|
+
await runBackup();
|
|
393
|
+
} catch (err) {
|
|
394
|
+
blog.error("scheduled backup failed", logger_default.errorData(err));
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
var backupManager = null;
|
|
399
|
+
function initBackupManager() {
|
|
400
|
+
if (!backupManager) backupManager = new BackupManager();
|
|
401
|
+
return backupManager;
|
|
402
|
+
}
|
|
403
|
+
|
|
329
404
|
// packages/daemon/src/lib/daemon/bridge-manager.ts
|
|
330
405
|
import { spawn } from "child_process";
|
|
331
406
|
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, unlinkSync, writeFileSync } from "fs";
|
|
@@ -394,7 +469,7 @@ function checkMissingBridgeEnv(def, env) {
|
|
|
394
469
|
}
|
|
395
470
|
|
|
396
471
|
// packages/daemon/src/lib/daemon/bridge-manager.ts
|
|
397
|
-
var
|
|
472
|
+
var blog2 = logger_default.child("bridges");
|
|
398
473
|
function searchUpwards(...segments) {
|
|
399
474
|
let searchDir = dirname(new URL(import.meta.url).pathname);
|
|
400
475
|
for (let i = 0; i < 5; i++) {
|
|
@@ -415,7 +490,7 @@ var BridgeManager = class {
|
|
|
415
490
|
await Promise.all(
|
|
416
491
|
platforms.map(
|
|
417
492
|
(platform) => this.startBridge(platform, daemonPort).catch((err) => {
|
|
418
|
-
|
|
493
|
+
blog2.warn(`failed to start bridge ${platform}`, logger_default.errorData(err));
|
|
419
494
|
})
|
|
420
495
|
)
|
|
421
496
|
);
|
|
@@ -444,7 +519,7 @@ var BridgeManager = class {
|
|
|
444
519
|
}
|
|
445
520
|
} catch (err) {
|
|
446
521
|
if (err instanceof Error && err.code !== "ESRCH") {
|
|
447
|
-
|
|
522
|
+
blog2.warn(`failed to stop existing bridge ${platform}`, logger_default.errorData(err));
|
|
448
523
|
}
|
|
449
524
|
res();
|
|
450
525
|
}
|
|
@@ -509,24 +584,24 @@ var BridgeManager = class {
|
|
|
509
584
|
}
|
|
510
585
|
if (this.shuttingDown) return;
|
|
511
586
|
if (this.stopping.has(platform)) return;
|
|
512
|
-
|
|
513
|
-
if (lastStderr)
|
|
587
|
+
blog2.error(`bridge ${platform} exited with code ${code}`);
|
|
588
|
+
if (lastStderr) blog2.warn(`bridge ${platform} last output: ${lastStderr}`);
|
|
514
589
|
const { shouldRestart, delay, attempt } = this.restartTracker.recordCrash(platform);
|
|
515
590
|
if (!shouldRestart) {
|
|
516
|
-
|
|
591
|
+
blog2.error(`bridge ${platform} crashed ${attempt} times \u2014 giving up`);
|
|
517
592
|
return;
|
|
518
593
|
}
|
|
519
|
-
|
|
594
|
+
blog2.info(
|
|
520
595
|
`restarting bridge ${platform} \u2014 attempt ${attempt}/${this.restartTracker.maxRestartAttempts}, in ${delay}ms`
|
|
521
596
|
);
|
|
522
597
|
setTimeout(() => {
|
|
523
598
|
if (this.shuttingDown || this.stopping.has(platform)) return;
|
|
524
599
|
this.startBridge(platform, daemonPort).catch((err) => {
|
|
525
|
-
|
|
600
|
+
blog2.error(`failed to restart bridge ${platform}`, logger_default.errorData(err));
|
|
526
601
|
});
|
|
527
602
|
}, delay);
|
|
528
603
|
});
|
|
529
|
-
|
|
604
|
+
blog2.info(`started bridge ${platform}`);
|
|
530
605
|
}
|
|
531
606
|
async stopBridge(platform) {
|
|
532
607
|
const tracked = this.bridges.get(platform);
|
|
@@ -543,7 +618,7 @@ var BridgeManager = class {
|
|
|
543
618
|
}
|
|
544
619
|
} catch (err) {
|
|
545
620
|
if (err instanceof Error && err.code !== "ESRCH") {
|
|
546
|
-
|
|
621
|
+
blog2.warn(`failed to stop bridge ${platform}`, logger_default.errorData(err));
|
|
547
622
|
}
|
|
548
623
|
resolve17();
|
|
549
624
|
}
|
|
@@ -564,9 +639,9 @@ var BridgeManager = class {
|
|
|
564
639
|
try {
|
|
565
640
|
this.removeBridgePid(platform);
|
|
566
641
|
} catch (err) {
|
|
567
|
-
|
|
642
|
+
blog2.warn(`failed to remove PID file for bridge ${platform}`, logger_default.errorData(err));
|
|
568
643
|
}
|
|
569
|
-
|
|
644
|
+
blog2.info(`stopped bridge ${platform}`);
|
|
570
645
|
}
|
|
571
646
|
async stopAll() {
|
|
572
647
|
this.shuttingDown = true;
|
|
@@ -596,7 +671,7 @@ var BridgeManager = class {
|
|
|
596
671
|
unlinkSync(this.bridgePidPath(platform));
|
|
597
672
|
} catch (err) {
|
|
598
673
|
if (err instanceof Error && err.code !== "ENOENT") {
|
|
599
|
-
|
|
674
|
+
blog2.warn(`failed to remove PID file for bridge ${platform}`, logger_default.errorData(err));
|
|
600
675
|
}
|
|
601
676
|
}
|
|
602
677
|
}
|
|
@@ -614,18 +689,18 @@ var BridgeManager = class {
|
|
|
614
689
|
} catch {
|
|
615
690
|
}
|
|
616
691
|
}
|
|
617
|
-
|
|
692
|
+
blog2.warn(`killed orphan bridge ${platform} (pid ${pid})`);
|
|
618
693
|
}
|
|
619
694
|
} catch (err) {
|
|
620
695
|
if (err instanceof Error && err.code !== "ESRCH") {
|
|
621
|
-
|
|
696
|
+
blog2.debug(`orphan bridge ${platform} cleanup: ${err}`);
|
|
622
697
|
}
|
|
623
698
|
}
|
|
624
699
|
try {
|
|
625
700
|
unlinkSync(pidPath);
|
|
626
701
|
} catch (err) {
|
|
627
702
|
if (err instanceof Error && err.code !== "ENOENT") {
|
|
628
|
-
|
|
703
|
+
blog2.warn(`failed to clean up PID file for orphan bridge ${platform}`, logger_default.errorData(err));
|
|
629
704
|
}
|
|
630
705
|
}
|
|
631
706
|
}
|
|
@@ -1400,10 +1475,10 @@ function getCachedApiKey(provider) {
|
|
|
1400
1475
|
var keyRefreshTimer = null;
|
|
1401
1476
|
var slog = logger_default.child("ai-keys");
|
|
1402
1477
|
var oauthHealth = /* @__PURE__ */ new Map();
|
|
1403
|
-
function needsRefresh(oauth) {
|
|
1478
|
+
function needsRefresh(oauth, now = Date.now()) {
|
|
1404
1479
|
const expires = oauth.expires;
|
|
1405
|
-
if (!expires ||
|
|
1406
|
-
return expires -
|
|
1480
|
+
if (!expires || now >= expires) return true;
|
|
1481
|
+
return expires - now < 15 * 60 * 1e3;
|
|
1407
1482
|
}
|
|
1408
1483
|
async function refreshApiKeyCache() {
|
|
1409
1484
|
const ai = getAiConfig();
|
|
@@ -1457,7 +1532,7 @@ function stopApiKeyRefresh() {
|
|
|
1457
1532
|
var system_default = app;
|
|
1458
1533
|
|
|
1459
1534
|
// packages/daemon/src/web/app.ts
|
|
1460
|
-
import { Hono as
|
|
1535
|
+
import { Hono as Hono29 } from "hono";
|
|
1461
1536
|
import { bodyLimit } from "hono/body-limit";
|
|
1462
1537
|
import { cors } from "hono/cors";
|
|
1463
1538
|
import { csrf } from "hono/csrf";
|
|
@@ -1824,10 +1899,115 @@ var app3 = new Hono3().post("/register", zValidator2("json", credentialsSchema),
|
|
|
1824
1899
|
}).route("/", admin).route("/", authenticated);
|
|
1825
1900
|
var auth_default = app3;
|
|
1826
1901
|
|
|
1827
|
-
// packages/daemon/src/web/api/
|
|
1902
|
+
// packages/daemon/src/web/api/backup.ts
|
|
1903
|
+
import { randomBytes } from "crypto";
|
|
1828
1904
|
import { zValidator as zValidator3 } from "@hono/zod-validator";
|
|
1905
|
+
import { CronExpressionParser as CronExpressionParser2 } from "cron-parser";
|
|
1829
1906
|
import { Hono as Hono4 } from "hono";
|
|
1830
1907
|
import { z as z3 } from "zod";
|
|
1908
|
+
function redactedConfig() {
|
|
1909
|
+
const backup2 = readGlobalConfig().backup ?? {};
|
|
1910
|
+
return {
|
|
1911
|
+
repository: backup2.repository,
|
|
1912
|
+
schedule: backup2.schedule ?? DEFAULT_BACKUP_SCHEDULE,
|
|
1913
|
+
enabled: backup2.enabled,
|
|
1914
|
+
keep: backup2.keep,
|
|
1915
|
+
includeSessions: backup2.includeSessions,
|
|
1916
|
+
hasPassword: !!backup2.password,
|
|
1917
|
+
envKeys: Object.keys(backup2.env ?? {})
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1920
|
+
var configSchema = z3.object({
|
|
1921
|
+
repository: z3.string().optional(),
|
|
1922
|
+
schedule: z3.string().refine(
|
|
1923
|
+
(cron) => {
|
|
1924
|
+
try {
|
|
1925
|
+
CronExpressionParser2.parse(cron);
|
|
1926
|
+
return true;
|
|
1927
|
+
} catch {
|
|
1928
|
+
return false;
|
|
1929
|
+
}
|
|
1930
|
+
},
|
|
1931
|
+
{ message: "Invalid cron expression" }
|
|
1932
|
+
).optional(),
|
|
1933
|
+
enabled: z3.boolean().optional(),
|
|
1934
|
+
keep: z3.object({
|
|
1935
|
+
daily: z3.number().int().min(0).optional(),
|
|
1936
|
+
weekly: z3.number().int().min(0).optional(),
|
|
1937
|
+
monthly: z3.number().int().min(0).optional()
|
|
1938
|
+
}).refine((keep) => !(keep.daily === 0 && keep.weekly === 0 && keep.monthly === 0), {
|
|
1939
|
+
message: "Retention cannot be zero everywhere \u2014 prune would delete every snapshot"
|
|
1940
|
+
}).optional(),
|
|
1941
|
+
includeSessions: z3.boolean().optional(),
|
|
1942
|
+
password: z3.string().optional(),
|
|
1943
|
+
env: z3.record(z3.string(), z3.string()).optional()
|
|
1944
|
+
});
|
|
1945
|
+
var backup = new Hono4().get("/config", requireAdmin, (c) => c.json(redactedConfig())).put("/config", requireAdmin, zValidator3("json", configSchema), (c) => {
|
|
1946
|
+
const updates = c.req.valid("json");
|
|
1947
|
+
const config2 = readGlobalConfig();
|
|
1948
|
+
const current = config2.backup ?? {};
|
|
1949
|
+
config2.backup = {
|
|
1950
|
+
...current,
|
|
1951
|
+
...updates,
|
|
1952
|
+
// Empty-string password means "keep existing" so the UI can save
|
|
1953
|
+
// settings without re-entering the passphrase.
|
|
1954
|
+
password: updates.password || current.password,
|
|
1955
|
+
env: updates.env ?? current.env
|
|
1956
|
+
};
|
|
1957
|
+
writeGlobalConfig(config2);
|
|
1958
|
+
return c.json(redactedConfig());
|
|
1959
|
+
}).post("/init", requireAdmin, async (c) => {
|
|
1960
|
+
const config2 = readGlobalConfig();
|
|
1961
|
+
if (!config2.backup?.repository) {
|
|
1962
|
+
return c.json({ error: "Backup repository is not configured" }, 400);
|
|
1963
|
+
}
|
|
1964
|
+
let generatedPassword = null;
|
|
1965
|
+
if (!config2.backup.password) {
|
|
1966
|
+
generatedPassword = randomBytes(32).toString("base64url");
|
|
1967
|
+
config2.backup.password = generatedPassword;
|
|
1968
|
+
}
|
|
1969
|
+
try {
|
|
1970
|
+
await initRepo(config2.backup);
|
|
1971
|
+
} catch (err) {
|
|
1972
|
+
const stderr = err.stderr;
|
|
1973
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
1974
|
+
return c.json({ error: stderr?.trim() || detail }, 500);
|
|
1975
|
+
}
|
|
1976
|
+
if (generatedPassword) writeGlobalConfig(config2);
|
|
1977
|
+
return c.json({ ok: true, password: generatedPassword });
|
|
1978
|
+
}).post("/run", requireAdmin, async (c) => {
|
|
1979
|
+
try {
|
|
1980
|
+
const summary = await runBackup();
|
|
1981
|
+
return c.json(summary);
|
|
1982
|
+
} catch (err) {
|
|
1983
|
+
const stderr = err.stderr;
|
|
1984
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
1985
|
+
return c.json({ error: stderr?.trim() || detail }, 500);
|
|
1986
|
+
}
|
|
1987
|
+
}).get("/snapshots", requireAdmin, async (c) => {
|
|
1988
|
+
try {
|
|
1989
|
+
return c.json(await listSnapshots());
|
|
1990
|
+
} catch (err) {
|
|
1991
|
+
const stderr = err.stderr;
|
|
1992
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
1993
|
+
return c.json({ error: stderr?.trim() || detail }, 500);
|
|
1994
|
+
}
|
|
1995
|
+
}).get("/status", requireAdmin, async (c) => {
|
|
1996
|
+
const version = await resticVersion();
|
|
1997
|
+
return c.json({
|
|
1998
|
+
resticInstalled: version !== null,
|
|
1999
|
+
resticVersion: version,
|
|
2000
|
+
installHint: version === null ? RESTIC_INSTALL_HINT : null,
|
|
2001
|
+
config: redactedConfig(),
|
|
2002
|
+
state: readBackupState()
|
|
2003
|
+
});
|
|
2004
|
+
});
|
|
2005
|
+
var backup_default = backup;
|
|
2006
|
+
|
|
2007
|
+
// packages/daemon/src/web/api/bridges.ts
|
|
2008
|
+
import { zValidator as zValidator4 } from "@hono/zod-validator";
|
|
2009
|
+
import { Hono as Hono5 } from "hono";
|
|
2010
|
+
import { z as z4 } from "zod";
|
|
1831
2011
|
|
|
1832
2012
|
// packages/daemon/src/lib/chat/puppets.ts
|
|
1833
2013
|
import { and as and2, eq as eq2 } from "drizzle-orm";
|
|
@@ -1916,27 +2096,27 @@ async function fanOutToMinds(opts) {
|
|
|
1916
2096
|
}
|
|
1917
2097
|
|
|
1918
2098
|
// packages/daemon/src/web/api/bridges.ts
|
|
1919
|
-
var inboundSchema =
|
|
1920
|
-
content:
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
2099
|
+
var inboundSchema = z4.object({
|
|
2100
|
+
content: z4.array(
|
|
2101
|
+
z4.union([
|
|
2102
|
+
z4.object({ type: z4.literal("text"), text: z4.string() }),
|
|
2103
|
+
z4.object({ type: z4.literal("image"), media_type: z4.string(), data: z4.string() })
|
|
1924
2104
|
])
|
|
1925
2105
|
).min(1),
|
|
1926
|
-
platformUserId:
|
|
1927
|
-
displayName:
|
|
1928
|
-
externalChannel:
|
|
1929
|
-
isDM:
|
|
1930
|
-
targetMind:
|
|
2106
|
+
platformUserId: z4.string(),
|
|
2107
|
+
displayName: z4.string(),
|
|
2108
|
+
externalChannel: z4.string(),
|
|
2109
|
+
isDM: z4.boolean(),
|
|
2110
|
+
targetMind: z4.string().optional()
|
|
1931
2111
|
});
|
|
1932
|
-
var mappingSchema =
|
|
1933
|
-
externalChannel:
|
|
1934
|
-
voluteChannel:
|
|
2112
|
+
var mappingSchema = z4.object({
|
|
2113
|
+
externalChannel: z4.string(),
|
|
2114
|
+
voluteChannel: z4.string()
|
|
1935
2115
|
});
|
|
1936
|
-
var enableSchema =
|
|
1937
|
-
defaultMind:
|
|
2116
|
+
var enableSchema = z4.object({
|
|
2117
|
+
defaultMind: z4.string()
|
|
1938
2118
|
});
|
|
1939
|
-
var app4 = new
|
|
2119
|
+
var app4 = new Hono5().post("/:platform/inbound", zValidator4("json", inboundSchema), async (c) => {
|
|
1940
2120
|
const user = c.get("user");
|
|
1941
2121
|
if (user.id !== 0) return c.json({ error: "Bridge inbound requires daemon token" }, 403);
|
|
1942
2122
|
const platform = c.req.param("platform");
|
|
@@ -1988,7 +2168,7 @@ var app4 = new Hono4().post("/:platform/inbound", zValidator3("json", inboundSch
|
|
|
1988
2168
|
}
|
|
1989
2169
|
const participants = await getParticipants(channel.id);
|
|
1990
2170
|
if (!participants.some((p) => p.userId === puppet.id)) {
|
|
1991
|
-
const { addParticipant } = await import("./conversations-
|
|
2171
|
+
const { addParticipant } = await import("./conversations-JZTD6KLR.js");
|
|
1992
2172
|
await addParticipant(channel.id, puppet.id);
|
|
1993
2173
|
}
|
|
1994
2174
|
const contentBlocks = body.content;
|
|
@@ -2018,7 +2198,7 @@ var app4 = new Hono4().post("/:platform/inbound", zValidator3("json", inboundSch
|
|
|
2018
2198
|
};
|
|
2019
2199
|
});
|
|
2020
2200
|
return c.json(bridges);
|
|
2021
|
-
}).post("/:platform", requireAdmin,
|
|
2201
|
+
}).post("/:platform", requireAdmin, zValidator4("json", enableSchema), async (c) => {
|
|
2022
2202
|
const platform = c.req.param("platform");
|
|
2023
2203
|
const body = c.req.valid("json");
|
|
2024
2204
|
const def = getBridgeDef(platform);
|
|
@@ -2057,7 +2237,7 @@ var app4 = new Hono4().post("/:platform/inbound", zValidator3("json", inboundSch
|
|
|
2057
2237
|
await manager.stopBridge(platform);
|
|
2058
2238
|
removeBridgeConfig(platform);
|
|
2059
2239
|
return c.json({ ok: true });
|
|
2060
|
-
}).put("/:platform/mappings", requireAdmin,
|
|
2240
|
+
}).put("/:platform/mappings", requireAdmin, zValidator4("json", mappingSchema), (c) => {
|
|
2061
2241
|
const platform = c.req.param("platform");
|
|
2062
2242
|
const body = c.req.valid("json");
|
|
2063
2243
|
try {
|
|
@@ -2088,11 +2268,11 @@ async function fanOutToBridgedMinds(opts) {
|
|
|
2088
2268
|
var bridges_default = app4;
|
|
2089
2269
|
|
|
2090
2270
|
// packages/daemon/src/web/api/channels.ts
|
|
2091
|
-
import { Hono as
|
|
2271
|
+
import { Hono as Hono6 } from "hono";
|
|
2092
2272
|
function buildEnv(name) {
|
|
2093
2273
|
return { ...loadMergedEnv(name), VOLUTE_MIND: name, VOLUTE_MIND_DIR: mindDir(name) };
|
|
2094
2274
|
}
|
|
2095
|
-
var app5 = new
|
|
2275
|
+
var app5 = new Hono6().post("/:name/channels/create", requireSelf(), async (c) => {
|
|
2096
2276
|
const name = c.req.param("name");
|
|
2097
2277
|
if (!await findMind(name)) return c.json({ error: "Mind not found" }, 404);
|
|
2098
2278
|
const {
|
|
@@ -2117,8 +2297,8 @@ var app5 = new Hono5().post("/:name/channels/create", requireSelf(), async (c) =
|
|
|
2117
2297
|
var channels_default = app5;
|
|
2118
2298
|
|
|
2119
2299
|
// packages/daemon/src/web/api/config.ts
|
|
2120
|
-
import { Hono as
|
|
2121
|
-
var config = new
|
|
2300
|
+
import { Hono as Hono7 } from "hono";
|
|
2301
|
+
var config = new Hono7();
|
|
2122
2302
|
config.get("/models", async (c) => {
|
|
2123
2303
|
const enabled = new Set(getEnabledModels());
|
|
2124
2304
|
const all = await getAvailableModels();
|
|
@@ -2145,8 +2325,8 @@ config.get("/status", (c) => {
|
|
|
2145
2325
|
var config_default = config;
|
|
2146
2326
|
|
|
2147
2327
|
// packages/daemon/src/web/api/env.ts
|
|
2148
|
-
import { Hono as
|
|
2149
|
-
var app6 = new
|
|
2328
|
+
import { Hono as Hono8 } from "hono";
|
|
2329
|
+
var app6 = new Hono8().get("/:name/env", requireSelf(), async (c) => {
|
|
2150
2330
|
const name = c.req.param("name");
|
|
2151
2331
|
if (!await findMind(name)) return c.json({ error: "Mind not found" }, 404);
|
|
2152
2332
|
const shared = readEnv(sharedEnvPath());
|
|
@@ -2189,7 +2369,7 @@ var app6 = new Hono7().get("/:name/env", requireSelf(), async (c) => {
|
|
|
2189
2369
|
writeEnv(path, env);
|
|
2190
2370
|
return c.json({ ok: true });
|
|
2191
2371
|
});
|
|
2192
|
-
var sharedEnvApp = new
|
|
2372
|
+
var sharedEnvApp = new Hono8().get("/", requireAdmin, (c) => {
|
|
2193
2373
|
return c.json(readEnv(sharedEnvPath()));
|
|
2194
2374
|
}).put("/:key", requireAdmin, async (c) => {
|
|
2195
2375
|
const key = c.req.param("key");
|
|
@@ -2219,8 +2399,8 @@ var sharedEnvApp = new Hono7().get("/", requireAdmin, (c) => {
|
|
|
2219
2399
|
var env_default = app6;
|
|
2220
2400
|
|
|
2221
2401
|
// packages/daemon/src/web/api/extensions.ts
|
|
2222
|
-
import { Hono as
|
|
2223
|
-
var app7 = new
|
|
2402
|
+
import { Hono as Hono9 } from "hono";
|
|
2403
|
+
var app7 = new Hono9().get("/", (c) => {
|
|
2224
2404
|
return c.json(getLoadedExtensions());
|
|
2225
2405
|
}).get("/all", (c) => {
|
|
2226
2406
|
const detail = c.req.query("detail") === "true";
|
|
@@ -2267,18 +2447,18 @@ var extensions_default = app7;
|
|
|
2267
2447
|
// packages/daemon/src/web/api/file-sharing.ts
|
|
2268
2448
|
import { readFileSync as readFileSync4, statSync as statSync2 } from "fs";
|
|
2269
2449
|
import { resolve as resolve4 } from "path";
|
|
2270
|
-
import { Hono as
|
|
2450
|
+
import { Hono as Hono10 } from "hono";
|
|
2271
2451
|
async function notifyMind(mindName, message) {
|
|
2272
2452
|
const entry = await findMind(mindName);
|
|
2273
2453
|
if (!entry) return;
|
|
2274
2454
|
try {
|
|
2275
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
2455
|
+
const { sendSystemMessage } = await import("./system-chat-XOALE2RD.js");
|
|
2276
2456
|
await sendSystemMessage(mindName, message);
|
|
2277
2457
|
} catch (err) {
|
|
2278
2458
|
logger_default.warn(`[file-sharing] notify mind ${mindName} failed`, logger_default.errorData(err));
|
|
2279
2459
|
}
|
|
2280
2460
|
}
|
|
2281
|
-
var app8 = new
|
|
2461
|
+
var app8 = new Hono10().post("/:name/files/send", requireSelf(), async (c) => {
|
|
2282
2462
|
const senderName = c.req.param("name");
|
|
2283
2463
|
const senderEntry = await findMind(senderName);
|
|
2284
2464
|
if (!senderEntry) return c.json({ error: "Sender mind not found" }, 404);
|
|
@@ -2398,7 +2578,7 @@ var file_sharing_default = app8;
|
|
|
2398
2578
|
import { mkdirSync as mkdirSync3, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
2399
2579
|
import { readdir, readFile, realpath, stat } from "fs/promises";
|
|
2400
2580
|
import { extname as extname2, resolve as resolve5 } from "path";
|
|
2401
|
-
import { Hono as
|
|
2581
|
+
import { Hono as Hono11 } from "hono";
|
|
2402
2582
|
var AVATAR_MIME2 = {
|
|
2403
2583
|
".png": "image/png",
|
|
2404
2584
|
".jpg": "image/jpeg",
|
|
@@ -2425,7 +2605,7 @@ var MIME_TYPES = {
|
|
|
2425
2605
|
".woff": "font/woff",
|
|
2426
2606
|
".woff2": "font/woff2"
|
|
2427
2607
|
};
|
|
2428
|
-
var app9 = new
|
|
2608
|
+
var app9 = new Hono11().post("/:name/avatar", requireSelf(), async (c) => {
|
|
2429
2609
|
const name = c.req.param("name");
|
|
2430
2610
|
const entry = await findMind(name);
|
|
2431
2611
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
@@ -2570,7 +2750,7 @@ var files_default = app9;
|
|
|
2570
2750
|
|
|
2571
2751
|
// packages/daemon/src/web/api/history.ts
|
|
2572
2752
|
import { and as and3, desc as desc2, eq as eq3, gte, inArray, sql } from "drizzle-orm";
|
|
2573
|
-
import { Hono as
|
|
2753
|
+
import { Hono as Hono12 } from "hono";
|
|
2574
2754
|
async function resolveMindFilter(c) {
|
|
2575
2755
|
const user = c.get("user");
|
|
2576
2756
|
if (user.role === "admin" || user.role === "system") {
|
|
@@ -2578,7 +2758,7 @@ async function resolveMindFilter(c) {
|
|
|
2578
2758
|
}
|
|
2579
2759
|
return getBaseName(user.username);
|
|
2580
2760
|
}
|
|
2581
|
-
var history = new
|
|
2761
|
+
var history = new Hono12().get("/turns", async (c) => {
|
|
2582
2762
|
const mindFilter = await resolveMindFilter(c);
|
|
2583
2763
|
const turnIdFilter = c.req.query("turnId");
|
|
2584
2764
|
const turnIdsFilter = c.req.query("turnIds");
|
|
@@ -2969,7 +3149,7 @@ var history = new Hono11().get("/turns", async (c) => {
|
|
|
2969
3149
|
var history_default = history;
|
|
2970
3150
|
|
|
2971
3151
|
// packages/daemon/src/web/api/keys.ts
|
|
2972
|
-
import { Hono as
|
|
3152
|
+
import { Hono as Hono13 } from "hono";
|
|
2973
3153
|
|
|
2974
3154
|
// packages/daemon/src/lib/mind/identity.ts
|
|
2975
3155
|
import { createHash, generateKeyPairSync, sign, verify } from "crypto";
|
|
@@ -3029,7 +3209,7 @@ async function publishPublicKey(mindName, publicKeyPem) {
|
|
|
3029
3209
|
}
|
|
3030
3210
|
|
|
3031
3211
|
// packages/daemon/src/web/api/keys.ts
|
|
3032
|
-
var app10 = new
|
|
3212
|
+
var app10 = new Hono13().get("/:fingerprint", async (c) => {
|
|
3033
3213
|
const fingerprint = c.req.param("fingerprint");
|
|
3034
3214
|
for (const entry of await readRegistry()) {
|
|
3035
3215
|
try {
|
|
@@ -3049,9 +3229,9 @@ var keys_default = app10;
|
|
|
3049
3229
|
import { spawn as spawn2 } from "child_process";
|
|
3050
3230
|
import { existsSync as existsSync5 } from "fs";
|
|
3051
3231
|
import { resolve as resolve7 } from "path";
|
|
3052
|
-
import { Hono as
|
|
3232
|
+
import { Hono as Hono14 } from "hono";
|
|
3053
3233
|
import { streamSSE as streamSSE3 } from "hono/streaming";
|
|
3054
|
-
var app11 = new
|
|
3234
|
+
var app11 = new Hono14().get("/:name/logs", requireSelf(), async (c) => {
|
|
3055
3235
|
const name = c.req.param("name");
|
|
3056
3236
|
const entry = await findMind(name);
|
|
3057
3237
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
@@ -3102,10 +3282,10 @@ var app11 = new Hono13().get("/:name/logs", requireSelf(), async (c) => {
|
|
|
3102
3282
|
var logs_default = app11;
|
|
3103
3283
|
|
|
3104
3284
|
// packages/daemon/src/web/api/mind-skills.ts
|
|
3105
|
-
import { zValidator as
|
|
3106
|
-
import { Hono as
|
|
3107
|
-
import { z as
|
|
3108
|
-
var app12 = new
|
|
3285
|
+
import { zValidator as zValidator5 } from "@hono/zod-validator";
|
|
3286
|
+
import { Hono as Hono15 } from "hono";
|
|
3287
|
+
import { z as z5 } from "zod";
|
|
3288
|
+
var app12 = new Hono15().get("/:name/skills", async (c) => {
|
|
3109
3289
|
const name = c.req.param("name");
|
|
3110
3290
|
const entry = await findMind(name);
|
|
3111
3291
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
@@ -3115,7 +3295,7 @@ var app12 = new Hono14().get("/:name/skills", async (c) => {
|
|
|
3115
3295
|
}).post(
|
|
3116
3296
|
"/:name/skills/install",
|
|
3117
3297
|
requireSelf(),
|
|
3118
|
-
|
|
3298
|
+
zValidator5("json", z5.object({ skillId: z5.string() })),
|
|
3119
3299
|
async (c) => {
|
|
3120
3300
|
const name = c.req.param("name");
|
|
3121
3301
|
const entry = await findMind(name);
|
|
@@ -3124,6 +3304,7 @@ var app12 = new Hono14().get("/:name/skills", async (c) => {
|
|
|
3124
3304
|
const dir = entry.dir ?? mindDir(name);
|
|
3125
3305
|
try {
|
|
3126
3306
|
const result = await installSkill(name, dir, skillId);
|
|
3307
|
+
await chownMindDir(dir, name);
|
|
3127
3308
|
return c.json({ ok: true, ...result });
|
|
3128
3309
|
} catch (e) {
|
|
3129
3310
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -3133,7 +3314,7 @@ var app12 = new Hono14().get("/:name/skills", async (c) => {
|
|
|
3133
3314
|
).post(
|
|
3134
3315
|
"/:name/skills/update",
|
|
3135
3316
|
requireSelf(),
|
|
3136
|
-
|
|
3317
|
+
zValidator5("json", z5.object({ skillId: z5.string() })),
|
|
3137
3318
|
async (c) => {
|
|
3138
3319
|
const name = c.req.param("name");
|
|
3139
3320
|
const entry = await findMind(name);
|
|
@@ -3142,6 +3323,7 @@ var app12 = new Hono14().get("/:name/skills", async (c) => {
|
|
|
3142
3323
|
const dir = entry.dir ?? mindDir(name);
|
|
3143
3324
|
try {
|
|
3144
3325
|
const result = await updateSkill(name, dir, skillId);
|
|
3326
|
+
await chownMindDir(dir, name);
|
|
3145
3327
|
return c.json(result);
|
|
3146
3328
|
} catch (e) {
|
|
3147
3329
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -3151,7 +3333,7 @@ var app12 = new Hono14().get("/:name/skills", async (c) => {
|
|
|
3151
3333
|
).post(
|
|
3152
3334
|
"/:name/skills/publish",
|
|
3153
3335
|
requireSelf(),
|
|
3154
|
-
|
|
3336
|
+
zValidator5("json", z5.object({ skillId: z5.string() })),
|
|
3155
3337
|
async (c) => {
|
|
3156
3338
|
const name = c.req.param("name");
|
|
3157
3339
|
const entry = await findMind(name);
|
|
@@ -3174,6 +3356,7 @@ var app12 = new Hono14().get("/:name/skills", async (c) => {
|
|
|
3174
3356
|
const dir = entry.dir ?? mindDir(name);
|
|
3175
3357
|
try {
|
|
3176
3358
|
await uninstallSkill(name, dir, skillName);
|
|
3359
|
+
await chownMindDir(dir, name);
|
|
3177
3360
|
} catch (e) {
|
|
3178
3361
|
const msg = e instanceof Error ? e.message : String(e);
|
|
3179
3362
|
return c.json({ error: msg }, 400);
|
|
@@ -3192,11 +3375,11 @@ import {
|
|
|
3192
3375
|
rmSync as rmSync4,
|
|
3193
3376
|
writeFileSync as writeFileSync7
|
|
3194
3377
|
} from "fs";
|
|
3195
|
-
import {
|
|
3196
|
-
import { zValidator as
|
|
3378
|
+
import { relative, resolve as resolve10 } from "path";
|
|
3379
|
+
import { zValidator as zValidator6 } from "@hono/zod-validator";
|
|
3197
3380
|
import { and as and5, desc as desc4, eq as eq5, sql as sql3 } from "drizzle-orm";
|
|
3198
|
-
import { Hono as
|
|
3199
|
-
import { z as
|
|
3381
|
+
import { Hono as Hono16 } from "hono";
|
|
3382
|
+
import { z as z6 } from "zod";
|
|
3200
3383
|
|
|
3201
3384
|
// packages/daemon/src/lib/daemon/turn-lifecycle.ts
|
|
3202
3385
|
import { and as and4, desc as desc3, eq as eq4, inArray as inArray2, sql as sql2 } from "drizzle-orm";
|
|
@@ -3313,13 +3496,18 @@ async function handleMindEvent(mind, event) {
|
|
|
3313
3496
|
}).returning({ id: mindHistory.id });
|
|
3314
3497
|
insertedId = result[0]?.id;
|
|
3315
3498
|
} catch (err) {
|
|
3316
|
-
llog.error(
|
|
3499
|
+
llog.error(
|
|
3500
|
+
`HISTORY GAP: failed to persist ${event.type} event for ${mind}${event.session ? ` (session ${event.session})` : ""}${event.channel ? ` on ${event.channel}` : ""}`,
|
|
3501
|
+
logger_default.errorData(err)
|
|
3502
|
+
);
|
|
3317
3503
|
}
|
|
3318
3504
|
if (event.type === "tool_use" && insertedId != null) {
|
|
3319
|
-
|
|
3505
|
+
const toolUseId = typeof event.metadata?.id === "string" ? event.metadata.id : void 0;
|
|
3506
|
+
trackToolUse(mind, event.session, insertedId, toolUseId);
|
|
3320
3507
|
}
|
|
3321
3508
|
if (event.type === "tool_result" && turnId && event.content) {
|
|
3322
|
-
const
|
|
3509
|
+
const resultToolUseId = typeof event.metadata?.tool_use_id === "string" ? event.metadata.tool_use_id : void 0;
|
|
3510
|
+
const toolUseEventId = getToolUseEventId(mind, event.session, resultToolUseId);
|
|
3323
3511
|
try {
|
|
3324
3512
|
await linkToolResultToTurn(mind, turnId, event.content, toolUseEventId);
|
|
3325
3513
|
} catch (err) {
|
|
@@ -3382,7 +3570,7 @@ async function handleMindEvent(mind, event) {
|
|
|
3382
3570
|
session: event.session,
|
|
3383
3571
|
kind: "budget",
|
|
3384
3572
|
reason: "token_budget",
|
|
3385
|
-
detail: "You've
|
|
3573
|
+
detail: "You've used your token budget for this period, so your activity may pause until it resets. This isn't anything you did wrong \u2014 it's just a rest imposed by the budget. Anything that arrives while you're paused will be kept for you. If you're mid-thought, this turn is a good moment to jot it down."
|
|
3386
3574
|
});
|
|
3387
3575
|
}
|
|
3388
3576
|
}
|
|
@@ -3413,35 +3601,50 @@ async function completeTurnAndSummarize(mind, event, insertedId) {
|
|
|
3413
3601
|
// packages/daemon/src/lib/mind/consolidate.ts
|
|
3414
3602
|
import { readdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
3415
3603
|
import { resolve as resolve8 } from "path";
|
|
3416
|
-
|
|
3604
|
+
var cLog = logger_default.child("consolidate");
|
|
3605
|
+
var MAX_CONSOLIDATION_INPUT_CHARS = 2e5;
|
|
3606
|
+
function readDailyLogs(memoryDir) {
|
|
3607
|
+
let files;
|
|
3608
|
+
try {
|
|
3609
|
+
files = readdirSync(memoryDir).filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)).sort();
|
|
3610
|
+
} catch {
|
|
3611
|
+
return [];
|
|
3612
|
+
}
|
|
3613
|
+
const logs = [];
|
|
3614
|
+
for (const filename of files) {
|
|
3615
|
+
const date = filename.replace(".md", "");
|
|
3616
|
+
const content = readFileSync6(resolve8(memoryDir, filename), "utf-8").trim();
|
|
3617
|
+
if (content) logs.push(`### ${date}
|
|
3618
|
+
|
|
3619
|
+
${content}`);
|
|
3620
|
+
}
|
|
3621
|
+
return logs;
|
|
3622
|
+
}
|
|
3623
|
+
function boundLogText(logs, maxChars = MAX_CONSOLIDATION_INPUT_CHARS) {
|
|
3624
|
+
const kept = [];
|
|
3625
|
+
let total = 0;
|
|
3626
|
+
for (let i = logs.length - 1; i >= 0; i--) {
|
|
3627
|
+
const len = logs[i].length + (kept.length > 0 ? 2 : 0);
|
|
3628
|
+
if (total + len > maxChars) break;
|
|
3629
|
+
kept.unshift(logs[i]);
|
|
3630
|
+
total += len;
|
|
3631
|
+
}
|
|
3632
|
+
if (kept.length === 0 && logs.length > 0) {
|
|
3633
|
+
return logs[logs.length - 1].slice(-maxChars);
|
|
3634
|
+
}
|
|
3635
|
+
return kept.join("\n\n");
|
|
3636
|
+
}
|
|
3637
|
+
async function consolidateMemory(mindDir2, complete = aiCompleteUtility) {
|
|
3417
3638
|
const soulPath = resolve8(mindDir2, "home/SOUL.md");
|
|
3418
3639
|
const memoryPath = resolve8(mindDir2, "home/MEMORY.md");
|
|
3419
3640
|
const memoryDir = resolve8(mindDir2, "home/memory");
|
|
3420
3641
|
const soul = readFileSync6(soulPath, "utf-8");
|
|
3421
|
-
const logs =
|
|
3422
|
-
try {
|
|
3423
|
-
const files = readdirSync(memoryDir).filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)).sort();
|
|
3424
|
-
for (const filename of files) {
|
|
3425
|
-
const date = filename.replace(".md", "");
|
|
3426
|
-
const content2 = readFileSync6(resolve8(memoryDir, filename), "utf-8").trim();
|
|
3427
|
-
if (content2) {
|
|
3428
|
-
logs.push(`### ${date}
|
|
3429
|
-
|
|
3430
|
-
${content2}`);
|
|
3431
|
-
}
|
|
3432
|
-
}
|
|
3433
|
-
} catch {
|
|
3434
|
-
}
|
|
3642
|
+
const logs = readDailyLogs(memoryDir);
|
|
3435
3643
|
if (logs.length === 0) {
|
|
3436
|
-
|
|
3437
|
-
return;
|
|
3438
|
-
}
|
|
3439
|
-
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
3440
|
-
if (!apiKey) {
|
|
3441
|
-
console.error("ANTHROPIC_API_KEY not set, skipping memory consolidation.");
|
|
3644
|
+
cLog.info("No daily logs found; skipping memory consolidation.");
|
|
3442
3645
|
return;
|
|
3443
3646
|
}
|
|
3444
|
-
|
|
3647
|
+
cLog.info("Consolidating memory from daily logs...");
|
|
3445
3648
|
const userMessage = [
|
|
3446
3649
|
"You have daily logs from a previous environment but no long-term memory file yet.",
|
|
3447
3650
|
"Please review the daily logs below and produce consolidated MEMORY.md content.",
|
|
@@ -3449,40 +3652,20 @@ ${content2}`);
|
|
|
3449
3652
|
"",
|
|
3450
3653
|
"## Daily logs",
|
|
3451
3654
|
"",
|
|
3452
|
-
logs
|
|
3655
|
+
boundLogText(logs)
|
|
3453
3656
|
].join("\n");
|
|
3454
|
-
const
|
|
3455
|
-
method: "POST",
|
|
3456
|
-
headers: {
|
|
3457
|
-
"Content-Type": "application/json",
|
|
3458
|
-
"x-api-key": apiKey,
|
|
3459
|
-
"anthropic-version": "2023-06-01"
|
|
3460
|
-
},
|
|
3461
|
-
body: JSON.stringify({
|
|
3462
|
-
model: "claude-sonnet-4-20250514",
|
|
3463
|
-
max_tokens: 4096,
|
|
3464
|
-
system: soul,
|
|
3465
|
-
messages: [{ role: "user", content: userMessage }]
|
|
3466
|
-
})
|
|
3467
|
-
});
|
|
3468
|
-
if (!res.ok) {
|
|
3469
|
-
const body = await res.text();
|
|
3470
|
-
console.error(`Anthropic API error (${res.status}): ${body}`);
|
|
3471
|
-
return;
|
|
3472
|
-
}
|
|
3473
|
-
const data = await res.json();
|
|
3474
|
-
const content = data.content.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("").trim();
|
|
3657
|
+
const content = (await complete(soul, userMessage))?.trim();
|
|
3475
3658
|
if (content) {
|
|
3476
3659
|
writeFileSync5(memoryPath, `${content}
|
|
3477
3660
|
`);
|
|
3478
|
-
|
|
3661
|
+
cLog.info("MEMORY.md created successfully.");
|
|
3479
3662
|
} else {
|
|
3480
|
-
|
|
3663
|
+
cLog.warn("No content produced; skipping memory consolidation.");
|
|
3481
3664
|
}
|
|
3482
3665
|
}
|
|
3483
3666
|
|
|
3484
3667
|
// packages/daemon/src/lib/mind/last-known-good.ts
|
|
3485
|
-
import { randomBytes } from "crypto";
|
|
3668
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
3486
3669
|
var glog = logger_default.child("last-known-good");
|
|
3487
3670
|
async function hasSrcChanges(dir, mindName) {
|
|
3488
3671
|
const status = (await gitExec(["status", "--porcelain", "--", "src"], { cwd: dir, mindName })).trim();
|
|
@@ -3491,7 +3674,7 @@ async function hasSrcChanges(dir, mindName) {
|
|
|
3491
3674
|
async function rollbackSrcChanges(dir, mindName) {
|
|
3492
3675
|
if (!await hasSrcChanges(dir, mindName)) return { parked: false };
|
|
3493
3676
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3494
|
-
const branch = `broken/${ts}-${
|
|
3677
|
+
const branch = `broken/${ts}-${randomBytes2(4).toString("hex")}`;
|
|
3495
3678
|
const opts = { cwd: dir, mindName };
|
|
3496
3679
|
await gitExec(["add", "--", "src"], opts);
|
|
3497
3680
|
await gitExec(
|
|
@@ -3524,7 +3707,7 @@ async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
|
|
|
3524
3707
|
logger_default.warn(`failed to stop variant ${variantName}`, logger_default.errorData(err));
|
|
3525
3708
|
}
|
|
3526
3709
|
}
|
|
3527
|
-
const { findMind: findMind2 } = await import("./registry-
|
|
3710
|
+
const { findMind: findMind2 } = await import("./registry-OUZBZ3Q4.js");
|
|
3528
3711
|
const variantEntry = await findMind2(variantName);
|
|
3529
3712
|
const branchName = variantEntry?.branch ?? variantName;
|
|
3530
3713
|
if (existsSync6(variantPath)) {
|
|
@@ -3753,7 +3936,7 @@ async function getMindStatus(name, port, registryRunning) {
|
|
|
3753
3936
|
const manager = getMindManager();
|
|
3754
3937
|
let status = "stopped";
|
|
3755
3938
|
try {
|
|
3756
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
3939
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
|
|
3757
3940
|
if (getSleepManagerIfReady2()?.isSleeping(name)) {
|
|
3758
3941
|
status = "sleeping";
|
|
3759
3942
|
}
|
|
@@ -4179,15 +4362,15 @@ function importSessionsFromArchive(dest, tempDir) {
|
|
|
4179
4362
|
logger_default.error("Failed to import sessions from archive", logger_default.errorData(err));
|
|
4180
4363
|
}
|
|
4181
4364
|
}
|
|
4182
|
-
var createMindSchema =
|
|
4183
|
-
name:
|
|
4184
|
-
template:
|
|
4185
|
-
stage:
|
|
4186
|
-
description:
|
|
4187
|
-
model:
|
|
4188
|
-
seedSoul:
|
|
4189
|
-
skills:
|
|
4190
|
-
createdBy:
|
|
4365
|
+
var createMindSchema = z6.object({
|
|
4366
|
+
name: z6.string(),
|
|
4367
|
+
template: z6.string().optional(),
|
|
4368
|
+
stage: z6.enum(["seed", "sprouted"]).optional(),
|
|
4369
|
+
description: z6.string().optional(),
|
|
4370
|
+
model: z6.string().optional(),
|
|
4371
|
+
seedSoul: z6.string().optional(),
|
|
4372
|
+
skills: z6.array(z6.string()).optional(),
|
|
4373
|
+
createdBy: z6.string().optional()
|
|
4191
4374
|
});
|
|
4192
4375
|
function formatTimeAgo(date) {
|
|
4193
4376
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
@@ -4231,7 +4414,7 @@ async function proxyToMind(c, path) {
|
|
|
4231
4414
|
return c.json({ error: "Failed to reach mind" }, 503);
|
|
4232
4415
|
}
|
|
4233
4416
|
}
|
|
4234
|
-
var app13 = new
|
|
4417
|
+
var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", createMindSchema), async (c) => {
|
|
4235
4418
|
const body = c.req.valid("json");
|
|
4236
4419
|
const { name } = body;
|
|
4237
4420
|
const template = body.template ?? await resolveTemplate(body.model);
|
|
@@ -4248,7 +4431,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4248
4431
|
applyInitFiles(dest);
|
|
4249
4432
|
const { publicKeyPem } = generateIdentity(dest);
|
|
4250
4433
|
{
|
|
4251
|
-
const { readGlobalConfig: readGlobal } = await import("./setup-
|
|
4434
|
+
const { readGlobalConfig: readGlobal } = await import("./setup-Y2EJI3GG.js");
|
|
4252
4435
|
const mindDefaults = readGlobal().mindDefaults;
|
|
4253
4436
|
const config2 = readVoluteConfig(dest);
|
|
4254
4437
|
if (!config2) throw new Error("Failed to read volute.json after identity generation");
|
|
@@ -4328,7 +4511,6 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4328
4511
|
rmSync4(resolve10(dest, ".git"), { recursive: true, force: true });
|
|
4329
4512
|
gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
|
|
4330
4513
|
}
|
|
4331
|
-
await chownMindDir(dest, name);
|
|
4332
4514
|
if (body.stage === "seed") {
|
|
4333
4515
|
const descLine = body.description ? `
|
|
4334
4516
|
The human who planted you described you as: "${body.description}"
|
|
@@ -4339,7 +4521,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4339
4521
|
}
|
|
4340
4522
|
let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
|
|
4341
4523
|
if (body.stage === "seed" && !body.skills) {
|
|
4342
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
4524
|
+
const { isImagegenEnabled } = await import("./setup-Y2EJI3GG.js");
|
|
4343
4525
|
if (isImagegenEnabled()) {
|
|
4344
4526
|
skillSet = [...skillSet, "imagegen"];
|
|
4345
4527
|
}
|
|
@@ -4357,7 +4539,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4357
4539
|
try {
|
|
4358
4540
|
const spiritEntry = await findMind("volute");
|
|
4359
4541
|
if (spiritEntry) {
|
|
4360
|
-
const { spiritDir } = await import("./spirit-
|
|
4542
|
+
const { spiritDir } = await import("./spirit-DBTIW7P4.js");
|
|
4361
4543
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
4362
4544
|
const spiritConfig = readVoluteConfig(sDir) ?? {};
|
|
4363
4545
|
const schedules = spiritConfig.schedules ?? [];
|
|
@@ -4372,7 +4554,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4372
4554
|
});
|
|
4373
4555
|
spiritConfig.schedules = schedules;
|
|
4374
4556
|
writeVoluteConfig(sDir, spiritConfig);
|
|
4375
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
4557
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-P6DXLLXI.js");
|
|
4376
4558
|
getScheduler2().loadSchedules("volute", sDir);
|
|
4377
4559
|
}
|
|
4378
4560
|
}
|
|
@@ -4390,6 +4572,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4390
4572
|
writeFileSync7(resolve10(dest, "home/MEMORY.md"), customMemory);
|
|
4391
4573
|
}
|
|
4392
4574
|
}
|
|
4575
|
+
await chownMindDir(dest, name);
|
|
4393
4576
|
publishPublicKey(name, publicKeyPem).catch(
|
|
4394
4577
|
(err) => logger_default.warn(`failed to publish key for ${name}`, { error: err.message })
|
|
4395
4578
|
);
|
|
@@ -4637,7 +4820,7 @@ ${user.trimEnd()}
|
|
|
4637
4820
|
const manager = getMindManager();
|
|
4638
4821
|
try {
|
|
4639
4822
|
if (context?.type === "reload") {
|
|
4640
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4823
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
|
|
4641
4824
|
const sleepState = getSleepManagerIfReady2()?.getState(name);
|
|
4642
4825
|
if (sleepState?.sleeping) {
|
|
4643
4826
|
logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
|
|
@@ -4764,7 +4947,7 @@ ${user.trimEnd()}
|
|
|
4764
4947
|
const name = c.req.param("name");
|
|
4765
4948
|
const entry = await findMind(name);
|
|
4766
4949
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4767
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4950
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
|
|
4768
4951
|
const sm = getSleepManagerIfReady2();
|
|
4769
4952
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4770
4953
|
return c.json(sm.getState(name));
|
|
@@ -4772,7 +4955,7 @@ ${user.trimEnd()}
|
|
|
4772
4955
|
const name = c.req.param("name");
|
|
4773
4956
|
const entry = await findMind(name);
|
|
4774
4957
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4775
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4958
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
|
|
4776
4959
|
const sm = getSleepManagerIfReady2();
|
|
4777
4960
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4778
4961
|
if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
|
|
@@ -4792,7 +4975,7 @@ ${user.trimEnd()}
|
|
|
4792
4975
|
const name = c.req.param("name");
|
|
4793
4976
|
const entry = await findMind(name);
|
|
4794
4977
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4795
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4978
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
|
|
4796
4979
|
const sm = getSleepManagerIfReady2();
|
|
4797
4980
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4798
4981
|
const sleepState = sm.getState(name);
|
|
@@ -4807,7 +4990,7 @@ ${user.trimEnd()}
|
|
|
4807
4990
|
const name = c.req.param("name");
|
|
4808
4991
|
const entry = await findMind(name);
|
|
4809
4992
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4810
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4993
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
|
|
4811
4994
|
const sm = getSleepManagerIfReady2();
|
|
4812
4995
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
4813
4996
|
const flushed = await sm.flushQueuedMessages(name);
|
|
@@ -4822,10 +5005,20 @@ ${user.trimEnd()}
|
|
|
4822
5005
|
const profile = config2.profile ?? {};
|
|
4823
5006
|
if (body.displayName !== void 0) profile.displayName = body.displayName;
|
|
4824
5007
|
if (body.description !== void 0) profile.description = body.description;
|
|
4825
|
-
if (body.avatar !== void 0)
|
|
5008
|
+
if (body.avatar !== void 0) {
|
|
5009
|
+
const homeDir = resolve10(dir, "home");
|
|
5010
|
+
const avatarPath = safeResolveWithinBase(homeDir, body.avatar);
|
|
5011
|
+
if (!avatarPath) {
|
|
5012
|
+
return c.json({ error: "Avatar path must be inside the mind's home directory" }, 400);
|
|
5013
|
+
}
|
|
5014
|
+
if (!existsSync7(avatarPath)) {
|
|
5015
|
+
return c.json({ error: `Avatar file not found: ${relative(homeDir, avatarPath)}` }, 400);
|
|
5016
|
+
}
|
|
5017
|
+
profile.avatar = relative(homeDir, avatarPath);
|
|
5018
|
+
}
|
|
4826
5019
|
config2.profile = profile;
|
|
4827
5020
|
writeVoluteConfig(dir, config2);
|
|
4828
|
-
const { syncMindProfile: syncMindProfile2 } = await import("./auth-
|
|
5021
|
+
const { syncMindProfile: syncMindProfile2 } = await import("./auth-FLAEXXZK.js");
|
|
4829
5022
|
await syncMindProfile2(name, profile);
|
|
4830
5023
|
broadcast({ type: "profile_updated", mind: name, summary: `${name} profile updated` });
|
|
4831
5024
|
return c.json({ ok: true });
|
|
@@ -4872,7 +5065,7 @@ ${user.trimEnd()}
|
|
|
4872
5065
|
const config2 = readVoluteConfig(dir);
|
|
4873
5066
|
const displayNameSet = !!config2?.profile?.displayName;
|
|
4874
5067
|
const avatarSet = !!config2?.profile?.avatar;
|
|
4875
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
5068
|
+
const { isImagegenEnabled } = await import("./setup-Y2EJI3GG.js");
|
|
4876
5069
|
const imagegenEnabled = isImagegenEnabled();
|
|
4877
5070
|
const done = [];
|
|
4878
5071
|
const remaining = [];
|
|
@@ -4910,7 +5103,7 @@ ${user.trimEnd()}
|
|
|
4910
5103
|
try {
|
|
4911
5104
|
const spiritEntry = await findMind("volute");
|
|
4912
5105
|
if (spiritEntry) {
|
|
4913
|
-
const { spiritDir } = await import("./spirit-
|
|
5106
|
+
const { spiritDir } = await import("./spirit-DBTIW7P4.js");
|
|
4914
5107
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
4915
5108
|
const spiritConfig = readVoluteConfig(sDir);
|
|
4916
5109
|
if (spiritConfig?.schedules) {
|
|
@@ -4918,7 +5111,7 @@ ${user.trimEnd()}
|
|
|
4918
5111
|
spiritConfig.schedules = spiritConfig.schedules.filter((s) => s.id !== nurtureId);
|
|
4919
5112
|
if (spiritConfig.schedules.length === 0) spiritConfig.schedules = void 0;
|
|
4920
5113
|
writeVoluteConfig(sDir, spiritConfig);
|
|
4921
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
5114
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-P6DXLLXI.js");
|
|
4922
5115
|
getScheduler2().loadSchedules("volute", sDir);
|
|
4923
5116
|
}
|
|
4924
5117
|
}
|
|
@@ -5303,16 +5496,16 @@ ${user.trimEnd()}
|
|
|
5303
5496
|
}).put(
|
|
5304
5497
|
"/:name/config",
|
|
5305
5498
|
requireSelf(),
|
|
5306
|
-
|
|
5499
|
+
zValidator6(
|
|
5307
5500
|
"json",
|
|
5308
|
-
|
|
5309
|
-
model:
|
|
5310
|
-
thinkingLevel:
|
|
5311
|
-
maxThinkingTokens:
|
|
5312
|
-
tokenBudget:
|
|
5313
|
-
tokenBudgetPeriodMinutes:
|
|
5314
|
-
compaction:
|
|
5315
|
-
unescapeNewlines:
|
|
5501
|
+
z6.object({
|
|
5502
|
+
model: z6.string().optional(),
|
|
5503
|
+
thinkingLevel: z6.enum(["off", "minimal", "low", "medium", "high", "xhigh"]).optional(),
|
|
5504
|
+
maxThinkingTokens: z6.number().int().positive().nullable().optional(),
|
|
5505
|
+
tokenBudget: z6.number().int().positive().nullable().optional(),
|
|
5506
|
+
tokenBudgetPeriodMinutes: z6.number().int().positive().nullable().optional(),
|
|
5507
|
+
compaction: z6.object({ maxContextTokens: z6.number().int().positive().nullable().optional() }).nullable().optional(),
|
|
5508
|
+
unescapeNewlines: z6.boolean().optional()
|
|
5316
5509
|
})
|
|
5317
5510
|
),
|
|
5318
5511
|
async (c) => {
|
|
@@ -5353,7 +5546,7 @@ ${user.trimEnd()}
|
|
|
5353
5546
|
}
|
|
5354
5547
|
writeVoluteConfig(dir, existing);
|
|
5355
5548
|
if (body.unescapeNewlines !== void 0) {
|
|
5356
|
-
const { clearEchoTextCache } = await import("./echo-text-
|
|
5549
|
+
const { clearEchoTextCache } = await import("./echo-text-6JJOPUD4.js");
|
|
5357
5550
|
clearEchoTextCache(name);
|
|
5358
5551
|
}
|
|
5359
5552
|
const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.maxThinkingTokens !== void 0 || body.compaction !== void 0;
|
|
@@ -5430,7 +5623,7 @@ ${user.trimEnd()}
|
|
|
5430
5623
|
}
|
|
5431
5624
|
if (entry.mindType === "spirit" && body.model !== void 0) {
|
|
5432
5625
|
try {
|
|
5433
|
-
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-
|
|
5626
|
+
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-Y2EJI3GG.js");
|
|
5434
5627
|
const globalConfig = readGlobalConfig2();
|
|
5435
5628
|
globalConfig.spiritModel = body.model;
|
|
5436
5629
|
writeGlobalConfig2(globalConfig);
|
|
@@ -5458,7 +5651,7 @@ ${user.trimEnd()}
|
|
|
5458
5651
|
if (!body.systemPrompt || !body.message) {
|
|
5459
5652
|
return c.json({ error: "systemPrompt and message required" }, 400);
|
|
5460
5653
|
}
|
|
5461
|
-
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-
|
|
5654
|
+
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-UODCCE4O.js");
|
|
5462
5655
|
if (!isAiConfigured()) {
|
|
5463
5656
|
return c.json({ error: "AI service not configured" }, 503);
|
|
5464
5657
|
}
|
|
@@ -5750,11 +5943,11 @@ ${lines.join("\n")}` });
|
|
|
5750
5943
|
var minds_default = app13;
|
|
5751
5944
|
|
|
5752
5945
|
// packages/daemon/src/web/api/prompts.ts
|
|
5753
|
-
import { zValidator as
|
|
5946
|
+
import { zValidator as zValidator7 } from "@hono/zod-validator";
|
|
5754
5947
|
import { eq as eq6, sql as sql4 } from "drizzle-orm";
|
|
5755
|
-
import { Hono as
|
|
5756
|
-
import { z as
|
|
5757
|
-
var app14 = new
|
|
5948
|
+
import { Hono as Hono17 } from "hono";
|
|
5949
|
+
import { z as z7 } from "zod";
|
|
5950
|
+
var app14 = new Hono17().get("/", async (c) => {
|
|
5758
5951
|
let rows;
|
|
5759
5952
|
try {
|
|
5760
5953
|
const db = await getDb();
|
|
@@ -5777,7 +5970,7 @@ var app14 = new Hono16().get("/", async (c) => {
|
|
|
5777
5970
|
};
|
|
5778
5971
|
});
|
|
5779
5972
|
return c.json(prompts);
|
|
5780
|
-
}).put("/:key", requireAdmin,
|
|
5973
|
+
}).put("/:key", requireAdmin, zValidator7("json", z7.object({ content: z7.string() })), async (c) => {
|
|
5781
5974
|
const key = c.req.param("key");
|
|
5782
5975
|
if (!PROMPT_KEYS.includes(key)) {
|
|
5783
5976
|
return c.json({ error: "Unknown prompt key" }, 404);
|
|
@@ -5801,8 +5994,8 @@ var app14 = new Hono16().get("/", async (c) => {
|
|
|
5801
5994
|
var prompts_default = app14;
|
|
5802
5995
|
|
|
5803
5996
|
// packages/daemon/src/web/api/schedules.ts
|
|
5804
|
-
import { CronExpressionParser } from "cron-parser";
|
|
5805
|
-
import { Hono as
|
|
5997
|
+
import { CronExpressionParser as CronExpressionParser3 } from "cron-parser";
|
|
5998
|
+
import { Hono as Hono18 } from "hono";
|
|
5806
5999
|
var slog2 = logger_default.child("schedules");
|
|
5807
6000
|
function readSchedules(dir) {
|
|
5808
6001
|
return readVoluteConfig(dir)?.schedules ?? [];
|
|
@@ -5819,7 +6012,7 @@ function writeSchedules(name, dir, schedules) {
|
|
|
5819
6012
|
data: { schedules }
|
|
5820
6013
|
});
|
|
5821
6014
|
}
|
|
5822
|
-
var app15 = new
|
|
6015
|
+
var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) => {
|
|
5823
6016
|
const name = c.req.param("name");
|
|
5824
6017
|
const entry = await findMind(name);
|
|
5825
6018
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
@@ -5840,14 +6033,14 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
5840
6033
|
}
|
|
5841
6034
|
} else if (s.cron) {
|
|
5842
6035
|
try {
|
|
5843
|
-
const interval =
|
|
6036
|
+
const interval = CronExpressionParser3.parse(s.cron);
|
|
5844
6037
|
const next = interval.next().toDate();
|
|
5845
6038
|
upcoming.push({ id: s.id, at: next.toISOString(), type: "cron" });
|
|
5846
6039
|
} catch {
|
|
5847
6040
|
slog2.warn(`invalid cron "${s.cron}" for schedule "${s.id}" of ${name}`);
|
|
5848
6041
|
}
|
|
5849
6042
|
try {
|
|
5850
|
-
const prevInterval =
|
|
6043
|
+
const prevInterval = CronExpressionParser3.parse(s.cron);
|
|
5851
6044
|
const prev = prevInterval.prev().toDate();
|
|
5852
6045
|
previous.push({ id: s.id, at: prev.toISOString() });
|
|
5853
6046
|
} catch {
|
|
@@ -5863,13 +6056,13 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
5863
6056
|
}
|
|
5864
6057
|
} else if (sleepConfig?.enabled && sleepConfig.schedule) {
|
|
5865
6058
|
try {
|
|
5866
|
-
const sleepInterval =
|
|
6059
|
+
const sleepInterval = CronExpressionParser3.parse(sleepConfig.schedule.sleep);
|
|
5867
6060
|
const nextSleep = sleepInterval.next().toDate();
|
|
5868
6061
|
upcoming.push({ id: "sleep", at: nextSleep.toISOString(), type: "cron" });
|
|
5869
6062
|
} catch {
|
|
5870
6063
|
}
|
|
5871
6064
|
try {
|
|
5872
|
-
const prevWakeInterval =
|
|
6065
|
+
const prevWakeInterval = CronExpressionParser3.parse(sleepConfig.schedule.wake);
|
|
5873
6066
|
const prevWake = prevWakeInterval.prev().toDate();
|
|
5874
6067
|
previous.push({ id: "sleep", at: prevWake.toISOString() });
|
|
5875
6068
|
} catch {
|
|
@@ -5893,7 +6086,7 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
5893
6086
|
for (const field of ["sleep", "wake"]) {
|
|
5894
6087
|
if (body.schedule[field]) {
|
|
5895
6088
|
try {
|
|
5896
|
-
|
|
6089
|
+
CronExpressionParser3.parse(body.schedule[field]);
|
|
5897
6090
|
} catch {
|
|
5898
6091
|
return c.json({ error: `Invalid ${field} cron: ${body.schedule[field]}` }, 400);
|
|
5899
6092
|
}
|
|
@@ -5939,7 +6132,7 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
5939
6132
|
}
|
|
5940
6133
|
if (body.cron) {
|
|
5941
6134
|
try {
|
|
5942
|
-
|
|
6135
|
+
CronExpressionParser3.parse(body.cron);
|
|
5943
6136
|
} catch {
|
|
5944
6137
|
return c.json({ error: `Invalid cron expression: ${body.cron}` }, 400);
|
|
5945
6138
|
}
|
|
@@ -5986,7 +6179,7 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
5986
6179
|
}
|
|
5987
6180
|
if (body.cron !== void 0) {
|
|
5988
6181
|
try {
|
|
5989
|
-
|
|
6182
|
+
CronExpressionParser3.parse(body.cron);
|
|
5990
6183
|
} catch {
|
|
5991
6184
|
return c.json({ error: `Invalid cron expression: ${body.cron}` }, 400);
|
|
5992
6185
|
}
|
|
@@ -6043,7 +6236,7 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
6043
6236
|
const body = await c.req.text();
|
|
6044
6237
|
const message = `[webhook: ${event}] ${body}`;
|
|
6045
6238
|
try {
|
|
6046
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
6239
|
+
const { sendSystemMessage } = await import("./system-chat-XOALE2RD.js");
|
|
6047
6240
|
await sendSystemMessage(name, message);
|
|
6048
6241
|
return c.json({ ok: true });
|
|
6049
6242
|
} catch (err) {
|
|
@@ -6057,10 +6250,10 @@ var schedules_default = app15;
|
|
|
6057
6250
|
import { mkdirSync as mkdirSync7 } from "fs";
|
|
6058
6251
|
import { homedir as homedir2 } from "os";
|
|
6059
6252
|
import { resolve as resolve11 } from "path";
|
|
6060
|
-
import { Hono as
|
|
6253
|
+
import { Hono as Hono19 } from "hono";
|
|
6061
6254
|
import { setCookie as setCookie2 } from "hono/cookie";
|
|
6062
6255
|
var DEFAULT_API_URL2 = "https://volute.systems";
|
|
6063
|
-
var setup = new
|
|
6256
|
+
var setup = new Hono19();
|
|
6064
6257
|
function writeSetupConfig(systemName, description) {
|
|
6065
6258
|
const configHome = process.env.VOLUTE_HOME ?? resolve11(homedir2(), ".volute");
|
|
6066
6259
|
const mindsDir = resolve11(configHome, "minds");
|
|
@@ -6097,7 +6290,7 @@ setup.get("/status", async (c) => {
|
|
|
6097
6290
|
let hasAccount = false;
|
|
6098
6291
|
if (hasSystem) {
|
|
6099
6292
|
try {
|
|
6100
|
-
const { listUsersByType: listUsersByType2 } = await import("./auth-
|
|
6293
|
+
const { listUsersByType: listUsersByType2 } = await import("./auth-FLAEXXZK.js");
|
|
6101
6294
|
const brains = await listUsersByType2("brain");
|
|
6102
6295
|
hasAccount = brains.length > 0;
|
|
6103
6296
|
} catch (err) {
|
|
@@ -6308,7 +6501,7 @@ setup.post("/account", async (c) => {
|
|
|
6308
6501
|
}
|
|
6309
6502
|
}
|
|
6310
6503
|
try {
|
|
6311
|
-
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-
|
|
6504
|
+
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-FLAEXXZK.js");
|
|
6312
6505
|
const user = await createUser2(body.username.trim(), body.password);
|
|
6313
6506
|
if (body.displayName?.trim()) {
|
|
6314
6507
|
await updateUserProfile2(user.id, { display_name: body.displayName.trim() });
|
|
@@ -6354,7 +6547,7 @@ setup.post("/models", async (c) => {
|
|
|
6354
6547
|
return c.json({ error: "Spirit model is required" }, 400);
|
|
6355
6548
|
}
|
|
6356
6549
|
try {
|
|
6357
|
-
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-
|
|
6550
|
+
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-UODCCE4O.js");
|
|
6358
6551
|
setEnabledModels3(body.models);
|
|
6359
6552
|
const config2 = readGlobalConfig();
|
|
6360
6553
|
config2.spiritModel = body.spiritModel.trim();
|
|
@@ -6372,15 +6565,15 @@ setup.post("/complete", async (c) => {
|
|
|
6372
6565
|
return c.json({ error: "Setup already complete" }, 400);
|
|
6373
6566
|
}
|
|
6374
6567
|
try {
|
|
6375
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
6376
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
6568
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-DBTIW7P4.js");
|
|
6569
|
+
const { startSpiritFull } = await import("./mind-service-3F4I46CI.js");
|
|
6377
6570
|
await ensureSpiritProject();
|
|
6378
6571
|
await syncSpiritTemplate();
|
|
6379
6572
|
const warnings = [];
|
|
6380
6573
|
const config2 = readGlobalConfig();
|
|
6381
6574
|
if (config2.setup?.service && config2.setup?.type === "local") {
|
|
6382
6575
|
try {
|
|
6383
|
-
const { installUserService } = await import("./service-install-
|
|
6576
|
+
const { installUserService } = await import("./service-install-4HHFDDWY.js");
|
|
6384
6577
|
const installed = await installUserService(config2.port, config2.hostname);
|
|
6385
6578
|
if (!installed) {
|
|
6386
6579
|
warnings.push("Service installation is not supported on this platform.");
|
|
@@ -6408,8 +6601,8 @@ setup.post("/complete", async (c) => {
|
|
|
6408
6601
|
}
|
|
6409
6602
|
let spiritConversationId;
|
|
6410
6603
|
try {
|
|
6411
|
-
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-
|
|
6412
|
-
const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-
|
|
6604
|
+
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-FLAEXXZK.js");
|
|
6605
|
+
const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-JZTD6KLR.js");
|
|
6413
6606
|
const spiritUser = await getOrCreateMindUser2("volute");
|
|
6414
6607
|
const brains = await listUsersByType2("brain");
|
|
6415
6608
|
const admin2 = brains.find((u) => u.role === "admin");
|
|
@@ -6431,8 +6624,8 @@ setup.post("/complete", async (c) => {
|
|
|
6431
6624
|
logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
|
|
6432
6625
|
if (spiritConversationId && spiritStarted) {
|
|
6433
6626
|
try {
|
|
6434
|
-
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-
|
|
6435
|
-
const { listUsersByType: listUsers2 } = await import("./auth-
|
|
6627
|
+
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-3C65ZI6L.js");
|
|
6628
|
+
const { listUsersByType: listUsers2 } = await import("./auth-FLAEXXZK.js");
|
|
6436
6629
|
const admins = await listUsers2("brain");
|
|
6437
6630
|
const admin2 = admins.find((u) => u.role === "admin");
|
|
6438
6631
|
const adminName = admin2?.display_name || admin2?.username || "the admin";
|
|
@@ -6473,8 +6666,8 @@ import { existsSync as existsSync8, mkdtempSync, readdirSync as readdirSync3, rm
|
|
|
6473
6666
|
import { tmpdir } from "os";
|
|
6474
6667
|
import { join, resolve as resolve12 } from "path";
|
|
6475
6668
|
import AdmZip from "adm-zip";
|
|
6476
|
-
import { Hono as
|
|
6477
|
-
var app16 = new
|
|
6669
|
+
import { Hono as Hono20 } from "hono";
|
|
6670
|
+
var app16 = new Hono20().get("/", async (c) => {
|
|
6478
6671
|
const skills = await listSharedSkills();
|
|
6479
6672
|
return c.json(skills);
|
|
6480
6673
|
}).get("/defaults/list", async (c) => {
|
|
@@ -6598,15 +6791,15 @@ var app16 = new Hono19().get("/", async (c) => {
|
|
|
6598
6791
|
var skills_default = app16;
|
|
6599
6792
|
|
|
6600
6793
|
// packages/daemon/src/web/api/typing.ts
|
|
6601
|
-
import { zValidator as
|
|
6602
|
-
import { Hono as
|
|
6603
|
-
import { z as
|
|
6604
|
-
var typingSchema =
|
|
6605
|
-
channel:
|
|
6606
|
-
sender:
|
|
6607
|
-
active:
|
|
6794
|
+
import { zValidator as zValidator8 } from "@hono/zod-validator";
|
|
6795
|
+
import { Hono as Hono21 } from "hono";
|
|
6796
|
+
import { z as z8 } from "zod";
|
|
6797
|
+
var typingSchema = z8.object({
|
|
6798
|
+
channel: z8.string().min(1),
|
|
6799
|
+
sender: z8.string().min(1),
|
|
6800
|
+
active: z8.boolean()
|
|
6608
6801
|
});
|
|
6609
|
-
var app17 = new
|
|
6802
|
+
var app17 = new Hono21().post("/:name/typing", zValidator8("json", typingSchema), (c) => {
|
|
6610
6803
|
const { channel, sender, active } = c.req.valid("json");
|
|
6611
6804
|
const map = getTypingMap();
|
|
6612
6805
|
if (active) {
|
|
@@ -6630,9 +6823,9 @@ var typing_default = app17;
|
|
|
6630
6823
|
|
|
6631
6824
|
// packages/daemon/src/web/api/update.ts
|
|
6632
6825
|
import { spawn as spawn3 } from "child_process";
|
|
6633
|
-
import { Hono as
|
|
6826
|
+
import { Hono as Hono22 } from "hono";
|
|
6634
6827
|
var bin;
|
|
6635
|
-
var app18 = new
|
|
6828
|
+
var app18 = new Hono22().get("/update", async (c) => {
|
|
6636
6829
|
const result = await checkForUpdate();
|
|
6637
6830
|
return c.json(result);
|
|
6638
6831
|
}).post("/update", requireAdmin, async (c) => {
|
|
@@ -6650,13 +6843,13 @@ var app18 = new Hono21().get("/update", async (c) => {
|
|
|
6650
6843
|
var update_default = app18;
|
|
6651
6844
|
|
|
6652
6845
|
// packages/daemon/src/web/api/v1/conversations.ts
|
|
6653
|
-
import { zValidator as
|
|
6654
|
-
import { Hono as
|
|
6655
|
-
import { z as
|
|
6656
|
-
var createSchema =
|
|
6657
|
-
participantNames:
|
|
6846
|
+
import { zValidator as zValidator9 } from "@hono/zod-validator";
|
|
6847
|
+
import { Hono as Hono23 } from "hono";
|
|
6848
|
+
import { z as z9 } from "zod";
|
|
6849
|
+
var createSchema = z9.object({
|
|
6850
|
+
participantNames: z9.array(z9.string()).min(1)
|
|
6658
6851
|
});
|
|
6659
|
-
var app19 = new
|
|
6852
|
+
var app19 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
6660
6853
|
const user = c.get("user");
|
|
6661
6854
|
const convs = await listConversationsWithParticipants(user.id);
|
|
6662
6855
|
return c.json(convs);
|
|
@@ -6683,7 +6876,7 @@ var app19 = new Hono22().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6683
6876
|
}
|
|
6684
6877
|
const participants = await getParticipants(id);
|
|
6685
6878
|
return c.json(participants);
|
|
6686
|
-
}).post("/",
|
|
6879
|
+
}).post("/", zValidator9("json", createSchema), async (c) => {
|
|
6687
6880
|
const user = c.get("user");
|
|
6688
6881
|
const body = c.req.valid("json");
|
|
6689
6882
|
const participantIds = /* @__PURE__ */ new Set();
|
|
@@ -6732,7 +6925,7 @@ var app19 = new Hono22().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6732
6925
|
}
|
|
6733
6926
|
await markConversationRead(user.id, id);
|
|
6734
6927
|
return c.json({ ok: true });
|
|
6735
|
-
}).put("/:id/private",
|
|
6928
|
+
}).put("/:id/private", zValidator9("json", z9.object({ private: z9.boolean() })), async (c) => {
|
|
6736
6929
|
const id = c.req.param("id");
|
|
6737
6930
|
const user = c.get("user");
|
|
6738
6931
|
if (!await isParticipantOrOwner(id, user.id)) {
|
|
@@ -6752,7 +6945,7 @@ var conversations_default = app19;
|
|
|
6752
6945
|
|
|
6753
6946
|
// packages/daemon/src/web/api/v1/events.ts
|
|
6754
6947
|
import { desc as desc5, eq as eq7 } from "drizzle-orm";
|
|
6755
|
-
import { Hono as
|
|
6948
|
+
import { Hono as Hono24 } from "hono";
|
|
6756
6949
|
import { streamSSE as streamSSE4 } from "hono/streaming";
|
|
6757
6950
|
|
|
6758
6951
|
// packages/daemon/src/lib/events/brain-presence.ts
|
|
@@ -6815,7 +7008,7 @@ function getEventsSince(sinceId, allowedConversationIds, allowedActivityMind) {
|
|
|
6815
7008
|
}
|
|
6816
7009
|
|
|
6817
7010
|
// packages/daemon/src/web/api/v1/events.ts
|
|
6818
|
-
var app20 = new
|
|
7011
|
+
var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
|
|
6819
7012
|
const user = c.get("user");
|
|
6820
7013
|
const since = c.req.query("since");
|
|
6821
7014
|
const sinceId = since ? Number(since) : 0;
|
|
@@ -6833,7 +7026,7 @@ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
|
6833
7026
|
conversations2 = await listConversationsWithParticipants(user.id);
|
|
6834
7027
|
if (conversations2.length > 0) {
|
|
6835
7028
|
const convIds = conversations2.map((c2) => c2.id);
|
|
6836
|
-
const unreads = await getUnreadCounts(user.id, convIds);
|
|
7029
|
+
const unreads = await getUnreadCounts(user.id, convIds, user.username);
|
|
6837
7030
|
for (const conv of conversations2) {
|
|
6838
7031
|
conv.unreadCount = unreads[conv.id] ?? 0;
|
|
6839
7032
|
}
|
|
@@ -6927,7 +7120,7 @@ var events_default = app20;
|
|
|
6927
7120
|
// packages/daemon/src/web/api/variants.ts
|
|
6928
7121
|
import { existsSync as existsSync9, mkdirSync as mkdirSync9, writeFileSync as writeFileSync8 } from "fs";
|
|
6929
7122
|
import { resolve as resolve14 } from "path";
|
|
6930
|
-
import { Hono as
|
|
7123
|
+
import { Hono as Hono25 } from "hono";
|
|
6931
7124
|
|
|
6932
7125
|
// packages/daemon/src/lib/mind/spawn-server.ts
|
|
6933
7126
|
import { spawn as spawn4 } from "child_process";
|
|
@@ -7052,7 +7245,7 @@ async function verify2(port) {
|
|
|
7052
7245
|
}
|
|
7053
7246
|
|
|
7054
7247
|
// packages/daemon/src/web/api/variants.ts
|
|
7055
|
-
var app21 = new
|
|
7248
|
+
var app21 = new Hono25().get("/:name/variants", async (c) => {
|
|
7056
7249
|
const name = c.req.param("name");
|
|
7057
7250
|
const entry = await findMind(name);
|
|
7058
7251
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
@@ -7082,6 +7275,11 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7082
7275
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
7083
7276
|
if (entry.stage === "seed")
|
|
7084
7277
|
return c.json({ error: "Seed minds cannot create variants \u2014 sprout first" }, 403);
|
|
7278
|
+
if (entry.parent)
|
|
7279
|
+
return c.json(
|
|
7280
|
+
{ error: "Cannot split from a variant \u2014 split from the base mind instead" },
|
|
7281
|
+
403
|
|
7282
|
+
);
|
|
7085
7283
|
let body;
|
|
7086
7284
|
try {
|
|
7087
7285
|
body = await c.req.json();
|
|
@@ -7095,7 +7293,7 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7095
7293
|
if (await findMind(variantName)) {
|
|
7096
7294
|
return c.json({ error: `Name already in use: ${variantName}` }, 409);
|
|
7097
7295
|
}
|
|
7098
|
-
const projectRoot = mindDir(mindName);
|
|
7296
|
+
const projectRoot = entry.dir ?? mindDir(mindName);
|
|
7099
7297
|
const variantDir = resolve14(projectRoot, ".variants", variantName);
|
|
7100
7298
|
if (existsSync9(variantDir)) {
|
|
7101
7299
|
return c.json({ error: `Variant directory already exists: ${variantDir}` }, 409);
|
|
@@ -7129,7 +7327,9 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7129
7327
|
await addVariant(variantName, mindName, variantPort, variantDir, variantName);
|
|
7130
7328
|
if (!body.noStart) {
|
|
7131
7329
|
try {
|
|
7132
|
-
|
|
7330
|
+
const manager = getMindManager();
|
|
7331
|
+
manager.setPendingContext(variantName, { type: "split", parent: mindName });
|
|
7332
|
+
await manager.startMind(variantName);
|
|
7133
7333
|
} catch (e) {
|
|
7134
7334
|
const msg = e instanceof Error ? e.message : String(e);
|
|
7135
7335
|
return c.json({ error: `Variant created but failed to start: ${msg}` }, 500);
|
|
@@ -7157,7 +7357,7 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7157
7357
|
body = await c.req.json();
|
|
7158
7358
|
} catch {
|
|
7159
7359
|
}
|
|
7160
|
-
const projectRoot = mindDir(mindName);
|
|
7360
|
+
const projectRoot = parentEntry.dir ?? mindDir(mindName);
|
|
7161
7361
|
if (existsSync9(variantEntry.dir)) {
|
|
7162
7362
|
const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
|
|
7163
7363
|
if (status) {
|
|
@@ -7190,7 +7390,7 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7190
7390
|
}
|
|
7191
7391
|
const verified = await verify2(result.actualPort);
|
|
7192
7392
|
try {
|
|
7193
|
-
process.kill(result.child.pid);
|
|
7393
|
+
process.kill(-result.child.pid, "SIGTERM");
|
|
7194
7394
|
} catch {
|
|
7195
7395
|
}
|
|
7196
7396
|
if (!verified) {
|
|
@@ -7217,13 +7417,47 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7217
7417
|
try {
|
|
7218
7418
|
await gitExec(["merge", variantEntry.branch], { cwd: projectRoot });
|
|
7219
7419
|
} catch (_e) {
|
|
7220
|
-
|
|
7420
|
+
let conflicts = [];
|
|
7421
|
+
try {
|
|
7422
|
+
const out = (await gitExec(["diff", "--name-only", "--diff-filter=U"], { cwd: projectRoot })).trim();
|
|
7423
|
+
conflicts = out ? out.split("\n") : [];
|
|
7424
|
+
} catch (err) {
|
|
7425
|
+
logger_default.warn(`failed to list merge conflicts for ${mindName}`, logger_default.errorData(err));
|
|
7426
|
+
}
|
|
7427
|
+
try {
|
|
7428
|
+
await gitExec(["merge", "--abort"], { cwd: projectRoot });
|
|
7429
|
+
} catch (err) {
|
|
7430
|
+
logger_default.warn(`failed to abort merge for ${mindName}`, logger_default.errorData(err));
|
|
7431
|
+
}
|
|
7432
|
+
try {
|
|
7433
|
+
await chownMindDir(projectRoot, mindName);
|
|
7434
|
+
} catch (err) {
|
|
7435
|
+
logger_default.warn(
|
|
7436
|
+
`failed to restore ownership after aborted merge for ${mindName}`,
|
|
7437
|
+
logger_default.errorData(err)
|
|
7438
|
+
);
|
|
7439
|
+
return c.json(
|
|
7440
|
+
{
|
|
7441
|
+
error: `Merge failed and restoring parent ownership failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
7442
|
+
conflicts
|
|
7443
|
+
},
|
|
7444
|
+
500
|
|
7445
|
+
);
|
|
7446
|
+
}
|
|
7447
|
+
return c.json(
|
|
7448
|
+
{
|
|
7449
|
+
error: "Merge failed. Resolve conflicts in the variant and retry the join.",
|
|
7450
|
+
conflicts
|
|
7451
|
+
},
|
|
7452
|
+
500
|
|
7453
|
+
);
|
|
7221
7454
|
}
|
|
7222
|
-
await cleanupVariant(variantName, projectRoot, variantEntry.dir);
|
|
7455
|
+
await cleanupVariant(variantName, projectRoot, variantEntry.dir, { stop: true });
|
|
7456
|
+
await chownMindDir(projectRoot, mindName);
|
|
7223
7457
|
if (variantName.endsWith("-upgrade") || variantName === "upgrade") {
|
|
7224
7458
|
try {
|
|
7225
7459
|
const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-446HHH5V.js");
|
|
7226
|
-
const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-
|
|
7460
|
+
const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-OUZBZ3Q4.js");
|
|
7227
7461
|
const tmpl = parentEntry.template ?? "claude";
|
|
7228
7462
|
await setMindTemplateHash2(mindName, computeTemplateHash2(tmpl));
|
|
7229
7463
|
} catch (err) {
|
|
@@ -7274,29 +7508,29 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7274
7508
|
return c.json({ error: `Unknown variant: ${variantName}` }, 404);
|
|
7275
7509
|
}
|
|
7276
7510
|
if (!variantEntry.dir) return c.json({ error: `Variant ${variantName} has no directory` }, 500);
|
|
7277
|
-
const projectRoot = mindDir(mindName);
|
|
7511
|
+
const projectRoot = parentEntry.dir ?? mindDir(mindName);
|
|
7278
7512
|
await cleanupVariant(variantName, projectRoot, variantEntry.dir, { stop: true });
|
|
7279
7513
|
return c.json({ ok: true });
|
|
7280
7514
|
});
|
|
7281
7515
|
var variants_default = app21;
|
|
7282
7516
|
|
|
7283
7517
|
// packages/daemon/src/web/api/volute/channels.ts
|
|
7284
|
-
import { zValidator as
|
|
7285
|
-
import { Hono as
|
|
7286
|
-
import { z as
|
|
7287
|
-
var channelSettingsSchema =
|
|
7288
|
-
description:
|
|
7289
|
-
rules:
|
|
7290
|
-
charLimit:
|
|
7291
|
-
private:
|
|
7518
|
+
import { zValidator as zValidator10 } from "@hono/zod-validator";
|
|
7519
|
+
import { Hono as Hono26 } from "hono";
|
|
7520
|
+
import { z as z10 } from "zod";
|
|
7521
|
+
var channelSettingsSchema = z10.object({
|
|
7522
|
+
description: z10.string().nullable().optional(),
|
|
7523
|
+
rules: z10.string().nullable().optional(),
|
|
7524
|
+
charLimit: z10.number().int().positive().nullable().optional(),
|
|
7525
|
+
private: z10.boolean().optional()
|
|
7292
7526
|
});
|
|
7293
|
-
var createSchema2 =
|
|
7294
|
-
name:
|
|
7527
|
+
var createSchema2 = z10.object({
|
|
7528
|
+
name: z10.string().min(1).max(50).regex(/^[a-z0-9][a-z0-9-]*$/, "Channel names must be lowercase alphanumeric with hyphens")
|
|
7295
7529
|
}).merge(channelSettingsSchema);
|
|
7296
|
-
var inviteSchema =
|
|
7297
|
-
username:
|
|
7530
|
+
var inviteSchema = z10.object({
|
|
7531
|
+
username: z10.string().min(1)
|
|
7298
7532
|
});
|
|
7299
|
-
var app22 = new
|
|
7533
|
+
var app22 = new Hono26().get("/", async (c) => {
|
|
7300
7534
|
const user = c.get("user");
|
|
7301
7535
|
const channels2 = await listChannels();
|
|
7302
7536
|
const results = await Promise.all(
|
|
@@ -7307,7 +7541,7 @@ var app22 = new Hono25().get("/", async (c) => {
|
|
|
7307
7541
|
})
|
|
7308
7542
|
);
|
|
7309
7543
|
return c.json(results);
|
|
7310
|
-
}).post("/",
|
|
7544
|
+
}).post("/", zValidator10("json", createSchema2), async (c) => {
|
|
7311
7545
|
const user = c.get("user");
|
|
7312
7546
|
const body = c.req.valid("json");
|
|
7313
7547
|
try {
|
|
@@ -7335,7 +7569,7 @@ var app22 = new Hono25().get("/", async (c) => {
|
|
|
7335
7569
|
participants,
|
|
7336
7570
|
settings: formatChannelSettings(settings)
|
|
7337
7571
|
});
|
|
7338
|
-
}).patch("/:name",
|
|
7572
|
+
}).patch("/:name", zValidator10("json", channelSettingsSchema), async (c) => {
|
|
7339
7573
|
const name = c.req.param("name");
|
|
7340
7574
|
const user = c.get("user");
|
|
7341
7575
|
const body = c.req.valid("json");
|
|
@@ -7367,7 +7601,7 @@ var app22 = new Hono25().get("/", async (c) => {
|
|
|
7367
7601
|
if (!ch) return c.json({ error: "Channel not found" }, 404);
|
|
7368
7602
|
const participants = await getParticipants(ch.id);
|
|
7369
7603
|
return c.json(participants);
|
|
7370
|
-
}).post("/:name/invite",
|
|
7604
|
+
}).post("/:name/invite", zValidator10("json", inviteSchema), async (c) => {
|
|
7371
7605
|
const name = c.req.param("name");
|
|
7372
7606
|
const inviter = c.get("user");
|
|
7373
7607
|
const { username } = c.req.valid("json");
|
|
@@ -7393,27 +7627,27 @@ var app22 = new Hono25().get("/", async (c) => {
|
|
|
7393
7627
|
var channels_default2 = app22;
|
|
7394
7628
|
|
|
7395
7629
|
// packages/daemon/src/web/api/volute/chat.ts
|
|
7396
|
-
import { zValidator as
|
|
7397
|
-
import { Hono as
|
|
7630
|
+
import { zValidator as zValidator11 } from "@hono/zod-validator";
|
|
7631
|
+
import { Hono as Hono27 } from "hono";
|
|
7398
7632
|
import { streamSSE as streamSSE5 } from "hono/streaming";
|
|
7399
|
-
import { z as
|
|
7400
|
-
var fileSchema =
|
|
7401
|
-
filename:
|
|
7402
|
-
data:
|
|
7633
|
+
import { z as z11 } from "zod";
|
|
7634
|
+
var fileSchema = z11.object({
|
|
7635
|
+
filename: z11.string(),
|
|
7636
|
+
data: z11.string()
|
|
7403
7637
|
// base64
|
|
7404
7638
|
});
|
|
7405
|
-
var chatSchema =
|
|
7406
|
-
message:
|
|
7407
|
-
conversationId:
|
|
7408
|
-
targetMind:
|
|
7409
|
-
sender:
|
|
7410
|
-
images:
|
|
7411
|
-
|
|
7412
|
-
media_type:
|
|
7413
|
-
data:
|
|
7639
|
+
var chatSchema = z11.object({
|
|
7640
|
+
message: z11.string().optional(),
|
|
7641
|
+
conversationId: z11.string().optional(),
|
|
7642
|
+
targetMind: z11.string().optional(),
|
|
7643
|
+
sender: z11.string().optional(),
|
|
7644
|
+
images: z11.array(
|
|
7645
|
+
z11.object({
|
|
7646
|
+
media_type: z11.string(),
|
|
7647
|
+
data: z11.string()
|
|
7414
7648
|
})
|
|
7415
7649
|
).optional(),
|
|
7416
|
-
files:
|
|
7650
|
+
files: z11.array(fileSchema).optional()
|
|
7417
7651
|
});
|
|
7418
7652
|
var MAX_FILE_SIZE2 = 50 * 1024 * 1024;
|
|
7419
7653
|
function stageFilesForMinds(files, targetMinds, senderName) {
|
|
@@ -7441,9 +7675,9 @@ function stageFilesForMinds(files, targetMinds, senderName) {
|
|
|
7441
7675
|
}
|
|
7442
7676
|
return { notifications };
|
|
7443
7677
|
}
|
|
7444
|
-
var unifiedChatApp = new
|
|
7678
|
+
var unifiedChatApp = new Hono27().post(
|
|
7445
7679
|
"/chat",
|
|
7446
|
-
|
|
7680
|
+
zValidator11("json", chatSchema),
|
|
7447
7681
|
async (c) => {
|
|
7448
7682
|
const user = c.get("user");
|
|
7449
7683
|
const body = c.req.valid("json");
|
|
@@ -7454,7 +7688,7 @@ var unifiedChatApp = new Hono26().post(
|
|
|
7454
7688
|
return c.json({ error: "conversationId or targetMind required" }, 400);
|
|
7455
7689
|
}
|
|
7456
7690
|
const senderName = user.id === 0 && body.sender ? body.sender : user.username;
|
|
7457
|
-
const senderIsMind = user.id === 0 && body.sender && await findMind(body.sender) || user.user_type === "mind";
|
|
7691
|
+
const senderIsMind = user.id === 0 && body.sender && await findMind(body.sender) || user.user_type === "mind" || user.user_type === "system" && !!await findMind(user.username);
|
|
7458
7692
|
let baseName;
|
|
7459
7693
|
let variantName;
|
|
7460
7694
|
let conversationId = body.conversationId;
|
|
@@ -7531,7 +7765,7 @@ var unifiedChatApp = new Hono26().post(
|
|
|
7531
7765
|
}
|
|
7532
7766
|
}
|
|
7533
7767
|
if (senderIsMind) {
|
|
7534
|
-
const vCfg = readVoluteConfig(
|
|
7768
|
+
const vCfg = readVoluteConfig(await resolveMindDir(baseName ?? senderName));
|
|
7535
7769
|
const shouldUnescapeNewlines = vCfg?.unescapeNewlines === true;
|
|
7536
7770
|
for (const block of contentBlocks) {
|
|
7537
7771
|
if (block.type === "text") {
|
|
@@ -7624,18 +7858,21 @@ var unifiedChatApp = new Hono26().post(
|
|
|
7624
7858
|
targetName: baseName ? (username) => username === baseName ? variantName : username : void 0
|
|
7625
7859
|
});
|
|
7626
7860
|
const systemReplyTarget = baseName ?? senderName;
|
|
7627
|
-
if (
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7861
|
+
if (shouldGenerateSystemFallback({
|
|
7862
|
+
senderIsMind: !!senderIsMind,
|
|
7863
|
+
hasMessage: !!body.message,
|
|
7864
|
+
convType: conv.type,
|
|
7865
|
+
participants,
|
|
7866
|
+
replyTarget: systemReplyTarget
|
|
7867
|
+
})) {
|
|
7868
|
+
generateSystemFallbackReply(conversationId, systemReplyTarget, body.message).catch(
|
|
7869
|
+
(err) => logger_default.error(`system reply generation failed for ${systemReplyTarget}`, logger_default.errorData(err))
|
|
7870
|
+
);
|
|
7634
7871
|
}
|
|
7635
7872
|
return c.json({ ok: true, conversationId, outboundId });
|
|
7636
7873
|
}
|
|
7637
7874
|
);
|
|
7638
|
-
var app23 = new
|
|
7875
|
+
var app23 = new Hono27().get("/:name/conversations/:id/events", async (c) => {
|
|
7639
7876
|
const conversationId = c.req.param("id");
|
|
7640
7877
|
const user = c.get("user");
|
|
7641
7878
|
if (user.id !== 0 && !await isParticipantOrOwner(conversationId, user.id)) {
|
|
@@ -7664,14 +7901,14 @@ var app23 = new Hono26().get("/:name/conversations/:id/events", async (c) => {
|
|
|
7664
7901
|
var chat_default = app23;
|
|
7665
7902
|
|
|
7666
7903
|
// packages/daemon/src/web/api/volute/conversations.ts
|
|
7667
|
-
import { zValidator as
|
|
7668
|
-
import { Hono as
|
|
7669
|
-
import { z as
|
|
7670
|
-
var createConvSchema =
|
|
7671
|
-
participantIds:
|
|
7672
|
-
participantNames:
|
|
7904
|
+
import { zValidator as zValidator12 } from "@hono/zod-validator";
|
|
7905
|
+
import { Hono as Hono28 } from "hono";
|
|
7906
|
+
import { z as z12 } from "zod";
|
|
7907
|
+
var createConvSchema = z12.object({
|
|
7908
|
+
participantIds: z12.array(z12.number()).optional(),
|
|
7909
|
+
participantNames: z12.array(z12.string()).optional()
|
|
7673
7910
|
});
|
|
7674
|
-
var app24 = new
|
|
7911
|
+
var app24 = new Hono28().get("/:name/conversations", async (c) => {
|
|
7675
7912
|
const name = c.req.param("name");
|
|
7676
7913
|
const user = c.get("user");
|
|
7677
7914
|
let lookupId = user.id;
|
|
@@ -7681,7 +7918,7 @@ var app24 = new Hono27().get("/:name/conversations", async (c) => {
|
|
|
7681
7918
|
}
|
|
7682
7919
|
const convs = await listConversationsForUser(lookupId);
|
|
7683
7920
|
return c.json(convs);
|
|
7684
|
-
}).post("/:name/conversations",
|
|
7921
|
+
}).post("/:name/conversations", zValidator12("json", createConvSchema), async (c) => {
|
|
7685
7922
|
const name = c.req.param("name");
|
|
7686
7923
|
const user = c.get("user");
|
|
7687
7924
|
const body = c.req.valid("json");
|
|
@@ -7777,7 +8014,7 @@ var conversations_default2 = app24;
|
|
|
7777
8014
|
|
|
7778
8015
|
// packages/daemon/src/web/app.ts
|
|
7779
8016
|
var httpLog = logger_default.child("http");
|
|
7780
|
-
var app25 = new
|
|
8017
|
+
var app25 = new Hono29();
|
|
7781
8018
|
app25.onError((err, c) => {
|
|
7782
8019
|
if (err instanceof HTTPException) {
|
|
7783
8020
|
return err.getResponse();
|
|
@@ -7844,10 +8081,11 @@ app25.use("/api/skills/*", authMiddleware);
|
|
|
7844
8081
|
app25.use("/api/extensions/*", authMiddleware);
|
|
7845
8082
|
app25.use("/api/bridges/*", authMiddleware);
|
|
7846
8083
|
app25.use("/api/config/*", authMiddleware);
|
|
8084
|
+
app25.use("/api/backup/*", authMiddleware);
|
|
7847
8085
|
app25.use("/api/v1/*", authMiddleware);
|
|
7848
8086
|
app25.route("/api/setup", setup_default);
|
|
7849
8087
|
app25.route("/api/config", config_default);
|
|
7850
|
-
var routes = app25.route("/api/activity", activity_default).route("/api/keys", keys_default).route("/api/auth", auth_default).route("/api/system", system_default).route("/api/system", update_default).route("/api/minds", minds_default).route("/api/minds", chat_default).route("/api/minds", schedules_default).route("/api/minds", logs_default).route("/api/minds", typing_default).route("/api/minds", variants_default).route("/api/minds", file_sharing_default).route("/api/minds", files_default).route("/api/minds", channels_default).route("/api/minds", env_default).route("/api/minds", mind_skills_default).route("/api/minds", conversations_default2).route("/api/env", sharedEnvApp).route("/api/prompts", prompts_default).route("/api/skills", skills_default).route("/api/bridges", bridges_default).route("/api/extensions", extensions_default).route("/api/v1/conversations", conversations_default).route("/api/v1/events", events_default).route("/api/v1", unifiedChatApp).route("/api/v1/channels", channels_default2).route("/api/v1/history", history_default);
|
|
8088
|
+
var routes = app25.route("/api/activity", activity_default).route("/api/keys", keys_default).route("/api/auth", auth_default).route("/api/system", system_default).route("/api/system", update_default).route("/api/backup", backup_default).route("/api/minds", minds_default).route("/api/minds", chat_default).route("/api/minds", schedules_default).route("/api/minds", logs_default).route("/api/minds", typing_default).route("/api/minds", variants_default).route("/api/minds", file_sharing_default).route("/api/minds", files_default).route("/api/minds", channels_default).route("/api/minds", env_default).route("/api/minds", mind_skills_default).route("/api/minds", conversations_default2).route("/api/env", sharedEnvApp).route("/api/prompts", prompts_default).route("/api/skills", skills_default).route("/api/bridges", bridges_default).route("/api/extensions", extensions_default).route("/api/v1/conversations", conversations_default).route("/api/v1/events", events_default).route("/api/v1", unifiedChatApp).route("/api/v1/channels", channels_default2).route("/api/v1/history", history_default);
|
|
7851
8089
|
app25.route("/api/v1/minds", minds_default);
|
|
7852
8090
|
app25.route("/api/v1/minds", chat_default);
|
|
7853
8091
|
app25.route("/api/v1/minds", typing_default);
|
|
@@ -7906,8 +8144,8 @@ async function startServer({
|
|
|
7906
8144
|
const ext = extname3(filePath);
|
|
7907
8145
|
const mime = MIME_TYPES2[ext] || "application/octet-stream";
|
|
7908
8146
|
const body = await readFile2(filePath);
|
|
7909
|
-
const
|
|
7910
|
-
const nameWithoutExt =
|
|
8147
|
+
const basename = filePath.slice(filePath.lastIndexOf("/") + 1);
|
|
8148
|
+
const nameWithoutExt = basename.slice(0, basename.lastIndexOf("."));
|
|
7911
8149
|
const isHashed = /[-.][\da-f]{8,}$/.test(nameWithoutExt);
|
|
7912
8150
|
const cacheControl = isHashed ? "public, max-age=31536000, immutable" : "no-cache";
|
|
7913
8151
|
return c.body(body, 200, { "Content-Type": mime, "Cache-Control": cacheControl });
|
|
@@ -8005,27 +8243,27 @@ async function startDaemon(opts) {
|
|
|
8005
8243
|
const DAEMON_TOKEN_PATH = resolve16(systemDir, "daemon-token");
|
|
8006
8244
|
mkdirSync10(home, { recursive: true });
|
|
8007
8245
|
ensureSystemDir();
|
|
8008
|
-
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-
|
|
8246
|
+
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-Y2EJI3GG.js");
|
|
8009
8247
|
migrateConfigSecrets();
|
|
8010
8248
|
migrateSetupCompleted();
|
|
8011
|
-
const { migrateAiModelQualification } = await import("./ai-service-
|
|
8249
|
+
const { migrateAiModelQualification } = await import("./ai-service-UODCCE4O.js");
|
|
8012
8250
|
migrateAiModelQualification();
|
|
8013
|
-
await (await import("./db-
|
|
8251
|
+
await (await import("./db-MF2JNRUW.js")).getDb();
|
|
8014
8252
|
try {
|
|
8015
8253
|
const { eq: eq8, and: and6 } = await import("drizzle-orm");
|
|
8016
8254
|
const { users: users2 } = await import("./schema-PVNG3PQM.js");
|
|
8017
|
-
const db = await (await import("./db-
|
|
8255
|
+
const db = await (await import("./db-MF2JNRUW.js")).getDb();
|
|
8018
8256
|
await db.update(users2).set({ role: "system" }).where(and6(eq8(users2.user_type, "system"), eq8(users2.role, "user")));
|
|
8019
8257
|
} catch (err) {
|
|
8020
8258
|
logger_default.warn("failed to migrate system user role", logger_default.errorData(err));
|
|
8021
8259
|
}
|
|
8022
8260
|
try {
|
|
8023
|
-
const { migrateAvatarSizes } = await import("./avatar-image-
|
|
8261
|
+
const { migrateAvatarSizes } = await import("./avatar-image-6KY6UU4D.js");
|
|
8024
8262
|
await migrateAvatarSizes();
|
|
8025
8263
|
} catch (err) {
|
|
8026
8264
|
logger_default.warn("avatar size migration failed", logger_default.errorData(err));
|
|
8027
8265
|
}
|
|
8028
|
-
const { initSandbox } = await import("./sandbox-
|
|
8266
|
+
const { initSandbox } = await import("./sandbox-ZJ7QA6Z6.js");
|
|
8029
8267
|
await initSandbox();
|
|
8030
8268
|
try {
|
|
8031
8269
|
await syncBuiltinSkills();
|
|
@@ -8052,7 +8290,7 @@ async function startDaemon(opts) {
|
|
|
8052
8290
|
logger_default.warn("failed to ensure #system channel", logger_default.errorData(err));
|
|
8053
8291
|
}
|
|
8054
8292
|
try {
|
|
8055
|
-
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-
|
|
8293
|
+
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-FLAEXXZK.js");
|
|
8056
8294
|
await getOrCreateSystemUser2();
|
|
8057
8295
|
} catch (err) {
|
|
8058
8296
|
logger_default.warn(
|
|
@@ -8060,13 +8298,13 @@ async function startDaemon(opts) {
|
|
|
8060
8298
|
logger_default.errorData(err)
|
|
8061
8299
|
);
|
|
8062
8300
|
}
|
|
8063
|
-
const token = process.env.VOLUTE_DAEMON_TOKEN ||
|
|
8064
|
-
const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-
|
|
8301
|
+
const token = process.env.VOLUTE_DAEMON_TOKEN || randomBytes3(32).toString("hex");
|
|
8302
|
+
const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-Y2EJI3GG.js");
|
|
8065
8303
|
const globalCfg = readGlobalConfig2();
|
|
8066
8304
|
let tls;
|
|
8067
8305
|
if (opts.tailscale || globalCfg.tailscale) {
|
|
8068
8306
|
try {
|
|
8069
|
-
const { getTailscaleTls } = await import("./tailscale-
|
|
8307
|
+
const { getTailscaleTls } = await import("./tailscale-3XOKOW7T.js");
|
|
8070
8308
|
const tlsConfig = await getTailscaleTls();
|
|
8071
8309
|
tls = { key: tlsConfig.key, cert: tlsConfig.cert };
|
|
8072
8310
|
logger_default.info("Tailscale HTTPS enabled", { hostname: tlsConfig.hostname });
|
|
@@ -8112,6 +8350,8 @@ async function startDaemon(opts) {
|
|
|
8112
8350
|
sleepManager.start();
|
|
8113
8351
|
const summarizer = initSummarizer();
|
|
8114
8352
|
summarizer.start();
|
|
8353
|
+
const backupManager2 = initBackupManager();
|
|
8354
|
+
backupManager2.start();
|
|
8115
8355
|
const unsubscribeWebhook = initWebhook();
|
|
8116
8356
|
const orphanedTurns = await completeOrphanedTurns();
|
|
8117
8357
|
summarizeOrphanedTurns(orphanedTurns);
|
|
@@ -8144,10 +8384,10 @@ async function startDaemon(opts) {
|
|
|
8144
8384
|
await Promise.all(workers);
|
|
8145
8385
|
}
|
|
8146
8386
|
try {
|
|
8147
|
-
const { isSetupComplete: isSetupComplete2 } = await import("./setup-
|
|
8387
|
+
const { isSetupComplete: isSetupComplete2 } = await import("./setup-Y2EJI3GG.js");
|
|
8148
8388
|
if (isSetupComplete2()) {
|
|
8149
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
8150
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
8389
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-DBTIW7P4.js");
|
|
8390
|
+
const { startSpiritFull } = await import("./mind-service-3F4I46CI.js");
|
|
8151
8391
|
await ensureSpiritProject();
|
|
8152
8392
|
await syncSpiritTemplate();
|
|
8153
8393
|
const spiritEntry = await findMind("volute");
|
|
@@ -8164,7 +8404,7 @@ async function startDaemon(opts) {
|
|
|
8164
8404
|
bridgeManager.startBridges(daemonPort).catch((err) => {
|
|
8165
8405
|
logger_default.warn("failed to start bridges", logger_default.errorData(err));
|
|
8166
8406
|
});
|
|
8167
|
-
import("./cloud-sync-
|
|
8407
|
+
import("./cloud-sync-3OJOPZRT.js").then(
|
|
8168
8408
|
({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
|
|
8169
8409
|
logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
|
|
8170
8410
|
})
|
|
@@ -8172,7 +8412,7 @@ async function startDaemon(opts) {
|
|
|
8172
8412
|
logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
|
|
8173
8413
|
});
|
|
8174
8414
|
try {
|
|
8175
|
-
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-
|
|
8415
|
+
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-3XMAIQTE.js");
|
|
8176
8416
|
backfillTemplateHashes();
|
|
8177
8417
|
notifyVersionUpdate().catch((err) => {
|
|
8178
8418
|
logger_default.warn("failed to send version update notifications", logger_default.errorData(err));
|
|
@@ -8240,6 +8480,7 @@ async function startDaemon(opts) {
|
|
|
8240
8480
|
safe("mailPoller.stop", () => mailPoller.stop());
|
|
8241
8481
|
safe("tokenBudget.stop", () => tokenBudget.stop());
|
|
8242
8482
|
safe("summarizer.stop", () => summarizer.stop());
|
|
8483
|
+
safe("backupManager.stop", () => backupManager2.stop());
|
|
8243
8484
|
safe("stopApiKeyRefresh", stopApiKeyRefresh);
|
|
8244
8485
|
safe("delivery.dispose", () => delivery.dispose());
|
|
8245
8486
|
await safe("bridgeManager.stopAll", () => bridgeManager.stopAll());
|