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.
Files changed (122) hide show
  1. package/README.md +112 -13
  2. package/dist/{accept-666DIZX2.js → accept-E3PAH3QJ.js} +2 -2
  3. package/dist/{activity-events-BBIEA2F4.js → activity-events-BKBPPUBP.js} +2 -2
  4. package/dist/ai-service-VAJT5UBS.js +29 -0
  5. package/dist/api.d.ts +351 -477
  6. package/dist/{archive-UA4BDFXQ.js → archive-WWDBWYN2.js} +2 -2
  7. package/dist/{bridge-FQHZL3MC.js → bridge-RO37CUFM.js} +2 -2
  8. package/dist/{chat-KTPOR2JT.js → chat-TCUNPFGO.js} +8 -8
  9. package/dist/{chunk-FLZGS4QH.js → chunk-2C2VXEBB.js} +2 -2
  10. package/dist/chunk-2NDZC3S7.js +1330 -0
  11. package/dist/{chunk-IKRVFPWU.js → chunk-7D47T4RB.js} +3 -2
  12. package/dist/{chunk-AW7PFDVN.js → chunk-CVH6Y2YG.js} +1 -1
  13. package/dist/{chunk-XBLSAVJF.js → chunk-DTC6EH5I.js} +1 -1
  14. package/dist/{chunk-THUUIU3E.js → chunk-EFP3PE6C.js} +5 -5
  15. package/dist/{chunk-JGFVMROS.js → chunk-EFVHR7KH.js} +1 -1
  16. package/dist/{chunk-CQ7SNKNI.js → chunk-FSM45XD5.js} +1 -1
  17. package/dist/{chunk-LAC664WU.js → chunk-FXHXHI2A.js} +42 -24
  18. package/dist/{chunk-RKQEHRBB.js → chunk-G3GBKZGG.js} +1 -1
  19. package/dist/{chunk-H7OZRFJB.js → chunk-HHTXM4JT.js} +0 -49
  20. package/dist/{chunk-J4IBNXGJ.js → chunk-IKHDUZRH.js} +4 -3
  21. package/dist/{chunk-MD4C26II.js → chunk-JGFRDMR6.js} +1 -1
  22. package/dist/{chunk-EHZKEMMV.js → chunk-LIRWLNAK.js} +24 -10
  23. package/dist/{chunk-NI5FFCCS.js → chunk-MDPCSXZ4.js} +35 -11
  24. package/dist/chunk-NSBFETWP.js +188 -0
  25. package/dist/{chunk-VIVMW2H2.js → chunk-P27RV5WM.js} +1 -1
  26. package/dist/{chunk-EHYDTZTF.js → chunk-P7VFDSSG.js} +2 -2
  27. package/dist/{chunk-CMILSHZD.js → chunk-QVAQ5454.js} +84 -300
  28. package/dist/{chunk-HDN7MNGD.js → chunk-S5LR3XYJ.js} +1 -1
  29. package/dist/{chunk-2YP2TVDT.js → chunk-UPA6COHU.js} +5 -5
  30. package/dist/{chunk-AKPFNL7L.js → chunk-VGWJSNHS.js} +1 -1
  31. package/dist/{chunk-DUAUMCEE.js → chunk-W5OOPLNP.js} +3 -3
  32. package/dist/{chunk-2WPW7OT6.js → chunk-ZWKTUQEL.js} +1 -1
  33. package/dist/cli.js +22 -26
  34. package/dist/{clock-DGCBVGYA.js → clock-G3ALCMLJ.js} +10 -6
  35. package/dist/{cloud-sync-KILFGV5Q.js → cloud-sync-JV4LJOK3.js} +13 -12
  36. package/dist/{conversations-P5BL7RMX.js → conversations-7KVQV7EZ.js} +3 -3
  37. package/dist/{create-DFCAGEE5.js → create-JTLS7GX3.js} +2 -2
  38. package/dist/{create-QWV73WXD.js → create-VQSQHJQW.js} +1 -1
  39. package/dist/{daemon-client-I42FK2BF.js → daemon-client-BCTFGVCZ.js} +2 -2
  40. package/dist/{daemon-restart-UHOMICXT.js → daemon-restart-4JGBHEJ4.js} +7 -7
  41. package/dist/daemon.js +1257 -1022
  42. package/dist/{db-IC4J52XQ.js → db-HMFPIRO2.js} +1 -1
  43. package/dist/{delete-4JYGD4VN.js → delete-JESHKE7F.js} +1 -1
  44. package/dist/down-NGBMGORS.js +14 -0
  45. package/dist/{env-YJMUMFIY.js → env-CLXXT7M2.js} +2 -2
  46. package/dist/{export-BOJQWBMA.js → export-EGA5M5PB.js} +3 -3
  47. package/dist/extension-WZ4SUPJB.js +174 -0
  48. package/dist/extensions-ECO4RPFQ.js +27 -0
  49. package/dist/{files-M546TKVN.js → files-4VEJDASH.js} +3 -3
  50. package/dist/{history-ALPTNB3I.js → history-EJMMLXDO.js} +17 -2
  51. package/dist/{import-SRTQXBGH.js → import-YCGPMBSI.js} +3 -3
  52. package/dist/{join-J4QU42DL.js → join-2GBJKZEN.js} +1 -1
  53. package/dist/{list-R73GENNL.js → list-Q6O7FGAN.js} +2 -2
  54. package/dist/{login-3QZNR2DF.js → login-RET5WESK.js} +2 -2
  55. package/dist/{login-BKP3AFWN.js → login-RL6AU2SM.js} +3 -3
  56. package/dist/{logout-T53VKCPU.js → logout-CGAGJN3L.js} +2 -2
  57. package/dist/{logout-IQK7FNEK.js → logout-JRPBEMMR.js} +3 -3
  58. package/dist/message-delivery-6YMVNOEC.js +28 -0
  59. package/dist/{migrate-registry-to-db-XC7T5B7P.js → migrate-registry-to-db-FK35IPEH.js} +1 -1
  60. package/dist/{mind-S5V6CK5W.js → mind-LUWRQUQ5.js} +17 -17
  61. package/dist/{mind-activity-tracker-WRHFI3YW.js → mind-activity-tracker-VYN2ZZ2M.js} +3 -3
  62. package/dist/{mind-list-UPJ75GPI.js → mind-list-V5WW5DUA.js} +2 -2
  63. package/dist/{mind-manager-P66HQDNE.js → mind-manager-YFCOIAAX.js} +6 -6
  64. package/dist/{mind-sleep-BTSWQNAC.js → mind-sleep-R6PTNNW4.js} +2 -2
  65. package/dist/{mind-status-TK5AETEM.js → mind-status-I4ISFJ6I.js} +2 -2
  66. package/dist/{mind-wake-SBAKIDVP.js → mind-wake-67ZQEWAV.js} +2 -2
  67. package/dist/{package-OFKXNKJF.js → package-S2OAA5ZA.js} +11 -5
  68. package/dist/{pages-watcher-P7QECRE2.js → pages-watcher-Z3PKNROC.js} +3 -3
  69. package/dist/{read-36UFXN3G.js → read-WQMPTSN2.js} +2 -2
  70. package/dist/{register-CHREOMJ3.js → register-NZDSTLP3.js} +3 -3
  71. package/dist/{registry-NDNOOYG4.js → registry-ODSALQQL.js} +1 -1
  72. package/dist/{reject-LXIZFJ4Q.js → reject-2HZOJEIJ.js} +2 -2
  73. package/dist/{restart-6ESL3NBO.js → restart-QHS3NT64.js} +2 -2
  74. package/dist/{sandbox-5BW5HPXM.js → sandbox-O5FUSF43.js} +3 -3
  75. package/dist/{seed-SSUCYYDF.js → seed-WUQMPLDM.js} +1 -1
  76. package/dist/{send-TAOEZ4NH.js → send-OAN3RYYY.js} +20 -6
  77. package/dist/{setup-JHL5ZEST.js → setup-QMDK5RZX.js} +2 -2
  78. package/dist/{setup-RXYVGGT7.js → setup-XJH3E7YM.js} +45 -14
  79. package/dist/{skill-AUAQTSP5.js → skill-FZIN4W4Q.js} +65 -3
  80. package/dist/skills/volute-mind/SKILL.md +10 -19
  81. package/dist/sleep-manager-O7YQFCV5.js +30 -0
  82. package/dist/{split-TKJ5OT3P.js → split-EXYGGGQN.js} +1 -1
  83. package/dist/{sprout-UNT7LKKE.js → sprout-AXQ6H5DB.js} +8 -7
  84. package/dist/{start-EUJSS5R4.js → start-MTOVL6SY.js} +2 -2
  85. package/dist/{status-NQJYR4BG.js → status-ZRO37MWR.js} +5 -5
  86. package/dist/{stop-3XAITBBF.js → stop-OK5WEPVC.js} +2 -2
  87. package/dist/{systems-SMEFSHTA.js → systems-W3BBMSOZ.js} +5 -5
  88. package/dist/{tailscale-NY5MUMY3.js → tailscale-BM72RXCJ.js} +1 -1
  89. package/dist/{template-hash-BIMA4ILT.js → template-hash-3HOR4UAJ.js} +1 -1
  90. package/dist/up-BXUAIDXB.js +17 -0
  91. package/dist/{update-PTSH22AZ.js → update-PLPHMMZ2.js} +5 -5
  92. package/dist/{update-check-64FWC4Y2.js → update-check-CVCN7MF6.js} +2 -2
  93. package/dist/{upgrade-HA47CS4C.js → upgrade-I6NPCYUU.js} +1 -1
  94. package/dist/{version-notify-WDHRO3XD.js → version-notify-2NTWVEHL.js} +15 -14
  95. package/dist/web-assets/assets/index--kREqKl9.js +72 -0
  96. package/dist/web-assets/assets/index-BXYTG0nJ.css +1 -0
  97. package/dist/web-assets/ext-theme.css +111 -0
  98. package/dist/web-assets/index.html +2 -2
  99. package/package.json +11 -5
  100. package/packages/extensions/notes/dist/ui/assets/index-DgawVO5g.css +1 -0
  101. package/packages/extensions/notes/dist/ui/assets/index-qUWoeC4c.js +2 -0
  102. package/packages/extensions/notes/dist/ui/index.html +14 -0
  103. package/packages/extensions/notes/skills/notes/SKILL.md +62 -0
  104. package/packages/extensions/notes/skills/notes/scripts/notes.mjs +185 -0
  105. package/packages/extensions/pages/dist/ui/assets/index-D0HyS-xQ.css +1 -0
  106. package/packages/extensions/pages/dist/ui/assets/index-tLTROSk5.js +2 -0
  107. package/packages/extensions/pages/dist/ui/index.html +14 -0
  108. package/packages/extensions/pages/skills/pages/SKILL.md +58 -0
  109. package/templates/_base/home/VOLUTE.md +1 -1
  110. package/dist/chunk-P72MVS4R.js +0 -188
  111. package/dist/chunk-ZYGKG6VC.js +0 -22
  112. package/dist/down-LVBXEULC.js +0 -14
  113. package/dist/message-delivery-Q7VUMIEI.js +0 -27
  114. package/dist/notes-XCER3I7M.js +0 -220
  115. package/dist/pages-EUJR52AH.js +0 -36
  116. package/dist/publish-ZZB33WP4.js +0 -86
  117. package/dist/skills/notes/SKILL.md +0 -34
  118. package/dist/sleep-manager-G4B5GW5P.js +0 -29
  119. package/dist/status-S7UUPNRW.js +0 -38
  120. package/dist/up-W6VAK2XE.js +0 -17
  121. package/dist/web-assets/assets/index-BmKDnWDB.css +0 -1
  122. 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
- startWatcher,
4
- stopWatcher
5
- } from "./chunk-THUUIU3E.js";
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-FLZGS4QH.js";
19
+ } from "./chunk-2C2VXEBB.js";
14
20
  import {
15
- markIdle
16
- } from "./chunk-CQ7SNKNI.js";
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-VIVMW2H2.js";
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-AW7PFDVN.js";
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
- voluteUserHome
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 existsSync5,
54
- mkdirSync as mkdirSync5,
53
+ existsSync as existsSync4,
54
+ mkdirSync as mkdirSync4,
55
55
  readdirSync,
56
- readFileSync as readFileSync6,
56
+ readFileSync as readFileSync5,
57
57
  readlinkSync,
58
- renameSync as renameSync2,
59
- writeFileSync as writeFileSync5
58
+ renameSync,
59
+ writeFileSync as writeFileSync4
60
60
  } from "fs";
61
- import { resolve as resolve8 } from "path";
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 and3, eq as eq3, inArray as inArray2 } from "drizzle-orm";
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) + "\n");
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 as and2, eq as eq2, sql } from "drizzle-orm";
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(eq2(deliveryQueue.status, "pending"));
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(eq2(deliveryQueue.id, row.id));
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(and2(eq2(deliveryQueue.mind, mindName), eq2(deliveryQueue.status, "gated")));
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
- and2(
871
- eq2(deliveryQueue.mind, baseName),
872
- eq2(deliveryQueue.session, session),
873
- eq2(deliveryQueue.status, "pending")
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 count2 = await db.select({ count: sql`count(*)` }).from(deliveryQueue).where(
1000
- and2(
1001
- eq2(deliveryQueue.mind, baseName),
1002
- eq2(deliveryQueue.channel, payload.channel),
1003
- eq2(deliveryQueue.status, "gated")
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 ((count2[0]?.count ?? 0) <= 1) {
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 resolve6 } from "path";
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 resolve6(voluteSystemDir(), "scheduler-state.json");
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 = resolve6(mindDir(mindName), "home");
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 existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
1782
- import { resolve as resolve7 } from "path";
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 resolve7(stateDir(mind), "budget.json");
1703
+ return resolve6(stateDir(mind), "budget.json");
1901
1704
  }
1902
1705
  saveBudgetState(mind, state) {
1903
1706
  try {
1904
1707
  const dir = stateDir(mind);
1905
- mkdirSync4(dir, { recursive: true });
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
- writeFileSync4(this.budgetStatePath(mind), `${JSON.stringify(data)}
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 (!existsSync4(path)) return null;
1922
- const data = JSON.parse(readFileSync5(path, "utf-8"));
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
- startWatcher(baseName);
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
- stopWatcher(baseName);
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 resolve8(voluteSystemDir(), "sleep-state.json");
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 (existsSync5(this.statePath)) {
2103
- const data = JSON.parse(readFileSync6(this.statePath, "utf-8"));
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
- writeFileSync5(this.statePath, `${JSON.stringify(data, null, 2)}
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(and3(eq3(deliveryQueue.mind, name), eq3(deliveryQueue.status, "sleep-queued"))).all();
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-Q7VUMIEI.js");
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(inArray2(deliveryQueue.id, delivered));
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((resolve9) => {
2253
+ return new Promise((resolve8) => {
2451
2254
  const timeout = setTimeout(() => {
2452
2255
  unsub();
2453
- resolve9();
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
- resolve9();
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 = resolve8(dir, ".mind", "sessions");
2469
- if (existsSync5(sessionsDir)) {
2470
- const archiveDir = resolve8(sessionsDir, "archive");
2471
- mkdirSync5(archiveDir, { recursive: true });
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 = resolve8(sessionsDir, file);
2277
+ const src = resolve7(sessionsDir, file);
2475
2278
  const base = file.replace(/\.json$/, "");
2476
- const dest = resolve8(archiveDir, `${base}-${timestamp}.json`);
2279
+ const dest = resolve7(archiveDir, `${base}-${timestamp}.json`);
2477
2280
  try {
2478
- renameSync2(src, dest);
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 = resolve8(dir, ".mind", "pi-sessions");
2485
- if (existsSync5(piSessionsDir)) {
2486
- const archiveDir = resolve8(piSessionsDir, "archive");
2487
- mkdirSync5(archiveDir, { recursive: true });
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 = resolve8(piSessionsDir, entry.name);
2491
- const dest = resolve8(archiveDir, `${entry.name}-${timestamp}`);
2293
+ const src = resolve7(piSessionsDir, entry.name);
2294
+ const dest = resolve7(archiveDir, `${entry.name}-${timestamp}`);
2492
2295
  try {
2493
- renameSync2(src, dest);
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 = resolve8(mindDir(name), "home", ".config", "hooks", "wake-context.sh");
2502
- if (!existsSync5(scriptPath)) return "";
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(and3(eq3(deliveryQueue.mind, name), eq3(deliveryQueue.status, "sleep-queued"))).all();
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, count2]) => `${count2} on ${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 = readFileSync6("/proc/net/tcp6", "utf-8");
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
  };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  voluteSystemDir
4
- } from "./chunk-H7OZRFJB.js";
4
+ } from "./chunk-HHTXM4JT.js";
5
5
 
6
6
  // src/lib/update-check.ts
7
7
  import { existsSync, readFileSync, writeFileSync } from "fs";