volute 0.54.0 → 0.55.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 (135) hide show
  1. package/dist/{activity-events-LQII6PZS.js → activity-events-TFAJBNBW.js} +2 -2
  2. package/dist/{ai-service-YW5SWCSB.js → ai-service-KEK2V3AP.js} +2 -2
  3. package/dist/{auth-KRDSM55Q.js → auth-Y27LTNZK.js} +3 -3
  4. package/dist/auto-upgrade-2MZF7NG3.js +46 -0
  5. package/dist/{avatar-image-52WGXLHV.js → avatar-image-SN576P45.js} +2 -2
  6. package/dist/{backup-QRNX6RK7.js → backup-GDCWH6MC.js} +2 -2
  7. package/dist/{channels-CKCY64TD.js → channels-AFJWGX7W.js} +15 -15
  8. package/dist/{chat-ZUGNL5GS.js → chat-HVPOZK3O.js} +3 -3
  9. package/dist/{chunk-QUSMYGNQ.js → chunk-2674KIGI.js} +1 -0
  10. package/dist/chunk-2GATCSZK.js +520 -0
  11. package/dist/{chunk-LKUGUQUW.js → chunk-3SFKY4GI.js} +4 -4
  12. package/dist/{chunk-CLCHOXLR.js → chunk-45QTYKQQ.js} +4 -4
  13. package/dist/{chunk-PPSN2MLC.js → chunk-4VAQKLMU.js} +7 -4
  14. package/dist/{chunk-TPX6E6PL.js → chunk-6HBGUPBA.js} +2 -2
  15. package/dist/{chunk-UFTDRTCP.js → chunk-7AA4T2RT.js} +2 -2
  16. package/dist/{chunk-56IT2ZXF.js → chunk-BP2X5AIK.js} +8 -14
  17. package/dist/{chunk-444RR3YF.js → chunk-CKOA4LWV.js} +11 -11
  18. package/dist/{chunk-HKGYZVWN.js → chunk-DUV4EMNW.js} +37 -3
  19. package/dist/{chunk-CV6BNGFK.js → chunk-FSXPPOPM.js} +3 -3
  20. package/dist/{chunk-3LHUXY3E.js → chunk-FZUPIS3T.js} +3 -3
  21. package/dist/{chunk-L7BKTZ5U.js → chunk-G3XAB4DK.js} +1 -1
  22. package/dist/{chunk-WHL6PKYP.js → chunk-HLWQ3P3R.js} +49 -45
  23. package/dist/{chunk-OAYY3WF3.js → chunk-HTSWDOJE.js} +0 -11
  24. package/dist/{chunk-OYF25B62.js → chunk-IR2FW4W7.js} +1 -1
  25. package/dist/{chunk-ICXY54ZC.js → chunk-IT4GEFDH.js} +1 -1
  26. package/dist/{chunk-F6D766VQ.js → chunk-KS62IHE2.js} +1 -1
  27. package/dist/{chunk-LNNI3MS4.js → chunk-MNKPAAQF.js} +9 -2
  28. package/dist/{chunk-LGXVGIWN.js → chunk-NCRG4SBR.js} +189 -55
  29. package/dist/{chunk-I7U5EEZC.js → chunk-NM5FDH4T.js} +1 -1
  30. package/dist/{chunk-7LT3YZUR.js → chunk-OFU6WJJZ.js} +1 -1
  31. package/dist/{chunk-OT5SXF7L.js → chunk-OUGD5L5U.js} +26 -12
  32. package/dist/{chunk-X67BDDZR.js → chunk-P3GXOT2X.js} +48 -2
  33. package/dist/{chunk-U54PJPTB.js → chunk-PRZUBJ4K.js} +1 -1
  34. package/dist/{chunk-OGPVJ53N.js → chunk-QVS3C4DK.js} +2 -2
  35. package/dist/{chunk-VDUCLVZI.js → chunk-TMTAHKYP.js} +27 -25
  36. package/dist/{chunk-RGHF3OK5.js → chunk-UEZC5MNB.js} +13 -13
  37. package/dist/{chunk-ATZF2RNJ.js → chunk-VTFXZPC3.js} +12 -12
  38. package/dist/{chunk-YSRYCS3N.js → chunk-W3OIPJPB.js} +1 -1
  39. package/dist/{chunk-5Y54AE3L.js → chunk-XAG53RWY.js} +1 -1
  40. package/dist/{chunk-HTRSSOHY.js → chunk-YU5EYQAE.js} +1 -1
  41. package/dist/{chunk-EGV6R6UF.js → chunk-Z7TNIIHW.js} +3 -1
  42. package/dist/cli.js +8 -8
  43. package/dist/{cloud-sync-52YNJRMR.js → cloud-sync-FM73SVFJ.js} +20 -20
  44. package/dist/{conversations-ZL6PHROD.js → conversations-FH3ODBL7.js} +3 -3
  45. package/dist/{create-G2RIKQYK.js → create-P75ZFTVN.js} +1 -1
  46. package/dist/{daemon-restart-QWHN5VMU.js → daemon-restart-JQMMMITM.js} +1 -1
  47. package/dist/daemon.js +187 -159
  48. package/dist/{db-I4EH5SLF.js → db-JH3NTERX.js} +17 -3
  49. package/dist/{delivery-manager-7R2YIQ2W.js → delivery-manager-H23Q23N7.js} +15 -15
  50. package/dist/{delivery-notices-RZQ6GONP.js → delivery-notices-S7TKOACE.js} +5 -5
  51. package/dist/{delivery-router-QS4NLJR6.js → delivery-router-KHBVEVVL.js} +2 -2
  52. package/dist/echo-text-ULEIFJJF.js +40 -0
  53. package/dist/{extensions-QT65JGV6.js → extensions-QD22GXZD.js} +24 -20
  54. package/dist/{files-PCKBQHAY.js → files-DUGRXN6V.js} +2 -2
  55. package/dist/{import-DB2KULRO.js → import-RDDUGGFI.js} +3 -3
  56. package/dist/message-delivery-LU4EP244.js +46 -0
  57. package/dist/migrate-init-infrastructure-Z72UJ5NT.js +44 -0
  58. package/dist/{migrate-name-placeholder-C7NCNLWF.js → migrate-name-placeholder-64AEAWPE.js} +1 -1
  59. package/dist/{migrate-thread-config-EQSEP2XG.js → migrate-thread-config-SVF2M3D3.js} +1 -1
  60. package/dist/{mind-CT6ANXK4.js → mind-BARCLI7O.js} +4 -4
  61. package/dist/{mind-activity-tracker-QF6DCX2X.js → mind-activity-tracker-UT23RGBF.js} +3 -3
  62. package/dist/mind-service-ZJCUBAUL.js +48 -0
  63. package/dist/{package-F6S5NHY2.js → package-AUDBDKAO.js} +10 -12
  64. package/dist/{prompts-JECJIFPQ.js → prompts-MOBF3TMO.js} +1 -1
  65. package/dist/{sandbox-NNWCTHRI.js → sandbox-VI7XWBIA.js} +2 -2
  66. package/dist/scheduler-GLINVC2B.js +27 -0
  67. package/dist/{seed-DRKAP3XV.js → seed-5JGR7ZRA.js} +1 -1
  68. package/dist/{seed-cmd-6IMTO3LG.js → seed-cmd-M6A7N7F3.js} +2 -2
  69. package/dist/{seed-create-VNLDYRFK.js → seed-create-TGFZW4IO.js} +3 -3
  70. package/dist/{seed-readiness-H5TTPAQH.js → seed-readiness-XBH2MUNA.js} +2 -2
  71. package/dist/{seed-sprout-PPGYGK4G.js → seed-sprout-3IC5ZVTI.js} +7 -7
  72. package/dist/{send-UXUQKO4N.js → send-DHYBAYK4.js} +2 -2
  73. package/dist/{setup-YUAQMDVZ.js → setup-6KAH3GRW.js} +1 -1
  74. package/dist/skills/volute-mind/SKILL.md +8 -0
  75. package/dist/{skills-GMQ5UIIW.js → skills-LKQCYFVP.js} +2 -2
  76. package/dist/sleep-manager-Q3ITFNOJ.js +42 -0
  77. package/dist/{spirit-Q5VGFWUI.js → spirit-FKXMGO3N.js} +5 -5
  78. package/dist/spirit-availability-5R2WYSWF.js +43 -0
  79. package/dist/{sprout-PMTRL7QN.js → sprout-VEW3CUNX.js} +1 -1
  80. package/dist/{src-H3UCOP6B.js → src-246GSX7A.js} +5 -2
  81. package/dist/src-LOUB3WPR.js +4189 -0
  82. package/dist/{system-events-Q7IVZ5T4.js → system-events-ZYOCYAO2.js} +5 -3
  83. package/dist/{tailscale-KHNZFC7L.js → tailscale-F2IMBILZ.js} +1 -1
  84. package/dist/{template-hash-YKWMVYMM.js → template-hash-RJRMF6DT.js} +2 -2
  85. package/dist/{template-staleness-PY2CULH6.js → template-staleness-IBD722PN.js} +4 -4
  86. package/dist/{turn-tracker-HZDPMSCC.js → turn-tracker-BE34OI6O.js} +7 -7
  87. package/dist/{up-XZDSJVMU.js → up-J47J5JRB.js} +1 -1
  88. package/dist/variant-cleanup-JGJZ5KB4.js +24 -0
  89. package/dist/{version-notify-VNVFX6UP.js → version-notify-KIXYNHJC.js} +11 -11
  90. package/dist/web-assets/assets/{index-CwtxGwe_.js → index-CoU1eUKE.js} +15 -15
  91. package/dist/web-assets/assets/index-hPn_fkz3.css +1 -0
  92. package/dist/web-assets/index.html +2 -2
  93. package/package.json +10 -12
  94. package/packages/extensions/intentions/dist/ui/assets/index-Bl5KEcli.js +67 -0
  95. package/packages/extensions/intentions/dist/ui/index.html +1 -1
  96. package/packages/extensions/pages/dist/ui/assets/index-BKxVQkA9.css +1 -0
  97. package/packages/extensions/pages/dist/ui/assets/index-BMt6sStP.js +68 -0
  98. package/packages/extensions/pages/dist/ui/index.html +2 -2
  99. package/packages/extensions/pages/skills/pages/SKILL.md +123 -4
  100. package/templates/_base/.init/.config/prompts.json +0 -1
  101. package/templates/_base/.init/.local/hooks/pre-prompt/turn-context.ts +30 -0
  102. package/templates/_base/src/lib/codex-session-seed.ts +6 -55
  103. package/templates/_base/src/lib/pi-session-seed.ts +8 -57
  104. package/templates/_base/src/lib/seed-note.ts +4 -4
  105. package/templates/_base/src/lib/session-seed.ts +8 -53
  106. package/templates/_base/src/lib/startup.ts +0 -20
  107. package/templates/claude/package.json +2 -2
  108. package/templates/claude/src/agent.ts +34 -102
  109. package/templates/claude/src/lib/hooks/pre-compact.ts +6 -6
  110. package/templates/claude/src/server.ts +0 -1
  111. package/templates/codex/package.json +2 -2
  112. package/templates/codex/src/agent.ts +23 -89
  113. package/templates/pi/package.json +1 -1
  114. package/templates/pi/src/agent.ts +26 -93
  115. package/templates/pi/src/server.ts +0 -1
  116. package/dist/auto-upgrade-HEVZKPTF.js +0 -46
  117. package/dist/chunk-AAPNU7GA.js +0 -168
  118. package/dist/echo-text-73CYQRL7.js +0 -40
  119. package/dist/message-delivery-TRKT4T2P.js +0 -46
  120. package/dist/mind-service-7EFIJ3ZA.js +0 -48
  121. package/dist/scheduler-73Q4MQ7Y.js +0 -27
  122. package/dist/sleep-manager-KHI65FEX.js +0 -42
  123. package/dist/spirit-availability-G5FMWKRH.js +0 -43
  124. package/dist/src-3FIW7DLH.js +0 -2376
  125. package/dist/src-LTTQVN2Z.js +0 -832
  126. package/dist/variant-cleanup-QHGGY7ND.js +0 -24
  127. package/dist/web-assets/assets/index-DhM1yYRN.css +0 -1
  128. package/packages/extensions/intentions/dist/ui/assets/index-CQz4aceM.js +0 -67
  129. package/packages/extensions/notes/dist/ui/assets/index-BBs8pyel.js +0 -67
  130. package/packages/extensions/notes/dist/ui/assets/index-D3cdui42.css +0 -1
  131. package/packages/extensions/notes/dist/ui/index.html +0 -14
  132. package/packages/extensions/notes/skills/notes/SKILL.md +0 -90
  133. package/packages/extensions/pages/dist/ui/assets/index-B589e8Xe.js +0 -2
  134. package/packages/extensions/pages/dist/ui/assets/index-BuXnE-rb.css +0 -1
  135. /package/dist/{chunk-ZNHL5KQJ.js → chunk-OKM67ZWH.js} +0 -0
@@ -1,36 +1,52 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  spiritDir
4
- } from "./chunk-RGHF3OK5.js";
4
+ } from "./chunk-UEZC5MNB.js";
5
5
  import {
6
6
  getScheduler
7
- } from "./chunk-444RR3YF.js";
7
+ } from "./chunk-CKOA4LWV.js";
8
8
  import {
9
9
  getDeliveryManager
10
- } from "./chunk-VDUCLVZI.js";
10
+ } from "./chunk-TMTAHKYP.js";
11
11
  import {
12
12
  getMindManager,
13
13
  resolveMindToken
14
- } from "./chunk-WHL6PKYP.js";
14
+ } from "./chunk-HLWQ3P3R.js";
15
+ import {
16
+ addMessage,
17
+ createChannel,
18
+ createConversation,
19
+ findDMConversation,
20
+ getChannelByName,
21
+ getChannelSettings,
22
+ getParticipants,
23
+ joinChannel,
24
+ updateChannelSettings
25
+ } from "./chunk-6HBGUPBA.js";
26
+ import {
27
+ markIdle
28
+ } from "./chunk-7AA4T2RT.js";
29
+ import {
30
+ readVoluteConfig,
31
+ resolveWakeTriggers
32
+ } from "./chunk-WCFSBH33.js";
15
33
  import {
16
34
  extractTextContent,
17
35
  getRoutingConfig,
18
36
  resolveRoute,
19
37
  shouldGate
20
- } from "./chunk-YSRYCS3N.js";
21
- import {
22
- hashSkillDir,
23
- importSkillFromDir,
24
- removeSharedSkill,
25
- sharedSkillsDir
26
- } from "./chunk-PPSN2MLC.js";
38
+ } from "./chunk-W3OIPJPB.js";
27
39
  import {
28
40
  getOrCreateMindUser,
29
41
  getOrCreateSystemUser,
30
42
  getUser,
31
43
  getUserByUsername,
32
44
  syncMindProfile
33
- } from "./chunk-7LT3YZUR.js";
45
+ } from "./chunk-OFU6WJJZ.js";
46
+ import {
47
+ publish,
48
+ subscribe
49
+ } from "./chunk-PRZUBJ4K.js";
34
50
  import {
35
51
  MIND_LEVEL_THREAD,
36
52
  deliverEvent,
@@ -38,45 +54,30 @@ import {
38
54
  pendingEventCount,
39
55
  pendingEventsLine,
40
56
  recordNotice
41
- } from "./chunk-HKGYZVWN.js";
57
+ } from "./chunk-DUV4EMNW.js";
42
58
  import {
43
59
  publish as publish2
44
- } from "./chunk-LNNI3MS4.js";
60
+ } from "./chunk-MNKPAAQF.js";
45
61
  import {
46
62
  getPrompt
47
- } from "./chunk-OAYY3WF3.js";
63
+ } from "./chunk-HTSWDOJE.js";
48
64
  import {
49
- addMessage,
50
- createChannel,
51
- createConversation,
52
- findDMConversation,
53
- getChannelByName,
54
- getChannelSettings,
55
- getParticipants,
56
- joinChannel,
57
- updateChannelSettings
58
- } from "./chunk-TPX6E6PL.js";
59
- import {
60
- markIdle
61
- } from "./chunk-UFTDRTCP.js";
62
- import {
63
- publish,
64
- subscribe
65
- } from "./chunk-U54PJPTB.js";
66
- import {
67
- readVoluteConfig,
68
- resolveWakeTriggers
69
- } from "./chunk-WCFSBH33.js";
65
+ hashSkillDir,
66
+ importSkillFromDir,
67
+ listSharedSkills,
68
+ removeSharedSkill,
69
+ sharedSkillsDir
70
+ } from "./chunk-4VAQKLMU.js";
70
71
  import {
71
72
  isIsolationEnabled,
72
73
  mindUserName
73
74
  } from "./chunk-OIOW3FPT.js";
74
75
  import {
75
76
  missingCredentialWarning
76
- } from "./chunk-EGV6R6UF.js";
77
+ } from "./chunk-Z7TNIIHW.js";
77
78
  import {
78
79
  logger_default
79
- } from "./chunk-QUSMYGNQ.js";
80
+ } from "./chunk-2674KIGI.js";
80
81
  import {
81
82
  findMind,
82
83
  getBaseName,
@@ -328,6 +329,85 @@ import { promisify } from "util";
328
329
  import { CronExpressionParser } from "cron-parser";
329
330
  import { and as and2, eq as eq3, inArray } from "drizzle-orm";
330
331
 
332
+ // packages/daemon/src/lib/turn-context.ts
333
+ var tlog = logger_default.child("turn-context");
334
+ var TURN_CONTEXT_BUDGET = {
335
+ turn: 1200,
336
+ wake: 3e3
337
+ };
338
+ var PROVIDER_TIMEOUT_MS = 1e3;
339
+ var TOTAL_TIMEOUT_MS = 2e3;
340
+ var SEPARATOR = "\n\n";
341
+ function withTimeout(p, ms) {
342
+ return new Promise((resolve6, reject) => {
343
+ const timer = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);
344
+ p.then(
345
+ (v) => {
346
+ clearTimeout(timer);
347
+ resolve6(v);
348
+ },
349
+ (err) => {
350
+ clearTimeout(timer);
351
+ reject(err);
352
+ }
353
+ );
354
+ });
355
+ }
356
+ async function collectFromProviders(providers, reason, total = TURN_CONTEXT_BUDGET[reason], now = Date.now) {
357
+ if (providers.length === 0 || total <= 0) return null;
358
+ const deadline = now() + TOTAL_TIMEOUT_MS;
359
+ const blocks = [];
360
+ let remaining = total;
361
+ for (let i = 0; i < providers.length; i++) {
362
+ const { id, run } = providers[i];
363
+ if (remaining <= 0) break;
364
+ if (now() >= deadline) {
365
+ tlog.warn(
366
+ `deadline reached before asking ${providers.length - i} remaining extension(s) for ${reason} context`
367
+ );
368
+ break;
369
+ }
370
+ const joinerCost = blocks.length > 0 ? SEPARATOR.length : 0;
371
+ const available = remaining - joinerCost;
372
+ if (available <= 0) break;
373
+ const budget = Math.floor(available / (providers.length - i));
374
+ if (budget <= 0) break;
375
+ let text;
376
+ try {
377
+ text = await withTimeout(run(budget), PROVIDER_TIMEOUT_MS);
378
+ } catch (err) {
379
+ tlog.warn(`extension ${id}: turnContext failed, dropped from this turn`, logger_default.errorData(err));
380
+ continue;
381
+ }
382
+ if (typeof text !== "string") continue;
383
+ const trimmed = text.trim();
384
+ if (!trimmed) continue;
385
+ if (trimmed.length > budget) {
386
+ tlog.warn(
387
+ `extension ${id}: turnContext returned ${trimmed.length} chars over a ${budget} budget \u2014 dropped`
388
+ );
389
+ continue;
390
+ }
391
+ blocks.push(trimmed);
392
+ remaining -= trimmed.length + joinerCost;
393
+ }
394
+ if (blocks.length === 0) return null;
395
+ return blocks.join(SEPARATOR);
396
+ }
397
+ async function collectTurnContext(mindName, reason) {
398
+ try {
399
+ const providers = getTurnContextProviders().map(({ id, manifest, context }) => ({
400
+ id,
401
+ // Non-null: getTurnContextProviders filters to manifests that declare it.
402
+ run: (budget) => manifest.turnContext(mindName, context, { budget, reason })
403
+ }));
404
+ return await collectFromProviders(providers, reason);
405
+ } catch (err) {
406
+ tlog.error(`failed to collect ${reason} context for ${mindName}`, logger_default.errorData(err));
407
+ return null;
408
+ }
409
+ }
410
+
331
411
  // packages/daemon/src/lib/daemon/mind-service.ts
332
412
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
333
413
  import { resolve as resolve3 } from "path";
@@ -642,7 +722,7 @@ async function ensureMailAddress(mindName) {
642
722
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
643
723
  import { mkdir, writeFile } from "fs/promises";
644
724
  import { resolve as resolve2 } from "path";
645
- var tlog = logger_default.child("token-budget");
725
+ var tlog2 = logger_default.child("token-budget");
646
726
  var DEFAULT_BUDGET_PERIOD_MINUTES = 60;
647
727
  var MAX_QUEUE_SIZE = 100;
648
728
  var TokenBudget = class {
@@ -651,7 +731,7 @@ var TokenBudget = class {
651
731
  dirty = /* @__PURE__ */ new Set();
652
732
  start() {
653
733
  this.interval = setInterval(() => {
654
- this.tick().catch((err) => tlog.error("token budget tick failed", logger_default.errorData(err)));
734
+ this.tick().catch((err) => tlog2.error("token budget tick failed", logger_default.errorData(err)));
655
735
  }, 6e4);
656
736
  }
657
737
  async stop() {
@@ -761,7 +841,7 @@ var TokenBudget = class {
761
841
  const queued = this.drain(mind);
762
842
  if (queued.length > 0) {
763
843
  this.replay(mind, queued).catch((err) => {
764
- tlog.warn(`replay error for ${mind}`, logger_default.errorData(err));
844
+ tlog2.warn(`replay error for ${mind}`, logger_default.errorData(err));
765
845
  });
766
846
  }
767
847
  }
@@ -796,7 +876,7 @@ var TokenBudget = class {
796
876
  await writeFile(this.budgetStatePath(mind), `${JSON.stringify(data)}
797
877
  `);
798
878
  } catch (err) {
799
- tlog.warn(`failed to save budget state for ${mind}`, logger_default.errorData(err));
879
+ tlog2.warn(`failed to save budget state for ${mind}`, logger_default.errorData(err));
800
880
  }
801
881
  }
802
882
  loadBudgetState(mind) {
@@ -817,7 +897,7 @@ var TokenBudget = class {
817
897
  // will be overwritten by caller
818
898
  };
819
899
  } catch (err) {
820
- tlog.warn(`failed to load budget state for ${mind}`, logger_default.errorData(err));
900
+ tlog2.warn(`failed to load budget state for ${mind}`, logger_default.errorData(err));
821
901
  return null;
822
902
  }
823
903
  }
@@ -835,9 +915,9 @@ var TokenBudget = class {
835
915
 
836
916
  ${summary}`
837
917
  });
838
- tlog.info(`replayed ${messages2.length} queued message(s) for ${mindName}`);
918
+ tlog2.info(`replayed ${messages2.length} queued message(s) for ${mindName}`);
839
919
  } catch (err) {
840
- tlog.warn(`failed to replay for ${mindName}`, logger_default.errorData(err));
920
+ tlog2.warn(`failed to replay for ${mindName}`, logger_default.errorData(err));
841
921
  const state = this.budgets.get(mindName);
842
922
  if (state) state.queue.push(...messages2);
843
923
  }
@@ -932,7 +1012,7 @@ async function startMindFull(name) {
932
1012
  }
933
1013
  }
934
1014
  async function recordMissingCredentialsNotice(mind, template) {
935
- const { hasUndeliveredEvent, recordNotice: recordNotice2, MIND_LEVEL_THREAD: MIND_LEVEL_THREAD2 } = await import("./system-events-Q7IVZ5T4.js");
1015
+ const { hasUndeliveredEvent, recordNotice: recordNotice2, MIND_LEVEL_THREAD: MIND_LEVEL_THREAD2 } = await import("./system-events-ZYOCYAO2.js");
936
1016
  const warning = await missingCredentialWarning(template, readMindModel(mind, template), mind);
937
1017
  if (!warning) return;
938
1018
  if (await hasUndeliveredEvent(mind, "no_credentials")) return;
@@ -976,7 +1056,7 @@ async function wakeMind(name) {
976
1056
  async function startSpiritFull(name) {
977
1057
  const entry = await findMind(name);
978
1058
  if (entry?.dir) {
979
- const { registerMindDir } = await import("./delivery-router-QS4NLJR6.js");
1059
+ const { registerMindDir } = await import("./delivery-router-KHBVEVVL.js");
980
1060
  registerMindDir(name, entry.dir);
981
1061
  }
982
1062
  await getMindManager().startMind(name);
@@ -1015,7 +1095,7 @@ function buildSeedOrientation(createdBy, creatorType) {
1015
1095
  async function sendSeedOrientation(mindName, createdBy) {
1016
1096
  let creatorType;
1017
1097
  if (createdBy) {
1018
- const { getUserByUsername: getUserByUsername2 } = await import("./auth-KRDSM55Q.js");
1098
+ const { getUserByUsername: getUserByUsername2 } = await import("./auth-Y27LTNZK.js");
1019
1099
  creatorType = (await getUserByUsername2(createdBy))?.user_type;
1020
1100
  }
1021
1101
  await deliverEvent(mindName, {
@@ -1024,8 +1104,8 @@ async function sendSeedOrientation(mindName, createdBy) {
1024
1104
  });
1025
1105
  }
1026
1106
  async function ensureCreatorDM(mindName, creatorUsername) {
1027
- const { getOrCreateMindUser: getOrCreateMindUser2, getUserByUsername: getUserByUsername2 } = await import("./auth-KRDSM55Q.js");
1028
- const { findDMConversation: findDMConversation2, createConversation: createConversation2 } = await import("./conversations-ZL6PHROD.js");
1107
+ const { getOrCreateMindUser: getOrCreateMindUser2, getUserByUsername: getUserByUsername2 } = await import("./auth-Y27LTNZK.js");
1108
+ const { findDMConversation: findDMConversation2, createConversation: createConversation2 } = await import("./conversations-FH3ODBL7.js");
1029
1109
  const mindUser = await getOrCreateMindUser2(mindName);
1030
1110
  const creatorUser = await getUserByUsername2(creatorUsername);
1031
1111
  if (!creatorUser) {
@@ -1325,7 +1405,14 @@ var SleepManager = class {
1325
1405
  );
1326
1406
  const queuedSummary = await this.buildQueuedSummary(name);
1327
1407
  const eventsSummary = pendingEventsLine(await pendingEventCount(name));
1328
- const sleepActivity = [triggerWakeSummary, wakeContext, queuedSummary, eventsSummary].filter(Boolean).join("\n\n");
1408
+ const extensionContext = await collectTurnContext(name, "wake");
1409
+ const sleepActivity = [
1410
+ triggerWakeSummary,
1411
+ wakeContext,
1412
+ queuedSummary,
1413
+ eventsSummary,
1414
+ extensionContext
1415
+ ].filter(Boolean).join("\n\n");
1329
1416
  const summaryText = await getPrompt("wake_summary", {
1330
1417
  currentDate,
1331
1418
  sleepTime,
@@ -1459,7 +1546,7 @@ var SleepManager = class {
1459
1546
  * the real delivery stack. Returns whether the batch was handed off to the mind.
1460
1547
  */
1461
1548
  async deliverQueuedBatch(name, payloads) {
1462
- const { deliverBatch: deliverBatch2 } = await import("./message-delivery-TRKT4T2P.js");
1549
+ const { deliverBatch: deliverBatch2 } = await import("./message-delivery-LU4EP244.js");
1463
1550
  return deliverBatch2(name, payloads);
1464
1551
  }
1465
1552
  // --- Wake failure handling (#419) ---
@@ -2293,6 +2380,16 @@ async function openExtensionDb(_id, dataDir) {
2293
2380
  const Database = await getLibsqlDatabase();
2294
2381
  return new Database(dbPath);
2295
2382
  }
2383
+ function normalizeTrailingSlash(app) {
2384
+ return async (c, next) => {
2385
+ const url = new URL(c.req.url);
2386
+ if (url.pathname.length > 1 && url.pathname.endsWith("/")) {
2387
+ url.pathname = url.pathname.replace(/\/+$/, "");
2388
+ return app.fetch(new Request(url, c.req.raw), c.env);
2389
+ }
2390
+ await next();
2391
+ };
2392
+ }
2296
2393
  async function buildExtensionContext(manifest, dataDir, authMw) {
2297
2394
  let db = null;
2298
2395
  if (manifest.initDb) {
@@ -2340,6 +2437,18 @@ async function buildExtensionContext(manifest, dataDir, authMw) {
2340
2437
  return null;
2341
2438
  }
2342
2439
  },
2440
+ listMinds: async () => {
2441
+ try {
2442
+ return (await readRegistry()).map((m) => ({
2443
+ name: m.name,
2444
+ mindType: m.mindType === "spirit" ? "spirit" : "mind",
2445
+ stage: m.stage
2446
+ }));
2447
+ } catch (err) {
2448
+ logger_default.warn(`extension ${manifest.id}: failed to list minds`, logger_default.errorData(err));
2449
+ return [];
2450
+ }
2451
+ },
2343
2452
  getSystemsConfig: () => readSystemsConfig(),
2344
2453
  announceToSystem: (text) => announceToSystem(text),
2345
2454
  recordNotice: async (mindName, text) => {
@@ -2541,9 +2650,8 @@ function resolveSkillsDir(manifest) {
2541
2650
  }
2542
2651
  async function discoverBuiltinExtensions(disabledIds) {
2543
2652
  const builtins = [
2544
- { id: "notes", load: async () => (await import("./src-LTTQVN2Z.js")).default },
2545
- { id: "pages", load: async () => (await import("./src-3FIW7DLH.js")).default },
2546
- { id: "intentions", load: async () => (await import("./src-H3UCOP6B.js")).default }
2653
+ { id: "pages", load: async () => (await import("./src-LOUB3WPR.js")).default },
2654
+ { id: "intentions", load: async () => (await import("./src-246GSX7A.js")).default }
2547
2655
  ];
2548
2656
  const results = [];
2549
2657
  for (const { id, load } of builtins) {
@@ -2664,6 +2772,7 @@ async function loadAllExtensions(app, authMw) {
2664
2772
  logger_default.error(`failed to load extension: ${manifest.id}`, logger_default.errorData(err));
2665
2773
  }
2666
2774
  }
2775
+ await pruneOrphanedExtensionSkills();
2667
2776
  app.get("/api/extensions/commands", (c) => {
2668
2777
  const result = {};
2669
2778
  for (const { manifest } of loaded) {
@@ -2823,6 +2932,25 @@ async function uninstallNpmExtension(pkg) {
2823
2932
  }
2824
2933
  logger_default.info(`uninstalled extension package: ${pkg}`);
2825
2934
  }
2935
+ async function pruneOrphanedExtensionSkills() {
2936
+ try {
2937
+ const present = new Set(discovered.map((e) => e.manifest.id));
2938
+ const skills = await listSharedSkills();
2939
+ for (const skill of skills) {
2940
+ if (!skill.author?.startsWith("ext:")) continue;
2941
+ const extId = skill.author.slice("ext:".length);
2942
+ if (present.has(extId)) continue;
2943
+ try {
2944
+ await removeSharedSkill(skill.id);
2945
+ logger_default.info(`removed orphaned skill "${skill.id}" from absent extension ${extId}`);
2946
+ } catch (err) {
2947
+ logger_default.warn(`failed to remove orphaned skill "${skill.id}"`, logger_default.errorData(err));
2948
+ }
2949
+ }
2950
+ } catch (err) {
2951
+ logger_default.warn("could not prune orphaned extension skills", logger_default.errorData(err));
2952
+ }
2953
+ }
2826
2954
  async function cleanupExtensionSkills(pkg) {
2827
2955
  try {
2828
2956
  const pkgDir = resolve5(extensionsNpmDir(), "node_modules", pkg);
@@ -2923,6 +3051,9 @@ function notifyExtensionsMindStop(mindName) {
2923
3051
  }
2924
3052
  }
2925
3053
  }
3054
+ function getTurnContextProviders() {
3055
+ return loaded.filter(({ manifest }) => typeof manifest.turnContext === "function").map(({ manifest, context }) => ({ id: manifest.id, manifest, context })).sort((a, b) => a.id.localeCompare(b.id));
3056
+ }
2926
3057
  function _registerExtensionForTest(manifest) {
2927
3058
  loaded.push({ manifest, context: {} });
2928
3059
  }
@@ -2950,6 +3081,7 @@ export {
2950
3081
  deleteSystemsConfig,
2951
3082
  enrichActivityMetadata,
2952
3083
  parseCommandArgs,
3084
+ normalizeTrailingSlash,
2953
3085
  buildExtensionContext,
2954
3086
  loadAllExtensions,
2955
3087
  getLoadedExtensions,
@@ -2965,8 +3097,10 @@ export {
2965
3097
  notifyExtensionsDaemonStop,
2966
3098
  notifyExtensionsMindStart,
2967
3099
  notifyExtensionsMindStop,
3100
+ getTurnContextProviders,
2968
3101
  _registerExtensionForTest,
2969
3102
  _clearLoadedExtensionsForTest,
3103
+ collectTurnContext,
2970
3104
  initMailPoller,
2971
3105
  initTokenBudget,
2972
3106
  getTokenBudget,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  setBridgeConfig
4
- } from "./chunk-L7BKTZ5U.js";
4
+ } from "./chunk-G3XAB4DK.js";
5
5
  import {
6
6
  readEnv,
7
7
  sharedEnvPath,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  broadcast
4
- } from "./chunk-U54PJPTB.js";
4
+ } from "./chunk-PRZUBJ4K.js";
5
5
  import {
6
6
  findMind,
7
7
  getDb,
@@ -1,35 +1,36 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  isTemplateStale
4
- } from "./chunk-CV6BNGFK.js";
4
+ } from "./chunk-FSXPPOPM.js";
5
5
  import {
6
6
  computeTemplateHash
7
- } from "./chunk-HTRSSOHY.js";
7
+ } from "./chunk-YU5EYQAE.js";
8
8
  import {
9
9
  cleanupVariant
10
- } from "./chunk-OGPVJ53N.js";
10
+ } from "./chunk-QVS3C4DK.js";
11
11
  import {
12
12
  getSleepManagerIfReady,
13
13
  readSystemsConfig
14
- } from "./chunk-LGXVGIWN.js";
14
+ } from "./chunk-NCRG4SBR.js";
15
15
  import {
16
16
  applyTemplateHomeFiles,
17
+ backfillInitInfrastructure,
17
18
  composeTemplate,
18
19
  copyTemplateToDir,
19
20
  findTemplatesRoot
20
- } from "./chunk-X67BDDZR.js";
21
+ } from "./chunk-P3GXOT2X.js";
21
22
  import {
22
23
  getMindManager
23
- } from "./chunk-WHL6PKYP.js";
24
+ } from "./chunk-HLWQ3P3R.js";
24
25
  import {
25
- migrateSkillsToTemplate
26
- } from "./chunk-PPSN2MLC.js";
26
+ readVoluteConfig
27
+ } from "./chunk-WCFSBH33.js";
27
28
  import {
28
29
  deliverEvent
29
- } from "./chunk-HKGYZVWN.js";
30
+ } from "./chunk-DUV4EMNW.js";
30
31
  import {
31
- readVoluteConfig
32
- } from "./chunk-WCFSBH33.js";
32
+ migrateSkillsToTemplate
33
+ } from "./chunk-4VAQKLMU.js";
33
34
  import {
34
35
  chownMindDir,
35
36
  exec,
@@ -39,7 +40,7 @@ import {
39
40
  } from "./chunk-OIOW3FPT.js";
40
41
  import {
41
42
  logger_default
42
- } from "./chunk-QUSMYGNQ.js";
43
+ } from "./chunk-2674KIGI.js";
43
44
  import {
44
45
  findMind,
45
46
  mindDir,
@@ -249,6 +250,8 @@ var VariantMergeError = class extends Error {
249
250
  this.abortFailed = abortFailed;
250
251
  this.name = "VariantMergeError";
251
252
  }
253
+ conflicts;
254
+ abortFailed;
252
255
  };
253
256
  async function mergeInProgress(opts) {
254
257
  return gitExec(["rev-parse", "-q", "--verify", "MERGE_HEAD"], opts).then(
@@ -498,6 +501,17 @@ async function mergeUpgradeAndRestart(mindName, dir, worktreeDir, upgradeVariant
498
501
  };
499
502
  }
500
503
  }
504
+ try {
505
+ const added = backfillInitInfrastructure(resolve3(dir, "home"), template, mindName);
506
+ if (added.length > 0) {
507
+ logger_default.info(`backfilled ${added.length} missing infrastructure files for ${mindName}`, {
508
+ files: added
509
+ });
510
+ await chownMindDir(dir, mindName);
511
+ }
512
+ } catch (err) {
513
+ logger_default.warn(`failed to backfill infrastructure files for ${mindName}`, logger_default.errorData(err));
514
+ }
501
515
  try {
502
516
  await setMindTemplateHash(mindName, computeTemplateHash(template));
503
517
  await setMindTemplate(mindName, template);
@@ -2,6 +2,7 @@
2
2
 
3
3
  // packages/daemon/src/lib/template/template.ts
4
4
  import {
5
+ chmodSync,
5
6
  cpSync,
6
7
  existsSync,
7
8
  mkdirSync,
@@ -14,9 +15,9 @@ import {
14
15
  writeFileSync
15
16
  } from "fs";
16
17
  import { tmpdir } from "os";
17
- import { dirname, join, relative, resolve } from "path";
18
+ import { dirname, join, relative, resolve, sep } from "path";
18
19
  var _templatesRoot = null;
19
- function findTemplatesRoot() {
20
+ function locateTemplatesRoot() {
20
21
  if (_templatesRoot) return _templatesRoot;
21
22
  let dir = dirname(new URL(import.meta.url).pathname);
22
23
  for (let i = 0; i < 7; i++) {
@@ -27,6 +28,11 @@ function findTemplatesRoot() {
27
28
  }
28
29
  dir = dirname(dir);
29
30
  }
31
+ return null;
32
+ }
33
+ function findTemplatesRoot() {
34
+ const root = locateTemplatesRoot();
35
+ if (root) return root;
30
36
  console.error(
31
37
  "Templates directory not found. Searched up from:",
32
38
  dirname(new URL(import.meta.url).pathname)
@@ -100,6 +106,45 @@ function applyInitFiles(destDir) {
100
106
  }
101
107
  rmSync(initDir, { recursive: true, force: true });
102
108
  }
109
+ var INIT_INFRASTRUCTURE_PREFIXES = [".local/"];
110
+ function isInitInfrastructure(relPath) {
111
+ const normalized = relPath.split(sep).join("/");
112
+ return INIT_INFRASTRUCTURE_PREFIXES.some((prefix) => normalized.startsWith(prefix));
113
+ }
114
+ function backfillInitInfrastructure(homeDir, template, mindName) {
115
+ const root = locateTemplatesRoot();
116
+ if (!root) throw new Error("templates root not found on disk");
117
+ if (!existsSync(resolve(root, template, "volute-template.json"))) {
118
+ throw new Error(`template "${template}" is missing or has no manifest at ${root}`);
119
+ }
120
+ const { composedDir, manifest } = composeTemplate(root, template);
121
+ try {
122
+ const initDir = resolve(composedDir, ".init");
123
+ if (!existsSync(initDir)) return [];
124
+ const substitute = new Set(
125
+ manifest.substitute.map((p) => p.split(sep).join("/")).filter((p) => p.startsWith(".init/")).map((p) => p.slice(".init/".length))
126
+ );
127
+ const added = [];
128
+ for (const file of listFiles(initDir)) {
129
+ const rel = file.split(sep).join("/");
130
+ if (!isInitInfrastructure(rel)) continue;
131
+ const dest = resolve(homeDir, file);
132
+ if (existsSync(dest)) continue;
133
+ const src = resolve(initDir, file);
134
+ mkdirSync(dirname(dest), { recursive: true });
135
+ if (substitute.has(rel)) {
136
+ writeFileSync(dest, readFileSync(src, "utf-8").replaceAll("{{name}}", mindName));
137
+ chmodSync(dest, statSync(src).mode);
138
+ } else {
139
+ cpSync(src, dest);
140
+ }
141
+ added.push(rel);
142
+ }
143
+ return added;
144
+ } finally {
145
+ rmSync(composedDir, { recursive: true, force: true });
146
+ }
147
+ }
103
148
  var MECHANICS_DOCS = {
104
149
  claude: "CLAUDE.md",
105
150
  pi: "MINDS.md",
@@ -155,6 +200,7 @@ export {
155
200
  copyTemplateToDir,
156
201
  renderComposedPackageJson,
157
202
  applyInitFiles,
203
+ backfillInitInfrastructure,
158
204
  isKnownTemplate,
159
205
  applyTemplateHomeFiles,
160
206
  listFiles
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  logger_default
4
- } from "./chunk-QUSMYGNQ.js";
4
+ } from "./chunk-2674KIGI.js";
5
5
  import {
6
6
  getDb
7
7
  } from "./chunk-H6X6CKDN.js";
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getMindManager
4
- } from "./chunk-WHL6PKYP.js";
4
+ } from "./chunk-HLWQ3P3R.js";
5
5
  import {
6
6
  chownMindDir,
7
7
  gitExec
8
8
  } from "./chunk-OIOW3FPT.js";
9
9
  import {
10
10
  logger_default
11
- } from "./chunk-QUSMYGNQ.js";
11
+ } from "./chunk-2674KIGI.js";
12
12
  import {
13
13
  deleteMindDbFootprint,
14
14
  mindDir,