volute 0.28.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/README.md +127 -18
  2. package/dist/{accept-666DIZX2.js → accept-E3PAH3QJ.js} +2 -2
  3. package/dist/{activity-events-BBIEA2F4.js → activity-events-BKBPPUBP.js} +2 -2
  4. package/dist/ai-service-VAJT5UBS.js +29 -0
  5. package/dist/api.d.ts +586 -529
  6. package/dist/{archive-UA4BDFXQ.js → archive-WWDBWYN2.js} +2 -2
  7. package/dist/{bridge-FQHZL3MC.js → bridge-RO37CUFM.js} +2 -2
  8. package/dist/{chat-M4SX42JD.js → chat-TCUNPFGO.js} +8 -8
  9. package/dist/{chunk-IAYBDWVG.js → chunk-2C2VXEBB.js} +147 -2
  10. package/dist/chunk-2NDZC3S7.js +1330 -0
  11. package/dist/{chunk-IKRVFPWU.js → chunk-7D47T4RB.js} +3 -2
  12. package/dist/chunk-A6TUJJ3L.js +19 -0
  13. package/dist/{chunk-AW7PFDVN.js → chunk-CVH6Y2YG.js} +1 -1
  14. package/dist/{chunk-XBLSAVJF.js → chunk-DTC6EH5I.js} +1 -1
  15. package/dist/chunk-EFP3PE6C.js +232 -0
  16. package/dist/{chunk-JGFVMROS.js → chunk-EFVHR7KH.js} +1 -1
  17. package/dist/{chunk-K5NAC55T.js → chunk-FSM45XD5.js} +2 -2
  18. package/dist/{chunk-LAC664WU.js → chunk-FXHXHI2A.js} +42 -24
  19. package/dist/{chunk-RKQEHRBB.js → chunk-G3GBKZGG.js} +1 -1
  20. package/dist/{chunk-H7OZRFJB.js → chunk-HHTXM4JT.js} +0 -49
  21. package/dist/{chunk-J4IBNXGJ.js → chunk-IKHDUZRH.js} +4 -3
  22. package/dist/{chunk-MD4C26II.js → chunk-JGFRDMR6.js} +1 -1
  23. package/dist/{chunk-POSXWWTA.js → chunk-LIRWLNAK.js} +26 -12
  24. package/dist/{chunk-NI5FFCCS.js → chunk-MDPCSXZ4.js} +35 -11
  25. package/dist/chunk-NSBFETWP.js +188 -0
  26. package/dist/{chunk-VIVMW2H2.js → chunk-P27RV5WM.js} +1 -1
  27. package/dist/{chunk-EHYDTZTF.js → chunk-P7VFDSSG.js} +2 -2
  28. package/dist/{chunk-AAPXKR5V.js → chunk-QVAQ5454.js} +181 -544
  29. package/dist/{chunk-HDN7MNGD.js → chunk-S5LR3XYJ.js} +1 -1
  30. package/dist/{chunk-2YP2TVDT.js → chunk-UPA6COHU.js} +5 -5
  31. package/dist/{chunk-AKPFNL7L.js → chunk-VGWJSNHS.js} +1 -1
  32. package/dist/{chunk-SGVNFZHW.js → chunk-W5OOPLNP.js} +3 -3
  33. package/dist/{chunk-2WPW7OT6.js → chunk-ZWKTUQEL.js} +1 -1
  34. package/dist/cli.js +25 -26
  35. package/dist/clock-G3ALCMLJ.js +263 -0
  36. package/dist/{cloud-sync-HDL6PHZI.js → cloud-sync-JV4LJOK3.js} +14 -12
  37. package/dist/connectors/discord-bridge.js +1 -1
  38. package/dist/connectors/slack-bridge.js +1 -1
  39. package/dist/connectors/telegram-bridge.js +1 -1
  40. package/dist/{conversations-M2K4253F.js → conversations-7KVQV7EZ.js} +9 -3
  41. package/dist/create-JTLS7GX3.js +70 -0
  42. package/dist/{create-QWV73WXD.js → create-VQSQHJQW.js} +1 -1
  43. package/dist/{daemon-client-I42FK2BF.js → daemon-client-BCTFGVCZ.js} +2 -2
  44. package/dist/{daemon-restart-G4B2OYAB.js → daemon-restart-4JGBHEJ4.js} +7 -7
  45. package/dist/daemon.js +1474 -1124
  46. package/dist/{db-IC4J52XQ.js → db-HMFPIRO2.js} +1 -1
  47. package/dist/{delete-4JYGD4VN.js → delete-JESHKE7F.js} +1 -1
  48. package/dist/down-NGBMGORS.js +14 -0
  49. package/dist/{env-YJMUMFIY.js → env-CLXXT7M2.js} +2 -2
  50. package/dist/{export-BOJQWBMA.js → export-EGA5M5PB.js} +3 -3
  51. package/dist/extension-WZ4SUPJB.js +174 -0
  52. package/dist/extensions-ECO4RPFQ.js +27 -0
  53. package/dist/{files-M546TKVN.js → files-4VEJDASH.js} +3 -3
  54. package/dist/{history-ALPTNB3I.js → history-EJMMLXDO.js} +17 -2
  55. package/dist/{import-SRTQXBGH.js → import-YCGPMBSI.js} +3 -3
  56. package/dist/{join-J4QU42DL.js → join-2GBJKZEN.js} +1 -1
  57. package/dist/{list-R73GENNL.js → list-Q6O7FGAN.js} +2 -2
  58. package/dist/{login-3QZNR2DF.js → login-RET5WESK.js} +2 -2
  59. package/dist/{login-BKP3AFWN.js → login-RL6AU2SM.js} +3 -3
  60. package/dist/{logout-T53VKCPU.js → logout-CGAGJN3L.js} +2 -2
  61. package/dist/{logout-IQK7FNEK.js → logout-JRPBEMMR.js} +3 -3
  62. package/dist/message-delivery-6YMVNOEC.js +28 -0
  63. package/dist/{migrate-registry-to-db-XC7T5B7P.js → migrate-registry-to-db-FK35IPEH.js} +1 -1
  64. package/dist/{mind-S5V6CK5W.js → mind-LUWRQUQ5.js} +17 -17
  65. package/dist/{mind-activity-tracker-EN6XNXPF.js → mind-activity-tracker-VYN2ZZ2M.js} +3 -3
  66. package/dist/{mind-list-UPJ75GPI.js → mind-list-V5WW5DUA.js} +2 -2
  67. package/dist/{mind-manager-S6ILZVX3.js → mind-manager-YFCOIAAX.js} +6 -6
  68. package/dist/{mind-sleep-BTSWQNAC.js → mind-sleep-R6PTNNW4.js} +2 -2
  69. package/dist/{mind-status-TK5AETEM.js → mind-status-I4ISFJ6I.js} +2 -2
  70. package/dist/{mind-wake-SBAKIDVP.js → mind-wake-67ZQEWAV.js} +2 -2
  71. package/dist/{package-CG4RWUGP.js → package-S2OAA5ZA.js} +11 -5
  72. package/dist/pages-watcher-Z3PKNROC.js +21 -0
  73. package/dist/{read-36UFXN3G.js → read-WQMPTSN2.js} +2 -2
  74. package/dist/{register-CHREOMJ3.js → register-NZDSTLP3.js} +3 -3
  75. package/dist/{registry-NDNOOYG4.js → registry-ODSALQQL.js} +1 -1
  76. package/dist/{reject-LXIZFJ4Q.js → reject-2HZOJEIJ.js} +2 -2
  77. package/dist/{restart-6ESL3NBO.js → restart-QHS3NT64.js} +2 -2
  78. package/dist/{sandbox-5BW5HPXM.js → sandbox-O5FUSF43.js} +3 -3
  79. package/dist/{seed-SSUCYYDF.js → seed-WUQMPLDM.js} +1 -1
  80. package/dist/{send-TAOEZ4NH.js → send-OAN3RYYY.js} +20 -6
  81. package/dist/{setup-JHL5ZEST.js → setup-QMDK5RZX.js} +2 -2
  82. package/dist/{setup-RXYVGGT7.js → setup-XJH3E7YM.js} +45 -14
  83. package/dist/{skill-AUAQTSP5.js → skill-FZIN4W4Q.js} +65 -3
  84. package/dist/skills/dreaming/references/INSTALL.md +3 -17
  85. package/dist/skills/volute-mind/SKILL.md +45 -27
  86. package/dist/sleep-manager-O7YQFCV5.js +30 -0
  87. package/dist/{split-TKJ5OT3P.js → split-EXYGGGQN.js} +1 -1
  88. package/dist/{sprout-UNT7LKKE.js → sprout-AXQ6H5DB.js} +8 -7
  89. package/dist/{start-EUJSS5R4.js → start-MTOVL6SY.js} +2 -2
  90. package/dist/{status-NQJYR4BG.js → status-ZRO37MWR.js} +5 -5
  91. package/dist/{stop-3XAITBBF.js → stop-OK5WEPVC.js} +2 -2
  92. package/dist/{systems-SMEFSHTA.js → systems-W3BBMSOZ.js} +5 -5
  93. package/dist/{tailscale-NY5MUMY3.js → tailscale-BM72RXCJ.js} +1 -1
  94. package/dist/{template-hash-BIMA4ILT.js → template-hash-3HOR4UAJ.js} +1 -1
  95. package/dist/up-BXUAIDXB.js +17 -0
  96. package/dist/{update-PTSH22AZ.js → update-PLPHMMZ2.js} +5 -5
  97. package/dist/{update-check-64FWC4Y2.js → update-check-CVCN7MF6.js} +2 -2
  98. package/dist/{upgrade-HA47CS4C.js → upgrade-I6NPCYUU.js} +1 -1
  99. package/dist/{version-notify-JDUF4HQJ.js → version-notify-2NTWVEHL.js} +18 -16
  100. package/dist/web-assets/assets/index--kREqKl9.js +72 -0
  101. package/dist/web-assets/assets/index-BXYTG0nJ.css +1 -0
  102. package/dist/web-assets/ext-theme.css +111 -0
  103. package/dist/web-assets/index.html +2 -2
  104. package/package.json +11 -5
  105. package/packages/extensions/notes/dist/ui/assets/index-DgawVO5g.css +1 -0
  106. package/packages/extensions/notes/dist/ui/assets/index-qUWoeC4c.js +2 -0
  107. package/packages/extensions/notes/dist/ui/index.html +14 -0
  108. package/packages/extensions/notes/skills/notes/SKILL.md +62 -0
  109. package/packages/extensions/notes/skills/notes/scripts/notes.mjs +185 -0
  110. package/packages/extensions/pages/dist/ui/assets/index-D0HyS-xQ.css +1 -0
  111. package/packages/extensions/pages/dist/ui/assets/index-tLTROSk5.js +2 -0
  112. package/packages/extensions/pages/dist/ui/index.html +14 -0
  113. package/packages/extensions/pages/skills/pages/SKILL.md +58 -0
  114. package/templates/_base/home/VOLUTE.md +1 -1
  115. package/templates/_base/src/lib/logger.ts +10 -49
  116. package/templates/_base/src/lib/router.ts +1 -9
  117. package/templates/claude/src/lib/stream-consumer.ts +1 -4
  118. package/templates/pi/src/lib/event-handler.ts +1 -14
  119. package/dist/chunk-P72MVS4R.js +0 -188
  120. package/dist/chunk-T6HKBWXZ.js +0 -23
  121. package/dist/chunk-ZYGKG6VC.js +0 -22
  122. package/dist/create-D7J73A6H.js +0 -45
  123. package/dist/down-LVBXEULC.js +0 -14
  124. package/dist/message-delivery-HV3S6HZV.js +0 -24
  125. package/dist/notes-XCER3I7M.js +0 -220
  126. package/dist/pages-KJDJX4TA.js +0 -36
  127. package/dist/publish-ZZB33WP4.js +0 -86
  128. package/dist/schedule-QTJMFATP.js +0 -154
  129. package/dist/skills/notes/SKILL.md +0 -34
  130. package/dist/sleep-manager-WMVG2VCL.js +0 -28
  131. package/dist/status-S7UUPNRW.js +0 -38
  132. package/dist/up-GM2JOH2Y.js +0 -17
  133. package/dist/web-assets/assets/index-BZGvToHi.css +0 -1
  134. package/dist/web-assets/assets/index-Cz4TrpzB.js +0 -75
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  voluteHome,
4
4
  voluteSystemDir
5
- } from "./chunk-H7OZRFJB.js";
5
+ } from "./chunk-HHTXM4JT.js";
6
6
 
7
7
  // src/lib/setup.ts
8
8
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -25,7 +25,8 @@ function readGlobalConfig() {
25
25
  function writeGlobalConfig(config) {
26
26
  const path = configPath();
27
27
  mkdirSync(voluteSystemDir(), { recursive: true });
28
- writeFileSync(path, JSON.stringify(config, null, 2) + "\n");
28
+ writeFileSync(path, `${JSON.stringify(config, null, 2)}
29
+ `);
29
30
  }
30
31
  function isSetupComplete() {
31
32
  const config = readGlobalConfig();
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/lib/slugify.ts
4
+ function slugify(text) {
5
+ return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
6
+ }
7
+ function buildVoluteSlug(opts) {
8
+ if (opts.convType === "channel" && opts.convName) {
9
+ return `volute:#${opts.convName}`;
10
+ }
11
+ const other = opts.participants.find((p) => p.username !== opts.mindUsername);
12
+ const otherSlug = other ? slugify(other.username) : "";
13
+ return otherSlug ? `volute:@${otherSlug}` : `volute:${opts.conversationId}`;
14
+ }
15
+
16
+ export {
17
+ slugify,
18
+ buildVoluteSlug
19
+ };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  wrapForIsolation
4
- } from "./chunk-RKQEHRBB.js";
4
+ } from "./chunk-G3GBKZGG.js";
5
5
 
6
6
  // src/lib/exec.ts
7
7
  import { execFile as execFileCb, execFileSync, spawn } from "child_process";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  mindDir,
4
4
  stateDir
5
- } from "./chunk-H7OZRFJB.js";
5
+ } from "./chunk-HHTXM4JT.js";
6
6
 
7
7
  // src/lib/archive.ts
8
8
  import { execFileSync } from "child_process";
@@ -0,0 +1,232 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ publish
4
+ } from "./chunk-P27RV5WM.js";
5
+ import {
6
+ logger_default
7
+ } from "./chunk-YUIHSKR6.js";
8
+ import {
9
+ mindDir,
10
+ readRegistry,
11
+ voluteHome
12
+ } from "./chunk-HHTXM4JT.js";
13
+
14
+ // src/lib/pages-watcher.ts
15
+ import { existsSync, readdirSync, statSync, watch } from "fs";
16
+ import { join, resolve } from "path";
17
+ var watchers = /* @__PURE__ */ new Map();
18
+ var homeWatchers = /* @__PURE__ */ new Map();
19
+ var debounceTimers = /* @__PURE__ */ new Map();
20
+ var sitesCache = null;
21
+ var recentPagesCache = null;
22
+ function startPagesWatcher(mindName, pagesDir) {
23
+ try {
24
+ const watcher = watch(pagesDir, { recursive: true }, (_eventType, filename) => {
25
+ if (!filename || !filename.endsWith(".html")) return;
26
+ const key = `${mindName}:${filename}`;
27
+ const existing = debounceTimers.get(key);
28
+ if (existing) clearTimeout(existing);
29
+ debounceTimers.set(
30
+ key,
31
+ setTimeout(() => {
32
+ debounceTimers.delete(key);
33
+ invalidateCache();
34
+ publish({
35
+ type: "page_updated",
36
+ mind: mindName,
37
+ summary: `${mindName} updated ${filename}`,
38
+ metadata: { file: filename }
39
+ }).catch(
40
+ (err) => logger_default.error("failed to publish page_updated activity", logger_default.errorData(err))
41
+ );
42
+ }, 100)
43
+ );
44
+ });
45
+ watchers.set(mindName, watcher);
46
+ } catch (err) {
47
+ logger_default.warn(`failed to start pages watcher for ${mindName}`, logger_default.errorData(err));
48
+ }
49
+ }
50
+ function startSystemWatcher() {
51
+ if (watchers.has("_system")) return;
52
+ const systemPagesDir = resolve(voluteHome(), "shared", "pages");
53
+ if (!existsSync(systemPagesDir)) return;
54
+ startPagesWatcher("_system", systemPagesDir);
55
+ }
56
+ function startWatcher(mindName) {
57
+ if (watchers.has(mindName)) return;
58
+ const pagesDir = resolve(mindDir(mindName), "home", "public", "pages");
59
+ if (existsSync(pagesDir)) {
60
+ startPagesWatcher(mindName, pagesDir);
61
+ return;
62
+ }
63
+ if (homeWatchers.has(mindName)) return;
64
+ const publicDir = resolve(mindDir(mindName), "home", "public");
65
+ if (!existsSync(publicDir)) return;
66
+ try {
67
+ const hw = watch(publicDir, (_eventType, filename) => {
68
+ if (filename !== "pages") return;
69
+ if (!existsSync(pagesDir)) return;
70
+ hw.close();
71
+ homeWatchers.delete(mindName);
72
+ invalidateCache();
73
+ startPagesWatcher(mindName, pagesDir);
74
+ });
75
+ homeWatchers.set(mindName, hw);
76
+ } catch (err) {
77
+ logger_default.warn(`failed to start home watcher for ${mindName}`, logger_default.errorData(err));
78
+ }
79
+ }
80
+ function stopWatcher(mindName) {
81
+ const watcher = watchers.get(mindName);
82
+ if (watcher) {
83
+ watcher.close();
84
+ watchers.delete(mindName);
85
+ }
86
+ const hw = homeWatchers.get(mindName);
87
+ if (hw) {
88
+ hw.close();
89
+ homeWatchers.delete(mindName);
90
+ }
91
+ for (const [key, timer] of debounceTimers) {
92
+ if (key.startsWith(`${mindName}:`)) {
93
+ clearTimeout(timer);
94
+ debounceTimers.delete(key);
95
+ }
96
+ }
97
+ }
98
+ function stopAllWatchers() {
99
+ for (const [, watcher] of watchers) {
100
+ watcher.close();
101
+ }
102
+ watchers.clear();
103
+ for (const [, hw] of homeWatchers) {
104
+ hw.close();
105
+ }
106
+ homeWatchers.clear();
107
+ for (const [, timer] of debounceTimers) {
108
+ clearTimeout(timer);
109
+ }
110
+ debounceTimers.clear();
111
+ invalidateCache();
112
+ }
113
+ function invalidateCache() {
114
+ sitesCache = null;
115
+ recentPagesCache = null;
116
+ }
117
+ function scanPagesDir(dir, urlPrefix) {
118
+ const pages = [];
119
+ let items;
120
+ try {
121
+ items = readdirSync(dir);
122
+ } catch {
123
+ return pages;
124
+ }
125
+ for (const item of items) {
126
+ if (item.startsWith(".")) continue;
127
+ const fullPath = resolve(dir, item);
128
+ try {
129
+ const s = statSync(fullPath);
130
+ if (s.isFile() && item.endsWith(".html")) {
131
+ pages.push({
132
+ file: item,
133
+ modified: s.mtime.toISOString(),
134
+ url: `${urlPrefix}/${item}`
135
+ });
136
+ } else if (s.isDirectory()) {
137
+ const indexPath = resolve(fullPath, "index.html");
138
+ if (existsSync(indexPath)) {
139
+ const indexStat = statSync(indexPath);
140
+ pages.push({
141
+ file: join(item, "index.html"),
142
+ modified: indexStat.mtime.toISOString(),
143
+ url: `${urlPrefix}/${item}/`
144
+ });
145
+ }
146
+ }
147
+ } catch {
148
+ }
149
+ }
150
+ pages.sort((a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime());
151
+ return pages;
152
+ }
153
+ async function buildSites() {
154
+ const sites = [];
155
+ const systemPagesDir = resolve(voluteHome(), "shared", "pages");
156
+ if (existsSync(systemPagesDir)) {
157
+ const systemPages = scanPagesDir(systemPagesDir, "/pages/_system");
158
+ if (systemPages.length > 0) {
159
+ sites.push({ name: "_system", label: "System", pages: systemPages });
160
+ }
161
+ }
162
+ const entries = await readRegistry();
163
+ for (const entry of [...entries].sort((a, b) => a.name.localeCompare(b.name))) {
164
+ const pagesDir = resolve(mindDir(entry.name), "home", "public", "pages");
165
+ if (!existsSync(pagesDir)) continue;
166
+ const mindPages = scanPagesDir(pagesDir, `/minds/${entry.name}/pages`);
167
+ if (mindPages.length > 0) {
168
+ sites.push({ name: entry.name, label: entry.name, pages: mindPages });
169
+ }
170
+ }
171
+ return sites;
172
+ }
173
+ async function buildRecentPages() {
174
+ const entries = await readRegistry();
175
+ const pages = [];
176
+ for (const entry of entries) {
177
+ const pagesDir = resolve(mindDir(entry.name), "home", "public", "pages");
178
+ if (!existsSync(pagesDir)) continue;
179
+ let items;
180
+ try {
181
+ items = readdirSync(pagesDir);
182
+ } catch {
183
+ continue;
184
+ }
185
+ for (const item of items) {
186
+ if (item.startsWith(".")) continue;
187
+ const fullPath = resolve(pagesDir, item);
188
+ try {
189
+ const s = statSync(fullPath);
190
+ if (s.isFile() && item.endsWith(".html")) {
191
+ pages.push({
192
+ mind: entry.name,
193
+ file: item,
194
+ modified: s.mtime.toISOString(),
195
+ url: `/minds/${entry.name}/pages/${item}`
196
+ });
197
+ } else if (s.isDirectory()) {
198
+ const indexPath = resolve(fullPath, "index.html");
199
+ if (existsSync(indexPath)) {
200
+ const indexStat = statSync(indexPath);
201
+ pages.push({
202
+ mind: entry.name,
203
+ file: join(item, "index.html"),
204
+ modified: indexStat.mtime.toISOString(),
205
+ url: `/minds/${entry.name}/pages/${item}/`
206
+ });
207
+ }
208
+ }
209
+ } catch {
210
+ }
211
+ }
212
+ }
213
+ pages.sort((a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime());
214
+ return pages.slice(0, 10);
215
+ }
216
+ async function getCachedSites() {
217
+ if (!sitesCache) sitesCache = await buildSites();
218
+ return sitesCache;
219
+ }
220
+ async function getCachedRecentPages() {
221
+ if (!recentPagesCache) recentPagesCache = await buildRecentPages();
222
+ return recentPagesCache;
223
+ }
224
+
225
+ export {
226
+ startSystemWatcher,
227
+ startWatcher,
228
+ stopWatcher,
229
+ stopAllWatchers,
230
+ getCachedSites,
231
+ getCachedRecentPages
232
+ };
@@ -3,7 +3,7 @@ import {
3
3
  voluteHome,
4
4
  voluteSystemDir,
5
5
  voluteUserHome
6
- } from "./chunk-H7OZRFJB.js";
6
+ } from "./chunk-HHTXM4JT.js";
7
7
 
8
8
  // src/lib/daemon-client.ts
9
9
  import { existsSync, readFileSync } from "fs";
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  publish
4
- } from "./chunk-VIVMW2H2.js";
4
+ } from "./chunk-P27RV5WM.js";
5
5
  import {
6
6
  logger_default
7
7
  } from "./chunk-YUIHSKR6.js";
8
8
 
9
9
  // src/lib/events/mind-activity-tracker.ts
10
- var IDLE_TIMEOUT_MS = 2 * 60 * 1e3;
10
+ var IDLE_TIMEOUT_MS = 5 * 60 * 1e3;
11
11
  var minds = /* @__PURE__ */ new Map();
12
12
  function getState(mind) {
13
13
  let state = minds.get(mind);
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ exec,
3
4
  execInherit
4
- } from "./chunk-AW7PFDVN.js";
5
+ } from "./chunk-CVH6Y2YG.js";
5
6
  import {
6
7
  voluteHome,
7
8
  voluteSystemDir
8
- } from "./chunk-H7OZRFJB.js";
9
+ } from "./chunk-HHTXM4JT.js";
9
10
 
10
11
  // src/lib/service-mode.ts
11
12
  import { execFileSync } from "child_process";
@@ -98,11 +99,25 @@ async function startService(mode) {
98
99
  await execInherit("systemctl", ["--user", "start", "volute"]);
99
100
  break;
100
101
  case "system-launchd":
101
- await execInherit("sudo", ["launchctl", "load", SYSTEM_LAUNCHD_PLIST_PATH]);
102
+ await exec("sudo", ["launchctl", "bootout", `system/${LAUNCHD_PLIST_LABEL}`]).catch(
103
+ (err) => console.warn(
104
+ `Warning: launchctl bootout failed (may not be loaded): ${err instanceof Error ? err.message : err}`
105
+ )
106
+ );
107
+ await execInherit("sudo", ["launchctl", "bootstrap", "system", SYSTEM_LAUNCHD_PLIST_PATH]);
108
+ await execInherit("sudo", ["launchctl", "kickstart", `system/${LAUNCHD_PLIST_LABEL}`]);
102
109
  break;
103
- case "user-launchd":
104
- await execInherit("launchctl", ["load", LAUNCHD_PLIST_PATH]);
110
+ case "user-launchd": {
111
+ const uid = `gui/${process.getuid()}`;
112
+ await exec("launchctl", ["bootout", `${uid}/${LAUNCHD_PLIST_LABEL}`]).catch(
113
+ (err) => console.warn(
114
+ `Warning: launchctl bootout failed (may not be loaded): ${err instanceof Error ? err.message : err}`
115
+ )
116
+ );
117
+ await execInherit("launchctl", ["bootstrap", uid, LAUNCHD_PLIST_PATH]);
118
+ await execInherit("launchctl", ["kickstart", `${uid}/${LAUNCHD_PLIST_LABEL}`]);
105
119
  break;
120
+ }
106
121
  }
107
122
  }
108
123
  async function stopService(mode) {
@@ -114,10 +129,13 @@ async function stopService(mode) {
114
129
  await execInherit("systemctl", ["--user", "stop", "volute"]);
115
130
  break;
116
131
  case "system-launchd":
117
- await execInherit("sudo", ["launchctl", "unload", SYSTEM_LAUNCHD_PLIST_PATH]);
132
+ await execInherit("sudo", ["launchctl", "bootout", `system/${LAUNCHD_PLIST_LABEL}`]);
118
133
  break;
119
134
  case "user-launchd":
120
- await execInherit("launchctl", ["unload", LAUNCHD_PLIST_PATH]);
135
+ await execInherit("launchctl", [
136
+ "bootout",
137
+ `gui/${process.getuid()}/${LAUNCHD_PLIST_LABEL}`
138
+ ]);
121
139
  break;
122
140
  }
123
141
  }
@@ -130,25 +148,25 @@ async function restartService(mode) {
130
148
  await execInherit("systemctl", ["--user", "restart", "volute"]);
131
149
  break;
132
150
  case "system-launchd":
133
- try {
134
- await execInherit("sudo", ["launchctl", "unload", SYSTEM_LAUNCHD_PLIST_PATH]);
135
- } catch (err) {
136
- console.warn(
137
- `Warning: launchctl unload failed: ${err instanceof Error ? err.message : err}`
138
- );
139
- }
140
- await execInherit("sudo", ["launchctl", "load", SYSTEM_LAUNCHD_PLIST_PATH]);
151
+ await exec("sudo", ["launchctl", "bootout", `system/${LAUNCHD_PLIST_LABEL}`]).catch(
152
+ (err) => console.warn(
153
+ `Warning: launchctl bootout failed (may not be loaded): ${err instanceof Error ? err.message : err}`
154
+ )
155
+ );
156
+ await execInherit("sudo", ["launchctl", "bootstrap", "system", SYSTEM_LAUNCHD_PLIST_PATH]);
157
+ await execInherit("sudo", ["launchctl", "kickstart", `system/${LAUNCHD_PLIST_LABEL}`]);
141
158
  break;
142
- case "user-launchd":
143
- try {
144
- await execInherit("launchctl", ["unload", LAUNCHD_PLIST_PATH]);
145
- } catch (err) {
146
- console.warn(
147
- `Warning: launchctl unload failed: ${err instanceof Error ? err.message : err}`
148
- );
149
- }
150
- await execInherit("launchctl", ["load", LAUNCHD_PLIST_PATH]);
159
+ case "user-launchd": {
160
+ const uid = `gui/${process.getuid()}`;
161
+ await exec("launchctl", ["bootout", `${uid}/${LAUNCHD_PLIST_LABEL}`]).catch(
162
+ (err) => console.warn(
163
+ `Warning: launchctl bootout failed (may not be loaded): ${err instanceof Error ? err.message : err}`
164
+ )
165
+ );
166
+ await execInherit("launchctl", ["bootstrap", uid, LAUNCHD_PLIST_PATH]);
167
+ await execInherit("launchctl", ["kickstart", `${uid}/${LAUNCHD_PLIST_LABEL}`]);
151
168
  break;
169
+ }
152
170
  }
153
171
  }
154
172
  function readDaemonConfig() {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  getBaseName,
4
4
  validateMindName
5
- } from "./chunk-H7OZRFJB.js";
5
+ } from "./chunk-HHTXM4JT.js";
6
6
 
7
7
  // src/lib/isolation.ts
8
8
  import { execFileSync } from "child_process";
@@ -28,9 +28,6 @@ __export(schema_exports, {
28
28
  messages: () => messages,
29
29
  mindHistory: () => mindHistory,
30
30
  minds: () => minds,
31
- noteComments: () => noteComments,
32
- noteReactions: () => noteReactions,
33
- notes: () => notes,
34
31
  sessions: () => sessions,
35
32
  sharedSkills: () => sharedSkills,
36
33
  systemPrompts: () => systemPrompts,
@@ -180,49 +177,6 @@ var conversationReads = sqliteTable(
180
177
  uniqueIndex("idx_conversation_reads_unique").on(table.user_id, table.conversation_id)
181
178
  ]
182
179
  );
183
- var notes = sqliteTable(
184
- "notes",
185
- {
186
- id: integer("id").primaryKey({ autoIncrement: true }),
187
- author_id: integer("author_id").notNull().references(() => users.id, { onDelete: "cascade" }),
188
- title: text("title").notNull(),
189
- slug: text("slug").notNull(),
190
- content: text("content").notNull(),
191
- reply_to_id: integer("reply_to_id"),
192
- created_at: text("created_at").notNull().default(sql`(datetime('now'))`),
193
- updated_at: text("updated_at").notNull().default(sql`(datetime('now'))`)
194
- },
195
- (table) => [
196
- uniqueIndex("idx_notes_author_slug").on(table.author_id, table.slug),
197
- index("idx_notes_created_at").on(table.created_at),
198
- index("idx_notes_reply_to").on(table.reply_to_id)
199
- ]
200
- );
201
- var noteComments = sqliteTable(
202
- "note_comments",
203
- {
204
- id: integer("id").primaryKey({ autoIncrement: true }),
205
- note_id: integer("note_id").notNull().references(() => notes.id, { onDelete: "cascade" }),
206
- author_id: integer("author_id").notNull().references(() => users.id, { onDelete: "cascade" }),
207
- content: text("content").notNull(),
208
- created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
209
- },
210
- (table) => [index("idx_note_comments_note_id").on(table.note_id)]
211
- );
212
- var noteReactions = sqliteTable(
213
- "note_reactions",
214
- {
215
- id: integer("id").primaryKey({ autoIncrement: true }),
216
- note_id: integer("note_id").notNull().references(() => notes.id, { onDelete: "cascade" }),
217
- user_id: integer("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
218
- emoji: text("emoji").notNull(),
219
- created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
220
- },
221
- (table) => [
222
- uniqueIndex("idx_note_reactions_unique").on(table.note_id, table.user_id, table.emoji),
223
- index("idx_note_reactions_note_id").on(table.note_id)
224
- ]
225
- );
226
180
  var messages = sqliteTable(
227
181
  "messages",
228
182
  {
@@ -403,9 +357,6 @@ export {
403
357
  deliveryQueue,
404
358
  activity,
405
359
  conversationReads,
406
- notes,
407
- noteComments,
408
- noteReactions,
409
360
  messages,
410
361
  getDb,
411
362
  voluteHome,
@@ -4,14 +4,14 @@ import {
4
4
  } from "./chunk-YUIHSKR6.js";
5
5
  import {
6
6
  readGlobalConfig
7
- } from "./chunk-IKRVFPWU.js";
7
+ } from "./chunk-7D47T4RB.js";
8
8
  import {
9
9
  getBaseName,
10
10
  readRegistry,
11
11
  voluteHome,
12
12
  voluteSystemDir,
13
13
  voluteUserHome
14
- } from "./chunk-H7OZRFJB.js";
14
+ } from "./chunk-HHTXM4JT.js";
15
15
 
16
16
  // src/lib/sandbox.ts
17
17
  import { resolve } from "path";
@@ -29,7 +29,8 @@ async function initSandbox() {
29
29
  network: {
30
30
  allowedDomains: ["*"],
31
31
  deniedDomains: [],
32
- allowLocalBinding: true
32
+ allowLocalBinding: true,
33
+ allowAllUnixSockets: true
33
34
  },
34
35
  filesystem: {
35
36
  denyRead: [],
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  stateDir
4
- } from "./chunk-H7OZRFJB.js";
4
+ } from "./chunk-HHTXM4JT.js";
5
5
 
6
6
  // src/lib/file-sharing.ts
7
7
  import { randomBytes } from "crypto";
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  isSandboxEnabled,
4
4
  wrapForSandbox
5
- } from "./chunk-J4IBNXGJ.js";
5
+ } from "./chunk-IKHDUZRH.js";
6
6
  import {
7
7
  loadMergedEnv
8
- } from "./chunk-2WPW7OT6.js";
8
+ } from "./chunk-ZWKTUQEL.js";
9
9
  import {
10
10
  logger_default
11
11
  } from "./chunk-YUIHSKR6.js";
@@ -13,7 +13,7 @@ import {
13
13
  chownMindDir,
14
14
  isIsolationEnabled,
15
15
  wrapForIsolation
16
- } from "./chunk-RKQEHRBB.js";
16
+ } from "./chunk-G3GBKZGG.js";
17
17
  import {
18
18
  findMind,
19
19
  getDb,
@@ -23,7 +23,7 @@ import {
23
23
  stateDir,
24
24
  systemPrompts,
25
25
  voluteSystemDir
26
- } from "./chunk-H7OZRFJB.js";
26
+ } from "./chunk-HHTXM4JT.js";
27
27
 
28
28
  // src/lib/daemon/mind-manager.ts
29
29
  import { execFile, spawn } from "child_process";
@@ -82,7 +82,8 @@ var PROMPT_KEYS = [
82
82
  "reply_instructions",
83
83
  "channel_invite",
84
84
  "pre_sleep",
85
- "wake_summary"
85
+ "wake_summary",
86
+ "turn_summary"
86
87
  ];
87
88
  var PROMPT_DEFAULTS = {
88
89
  seed_soul: {
@@ -99,7 +100,10 @@ Have a conversation with the human. Explore what kind of mind you want to be. Wh
99
100
  default_soul: {
100
101
  content: `You are {{name}}.
101
102
  `,
102
- description: "SOUL.md for sprouted minds. Uses {{name}} placeholder (replaced at creation, not by ${var} system)",
103
+ description: (
104
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: describing template syntax, not using it
105
+ "SOUL.md for sprouted minds. Uses {{name}} placeholder (replaced at creation, not by ${var} system)"
106
+ ),
103
107
  variables: ["name"],
104
108
  category: "creation"
105
109
  },
@@ -172,9 +176,9 @@ To reject, delete \${filePath}`,
172
176
  category: "mind"
173
177
  },
174
178
  pre_sleep: {
175
- content: "Time to rest. You have this turn to wind down however feels right \u2014 reflect on your day, update your journal or memory, finish any threads of thought, or simply settle.\n\nYour current session will be archived and a fresh one will begin when you wake. Anything in session context that isn't saved to files will be lost.\n\nYou'll wake at ${wakeTime}. ${queuedInfo}",
179
+ content: "Time to rest. You have this turn to wind down however feels right \u2014 reflect on your day, update your journal or memory, finish any threads of thought, or simply settle.\n\nYour current session will be archived and a fresh one will begin when you wake. Anything in session context that isn't saved to files will be lost.\n\nYou'll wake at ${wakeTime}.",
176
180
  description: "Pre-sleep message sent before stopping the mind",
177
- variables: ["wakeTime", "queuedInfo"],
181
+ variables: ["wakeTime"],
178
182
  category: "system"
179
183
  },
180
184
  wake_summary: {
@@ -182,6 +186,12 @@ To reject, delete \${filePath}`,
182
186
  description: "Wake-up summary after scheduled sleep",
183
187
  variables: ["currentDate", "sleepTime", "duration", "sleepActivity"],
184
188
  category: "system"
189
+ },
190
+ turn_summary: {
191
+ content: "Summarize what this AI mind did in this turn in 1-2 concise sentences. Focus on what was accomplished, not the mechanics.",
192
+ description: "System prompt for AI-generated turn summaries",
193
+ variables: [],
194
+ category: "system"
185
195
  }
186
196
  };
187
197
  function isValidKey(key) {
@@ -456,7 +466,11 @@ var MindManager = class {
456
466
  if (isIsolationEnabled()) {
457
467
  [spawnCmd, spawnArgs] = await wrapForIsolation(tsxBin, tsxArgs, name);
458
468
  } else if (isSandboxEnabled()) {
459
- [spawnCmd, spawnArgs] = await wrapForSandbox(tsxBin, tsxArgs, dir, name);
469
+ [spawnCmd, spawnArgs] = await wrapForSandbox(tsxBin, tsxArgs, dir, name, [
470
+ dir,
471
+ mindStateDir,
472
+ "/tmp"
473
+ ]);
460
474
  } else {
461
475
  spawnCmd = tsxBin;
462
476
  spawnArgs = tsxArgs;
@@ -568,7 +582,7 @@ var MindManager = class {
568
582
  if (this.shuttingDown || this.stopping.has(name)) return;
569
583
  mlog.error(`mind ${name} exited with code ${code}`);
570
584
  try {
571
- const { getSleepManagerIfReady } = await import("./sleep-manager-WMVG2VCL.js");
585
+ const { getSleepManagerIfReady } = await import("./sleep-manager-O7YQFCV5.js");
572
586
  const sleepState = getSleepManagerIfReady()?.getState(name);
573
587
  if (sleepState?.sleeping) {
574
588
  mlog.info(`${name} is sleeping \u2014 skipping crash recovery`);
@@ -577,8 +591,8 @@ var MindManager = class {
577
591
  } catch (err) {
578
592
  mlog.warn(`failed to check sleep state for ${name}`, logger_default.errorData(err));
579
593
  }
580
- import("./mind-activity-tracker-EN6XNXPF.js").then(({ markIdle }) => markIdle(name)).catch((err) => mlog.warn(`failed to mark ${name} idle after crash`, logger_default.errorData(err)));
581
- import("./activity-events-BBIEA2F4.js").then(
594
+ import("./mind-activity-tracker-VYN2ZZ2M.js").then(({ markIdle }) => markIdle(name)).catch((err) => mlog.warn(`failed to mark ${name} idle after crash`, logger_default.errorData(err)));
595
+ import("./activity-events-BKBPPUBP.js").then(
582
596
  ({ publish }) => publish({ type: "mind_stopped", mind: name, summary: `${name} crashed (exit ${code})` })
583
597
  ).catch((err) => mlog.warn(`failed to publish crash event for ${name}`, logger_default.errorData(err)));
584
598
  const { shouldRestart, delay, attempt } = this.restartTracker.recordCrash(name);