volute 0.54.0 → 0.56.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 (204) hide show
  1. package/dist/{activity-events-LQII6PZS.js → activity-events-YASF46HS.js} +3 -3
  2. package/dist/{ai-service-YW5SWCSB.js → ai-service-3UFNG6GI.js} +3 -5
  3. package/dist/{archive-FOHGXHPT.js → archive-L2OFBGDQ.js} +2 -2
  4. package/dist/{auth-KRDSM55Q.js → auth-N2F5ASAB.js} +4 -4
  5. package/dist/auto-upgrade-O4MQPYQF.js +46 -0
  6. package/dist/{avatar-image-52WGXLHV.js → avatar-image-QEKKUFDF.js} +3 -3
  7. package/dist/{backup-QRNX6RK7.js → backup-TPM7QQBQ.js} +13 -13
  8. package/dist/{channels-CKCY64TD.js → channels-JP3GYTPX.js} +18 -18
  9. package/dist/{chat-ZUGNL5GS.js → chat-7YCF4ZU5.js} +3 -3
  10. package/dist/{chunk-QUSMYGNQ.js → chunk-2674KIGI.js} +1 -0
  11. package/dist/{chunk-444RR3YF.js → chunk-2B4E6SL7.js} +14 -14
  12. package/dist/chunk-2GATCSZK.js +520 -0
  13. package/dist/{chunk-I7U5EEZC.js → chunk-2LFTJNVH.js} +2 -2
  14. package/dist/{chunk-L7BKTZ5U.js → chunk-2QLWAYIU.js} +2 -2
  15. package/dist/{chunk-F6D766VQ.js → chunk-45MCH4G4.js} +2 -2
  16. package/dist/{chunk-OGPVJ53N.js → chunk-4RZS7XCV.js} +5 -5
  17. package/dist/{chunk-HKGYZVWN.js → chunk-6LICEQGP.js} +38 -4
  18. package/dist/{chunk-LAUCO2HC.js → chunk-APDEUAIE.js} +1 -1
  19. package/dist/{chunk-5Y54AE3L.js → chunk-CLH357FI.js} +2 -2
  20. package/dist/{chunk-OAYY3WF3.js → chunk-CVPCRWWC.js} +1 -12
  21. package/dist/{chunk-EGV6R6UF.js → chunk-E2SN3ZOJ.js} +5 -40
  22. package/dist/{chunk-LGXVGIWN.js → chunk-ELQU2GBT.js} +193 -69
  23. package/dist/{chunk-OT5SXF7L.js → chunk-EPRLTYJR.js} +28 -14
  24. package/dist/{chunk-ATZF2RNJ.js → chunk-EYFBT2KP.js} +15 -15
  25. package/dist/{chunk-U54PJPTB.js → chunk-FYMIGUJ5.js} +2 -2
  26. package/dist/{chunk-7XKPG66D.js → chunk-G7A5LEVI.js} +5 -5
  27. package/dist/{chunk-RGHF3OK5.js → chunk-GAAATVTM.js} +17 -17
  28. package/dist/{chunk-7LT3YZUR.js → chunk-I3OJ342S.js} +2 -2
  29. package/dist/{chunk-3LHUXY3E.js → chunk-IABDYN4N.js} +4 -4
  30. package/dist/{chunk-VDUCLVZI.js → chunk-IOMBP2T5.js} +28 -26
  31. package/dist/{chunk-YSRYCS3N.js → chunk-IQROTVBG.js} +2 -2
  32. package/dist/{chunk-PPSN2MLC.js → chunk-IRNM4LSF.js} +9 -6
  33. package/dist/{chunk-ZNHL5KQJ.js → chunk-KN3UHV7O.js} +8 -3
  34. package/dist/{chunk-CV6BNGFK.js → chunk-KXM4K46T.js} +4 -4
  35. package/dist/{chunk-Z4Q6TQWL.js → chunk-LRRPKZBD.js} +2 -2
  36. package/dist/{chunk-LNNI3MS4.js → chunk-MNKPAAQF.js} +9 -2
  37. package/dist/{chunk-OIOW3FPT.js → chunk-NA2NJXY4.js} +1 -1
  38. package/dist/{chunk-GLM7TVWP.js → chunk-OHHS5PSI.js} +1 -1
  39. package/dist/{chunk-CKPAVQNK.js → chunk-OPTA3BJ4.js} +36 -24
  40. package/dist/{chunk-X67BDDZR.js → chunk-P3GXOT2X.js} +48 -2
  41. package/dist/{chunk-WHL6PKYP.js → chunk-PAO7JZNW.js} +52 -48
  42. package/dist/{chunk-TPX6E6PL.js → chunk-Q5M5QFKY.js} +3 -3
  43. package/dist/{chunk-OYF25B62.js → chunk-T7UMSTH2.js} +3 -3
  44. package/dist/{chunk-H6X6CKDN.js → chunk-TAVIVN2I.js} +2 -32
  45. package/dist/{chunk-56IT2ZXF.js → chunk-TGYKFUCF.js} +9 -15
  46. package/dist/{chunk-5U5GLZSD.js → chunk-TZ7OHGNL.js} +2 -2
  47. package/dist/{chunk-UFTDRTCP.js → chunk-UMQP5TC5.js} +2 -2
  48. package/dist/{chunk-LKUGUQUW.js → chunk-UNTDRIV2.js} +5 -5
  49. package/dist/{chunk-CLCHOXLR.js → chunk-V2M6PNLE.js} +5 -5
  50. package/dist/{chunk-ICXY54ZC.js → chunk-WTZD6LFW.js} +2 -2
  51. package/dist/{chunk-FLIEXG2T.js → chunk-XZP3FJ7Q.js} +1 -1
  52. package/dist/{chunk-HTRSSOHY.js → chunk-YU5EYQAE.js} +1 -1
  53. package/dist/cli.js +26 -23
  54. package/dist/{clock-X7V3C7NL.js → clock-ZT5YT6HA.js} +2 -2
  55. package/dist/{cloud-sync-52YNJRMR.js → cloud-sync-RTUXMYU2.js} +23 -23
  56. package/dist/{conversations-ZL6PHROD.js → conversations-ERMMPMOS.js} +4 -4
  57. package/dist/{create-G2RIKQYK.js → create-IUCFJXCE.js} +1 -1
  58. package/dist/{daemon-restart-QWHN5VMU.js → daemon-restart-N2YOISNJ.js} +11 -6
  59. package/dist/daemon.js +230 -279
  60. package/dist/{db-BONH4SUG.js → db-BQFYIONA.js} +1 -1
  61. package/dist/{db-I4EH5SLF.js → db-JH3NTERX.js} +17 -3
  62. package/dist/delivery-manager-5EGCFN4K.js +41 -0
  63. package/dist/{delivery-notices-RZQ6GONP.js → delivery-notices-LZKZXWTX.js} +6 -6
  64. package/dist/{delivery-router-QS4NLJR6.js → delivery-router-U6Q22ZYU.js} +3 -3
  65. package/dist/doctor-225FYBAQ.js +454 -0
  66. package/dist/{down-UN2EDX2Y.js → down-3BQSPUAZ.js} +4 -4
  67. package/dist/echo-text-Y2DFTD7L.js +40 -0
  68. package/dist/{env-SQFCWW52.js → env-4YX5YNWZ.js} +2 -2
  69. package/dist/{exec-Z34TTUO3.js → exec-Y5VMDAVA.js} +2 -2
  70. package/dist/{export-VBNWM7I4.js → export-ASRHBMRG.js} +2 -2
  71. package/dist/{extensions-QT65JGV6.js → extensions-YEPEWURN.js} +27 -23
  72. package/dist/{files-PCKBQHAY.js → files-FASUDSZQ.js} +3 -3
  73. package/dist/{import-DB2KULRO.js → import-O35Y7DSF.js} +6 -6
  74. package/dist/{isolation-UQPDO34R.js → isolation-ZOAUXYXA.js} +2 -2
  75. package/dist/{login-57MMYILL.js → login-54TZQQP4.js} +5 -5
  76. package/dist/{logout-YFZAJRPY.js → logout-4G46Z4RU.js} +1 -1
  77. package/dist/message-delivery-HBTMGWFU.js +46 -0
  78. package/dist/{mind-CT6ANXK4.js → mind-IKMX7K7G.js} +8 -24
  79. package/dist/{mind-activity-tracker-QF6DCX2X.js → mind-activity-tracker-ABAEIMA3.js} +4 -4
  80. package/dist/mind-service-LRVOQG2T.js +48 -0
  81. package/dist/{mind-sleep-24HV4RCA.js → mind-sleep-LZAFBDZD.js} +2 -2
  82. package/dist/{package-F6S5NHY2.js → package-X5O7OD2E.js} +12 -13
  83. package/dist/{prompts-JECJIFPQ.js → prompts-ZNOE3KN3.js} +2 -2
  84. package/dist/{registry-TRC2HJXR.js → registry-BTQXLDW6.js} +1 -1
  85. package/dist/{sandbox-NNWCTHRI.js → sandbox-OUFAGN45.js} +3 -3
  86. package/dist/scheduler-G6BCIVGP.js +27 -0
  87. package/dist/{seed-cmd-6IMTO3LG.js → seed-cmd-BGAW3WDY.js} +2 -2
  88. package/dist/{seed-create-VNLDYRFK.js → seed-create-SMCPEUFQ.js} +3 -3
  89. package/dist/{seed-readiness-H5TTPAQH.js → seed-readiness-RBANMSWW.js} +3 -3
  90. package/dist/{seed-sprout-PPGYGK4G.js → seed-sprout-CSHV36N3.js} +9 -9
  91. package/dist/{send-UXUQKO4N.js → send-D3ADUBR5.js} +6 -6
  92. package/dist/{service-T4P5W6RS.js → service-SWEEBOOY.js} +3 -24
  93. package/dist/{service-install-R4SNYUVO.js → service-install-RCC26KDV.js} +4 -4
  94. package/dist/{setup-YUAQMDVZ.js → setup-L5NZG2U3.js} +5 -5
  95. package/dist/{setup-WZSXHHRJ.js → setup-R7Q4HFJP.js} +1 -5
  96. package/dist/skills/volute-mind/SKILL.md +8 -0
  97. package/dist/{skills-GMQ5UIIW.js → skills-BCCU4OJW.js} +4 -4
  98. package/dist/sleep-manager-25P44HAO.js +42 -0
  99. package/dist/{spirit-Q5VGFWUI.js → spirit-YPG2MU6W.js} +7 -7
  100. package/dist/spirit-availability-ZQM5IH4C.js +43 -0
  101. package/dist/{src-H3UCOP6B.js → src-246GSX7A.js} +5 -2
  102. package/dist/src-LOUB3WPR.js +4189 -0
  103. package/dist/{status-LCKTTIWS.js → status-BYPCJU6H.js} +4 -4
  104. package/dist/{system-events-Q7IVZ5T4.js → system-events-CWC7CBKP.js} +6 -4
  105. package/dist/{systems-HL7SGSW7.js → systems-VDRUZXNF.js} +2 -2
  106. package/dist/{tailscale-KHNZFC7L.js → tailscale-4XY7B5A2.js} +2 -2
  107. package/dist/{template-hash-YKWMVYMM.js → template-hash-RJRMF6DT.js} +2 -2
  108. package/dist/{template-staleness-PY2CULH6.js → template-staleness-CL4V7BT7.js} +5 -5
  109. package/dist/{turn-tracker-HZDPMSCC.js → turn-tracker-LZP5X6GZ.js} +8 -8
  110. package/dist/{up-XZDSJVMU.js → up-3AAN4GYY.js} +4 -4
  111. package/dist/{update-ILCPVNDD.js → update-2MWXRE2S.js} +4 -4
  112. package/dist/{update-check-SZ7B5IFI.js → update-check-PJOZXZYJ.js} +2 -2
  113. package/dist/variant-cleanup-K7RFMSH7.js +24 -0
  114. package/dist/{version-notify-VNVFX6UP.js → version-notify-QIDHR6WO.js} +12 -12
  115. package/dist/web-assets/assets/{index-CwtxGwe_.js → index-Bfvls20e.js} +17 -17
  116. package/dist/web-assets/assets/index-hPn_fkz3.css +1 -0
  117. package/dist/web-assets/index.html +2 -2
  118. package/drizzle/0000_crazy_epoch.sql +232 -0
  119. package/drizzle/README.md +42 -0
  120. package/drizzle/meta/0000_snapshot.json +1420 -3
  121. package/drizzle/meta/_journal.json +2 -128
  122. package/package.json +12 -13
  123. package/packages/extensions/intentions/dist/ui/assets/index-Bl5KEcli.js +67 -0
  124. package/packages/extensions/intentions/dist/ui/index.html +1 -1
  125. package/packages/extensions/pages/dist/ui/assets/index-BKxVQkA9.css +1 -0
  126. package/packages/extensions/pages/dist/ui/assets/index-BMt6sStP.js +68 -0
  127. package/packages/extensions/pages/dist/ui/index.html +2 -2
  128. package/packages/extensions/pages/skills/pages/SKILL.md +123 -4
  129. package/templates/_base/.init/.config/prompts.json +0 -1
  130. package/templates/_base/.init/.local/hooks/pre-prompt/turn-context.ts +30 -0
  131. package/templates/_base/src/lib/codex-session-seed.ts +6 -55
  132. package/templates/_base/src/lib/pi-session-seed.ts +8 -57
  133. package/templates/_base/src/lib/seed-note.ts +4 -4
  134. package/templates/_base/src/lib/session-seed.ts +8 -53
  135. package/templates/_base/src/lib/startup.ts +0 -20
  136. package/templates/claude/package.json +2 -2
  137. package/templates/claude/src/agent.ts +34 -102
  138. package/templates/claude/src/lib/hooks/pre-compact.ts +6 -6
  139. package/templates/claude/src/server.ts +0 -1
  140. package/templates/codex/package.json +2 -2
  141. package/templates/codex/src/agent.ts +23 -89
  142. package/templates/pi/package.json +1 -1
  143. package/templates/pi/src/agent.ts +26 -93
  144. package/templates/pi/src/server.ts +0 -1
  145. package/dist/auto-upgrade-HEVZKPTF.js +0 -46
  146. package/dist/chunk-AAPNU7GA.js +0 -168
  147. package/dist/delivery-manager-7R2YIQ2W.js +0 -41
  148. package/dist/echo-text-73CYQRL7.js +0 -40
  149. package/dist/message-delivery-TRKT4T2P.js +0 -46
  150. package/dist/migrate-name-placeholder-C7NCNLWF.js +0 -37
  151. package/dist/migrate-thread-config-EQSEP2XG.js +0 -90
  152. package/dist/mind-service-7EFIJ3ZA.js +0 -48
  153. package/dist/scheduler-73Q4MQ7Y.js +0 -27
  154. package/dist/seed-DRKAP3XV.js +0 -11
  155. package/dist/sleep-manager-KHI65FEX.js +0 -42
  156. package/dist/spirit-availability-G5FMWKRH.js +0 -43
  157. package/dist/sprout-PMTRL7QN.js +0 -11
  158. package/dist/src-3FIW7DLH.js +0 -2376
  159. package/dist/src-LTTQVN2Z.js +0 -832
  160. package/dist/variant-HHDTW74J.js +0 -62
  161. package/dist/variant-cleanup-QHGGY7ND.js +0 -24
  162. package/dist/web-assets/assets/index-DhM1yYRN.css +0 -1
  163. package/drizzle/0000_baseline.sql +0 -152
  164. package/drizzle/0001_add_conversation_private.sql +0 -1
  165. package/drizzle/0002_turns.sql +0 -21
  166. package/drizzle/0003_turn_feed_links.sql +0 -11
  167. package/drizzle/0004_spirits.sql +0 -5
  168. package/drizzle/0005_meta_summaries.sql +0 -15
  169. package/drizzle/0006_channels.sql +0 -17
  170. package/drizzle/0007_drop_conversation_name_title.sql +0 -11
  171. package/drizzle/0008_performance_indexes.sql +0 -6
  172. package/drizzle/0009_mind_notices.sql +0 -14
  173. package/drizzle/0010_delivery_queue_redrive.sql +0 -10
  174. package/drizzle/0011_drop_turn_summary_event_id.sql +0 -3
  175. package/drizzle/0012_channel_gates.sql +0 -17
  176. package/drizzle/0013_variant_purpose.sql +0 -3
  177. package/drizzle/0014_system_events.sql +0 -26
  178. package/drizzle/0015_rename_session_to_thread.sql +0 -12
  179. package/drizzle/0016_brain_to_human.sql +0 -4
  180. package/drizzle/0017_event_history_rows.sql +0 -9
  181. package/drizzle/0018_api_tokens.sql +0 -20
  182. package/drizzle/meta/0001_snapshot.json +0 -7
  183. package/drizzle/meta/0002_snapshot.json +0 -7
  184. package/drizzle/meta/0003_snapshot.json +0 -7
  185. package/drizzle/meta/0004_snapshot.json +0 -7
  186. package/drizzle/meta/0005_snapshot.json +0 -7
  187. package/drizzle/meta/0006_snapshot.json +0 -7
  188. package/drizzle/meta/0007_snapshot.json +0 -7
  189. package/packages/extensions/intentions/dist/ui/assets/index-CQz4aceM.js +0 -67
  190. package/packages/extensions/notes/dist/ui/assets/index-BBs8pyel.js +0 -67
  191. package/packages/extensions/notes/dist/ui/assets/index-D3cdui42.css +0 -1
  192. package/packages/extensions/notes/dist/ui/index.html +0 -14
  193. package/packages/extensions/notes/skills/notes/SKILL.md +0 -90
  194. package/packages/extensions/pages/dist/ui/assets/index-B589e8Xe.js +0 -2
  195. package/packages/extensions/pages/dist/ui/assets/index-BuXnE-rb.css +0 -1
  196. package/dist/{env-7AZFBPWX.js → env-IBW2QI6K.js} +5 -5
  197. package/dist/{login-4NUS72Z5.js → login-RJJTCVR3.js} +3 -3
  198. package/dist/{mind-contacts-PEXCDRXA.js → mind-contacts-KV64UDJS.js} +6 -6
  199. package/dist/{mind-history-RZMMCHMX.js → mind-history-H45GM2M2.js} +6 -6
  200. package/dist/{register-WNCSOTAU.js → register-OX4HRSGC.js} +3 -3
  201. package/dist/{restart-B4GNMVF2.js → restart-AGEGNSYQ.js} +4 -4
  202. package/dist/{skill-QYTBUDNQ.js → skill-B5OJEQUA.js} +4 -4
  203. package/dist/{start-BDHJVOVX.js → start-MUMNFR52.js} +3 -3
  204. package/dist/{stop-45QYSGYS.js → stop-EKERNYTX.js} +4 -4
@@ -1,10 +1,10 @@
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
  readGlobalConfig
7
- } from "./chunk-H6X6CKDN.js";
7
+ } from "./chunk-TAVIVN2I.js";
8
8
 
9
9
  // packages/daemon/src/lib/mind/sandbox.ts
10
10
  import { execFileSync } from "child_process";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getDb
4
- } from "./chunk-H6X6CKDN.js";
4
+ } from "./chunk-TAVIVN2I.js";
5
5
  import {
6
6
  systemPrompts
7
7
  } from "./chunk-2RNMBXD2.js";
@@ -18,7 +18,6 @@ var PROMPT_KEYS = [
18
18
  "upgrade_message",
19
19
  "split_message",
20
20
  "farewell_message",
21
- "compaction_warning",
22
21
  "compaction_instructions",
23
22
  "reply_instructions",
24
23
  "event_instructions",
@@ -103,16 +102,6 @@ Take your time. Talk with your creator. Explore what kind of mind you want to be
103
102
  variables: ["parent", "path"],
104
103
  category: "system"
105
104
  },
106
- compaction_warning: {
107
- content: `Context limit approaching \u2014 this session will rotate shortly. Turns before \${cutoff} will be collapsed to their summaries; turns from \${cutoff} on are kept verbatim in the continued session, so there's no need to re-describe them.
108
-
109
- For the turns that will collapse, make sure they read the way you'd want: \`volute mind history --provisional\` shows the provisional summaries, and \`volute mind history --write --turn <id> --text "..."\` replaces any with your own account. Also save anything important to your files (memory/journal/\${date}.md, or a memory/ file). Provisional summaries are kept if you write nothing \u2014 nothing blocks on this.
110
-
111
- Your MEMORY.md is currently \${memory_size}. It is loaded into every request, so consolidate rather than append \u2014 distill detail into memory/ files and keep MEMORY.md lean (see the memory skill).`,
112
- description: "Pre-rotation warning: which turns collapse (before the cutoff) vs survive verbatim",
113
- variables: ["cutoff", "date", "memory_size"],
114
- category: "mind"
115
- },
116
105
  compaction_instructions: {
117
106
  content: "Preserve your sense of who you are, what matters to you, what happened in this conversation, and the threads of thought and connection you'd want to return to.",
118
107
  description: "Custom instructions for the compaction summarizer",
@@ -1,11 +1,11 @@
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
  readGlobalConfig,
7
7
  writeGlobalConfig
8
- } from "./chunk-H6X6CKDN.js";
8
+ } from "./chunk-TAVIVN2I.js";
9
9
 
10
10
  // packages/daemon/src/lib/ai-service.ts
11
11
  import { defaultProviderAuthContext } from "@earendil-works/pi-ai";
@@ -133,7 +133,7 @@ async function missingCredentialWarning(template, model, mindName) {
133
133
  const envVar = PROVIDER_ENV_VAR[provider] ?? `${provider.toUpperCase().replace(/-/g, "_")}_API_KEY`;
134
134
  if (await resolveApiKey(provider)) return null;
135
135
  if (provider === "openai-codex" && process.env.OPENAI_API_KEY) return null;
136
- const { loadMergedEnv } = await import("./env-SQFCWW52.js");
136
+ const { loadMergedEnv } = await import("./env-4YX5YNWZ.js");
137
137
  if (loadMergedEnv(mindName)[envVar]) return null;
138
138
  if (getAiConfig()?.providers[provider]?.oauth) {
139
139
  return `${provider} authentication is temporarily unavailable, so ${mindName} will start but may stay silent until it recovers (OAuth token refresh is failing \u2014 usually transient). If it persists, re-check the ${provider} provider in the web dashboard (Settings \u2192 Providers).`;
@@ -172,42 +172,6 @@ function setEnabledModels(modelIds) {
172
172
  const config = readGlobalConfig();
173
173
  writeGlobalConfig({ ...config, ai });
174
174
  }
175
- function migrateAiModelQualification() {
176
- const config = readGlobalConfig();
177
- const ai = config.ai;
178
- const isBare = (id) => id != null && !id.includes(":");
179
- const hasBareInList = (ai?.models ?? []).some(isBare);
180
- if (!hasBareInList && !isBare(config.spiritModel) && !isBare(ai?.utilityModel)) return;
181
- const providers = ai ? Object.keys(ai.providers) : [];
182
- const customModels = ai?.customModels ?? [];
183
- const providersServing = (bareId) => providers.filter(
184
- (p) => getBuiltinModel(p, bareId) != null || customModels.some((cm) => cm.provider === p && cm.id === bareId)
185
- );
186
- let changed = false;
187
- if (ai?.models) {
188
- const expanded = [];
189
- for (const id of ai.models) {
190
- if (!isBare(id)) {
191
- expanded.push(id);
192
- continue;
193
- }
194
- changed = true;
195
- for (const p of providersServing(id)) expanded.push(`${p}:${id}`);
196
- }
197
- ai.models = expanded.length > 0 ? [...new Set(expanded)] : void 0;
198
- if (!ai.models) delete ai.models;
199
- }
200
- const qualifyOne = (id) => {
201
- if (!isBare(id)) return id;
202
- const [provider] = providersServing(id);
203
- if (!provider) return id;
204
- changed = true;
205
- return `${provider}:${id}`;
206
- };
207
- config.spiritModel = qualifyOne(config.spiritModel);
208
- if (ai) ai.utilityModel = qualifyOne(ai.utilityModel);
209
- if (changed) writeGlobalConfig(config);
210
- }
211
175
  function getCustomModels() {
212
176
  return getAiConfig()?.customModels ?? [];
213
177
  }
@@ -311,6 +275,8 @@ var OAuthRefreshError = class extends Error {
311
275
  this.cause = cause;
312
276
  this.name = "OAuthRefreshError";
313
277
  }
278
+ providerId;
279
+ cause;
314
280
  };
315
281
  async function resolveOAuthCredentials(providerId) {
316
282
  const ai = getAiConfig();
@@ -433,7 +399,6 @@ export {
433
399
  resolveTemplate,
434
400
  getEnabledModels,
435
401
  setEnabledModels,
436
- migrateAiModelQualification,
437
402
  getCustomModels,
438
403
  addCustomModel,
439
404
  removeCustomModel,
@@ -1,36 +1,52 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  spiritDir
4
- } from "./chunk-RGHF3OK5.js";
4
+ } from "./chunk-GAAATVTM.js";
5
5
  import {
6
6
  getScheduler
7
- } from "./chunk-444RR3YF.js";
7
+ } from "./chunk-2B4E6SL7.js";
8
8
  import {
9
9
  getDeliveryManager
10
- } from "./chunk-VDUCLVZI.js";
10
+ } from "./chunk-IOMBP2T5.js";
11
11
  import {
12
12
  getMindManager,
13
13
  resolveMindToken
14
- } from "./chunk-WHL6PKYP.js";
14
+ } from "./chunk-PAO7JZNW.js";
15
+ import {
16
+ addMessage,
17
+ createChannel,
18
+ createConversation,
19
+ findDMConversation,
20
+ getChannelByName,
21
+ getChannelSettings,
22
+ getParticipants,
23
+ joinChannel,
24
+ updateChannelSettings
25
+ } from "./chunk-Q5M5QFKY.js";
26
+ import {
27
+ markIdle
28
+ } from "./chunk-UMQP5TC5.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-IQROTVBG.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-I3OJ342S.js";
46
+ import {
47
+ publish,
48
+ subscribe
49
+ } from "./chunk-FYMIGUJ5.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-6LICEQGP.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-CVPCRWWC.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-IRNM4LSF.js";
70
71
  import {
71
72
  isIsolationEnabled,
72
73
  mindUserName
73
- } from "./chunk-OIOW3FPT.js";
74
+ } from "./chunk-NA2NJXY4.js";
74
75
  import {
75
76
  missingCredentialWarning
76
- } from "./chunk-EGV6R6UF.js";
77
+ } from "./chunk-E2SN3ZOJ.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,
@@ -91,7 +92,7 @@ import {
91
92
  voluteHome,
92
93
  voluteSystemDir,
93
94
  writeGlobalConfig
94
- } from "./chunk-H6X6CKDN.js";
95
+ } from "./chunk-TAVIVN2I.js";
95
96
  import {
96
97
  activity,
97
98
  apiTokens,
@@ -146,15 +147,6 @@ async function listApiTokens(userId) {
146
147
  // packages/daemon/src/web/middleware/auth.ts
147
148
  var MIND_USER_CACHE_TTL = 5 * 60 * 1e3;
148
149
  var mindUserCache = /* @__PURE__ */ new Map();
149
- var alog = logger_default.child("auth");
150
- var legacySessionHeaderWarned = /* @__PURE__ */ new Set();
151
- function warnLegacySessionHeader(legacyHeader, mindName) {
152
- if (!legacyHeader || legacySessionHeaderWarned.has(mindName)) return;
153
- legacySessionHeaderWarned.add(mindName);
154
- alog.warn(
155
- `mind ${mindName} sent legacy X-Volute-Session header (now X-Volute-Thread); run \`volute mind upgrade ${mindName}\` to update its template`
156
- );
157
- }
158
150
  function invalidateMindUserCache(mindName) {
159
151
  mindUserCache.delete(mindName);
160
152
  }
@@ -263,7 +255,6 @@ var authMiddleware = createMiddleware(async (c, next) => {
263
255
  c.set("user", mindUser);
264
256
  const mindSessionHeader = c.req.header("X-Volute-Thread");
265
257
  if (mindSessionHeader) c.set("mindSession", mindSessionHeader);
266
- else warnLegacySessionHeader(c.req.header("X-Volute-Session"), mindName);
267
258
  await next();
268
259
  return;
269
260
  }
@@ -328,6 +319,85 @@ import { promisify } from "util";
328
319
  import { CronExpressionParser } from "cron-parser";
329
320
  import { and as and2, eq as eq3, inArray } from "drizzle-orm";
330
321
 
322
+ // packages/daemon/src/lib/turn-context.ts
323
+ var tlog = logger_default.child("turn-context");
324
+ var TURN_CONTEXT_BUDGET = {
325
+ turn: 1200,
326
+ wake: 3e3
327
+ };
328
+ var PROVIDER_TIMEOUT_MS = 1e3;
329
+ var TOTAL_TIMEOUT_MS = 2e3;
330
+ var SEPARATOR = "\n\n";
331
+ function withTimeout(p, ms) {
332
+ return new Promise((resolve6, reject) => {
333
+ const timer = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);
334
+ p.then(
335
+ (v) => {
336
+ clearTimeout(timer);
337
+ resolve6(v);
338
+ },
339
+ (err) => {
340
+ clearTimeout(timer);
341
+ reject(err);
342
+ }
343
+ );
344
+ });
345
+ }
346
+ async function collectFromProviders(providers, reason, total = TURN_CONTEXT_BUDGET[reason], now = Date.now) {
347
+ if (providers.length === 0 || total <= 0) return null;
348
+ const deadline = now() + TOTAL_TIMEOUT_MS;
349
+ const blocks = [];
350
+ let remaining = total;
351
+ for (let i = 0; i < providers.length; i++) {
352
+ const { id, run } = providers[i];
353
+ if (remaining <= 0) break;
354
+ if (now() >= deadline) {
355
+ tlog.warn(
356
+ `deadline reached before asking ${providers.length - i} remaining extension(s) for ${reason} context`
357
+ );
358
+ break;
359
+ }
360
+ const joinerCost = blocks.length > 0 ? SEPARATOR.length : 0;
361
+ const available = remaining - joinerCost;
362
+ if (available <= 0) break;
363
+ const budget = Math.floor(available / (providers.length - i));
364
+ if (budget <= 0) break;
365
+ let text;
366
+ try {
367
+ text = await withTimeout(run(budget), PROVIDER_TIMEOUT_MS);
368
+ } catch (err) {
369
+ tlog.warn(`extension ${id}: turnContext failed, dropped from this turn`, logger_default.errorData(err));
370
+ continue;
371
+ }
372
+ if (typeof text !== "string") continue;
373
+ const trimmed = text.trim();
374
+ if (!trimmed) continue;
375
+ if (trimmed.length > budget) {
376
+ tlog.warn(
377
+ `extension ${id}: turnContext returned ${trimmed.length} chars over a ${budget} budget \u2014 dropped`
378
+ );
379
+ continue;
380
+ }
381
+ blocks.push(trimmed);
382
+ remaining -= trimmed.length + joinerCost;
383
+ }
384
+ if (blocks.length === 0) return null;
385
+ return blocks.join(SEPARATOR);
386
+ }
387
+ async function collectTurnContext(mindName, reason) {
388
+ try {
389
+ const providers = getTurnContextProviders().map(({ id, manifest, context }) => ({
390
+ id,
391
+ // Non-null: getTurnContextProviders filters to manifests that declare it.
392
+ run: (budget) => manifest.turnContext(mindName, context, { budget, reason })
393
+ }));
394
+ return await collectFromProviders(providers, reason);
395
+ } catch (err) {
396
+ tlog.error(`failed to collect ${reason} context for ${mindName}`, logger_default.errorData(err));
397
+ return null;
398
+ }
399
+ }
400
+
331
401
  // packages/daemon/src/lib/daemon/mind-service.ts
332
402
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
333
403
  import { resolve as resolve3 } from "path";
@@ -642,7 +712,7 @@ async function ensureMailAddress(mindName) {
642
712
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
643
713
  import { mkdir, writeFile } from "fs/promises";
644
714
  import { resolve as resolve2 } from "path";
645
- var tlog = logger_default.child("token-budget");
715
+ var tlog2 = logger_default.child("token-budget");
646
716
  var DEFAULT_BUDGET_PERIOD_MINUTES = 60;
647
717
  var MAX_QUEUE_SIZE = 100;
648
718
  var TokenBudget = class {
@@ -651,7 +721,7 @@ var TokenBudget = class {
651
721
  dirty = /* @__PURE__ */ new Set();
652
722
  start() {
653
723
  this.interval = setInterval(() => {
654
- this.tick().catch((err) => tlog.error("token budget tick failed", logger_default.errorData(err)));
724
+ this.tick().catch((err) => tlog2.error("token budget tick failed", logger_default.errorData(err)));
655
725
  }, 6e4);
656
726
  }
657
727
  async stop() {
@@ -761,7 +831,7 @@ var TokenBudget = class {
761
831
  const queued = this.drain(mind);
762
832
  if (queued.length > 0) {
763
833
  this.replay(mind, queued).catch((err) => {
764
- tlog.warn(`replay error for ${mind}`, logger_default.errorData(err));
834
+ tlog2.warn(`replay error for ${mind}`, logger_default.errorData(err));
765
835
  });
766
836
  }
767
837
  }
@@ -796,7 +866,7 @@ var TokenBudget = class {
796
866
  await writeFile(this.budgetStatePath(mind), `${JSON.stringify(data)}
797
867
  `);
798
868
  } catch (err) {
799
- tlog.warn(`failed to save budget state for ${mind}`, logger_default.errorData(err));
869
+ tlog2.warn(`failed to save budget state for ${mind}`, logger_default.errorData(err));
800
870
  }
801
871
  }
802
872
  loadBudgetState(mind) {
@@ -817,7 +887,7 @@ var TokenBudget = class {
817
887
  // will be overwritten by caller
818
888
  };
819
889
  } catch (err) {
820
- tlog.warn(`failed to load budget state for ${mind}`, logger_default.errorData(err));
890
+ tlog2.warn(`failed to load budget state for ${mind}`, logger_default.errorData(err));
821
891
  return null;
822
892
  }
823
893
  }
@@ -835,9 +905,9 @@ var TokenBudget = class {
835
905
 
836
906
  ${summary}`
837
907
  });
838
- tlog.info(`replayed ${messages2.length} queued message(s) for ${mindName}`);
908
+ tlog2.info(`replayed ${messages2.length} queued message(s) for ${mindName}`);
839
909
  } catch (err) {
840
- tlog.warn(`failed to replay for ${mindName}`, logger_default.errorData(err));
910
+ tlog2.warn(`failed to replay for ${mindName}`, logger_default.errorData(err));
841
911
  const state = this.budgets.get(mindName);
842
912
  if (state) state.queue.push(...messages2);
843
913
  }
@@ -932,7 +1002,7 @@ async function startMindFull(name) {
932
1002
  }
933
1003
  }
934
1004
  async function recordMissingCredentialsNotice(mind, template) {
935
- const { hasUndeliveredEvent, recordNotice: recordNotice2, MIND_LEVEL_THREAD: MIND_LEVEL_THREAD2 } = await import("./system-events-Q7IVZ5T4.js");
1005
+ const { hasUndeliveredEvent, recordNotice: recordNotice2, MIND_LEVEL_THREAD: MIND_LEVEL_THREAD2 } = await import("./system-events-CWC7CBKP.js");
936
1006
  const warning = await missingCredentialWarning(template, readMindModel(mind, template), mind);
937
1007
  if (!warning) return;
938
1008
  if (await hasUndeliveredEvent(mind, "no_credentials")) return;
@@ -976,7 +1046,7 @@ async function wakeMind(name) {
976
1046
  async function startSpiritFull(name) {
977
1047
  const entry = await findMind(name);
978
1048
  if (entry?.dir) {
979
- const { registerMindDir } = await import("./delivery-router-QS4NLJR6.js");
1049
+ const { registerMindDir } = await import("./delivery-router-U6Q22ZYU.js");
980
1050
  registerMindDir(name, entry.dir);
981
1051
  }
982
1052
  await getMindManager().startMind(name);
@@ -1015,7 +1085,7 @@ function buildSeedOrientation(createdBy, creatorType) {
1015
1085
  async function sendSeedOrientation(mindName, createdBy) {
1016
1086
  let creatorType;
1017
1087
  if (createdBy) {
1018
- const { getUserByUsername: getUserByUsername2 } = await import("./auth-KRDSM55Q.js");
1088
+ const { getUserByUsername: getUserByUsername2 } = await import("./auth-N2F5ASAB.js");
1019
1089
  creatorType = (await getUserByUsername2(createdBy))?.user_type;
1020
1090
  }
1021
1091
  await deliverEvent(mindName, {
@@ -1024,8 +1094,8 @@ async function sendSeedOrientation(mindName, createdBy) {
1024
1094
  });
1025
1095
  }
1026
1096
  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");
1097
+ const { getOrCreateMindUser: getOrCreateMindUser2, getUserByUsername: getUserByUsername2 } = await import("./auth-N2F5ASAB.js");
1098
+ const { findDMConversation: findDMConversation2, createConversation: createConversation2 } = await import("./conversations-ERMMPMOS.js");
1029
1099
  const mindUser = await getOrCreateMindUser2(mindName);
1030
1100
  const creatorUser = await getUserByUsername2(creatorUsername);
1031
1101
  if (!creatorUser) {
@@ -1325,7 +1395,14 @@ var SleepManager = class {
1325
1395
  );
1326
1396
  const queuedSummary = await this.buildQueuedSummary(name);
1327
1397
  const eventsSummary = pendingEventsLine(await pendingEventCount(name));
1328
- const sleepActivity = [triggerWakeSummary, wakeContext, queuedSummary, eventsSummary].filter(Boolean).join("\n\n");
1398
+ const extensionContext = await collectTurnContext(name, "wake");
1399
+ const sleepActivity = [
1400
+ triggerWakeSummary,
1401
+ wakeContext,
1402
+ queuedSummary,
1403
+ eventsSummary,
1404
+ extensionContext
1405
+ ].filter(Boolean).join("\n\n");
1329
1406
  const summaryText = await getPrompt("wake_summary", {
1330
1407
  currentDate,
1331
1408
  sleepTime,
@@ -1459,7 +1536,7 @@ var SleepManager = class {
1459
1536
  * the real delivery stack. Returns whether the batch was handed off to the mind.
1460
1537
  */
1461
1538
  async deliverQueuedBatch(name, payloads) {
1462
- const { deliverBatch: deliverBatch2 } = await import("./message-delivery-TRKT4T2P.js");
1539
+ const { deliverBatch: deliverBatch2 } = await import("./message-delivery-HBTMGWFU.js");
1463
1540
  return deliverBatch2(name, payloads);
1464
1541
  }
1465
1542
  // --- Wake failure handling (#419) ---
@@ -2293,6 +2370,16 @@ async function openExtensionDb(_id, dataDir) {
2293
2370
  const Database = await getLibsqlDatabase();
2294
2371
  return new Database(dbPath);
2295
2372
  }
2373
+ function normalizeTrailingSlash(app) {
2374
+ return async (c, next) => {
2375
+ const url = new URL(c.req.url);
2376
+ if (url.pathname.length > 1 && url.pathname.endsWith("/")) {
2377
+ url.pathname = url.pathname.replace(/\/+$/, "");
2378
+ return app.fetch(new Request(url, c.req.raw), c.env);
2379
+ }
2380
+ await next();
2381
+ };
2382
+ }
2296
2383
  async function buildExtensionContext(manifest, dataDir, authMw) {
2297
2384
  let db = null;
2298
2385
  if (manifest.initDb) {
@@ -2340,6 +2427,18 @@ async function buildExtensionContext(manifest, dataDir, authMw) {
2340
2427
  return null;
2341
2428
  }
2342
2429
  },
2430
+ listMinds: async () => {
2431
+ try {
2432
+ return (await readRegistry()).map((m) => ({
2433
+ name: m.name,
2434
+ mindType: m.mindType === "spirit" ? "spirit" : "mind",
2435
+ stage: m.stage
2436
+ }));
2437
+ } catch (err) {
2438
+ logger_default.warn(`extension ${manifest.id}: failed to list minds`, logger_default.errorData(err));
2439
+ return [];
2440
+ }
2441
+ },
2343
2442
  getSystemsConfig: () => readSystemsConfig(),
2344
2443
  announceToSystem: (text) => announceToSystem(text),
2345
2444
  recordNotice: async (mindName, text) => {
@@ -2541,9 +2640,8 @@ function resolveSkillsDir(manifest) {
2541
2640
  }
2542
2641
  async function discoverBuiltinExtensions(disabledIds) {
2543
2642
  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 }
2643
+ { id: "pages", load: async () => (await import("./src-LOUB3WPR.js")).default },
2644
+ { id: "intentions", load: async () => (await import("./src-246GSX7A.js")).default }
2547
2645
  ];
2548
2646
  const results = [];
2549
2647
  for (const { id, load } of builtins) {
@@ -2664,6 +2762,7 @@ async function loadAllExtensions(app, authMw) {
2664
2762
  logger_default.error(`failed to load extension: ${manifest.id}`, logger_default.errorData(err));
2665
2763
  }
2666
2764
  }
2765
+ await pruneOrphanedExtensionSkills();
2667
2766
  app.get("/api/extensions/commands", (c) => {
2668
2767
  const result = {};
2669
2768
  for (const { manifest } of loaded) {
@@ -2792,7 +2891,7 @@ async function installNpmExtension(pkg) {
2792
2891
  throw new Error(`Extension "${pkg}" is already installed`);
2793
2892
  }
2794
2893
  const dir = ensureExtensionsNpmDir();
2795
- const { exec } = await import("./exec-Z34TTUO3.js");
2894
+ const { exec } = await import("./exec-Y5VMDAVA.js");
2796
2895
  try {
2797
2896
  await exec("npm", ["install", "--ignore-scripts", pkg], { cwd: dir });
2798
2897
  } catch (err) {
@@ -2813,7 +2912,7 @@ async function uninstallNpmExtension(pkg) {
2813
2912
  packages.splice(idx, 1);
2814
2913
  writeExtensionsConfig(packages);
2815
2914
  try {
2816
- const { exec } = await import("./exec-Z34TTUO3.js");
2915
+ const { exec } = await import("./exec-Y5VMDAVA.js");
2817
2916
  await exec("npm", ["uninstall", "--ignore-scripts", pkg], { cwd: extensionsNpmDir() });
2818
2917
  } catch (err) {
2819
2918
  logger_default.warn(
@@ -2823,6 +2922,25 @@ async function uninstallNpmExtension(pkg) {
2823
2922
  }
2824
2923
  logger_default.info(`uninstalled extension package: ${pkg}`);
2825
2924
  }
2925
+ async function pruneOrphanedExtensionSkills() {
2926
+ try {
2927
+ const present = new Set(discovered.map((e) => e.manifest.id));
2928
+ const skills = await listSharedSkills();
2929
+ for (const skill of skills) {
2930
+ if (!skill.author?.startsWith("ext:")) continue;
2931
+ const extId = skill.author.slice("ext:".length);
2932
+ if (present.has(extId)) continue;
2933
+ try {
2934
+ await removeSharedSkill(skill.id);
2935
+ logger_default.info(`removed orphaned skill "${skill.id}" from absent extension ${extId}`);
2936
+ } catch (err) {
2937
+ logger_default.warn(`failed to remove orphaned skill "${skill.id}"`, logger_default.errorData(err));
2938
+ }
2939
+ }
2940
+ } catch (err) {
2941
+ logger_default.warn("could not prune orphaned extension skills", logger_default.errorData(err));
2942
+ }
2943
+ }
2826
2944
  async function cleanupExtensionSkills(pkg) {
2827
2945
  try {
2828
2946
  const pkgDir = resolve5(extensionsNpmDir(), "node_modules", pkg);
@@ -2923,6 +3041,9 @@ function notifyExtensionsMindStop(mindName) {
2923
3041
  }
2924
3042
  }
2925
3043
  }
3044
+ function getTurnContextProviders() {
3045
+ return loaded.filter(({ manifest }) => typeof manifest.turnContext === "function").map(({ manifest, context }) => ({ id: manifest.id, manifest, context })).sort((a, b) => a.id.localeCompare(b.id));
3046
+ }
2926
3047
  function _registerExtensionForTest(manifest) {
2927
3048
  loaded.push({ manifest, context: {} });
2928
3049
  }
@@ -2950,6 +3071,7 @@ export {
2950
3071
  deleteSystemsConfig,
2951
3072
  enrichActivityMetadata,
2952
3073
  parseCommandArgs,
3074
+ normalizeTrailingSlash,
2953
3075
  buildExtensionContext,
2954
3076
  loadAllExtensions,
2955
3077
  getLoadedExtensions,
@@ -2965,8 +3087,10 @@ export {
2965
3087
  notifyExtensionsDaemonStop,
2966
3088
  notifyExtensionsMindStart,
2967
3089
  notifyExtensionsMindStop,
3090
+ getTurnContextProviders,
2968
3091
  _registerExtensionForTest,
2969
3092
  _clearLoadedExtensionsForTest,
3093
+ collectTurnContext,
2970
3094
  initMailPoller,
2971
3095
  initTokenBudget,
2972
3096
  getTokenBudget,