volute 0.29.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -13
- package/dist/{accept-666DIZX2.js → accept-E3PAH3QJ.js} +2 -2
- package/dist/{activity-events-BBIEA2F4.js → activity-events-BKBPPUBP.js} +2 -2
- package/dist/ai-service-VAJT5UBS.js +29 -0
- package/dist/api.d.ts +351 -477
- package/dist/{archive-UA4BDFXQ.js → archive-WWDBWYN2.js} +2 -2
- package/dist/{bridge-FQHZL3MC.js → bridge-RO37CUFM.js} +2 -2
- package/dist/{chat-KTPOR2JT.js → chat-TCUNPFGO.js} +8 -8
- package/dist/{chunk-FLZGS4QH.js → chunk-2C2VXEBB.js} +2 -2
- package/dist/chunk-2NDZC3S7.js +1330 -0
- package/dist/{chunk-IKRVFPWU.js → chunk-7D47T4RB.js} +3 -2
- package/dist/{chunk-AW7PFDVN.js → chunk-CVH6Y2YG.js} +1 -1
- package/dist/{chunk-XBLSAVJF.js → chunk-DTC6EH5I.js} +1 -1
- package/dist/{chunk-THUUIU3E.js → chunk-EFP3PE6C.js} +5 -5
- package/dist/{chunk-JGFVMROS.js → chunk-EFVHR7KH.js} +1 -1
- package/dist/{chunk-CQ7SNKNI.js → chunk-FSM45XD5.js} +1 -1
- package/dist/{chunk-LAC664WU.js → chunk-FXHXHI2A.js} +42 -24
- package/dist/{chunk-RKQEHRBB.js → chunk-G3GBKZGG.js} +1 -1
- package/dist/{chunk-H7OZRFJB.js → chunk-HHTXM4JT.js} +0 -49
- package/dist/{chunk-J4IBNXGJ.js → chunk-IKHDUZRH.js} +4 -3
- package/dist/{chunk-MD4C26II.js → chunk-JGFRDMR6.js} +1 -1
- package/dist/{chunk-EHZKEMMV.js → chunk-LIRWLNAK.js} +24 -10
- package/dist/{chunk-NI5FFCCS.js → chunk-MDPCSXZ4.js} +35 -11
- package/dist/chunk-NSBFETWP.js +188 -0
- package/dist/{chunk-VIVMW2H2.js → chunk-P27RV5WM.js} +1 -1
- package/dist/{chunk-EHYDTZTF.js → chunk-P7VFDSSG.js} +2 -2
- package/dist/{chunk-CMILSHZD.js → chunk-QVAQ5454.js} +84 -300
- package/dist/{chunk-HDN7MNGD.js → chunk-S5LR3XYJ.js} +1 -1
- package/dist/{chunk-2YP2TVDT.js → chunk-UPA6COHU.js} +5 -5
- package/dist/{chunk-AKPFNL7L.js → chunk-VGWJSNHS.js} +1 -1
- package/dist/{chunk-DUAUMCEE.js → chunk-W5OOPLNP.js} +3 -3
- package/dist/{chunk-2WPW7OT6.js → chunk-ZWKTUQEL.js} +1 -1
- package/dist/cli.js +22 -26
- package/dist/{clock-DGCBVGYA.js → clock-G3ALCMLJ.js} +10 -6
- package/dist/{cloud-sync-KILFGV5Q.js → cloud-sync-JV4LJOK3.js} +13 -12
- package/dist/{conversations-P5BL7RMX.js → conversations-7KVQV7EZ.js} +3 -3
- package/dist/{create-DFCAGEE5.js → create-JTLS7GX3.js} +2 -2
- package/dist/{create-QWV73WXD.js → create-VQSQHJQW.js} +1 -1
- package/dist/{daemon-client-I42FK2BF.js → daemon-client-BCTFGVCZ.js} +2 -2
- package/dist/{daemon-restart-UHOMICXT.js → daemon-restart-4JGBHEJ4.js} +7 -7
- package/dist/daemon.js +1257 -1022
- package/dist/{db-IC4J52XQ.js → db-HMFPIRO2.js} +1 -1
- package/dist/{delete-4JYGD4VN.js → delete-JESHKE7F.js} +1 -1
- package/dist/down-NGBMGORS.js +14 -0
- package/dist/{env-YJMUMFIY.js → env-CLXXT7M2.js} +2 -2
- package/dist/{export-BOJQWBMA.js → export-EGA5M5PB.js} +3 -3
- package/dist/extension-WZ4SUPJB.js +174 -0
- package/dist/extensions-ECO4RPFQ.js +27 -0
- package/dist/{files-M546TKVN.js → files-4VEJDASH.js} +3 -3
- package/dist/{history-ALPTNB3I.js → history-EJMMLXDO.js} +17 -2
- package/dist/{import-SRTQXBGH.js → import-YCGPMBSI.js} +3 -3
- package/dist/{join-J4QU42DL.js → join-2GBJKZEN.js} +1 -1
- package/dist/{list-R73GENNL.js → list-Q6O7FGAN.js} +2 -2
- package/dist/{login-3QZNR2DF.js → login-RET5WESK.js} +2 -2
- package/dist/{login-BKP3AFWN.js → login-RL6AU2SM.js} +3 -3
- package/dist/{logout-T53VKCPU.js → logout-CGAGJN3L.js} +2 -2
- package/dist/{logout-IQK7FNEK.js → logout-JRPBEMMR.js} +3 -3
- package/dist/message-delivery-6YMVNOEC.js +28 -0
- package/dist/{migrate-registry-to-db-XC7T5B7P.js → migrate-registry-to-db-FK35IPEH.js} +1 -1
- package/dist/{mind-S5V6CK5W.js → mind-LUWRQUQ5.js} +17 -17
- package/dist/{mind-activity-tracker-WRHFI3YW.js → mind-activity-tracker-VYN2ZZ2M.js} +3 -3
- package/dist/{mind-list-UPJ75GPI.js → mind-list-V5WW5DUA.js} +2 -2
- package/dist/{mind-manager-P66HQDNE.js → mind-manager-YFCOIAAX.js} +6 -6
- package/dist/{mind-sleep-BTSWQNAC.js → mind-sleep-R6PTNNW4.js} +2 -2
- package/dist/{mind-status-TK5AETEM.js → mind-status-I4ISFJ6I.js} +2 -2
- package/dist/{mind-wake-SBAKIDVP.js → mind-wake-67ZQEWAV.js} +2 -2
- package/dist/{package-OFKXNKJF.js → package-S2OAA5ZA.js} +11 -5
- package/dist/{pages-watcher-P7QECRE2.js → pages-watcher-Z3PKNROC.js} +3 -3
- package/dist/{read-36UFXN3G.js → read-WQMPTSN2.js} +2 -2
- package/dist/{register-CHREOMJ3.js → register-NZDSTLP3.js} +3 -3
- package/dist/{registry-NDNOOYG4.js → registry-ODSALQQL.js} +1 -1
- package/dist/{reject-LXIZFJ4Q.js → reject-2HZOJEIJ.js} +2 -2
- package/dist/{restart-6ESL3NBO.js → restart-QHS3NT64.js} +2 -2
- package/dist/{sandbox-5BW5HPXM.js → sandbox-O5FUSF43.js} +3 -3
- package/dist/{seed-SSUCYYDF.js → seed-WUQMPLDM.js} +1 -1
- package/dist/{send-TAOEZ4NH.js → send-OAN3RYYY.js} +20 -6
- package/dist/{setup-JHL5ZEST.js → setup-QMDK5RZX.js} +2 -2
- package/dist/{setup-RXYVGGT7.js → setup-XJH3E7YM.js} +45 -14
- package/dist/{skill-AUAQTSP5.js → skill-FZIN4W4Q.js} +65 -3
- package/dist/skills/volute-mind/SKILL.md +10 -19
- package/dist/sleep-manager-O7YQFCV5.js +30 -0
- package/dist/{split-TKJ5OT3P.js → split-EXYGGGQN.js} +1 -1
- package/dist/{sprout-UNT7LKKE.js → sprout-AXQ6H5DB.js} +8 -7
- package/dist/{start-EUJSS5R4.js → start-MTOVL6SY.js} +2 -2
- package/dist/{status-NQJYR4BG.js → status-ZRO37MWR.js} +5 -5
- package/dist/{stop-3XAITBBF.js → stop-OK5WEPVC.js} +2 -2
- package/dist/{systems-SMEFSHTA.js → systems-W3BBMSOZ.js} +5 -5
- package/dist/{tailscale-NY5MUMY3.js → tailscale-BM72RXCJ.js} +1 -1
- package/dist/{template-hash-BIMA4ILT.js → template-hash-3HOR4UAJ.js} +1 -1
- package/dist/up-BXUAIDXB.js +17 -0
- package/dist/{update-PTSH22AZ.js → update-PLPHMMZ2.js} +5 -5
- package/dist/{update-check-64FWC4Y2.js → update-check-CVCN7MF6.js} +2 -2
- package/dist/{upgrade-HA47CS4C.js → upgrade-I6NPCYUU.js} +1 -1
- package/dist/{version-notify-WDHRO3XD.js → version-notify-2NTWVEHL.js} +15 -14
- package/dist/web-assets/assets/index--kREqKl9.js +72 -0
- package/dist/web-assets/assets/index-BXYTG0nJ.css +1 -0
- package/dist/web-assets/ext-theme.css +111 -0
- package/dist/web-assets/index.html +2 -2
- package/package.json +11 -5
- package/packages/extensions/notes/dist/ui/assets/index-DgawVO5g.css +1 -0
- package/packages/extensions/notes/dist/ui/assets/index-qUWoeC4c.js +2 -0
- package/packages/extensions/notes/dist/ui/index.html +14 -0
- package/packages/extensions/notes/skills/notes/SKILL.md +62 -0
- package/packages/extensions/notes/skills/notes/scripts/notes.mjs +185 -0
- package/packages/extensions/pages/dist/ui/assets/index-D0HyS-xQ.css +1 -0
- package/packages/extensions/pages/dist/ui/assets/index-tLTROSk5.js +2 -0
- package/packages/extensions/pages/dist/ui/index.html +14 -0
- package/packages/extensions/pages/skills/pages/SKILL.md +58 -0
- package/templates/_base/home/VOLUTE.md +1 -1
- package/dist/chunk-P72MVS4R.js +0 -188
- package/dist/chunk-ZYGKG6VC.js +0 -22
- package/dist/down-LVBXEULC.js +0 -14
- package/dist/message-delivery-Q7VUMIEI.js +0 -27
- package/dist/notes-XCER3I7M.js +0 -220
- package/dist/pages-EUJR52AH.js +0 -36
- package/dist/publish-ZZB33WP4.js +0 -86
- package/dist/skills/notes/SKILL.md +0 -34
- package/dist/sleep-manager-G4B5GW5P.js +0 -29
- package/dist/status-S7UUPNRW.js +0 -38
- package/dist/up-W6VAK2XE.js +0 -17
- package/dist/web-assets/assets/index-BmKDnWDB.css +0 -1
- package/dist/web-assets/assets/index-CLJMx-GA.js +0 -71
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
markIdle
|
|
4
|
+
} from "./chunk-FSM45XD5.js";
|
|
5
|
+
import {
|
|
6
|
+
clearJsonMap,
|
|
7
|
+
getMindManager,
|
|
8
|
+
getPrompt,
|
|
9
|
+
loadJsonMap,
|
|
10
|
+
saveJsonMap
|
|
11
|
+
} from "./chunk-LIRWLNAK.js";
|
|
6
12
|
import {
|
|
7
13
|
addMessage,
|
|
8
14
|
createChannel,
|
|
@@ -10,28 +16,24 @@ import {
|
|
|
10
16
|
getParticipants,
|
|
11
17
|
joinChannel,
|
|
12
18
|
publish as publish2
|
|
13
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-2C2VXEBB.js";
|
|
14
20
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
getOrCreateMindUser,
|
|
22
|
+
notifyExtensionsMindStart,
|
|
23
|
+
notifyExtensionsMindStop,
|
|
24
|
+
readSystemsConfig,
|
|
25
|
+
syncMindProfile
|
|
26
|
+
} from "./chunk-2NDZC3S7.js";
|
|
17
27
|
import {
|
|
18
|
-
broadcast,
|
|
19
28
|
publish,
|
|
20
29
|
subscribe
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import {
|
|
23
|
-
clearJsonMap,
|
|
24
|
-
getMindManager,
|
|
25
|
-
getPrompt,
|
|
26
|
-
loadJsonMap,
|
|
27
|
-
saveJsonMap
|
|
28
|
-
} from "./chunk-EHZKEMMV.js";
|
|
30
|
+
} from "./chunk-P27RV5WM.js";
|
|
29
31
|
import {
|
|
30
32
|
logger_default
|
|
31
33
|
} from "./chunk-YUIHSKR6.js";
|
|
32
34
|
import {
|
|
33
35
|
exec
|
|
34
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-CVH6Y2YG.js";
|
|
35
37
|
import {
|
|
36
38
|
deliveryQueue,
|
|
37
39
|
findMind,
|
|
@@ -41,27 +43,25 @@ import {
|
|
|
41
43
|
mindHistory,
|
|
42
44
|
readRegistry,
|
|
43
45
|
stateDir,
|
|
44
|
-
users,
|
|
45
46
|
voluteHome,
|
|
46
|
-
voluteSystemDir
|
|
47
|
-
|
|
48
|
-
} from "./chunk-H7OZRFJB.js";
|
|
47
|
+
voluteSystemDir
|
|
48
|
+
} from "./chunk-HHTXM4JT.js";
|
|
49
49
|
|
|
50
50
|
// src/lib/daemon/sleep-manager.ts
|
|
51
51
|
import { execFile, spawn as spawnChild } from "child_process";
|
|
52
52
|
import {
|
|
53
|
-
existsSync as
|
|
54
|
-
mkdirSync as
|
|
53
|
+
existsSync as existsSync4,
|
|
54
|
+
mkdirSync as mkdirSync4,
|
|
55
55
|
readdirSync,
|
|
56
|
-
readFileSync as
|
|
56
|
+
readFileSync as readFileSync5,
|
|
57
57
|
readlinkSync,
|
|
58
|
-
renameSync
|
|
59
|
-
writeFileSync as
|
|
58
|
+
renameSync,
|
|
59
|
+
writeFileSync as writeFileSync4
|
|
60
60
|
} from "fs";
|
|
61
|
-
import { resolve as
|
|
61
|
+
import { resolve as resolve7 } from "path";
|
|
62
62
|
import { promisify } from "util";
|
|
63
63
|
import { CronExpressionParser as CronExpressionParser2 } from "cron-parser";
|
|
64
|
-
import { and as
|
|
64
|
+
import { and as and2, eq as eq2, inArray } from "drizzle-orm";
|
|
65
65
|
|
|
66
66
|
// src/lib/volute-config.ts
|
|
67
67
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -99,136 +99,6 @@ function writeVoluteConfig(mindDir2, config) {
|
|
|
99
99
|
`);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
// src/lib/auth.ts
|
|
103
|
-
import { compareSync, hashSync } from "bcryptjs";
|
|
104
|
-
import { and, count, eq, inArray } from "drizzle-orm";
|
|
105
|
-
var userSelectFields = {
|
|
106
|
-
id: users.id,
|
|
107
|
-
username: users.username,
|
|
108
|
-
role: users.role,
|
|
109
|
-
user_type: users.user_type,
|
|
110
|
-
display_name: users.display_name,
|
|
111
|
-
description: users.description,
|
|
112
|
-
avatar: users.avatar,
|
|
113
|
-
created_at: users.created_at
|
|
114
|
-
};
|
|
115
|
-
async function createUser(username, password) {
|
|
116
|
-
const db = await getDb();
|
|
117
|
-
const hash = hashSync(password, 10);
|
|
118
|
-
const [{ value }] = await db.select({ value: count() }).from(users).where(eq(users.user_type, "brain"));
|
|
119
|
-
const role = value === 0 ? "admin" : "pending";
|
|
120
|
-
const [result] = await db.insert(users).values({ username, password_hash: hash, role }).returning(userSelectFields);
|
|
121
|
-
return result;
|
|
122
|
-
}
|
|
123
|
-
async function verifyUser(username, password) {
|
|
124
|
-
const db = await getDb();
|
|
125
|
-
const row = await db.select().from(users).where(eq(users.username, username)).get();
|
|
126
|
-
if (!row) return null;
|
|
127
|
-
if (row.user_type === "mind") return null;
|
|
128
|
-
if (!compareSync(password, row.password_hash)) return null;
|
|
129
|
-
const { password_hash: _, ...user } = row;
|
|
130
|
-
return user;
|
|
131
|
-
}
|
|
132
|
-
async function getUser(id) {
|
|
133
|
-
const db = await getDb();
|
|
134
|
-
const row = await db.select(userSelectFields).from(users).where(eq(users.id, id)).get();
|
|
135
|
-
return row ?? null;
|
|
136
|
-
}
|
|
137
|
-
async function getUserByUsername(username) {
|
|
138
|
-
const db = await getDb();
|
|
139
|
-
const row = await db.select(userSelectFields).from(users).where(eq(users.username, username)).get();
|
|
140
|
-
return row ?? null;
|
|
141
|
-
}
|
|
142
|
-
async function listUsers() {
|
|
143
|
-
const db = await getDb();
|
|
144
|
-
return db.select(userSelectFields).from(users).orderBy(users.created_at).all();
|
|
145
|
-
}
|
|
146
|
-
async function listPendingUsers() {
|
|
147
|
-
const db = await getDb();
|
|
148
|
-
return db.select(userSelectFields).from(users).where(eq(users.role, "pending")).orderBy(users.created_at).all();
|
|
149
|
-
}
|
|
150
|
-
async function listUsersByType(userType) {
|
|
151
|
-
const db = await getDb();
|
|
152
|
-
return db.select(userSelectFields).from(users).where(eq(users.user_type, userType)).orderBy(users.created_at).all();
|
|
153
|
-
}
|
|
154
|
-
async function getOrCreateMindUser(mindName) {
|
|
155
|
-
const db = await getDb();
|
|
156
|
-
const existing = await db.select(userSelectFields).from(users).where(and(eq(users.username, mindName), eq(users.user_type, "mind"))).get();
|
|
157
|
-
if (existing) return existing;
|
|
158
|
-
try {
|
|
159
|
-
const [result] = await db.insert(users).values({
|
|
160
|
-
username: mindName,
|
|
161
|
-
password_hash: "!mind",
|
|
162
|
-
role: "user",
|
|
163
|
-
user_type: "mind"
|
|
164
|
-
}).returning(userSelectFields);
|
|
165
|
-
return result;
|
|
166
|
-
} catch (err) {
|
|
167
|
-
if (err instanceof Error && err.message.includes("UNIQUE constraint")) {
|
|
168
|
-
const retried = await db.select(userSelectFields).from(users).where(and(eq(users.username, mindName), eq(users.user_type, "mind"))).get();
|
|
169
|
-
if (retried) return retried;
|
|
170
|
-
}
|
|
171
|
-
throw err;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
async function deleteMindUser(mindName) {
|
|
175
|
-
const db = await getDb();
|
|
176
|
-
await db.delete(users).where(and(eq(users.username, mindName), eq(users.user_type, "mind")));
|
|
177
|
-
}
|
|
178
|
-
async function changePassword(userId, currentPassword, newPassword) {
|
|
179
|
-
const db = await getDb();
|
|
180
|
-
const row = await db.select().from(users).where(eq(users.id, userId)).get();
|
|
181
|
-
if (!row) return false;
|
|
182
|
-
if (!compareSync(currentPassword, row.password_hash)) return false;
|
|
183
|
-
const hash = hashSync(newPassword, 10);
|
|
184
|
-
await db.update(users).set({ password_hash: hash }).where(eq(users.id, userId));
|
|
185
|
-
return true;
|
|
186
|
-
}
|
|
187
|
-
async function approveUser(id) {
|
|
188
|
-
const db = await getDb();
|
|
189
|
-
await db.update(users).set({ role: "user" }).where(and(eq(users.id, id), eq(users.role, "pending")));
|
|
190
|
-
}
|
|
191
|
-
async function countAdmins() {
|
|
192
|
-
const db = await getDb();
|
|
193
|
-
const [{ value }] = await db.select({ value: count() }).from(users).where(eq(users.role, "admin"));
|
|
194
|
-
return value;
|
|
195
|
-
}
|
|
196
|
-
async function setUserRole(id, role) {
|
|
197
|
-
const db = await getDb();
|
|
198
|
-
const target = await db.select({ id: users.id }).from(users).where(eq(users.id, id)).get();
|
|
199
|
-
if (!target) throw new Error("User not found");
|
|
200
|
-
await db.update(users).set({ role }).where(eq(users.id, id));
|
|
201
|
-
}
|
|
202
|
-
async function deleteUser(id) {
|
|
203
|
-
const db = await getDb();
|
|
204
|
-
const target = await db.select({ id: users.id }).from(users).where(and(eq(users.id, id), eq(users.user_type, "brain"))).get();
|
|
205
|
-
if (!target) throw new Error("User not found");
|
|
206
|
-
await db.delete(users).where(and(eq(users.id, id), eq(users.user_type, "brain")));
|
|
207
|
-
}
|
|
208
|
-
async function updateUserProfile(userId, profile) {
|
|
209
|
-
const db = await getDb();
|
|
210
|
-
const target = await db.select({ id: users.id }).from(users).where(eq(users.id, userId)).get();
|
|
211
|
-
if (!target) throw new Error("User not found");
|
|
212
|
-
await db.update(users).set(profile).where(eq(users.id, userId));
|
|
213
|
-
}
|
|
214
|
-
async function syncMindProfile(mindName, config) {
|
|
215
|
-
const user = await getOrCreateMindUser(mindName);
|
|
216
|
-
const newProfile = {
|
|
217
|
-
display_name: config.displayName ?? null,
|
|
218
|
-
description: config.description ?? null,
|
|
219
|
-
avatar: config.avatar ?? null
|
|
220
|
-
};
|
|
221
|
-
const changed = user.display_name !== newProfile.display_name || user.description !== newProfile.description || user.avatar !== newProfile.avatar;
|
|
222
|
-
if (!changed) return;
|
|
223
|
-
const db = await getDb();
|
|
224
|
-
await db.update(users).set(newProfile).where(eq(users.id, user.id));
|
|
225
|
-
broadcast({ type: "profile_updated", mind: mindName, summary: `${mindName} profile updated` });
|
|
226
|
-
}
|
|
227
|
-
async function migrateMindRoles() {
|
|
228
|
-
const db = await getDb();
|
|
229
|
-
await db.update(users).set({ role: "user" }).where(and(eq(users.user_type, "mind"), inArray(users.role, ["mind", "agent"])));
|
|
230
|
-
}
|
|
231
|
-
|
|
232
102
|
// src/connectors/sdk.ts
|
|
233
103
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
234
104
|
import { join, resolve as resolve2 } from "path";
|
|
@@ -259,7 +129,8 @@ function writeChannelEntry(mindName, slug, entry) {
|
|
|
259
129
|
const filePath = join(dir, "channels.json");
|
|
260
130
|
const map = readChannelMap(mindName);
|
|
261
131
|
map[slug] = entry;
|
|
262
|
-
writeFileSync2(filePath, JSON.stringify(map, null, 2)
|
|
132
|
+
writeFileSync2(filePath, `${JSON.stringify(map, null, 2)}
|
|
133
|
+
`);
|
|
263
134
|
}
|
|
264
135
|
function resolveChannelId(mindName, slug) {
|
|
265
136
|
const map = readChannelMap(mindName);
|
|
@@ -301,7 +172,7 @@ function publish3(mind, event) {
|
|
|
301
172
|
// src/lib/delivery/delivery-manager.ts
|
|
302
173
|
import { readFile, realpath } from "fs/promises";
|
|
303
174
|
import { extname, resolve as resolve4 } from "path";
|
|
304
|
-
import { and
|
|
175
|
+
import { and, eq, sql } from "drizzle-orm";
|
|
305
176
|
|
|
306
177
|
// src/lib/typing.ts
|
|
307
178
|
var DEFAULT_TTL_MS = 1e4;
|
|
@@ -667,7 +538,7 @@ var DeliveryManager = class {
|
|
|
667
538
|
async restoreFromDb() {
|
|
668
539
|
try {
|
|
669
540
|
const db = await getDb();
|
|
670
|
-
const rows = await db.select().from(deliveryQueue).where(
|
|
541
|
+
const rows = await db.select().from(deliveryQueue).where(eq(deliveryQueue.status, "pending"));
|
|
671
542
|
for (const row of rows) {
|
|
672
543
|
let payload;
|
|
673
544
|
try {
|
|
@@ -685,7 +556,7 @@ var DeliveryManager = class {
|
|
|
685
556
|
this.addToBatchBuffer(row.mind, row.session, payload, sessionConfig);
|
|
686
557
|
} else {
|
|
687
558
|
try {
|
|
688
|
-
await db.delete(deliveryQueue).where(
|
|
559
|
+
await db.delete(deliveryQueue).where(eq(deliveryQueue.id, row.id));
|
|
689
560
|
} catch (err) {
|
|
690
561
|
dlog2.warn(`failed to delete queue row ${row.id} for ${row.mind}`, logger_default.errorData(err));
|
|
691
562
|
}
|
|
@@ -706,7 +577,7 @@ var DeliveryManager = class {
|
|
|
706
577
|
*/
|
|
707
578
|
async getPending(mindName) {
|
|
708
579
|
const db = await getDb();
|
|
709
|
-
const rows = await db.select().from(deliveryQueue).where(
|
|
580
|
+
const rows = await db.select().from(deliveryQueue).where(and(eq(deliveryQueue.mind, mindName), eq(deliveryQueue.status, "gated")));
|
|
710
581
|
const byChannel = /* @__PURE__ */ new Map();
|
|
711
582
|
for (const row of rows) {
|
|
712
583
|
const ch = row.channel ?? "unknown";
|
|
@@ -867,10 +738,10 @@ var DeliveryManager = class {
|
|
|
867
738
|
try {
|
|
868
739
|
const db = await getDb();
|
|
869
740
|
await db.delete(deliveryQueue).where(
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
741
|
+
and(
|
|
742
|
+
eq(deliveryQueue.mind, baseName),
|
|
743
|
+
eq(deliveryQueue.session, session),
|
|
744
|
+
eq(deliveryQueue.status, "pending")
|
|
874
745
|
)
|
|
875
746
|
);
|
|
876
747
|
} catch (err) {
|
|
@@ -996,14 +867,14 @@ var DeliveryManager = class {
|
|
|
996
867
|
await this.persistToQueue(baseName, session, payload, "gated");
|
|
997
868
|
try {
|
|
998
869
|
const db = await getDb();
|
|
999
|
-
const
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
870
|
+
const count = await db.select({ count: sql`count(*)` }).from(deliveryQueue).where(
|
|
871
|
+
and(
|
|
872
|
+
eq(deliveryQueue.mind, baseName),
|
|
873
|
+
eq(deliveryQueue.channel, payload.channel),
|
|
874
|
+
eq(deliveryQueue.status, "gated")
|
|
1004
875
|
)
|
|
1005
876
|
);
|
|
1006
|
-
if ((
|
|
877
|
+
if ((count[0]?.count ?? 0) <= 1) {
|
|
1007
878
|
await this.sendInviteNotification(mindName, payload);
|
|
1008
879
|
}
|
|
1009
880
|
} catch (err) {
|
|
@@ -1306,74 +1177,6 @@ async function announceToSystem(text) {
|
|
|
1306
1177
|
}
|
|
1307
1178
|
}
|
|
1308
1179
|
|
|
1309
|
-
// src/lib/systems-config.ts
|
|
1310
|
-
import {
|
|
1311
|
-
existsSync as existsSync3,
|
|
1312
|
-
mkdirSync as mkdirSync3,
|
|
1313
|
-
readFileSync as readFileSync4,
|
|
1314
|
-
renameSync,
|
|
1315
|
-
unlinkSync,
|
|
1316
|
-
writeFileSync as writeFileSync3
|
|
1317
|
-
} from "fs";
|
|
1318
|
-
import { resolve as resolve5 } from "path";
|
|
1319
|
-
var DEFAULT_API_URL = "https://volute.systems";
|
|
1320
|
-
function configPath2() {
|
|
1321
|
-
return resolve5(voluteSystemDir(), "systems.json");
|
|
1322
|
-
}
|
|
1323
|
-
function migrateIfNeeded() {
|
|
1324
|
-
const target = configPath2();
|
|
1325
|
-
if (existsSync3(target)) return;
|
|
1326
|
-
const oldPaths = [
|
|
1327
|
-
resolve5(voluteUserHome(), "systems.json"),
|
|
1328
|
-
resolve5(voluteHome(), "systems.json")
|
|
1329
|
-
];
|
|
1330
|
-
for (const old of oldPaths) {
|
|
1331
|
-
if (old !== target && existsSync3(old)) {
|
|
1332
|
-
try {
|
|
1333
|
-
mkdirSync3(voluteSystemDir(), { recursive: true });
|
|
1334
|
-
renameSync(old, target);
|
|
1335
|
-
} catch {
|
|
1336
|
-
}
|
|
1337
|
-
return;
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
}
|
|
1341
|
-
function readSystemsConfig() {
|
|
1342
|
-
migrateIfNeeded();
|
|
1343
|
-
const path = configPath2();
|
|
1344
|
-
if (!existsSync3(path)) return null;
|
|
1345
|
-
const raw = readFileSync4(path, "utf-8");
|
|
1346
|
-
let data;
|
|
1347
|
-
try {
|
|
1348
|
-
data = JSON.parse(raw);
|
|
1349
|
-
} catch {
|
|
1350
|
-
console.error(
|
|
1351
|
-
`Warning: ${path} contains invalid JSON. Run "volute systems logout" and re-login.`
|
|
1352
|
-
);
|
|
1353
|
-
return null;
|
|
1354
|
-
}
|
|
1355
|
-
if (!data.apiKey || !data.system) return null;
|
|
1356
|
-
return {
|
|
1357
|
-
apiKey: data.apiKey,
|
|
1358
|
-
system: data.system,
|
|
1359
|
-
apiUrl: data.apiUrl || DEFAULT_API_URL
|
|
1360
|
-
};
|
|
1361
|
-
}
|
|
1362
|
-
function writeSystemsConfig(config) {
|
|
1363
|
-
mkdirSync3(voluteSystemDir(), { recursive: true });
|
|
1364
|
-
writeFileSync3(configPath2(), `${JSON.stringify(config, null, 2)}
|
|
1365
|
-
`, { mode: 384 });
|
|
1366
|
-
}
|
|
1367
|
-
function deleteSystemsConfig() {
|
|
1368
|
-
try {
|
|
1369
|
-
unlinkSync(configPath2());
|
|
1370
|
-
return true;
|
|
1371
|
-
} catch (err) {
|
|
1372
|
-
if (err.code === "ENOENT") return false;
|
|
1373
|
-
throw err;
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
1180
|
// src/lib/daemon/mail-poller.ts
|
|
1378
1181
|
var mlog = logger_default.child("mail");
|
|
1379
1182
|
function formatEmailContent(email) {
|
|
@@ -1608,7 +1411,7 @@ async function ensureMailAddress(mindName) {
|
|
|
1608
1411
|
}
|
|
1609
1412
|
|
|
1610
1413
|
// src/lib/daemon/scheduler.ts
|
|
1611
|
-
import { resolve as
|
|
1414
|
+
import { resolve as resolve5 } from "path";
|
|
1612
1415
|
import { CronExpressionParser } from "cron-parser";
|
|
1613
1416
|
var slog = logger_default.child("scheduler");
|
|
1614
1417
|
var Scheduler = class {
|
|
@@ -1617,7 +1420,7 @@ var Scheduler = class {
|
|
|
1617
1420
|
lastFired = /* @__PURE__ */ new Map();
|
|
1618
1421
|
// "mind:scheduleId" → epoch minute
|
|
1619
1422
|
get statePath() {
|
|
1620
|
-
return
|
|
1423
|
+
return resolve5(voluteSystemDir(), "scheduler-state.json");
|
|
1621
1424
|
}
|
|
1622
1425
|
start() {
|
|
1623
1426
|
this.loadState();
|
|
@@ -1699,7 +1502,7 @@ var Scheduler = class {
|
|
|
1699
1502
|
try {
|
|
1700
1503
|
let text;
|
|
1701
1504
|
if (schedule.script) {
|
|
1702
|
-
const homeDir =
|
|
1505
|
+
const homeDir = resolve5(mindDir(mindName), "home");
|
|
1703
1506
|
try {
|
|
1704
1507
|
const output = await this.runScript(schedule.script, homeDir, mindName);
|
|
1705
1508
|
if (!output.trim()) {
|
|
@@ -1778,8 +1581,8 @@ function getScheduler() {
|
|
|
1778
1581
|
}
|
|
1779
1582
|
|
|
1780
1583
|
// src/lib/daemon/token-budget.ts
|
|
1781
|
-
import { existsSync as
|
|
1782
|
-
import { resolve as
|
|
1584
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
1585
|
+
import { resolve as resolve6 } from "path";
|
|
1783
1586
|
var tlog = logger_default.child("token-budget");
|
|
1784
1587
|
var DEFAULT_BUDGET_PERIOD_MINUTES = 60;
|
|
1785
1588
|
var MAX_QUEUE_SIZE = 100;
|
|
@@ -1897,19 +1700,19 @@ var TokenBudget = class {
|
|
|
1897
1700
|
this.dirty.clear();
|
|
1898
1701
|
}
|
|
1899
1702
|
budgetStatePath(mind) {
|
|
1900
|
-
return
|
|
1703
|
+
return resolve6(stateDir(mind), "budget.json");
|
|
1901
1704
|
}
|
|
1902
1705
|
saveBudgetState(mind, state) {
|
|
1903
1706
|
try {
|
|
1904
1707
|
const dir = stateDir(mind);
|
|
1905
|
-
|
|
1708
|
+
mkdirSync3(dir, { recursive: true });
|
|
1906
1709
|
const data = {
|
|
1907
1710
|
periodStart: state.periodStart,
|
|
1908
1711
|
tokensUsed: state.tokensUsed,
|
|
1909
1712
|
warningInjected: state.warningInjected,
|
|
1910
1713
|
queue: state.queue
|
|
1911
1714
|
};
|
|
1912
|
-
|
|
1715
|
+
writeFileSync3(this.budgetStatePath(mind), `${JSON.stringify(data)}
|
|
1913
1716
|
`);
|
|
1914
1717
|
} catch (err) {
|
|
1915
1718
|
tlog.warn(`failed to save budget state for ${mind}`, logger_default.errorData(err));
|
|
@@ -1918,8 +1721,8 @@ var TokenBudget = class {
|
|
|
1918
1721
|
loadBudgetState(mind) {
|
|
1919
1722
|
try {
|
|
1920
1723
|
const path = this.budgetStatePath(mind);
|
|
1921
|
-
if (!
|
|
1922
|
-
const data = JSON.parse(
|
|
1724
|
+
if (!existsSync3(path)) return null;
|
|
1725
|
+
const data = JSON.parse(readFileSync4(path, "utf-8"));
|
|
1923
1726
|
if (typeof data.periodStart !== "number" || typeof data.tokensUsed !== "number") return null;
|
|
1924
1727
|
return {
|
|
1925
1728
|
periodStart: data.periodStart,
|
|
@@ -2008,7 +1811,7 @@ async function startMindFull(name) {
|
|
|
2008
1811
|
config.tokenBudgetPeriodMinutes ?? DEFAULT_BUDGET_PERIOD_MINUTES
|
|
2009
1812
|
);
|
|
2010
1813
|
}
|
|
2011
|
-
|
|
1814
|
+
notifyExtensionsMindStart(baseName);
|
|
2012
1815
|
}
|
|
2013
1816
|
async function sleepMind(name) {
|
|
2014
1817
|
markIdle(name);
|
|
@@ -2031,7 +1834,7 @@ async function stopMindFull(name) {
|
|
|
2031
1834
|
const baseName = await getBaseName(name);
|
|
2032
1835
|
const isBase = baseName === name;
|
|
2033
1836
|
if (isBase) {
|
|
2034
|
-
|
|
1837
|
+
notifyExtensionsMindStop(baseName);
|
|
2035
1838
|
markIdle(baseName);
|
|
2036
1839
|
getScheduler().unloadSchedules(baseName);
|
|
2037
1840
|
getTokenBudget().removeBudget(baseName);
|
|
@@ -2083,7 +1886,7 @@ var SleepManager = class {
|
|
|
2083
1886
|
transitioning = /* @__PURE__ */ new Set();
|
|
2084
1887
|
sleepConfigs = /* @__PURE__ */ new Map();
|
|
2085
1888
|
get statePath() {
|
|
2086
|
-
return
|
|
1889
|
+
return resolve7(voluteSystemDir(), "sleep-state.json");
|
|
2087
1890
|
}
|
|
2088
1891
|
start() {
|
|
2089
1892
|
this.loadState();
|
|
@@ -2099,8 +1902,8 @@ var SleepManager = class {
|
|
|
2099
1902
|
// --- State persistence ---
|
|
2100
1903
|
loadState() {
|
|
2101
1904
|
try {
|
|
2102
|
-
if (
|
|
2103
|
-
const data = JSON.parse(
|
|
1905
|
+
if (existsSync4(this.statePath)) {
|
|
1906
|
+
const data = JSON.parse(readFileSync5(this.statePath, "utf-8"));
|
|
2104
1907
|
for (const [name, state] of Object.entries(data)) {
|
|
2105
1908
|
state.triggerWakeHistory ??= [];
|
|
2106
1909
|
this.states.set(name, state);
|
|
@@ -2116,7 +1919,7 @@ var SleepManager = class {
|
|
|
2116
1919
|
if (state.sleeping) data[name] = state;
|
|
2117
1920
|
}
|
|
2118
1921
|
try {
|
|
2119
|
-
|
|
1922
|
+
writeFileSync4(this.statePath, `${JSON.stringify(data, null, 2)}
|
|
2120
1923
|
`);
|
|
2121
1924
|
} catch (err) {
|
|
2122
1925
|
slog2.error("failed to save sleep state", logger_default.errorData(err));
|
|
@@ -2345,9 +2148,9 @@ var SleepManager = class {
|
|
|
2345
2148
|
async flushQueuedMessages(name) {
|
|
2346
2149
|
try {
|
|
2347
2150
|
const db = await getDb();
|
|
2348
|
-
const rows = await db.select().from(deliveryQueue).where(
|
|
2151
|
+
const rows = await db.select().from(deliveryQueue).where(and2(eq2(deliveryQueue.mind, name), eq2(deliveryQueue.status, "sleep-queued"))).all();
|
|
2349
2152
|
if (rows.length === 0) return 0;
|
|
2350
|
-
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-
|
|
2153
|
+
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-6YMVNOEC.js");
|
|
2351
2154
|
const delivered = [];
|
|
2352
2155
|
for (const row of rows) {
|
|
2353
2156
|
try {
|
|
@@ -2358,7 +2161,7 @@ var SleepManager = class {
|
|
|
2358
2161
|
}
|
|
2359
2162
|
}
|
|
2360
2163
|
if (delivered.length > 0) {
|
|
2361
|
-
await db.delete(deliveryQueue).where(
|
|
2164
|
+
await db.delete(deliveryQueue).where(inArray(deliveryQueue.id, delivered));
|
|
2362
2165
|
}
|
|
2363
2166
|
const state = this.states.get(name);
|
|
2364
2167
|
if (state) {
|
|
@@ -2447,17 +2250,17 @@ var SleepManager = class {
|
|
|
2447
2250
|
}
|
|
2448
2251
|
}
|
|
2449
2252
|
async waitForIdle(name, timeoutMs) {
|
|
2450
|
-
return new Promise((
|
|
2253
|
+
return new Promise((resolve8) => {
|
|
2451
2254
|
const timeout = setTimeout(() => {
|
|
2452
2255
|
unsub();
|
|
2453
|
-
|
|
2256
|
+
resolve8();
|
|
2454
2257
|
}, timeoutMs);
|
|
2455
2258
|
const unsub = subscribe((event) => {
|
|
2456
2259
|
if (event.mind !== name) return;
|
|
2457
2260
|
if (event.type === "mind_done" || event.type === "mind_idle") {
|
|
2458
2261
|
clearTimeout(timeout);
|
|
2459
2262
|
unsub();
|
|
2460
|
-
|
|
2263
|
+
resolve8();
|
|
2461
2264
|
}
|
|
2462
2265
|
});
|
|
2463
2266
|
});
|
|
@@ -2465,32 +2268,32 @@ var SleepManager = class {
|
|
|
2465
2268
|
async archiveSessions(name) {
|
|
2466
2269
|
const dir = mindDir(name);
|
|
2467
2270
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 16);
|
|
2468
|
-
const sessionsDir =
|
|
2469
|
-
if (
|
|
2470
|
-
const archiveDir =
|
|
2471
|
-
|
|
2271
|
+
const sessionsDir = resolve7(dir, ".mind", "sessions");
|
|
2272
|
+
if (existsSync4(sessionsDir)) {
|
|
2273
|
+
const archiveDir = resolve7(sessionsDir, "archive");
|
|
2274
|
+
mkdirSync4(archiveDir, { recursive: true });
|
|
2472
2275
|
for (const file of readdirSync(sessionsDir)) {
|
|
2473
2276
|
if (file === "archive" || !file.endsWith(".json")) continue;
|
|
2474
|
-
const src =
|
|
2277
|
+
const src = resolve7(sessionsDir, file);
|
|
2475
2278
|
const base = file.replace(/\.json$/, "");
|
|
2476
|
-
const dest =
|
|
2279
|
+
const dest = resolve7(archiveDir, `${base}-${timestamp}.json`);
|
|
2477
2280
|
try {
|
|
2478
|
-
|
|
2281
|
+
renameSync(src, dest);
|
|
2479
2282
|
} catch (err) {
|
|
2480
2283
|
slog2.warn(`failed to archive session ${file} for ${name}`, logger_default.errorData(err));
|
|
2481
2284
|
}
|
|
2482
2285
|
}
|
|
2483
2286
|
}
|
|
2484
|
-
const piSessionsDir =
|
|
2485
|
-
if (
|
|
2486
|
-
const archiveDir =
|
|
2487
|
-
|
|
2287
|
+
const piSessionsDir = resolve7(dir, ".mind", "pi-sessions");
|
|
2288
|
+
if (existsSync4(piSessionsDir)) {
|
|
2289
|
+
const archiveDir = resolve7(piSessionsDir, "archive");
|
|
2290
|
+
mkdirSync4(archiveDir, { recursive: true });
|
|
2488
2291
|
for (const entry of readdirSync(piSessionsDir, { withFileTypes: true })) {
|
|
2489
2292
|
if (entry.name === "archive" || !entry.isDirectory()) continue;
|
|
2490
|
-
const src =
|
|
2491
|
-
const dest =
|
|
2293
|
+
const src = resolve7(piSessionsDir, entry.name);
|
|
2294
|
+
const dest = resolve7(archiveDir, `${entry.name}-${timestamp}`);
|
|
2492
2295
|
try {
|
|
2493
|
-
|
|
2296
|
+
renameSync(src, dest);
|
|
2494
2297
|
} catch (err) {
|
|
2495
2298
|
slog2.warn(`failed to archive pi-session ${entry.name} for ${name}`, logger_default.errorData(err));
|
|
2496
2299
|
}
|
|
@@ -2498,8 +2301,8 @@ var SleepManager = class {
|
|
|
2498
2301
|
}
|
|
2499
2302
|
}
|
|
2500
2303
|
async runWakeContextScript(name, sleepingSince, duration) {
|
|
2501
|
-
const scriptPath =
|
|
2502
|
-
if (!
|
|
2304
|
+
const scriptPath = resolve7(mindDir(name), "home", ".config", "hooks", "wake-context.sh");
|
|
2305
|
+
if (!existsSync4(scriptPath)) return "";
|
|
2503
2306
|
const input = JSON.stringify({
|
|
2504
2307
|
sleepingSince,
|
|
2505
2308
|
duration,
|
|
@@ -2549,7 +2352,7 @@ var SleepManager = class {
|
|
|
2549
2352
|
async buildQueuedSummary(name) {
|
|
2550
2353
|
try {
|
|
2551
2354
|
const db = await getDb();
|
|
2552
|
-
const rows = await db.select({ channel: deliveryQueue.channel, sender: deliveryQueue.sender }).from(deliveryQueue).where(
|
|
2355
|
+
const rows = await db.select({ channel: deliveryQueue.channel, sender: deliveryQueue.sender }).from(deliveryQueue).where(and2(eq2(deliveryQueue.mind, name), eq2(deliveryQueue.status, "sleep-queued"))).all();
|
|
2553
2356
|
if (rows.length === 0) return "No messages arrived while you slept.";
|
|
2554
2357
|
const channelCounts = /* @__PURE__ */ new Map();
|
|
2555
2358
|
const senders = /* @__PURE__ */ new Set();
|
|
@@ -2558,7 +2361,7 @@ var SleepManager = class {
|
|
|
2558
2361
|
channelCounts.set(ch, (channelCounts.get(ch) ?? 0) + 1);
|
|
2559
2362
|
if (row.sender) senders.add(row.sender);
|
|
2560
2363
|
}
|
|
2561
|
-
const parts = [...channelCounts.entries()].map(([ch,
|
|
2364
|
+
const parts = [...channelCounts.entries()].map(([ch, count]) => `${count} on ${ch}`);
|
|
2562
2365
|
const senderNote = senders.size > 0 ? ` from ${[...senders].join(", ")}` : "";
|
|
2563
2366
|
return `${rows.length} message${rows.length === 1 ? "" : "s"} arrived while you slept${senderNote} (${parts.join(", ")}). They'll be delivered to your normal channels now.`;
|
|
2564
2367
|
} catch (err) {
|
|
@@ -2596,7 +2399,7 @@ var SleepManager = class {
|
|
|
2596
2399
|
} catch {
|
|
2597
2400
|
try {
|
|
2598
2401
|
const portHex = port.toString(16).toUpperCase().padStart(4, "0");
|
|
2599
|
-
const tcp6 =
|
|
2402
|
+
const tcp6 = readFileSync5("/proc/net/tcp6", "utf-8");
|
|
2600
2403
|
for (const line of tcp6.split("\n")) {
|
|
2601
2404
|
if (!line.includes(`:${portHex} `)) continue;
|
|
2602
2405
|
const fields = line.trim().split(/\s+/);
|
|
@@ -2663,22 +2466,6 @@ function getSleepManagerIfReady() {
|
|
|
2663
2466
|
}
|
|
2664
2467
|
|
|
2665
2468
|
export {
|
|
2666
|
-
createUser,
|
|
2667
|
-
verifyUser,
|
|
2668
|
-
getUser,
|
|
2669
|
-
getUserByUsername,
|
|
2670
|
-
listUsers,
|
|
2671
|
-
listPendingUsers,
|
|
2672
|
-
listUsersByType,
|
|
2673
|
-
getOrCreateMindUser,
|
|
2674
|
-
deleteMindUser,
|
|
2675
|
-
changePassword,
|
|
2676
|
-
approveUser,
|
|
2677
|
-
countAdmins,
|
|
2678
|
-
setUserRole,
|
|
2679
|
-
deleteUser,
|
|
2680
|
-
updateUserProfile,
|
|
2681
|
-
migrateMindRoles,
|
|
2682
2469
|
readVoluteConfig,
|
|
2683
2470
|
writeVoluteConfig,
|
|
2684
2471
|
splitMessage,
|
|
@@ -2708,8 +2495,5 @@ export {
|
|
|
2708
2495
|
recordInbound,
|
|
2709
2496
|
resolveSleepAction,
|
|
2710
2497
|
deliverMessage,
|
|
2711
|
-
readSystemsConfig,
|
|
2712
|
-
writeSystemsConfig,
|
|
2713
|
-
deleteSystemsConfig,
|
|
2714
2498
|
initMailPoller
|
|
2715
2499
|
};
|