volute 0.31.0 → 0.33.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 (195) hide show
  1. package/README.md +31 -22
  2. package/dist/{accept-GAKQ3MEH.js → accept-D5VBM7JW.js} +5 -4
  3. package/dist/{activity-events-T5ZRCVAL.js → activity-events-XJO3P4RR.js} +3 -2
  4. package/dist/{ai-service-UWUPM4T6.js → ai-service-SBY2WG7O.js} +18 -5
  5. package/dist/api.d.ts +703 -1068
  6. package/dist/{archive-YBNSJYZZ.js → archive-INXYFVCW.js} +3 -2
  7. package/dist/{auth-T5AW2USD.js → auth-GKCDSO4T.js} +4 -3
  8. package/dist/{bridge-4AJ3EY26.js → bridge-TXWWPPOJ.js} +5 -4
  9. package/dist/{chat-7YLT7FI3.js → chat-U5ZOME3O.js} +8 -8
  10. package/dist/{chunk-NV3TYNWX.js → chunk-2NGTS5UU.js} +1 -1
  11. package/dist/{chunk-BWKIHH7B.js → chunk-3Z2DPESO.js} +662 -508
  12. package/dist/chunk-6LXAAQ43.js +22 -0
  13. package/dist/chunk-7J3HEVR7.js +220 -0
  14. package/dist/{chunk-NOWVQ7AL.js → chunk-A2A4KLFE.js} +351 -301
  15. package/dist/{chunk-LX6T3GKQ.js → chunk-ALEF47VT.js} +1 -1
  16. package/dist/{chunk-S2TZLSDH.js → chunk-C7I35G4R.js} +163 -15
  17. package/dist/{chunk-VGWJSNHS.js → chunk-G53F3JA4.js} +1 -35
  18. package/dist/{chunk-A6TUJJ3L.js → chunk-G6BSYHPK.js} +2 -2
  19. package/dist/{chunk-DAXJKPHZ.js → chunk-GY5HBI7A.js} +2 -2
  20. package/dist/{chunk-BC3P3QCK.js → chunk-I5KY25PQ.js} +1 -9
  21. package/dist/{chunk-BNC43CSY.js → chunk-JUKK7FPS.js} +2 -2
  22. package/dist/{chunk-R5QJBZZG.js → chunk-JYVGHWEJ.js} +21 -11
  23. package/dist/chunk-KIEPMIM5.js +59 -0
  24. package/dist/{chunk-EKDWA7E4.js → chunk-KVK2DLWI.js} +5 -2
  25. package/dist/{chunk-AAO77TZX.js → chunk-LOEJ4HPQ.js} +1 -1
  26. package/dist/chunk-LRCG2JLP.js +251 -0
  27. package/dist/{chunk-EMPFLFTG.js → chunk-M7UL5S3Q.js} +1 -1
  28. package/dist/{chunk-6QIUN46C.js → chunk-N432I7QH.js} +20 -3
  29. package/dist/{chunk-SNVPRRT7.js → chunk-NNB4WIG7.js} +2 -2
  30. package/dist/{chunk-HDKY4TWU.js → chunk-NPKSDYA2.js} +3 -3
  31. package/dist/chunk-OYAKCAVY.js +29 -0
  32. package/dist/chunk-PB65JZK2.js +85 -0
  33. package/dist/chunk-PVY5W6QN.js +41 -0
  34. package/dist/{chunk-PNQCXLSV.js → chunk-QTUVYI7W.js} +58 -1
  35. package/dist/{chunk-X62AXPR7.js → chunk-RPZZSXV3.js} +8 -196
  36. package/dist/{chunk-WRS3B556.js → chunk-RSX4OPZY.js} +5 -5
  37. package/dist/{chunk-FAHDKPEH.js → chunk-RVGLDGMI.js} +5 -3
  38. package/dist/chunk-SKLSMHXO.js +208 -0
  39. package/dist/{chunk-4OUOFS23.js → chunk-UKVWJRKN.js} +1 -1
  40. package/dist/{chunk-57OKQMP3.js → chunk-VH33ZWMW.js} +5 -55
  41. package/dist/cli.js +49 -23
  42. package/dist/{clock-LJCG426D.js → clock-BVH3V6E3.js} +7 -6
  43. package/dist/{cloud-sync-O3LXIRN6.js → cloud-sync-4NWLMFVH.js} +20 -14
  44. package/dist/config-H2H4UIF7.js +72 -0
  45. package/dist/connectors/discord-bridge.js +1 -1
  46. package/dist/connectors/slack-bridge.js +1 -1
  47. package/dist/connectors/telegram-bridge.js +1 -1
  48. package/dist/{conversations-RKKGP5IA.js → conversations-AWI5SZW2.js} +4 -3
  49. package/dist/{create-TL623TFC.js → create-2FK7Z46Y.js} +6 -2
  50. package/dist/{create-WUTIIRI2.js → create-YWD2TIP4.js} +6 -5
  51. package/dist/{daemon-client-CVGM25DM.js → daemon-client-6QXHZ7US.js} +3 -2
  52. package/dist/{daemon-restart-EZP7XH3V.js → daemon-restart-GOBUKLX7.js} +8 -6
  53. package/dist/daemon.js +1918 -1472
  54. package/dist/{db-SW5PL6QA.js → db-F34YLV7D.js} +2 -1
  55. package/dist/db-RA45JBFG.js +16 -0
  56. package/dist/{delete-Z6HAG35F.js → delete-QTGWEDBI.js} +1 -1
  57. package/dist/delivery-manager-PFAKEJTC.js +32 -0
  58. package/dist/delivery-router-FL45JL7N.js +21 -0
  59. package/dist/down-FWWTEKXM.js +15 -0
  60. package/dist/{env-NHESNNSP.js → env-JCOF2222.js} +5 -4
  61. package/dist/{export-EVMP7GWY.js → export-SUYRLI5Q.js} +4 -3
  62. package/dist/{extension-LR7EW3JF.js → extension-OBTGKQQD.js} +5 -3
  63. package/dist/{extensions-NGEJI7JH.js → extensions-KYNTVTMO.js} +10 -7
  64. package/dist/{files-3SM7V33S.js → files-65PMW5IK.js} +6 -5
  65. package/dist/{history-PQD3LXEP.js → history-DKCDI3JO.js} +9 -4
  66. package/dist/{import-PR2OCGQJ.js → import-DDUFE7AY.js} +4 -3
  67. package/dist/isolation-LLAYQYDY.js +22 -0
  68. package/dist/{join-R4EN5CWQ.js → join-I5QEE3LG.js} +1 -1
  69. package/dist/{list-B4XNUOFO.js → list-JQ463EDA.js} +5 -4
  70. package/dist/{login-62JVY6A2.js → login-D7ETSU4R.js} +5 -4
  71. package/dist/{login-URWP6S2N.js → login-RIJF2F4G.js} +3 -2
  72. package/dist/{logout-NXJQJDLI.js → logout-5MLHZALK.js} +3 -2
  73. package/dist/{logout-ZK2N62T3.js → logout-UZJRGY4Z.js} +3 -2
  74. package/dist/message-delivery-DFF5SJRM.js +42 -0
  75. package/dist/{mind-E2ZV2WRX.js → mind-IOJFLEM5.js} +25 -19
  76. package/dist/{mind-activity-tracker-ASNZBMLC.js → mind-activity-tracker-F6O4Q2SL.js} +4 -3
  77. package/dist/{mind-list-BEI7E5WY.js → mind-list-WUPMQDYQ.js} +3 -2
  78. package/dist/mind-manager-NBJF5D26.js +32 -0
  79. package/dist/mind-profile-P67FEHOY.js +47 -0
  80. package/dist/mind-service-2MQ6UK5N.js +38 -0
  81. package/dist/{mind-sleep-CANABWJI.js → mind-sleep-WW2IX7JT.js} +5 -4
  82. package/dist/{mind-status-6WKZVUOP.js → mind-status-L3EFFRPR.js} +3 -2
  83. package/dist/{mind-wake-RZKLH2IN.js → mind-wake-VSSGW465.js} +5 -4
  84. package/dist/{package-NU4CA7OU.js → package-U3VFO273.js} +2 -1
  85. package/dist/{read-THL362EI.js → read-EBY56C33.js} +5 -4
  86. package/dist/read-stdin-HQJ7774D.js +8 -0
  87. package/dist/{register-QAQELAS6.js → register-HD74C4TT.js} +5 -4
  88. package/dist/{registry-ASXCQCNH.js → registry-PJ4S5PHQ.js} +8 -1
  89. package/dist/{reject-AYPBNPNL.js → reject-UJKFBHRO.js} +5 -4
  90. package/dist/{restart-6SKPV3T2.js → restart-3UCMRUVC.js} +3 -2
  91. package/dist/{sandbox-6ZEWQDVU.js → sandbox-GJOK4QLQ.js} +4 -3
  92. package/dist/scheduler-ZZ7XGQG6.js +32 -0
  93. package/dist/schema-PA3M5ZKH.js +32 -0
  94. package/dist/seed-QDYVLG74.js +11 -0
  95. package/dist/seed-check-S2IX25RL.js +32 -0
  96. package/dist/seed-cmd-DKOUFEAU.js +36 -0
  97. package/dist/{seed-OWX2AW75.js → seed-create-4XBBOLRH.js} +27 -10
  98. package/dist/{sprout-FDVI2CGN.js → seed-sprout-GQEIIQRT.js} +24 -9
  99. package/dist/{send-ZO4BTWXK.js → send-QIV2INHB.js} +92 -101
  100. package/dist/{setup-7CFITEQN.js → setup-TISPCO22.js} +7 -2
  101. package/dist/{setup-ZXBXG7E4.js → setup-XMCBE3LF.js} +11 -7
  102. package/dist/{skill-YFXP67A2.js → skill-PSQGRRJX.js} +5 -4
  103. package/dist/skills/dreaming/SKILL.md +6 -4
  104. package/dist/skills/dreaming/references/INSTALL.md +2 -2
  105. package/dist/skills/dreaming/scripts/dream.ts +2 -2
  106. package/dist/skills/dreaming/scripts/wake-context-dreams.sh +1 -1
  107. package/dist/skills/imagegen/SKILL.md +16 -11
  108. package/dist/skills/imagegen/references/INSTALL.md +1 -1
  109. package/dist/skills/imagegen/scripts/imagegen.ts +146 -25
  110. package/dist/skills/orientation/SKILL.md +9 -2
  111. package/dist/skills/resonance/SKILL.md +4 -1
  112. package/dist/skills/resonance/references/INSTALL.md +2 -2
  113. package/dist/skills/resonance/scripts/resonance-hook.sh +2 -0
  114. package/dist/skills/resonance/scripts/resonance.ts +35 -5
  115. package/dist/skills/seed-nurture/SKILL.md +42 -0
  116. package/dist/skills/volute-admin/SKILL.md +83 -0
  117. package/dist/skills/volute-mind/SKILL.md +15 -11
  118. package/dist/skills-7FV7EJTE.js +62 -0
  119. package/dist/sleep-manager-JTXSN7NV.js +36 -0
  120. package/dist/spirit-VRONKFMF.js +23 -0
  121. package/dist/{split-MI62KJUU.js → split-STOROBYJ.js} +1 -1
  122. package/dist/sprout-WKLZXUIQ.js +11 -0
  123. package/dist/{start-D64BRKPH.js → start-K2NCUUCG.js} +3 -2
  124. package/dist/{status-ZZWBYFGE.js → status-3JBTFSMI.js} +6 -4
  125. package/dist/{stop-OP2CTXCO.js → stop-H26JZDXF.js} +3 -2
  126. package/dist/system-chat-JAPOJ3KE.js +36 -0
  127. package/dist/{systems-EQPPT4B7.js → systems-XRI52VCH.js} +6 -5
  128. package/dist/{tailscale-6DJKUMNF.js → tailscale-XHQBZROW.js} +2 -1
  129. package/dist/{template-hash-3HOR4UAJ.js → template-hash-A6VVKOXJ.js} +2 -1
  130. package/dist/up-M5AS6SBV.js +18 -0
  131. package/dist/{update-KUJXATRS.js → update-UD543CXX.js} +6 -4
  132. package/dist/{update-check-5WVSU37T.js → update-check-ZD6OOIYQ.js} +3 -2
  133. package/dist/{upgrade-KBHCWX6T.js → upgrade-O4Q7WJM3.js} +12 -14
  134. package/dist/{version-notify-75ELVKPV.js → version-notify-NBI2MTJO.js} +22 -16
  135. package/dist/volute-config-HD7WWUQC.js +10 -0
  136. package/dist/web-assets/assets/index-CWJrVveV.css +1 -0
  137. package/dist/web-assets/assets/index-DJt14FRI.js +75 -0
  138. package/dist/web-assets/ext-theme.css +93 -0
  139. package/dist/web-assets/index.html +2 -2
  140. package/drizzle/0004_spirits.sql +5 -0
  141. package/drizzle/meta/0004_snapshot.json +7 -0
  142. package/drizzle/meta/_journal.json +7 -0
  143. package/package.json +2 -1
  144. package/packages/extensions/notes/dist/ui/assets/index-8jWEv9SA.js +61 -0
  145. package/packages/extensions/notes/dist/ui/assets/index-DkaB7Ytd.css +1 -0
  146. package/packages/extensions/notes/dist/ui/index.html +2 -2
  147. package/packages/extensions/pages/skills/pages/SKILL.md +16 -46
  148. package/templates/_base/.init/.config/hooks/pre-prompt/session-activity.ts +40 -0
  149. package/templates/_base/.init/{.config → .local}/bin/volute +1 -1
  150. package/templates/_base/.init/.local/hooks/pre-prompt/session-activity.ts +40 -0
  151. package/templates/_base/.init/.local/hooks/startup-context.ts +58 -0
  152. package/templates/_base/home/.config/routes.json +1 -1
  153. package/templates/_base/src/lib/daemon-client.ts +21 -13
  154. package/templates/_base/src/lib/format-prefix.ts +1 -0
  155. package/templates/_base/src/lib/hook-loader.ts +155 -0
  156. package/templates/_base/src/lib/startup.ts +11 -4
  157. package/templates/_base/src/lib/transparency.ts +2 -2
  158. package/templates/claude/.init/.claude/settings.json +1 -1
  159. package/templates/claude/.init/.config/routes.json +2 -2
  160. package/templates/claude/src/agent.ts +95 -13
  161. package/templates/claude/src/lib/message-channel.ts +7 -2
  162. package/templates/claude/src/lib/stream-consumer.ts +38 -0
  163. package/templates/codex/.init/.config/routes.json +11 -0
  164. package/templates/codex/.init/AGENTS.md +29 -0
  165. package/templates/codex/home/.config/config.json.tmpl +7 -0
  166. package/templates/codex/package.json.tmpl +20 -0
  167. package/templates/codex/src/agent.ts +554 -0
  168. package/templates/codex/src/lib/content.ts +16 -0
  169. package/templates/codex/src/lib/session-store.ts +56 -0
  170. package/templates/codex/src/server.ts +59 -0
  171. package/templates/codex/volute-template.json +8 -0
  172. package/templates/pi/.init/.config/routes.json +2 -2
  173. package/templates/pi/src/agent.ts +62 -8
  174. package/templates/pi/src/lib/event-handler.ts +1 -1
  175. package/templates/pi/src/lib/reply-instructions-extension.ts +32 -11
  176. package/dist/chunk-HR5JKIDG.js +0 -222
  177. package/dist/down-TS4XQBA4.js +0 -13
  178. package/dist/message-delivery-UJHCLVU4.js +0 -30
  179. package/dist/mind-manager-IPA6DZXD.js +0 -26
  180. package/dist/pages-watcher-72OVPRMH.js +0 -22
  181. package/dist/skills/sessions/SKILL.md +0 -49
  182. package/dist/sleep-manager-TPS6OGCA.js +0 -30
  183. package/dist/system-chat-B43GIXQU.js +0 -30
  184. package/dist/up-TDXEP3VA.js +0 -16
  185. package/dist/web-assets/assets/index-BM1cTzBg.js +0 -72
  186. package/dist/web-assets/assets/index-BfJkKTPF.css +0 -1
  187. package/packages/extensions/notes/dist/ui/assets/index-B8GdTnXs.css +0 -1
  188. package/packages/extensions/notes/dist/ui/assets/index-CDpGTCWb.js +0 -2
  189. package/packages/extensions/pages/skills/pages/scripts/pages.mjs +0 -58
  190. package/templates/_base/.init/.config/hooks/startup-context.sh +0 -46
  191. package/templates/_base/.init/.config/scripts/session-reader.ts +0 -59
  192. package/templates/_base/src/lib/session-monitor.ts +0 -400
  193. package/templates/claude/src/lib/hooks/session-context.ts +0 -32
  194. package/templates/pi/src/lib/session-context-extension.ts +0 -35
  195. /package/templates/_base/.init/{.config → .local}/hooks/wake-context.sh +0 -0
@@ -3,20 +3,6 @@ import {
3
3
  __export
4
4
  } from "./chunk-K3NQKI34.js";
5
5
 
6
- // src/lib/db.ts
7
- import { chmodSync, existsSync } from "fs";
8
- import { dirname as dirname2, resolve as resolve2 } from "path";
9
- import { fileURLToPath as fileURLToPath2 } from "url";
10
- import { drizzle } from "drizzle-orm/libsql";
11
- import { migrate } from "drizzle-orm/libsql/migrator";
12
-
13
- // src/lib/registry.ts
14
- import { mkdirSync } from "fs";
15
- import { homedir } from "os";
16
- import { dirname, resolve } from "path";
17
- import { fileURLToPath } from "url";
18
- import { eq, isNull } from "drizzle-orm";
19
-
20
6
  // src/lib/schema.ts
21
7
  var schema_exports = {};
22
8
  __export(schema_exports, {
@@ -48,9 +34,14 @@ var minds = sqliteTable(
48
34
  template: text("template"),
49
35
  template_hash: text("template_hash"),
50
36
  running: integer("running").notNull().default(0),
37
+ mind_type: text("mind_type").notNull().default("mind"),
38
+ created_by: text("created_by"),
51
39
  created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
52
40
  },
53
- (table) => [index("idx_minds_parent").on(table.parent)]
41
+ (table) => [
42
+ index("idx_minds_parent").on(table.parent),
43
+ index("idx_minds_mind_type").on(table.mind_type)
44
+ ]
54
45
  );
55
46
  var users = sqliteTable("users", {
56
47
  id: integer("id").primaryKey({ autoIncrement: true }),
@@ -218,166 +209,8 @@ var messages = sqliteTable(
218
209
  ]
219
210
  );
220
211
 
221
- // src/lib/registry.ts
222
- function voluteHome() {
223
- if (process.env.VOLUTE_HOME) return process.env.VOLUTE_HOME;
224
- const dir = dirname(fileURLToPath(import.meta.url));
225
- if (dir.endsWith("/src/lib")) {
226
- throw new Error(
227
- 'VOLUTE_HOME must be set when running from source. For tests, run via "npm test" or add "--import ./test/setup.ts".'
228
- );
229
- }
230
- return resolve(homedir(), ".volute");
231
- }
232
- function voluteUserHome() {
233
- if (process.env.VOLUTE_USER_HOME) return process.env.VOLUTE_USER_HOME;
234
- return resolve(homedir(), ".volute");
235
- }
236
- function voluteSystemDir() {
237
- return resolve(voluteHome(), "system");
238
- }
239
- function ensureSystemDir() {
240
- mkdirSync(voluteSystemDir(), { recursive: true });
241
- }
242
- function ensureVoluteHome() {
243
- const mindsBase = process.env.VOLUTE_MINDS_DIR ?? resolve(voluteHome(), "minds");
244
- mkdirSync(mindsBase, { recursive: true });
245
- ensureSystemDir();
246
- }
247
- function rowToEntry(row) {
248
- return {
249
- name: row.name,
250
- port: row.port,
251
- created: row.created_at,
252
- running: row.running === 1,
253
- stage: row.stage ?? (row.parent ? void 0 : "sprouted"),
254
- template: row.template ?? void 0,
255
- templateHash: row.template_hash ?? void 0,
256
- parent: row.parent ?? void 0,
257
- dir: row.dir ?? void 0,
258
- branch: row.branch ?? void 0
259
- };
260
- }
261
- async function readRegistry() {
262
- const db2 = await getDb();
263
- const rows = await db2.select().from(minds).where(isNull(minds.parent));
264
- return rows.map(rowToEntry);
265
- }
266
- async function readAllMinds() {
267
- const db2 = await getDb();
268
- const rows = await db2.select().from(minds);
269
- return rows.map(rowToEntry);
270
- }
271
- var MIND_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
272
- var MIND_NAME_MAX = 64;
273
- var RESERVED_NAMES = /* @__PURE__ */ new Set(["volute", "system"]);
274
- function validateMindName(name) {
275
- if (!name) return "Mind name is required";
276
- if (name.length > MIND_NAME_MAX) return `Mind name must be at most ${MIND_NAME_MAX} characters`;
277
- if (!MIND_NAME_RE.test(name)) {
278
- return "Mind name must start with alphanumeric and contain only alphanumeric, dots, dashes, or underscores";
279
- }
280
- if (RESERVED_NAMES.has(name.toLowerCase())) {
281
- return `"${name}" is a reserved name`;
282
- }
283
- return null;
284
- }
285
- async function addMind(name, port, stage, template) {
286
- const err = validateMindName(name);
287
- if (err) throw new Error(err);
288
- const db2 = await getDb();
289
- await db2.insert(minds).values({ name, port, stage: stage ?? null, template: template ?? null }).onConflictDoUpdate({
290
- target: minds.name,
291
- set: { port, stage: stage ?? null, template: template ?? null }
292
- });
293
- }
294
- async function addVariant(name, parent, port, dir, branch) {
295
- const err = validateMindName(name);
296
- if (err) throw new Error(err);
297
- const db2 = await getDb();
298
- await db2.insert(minds).values({ name, port, parent, dir, branch }).onConflictDoUpdate({
299
- target: minds.name,
300
- set: { port, parent, dir, branch }
301
- });
302
- }
303
- async function removeMind(name) {
304
- const db2 = await getDb();
305
- await db2.delete(minds).where(eq(minds.name, name));
306
- }
307
- async function setMindRunning(name, running) {
308
- const db2 = await getDb();
309
- await db2.update(minds).set({ running: running ? 1 : 0 }).where(eq(minds.name, name));
310
- }
311
- async function setMindStage(name, stage) {
312
- const db2 = await getDb();
313
- await db2.update(minds).set({ stage }).where(eq(minds.name, name));
314
- }
315
- async function setMindTemplateHash(name, hash) {
316
- const db2 = await getDb();
317
- await db2.update(minds).set({ template_hash: hash }).where(eq(minds.name, name));
318
- }
319
- async function findMind(name) {
320
- const db2 = await getDb();
321
- const rows = await db2.select().from(minds).where(eq(minds.name, name));
322
- if (rows.length === 0) return void 0;
323
- return rowToEntry(rows[0]);
324
- }
325
- async function findVariants(parent) {
326
- const db2 = await getDb();
327
- const rows = await db2.select().from(minds).where(eq(minds.parent, parent));
328
- return rows.map(rowToEntry);
329
- }
330
- async function getBaseName(name) {
331
- const entry = await findMind(name);
332
- return entry?.parent ?? name;
333
- }
334
- function mindDir(name) {
335
- if (process.env.VOLUTE_MINDS_DIR) {
336
- return resolve(process.env.VOLUTE_MINDS_DIR, name);
337
- }
338
- return resolve(voluteHome(), "minds", name);
339
- }
340
- function stateDir(name) {
341
- return resolve(voluteSystemDir(), "state", name);
342
- }
343
- async function nextPort() {
344
- const db2 = await getDb();
345
- const rows = await db2.select({ port: minds.port }).from(minds);
346
- const usedPorts = new Set(rows.map((r) => r.port));
347
- const basePort = parseInt(process.env.VOLUTE_BASE_PORT || "4100", 10);
348
- let port = basePort;
349
- while (usedPorts.has(port)) port++;
350
- if (port > 65535) throw new Error("No available ports \u2014 all ports 4100-65535 are allocated");
351
- return port;
352
- }
353
- function daemonLoopback() {
354
- const host = process.env.VOLUTE_DAEMON_HOSTNAME || "127.0.0.1";
355
- if (host === "0.0.0.0") return "127.0.0.1";
356
- if (host === "::") return "[::1]";
357
- return host;
358
- }
359
-
360
- // src/lib/db.ts
361
- var __dirname = dirname2(fileURLToPath2(import.meta.url));
362
- var migrationsFolder = existsSync(resolve2(__dirname, "../drizzle")) ? resolve2(__dirname, "../drizzle") : resolve2(__dirname, "../../drizzle");
363
- var db = null;
364
- async function getDb() {
365
- if (db) return db;
366
- const dbPath = process.env.VOLUTE_DB_PATH || resolve2(voluteSystemDir(), "volute.db");
367
- db = drizzle({ connection: { url: `file:${dbPath}` }, schema: schema_exports });
368
- await migrate(db, { migrationsFolder });
369
- try {
370
- chmodSync(dbPath, 384);
371
- } catch (err) {
372
- console.error(
373
- `[volute] WARNING: Failed to restrict database file permissions on ${dbPath}:`,
374
- err
375
- );
376
- }
377
- return db;
378
- }
379
-
380
212
  export {
213
+ minds,
381
214
  users,
382
215
  conversations,
383
216
  turns,
@@ -390,26 +223,5 @@ export {
390
223
  activity,
391
224
  conversationReads,
392
225
  messages,
393
- getDb,
394
- voluteHome,
395
- voluteUserHome,
396
- voluteSystemDir,
397
- ensureSystemDir,
398
- ensureVoluteHome,
399
- readRegistry,
400
- readAllMinds,
401
- validateMindName,
402
- addMind,
403
- addVariant,
404
- removeMind,
405
- setMindRunning,
406
- setMindStage,
407
- setMindTemplateHash,
408
- findMind,
409
- findVariants,
410
- getBaseName,
411
- mindDir,
412
- stateDir,
413
- nextPort,
414
- daemonLoopback
226
+ schema_exports
415
227
  };
@@ -3,7 +3,7 @@ import {
3
3
  readEnv,
4
4
  sharedEnvPath,
5
5
  writeEnv
6
- } from "./chunk-NV3TYNWX.js";
6
+ } from "./chunk-2NGTS5UU.js";
7
7
  import {
8
8
  logger_default
9
9
  } from "./chunk-YUIHSKR6.js";
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-D424ZQGI.js";
13
13
  import {
14
14
  voluteSystemDir
15
- } from "./chunk-X62AXPR7.js";
15
+ } from "./chunk-LRCG2JLP.js";
16
16
 
17
17
  // src/commands/import.ts
18
18
  import {
@@ -112,7 +112,7 @@ async function run(args) {
112
112
  return;
113
113
  }
114
114
  const wsDir = resolveWorkspace(inputPath);
115
- const { daemonFetch } = await import("./daemon-client-CVGM25DM.js");
115
+ const { daemonFetch } = await import("./daemon-client-6QXHZ7US.js");
116
116
  const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
117
117
  const client = getClient();
118
118
  const res = await daemonFetch(urlOf(client.api.minds.import.$url()), {
@@ -152,7 +152,7 @@ async function importArchive(archivePath, nameOverride) {
152
152
  console.error(`File not found: ${archivePath}`);
153
153
  process.exit(1);
154
154
  }
155
- const { extractArchive } = await import("./archive-YBNSJYZZ.js");
155
+ const { extractArchive } = await import("./archive-INXYFVCW.js");
156
156
  const tempDir = resolve2(tmpdir(), `volute-import-${Date.now()}`);
157
157
  mkdirSync(tempDir, { recursive: true });
158
158
  let extracted;
@@ -164,7 +164,7 @@ async function importArchive(archivePath, nameOverride) {
164
164
  process.exit(1);
165
165
  }
166
166
  try {
167
- const { daemonFetch } = await import("./daemon-client-CVGM25DM.js");
167
+ const { daemonFetch } = await import("./daemon-client-6QXHZ7US.js");
168
168
  const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
169
169
  const client = getClient();
170
170
  const res = await daemonFetch(urlOf(client.api.minds.import.$url()), {
@@ -1,18 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  subscribe
4
- } from "./chunk-EKDWA7E4.js";
4
+ } from "./chunk-KVK2DLWI.js";
5
5
  import {
6
6
  logger_default
7
7
  } from "./chunk-YUIHSKR6.js";
8
+ import {
9
+ getDb
10
+ } from "./chunk-LRCG2JLP.js";
8
11
  import {
9
12
  conversationParticipants,
10
13
  conversationReads,
11
14
  conversations,
12
- getDb,
13
15
  messages,
14
16
  users
15
- } from "./chunk-X62AXPR7.js";
17
+ } from "./chunk-RPZZSXV3.js";
16
18
 
17
19
  // src/lib/events/conversations.ts
18
20
  import { randomUUID } from "crypto";
@@ -0,0 +1,208 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ logger_default
4
+ } from "./chunk-YUIHSKR6.js";
5
+ import {
6
+ mindDir
7
+ } from "./chunk-LRCG2JLP.js";
8
+
9
+ // src/lib/delivery/delivery-router.ts
10
+ import { readFileSync, statSync } from "fs";
11
+ import { resolve } from "path";
12
+ function extractTextContent(content) {
13
+ if (typeof content === "string") return content;
14
+ if (Array.isArray(content)) {
15
+ return content.filter((p) => p.type === "text" && p.text).map((p) => p.text).join("\n");
16
+ }
17
+ return JSON.stringify(content);
18
+ }
19
+ var configCache = /* @__PURE__ */ new Map();
20
+ var statCheckCache = /* @__PURE__ */ new Map();
21
+ var STAT_TTL_MS = 5e3;
22
+ var dlog = logger_default.child("delivery-router");
23
+ var dirOverrides = /* @__PURE__ */ new Map();
24
+ function registerMindDir(name, dir) {
25
+ dirOverrides.set(name, dir);
26
+ }
27
+ function configPath(mindName) {
28
+ const dir = dirOverrides.get(mindName) ?? mindDir(mindName);
29
+ return resolve(dir, "home/.config/routes.json");
30
+ }
31
+ function getRoutingConfig(mindName) {
32
+ const path = configPath(mindName);
33
+ const now = Date.now();
34
+ const statCached = statCheckCache.get(mindName);
35
+ const cached = configCache.get(mindName);
36
+ if (statCached && cached && now - statCached.checkedAt < STAT_TTL_MS) {
37
+ return cached.config;
38
+ }
39
+ let mtime;
40
+ try {
41
+ mtime = statSync(path).mtimeMs;
42
+ } catch {
43
+ configCache.delete(mindName);
44
+ statCheckCache.delete(mindName);
45
+ return {};
46
+ }
47
+ statCheckCache.set(mindName, { mtime, checkedAt: now });
48
+ if (cached && cached.mtime === mtime) {
49
+ return cached.config;
50
+ }
51
+ try {
52
+ const config = JSON.parse(readFileSync(path, "utf-8"));
53
+ configCache.set(mindName, { config, mtime });
54
+ return config;
55
+ } catch (err) {
56
+ dlog.warn(`failed to load routes.json for ${mindName}`, logger_default.errorData(err));
57
+ configCache.delete(mindName);
58
+ return {};
59
+ }
60
+ }
61
+ var globRegexCache = /* @__PURE__ */ new Map();
62
+ function clearConfigCache(mindName) {
63
+ if (mindName) {
64
+ configCache.delete(mindName);
65
+ statCheckCache.delete(mindName);
66
+ } else {
67
+ configCache.clear();
68
+ statCheckCache.clear();
69
+ globRegexCache.clear();
70
+ }
71
+ }
72
+ function globMatch(pattern, value) {
73
+ let regex = globRegexCache.get(pattern);
74
+ if (!regex) {
75
+ const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
76
+ regex = new RegExp(`^${escaped}$`);
77
+ globRegexCache.set(pattern, regex);
78
+ }
79
+ return regex.test(value);
80
+ }
81
+ var GLOB_MATCH_KEYS = /* @__PURE__ */ new Set(["channel", "sender"]);
82
+ var NON_MATCH_KEYS = /* @__PURE__ */ new Set(["session", "destination", "path", "mode", "batch"]);
83
+ function ruleMatches(rule, meta) {
84
+ for (const [key, pattern] of Object.entries(rule)) {
85
+ if (NON_MATCH_KEYS.has(key)) continue;
86
+ if (key === "isDM") {
87
+ if (typeof pattern !== "boolean") return false;
88
+ if ((meta.isDM ?? false) !== pattern) return false;
89
+ continue;
90
+ }
91
+ if (key === "participants") {
92
+ if (typeof pattern !== "number") return false;
93
+ if ((meta.participantCount ?? 0) !== pattern) return false;
94
+ continue;
95
+ }
96
+ if (typeof pattern !== "string") return false;
97
+ if (!GLOB_MATCH_KEYS.has(key)) return false;
98
+ const value = meta[key] ?? "";
99
+ if (!globMatch(pattern, value)) return false;
100
+ }
101
+ return true;
102
+ }
103
+ function expandTemplate(template, meta) {
104
+ return template.replace(/\$\{sender\}/g, meta.sender ?? "unknown").replace(/\$\{channel\}/g, meta.channel ?? "unknown");
105
+ }
106
+ function sanitizeSessionName(name) {
107
+ return name.replace(/\0/g, "").replace(/[/\\]/g, "-").replace(/\.\./g, "-").slice(0, 100);
108
+ }
109
+ function resolveRoute(config, meta) {
110
+ const fallback = config.default ?? "main";
111
+ if (!config.rules) {
112
+ return { destination: "mind", session: fallback, matched: false };
113
+ }
114
+ for (const rule of config.rules) {
115
+ if (ruleMatches(rule, meta)) {
116
+ if (rule.destination === "file") {
117
+ if (!rule.path) {
118
+ dlog.warn("file destination rule missing path \u2014 falling through");
119
+ continue;
120
+ }
121
+ return { destination: "file", path: rule.path, matched: true };
122
+ }
123
+ return {
124
+ destination: "mind",
125
+ session: sanitizeSessionName(expandTemplate(rule.session ?? fallback, meta)),
126
+ matched: true,
127
+ mode: rule.mode,
128
+ rule
129
+ };
130
+ }
131
+ }
132
+ return { destination: "mind", session: fallback, matched: false };
133
+ }
134
+ var DEFAULT_BATCH_DEBOUNCE = 5;
135
+ var DEFAULT_BATCH_MAX_WAIT = 120;
136
+ function normalizeBatchConfig(batch) {
137
+ if (typeof batch === "number") return { maxWait: batch * 60 };
138
+ return batch;
139
+ }
140
+ function resolveDeliveryMode(config, sessionName, rule) {
141
+ const ruleBatch = rule?.batch;
142
+ const defaults = {
143
+ delivery: { mode: "immediate" },
144
+ interrupt: true
145
+ };
146
+ if (!config.sessions) {
147
+ if (ruleBatch != null) {
148
+ const batch = normalizeBatchConfig(ruleBatch);
149
+ return {
150
+ delivery: {
151
+ mode: "batch",
152
+ debounce: batch.debounce ?? DEFAULT_BATCH_DEBOUNCE,
153
+ maxWait: batch.maxWait ?? DEFAULT_BATCH_MAX_WAIT,
154
+ triggers: batch.triggers
155
+ },
156
+ interrupt: true
157
+ };
158
+ }
159
+ return defaults;
160
+ }
161
+ for (const [pattern, sessionConfig] of Object.entries(config.sessions)) {
162
+ if (globMatch(pattern, sessionName)) {
163
+ let delivery;
164
+ if (sessionConfig.delivery == null || sessionConfig.delivery === "immediate") {
165
+ delivery = { mode: "immediate" };
166
+ } else if (sessionConfig.delivery === "batch") {
167
+ delivery = {
168
+ mode: "batch",
169
+ debounce: DEFAULT_BATCH_DEBOUNCE,
170
+ maxWait: DEFAULT_BATCH_MAX_WAIT
171
+ };
172
+ } else {
173
+ delivery = {
174
+ mode: "batch",
175
+ debounce: sessionConfig.delivery.debounce ?? DEFAULT_BATCH_DEBOUNCE,
176
+ maxWait: sessionConfig.delivery.maxWait ?? DEFAULT_BATCH_MAX_WAIT
177
+ };
178
+ }
179
+ return {
180
+ delivery,
181
+ interrupt: true,
182
+ instructions: sessionConfig.instructions
183
+ };
184
+ }
185
+ }
186
+ if (ruleBatch != null) {
187
+ const batch = normalizeBatchConfig(ruleBatch);
188
+ return {
189
+ delivery: {
190
+ mode: "batch",
191
+ debounce: batch.debounce ?? DEFAULT_BATCH_DEBOUNCE,
192
+ maxWait: batch.maxWait ?? DEFAULT_BATCH_MAX_WAIT,
193
+ triggers: batch.triggers
194
+ },
195
+ interrupt: true
196
+ };
197
+ }
198
+ return defaults;
199
+ }
200
+
201
+ export {
202
+ extractTextContent,
203
+ registerMindDir,
204
+ getRoutingConfig,
205
+ clearConfigCache,
206
+ resolveRoute,
207
+ resolveDeliveryMode
208
+ };
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  voluteSystemDir,
4
4
  voluteUserHome
5
- } from "./chunk-X62AXPR7.js";
5
+ } from "./chunk-LRCG2JLP.js";
6
6
 
7
7
  // src/lib/daemon-client.ts
8
8
  import { existsSync, readFileSync } from "fs";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  getBaseName,
4
4
  validateMindName
5
- } from "./chunk-X62AXPR7.js";
5
+ } from "./chunk-LRCG2JLP.js";
6
6
 
7
7
  // src/lib/isolation.ts
8
8
  import { execFileSync } from "child_process";
@@ -11,7 +11,9 @@ function isIsolationEnabled() {
11
11
  }
12
12
  function mindUserName(mindName) {
13
13
  const err = validateMindName(mindName);
14
- if (err) throw new Error(`Invalid mind name for isolation: ${err}`);
14
+ if (err && mindName !== "volute") {
15
+ throw new Error(`Invalid mind name for isolation: ${err}`);
16
+ }
15
17
  const prefix = process.env.VOLUTE_USER_PREFIX ?? "mind-";
16
18
  return `${prefix}${mindName}`;
17
19
  }
@@ -166,54 +168,6 @@ function chownMindDir(dir, name) {
166
168
  }
167
169
  }
168
170
 
169
- // src/lib/exec.ts
170
- import { execFile as execFileCb, execFileSync as execFileSync2, spawn } from "child_process";
171
- async function exec(cmd, args, options) {
172
- const [wrappedCmd, wrappedArgs] = options?.mindName ? await wrapForIsolation(cmd, args, options.mindName) : [cmd, args];
173
- return new Promise((resolve, reject) => {
174
- execFileCb(
175
- wrappedCmd,
176
- wrappedArgs,
177
- { cwd: options?.cwd, env: options?.env },
178
- (err, stdout, stderr) => {
179
- if (err) {
180
- err.stderr = stderr;
181
- err.stdout = stdout;
182
- reject(err);
183
- } else {
184
- resolve(stdout);
185
- }
186
- }
187
- );
188
- });
189
- }
190
- function gitExec(args, options) {
191
- const fullArgs = process.env.VOLUTE_ISOLATION === "user" ? ["-c", "safe.directory=*", ...args] : args;
192
- return exec("git", fullArgs, options);
193
- }
194
- function resolveVoluteBin() {
195
- try {
196
- return execFileSync2("which", ["volute"], { encoding: "utf-8" }).trim();
197
- } catch {
198
- throw new Error("Could not find volute binary on PATH");
199
- }
200
- }
201
- async function execInherit(cmd, args, options) {
202
- const [wrappedCmd, wrappedArgs] = options?.mindName ? await wrapForIsolation(cmd, args, options.mindName) : [cmd, args];
203
- return new Promise((resolve, reject) => {
204
- const child = spawn(wrappedCmd, wrappedArgs, {
205
- cwd: options?.cwd,
206
- env: options?.env,
207
- stdio: "inherit"
208
- });
209
- child.on("error", reject);
210
- child.on("close", (code) => {
211
- if (code === 0) resolve();
212
- else reject(new Error(`${cmd} ${args.join(" ")} exited with code ${code}`));
213
- });
214
- });
215
- }
216
-
217
171
  export {
218
172
  isIsolationEnabled,
219
173
  mindUserName,
@@ -221,9 +175,5 @@ export {
221
175
  createMindUser,
222
176
  deleteMindUser,
223
177
  wrapForIsolation,
224
- chownMindDir,
225
- exec,
226
- gitExec,
227
- resolveVoluteBin,
228
- execInherit
178
+ chownMindDir
229
179
  };