volute 0.45.1 → 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-534WUSDL.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-OZXHL3JS.js → backup-TST5C2YN.js} +7 -7
- package/dist/{chat-I4EDDIQC.js → chat-76MRWWQX.js} +2 -2
- package/dist/{chunk-ZIR7HSAX.js → chunk-4JOQZPCE.js} +1 -1
- package/dist/{chunk-2BONPXAF.js → chunk-6EMWJZBK.js} +1 -1
- package/dist/{chunk-ZMIMSIIT.js → chunk-7C44R625.js} +1 -1
- package/dist/{chunk-Y6OPHHGM.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-322KE457.js → chunk-F7H6ATM4.js} +1 -1
- package/dist/{chunk-5AUKCNPE.js → chunk-FR6S2KNN.js} +8 -8
- package/dist/{chunk-KVKP6VQ5.js → chunk-FXORA5JG.js} +12 -3
- package/dist/{chunk-3ERIL673.js → chunk-H2X54EHC.js} +1 -1
- package/dist/{chunk-TSK5PI4L.js → chunk-IHKGWTGT.js} +1 -1
- package/dist/{chunk-OXXTPILE.js → chunk-JZ62SYWR.js} +1 -1
- package/dist/{chunk-77BVGCTZ.js → chunk-NYC5U6K7.js} +9 -9
- package/dist/{chunk-JSRMEY52.js → chunk-OP4JG2BS.js} +5 -4
- package/dist/{chunk-CU6OFXMM.js → chunk-PFZBNKUH.js} +9 -0
- package/dist/{chunk-QMJJWTNL.js → chunk-QCN24XEN.js} +1 -1
- package/dist/{chunk-IUXTYXFI.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-V4GYPD5L.js → chunk-UYLGEDVD.js} +4 -4
- package/dist/{chunk-U4FNXDEJ.js → chunk-YT7PEESJ.js} +231 -98
- package/dist/{chunk-5GT7URXJ.js → chunk-ZDZISKCL.js} +1 -1
- package/dist/cli.js +16 -16
- package/dist/{cloud-sync-Y7LQPRE3.js → cloud-sync-3OJOPZRT.js} +16 -16
- package/dist/{conversations-G4LYMHAA.js → conversations-JZTD6KLR.js} +3 -3
- package/dist/{create-2YY7IPMS.js → create-IOV4GCRX.js} +1 -1
- package/dist/{daemon-restart-ABP54YN6.js → daemon-restart-TIHKVVVA.js} +6 -6
- package/dist/daemon.js +180 -137
- package/dist/{db-JFLCJCUG.js → db-MF2JNRUW.js} +1 -1
- package/dist/delivery-manager-VDVKVA46.js +32 -0
- package/dist/{delivery-router-6DE3BPHO.js → delivery-router-N4A7ZC5T.js} +2 -2
- package/dist/{down-XCAZXWLB.js → down-U2CZ23M4.js} +4 -4
- package/dist/echo-text-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-AYSPKE33.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-KLHC7XYR.js → mind-DWB6XYCH.js} +6 -6
- 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-BMHV7UHN.js → package-A7KXT67Q.js} +1 -1
- package/dist/{registry-NUJAGLQJ.js → registry-OUZBZ3Q4.js} +5 -1
- package/dist/{sandbox-72MWV4JL.js → sandbox-ZJ7QA6Z6.js} +3 -3
- package/dist/scheduler-P6DXLLXI.js +30 -0
- package/dist/{seed-4MKQ5QKG.js → seed-HCP5NYKH.js} +1 -1
- package/dist/{seed-cmd-LCXMR7VV.js → seed-cmd-ILOGNIFB.js} +2 -2
- package/dist/{seed-create-N2BF5LQX.js → seed-create-OURS2LS4.js} +3 -3
- package/dist/{seed-sprout-6ZDP23YI.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-3O6O2JZ7.js → setup-DQM5VPY4.js} +6 -6
- package/dist/{setup-73YBJZQL.js → setup-Y2EJI3GG.js} +2 -2
- package/dist/skills/imagegen/scripts/imagegen.ts +100 -40
- package/dist/skills/volute-mind/SKILL.md +5 -1
- package/dist/{skills-ND4ZFYUW.js → skills-BKINFL7W.js} +4 -4
- package/dist/sleep-manager-HCUH4PM4.js +34 -0
- package/dist/{spirit-II3HOERM.js → spirit-DBTIW7P4.js} +7 -7
- package/dist/{sprout-4KUG76AQ.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-QQIVVXBI.js → turn-tracker-2W6Q2NSR.js} +4 -4
- package/dist/{up-LG56MPBI.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/{version-notify-CODJOUW2.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-Dac11sKB.js → index-Bc2m8gRC.js} +15 -15
- package/dist/web-assets/index.html +1 -1
- package/package.json +1 -1
- package/templates/_base/src/lib/file-handler.ts +3 -3
- package/templates/_base/src/lib/router.ts +21 -25
- package/templates/_base/src/lib/startup.ts +2 -0
- package/templates/_base/src/lib/types.ts +2 -2
- package/templates/claude/src/agent.ts +75 -10
- package/templates/claude/src/lib/message-channel.ts +23 -0
- package/templates/claude/src/lib/session-reaper.ts +37 -0
- package/templates/claude/src/server.ts +1 -0
- package/templates/codex/src/agent.ts +18 -6
- package/templates/pi/src/agent.ts +18 -7
- package/dist/delivery-manager-R5STGLXB.js +0 -32
- package/dist/echo-text-NQXYYYCU.js +0 -32
- package/dist/message-delivery-IUAXRPFE.js +0 -34
- package/dist/mind-service-BF2LUQMH.js +0 -36
- package/dist/scheduler-YHJRRV6E.js +0 -30
- package/dist/sleep-manager-YAHDOIU5.js +0 -34
- package/dist/system-chat-E65T2HSW.js +0 -34
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
loadMergedEnv
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZDZISKCL.js";
|
|
5
5
|
import {
|
|
6
6
|
spiritDir
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-FR6S2KNN.js";
|
|
8
8
|
import {
|
|
9
9
|
hashSkillDir,
|
|
10
10
|
importSkillFromDir,
|
|
11
11
|
removeSharedSkill,
|
|
12
12
|
sharedSkillsDir
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-7ZUB63PS.js";
|
|
14
14
|
import {
|
|
15
15
|
addMessage,
|
|
16
16
|
createChannel,
|
|
@@ -20,74 +20,77 @@ import {
|
|
|
20
20
|
getParticipants,
|
|
21
21
|
joinChannel,
|
|
22
22
|
publish as publish2
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-OP4JG2BS.js";
|
|
24
24
|
import {
|
|
25
25
|
readVoluteConfig,
|
|
26
|
+
resolveWakeTriggers,
|
|
26
27
|
writeVoluteConfig
|
|
27
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-PFZBNKUH.js";
|
|
28
29
|
import {
|
|
29
30
|
isSandboxEnabled,
|
|
30
31
|
wrapForSandbox
|
|
31
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-JZ62SYWR.js";
|
|
32
33
|
import {
|
|
33
34
|
markIdle,
|
|
34
35
|
onMindEvent
|
|
35
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-EJVPTVTI.js";
|
|
36
37
|
import {
|
|
37
38
|
extractTextContent,
|
|
38
39
|
getRoutingConfig,
|
|
39
40
|
resolveDeliveryMode,
|
|
40
41
|
resolveRoute,
|
|
41
42
|
setRoutesChangeListener
|
|
42
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-4JOQZPCE.js";
|
|
43
44
|
import {
|
|
44
45
|
clearMind,
|
|
45
46
|
getPrompt,
|
|
46
47
|
linkInboundToActiveTurn,
|
|
47
48
|
publish as publish3,
|
|
48
49
|
summarizeOrphanedTurns
|
|
49
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-UYLGEDVD.js";
|
|
50
51
|
import {
|
|
51
52
|
chownMindDir,
|
|
52
53
|
exec,
|
|
53
54
|
isIsolationEnabled,
|
|
54
55
|
mindUserName,
|
|
55
56
|
wrapForIsolation
|
|
56
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-H2X54EHC.js";
|
|
57
58
|
import {
|
|
58
59
|
aiCompleteUtility,
|
|
59
60
|
getAiConfig,
|
|
60
61
|
resolveApiKey
|
|
61
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-IHKGWTGT.js";
|
|
62
63
|
import {
|
|
63
64
|
readGlobalConfig,
|
|
64
65
|
writeGlobalConfig
|
|
65
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-F7H6ATM4.js";
|
|
66
67
|
import {
|
|
67
68
|
getOrCreateMindUser,
|
|
68
69
|
getOrCreateSystemUser,
|
|
69
70
|
getUser,
|
|
70
71
|
getUserByUsername,
|
|
71
72
|
syncMindProfile
|
|
72
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-T6HYVHPG.js";
|
|
73
74
|
import {
|
|
74
75
|
publish,
|
|
75
76
|
subscribe
|
|
76
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-7C44R625.js";
|
|
77
78
|
import {
|
|
78
79
|
logger_default
|
|
79
80
|
} from "./chunk-T2TP6ZC6.js";
|
|
80
81
|
import {
|
|
82
|
+
SPIRIT_NAME,
|
|
81
83
|
findMind,
|
|
82
84
|
getBaseName,
|
|
83
85
|
getDb,
|
|
86
|
+
isSpiritName,
|
|
84
87
|
mindDir,
|
|
85
88
|
mindTmpDir,
|
|
86
89
|
setMindRunning,
|
|
87
90
|
stateDir,
|
|
88
91
|
voluteHome,
|
|
89
92
|
voluteSystemDir
|
|
90
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-ALKYQULU.js";
|
|
91
94
|
import {
|
|
92
95
|
activity,
|
|
93
96
|
deliveryQueue,
|
|
@@ -98,7 +101,7 @@ import {
|
|
|
98
101
|
} from "./chunk-ZV7MFISX.js";
|
|
99
102
|
|
|
100
103
|
// packages/daemon/src/lib/delivery/message-delivery.ts
|
|
101
|
-
import { and as and5, eq as eq6, inArray as
|
|
104
|
+
import { and as and5, eq as eq6, inArray as inArray2 } from "drizzle-orm";
|
|
102
105
|
|
|
103
106
|
// packages/daemon/src/lib/daemon/sleep-manager.ts
|
|
104
107
|
import { execFile as execFile2, spawn as spawnChild } from "child_process";
|
|
@@ -114,7 +117,7 @@ import {
|
|
|
114
117
|
import { resolve as resolve7 } from "path";
|
|
115
118
|
import { promisify as promisify2 } from "util";
|
|
116
119
|
import { CronExpressionParser as CronExpressionParser2 } from "cron-parser";
|
|
117
|
-
import { and as and2, eq as eq3
|
|
120
|
+
import { and as and2, eq as eq3 } from "drizzle-orm";
|
|
118
121
|
|
|
119
122
|
// packages/daemon/src/lib/daemon/mind-manager.ts
|
|
120
123
|
import { execFile, spawn } from "child_process";
|
|
@@ -335,6 +338,9 @@ function revokeMindToken(mindName) {
|
|
|
335
338
|
function resolveMindToken(token) {
|
|
336
339
|
return tokenToMind.get(token) ?? null;
|
|
337
340
|
}
|
|
341
|
+
function getMindToken(mindName) {
|
|
342
|
+
return mindToToken.get(mindName) ?? null;
|
|
343
|
+
}
|
|
338
344
|
|
|
339
345
|
// packages/daemon/src/lib/daemon/notices.ts
|
|
340
346
|
import { and, asc, eq, lte, or, sql } from "drizzle-orm";
|
|
@@ -939,7 +945,7 @@ var MindManager = class {
|
|
|
939
945
|
if (this.shuttingDown || this.stopping.has(name)) return;
|
|
940
946
|
mlog.error(`mind ${name} exited with code ${code}`);
|
|
941
947
|
try {
|
|
942
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
948
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
|
|
943
949
|
const sleepMgr = getSleepManagerIfReady2();
|
|
944
950
|
const sleepState = sleepMgr?.getState(name);
|
|
945
951
|
if (sleepState?.sleeping) {
|
|
@@ -969,15 +975,15 @@ var MindManager = class {
|
|
|
969
975
|
(err) => mlog.warn(`failed to clear turn state for ${name} after crash`, logger_default.errorData(err))
|
|
970
976
|
);
|
|
971
977
|
try {
|
|
972
|
-
const { getDeliveryManager: getDeliveryManager2 } = await import("./delivery-manager-
|
|
978
|
+
const { getDeliveryManager: getDeliveryManager2 } = await import("./delivery-manager-VDVKVA46.js");
|
|
973
979
|
getDeliveryManager2().clearMindSessions(name);
|
|
974
980
|
} catch (err) {
|
|
975
981
|
if (!(err instanceof Error && err.message.includes("not initialized"))) {
|
|
976
982
|
mlog.warn(`failed to clear delivery state for ${name} after crash`, logger_default.errorData(err));
|
|
977
983
|
}
|
|
978
984
|
}
|
|
979
|
-
import("./mind-activity-tracker-
|
|
980
|
-
import("./activity-events-
|
|
985
|
+
import("./mind-activity-tracker-POBLU3LC.js").then(({ markIdle: markIdle2 }) => markIdle2(name)).catch((err) => mlog.warn(`failed to mark ${name} idle after crash`, logger_default.errorData(err)));
|
|
986
|
+
import("./activity-events-BUR2RYTJ.js").then(
|
|
981
987
|
({ publish: publish4 }) => publish4({ type: "mind_stopped", mind: name, summary: `${name} crashed (exit ${code})` })
|
|
982
988
|
).catch((err) => mlog.warn(`failed to publish crash event for ${name}`, logger_default.errorData(err)));
|
|
983
989
|
const { shouldRestart, delay, attempt } = this.restartTracker.recordCrash(name);
|
|
@@ -1035,7 +1041,7 @@ var MindManager = class {
|
|
|
1035
1041
|
mlog.warn(`failed to clear turn state for ${name} on stop`, logger_default.errorData(err));
|
|
1036
1042
|
}
|
|
1037
1043
|
try {
|
|
1038
|
-
const { getDeliveryManager: getDeliveryManager2 } = await import("./delivery-manager-
|
|
1044
|
+
const { getDeliveryManager: getDeliveryManager2 } = await import("./delivery-manager-VDVKVA46.js");
|
|
1039
1045
|
getDeliveryManager2().clearMindSessions(name);
|
|
1040
1046
|
} catch (err) {
|
|
1041
1047
|
if (!(err instanceof Error && err.message.includes("not initialized"))) {
|
|
@@ -1043,7 +1049,7 @@ var MindManager = class {
|
|
|
1043
1049
|
}
|
|
1044
1050
|
}
|
|
1045
1051
|
try {
|
|
1046
|
-
const { clearEchoTextCache } = await import("./echo-text-
|
|
1052
|
+
const { clearEchoTextCache } = await import("./echo-text-6JJOPUD4.js");
|
|
1047
1053
|
clearEchoTextCache(name);
|
|
1048
1054
|
} catch (err) {
|
|
1049
1055
|
mlog.debug(`failed to clear echo-text cache for ${name}`, logger_default.errorData(err));
|
|
@@ -1699,7 +1705,7 @@ function resolveSkillsDir(manifest) {
|
|
|
1699
1705
|
async function discoverBuiltinExtensions(disabledIds) {
|
|
1700
1706
|
const builtins = [
|
|
1701
1707
|
{ id: "notes", load: async () => (await import("./src-YH6PQ7LJ.js")).default },
|
|
1702
|
-
{ id: "pages", load: async () => (await import("./src-
|
|
1708
|
+
{ id: "pages", load: async () => (await import("./src-OJHARHTF.js")).default },
|
|
1703
1709
|
{ id: "plan", load: async () => (await import("./src-JAOVXO5W.js")).default }
|
|
1704
1710
|
];
|
|
1705
1711
|
const results = [];
|
|
@@ -1949,7 +1955,7 @@ async function installNpmExtension(pkg) {
|
|
|
1949
1955
|
throw new Error(`Extension "${pkg}" is already installed`);
|
|
1950
1956
|
}
|
|
1951
1957
|
const dir = ensureExtensionsNpmDir();
|
|
1952
|
-
const { exec: exec2 } = await import("./exec-
|
|
1958
|
+
const { exec: exec2 } = await import("./exec-G3ZRST4Z.js");
|
|
1953
1959
|
try {
|
|
1954
1960
|
await exec2("npm", ["install", "--ignore-scripts", pkg], { cwd: dir });
|
|
1955
1961
|
} catch (err) {
|
|
@@ -1970,7 +1976,7 @@ async function uninstallNpmExtension(pkg) {
|
|
|
1970
1976
|
packages.splice(idx, 1);
|
|
1971
1977
|
writeExtensionsConfig(packages);
|
|
1972
1978
|
try {
|
|
1973
|
-
const { exec: exec2 } = await import("./exec-
|
|
1979
|
+
const { exec: exec2 } = await import("./exec-G3ZRST4Z.js");
|
|
1974
1980
|
await exec2("npm", ["uninstall", "--ignore-scripts", pkg], { cwd: extensionsNpmDir() });
|
|
1975
1981
|
} catch (err) {
|
|
1976
1982
|
logger_default.warn(
|
|
@@ -2415,7 +2421,9 @@ ${stderr}` : ""}`;
|
|
|
2415
2421
|
return;
|
|
2416
2422
|
}
|
|
2417
2423
|
await this.deliverSystem(mindName, `[${schedule.id}] ${text}`, {
|
|
2418
|
-
|
|
2424
|
+
// Default schedule fires to "queue" while asleep so an unadorned cron
|
|
2425
|
+
// schedule doesn't inherit the DM wake-trigger fallback and wake the mind.
|
|
2426
|
+
whileSleeping: schedule.whileSleeping ?? "queue",
|
|
2419
2427
|
session: schedule.session
|
|
2420
2428
|
});
|
|
2421
2429
|
slog2.info(`fired "${schedule.id}" for ${mindName}`);
|
|
@@ -2452,15 +2460,41 @@ ${stderr}` : ""}`;
|
|
|
2452
2460
|
}
|
|
2453
2461
|
}
|
|
2454
2462
|
async runScript(script, cwd, mindName) {
|
|
2463
|
+
const env = await this.buildScriptEnv(mindName);
|
|
2455
2464
|
if (isSandboxEnabled()) {
|
|
2456
2465
|
const dir = this.mindDirs.get(mindName) ?? mindDir(mindName);
|
|
2457
2466
|
const [cmd, args] = await wrapForSandbox("bash", ["-c", script], dir, mindName, [
|
|
2458
2467
|
dir,
|
|
2459
2468
|
mindTmpDir(dir)
|
|
2460
2469
|
]);
|
|
2461
|
-
return exec(cmd, args, { cwd });
|
|
2470
|
+
return exec(cmd, args, { cwd, env });
|
|
2462
2471
|
}
|
|
2463
|
-
return exec("bash", ["-c", script], { cwd, mindName });
|
|
2472
|
+
return exec("bash", ["-c", script], { cwd, mindName, env });
|
|
2473
|
+
}
|
|
2474
|
+
/**
|
|
2475
|
+
* Build the environment for a scheduled script — mirrors the mind process env
|
|
2476
|
+
* (allowlisted base + merged mind env + VOLUTE_* runtime vars), authenticated
|
|
2477
|
+
* with the mind's own per-mind, non-admin token. Reuses the running mind's
|
|
2478
|
+
* token when present; otherwise mints one (stable across fires, regenerated on
|
|
2479
|
+
* next mind start). The daemon admin token is never included.
|
|
2480
|
+
*/
|
|
2481
|
+
async buildScriptEnv(mindName) {
|
|
2482
|
+
const dir = this.mindDirs.get(mindName) ?? mindDir(mindName);
|
|
2483
|
+
const entry = await findMind(mindName);
|
|
2484
|
+
const token = getMindToken(mindName) ?? generateMindToken(mindName);
|
|
2485
|
+
const mindLocalBin = resolve5(dir, "home", ".local", "bin");
|
|
2486
|
+
const currentPath = process.env.PATH ?? "";
|
|
2487
|
+
return {
|
|
2488
|
+
...buildMindBaseEnv(),
|
|
2489
|
+
...loadMergedEnv(mindName),
|
|
2490
|
+
VOLUTE_MIND: mindName,
|
|
2491
|
+
VOLUTE_STATE_DIR: stateDir(mindName),
|
|
2492
|
+
VOLUTE_MIND_DIR: dir,
|
|
2493
|
+
VOLUTE_MIND_PORT: entry ? String(entry.port) : void 0,
|
|
2494
|
+
VOLUTE_MIND_TOKEN: token,
|
|
2495
|
+
TMPDIR: mindTmpDir(dir),
|
|
2496
|
+
PATH: `${mindLocalBin}:${currentPath}`
|
|
2497
|
+
};
|
|
2464
2498
|
}
|
|
2465
2499
|
deliverSystem(mindName, text, opts) {
|
|
2466
2500
|
return sendSystemMessage(mindName, text, opts);
|
|
@@ -2771,7 +2805,7 @@ async function wakeMind(name) {
|
|
|
2771
2805
|
async function startSpiritFull(name) {
|
|
2772
2806
|
const entry = await findMind(name);
|
|
2773
2807
|
if (entry?.dir) {
|
|
2774
|
-
const { registerMindDir } = await import("./delivery-router-
|
|
2808
|
+
const { registerMindDir } = await import("./delivery-router-N4A7ZC5T.js");
|
|
2775
2809
|
registerMindDir(name, entry.dir);
|
|
2776
2810
|
}
|
|
2777
2811
|
await getMindManager().startMind(name);
|
|
@@ -2793,8 +2827,8 @@ async function stopSpiritFull(name) {
|
|
|
2793
2827
|
}).catch((err) => logger_default.error("failed to publish spirit_stopped activity", logger_default.errorData(err)));
|
|
2794
2828
|
}
|
|
2795
2829
|
async function ensureCreatorDM(mindName, creatorUsername) {
|
|
2796
|
-
const { getOrCreateMindUser: getOrCreateMindUser2, getUserByUsername: getUserByUsername2 } = await import("./auth-
|
|
2797
|
-
const { findDMConversation: findDMConversation2, createConversation: createConversation2 } = await import("./conversations-
|
|
2830
|
+
const { getOrCreateMindUser: getOrCreateMindUser2, getUserByUsername: getUserByUsername2 } = await import("./auth-FLAEXXZK.js");
|
|
2831
|
+
const { findDMConversation: findDMConversation2, createConversation: createConversation2 } = await import("./conversations-JZTD6KLR.js");
|
|
2798
2832
|
const mindUser = await getOrCreateMindUser2(mindName);
|
|
2799
2833
|
const creatorUser = await getUserByUsername2(creatorUsername);
|
|
2800
2834
|
if (!creatorUser) {
|
|
@@ -2827,6 +2861,8 @@ async function stopMindFull(name) {
|
|
|
2827
2861
|
|
|
2828
2862
|
// packages/daemon/src/lib/daemon/sleep-manager.ts
|
|
2829
2863
|
var slog3 = logger_default.child("sleep");
|
|
2864
|
+
var MAX_WAKE_ATTEMPTS = 5;
|
|
2865
|
+
var WAKE_BACKOFF_MS = [6e4, 5 * 6e4, 15 * 6e4, 60 * 6e4];
|
|
2830
2866
|
function defaultState() {
|
|
2831
2867
|
return {
|
|
2832
2868
|
sleeping: false,
|
|
@@ -2835,7 +2871,9 @@ function defaultState() {
|
|
|
2835
2871
|
wokenByTrigger: false,
|
|
2836
2872
|
voluntaryWakeAt: null,
|
|
2837
2873
|
queuedMessageCount: 0,
|
|
2838
|
-
triggerWakeHistory: []
|
|
2874
|
+
triggerWakeHistory: [],
|
|
2875
|
+
wakeFailures: 0,
|
|
2876
|
+
nextWakeAttemptAt: null
|
|
2839
2877
|
};
|
|
2840
2878
|
}
|
|
2841
2879
|
function formatCurrentDate() {
|
|
@@ -2905,6 +2943,8 @@ var SleepManager = class {
|
|
|
2905
2943
|
const data = JSON.parse(readFileSync7(this.statePath, "utf-8"));
|
|
2906
2944
|
for (const [name, state2] of Object.entries(data)) {
|
|
2907
2945
|
state2.triggerWakeHistory ??= [];
|
|
2946
|
+
state2.wakeFailures ??= 0;
|
|
2947
|
+
state2.nextWakeAttemptAt ??= null;
|
|
2908
2948
|
this.states.set(name, state2);
|
|
2909
2949
|
}
|
|
2910
2950
|
}
|
|
@@ -3061,12 +3101,13 @@ var SleepManager = class {
|
|
|
3061
3101
|
try {
|
|
3062
3102
|
await wakeMind(name);
|
|
3063
3103
|
} catch (err) {
|
|
3064
|
-
|
|
3104
|
+
await this.handleWakeFailure(name, err);
|
|
3065
3105
|
return;
|
|
3066
3106
|
}
|
|
3067
3107
|
}
|
|
3068
3108
|
const entry = await findMind(name);
|
|
3069
3109
|
if (!entry) return;
|
|
3110
|
+
this.resetWakeBackoff(name);
|
|
3070
3111
|
if (opts?.trigger) {
|
|
3071
3112
|
state2.wokenByTrigger = true;
|
|
3072
3113
|
state2.triggerWakeHistory.push({
|
|
@@ -3140,8 +3181,7 @@ var SleepManager = class {
|
|
|
3140
3181
|
checkWakeTrigger(name, payload) {
|
|
3141
3182
|
const config = this.getSleepConfig(name);
|
|
3142
3183
|
const triggers = config?.wakeTriggers;
|
|
3143
|
-
const mentionsEnabled = triggers
|
|
3144
|
-
const dmsEnabled = triggers?.dms !== false;
|
|
3184
|
+
const { mentions: mentionsEnabled, dms: dmsEnabled } = resolveWakeTriggers(triggers);
|
|
3145
3185
|
if (dmsEnabled && payload.isDM) return true;
|
|
3146
3186
|
if (mentionsEnabled && payload.content) {
|
|
3147
3187
|
const text = typeof payload.content === "string" ? payload.content : Array.isArray(payload.content) ? payload.content.filter((b) => b.type === "text" && b.text).map((b) => b.text).join(" ") : "";
|
|
@@ -3186,29 +3226,110 @@ var SleepManager = class {
|
|
|
3186
3226
|
const db = await getDb();
|
|
3187
3227
|
const rows = await db.select().from(deliveryQueue).where(and2(eq3(deliveryQueue.mind, name), eq3(deliveryQueue.status, "sleep-queued"))).all();
|
|
3188
3228
|
if (rows.length === 0) return 0;
|
|
3189
|
-
|
|
3190
|
-
const delivered = [];
|
|
3229
|
+
let deliveredCount = 0;
|
|
3191
3230
|
for (const row of rows) {
|
|
3231
|
+
let payload;
|
|
3192
3232
|
try {
|
|
3193
|
-
|
|
3194
|
-
delivered.push(row.id);
|
|
3233
|
+
payload = JSON.parse(row.payload);
|
|
3195
3234
|
} catch (err) {
|
|
3196
|
-
slog3.warn(
|
|
3235
|
+
slog3.warn(
|
|
3236
|
+
`dropping unparseable queued message ${row.id} for ${name}`,
|
|
3237
|
+
logger_default.errorData(err)
|
|
3238
|
+
);
|
|
3239
|
+
await db.delete(deliveryQueue).where(eq3(deliveryQueue.id, row.id));
|
|
3240
|
+
continue;
|
|
3197
3241
|
}
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3242
|
+
const delivered = await this.deliverQueued(name, payload);
|
|
3243
|
+
if (!delivered) {
|
|
3244
|
+
slog3.warn(`failed to flush queued message ${row.id} for ${name}; leaving it queued`);
|
|
3245
|
+
break;
|
|
3246
|
+
}
|
|
3247
|
+
await db.delete(deliveryQueue).where(eq3(deliveryQueue.id, row.id));
|
|
3248
|
+
deliveredCount++;
|
|
3201
3249
|
}
|
|
3202
3250
|
const state2 = this.states.get(name);
|
|
3203
3251
|
if (state2) {
|
|
3204
|
-
state2.queuedMessageCount = Math.max(0, state2.queuedMessageCount -
|
|
3252
|
+
state2.queuedMessageCount = Math.max(0, state2.queuedMessageCount - deliveredCount);
|
|
3205
3253
|
}
|
|
3206
|
-
return
|
|
3254
|
+
return deliveredCount;
|
|
3207
3255
|
} catch (err) {
|
|
3208
3256
|
slog3.warn(`failed to flush queued messages for ${name}`, logger_default.errorData(err));
|
|
3209
3257
|
return 0;
|
|
3210
3258
|
}
|
|
3211
3259
|
}
|
|
3260
|
+
/**
|
|
3261
|
+
* Deliver one queued message on the wake path. `isFlush` skips the queue-time inbound
|
|
3262
|
+
* recording (kept once, at arrival) and bypasses the sleep re-queue so the now-waking mind
|
|
3263
|
+
* actually receives it. Returns whether the message was handed off to the delivery manager.
|
|
3264
|
+
* Extracted as a seam so the flush loop can be unit-tested without the real delivery stack.
|
|
3265
|
+
*/
|
|
3266
|
+
async deliverQueued(name, payload) {
|
|
3267
|
+
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-3C65ZI6L.js");
|
|
3268
|
+
return deliverMessage2(name, payload, { isFlush: true });
|
|
3269
|
+
}
|
|
3270
|
+
// --- Wake failure handling (#419) ---
|
|
3271
|
+
/**
|
|
3272
|
+
* Record a failed wake attempt. Applies exponential backoff between retries and,
|
|
3273
|
+
* after MAX_WAKE_ATTEMPTS consecutive failures, gives up and marks the mind errored
|
|
3274
|
+
* rather than retrying every tick forever.
|
|
3275
|
+
*/
|
|
3276
|
+
async handleWakeFailure(name, err) {
|
|
3277
|
+
const state2 = this.states.get(name);
|
|
3278
|
+
if (!state2?.sleeping) return;
|
|
3279
|
+
state2.wakeFailures = (state2.wakeFailures ?? 0) + 1;
|
|
3280
|
+
if (state2.wakeFailures >= MAX_WAKE_ATTEMPTS) {
|
|
3281
|
+
await this.markWakeErrored(name, err);
|
|
3282
|
+
return;
|
|
3283
|
+
}
|
|
3284
|
+
const backoff = WAKE_BACKOFF_MS[Math.min(state2.wakeFailures - 1, WAKE_BACKOFF_MS.length - 1)];
|
|
3285
|
+
state2.nextWakeAttemptAt = new Date(Date.now() + backoff).toISOString();
|
|
3286
|
+
this.saveState();
|
|
3287
|
+
slog3.warn(
|
|
3288
|
+
`failed to wake ${name} (attempt ${state2.wakeFailures}/${MAX_WAKE_ATTEMPTS}); retrying in ${Math.round(backoff / 6e4)}m`,
|
|
3289
|
+
logger_default.errorData(err)
|
|
3290
|
+
);
|
|
3291
|
+
}
|
|
3292
|
+
/** Clear wake-failure backoff after a successful wake. */
|
|
3293
|
+
resetWakeBackoff(name) {
|
|
3294
|
+
const state2 = this.states.get(name);
|
|
3295
|
+
if (!state2) return;
|
|
3296
|
+
if (state2.wakeFailures === 0 && state2.nextWakeAttemptAt === null) return;
|
|
3297
|
+
state2.wakeFailures = 0;
|
|
3298
|
+
state2.nextWakeAttemptAt = null;
|
|
3299
|
+
this.saveState();
|
|
3300
|
+
}
|
|
3301
|
+
/**
|
|
3302
|
+
* A mind has failed to wake too many times — it isn't asleep, it's broken.
|
|
3303
|
+
* Clear the sleep state (so the tick stops retrying) and surface the failure
|
|
3304
|
+
* loudly: error log, activity event for the web UI, and a mind notice so the
|
|
3305
|
+
* mind learns what happened on its next successful session. A manual
|
|
3306
|
+
* `volute clock wake` / `volute mind start` is the recovery path.
|
|
3307
|
+
*/
|
|
3308
|
+
async markWakeErrored(name, err) {
|
|
3309
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
3310
|
+
this.markAwake(name);
|
|
3311
|
+
slog3.error(
|
|
3312
|
+
`${name} failed to wake ${MAX_WAKE_ATTEMPTS} times in a row; giving up and marking errored`,
|
|
3313
|
+
logger_default.errorData(err)
|
|
3314
|
+
);
|
|
3315
|
+
try {
|
|
3316
|
+
await publish({
|
|
3317
|
+
type: "mind_stopped",
|
|
3318
|
+
mind: name,
|
|
3319
|
+
summary: `${name} failed to wake after ${MAX_WAKE_ATTEMPTS} attempts`,
|
|
3320
|
+
metadata: { error: "wake_failed", detail }
|
|
3321
|
+
});
|
|
3322
|
+
} catch (e) {
|
|
3323
|
+
slog3.error(`failed to publish wake-failure activity for ${name}`, logger_default.errorData(e));
|
|
3324
|
+
}
|
|
3325
|
+
await recordNotice({
|
|
3326
|
+
mind: name,
|
|
3327
|
+
session: MIND_LEVEL_SESSION,
|
|
3328
|
+
kind: "startup",
|
|
3329
|
+
reason: "startup_failed",
|
|
3330
|
+
detail: `Wake failed ${MAX_WAKE_ATTEMPTS} times in a row and was given up. Last error: ${detail}`
|
|
3331
|
+
});
|
|
3332
|
+
}
|
|
3212
3333
|
// --- Internal methods ---
|
|
3213
3334
|
markSleeping(name, opts) {
|
|
3214
3335
|
const sleepConfig = this.getSleepConfig(name);
|
|
@@ -3219,7 +3340,9 @@ var SleepManager = class {
|
|
|
3219
3340
|
wokenByTrigger: false,
|
|
3220
3341
|
voluntaryWakeAt: opts?.voluntaryWakeAt ?? null,
|
|
3221
3342
|
queuedMessageCount: this.states.get(name)?.queuedMessageCount ?? 0,
|
|
3222
|
-
triggerWakeHistory: []
|
|
3343
|
+
triggerWakeHistory: [],
|
|
3344
|
+
wakeFailures: 0,
|
|
3345
|
+
nextWakeAttemptAt: null
|
|
3223
3346
|
};
|
|
3224
3347
|
this.states.set(name, state2);
|
|
3225
3348
|
this.saveState();
|
|
@@ -3250,6 +3373,9 @@ var SleepManager = class {
|
|
|
3250
3373
|
const config = this.getSleepConfig(name);
|
|
3251
3374
|
if (!config?.enabled || !config.schedule) continue;
|
|
3252
3375
|
const state2 = this.states.get(name);
|
|
3376
|
+
if (state2?.sleeping && state2.nextWakeAttemptAt && now < new Date(state2.nextWakeAttemptAt)) {
|
|
3377
|
+
continue;
|
|
3378
|
+
}
|
|
3253
3379
|
if (state2?.sleeping && state2.voluntaryWakeAt) {
|
|
3254
3380
|
const wakeAt = new Date(state2.voluntaryWakeAt);
|
|
3255
3381
|
if (now >= wakeAt) {
|
|
@@ -3507,7 +3633,7 @@ function getSleepManagerIfReady() {
|
|
|
3507
3633
|
// packages/daemon/src/lib/delivery/delivery-manager.ts
|
|
3508
3634
|
import { readFile, realpath } from "fs/promises";
|
|
3509
3635
|
import { extname, resolve as resolve8 } from "path";
|
|
3510
|
-
import { and as and4, eq as eq5, inArray
|
|
3636
|
+
import { and as and4, eq as eq5, inArray, sql as sql2 } from "drizzle-orm";
|
|
3511
3637
|
|
|
3512
3638
|
// packages/daemon/src/lib/chat/typing.ts
|
|
3513
3639
|
var DEFAULT_TTL_MS = 1e4;
|
|
@@ -3904,7 +4030,7 @@ var DeliveryManager = class {
|
|
|
3904
4030
|
if (promote.length === 0) return;
|
|
3905
4031
|
try {
|
|
3906
4032
|
const db = await getDb();
|
|
3907
|
-
await db.update(deliveryQueue).set({ status: "pending", attempts: 0, next_attempt_at: null }).where(
|
|
4033
|
+
await db.update(deliveryQueue).set({ status: "pending", attempts: 0, next_attempt_at: null }).where(inArray(deliveryQueue.id, promote));
|
|
3908
4034
|
dlog.info(`released ${promote.length} gated message(s) for ${baseName} after route change`);
|
|
3909
4035
|
} catch (err) {
|
|
3910
4036
|
dlog.warn(`failed to promote gated rows for ${baseName}`, logger_default.errorData(err));
|
|
@@ -4069,7 +4195,7 @@ var DeliveryManager = class {
|
|
|
4069
4195
|
if (valid.length === 0) return;
|
|
4070
4196
|
try {
|
|
4071
4197
|
const db = await getDb();
|
|
4072
|
-
await db.delete(deliveryQueue).where(
|
|
4198
|
+
await db.delete(deliveryQueue).where(inArray(deliveryQueue.id, valid));
|
|
4073
4199
|
} catch (err) {
|
|
4074
4200
|
dlog.warn("failed to delete delivered delivery queue rows", logger_default.errorData(err));
|
|
4075
4201
|
}
|
|
@@ -4080,7 +4206,7 @@ var DeliveryManager = class {
|
|
|
4080
4206
|
if (valid.length === 0) return;
|
|
4081
4207
|
try {
|
|
4082
4208
|
const db = await getDb();
|
|
4083
|
-
const rows = await db.select({ id: deliveryQueue.id, attempts: deliveryQueue.attempts }).from(deliveryQueue).where(
|
|
4209
|
+
const rows = await db.select({ id: deliveryQueue.id, attempts: deliveryQueue.attempts }).from(deliveryQueue).where(inArray(deliveryQueue.id, valid));
|
|
4084
4210
|
for (const row of rows) {
|
|
4085
4211
|
const attempts = row.attempts + 1;
|
|
4086
4212
|
const backoffSec = Math.round(
|
|
@@ -4343,7 +4469,7 @@ var DeliveryManager = class {
|
|
|
4343
4469
|
`To start hearing this channel, add a routing rule for "${channel}" to .config/routes.json.`,
|
|
4344
4470
|
`Messages are held safely until you do \u2014 nothing is lost. If you'd rather not engage, just leave it unrouted.`
|
|
4345
4471
|
].filter((line) => line !== null).join("\n");
|
|
4346
|
-
const { sendSystemMessage: sendSystemMessage2 } = await import("./system-chat-
|
|
4472
|
+
const { sendSystemMessage: sendSystemMessage2 } = await import("./system-chat-XOALE2RD.js");
|
|
4347
4473
|
await sendSystemMessage2(mindName, notification);
|
|
4348
4474
|
}
|
|
4349
4475
|
/**
|
|
@@ -4517,6 +4643,9 @@ var DeliveryManager = class {
|
|
|
4517
4643
|
const buffer = this.batchBuffers.get(bufferKey);
|
|
4518
4644
|
if (buffer && buffer.messages.length > 0) {
|
|
4519
4645
|
this.scheduleBatchTimers(mind, session, bufferKey);
|
|
4646
|
+
} else if (session.startsWith("new-")) {
|
|
4647
|
+
mindSessions.delete(session);
|
|
4648
|
+
if (mindSessions.size === 0) this.sessionStates.delete(mind);
|
|
4520
4649
|
}
|
|
4521
4650
|
}
|
|
4522
4651
|
}
|
|
@@ -4632,8 +4761,8 @@ async function linkToolResultToTurn(mind, turnId, toolResultContent, toolUseEven
|
|
|
4632
4761
|
await db.update(activity).set({
|
|
4633
4762
|
turn_id: turnId,
|
|
4634
4763
|
...toolUseEventId != null ? { source_event_id: toolUseEventId } : {}
|
|
4635
|
-
}).where(
|
|
4636
|
-
const actRows = await db.select().from(activity).where(
|
|
4764
|
+
}).where(inArray2(activity.id, activityIds));
|
|
4765
|
+
const actRows = await db.select().from(activity).where(inArray2(activity.id, activityIds));
|
|
4637
4766
|
if (actRows.length > 0) {
|
|
4638
4767
|
await db.insert(mindHistory).values(
|
|
4639
4768
|
actRows.map((a) => ({
|
|
@@ -4657,40 +4786,44 @@ function resolveSleepAction(sleepBehavior, wokenByTrigger, wakeTriggerMatches) {
|
|
|
4657
4786
|
if (!sleepBehavior && wakeTriggerMatches) return "queue-and-wake";
|
|
4658
4787
|
return "queue";
|
|
4659
4788
|
}
|
|
4660
|
-
async function deliverMessage(mindName, payload) {
|
|
4789
|
+
async function deliverMessage(mindName, payload, opts = {}) {
|
|
4661
4790
|
try {
|
|
4662
4791
|
const baseName = await getBaseName(mindName);
|
|
4663
4792
|
const entry = await findMind(baseName);
|
|
4664
4793
|
if (!entry) {
|
|
4665
4794
|
dlog2.warn(`cannot deliver to ${mindName}: mind not found`);
|
|
4666
|
-
return;
|
|
4795
|
+
return false;
|
|
4667
4796
|
}
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
if (action === "skip") {
|
|
4679
|
-
dlog2.info(
|
|
4680
|
-
`skipped delivery to ${baseName} (sleeping, whileSleeping=skip, channel=${payload.channel})`
|
|
4797
|
+
if (!opts.isFlush) {
|
|
4798
|
+
const textContent = extractTextContent(payload.content);
|
|
4799
|
+
await recordInbound(baseName, payload.channel, payload.sender ?? null, textContent);
|
|
4800
|
+
const sleepManager = getSleepManagerIfReady();
|
|
4801
|
+
if (sleepManager?.isSleeping(baseName)) {
|
|
4802
|
+
const sleepState = sleepManager.getState(baseName);
|
|
4803
|
+
const action = resolveSleepAction(
|
|
4804
|
+
payload.whileSleeping,
|
|
4805
|
+
sleepState.wokenByTrigger,
|
|
4806
|
+
sleepManager.checkWakeTrigger(baseName, payload)
|
|
4681
4807
|
);
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4808
|
+
if (action === "skip") {
|
|
4809
|
+
dlog2.info(
|
|
4810
|
+
`skipped delivery to ${baseName} (sleeping, whileSleeping=skip, channel=${payload.channel})`
|
|
4811
|
+
);
|
|
4812
|
+
return true;
|
|
4813
|
+
}
|
|
4814
|
+
await sleepManager.queueSleepMessage(baseName, payload);
|
|
4815
|
+
if (action === "queue-and-wake") {
|
|
4816
|
+
sleepManager.initiateWake(baseName, { trigger: { channel: payload.channel } }).catch((err) => dlog2.warn(`failed to trigger-wake ${baseName}`, logger_default.errorData(err)));
|
|
4817
|
+
}
|
|
4818
|
+
return true;
|
|
4687
4819
|
}
|
|
4688
|
-
return;
|
|
4689
4820
|
}
|
|
4690
4821
|
const manager = getDeliveryManager();
|
|
4691
4822
|
await manager.routeAndDeliver(mindName, payload);
|
|
4823
|
+
return true;
|
|
4692
4824
|
} catch (err) {
|
|
4693
4825
|
dlog2.warn(`unexpected error delivering to ${mindName}`, logger_default.errorData(err));
|
|
4826
|
+
return false;
|
|
4694
4827
|
}
|
|
4695
4828
|
}
|
|
4696
4829
|
|
|
@@ -4700,6 +4833,12 @@ var dmCache = /* @__PURE__ */ new Map();
|
|
|
4700
4833
|
function resetSystemDMCache() {
|
|
4701
4834
|
dmCache.clear();
|
|
4702
4835
|
}
|
|
4836
|
+
function shouldGenerateSystemFallback(opts) {
|
|
4837
|
+
const { senderIsMind, hasMessage, convType, participants, replyTarget } = opts;
|
|
4838
|
+
if (!senderIsMind || !hasMessage) return false;
|
|
4839
|
+
if (isSpiritName(replyTarget)) return false;
|
|
4840
|
+
return convType === "dm" && participants.length === 2 && participants.some((p) => p.userType === "system");
|
|
4841
|
+
}
|
|
4703
4842
|
async function ensureSystemDM(mindName) {
|
|
4704
4843
|
const cached = dmCache.get(mindName);
|
|
4705
4844
|
if (cached) return { conversationId: cached };
|
|
@@ -4720,7 +4859,7 @@ async function ensureSystemDM(mindName) {
|
|
|
4720
4859
|
return { conversationId: conv.id };
|
|
4721
4860
|
}
|
|
4722
4861
|
async function sendSystemMessage(mindName, text, opts) {
|
|
4723
|
-
const isSpirit = mindName
|
|
4862
|
+
const isSpirit = isSpiritName(mindName);
|
|
4724
4863
|
let conversationId;
|
|
4725
4864
|
if (!isSpirit) {
|
|
4726
4865
|
const dm = await ensureSystemDM(mindName);
|
|
@@ -4745,27 +4884,20 @@ async function sendSystemMessageDirect(mindName, text) {
|
|
|
4745
4884
|
await recordInbound(mindName, "@volute", "volute", text);
|
|
4746
4885
|
return { conversationId };
|
|
4747
4886
|
}
|
|
4748
|
-
async function
|
|
4749
|
-
const spiritEntry = await findMind(
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
channel: `@${mindName}`,
|
|
4758
|
-
conversationId,
|
|
4759
|
-
sender: mindName,
|
|
4760
|
-
isDM: true,
|
|
4761
|
-
participants: ["volute", mindName],
|
|
4762
|
-
participantCount: 2
|
|
4763
|
-
});
|
|
4764
|
-
return;
|
|
4765
|
-
} catch (err) {
|
|
4766
|
-
slog4.warn(`failed to route to spirit, falling back to aiCompleteUtility`, logger_default.errorData(err));
|
|
4767
|
-
}
|
|
4887
|
+
async function spiritWillHandle() {
|
|
4888
|
+
const spiritEntry = await findMind(SPIRIT_NAME);
|
|
4889
|
+
if (spiritEntry?.running && spiritEntry.mindType === "spirit") return true;
|
|
4890
|
+
try {
|
|
4891
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
|
|
4892
|
+
const sm = getSleepManagerIfReady2();
|
|
4893
|
+
if (sm?.isSleeping(SPIRIT_NAME)) return true;
|
|
4894
|
+
} catch (err) {
|
|
4895
|
+
slog4.debug("could not check spirit sleep state", logger_default.errorData(err));
|
|
4768
4896
|
}
|
|
4897
|
+
return false;
|
|
4898
|
+
}
|
|
4899
|
+
async function generateSystemFallbackReply(conversationId, mindName, message) {
|
|
4900
|
+
if (await spiritWillHandle()) return;
|
|
4769
4901
|
const entry = await findMind(mindName);
|
|
4770
4902
|
const dir = mindDir(mindName);
|
|
4771
4903
|
const config = readVoluteConfig(dir);
|
|
@@ -4784,7 +4916,7 @@ async function generateSystemReply(conversationId, mindName, message) {
|
|
|
4784
4916
|
if (config.sleep.schedule?.wake) contextParts.push(`Wake cron: ${config.sleep.schedule.wake}`);
|
|
4785
4917
|
}
|
|
4786
4918
|
try {
|
|
4787
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4919
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
|
|
4788
4920
|
const sm = getSleepManagerIfReady2();
|
|
4789
4921
|
if (sm) {
|
|
4790
4922
|
const state2 = sm.getState(mindName);
|
|
@@ -4830,10 +4962,11 @@ async function generateSystemReply(conversationId, mindName, message) {
|
|
|
4830
4962
|
|
|
4831
4963
|
export {
|
|
4832
4964
|
resetSystemDMCache,
|
|
4965
|
+
shouldGenerateSystemFallback,
|
|
4833
4966
|
ensureSystemDM,
|
|
4834
4967
|
sendSystemMessage,
|
|
4835
4968
|
sendSystemMessageDirect,
|
|
4836
|
-
|
|
4969
|
+
generateSystemFallbackReply,
|
|
4837
4970
|
checkHealth,
|
|
4838
4971
|
RotatingLog,
|
|
4839
4972
|
syncProviderToMinds,
|