volute 0.47.0 → 0.48.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 (128) hide show
  1. package/README.md +11 -11
  2. package/dist/{accept-YAFP5JFJ.js → accept-KYNC5X3U.js} +3 -3
  3. package/dist/{ai-service-CVZEYKTK.js → ai-service-643TNFPH.js} +6 -2
  4. package/dist/{avatar-image-7S3WA77A.js → avatar-image-Y45R7LW5.js} +3 -2
  5. package/dist/{backup-IIAFOW2L.js → backup-UDH4GMSW.js} +11 -11
  6. package/dist/{bridge-TIZGSXOD.js → bridge-3FNSWLNQ.js} +3 -3
  7. package/dist/{channels-ITE4YC57.js → channels-SGQZHNQJ.js} +3 -3
  8. package/dist/{chat-AJLJCQ3M.js → chat-X43VYHH2.js} +9 -9
  9. package/dist/chunk-4FCL4DVZ.js +48 -0
  10. package/dist/{chunk-SKNXMUIU.js → chunk-5KXCM5AW.js} +17 -1
  11. package/dist/{chunk-RBNMDAKB.js → chunk-BCG45AQB.js} +15 -1
  12. package/dist/chunk-DW4TRDOZ.js +29 -0
  13. package/dist/{chunk-CBOIHNMR.js → chunk-FJ2MZ5PH.js} +39 -3
  14. package/dist/{chunk-M6TTZRGH.js → chunk-HNGFKPNS.js} +20 -4
  15. package/dist/{chunk-IWJSNMSY.js → chunk-HUNDXZBZ.js} +2 -2
  16. package/dist/chunk-IYCV34IU.js +158 -0
  17. package/dist/{chunk-5IERLDUS.js → chunk-MJRXFUMS.js} +25 -5
  18. package/dist/{chunk-JCMGDCGX.js → chunk-MOERAQXH.js} +2 -0
  19. package/dist/{chunk-XHN6XBWV.js → chunk-OQJMTHEH.js} +1 -1
  20. package/dist/{chunk-BGYHLR54.js → chunk-PJVPDY2Z.js} +1 -1
  21. package/dist/{chunk-5NN2VHJV.js → chunk-Q7HOAVFR.js} +1 -1
  22. package/dist/{chunk-KDLYIECM.js → chunk-R772ET2M.js} +18 -4
  23. package/dist/{mind-list-KEGRGQEQ.js → chunk-SHKM5RGD.js} +19 -6
  24. package/dist/{chunk-4I72V3E5.js → chunk-T4VS7UDW.js} +11 -11
  25. package/dist/{chunk-K23P5Q5N.js → chunk-USD45JKR.js} +27 -5
  26. package/dist/{chunk-F55GRIEK.js → chunk-VB2QXUJQ.js} +176 -201
  27. package/dist/{chunk-M3XDVS5Q.js → chunk-VZRA5TYO.js} +1 -1
  28. package/dist/{chunk-JSVHH32K.js → chunk-WARH6GIV.js} +10 -10
  29. package/dist/{chunk-PFZBNKUH.js → chunk-WCFSBH33.js} +0 -1
  30. package/dist/{chunk-VMCZBXF2.js → chunk-WQ46E33M.js} +8 -32
  31. package/dist/{chunk-RUFLGTOT.js → chunk-XVBSFLM7.js} +1 -1
  32. package/dist/{chunk-LWDTP6DH.js → chunk-YNBXEQAP.js} +31 -1
  33. package/dist/cli.js +33 -25
  34. package/dist/{clock-E6N5Y3YW.js → clock-CNRF6F7T.js} +3 -3
  35. package/dist/{cloud-sync-LQTVDTQ3.js → cloud-sync-WHKCB4CD.js} +14 -12
  36. package/dist/{config-TJLYUV3U.js → config-RPSLA2HX.js} +3 -3
  37. package/dist/{create-PQQXKTJK.js → create-GJKHABJB.js} +16 -5
  38. package/dist/{create-A7PDHIIL.js → create-VIQVP3QB.js} +3 -3
  39. package/dist/{daemon-client-IYR4KCPU.js → daemon-client-ZFY5MOAL.js} +5 -3
  40. package/dist/{daemon-restart-5F3YTLZK.js → daemon-restart-7KUHVZIN.js} +4 -4
  41. package/dist/daemon.js +668 -401
  42. package/dist/{db-LZTLA7XC.js → db-IPXRJUI7.js} +1 -1
  43. package/dist/{delete-HPLC7ETU.js → delete-ESEP7NGQ.js} +1 -1
  44. package/dist/{delivery-manager-TN5KK2AP.js → delivery-manager-HZTT5SJR.js} +14 -12
  45. package/dist/{down-ZI4S6265.js → down-G6IADJXV.js} +2 -2
  46. package/dist/{echo-text-SEQCLGAT.js → echo-text-H3SH337Q.js} +16 -14
  47. package/dist/env-6TGPO5WG.js +18 -0
  48. package/dist/{env-HRL2PWAT.js → env-C7Z55QCJ.js} +7 -7
  49. package/dist/{export-4GVGNW54.js → export-C2K3NIRD.js} +1 -1
  50. package/dist/{extension-QBY4C44L.js → extension-J4ZQ2GHV.js} +3 -3
  51. package/dist/{extensions-PIMIQ7J3.js → extensions-GEKF47A4.js} +14 -12
  52. package/dist/{files-FEFZKMNM.js → files-LXQSQOFG.js} +3 -3
  53. package/dist/{import-7MO3YTRE.js → import-SX3ZXHB4.js} +4 -4
  54. package/dist/{join-ZJV7W6MO.js → join-34TR2GXQ.js} +1 -1
  55. package/dist/{list-LQO2DCIK.js → list-PMUXZNAM.js} +3 -3
  56. package/dist/{login-6TLMI2TQ.js → login-ARRZ4ORJ.js} +3 -3
  57. package/dist/{login-OF4WXDAN.js → login-CL4IT2ED.js} +12 -3
  58. package/dist/{logout-ERE2BGA3.js → logout-HZYJCYCA.js} +3 -3
  59. package/dist/{logout-BK53HXNY.js → logout-YZRMZ3O2.js} +3 -3
  60. package/dist/{message-delivery-ZE3YGJDD.js → message-delivery-GPQ5SE5N.js} +14 -12
  61. package/dist/{mind-POOHFZHP.js → mind-46AOK373.js} +23 -19
  62. package/dist/mind-contacts-GV7XYL5D.js +64 -0
  63. package/dist/{mind-history-47DN6ILW.js → mind-history-TTGA5BHZ.js} +7 -7
  64. package/dist/mind-list-OTHV4ZO4.js +13 -0
  65. package/dist/{mind-profile-PEQYASQX.js → mind-profile-LUG353ZT.js} +1 -1
  66. package/dist/{mind-service-JFY7UG5E.js → mind-service-2ARGJNKP.js} +16 -12
  67. package/dist/{mind-sleep-IN3WPA76.js → mind-sleep-DV7KP255.js} +5 -5
  68. package/dist/{mind-status-SMUWJKGV.js → mind-status-BJNPGXKC.js} +8 -3
  69. package/dist/{mind-wake-R54BPESY.js → mind-wake-LVTZ55EZ.js} +3 -3
  70. package/dist/notices-2KU5NTRY.js +25 -0
  71. package/dist/{package-WPEE2HVJ.js → package-RTN2PS7O.js} +4 -2
  72. package/dist/{read-PWAJOQIQ.js → read-YSWUXYL7.js} +3 -3
  73. package/dist/{register-7SZJFHU6.js → register-42VBJKTP.js} +3 -3
  74. package/dist/{reject-6VH7N2A4.js → reject-SXGCYN4A.js} +3 -3
  75. package/dist/{restart-H5WJDMA7.js → restart-YYEGZJDD.js} +7 -7
  76. package/dist/{sandbox-G4X4K3UN.js → sandbox-5VQ454XP.js} +2 -2
  77. package/dist/{scheduler-HQSDYJFY.js → scheduler-I7JZCT47.js} +14 -12
  78. package/dist/{seed-VANPU43L.js → seed-F2HXZQU4.js} +1 -1
  79. package/dist/{seed-check-VLTVILOV.js → seed-check-TYD7RRZY.js} +1 -1
  80. package/dist/{seed-cmd-SYVDZKM4.js → seed-cmd-MLCTGSX5.js} +3 -3
  81. package/dist/{seed-create-3FGZPS6C.js → seed-create-KQ7OILWB.js} +6 -4
  82. package/dist/seed-readiness-RBPGOLSZ.js +18 -0
  83. package/dist/{seed-sprout-H7QLFPFM.js → seed-sprout-HVYCFJLA.js} +29 -30
  84. package/dist/{send-HYDFGC6G.js → send-TD2X5U3K.js} +7 -7
  85. package/dist/{service-SYJ5G6LP.js → service-CVZMQYK6.js} +1 -1
  86. package/dist/{service-install-FQ43Z4DF.js → service-install-VCRMFWX5.js} +2 -2
  87. package/dist/{setup-KFYVWTXG.js → setup-5ECWTYKG.js} +5 -1
  88. package/dist/{setup-QJHGMGSN.js → setup-AE4CVUC4.js} +4 -4
  89. package/dist/{skill-GUKG2YVH.js → skill-UUM4JZRF.js} +7 -7
  90. package/dist/skills/dreaming/SKILL.md +5 -1
  91. package/dist/skills/dreaming/scripts/dream.ts +5 -1
  92. package/dist/skills/orientation/SKILL.md +8 -7
  93. package/dist/skills/tending/SKILL.md +51 -2
  94. package/dist/skills/volute-mind/SKILL.md +2 -0
  95. package/dist/{skills-L2CMTW7A.js → skills-B3SVDCEB.js} +2 -2
  96. package/dist/{sleep-manager-3NA7ZJP3.js → sleep-manager-Z27R3WTW.js} +14 -12
  97. package/dist/{spirit-WXN4IDBF.js → spirit-WXS3HCLN.js} +7 -5
  98. package/dist/{split-WBMZXBHF.js → split-SKZ4Y2D6.js} +1 -1
  99. package/dist/{sprout-LTL5P36T.js → sprout-KQ43BWZJ.js} +1 -1
  100. package/dist/{src-OJHARHTF.js → src-WLJE73NP.js} +14 -5
  101. package/dist/{start-X46I3GXB.js → start-O6UKK7BG.js} +7 -7
  102. package/dist/{status-V4RJMHJ4.js → status-F4PGREUU.js} +6 -4
  103. package/dist/{stop-HJQV4YSM.js → stop-UBX6X5RA.js} +7 -7
  104. package/dist/{system-chat-N2F7HVY3.js → system-chat-63ABFF6V.js} +14 -12
  105. package/dist/{systems-B5YJKMW4.js → systems-JJNGQHAO.js} +6 -6
  106. package/dist/{turn-tracker-JZRZDFWV.js → turn-tracker-KLPV3PAU.js} +4 -4
  107. package/dist/{up-J2PBPOZL.js → up-RVGDE6CQ.js} +5 -3
  108. package/dist/{update-ACV4SAY3.js → update-OXQEGGXD.js} +1 -1
  109. package/dist/{upgrade-NWAZ7MLD.js → upgrade-K5FIQPQD.js} +1 -1
  110. package/dist/{version-notify-XRGTEEDK.js → version-notify-73YURTFR.js} +17 -15
  111. package/dist/web-assets/assets/index-WdZ60R6c.css +1 -0
  112. package/dist/web-assets/assets/index-taX6Ezfa.js +92 -0
  113. package/dist/web-assets/index.html +2 -2
  114. package/package.json +4 -2
  115. package/packages/extensions/pages/dist/ui/assets/index-BuXnE-rb.css +1 -0
  116. package/packages/extensions/pages/dist/ui/assets/index-DtzftuPA.js +2 -0
  117. package/packages/extensions/pages/dist/ui/index.html +2 -2
  118. package/templates/_base/src/lib/startup.ts +16 -1
  119. package/templates/claude/src/agent.ts +9 -2
  120. package/templates/claude/src/server.ts +4 -2
  121. package/templates/pi/src/agent.ts +7 -10
  122. package/templates/pi/src/lib/dispatch.ts +65 -0
  123. package/dist/volute-config-A52FHWKM.js +0 -14
  124. package/dist/web-assets/assets/index-DtctoDXY.css +0 -1
  125. package/dist/web-assets/assets/index-Wpyb2CML.js +0 -86
  126. package/packages/extensions/pages/dist/ui/assets/index-BcY6lnq4.css +0 -1
  127. package/packages/extensions/pages/dist/ui/assets/index-CQjEQg1r.js +0 -2
  128. /package/dist/{chunk-IYG4FBMP.js → chunk-IJPMIEVE.js} +0 -0
@@ -1,51 +1,61 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- loadMergedEnv
4
- } from "./chunk-IYG4FBMP.js";
5
2
  import {
6
3
  spiritDir
7
- } from "./chunk-M6TTZRGH.js";
4
+ } from "./chunk-HNGFKPNS.js";
8
5
  import {
9
6
  clearMind,
10
7
  linkInboundToActiveTurn,
11
8
  publish as publish3,
12
9
  summarizeOrphanedTurns
13
- } from "./chunk-K23P5Q5N.js";
10
+ } from "./chunk-USD45JKR.js";
14
11
  import {
15
12
  getPrompt
16
- } from "./chunk-JCMGDCGX.js";
13
+ } from "./chunk-MOERAQXH.js";
17
14
  import {
18
15
  hashSkillDir,
19
16
  importSkillFromDir,
20
17
  removeSharedSkill,
21
18
  sharedSkillsDir
22
- } from "./chunk-IWJSNMSY.js";
19
+ } from "./chunk-HUNDXZBZ.js";
20
+ import {
21
+ getOrCreateMindUser,
22
+ getOrCreateSystemUser,
23
+ getUser,
24
+ getUserByUsername,
25
+ syncMindProfile
26
+ } from "./chunk-ODDGGLM6.js";
23
27
  import {
24
28
  addMessage,
25
29
  createChannel,
26
30
  createConversation,
27
31
  findDMConversation,
28
32
  getChannelByName,
33
+ getChannelSettings,
29
34
  getParticipants,
30
35
  joinChannel,
31
- publish as publish2
36
+ publish as publish2,
37
+ updateChannelSettings
32
38
  } from "./chunk-HPGN6XRT.js";
33
39
  import {
34
40
  isSandboxEnabled,
35
41
  wrapForSandbox
36
- } from "./chunk-M3XDVS5Q.js";
42
+ } from "./chunk-VZRA5TYO.js";
43
+ import {
44
+ MIND_LEVEL_SESSION,
45
+ recordNotice
46
+ } from "./chunk-IYCV34IU.js";
37
47
  import {
38
48
  markIdle,
39
49
  onMindEvent
40
50
  } from "./chunk-MTRMQFCQ.js";
41
51
  import {
42
52
  renderAvatarBlock
43
- } from "./chunk-VMCZBXF2.js";
53
+ } from "./chunk-WQ46E33M.js";
44
54
  import {
45
55
  readVoluteConfig,
46
56
  resolveWakeTriggers,
47
57
  writeVoluteConfig
48
- } from "./chunk-PFZBNKUH.js";
58
+ } from "./chunk-WCFSBH33.js";
49
59
  import {
50
60
  extractTextContent,
51
61
  getRoutingConfig,
@@ -60,22 +70,19 @@ import {
60
70
  mindUserName,
61
71
  wrapForIsolation
62
72
  } from "./chunk-DGGZVZTM.js";
73
+ import {
74
+ loadMergedEnv
75
+ } from "./chunk-IJPMIEVE.js";
63
76
  import {
64
77
  aiCompleteUtility,
65
78
  getAiConfig,
79
+ missingCredentialWarning,
66
80
  resolveApiKey
67
- } from "./chunk-LWDTP6DH.js";
81
+ } from "./chunk-YNBXEQAP.js";
68
82
  import {
69
83
  readGlobalConfig,
70
84
  writeGlobalConfig
71
- } from "./chunk-SKNXMUIU.js";
72
- import {
73
- getOrCreateMindUser,
74
- getOrCreateSystemUser,
75
- getUser,
76
- getUserByUsername,
77
- syncMindProfile
78
- } from "./chunk-ODDGGLM6.js";
85
+ } from "./chunk-5KXCM5AW.js";
79
86
  import {
80
87
  publish,
81
88
  subscribe
@@ -91,6 +98,7 @@ import {
91
98
  isSpiritName,
92
99
  mindDir,
93
100
  mindTmpDir,
101
+ readRegistry,
94
102
  setMindRunning,
95
103
  stateDir,
96
104
  voluteHome,
@@ -102,28 +110,27 @@ import {
102
110
  deliveryQueue,
103
111
  messages,
104
112
  mindHistory,
105
- mindNotices,
106
113
  sessions
107
114
  } from "./chunk-2MJ7EOMT.js";
108
115
 
109
116
  // packages/daemon/src/lib/delivery/message-delivery.ts
110
- import { and as and5, eq as eq6, inArray as inArray3 } from "drizzle-orm";
117
+ import { and as and4, eq as eq5, inArray as inArray3 } from "drizzle-orm";
111
118
 
112
119
  // packages/daemon/src/lib/daemon/sleep-manager.ts
113
120
  import { execFile as execFile2, spawn as spawnChild } from "child_process";
114
121
  import {
115
- existsSync as existsSync8,
122
+ existsSync as existsSync9,
116
123
  mkdirSync as mkdirSync5,
117
124
  readdirSync as readdirSync2,
118
- readFileSync as readFileSync7,
125
+ readFileSync as readFileSync8,
119
126
  readlinkSync,
120
127
  renameSync,
121
128
  writeFileSync as writeFileSync6
122
129
  } from "fs";
123
- import { resolve as resolve7 } from "path";
130
+ import { resolve as resolve8 } from "path";
124
131
  import { promisify as promisify2 } from "util";
125
132
  import { CronExpressionParser as CronExpressionParser2 } from "cron-parser";
126
- import { and as and2, eq as eq3, inArray } from "drizzle-orm";
133
+ import { and, eq as eq2, inArray } from "drizzle-orm";
127
134
 
128
135
  // packages/daemon/src/lib/daemon/mind-manager.ts
129
136
  import { execFile, spawn } from "child_process";
@@ -348,106 +355,6 @@ function getMindToken(mindName) {
348
355
  return mindToToken.get(mindName) ?? null;
349
356
  }
350
357
 
351
- // packages/daemon/src/lib/daemon/notices.ts
352
- import { and, asc, eq, lte, or, sql } from "drizzle-orm";
353
- var nlog = logger_default.child("notices");
354
- var MIND_LEVEL_SESSION = "";
355
- var MAX_NOTICES_PER_SESSION = 100;
356
- async function recordNotice(input) {
357
- try {
358
- const db = await getDb();
359
- await db.insert(mindNotices).values({
360
- mind: input.mind,
361
- session: input.session,
362
- kind: input.kind,
363
- reason: input.reason,
364
- detail: input.detail,
365
- raw: input.raw ?? null
366
- });
367
- await db.run(
368
- sql`DELETE FROM mind_notices WHERE mind = ${input.mind} AND session = ${input.session} AND id NOT IN (SELECT id FROM mind_notices WHERE mind = ${input.mind} AND session = ${input.session} ORDER BY id DESC LIMIT ${MAX_NOTICES_PER_SESSION})`
369
- );
370
- } catch (err) {
371
- nlog.error(`failed to record notice for ${input.mind}:${input.session}`, logger_default.errorData(err));
372
- }
373
- }
374
- async function drainNotices(mind, session, limit = MAX_NOTICES_PER_SESSION) {
375
- const db = await getDb();
376
- return db.select().from(mindNotices).where(
377
- and(
378
- eq(mindNotices.mind, mind),
379
- or(eq(mindNotices.session, session), eq(mindNotices.session, MIND_LEVEL_SESSION))
380
- )
381
- ).orderBy(asc(mindNotices.id)).limit(limit);
382
- }
383
- async function clearDeliveredNotices(mind, session, uptoId) {
384
- try {
385
- const db = await getDb();
386
- await db.delete(mindNotices).where(
387
- and(
388
- eq(mindNotices.mind, mind),
389
- or(eq(mindNotices.session, session), eq(mindNotices.session, MIND_LEVEL_SESSION)),
390
- lte(mindNotices.id, uptoId)
391
- )
392
- );
393
- } catch (err) {
394
- nlog.warn(`failed to clear delivered notices for ${mind}:${session}`, logger_default.errorData(err));
395
- }
396
- }
397
- var NOTICE_HEADER = "[Notices] While you were unavailable, one or more turns failed. You're back now:";
398
- function formatNotices(notices) {
399
- if (notices.length === 0) return null;
400
- const failures = notices.filter((n) => n.kind !== "extension" && n.kind !== "budget");
401
- const budgets = notices.filter((n) => n.kind === "budget");
402
- const extensions = notices.filter((n) => n.kind === "extension");
403
- const blocks = [];
404
- if (failures.length > 0) {
405
- const groups = /* @__PURE__ */ new Map();
406
- for (const n of failures) {
407
- const time = localHM(n.created_at);
408
- const g = groups.get(n.reason);
409
- if (g) {
410
- g.count += 1;
411
- g.detail = n.detail;
412
- g.last = time;
413
- } else {
414
- groups.set(n.reason, { count: 1, detail: n.detail, first: time, last: time });
415
- }
416
- }
417
- const lines = [...groups.values()].map((g) => {
418
- const span = g.first === g.last ? g.first : `${g.first}\u2013${g.last}`;
419
- const plural = g.count === 1 ? "turn" : "turns";
420
- return `- ${g.count} ${plural} failed (${span}): ${g.detail}`;
421
- });
422
- blocks.push(`${NOTICE_HEADER}
423
- ${lines.join("\n")}`);
424
- }
425
- if (budgets.length > 0) {
426
- const lines = budgets.map((n) => `- ${localHM(n.created_at)} ${n.detail}`);
427
- blocks.push(`[Budget]
428
- ${lines.join("\n")}`);
429
- }
430
- if (extensions.length > 0) {
431
- const byExt = /* @__PURE__ */ new Map();
432
- for (const n of extensions) {
433
- const arr = byExt.get(n.reason);
434
- if (arr) arr.push(n);
435
- else byExt.set(n.reason, [n]);
436
- }
437
- for (const [ext, items] of byExt) {
438
- const header = `[${ext.charAt(0).toUpperCase()}${ext.slice(1)}]`;
439
- const lines = items.map((n) => `- ${localHM(n.created_at)} ${n.detail}`);
440
- blocks.push(`${header}
441
- ${lines.join("\n")}`);
442
- }
443
- }
444
- return blocks.join("\n\n");
445
- }
446
- function localHM(createdAt) {
447
- const iso = createdAt.endsWith("Z") ? createdAt : `${createdAt.replace(" ", "T")}Z`;
448
- return new Date(iso).toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" });
449
- }
450
-
451
358
  // packages/daemon/src/lib/daemon/restart-tracker.ts
452
359
  var DEFAULT_MAX_ATTEMPTS = 5;
453
360
  var DEFAULT_BASE_DELAY = 3e3;
@@ -808,7 +715,7 @@ var MindManager = class {
808
715
  while (recentStderr.length > 20) recentStderr.shift();
809
716
  });
810
717
  try {
811
- await new Promise((resolve9, reject) => {
718
+ await new Promise((resolve10, reject) => {
812
719
  let settled = false;
813
720
  const deadline = Date.now() + 3e4;
814
721
  const onExit = (code) => {
@@ -838,7 +745,7 @@ var MindManager = class {
838
745
  const { ok } = await checkHealth(port);
839
746
  if (settled) return;
840
747
  if (ok) {
841
- finish(() => resolve9());
748
+ finish(() => resolve10());
842
749
  return;
843
750
  }
844
751
  if (Date.now() >= deadline) {
@@ -938,7 +845,7 @@ var MindManager = class {
938
845
  if (this.shuttingDown || this.stopping.has(name)) return;
939
846
  mlog.error(`mind ${name} exited with code ${code}`);
940
847
  try {
941
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-3NA7ZJP3.js");
848
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Z27R3WTW.js");
942
849
  const sleepMgr = getSleepManagerIfReady2();
943
850
  const sleepState = sleepMgr?.getState(name);
944
851
  if (sleepState?.sleeping) {
@@ -968,7 +875,7 @@ var MindManager = class {
968
875
  (err) => mlog.warn(`failed to clear turn state for ${name} after crash`, logger_default.errorData(err))
969
876
  );
970
877
  try {
971
- const { getDeliveryManager: getDeliveryManager2 } = await import("./delivery-manager-TN5KK2AP.js");
878
+ const { getDeliveryManager: getDeliveryManager2 } = await import("./delivery-manager-HZTT5SJR.js");
972
879
  getDeliveryManager2().clearMindSessions(name);
973
880
  } catch (err) {
974
881
  if (!(err instanceof Error && err.message.includes("not initialized"))) {
@@ -1006,23 +913,23 @@ var MindManager = class {
1006
913
  this.stopping.add(name);
1007
914
  const { child } = tracked;
1008
915
  this.minds.delete(name);
1009
- await new Promise((resolve9) => {
916
+ await new Promise((resolve10) => {
1010
917
  const killTimer = setTimeout(() => {
1011
918
  try {
1012
919
  process.kill(-child.pid, "SIGKILL");
1013
920
  } catch {
1014
921
  }
1015
- resolve9();
922
+ resolve10();
1016
923
  }, 5e3);
1017
924
  child.on("exit", () => {
1018
925
  clearTimeout(killTimer);
1019
- resolve9();
926
+ resolve10();
1020
927
  });
1021
928
  try {
1022
929
  process.kill(-child.pid, "SIGTERM");
1023
930
  } catch {
1024
931
  clearTimeout(killTimer);
1025
- resolve9();
932
+ resolve10();
1026
933
  }
1027
934
  });
1028
935
  this.stopping.delete(name);
@@ -1034,7 +941,7 @@ var MindManager = class {
1034
941
  mlog.warn(`failed to clear turn state for ${name} on stop`, logger_default.errorData(err));
1035
942
  }
1036
943
  try {
1037
- const { getDeliveryManager: getDeliveryManager2 } = await import("./delivery-manager-TN5KK2AP.js");
944
+ const { getDeliveryManager: getDeliveryManager2 } = await import("./delivery-manager-HZTT5SJR.js");
1038
945
  getDeliveryManager2().clearMindSessions(name);
1039
946
  } catch (err) {
1040
947
  if (!(err instanceof Error && err.message.includes("not initialized"))) {
@@ -1042,7 +949,7 @@ var MindManager = class {
1042
949
  }
1043
950
  }
1044
951
  try {
1045
- const { clearEchoTextCache } = await import("./echo-text-SEQCLGAT.js");
952
+ const { clearEchoTextCache } = await import("./echo-text-H3SH337Q.js");
1046
953
  clearEchoTextCache(name);
1047
954
  } catch (err) {
1048
955
  mlog.debug(`failed to clear echo-text cache for ${name}`, logger_default.errorData(err));
@@ -1126,17 +1033,30 @@ function tryGetMindManager() {
1126
1033
  return instance;
1127
1034
  }
1128
1035
 
1036
+ // packages/daemon/src/lib/daemon/mind-service.ts
1037
+ import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
1038
+ import { resolve as resolve7 } from "path";
1039
+
1129
1040
  // packages/daemon/src/lib/chat/system-channel.ts
1130
1041
  var SYSTEM_CHANNEL_NAME = "system";
1042
+ var SYSTEM_CHANNEL_DESCRIPTION = "The commons \u2014 a shared room for every mind and the spirit on this system. Think out loud, check in, riff, coordinate.";
1131
1043
  var cachedChannelId = null;
1132
1044
  async function ensureSystemChannel() {
1133
1045
  if (cachedChannelId) return cachedChannelId;
1134
1046
  const existing = await getChannelByName(SYSTEM_CHANNEL_NAME);
1135
1047
  if (existing) {
1136
1048
  cachedChannelId = existing.id;
1049
+ const settings = await getChannelSettings(SYSTEM_CHANNEL_NAME);
1050
+ if (settings && settings.description == null) {
1051
+ await updateChannelSettings(SYSTEM_CHANNEL_NAME, {
1052
+ description: SYSTEM_CHANNEL_DESCRIPTION
1053
+ });
1054
+ }
1137
1055
  return existing.id;
1138
1056
  }
1139
- const conv = await createChannel(SYSTEM_CHANNEL_NAME);
1057
+ const conv = await createChannel(SYSTEM_CHANNEL_NAME, void 0, {
1058
+ description: SYSTEM_CHANNEL_DESCRIPTION
1059
+ });
1140
1060
  cachedChannelId = conv.id;
1141
1061
  logger_default.info("created #system channel");
1142
1062
  return conv.id;
@@ -1149,6 +1069,25 @@ async function joinSystemChannelForMind(mindName) {
1149
1069
  const user = await getOrCreateMindUser(mindName);
1150
1070
  await joinSystemChannel(user.id);
1151
1071
  }
1072
+ async function joinSystemChannelForSpirit() {
1073
+ const user = await getOrCreateSystemUser();
1074
+ await joinSystemChannel(user.id);
1075
+ }
1076
+ async function backfillSystemChannelMembers() {
1077
+ const entries = await readRegistry();
1078
+ for (const entry of entries) {
1079
+ if (entry.stage === "seed") continue;
1080
+ try {
1081
+ if (entry.mindType === "spirit") {
1082
+ await joinSystemChannelForSpirit();
1083
+ } else {
1084
+ await joinSystemChannelForMind(entry.name);
1085
+ }
1086
+ } catch (err) {
1087
+ logger_default.error(`failed to backfill ${entry.name} into #system`, logger_default.errorData(err));
1088
+ }
1089
+ }
1090
+ }
1152
1091
  async function announceToSystem(text) {
1153
1092
  const channelId = await ensureSystemChannel();
1154
1093
  const systemUser = await getOrCreateSystemUser();
@@ -1178,7 +1117,7 @@ import { dirname, resolve as resolve4 } from "path";
1178
1117
 
1179
1118
  // packages/daemon/src/web/middleware/auth.ts
1180
1119
  import { timingSafeEqual } from "crypto";
1181
- import { eq as eq2, lt } from "drizzle-orm";
1120
+ import { eq, lt } from "drizzle-orm";
1182
1121
  import { getCookie } from "hono/cookie";
1183
1122
  import { createMiddleware } from "hono/factory";
1184
1123
  var MIND_USER_CACHE_TTL = 5 * 60 * 1e3;
@@ -1206,14 +1145,14 @@ async function createSession(userId) {
1206
1145
  async function deleteSession(sessionId) {
1207
1146
  sessionCache.delete(sessionId);
1208
1147
  const db = await getDb();
1209
- await db.delete(sessions).where(eq2(sessions.id, sessionId));
1148
+ await db.delete(sessions).where(eq(sessions.id, sessionId));
1210
1149
  }
1211
1150
  async function getSessionUserId(sessionId) {
1212
1151
  const db = await getDb();
1213
- const row = await db.select().from(sessions).where(eq2(sessions.id, sessionId)).get();
1152
+ const row = await db.select().from(sessions).where(eq(sessions.id, sessionId)).get();
1214
1153
  if (!row) return void 0;
1215
1154
  if (Date.now() - row.createdAt > SESSION_MAX_AGE) {
1216
- await db.delete(sessions).where(eq2(sessions.id, sessionId));
1155
+ await db.delete(sessions).where(eq(sessions.id, sessionId));
1217
1156
  return void 0;
1218
1157
  }
1219
1158
  return row.userId;
@@ -1734,7 +1673,7 @@ function resolveSkillsDir(manifest) {
1734
1673
  async function discoverBuiltinExtensions(disabledIds) {
1735
1674
  const builtins = [
1736
1675
  { id: "notes", load: async () => (await import("./src-YH6PQ7LJ.js")).default },
1737
- { id: "pages", load: async () => (await import("./src-OJHARHTF.js")).default },
1676
+ { id: "pages", load: async () => (await import("./src-WLJE73NP.js")).default },
1738
1677
  { id: "plan", load: async () => (await import("./src-JAOVXO5W.js")).default }
1739
1678
  ];
1740
1679
  const results = [];
@@ -2467,10 +2406,17 @@ var Scheduler = class {
2467
2406
  ${stderr}` : ""}`;
2468
2407
  slog2.warn(`script "${schedule.id}" failed for ${mindName}`, logger_default.errorData(err));
2469
2408
  }
2409
+ } else if (Array.isArray(schedule.messages) && schedule.messages.length > 0) {
2410
+ const pick = schedule.messages[Math.floor(Math.random() * schedule.messages.length)];
2411
+ if (typeof pick !== "string" || !pick.trim()) {
2412
+ slog2.warn(`schedule "${schedule.id}" for ${mindName} has a malformed messages pool`);
2413
+ return;
2414
+ }
2415
+ text = pick;
2470
2416
  } else if (schedule.message) {
2471
2417
  text = schedule.message;
2472
2418
  } else {
2473
- slog2.warn(`schedule "${schedule.id}" for ${mindName} has no message or script`);
2419
+ slog2.warn(`schedule "${schedule.id}" for ${mindName} has no message, messages, or script`);
2474
2420
  return;
2475
2421
  }
2476
2422
  await this.deliverSystem(mindName, `[${schedule.id}] ${text}`, {
@@ -2790,6 +2736,9 @@ async function startMindFull(name) {
2790
2736
  summary: `${name} started`
2791
2737
  }).catch((err) => logger_default.error("failed to publish mind_started activity", logger_default.errorData(err)));
2792
2738
  if (entry?.parent) return;
2739
+ recordMissingCredentialsNotice(baseName, entry?.template).catch(
2740
+ (err) => logger_default.error(`failed to check credentials for ${baseName}`, logger_default.errorData(err))
2741
+ );
2793
2742
  if (!entry || entry.stage === "seed") {
2794
2743
  if (entry?.stage === "seed") {
2795
2744
  sendSeedOrientation(baseName, entry.createdBy).catch(
@@ -2834,6 +2783,31 @@ async function startMindFull(name) {
2834
2783
  }
2835
2784
  notifyExtensionsMindStart(baseName);
2836
2785
  }
2786
+ async function recordMissingCredentialsNotice(mind, template) {
2787
+ const { hasUndeliveredNotice, recordNotice: recordNotice2, MIND_LEVEL_SESSION: MIND_LEVEL_SESSION2 } = await import("./notices-2KU5NTRY.js");
2788
+ const warning = await missingCredentialWarning(template, readMindModel(mind, template), mind);
2789
+ if (!warning) return;
2790
+ if (await hasUndeliveredNotice(mind, "no_credentials")) return;
2791
+ await recordNotice2({
2792
+ mind,
2793
+ session: MIND_LEVEL_SESSION2,
2794
+ kind: "startup",
2795
+ reason: "no_credentials",
2796
+ detail: warning
2797
+ });
2798
+ }
2799
+ function readMindModel(mind, template) {
2800
+ if (template !== "pi") return void 0;
2801
+ try {
2802
+ const configPath2 = resolve7(mindDir(mind), "home/.config/config.json");
2803
+ if (!existsSync8(configPath2)) return void 0;
2804
+ const model = JSON.parse(readFileSync7(configPath2, "utf-8")).model;
2805
+ return typeof model === "string" ? model : void 0;
2806
+ } catch (err) {
2807
+ logger_default.warn(`failed to read model for ${mind}`, logger_default.errorData(err));
2808
+ return void 0;
2809
+ }
2810
+ }
2837
2811
  async function sleepMind(name) {
2838
2812
  markIdle(name);
2839
2813
  await getMindManager().stopMind(name);
@@ -2858,6 +2832,9 @@ async function startSpiritFull(name) {
2858
2832
  registerMindDir(name, entry.dir);
2859
2833
  }
2860
2834
  await getMindManager().startMind(name);
2835
+ joinSystemChannelForSpirit().catch(
2836
+ (err) => logger_default.error(`failed to join #system for ${name}`, logger_default.errorData(err))
2837
+ );
2861
2838
  getScheduler().loadSchedules(name, entry?.dir ?? spiritDir());
2862
2839
  publish({
2863
2840
  type: "mind_started",
@@ -2987,7 +2964,7 @@ var SleepManager = class {
2987
2964
  transitioning = /* @__PURE__ */ new Set();
2988
2965
  sleepConfigs = /* @__PURE__ */ new Map();
2989
2966
  get statePath() {
2990
- return resolve7(voluteSystemDir(), "sleep-state.json");
2967
+ return resolve8(voluteSystemDir(), "sleep-state.json");
2991
2968
  }
2992
2969
  start() {
2993
2970
  this.loadState();
@@ -3003,8 +2980,8 @@ var SleepManager = class {
3003
2980
  // --- State persistence ---
3004
2981
  loadState() {
3005
2982
  try {
3006
- if (existsSync8(this.statePath)) {
3007
- const data = JSON.parse(readFileSync7(this.statePath, "utf-8"));
2983
+ if (existsSync9(this.statePath)) {
2984
+ const data = JSON.parse(readFileSync8(this.statePath, "utf-8"));
3008
2985
  for (const [name, state2] of Object.entries(data)) {
3009
2986
  state2.triggerWakeHistory ??= [];
3010
2987
  state2.wakeFailures ??= 0;
@@ -3295,7 +3272,7 @@ var SleepManager = class {
3295
3272
  async flushQueuedMessages(name) {
3296
3273
  try {
3297
3274
  const db = await getDb();
3298
- const rows = await db.select().from(deliveryQueue).where(and2(eq3(deliveryQueue.mind, name), eq3(deliveryQueue.status, "sleep-queued"))).all();
3275
+ const rows = await db.select().from(deliveryQueue).where(and(eq2(deliveryQueue.mind, name), eq2(deliveryQueue.status, "sleep-queued"))).all();
3299
3276
  if (rows.length === 0) return 0;
3300
3277
  const groups = /* @__PURE__ */ new Map();
3301
3278
  for (const row of rows) {
@@ -3307,7 +3284,7 @@ var SleepManager = class {
3307
3284
  `dropping unparseable queued message ${row.id} for ${name}`,
3308
3285
  logger_default.errorData(err)
3309
3286
  );
3310
- await db.delete(deliveryQueue).where(eq3(deliveryQueue.id, row.id));
3287
+ await db.delete(deliveryQueue).where(eq2(deliveryQueue.id, row.id));
3311
3288
  continue;
3312
3289
  }
3313
3290
  const channel = payload.channel ?? "unknown";
@@ -3350,7 +3327,7 @@ var SleepManager = class {
3350
3327
  * the real delivery stack. Returns whether the batch was handed off to the mind.
3351
3328
  */
3352
3329
  async deliverQueuedBatch(name, payloads) {
3353
- const { deliverBatch: deliverBatch2 } = await import("./message-delivery-ZE3YGJDD.js");
3330
+ const { deliverBatch: deliverBatch2 } = await import("./message-delivery-GPQ5SE5N.js");
3354
3331
  return deliverBatch2(name, payloads);
3355
3332
  }
3356
3333
  // --- Wake failure handling (#419) ---
@@ -3528,17 +3505,17 @@ var SleepManager = class {
3528
3505
  }
3529
3506
  }
3530
3507
  async waitForIdle(name, timeoutMs) {
3531
- return new Promise((resolve9) => {
3508
+ return new Promise((resolve10) => {
3532
3509
  const timeout = setTimeout(() => {
3533
3510
  unsub();
3534
- resolve9();
3511
+ resolve10();
3535
3512
  }, timeoutMs);
3536
3513
  const unsub = subscribe((event) => {
3537
3514
  if (event.mind !== name) return;
3538
3515
  if (event.type === "mind_done" || event.type === "mind_idle") {
3539
3516
  clearTimeout(timeout);
3540
3517
  unsub();
3541
- resolve9();
3518
+ resolve10();
3542
3519
  }
3543
3520
  });
3544
3521
  });
@@ -3546,15 +3523,15 @@ var SleepManager = class {
3546
3523
  async archiveSessions(name) {
3547
3524
  const dir = mindDir(name);
3548
3525
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 16);
3549
- const sessionsDir = resolve7(dir, ".mind", "sessions");
3550
- if (existsSync8(sessionsDir)) {
3551
- const archiveDir = resolve7(sessionsDir, "archive");
3526
+ const sessionsDir = resolve8(dir, ".mind", "sessions");
3527
+ if (existsSync9(sessionsDir)) {
3528
+ const archiveDir = resolve8(sessionsDir, "archive");
3552
3529
  mkdirSync5(archiveDir, { recursive: true });
3553
3530
  for (const file of readdirSync2(sessionsDir)) {
3554
3531
  if (file === "archive" || !file.endsWith(".json")) continue;
3555
- const src = resolve7(sessionsDir, file);
3532
+ const src = resolve8(sessionsDir, file);
3556
3533
  const base = file.replace(/\.json$/, "");
3557
- const dest = resolve7(archiveDir, `${base}-${timestamp}.json`);
3534
+ const dest = resolve8(archiveDir, `${base}-${timestamp}.json`);
3558
3535
  try {
3559
3536
  renameSync(src, dest);
3560
3537
  } catch (err) {
@@ -3562,14 +3539,14 @@ var SleepManager = class {
3562
3539
  }
3563
3540
  }
3564
3541
  }
3565
- const piSessionsDir = resolve7(dir, ".mind", "pi-sessions");
3566
- if (existsSync8(piSessionsDir)) {
3567
- const archiveDir = resolve7(piSessionsDir, "archive");
3542
+ const piSessionsDir = resolve8(dir, ".mind", "pi-sessions");
3543
+ if (existsSync9(piSessionsDir)) {
3544
+ const archiveDir = resolve8(piSessionsDir, "archive");
3568
3545
  mkdirSync5(archiveDir, { recursive: true });
3569
3546
  for (const entry of readdirSync2(piSessionsDir, { withFileTypes: true })) {
3570
3547
  if (entry.name === "archive" || !entry.isDirectory()) continue;
3571
- const src = resolve7(piSessionsDir, entry.name);
3572
- const dest = resolve7(archiveDir, `${entry.name}-${timestamp}`);
3548
+ const src = resolve8(piSessionsDir, entry.name);
3549
+ const dest = resolve8(archiveDir, `${entry.name}-${timestamp}`);
3573
3550
  try {
3574
3551
  renameSync(src, dest);
3575
3552
  } catch (err) {
@@ -3579,8 +3556,8 @@ var SleepManager = class {
3579
3556
  }
3580
3557
  }
3581
3558
  async runWakeContextScript(name, sleepingSince, duration) {
3582
- const scriptPath = resolve7(mindDir(name), "home", ".local", "hooks", "wake-context.sh");
3583
- if (!existsSync8(scriptPath)) return "";
3559
+ const scriptPath = resolve8(mindDir(name), "home", ".local", "hooks", "wake-context.sh");
3560
+ if (!existsSync9(scriptPath)) return "";
3584
3561
  const input = JSON.stringify({
3585
3562
  sleepingSince,
3586
3563
  duration,
@@ -3630,7 +3607,7 @@ var SleepManager = class {
3630
3607
  async buildQueuedSummary(name) {
3631
3608
  try {
3632
3609
  const db = await getDb();
3633
- const rows = await db.select({ channel: deliveryQueue.channel, sender: deliveryQueue.sender }).from(deliveryQueue).where(and2(eq3(deliveryQueue.mind, name), eq3(deliveryQueue.status, "sleep-queued"))).all();
3610
+ const rows = await db.select({ channel: deliveryQueue.channel, sender: deliveryQueue.sender }).from(deliveryQueue).where(and(eq2(deliveryQueue.mind, name), eq2(deliveryQueue.status, "sleep-queued"))).all();
3634
3611
  if (rows.length === 0) return "No messages arrived while you slept.";
3635
3612
  const channelCounts = /* @__PURE__ */ new Map();
3636
3613
  const senders = /* @__PURE__ */ new Set();
@@ -3677,7 +3654,7 @@ var SleepManager = class {
3677
3654
  } catch {
3678
3655
  try {
3679
3656
  const portHex = port.toString(16).toUpperCase().padStart(4, "0");
3680
- const tcp6 = readFileSync7("/proc/net/tcp6", "utf-8");
3657
+ const tcp6 = readFileSync8("/proc/net/tcp6", "utf-8");
3681
3658
  for (const line of tcp6.split("\n")) {
3682
3659
  if (!line.includes(`:${portHex} `)) continue;
3683
3660
  const fields = line.trim().split(/\s+/);
@@ -3746,8 +3723,8 @@ function getSleepManagerIfReady() {
3746
3723
 
3747
3724
  // packages/daemon/src/lib/delivery/delivery-manager.ts
3748
3725
  import { realpath } from "fs/promises";
3749
- import { resolve as resolve8 } from "path";
3750
- import { and as and4, eq as eq5, inArray as inArray2, sql as sql2 } from "drizzle-orm";
3726
+ import { resolve as resolve9 } from "path";
3727
+ import { and as and3, eq as eq4, inArray as inArray2, sql } from "drizzle-orm";
3751
3728
 
3752
3729
  // packages/daemon/src/lib/chat/typing.ts
3753
3730
  var DEFAULT_TTL_MS = 1e4;
@@ -3841,7 +3818,7 @@ function publishTypingForChannels(channels, map) {
3841
3818
  }
3842
3819
 
3843
3820
  // packages/daemon/src/lib/delivery/send-gate.ts
3844
- import { and as and3, asc as asc2, desc, eq as eq4, gt } from "drizzle-orm";
3821
+ import { and as and2, asc, desc, eq as eq3, gt } from "drizzle-orm";
3845
3822
  var state = /* @__PURE__ */ new Map();
3846
3823
  function extractText(raw) {
3847
3824
  if (!raw) return "";
@@ -3856,7 +3833,7 @@ function extractText(raw) {
3856
3833
  }
3857
3834
  async function maxMessageId(conversationId) {
3858
3835
  const db = await getDb();
3859
- const rows = await db.select({ id: messages.id }).from(messages).where(eq4(messages.conversation_id, conversationId)).orderBy(desc(messages.id)).limit(1);
3836
+ const rows = await db.select({ id: messages.id }).from(messages).where(eq3(messages.conversation_id, conversationId)).orderBy(desc(messages.id)).limit(1);
3860
3837
  return rows[0]?.id ?? 0;
3861
3838
  }
3862
3839
  async function onDeliveredToMind(mindBase, conversationId) {
@@ -3875,7 +3852,7 @@ async function checkStaleSend(mindBase, conversationId, excludeSenders) {
3875
3852
  const entry = state.get(mindBase)?.get(conversationId);
3876
3853
  if (!entry?.turnOpen || entry.heldThisTurn) return { held: false };
3877
3854
  const db = await getDb();
3878
- const rows = await db.select({ id: messages.id, sender: messages.sender_name, content: messages.content }).from(messages).where(and3(eq4(messages.conversation_id, conversationId), gt(messages.id, entry.baselineId))).orderBy(asc2(messages.id));
3855
+ const rows = await db.select({ id: messages.id, sender: messages.sender_name, content: messages.content }).from(messages).where(and2(eq3(messages.conversation_id, conversationId), gt(messages.id, entry.baselineId))).orderBy(asc(messages.id));
3879
3856
  const excluded = new Set(excludeSenders.filter(Boolean));
3880
3857
  const unseen = rows.filter((r) => r.sender && !excluded.has(r.sender));
3881
3858
  if (unseen.length === 0) return { held: false };
@@ -3936,7 +3913,7 @@ var DeliveryManager = class {
3936
3913
  isMindRunning = (name) => tryGetMindManager()?.isRunning(name) ?? false;
3937
3914
  /** Sends a system message to a mind (invites, release summaries); overridable in tests. */
3938
3915
  notify = async (mindName, text) => {
3939
- const { sendSystemMessage: sendSystemMessage2 } = await import("./system-chat-N2F7HVY3.js");
3916
+ const { sendSystemMessage: sendSystemMessage2 } = await import("./system-chat-63ABFF6V.js");
3940
3917
  await sendSystemMessage2(mindName, text);
3941
3918
  };
3942
3919
  constructor() {
@@ -4070,9 +4047,9 @@ var DeliveryManager = class {
4070
4047
  try {
4071
4048
  const db = await getDb();
4072
4049
  rows = await db.select().from(deliveryQueue).where(
4073
- and4(
4074
- eq5(deliveryQueue.status, "pending"),
4075
- sql2`(${deliveryQueue.next_attempt_at} IS NULL OR ${deliveryQueue.next_attempt_at} <= datetime('now'))`
4050
+ and3(
4051
+ eq4(deliveryQueue.status, "pending"),
4052
+ sql`(${deliveryQueue.next_attempt_at} IS NULL OR ${deliveryQueue.next_attempt_at} <= datetime('now'))`
4076
4053
  )
4077
4054
  ).orderBy(deliveryQueue.id).limit(REDRIVE_BATCH_LIMIT);
4078
4055
  } catch (err) {
@@ -4132,7 +4109,7 @@ var DeliveryManager = class {
4132
4109
  let rows;
4133
4110
  try {
4134
4111
  const db = await getDb();
4135
- rows = await db.select().from(deliveryQueue).where(and4(eq5(deliveryQueue.mind, baseName), eq5(deliveryQueue.status, "gated")));
4112
+ rows = await db.select().from(deliveryQueue).where(and3(eq4(deliveryQueue.mind, baseName), eq4(deliveryQueue.status, "gated")));
4136
4113
  } catch (err) {
4137
4114
  dlog.warn(`failed to read gated rows for ${baseName}`, logger_default.errorData(err));
4138
4115
  return;
@@ -4202,7 +4179,7 @@ var DeliveryManager = class {
4202
4179
  try {
4203
4180
  const db = await getDb();
4204
4181
  for (const p of promote) {
4205
- await db.update(deliveryQueue).set({ status: "pending", session: p.session, attempts: 0, next_attempt_at: null }).where(eq5(deliveryQueue.id, p.id));
4182
+ await db.update(deliveryQueue).set({ status: "pending", session: p.session, attempts: 0, next_attempt_at: null }).where(eq4(deliveryQueue.id, p.id));
4206
4183
  }
4207
4184
  dlog.info(`released ${promote.length} gated message(s) for ${baseName} after route change`);
4208
4185
  } catch (err) {
@@ -4220,7 +4197,7 @@ var DeliveryManager = class {
4220
4197
  if (!channel) return false;
4221
4198
  try {
4222
4199
  const db = await getDb();
4223
- const rows = await db.select({ state: channelGates.state }).from(channelGates).where(and4(eq5(channelGates.mind, baseName), eq5(channelGates.channel, channel)));
4200
+ const rows = await db.select({ state: channelGates.state }).from(channelGates).where(and3(eq4(channelGates.mind, baseName), eq4(channelGates.channel, channel)));
4224
4201
  return rows[0]?.state === "declined";
4225
4202
  } catch (err) {
4226
4203
  dlog.warn(`failed to read gate state for ${baseName}/${channel}`, logger_default.errorData(err));
@@ -4237,13 +4214,13 @@ var DeliveryManager = class {
4237
4214
  const db = await getDb();
4238
4215
  await db.insert(channelGates).values({ mind: baseName, channel, state: "declined" }).onConflictDoUpdate({
4239
4216
  target: [channelGates.mind, channelGates.channel],
4240
- set: { state: "declined", updated_at: sql2`(datetime('now'))` }
4217
+ set: { state: "declined", updated_at: sql`(datetime('now'))` }
4241
4218
  });
4242
4219
  const archived = await db.update(deliveryQueue).set({ status: "archived" }).where(
4243
- and4(
4244
- eq5(deliveryQueue.mind, baseName),
4245
- eq5(deliveryQueue.channel, channel),
4246
- eq5(deliveryQueue.status, "gated")
4220
+ and3(
4221
+ eq4(deliveryQueue.mind, baseName),
4222
+ eq4(deliveryQueue.channel, channel),
4223
+ eq4(deliveryQueue.status, "gated")
4247
4224
  )
4248
4225
  ).returning({ id: deliveryQueue.id });
4249
4226
  dlog.info(
@@ -4273,7 +4250,7 @@ var DeliveryManager = class {
4273
4250
  */
4274
4251
  async getPending(mindName) {
4275
4252
  const db = await getDb();
4276
- const rows = await db.select().from(deliveryQueue).where(and4(eq5(deliveryQueue.mind, mindName), eq5(deliveryQueue.status, "gated")));
4253
+ const rows = await db.select().from(deliveryQueue).where(and3(eq4(deliveryQueue.mind, mindName), eq4(deliveryQueue.status, "gated")));
4277
4254
  const byChannel = /* @__PURE__ */ new Map();
4278
4255
  for (const row of rows) {
4279
4256
  const ch = row.channel ?? "unknown";
@@ -4443,7 +4420,7 @@ var DeliveryManager = class {
4443
4420
  const backoffSec = Math.round(
4444
4421
  Math.min(RETRY_MAX_MS, RETRY_BASE_MS * 2 ** Math.min(attempts, 20)) / 1e3
4445
4422
  );
4446
- await db.update(deliveryQueue).set({ attempts, next_attempt_at: sql2`datetime('now', ${`+${backoffSec} seconds`})` }).where(eq5(deliveryQueue.id, row.id));
4423
+ await db.update(deliveryQueue).set({ attempts, next_attempt_at: sql`datetime('now', ${`+${backoffSec} seconds`})` }).where(eq4(deliveryQueue.id, row.id));
4447
4424
  }
4448
4425
  } catch (err) {
4449
4426
  dlog.warn("failed to schedule delivery retry", logger_default.errorData(err));
@@ -4672,10 +4649,10 @@ var DeliveryManager = class {
4672
4649
  if (declined) return;
4673
4650
  try {
4674
4651
  const db = await getDb();
4675
- const rows = await db.select({ count: sql2`count(*)` }).from(deliveryQueue).where(
4676
- and4(
4677
- eq5(deliveryQueue.mind, baseName),
4678
- eq5(deliveryQueue.channel, payload.channel),
4652
+ const rows = await db.select({ count: sql`count(*)` }).from(deliveryQueue).where(
4653
+ and3(
4654
+ eq4(deliveryQueue.mind, baseName),
4655
+ eq4(deliveryQueue.channel, payload.channel),
4679
4656
  inArray2(deliveryQueue.status, ["gated", "archived"])
4680
4657
  )
4681
4658
  );
@@ -4777,8 +4754,8 @@ var DeliveryManager = class {
4777
4754
  const dir = mindDir(p.username);
4778
4755
  const config = readVoluteConfig(dir);
4779
4756
  if (!config?.profile?.avatar) continue;
4780
- filePath = resolve8(dir, "home", config.profile.avatar);
4781
- const homeDir = resolve8(dir, "home");
4757
+ filePath = resolve9(dir, "home", config.profile.avatar);
4758
+ const homeDir = resolve9(dir, "home");
4782
4759
  if (!filePath.startsWith(`${homeDir}/`)) {
4783
4760
  dlog.warn(`avatar path for ${p.username} escapes home directory, skipping`);
4784
4761
  continue;
@@ -4797,7 +4774,7 @@ var DeliveryManager = class {
4797
4774
  throw err;
4798
4775
  }
4799
4776
  } else {
4800
- filePath = resolve8(voluteHome(), "avatars", p.avatar);
4777
+ filePath = resolve9(voluteHome(), "avatars", p.avatar);
4801
4778
  }
4802
4779
  const rendered = await renderAvatarBlock(filePath, p.username);
4803
4780
  if (rendered) blocks.push(...rendered);
@@ -4925,7 +4902,7 @@ async function linkToolResultToTurn(mind, turnId, toolResultContent, toolUseEven
4925
4902
  content: mindHistory.content,
4926
4903
  message_id: mindHistory.message_id,
4927
4904
  turn_id: mindHistory.turn_id
4928
- }).from(mindHistory).where(and5(eq6(mindHistory.id, outboundId), eq6(mindHistory.mind, mind))).limit(1);
4905
+ }).from(mindHistory).where(and4(eq5(mindHistory.id, outboundId), eq5(mindHistory.mind, mind))).limit(1);
4929
4906
  const row = rows[0];
4930
4907
  if (!row) {
4931
4908
  dlog2.warn(`outbound marker references missing record: mind=${mind} id=${outboundId}`);
@@ -4933,13 +4910,13 @@ async function linkToolResultToTurn(mind, turnId, toolResultContent, toolUseEven
4933
4910
  }
4934
4911
  const alreadyTagged = row.turn_id != null;
4935
4912
  if (!alreadyTagged) {
4936
- await db.update(mindHistory).set({ turn_id: turnId }).where(eq6(mindHistory.id, outboundId));
4913
+ await db.update(mindHistory).set({ turn_id: turnId }).where(eq5(mindHistory.id, outboundId));
4937
4914
  }
4938
4915
  if (row.message_id) {
4939
4916
  await db.update(messages).set({
4940
4917
  turn_id: turnId,
4941
4918
  ...toolUseEventId != null ? { source_event_id: toolUseEventId } : {}
4942
- }).where(eq6(messages.id, Number(row.message_id)));
4919
+ }).where(eq5(messages.id, Number(row.message_id)));
4943
4920
  }
4944
4921
  if (!alreadyTagged) {
4945
4922
  publish3(mind, {
@@ -5128,7 +5105,7 @@ async function spiritWillHandle() {
5128
5105
  const spiritEntry = await findMind(SPIRIT_NAME);
5129
5106
  if (spiritEntry?.running && spiritEntry.mindType === "spirit") return true;
5130
5107
  try {
5131
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-3NA7ZJP3.js");
5108
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Z27R3WTW.js");
5132
5109
  const sm = getSleepManagerIfReady2();
5133
5110
  if (sm?.isSleeping(SPIRIT_NAME)) return true;
5134
5111
  } catch (err) {
@@ -5156,7 +5133,7 @@ async function generateSystemFallbackReply(conversationId, mindName, message) {
5156
5133
  if (config.sleep.schedule?.wake) contextParts.push(`Wake cron: ${config.sleep.schedule.wake}`);
5157
5134
  }
5158
5135
  try {
5159
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-3NA7ZJP3.js");
5136
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-Z27R3WTW.js");
5160
5137
  const sm = getSleepManagerIfReady2();
5161
5138
  if (sm) {
5162
5139
  const state2 = sm.getState(mindName);
@@ -5210,10 +5187,6 @@ export {
5210
5187
  checkHealth,
5211
5188
  RotatingLog,
5212
5189
  syncProviderToMinds,
5213
- recordNotice,
5214
- drainNotices,
5215
- clearDeliveredNotices,
5216
- formatNotices,
5217
5190
  RestartTracker,
5218
5191
  getTypingMap,
5219
5192
  isConversationId,
@@ -5262,6 +5235,7 @@ export {
5262
5235
  initTokenBudget,
5263
5236
  getTokenBudget,
5264
5237
  startMindFull,
5238
+ recordMissingCredentialsNotice,
5265
5239
  sleepMind,
5266
5240
  wakeMind,
5267
5241
  startSpiritFull,
@@ -5281,5 +5255,6 @@ export {
5281
5255
  deliverBatch,
5282
5256
  ensureSystemChannel,
5283
5257
  joinSystemChannel,
5258
+ backfillSystemChannelMembers,
5284
5259
  announceToSystem
5285
5260
  };