volute 0.52.0 → 0.54.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.
- package/dist/{accept-5NK5XJB5.js → accept-RSDIVJL6.js} +3 -0
- package/dist/auto-upgrade-HEVZKPTF.js +46 -0
- package/dist/{backup-YVGV2ZNM.js → backup-QRNX6RK7.js} +10 -10
- package/dist/channels-CKCY64TD.js +203 -0
- package/dist/{chat-VAZ25KVT.js → chat-ZUGNL5GS.js} +5 -5
- package/dist/chunk-3LHUXY3E.js +102 -0
- package/dist/{chunk-SW2U6HRB.js → chunk-444RR3YF.js} +21 -4
- package/dist/{chunk-YVR6EHWL.js → chunk-56IT2ZXF.js} +160 -18
- package/dist/chunk-5RBEEAKW.js +58 -0
- package/dist/{chunk-OXWUEU5V.js → chunk-5U5GLZSD.js} +2 -2
- package/dist/{chunk-G7A5LEVI.js → chunk-7XKPG66D.js} +5 -5
- package/dist/{chunk-R772ET2M.js → chunk-AAPNU7GA.js} +4 -0
- package/dist/{chunk-XRWUQPCA.js → chunk-ATZF2RNJ.js} +25 -3
- package/dist/{chunk-6NLW72HP.js → chunk-CKPAVQNK.js} +1 -1
- package/dist/{chunk-JHKBALS2.js → chunk-CLCHOXLR.js} +1 -1
- package/dist/{chunk-DMK5ASKV.js → chunk-F6D766VQ.js} +6 -2
- package/dist/{chunk-AXFLY5GU.js → chunk-HKGYZVWN.js} +16 -1
- package/dist/{chunk-ZEZQNP2G.js → chunk-LGXVGIWN.js} +103 -25
- package/dist/{chunk-CW7BQKF6.js → chunk-LKUGUQUW.js} +3 -3
- package/dist/{chunk-FXWBFDQR.js → chunk-OAYY3WF3.js} +59 -12
- package/dist/{chunk-ITK6HV47.js → chunk-OGPVJ53N.js} +14 -6
- package/dist/{chunk-M77B73VV.js → chunk-OIOW3FPT.js} +7 -2
- package/dist/chunk-OT5SXF7L.js +904 -0
- package/dist/{chunk-EDR47UE2.js → chunk-OYF25B62.js} +1 -1
- package/dist/{chunk-RPPTGPYF.js → chunk-PPSN2MLC.js} +2 -2
- package/dist/{chunk-K2F237KS.js → chunk-RGHF3OK5.js} +154 -18
- package/dist/{chunk-RU74YG46.js → chunk-VDUCLVZI.js} +338 -30
- package/dist/{chunk-724DVYHU.js → chunk-WHL6PKYP.js} +10 -10
- package/dist/{chunk-EEOMA4DX.js → chunk-WZZCA23D.js} +2 -1
- package/dist/{chunk-UDZLPR34.js → chunk-YSRYCS3N.js} +13 -8
- package/dist/{chunk-5N32EN4O.js → chunk-Z4Q6TQWL.js} +1 -1
- package/dist/{chunk-VPOMJMV6.js → chunk-ZNHL5KQJ.js} +1 -1
- package/dist/cli.js +17 -17
- package/dist/{clock-ZT5YT6HA.js → clock-X7V3C7NL.js} +2 -2
- package/dist/{cloud-sync-H7EWZASD.js → cloud-sync-52YNJRMR.js} +12 -11
- package/dist/{daemon-restart-4FWUA5JF.js → daemon-restart-QWHN5VMU.js} +4 -4
- package/dist/daemon.js +538 -782
- package/dist/{db-IPXRJUI7.js → db-I4EH5SLF.js} +3 -1
- package/dist/{delivery-manager-VYXVKUMP.js → delivery-manager-7R2YIQ2W.js} +13 -7
- package/dist/delivery-notices-RZQ6GONP.js +18 -0
- package/dist/{delivery-router-RHANNTAC.js → delivery-router-QS4NLJR6.js} +3 -1
- package/dist/{down-QSNEMTTX.js → down-UN2EDX2Y.js} +3 -3
- package/dist/{echo-text-PEEV7FQU.js → echo-text-73CYQRL7.js} +14 -13
- package/dist/{exec-ABD3DYA2.js → exec-Z34TTUO3.js} +1 -1
- package/dist/{extensions-N6L5NYTK.js → extensions-QT65JGV6.js} +22 -11
- package/dist/{files-BRY5RRIM.js → files-PCKBQHAY.js} +2 -1
- package/dist/{isolation-GVV2IBAU.js → isolation-UQPDO34R.js} +1 -1
- package/dist/{message-delivery-7URC52ME.js → message-delivery-TRKT4T2P.js} +16 -13
- package/dist/migrate-name-placeholder-C7NCNLWF.js +37 -0
- package/dist/{mind-NEXGT3KE.js → mind-CT6ANXK4.js} +11 -11
- package/dist/{mind-contacts-QYU4TPEA.js → mind-contacts-PEXCDRXA.js} +6 -6
- package/dist/{mind-history-OGNR4L7W.js → mind-history-RZMMCHMX.js} +83 -11
- package/dist/{mind-list-SYRA7CH5.js → mind-list-7KBLPLES.js} +1 -1
- package/dist/{mind-service-E26ZQXDS.js → mind-service-7EFIJ3ZA.js} +12 -11
- package/dist/{mind-sleep-LZAFBDZD.js → mind-sleep-24HV4RCA.js} +2 -2
- package/dist/{mind-status-Z2LQFA6F.js → mind-status-4YW4PHMO.js} +15 -0
- package/dist/{package-2W2XKSIP.js → package-F6S5NHY2.js} +4 -4
- package/dist/{prompts-NBO3HRK3.js → prompts-JECJIFPQ.js} +1 -1
- package/dist/{reject-TWB4QJHG.js → reject-4NFLXKRN.js} +6 -2
- package/dist/{scheduler-JTTWZDYU.js → scheduler-73Q4MQ7Y.js} +8 -6
- package/dist/{seed-64XEHRUP.js → seed-DRKAP3XV.js} +1 -1
- package/dist/{seed-cmd-UEL2QB3Q.js → seed-cmd-6IMTO3LG.js} +2 -2
- package/dist/{seed-create-4JRQDPGA.js → seed-create-VNLDYRFK.js} +1 -1
- package/dist/{seed-readiness-DYOVCYHN.js → seed-readiness-H5TTPAQH.js} +2 -2
- package/dist/{seed-sprout-NIDIOJXT.js → seed-sprout-PPGYGK4G.js} +5 -5
- package/dist/{send-2YKOZJJ5.js → send-UXUQKO4N.js} +37 -22
- package/dist/{service-XQPMZAGI.js → service-T4P5W6RS.js} +2 -2
- package/dist/{service-install-2EWD7KXD.js → service-install-R4SNYUVO.js} +3 -3
- package/dist/{setup-4IX6PCD3.js → setup-YUAQMDVZ.js} +4 -4
- package/dist/skills/dreaming/SKILL.md +2 -2
- package/dist/skills/dreaming/references/INSTALL.md +1 -1
- package/dist/skills/memory/SKILL.md +47 -43
- package/dist/skills/tending/SKILL.md +2 -0
- package/dist/skills/volute-mind/references/integrations.md +3 -2
- package/dist/skills/volute-mind/references/routing.md +18 -5
- package/dist/{skills-MPUALV3S.js → skills-GMQ5UIIW.js} +2 -2
- package/dist/{sleep-manager-OFP2GFXF.js → sleep-manager-KHI65FEX.js} +12 -11
- package/dist/{spirit-4ECYIVGE.js → spirit-Q5VGFWUI.js} +19 -3
- package/dist/{spirit-availability-Y54Y3675.js → spirit-availability-G5FMWKRH.js} +13 -12
- package/dist/{sprout-GJMZFRGZ.js → sprout-PMTRL7QN.js} +1 -1
- package/dist/{src-LCSOQY6Z.js → src-3FIW7DLH.js} +241 -87
- package/dist/src-H3UCOP6B.js +516 -0
- package/dist/{src-HGNE2XG4.js → src-LTTQVN2Z.js} +1 -1
- package/dist/{status-MWLE3RVC.js → status-LCKTTIWS.js} +2 -2
- package/dist/{system-events-V43HDA3T.js → system-events-Q7IVZ5T4.js} +5 -1
- package/dist/{systems-VDRUZXNF.js → systems-HL7SGSW7.js} +2 -2
- package/dist/{turn-tracker-C5PVIC3B.js → turn-tracker-HZDPMSCC.js} +4 -2
- package/dist/{up-H6LJZDRK.js → up-XZDSJVMU.js} +3 -3
- package/dist/{update-CIWI2JYA.js → update-ILCPVNDD.js} +2 -2
- package/dist/{upgrade-LIE46UBB.js → upgrade-XY2J7NWZ.js} +9 -1
- package/dist/{variant-cleanup-STC6B5HR.js → variant-cleanup-QHGGY7ND.js} +8 -6
- package/dist/{version-notify-LBVHH5YV.js → version-notify-VNVFX6UP.js} +22 -7
- package/dist/web-assets/assets/{index-B_eYTa3R.js → index-CwtxGwe_.js} +16 -16
- package/dist/web-assets/assets/index-DhM1yYRN.css +1 -0
- package/dist/web-assets/index.html +2 -2
- package/package.json +4 -4
- package/packages/extensions/intentions/dist/ui/assets/index-3FneLCKR.css +1 -0
- package/packages/extensions/intentions/dist/ui/assets/index-CQz4aceM.js +67 -0
- package/packages/extensions/{plan → intentions}/dist/ui/index.html +3 -3
- package/packages/extensions/intentions/skills/intention-review/SKILL.md +38 -0
- package/packages/extensions/intentions/skills/intentions/SKILL.md +49 -0
- package/packages/extensions/intentions/skills/intentions/scripts/intentions-hook.sh +45 -0
- package/packages/extensions/pages/skills/commons-gardening/SKILL.md +50 -0
- package/packages/extensions/pages/skills/pages/SKILL.md +18 -13
- package/templates/_base/.init/.config/prompts.json +3 -3
- package/templates/{pi → _base}/.init/.config/routes.json +1 -0
- package/templates/_base/.init/memory/dreams/.gitkeep +0 -0
- package/templates/_base/home/.config/routes.json +1 -1
- package/templates/_base/home/VOLUTE.md +1 -1
- package/templates/_base/src/lib/codex-session-seed.ts +463 -0
- package/templates/_base/src/lib/context-breakdown.ts +11 -3
- package/templates/_base/src/lib/daemon-client.ts +35 -0
- package/templates/_base/src/lib/pi-session-seed.ts +434 -0
- package/templates/_base/src/lib/routing.ts +2 -2
- package/templates/_base/src/lib/seed-note.ts +78 -0
- package/templates/_base/src/lib/session-seed.ts +375 -0
- package/templates/_base/src/lib/startup.ts +112 -6
- package/templates/claude/.init/CLAUDE.md +7 -3
- package/templates/claude/src/agent.ts +295 -101
- package/templates/claude/src/lib/hooks/pre-compact.ts +30 -5
- package/templates/claude/src/lib/message-channel.ts +43 -15
- package/templates/claude/src/lib/recover.ts +69 -0
- package/templates/claude/src/lib/stream-consumer.ts +33 -2
- package/templates/claude/src/server.ts +2 -1
- package/templates/claude/volute-template.json +1 -1
- package/templates/codex/.init/AGENTS.md +7 -3
- package/templates/codex/src/agent.ts +256 -39
- package/templates/codex/src/server.ts +2 -1
- package/templates/codex/volute-template.json +1 -1
- package/templates/pi/.init/MINDS.md +7 -3
- package/templates/pi/src/agent.ts +269 -43
- package/templates/pi/src/lib/event-handler.ts +11 -0
- package/templates/pi/src/lib/mechanics-doc.ts +30 -0
- package/templates/pi/src/server.ts +5 -1
- package/templates/pi/volute-template.json +1 -1
- package/dist/channels-FSAHOQWI.js +0 -90
- package/dist/skills/plan-coordinator/SKILL.md +0 -60
- package/dist/src-UDMJZ6MH.js +0 -426
- package/dist/web-assets/assets/index-DhZrzddW.css +0 -1
- package/packages/extensions/plan/dist/ui/assets/index-B8s8wxyt.js +0 -67
- package/packages/extensions/plan/dist/ui/assets/index-jIkrt-vI.css +0 -1
- package/packages/extensions/plan/skills/plan/SKILL.md +0 -43
- package/packages/extensions/plan/skills/plan/scripts/plan-hook.sh +0 -37
- package/templates/claude/.init/.config/routes.json +0 -11
- package/templates/codex/.init/.config/routes.json +0 -11
- package/dist/{env-IBW2QI6K.js → env-7AZFBPWX.js} +5 -5
- package/dist/{login-RJJTCVR3.js → login-4NUS72Z5.js} +3 -3
- package/dist/{login-SB5OENMV.js → login-57MMYILL.js} +4 -4
- package/dist/{register-OX4HRSGC.js → register-WNCSOTAU.js} +3 -3
- package/dist/{restart-AGEGNSYQ.js → restart-B4GNMVF2.js} +4 -4
- package/dist/{skill-B5OJEQUA.js → skill-QYTBUDNQ.js} +4 -4
- package/dist/{start-MUMNFR52.js → start-BDHJVOVX.js} +3 -3
- package/dist/{stop-EKERNYTX.js → stop-45QYSGYS.js} +4 -4
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getUserByUsername
|
|
4
|
+
} from "./chunk-7LT3YZUR.js";
|
|
2
5
|
import {
|
|
3
6
|
publish
|
|
4
7
|
} from "./chunk-LNNI3MS4.js";
|
|
5
8
|
import {
|
|
6
9
|
getPrompt
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-OAYY3WF3.js";
|
|
8
11
|
import {
|
|
9
12
|
aiCompleteUtility
|
|
10
13
|
} from "./chunk-EGV6R6UF.js";
|
|
@@ -12,7 +15,8 @@ import {
|
|
|
12
15
|
logger_default
|
|
13
16
|
} from "./chunk-QUSMYGNQ.js";
|
|
14
17
|
import {
|
|
15
|
-
getDb
|
|
18
|
+
getDb,
|
|
19
|
+
resolveMindDir
|
|
16
20
|
} from "./chunk-H6X6CKDN.js";
|
|
17
21
|
import {
|
|
18
22
|
messages,
|
|
@@ -26,6 +30,8 @@ import { randomUUID } from "crypto";
|
|
|
26
30
|
import { and as and2, eq as eq2, inArray as inArray2, sql as sql2 } from "drizzle-orm";
|
|
27
31
|
|
|
28
32
|
// packages/daemon/src/lib/daemon/summarizer.ts
|
|
33
|
+
import { readFile } from "fs/promises";
|
|
34
|
+
import { join } from "path";
|
|
29
35
|
import { and, desc, eq, gte, inArray, like, lt, sql } from "drizzle-orm";
|
|
30
36
|
|
|
31
37
|
// packages/daemon/src/lib/util/format-tool.ts
|
|
@@ -181,6 +187,12 @@ function getTimeRange(periodKey, period) {
|
|
|
181
187
|
}
|
|
182
188
|
}
|
|
183
189
|
|
|
190
|
+
// packages/daemon/src/lib/util/time.ts
|
|
191
|
+
function parseDbTimestamp(ts) {
|
|
192
|
+
if (/[zZ]$|[+-]\d\d:?\d\d$/.test(ts)) return new Date(ts);
|
|
193
|
+
return /* @__PURE__ */ new Date(`${ts.replace(" ", "T")}Z`);
|
|
194
|
+
}
|
|
195
|
+
|
|
184
196
|
// packages/daemon/src/lib/daemon/summarizer.ts
|
|
185
197
|
var sLog = logger_default.child("summarizer");
|
|
186
198
|
var SYSTEM_MIND = "_system";
|
|
@@ -205,6 +217,7 @@ async function gatherTurnEvents(mind, session, doneId) {
|
|
|
205
217
|
type: mindHistory.type,
|
|
206
218
|
channel: mindHistory.channel,
|
|
207
219
|
session: mindHistory.thread,
|
|
220
|
+
sender: mindHistory.sender,
|
|
208
221
|
content: mindHistory.content,
|
|
209
222
|
metadata: mindHistory.metadata,
|
|
210
223
|
turn_id: mindHistory.turn_id,
|
|
@@ -223,6 +236,7 @@ async function gatherTurnEventsByTurnId(turnId) {
|
|
|
223
236
|
type: mindHistory.type,
|
|
224
237
|
channel: mindHistory.channel,
|
|
225
238
|
session: mindHistory.thread,
|
|
239
|
+
sender: mindHistory.sender,
|
|
226
240
|
content: mindHistory.content,
|
|
227
241
|
metadata: mindHistory.metadata,
|
|
228
242
|
turn_id: mindHistory.turn_id,
|
|
@@ -289,13 +303,19 @@ function buildTurnDeterministicSummary(events, parsedMeta) {
|
|
|
289
303
|
}
|
|
290
304
|
return parts.length > 0 ? `${parts.join(". ")}.` : "Turn completed.";
|
|
291
305
|
}
|
|
292
|
-
function buildTranscript(events, parsedMeta) {
|
|
306
|
+
function buildTranscript(events, parsedMeta, mind) {
|
|
293
307
|
const lines = [];
|
|
294
308
|
for (const ev of events) {
|
|
295
309
|
switch (ev.type) {
|
|
296
|
-
|
|
297
|
-
|
|
310
|
+
// Inbound messages come from *other* people. Attribute them to the sender by name (and
|
|
311
|
+
// channel) so the summarizer never absorbs someone else's first-person statements into
|
|
312
|
+
// the mind's own "I" in a multi-party channel.
|
|
313
|
+
case "inbound": {
|
|
314
|
+
const on = ev.channel ? ` on ${ev.channel}` : "";
|
|
315
|
+
const from = ev.sender ? ` from ${ev.sender}` : "";
|
|
316
|
+
lines.push(`[inbound${on}${from}] ${ev.content ?? ""}`);
|
|
298
317
|
break;
|
|
318
|
+
}
|
|
299
319
|
// A system event is what triggered the turn — the summarizer needs to see it, or a
|
|
300
320
|
// schedule/orientation/wake turn gets summarized from its tool calls alone, with no
|
|
301
321
|
// idea what prompted them. Framed as an event, not an inbound message: it has no
|
|
@@ -306,9 +326,12 @@ function buildTranscript(events, parsedMeta) {
|
|
|
306
326
|
lines.push(`[system event${named}] ${ev.content ?? ""}`);
|
|
307
327
|
break;
|
|
308
328
|
}
|
|
329
|
+
// The mind's own output/thoughts, labeled with its name so the "I" is unambiguous. Never
|
|
330
|
+
// truncated — a mid-sentence fragment is worse than a long line, because the model
|
|
331
|
+
// interpolates over the cut and invents a false memory.
|
|
309
332
|
case "outbound":
|
|
310
333
|
case "text":
|
|
311
|
-
lines.push(`[
|
|
334
|
+
lines.push(`[${mind} replied] ${ev.content ?? ""}`);
|
|
312
335
|
break;
|
|
313
336
|
case "tool_use": {
|
|
314
337
|
const meta = parsedMeta.get(ev.id);
|
|
@@ -329,12 +352,26 @@ function buildTranscript(events, parsedMeta) {
|
|
|
329
352
|
break;
|
|
330
353
|
}
|
|
331
354
|
case "thinking":
|
|
332
|
-
lines.push(`[thinking] ${
|
|
355
|
+
lines.push(`[${mind} thinking] ${ev.content ?? ""}`);
|
|
333
356
|
break;
|
|
334
357
|
}
|
|
335
358
|
}
|
|
336
359
|
return lines.join("\n");
|
|
337
360
|
}
|
|
361
|
+
async function getMindIdentityLine(mind) {
|
|
362
|
+
try {
|
|
363
|
+
const user = await getUserByUsername(mind);
|
|
364
|
+
if (!user) return "";
|
|
365
|
+
const name = user.display_name?.trim();
|
|
366
|
+
const desc2 = user.description?.trim();
|
|
367
|
+
if (!name && !desc2) return "";
|
|
368
|
+
const who = name ? `${mind} (${name})` : mind;
|
|
369
|
+
return `[about the mind] ${who}${desc2 ? `: ${desc2}` : ""}`;
|
|
370
|
+
} catch (err) {
|
|
371
|
+
sLog.debug(`failed to load identity for ${mind}`, logger_default.errorData(err));
|
|
372
|
+
return "";
|
|
373
|
+
}
|
|
374
|
+
}
|
|
338
375
|
async function summarizeTurn(mind, session, channel, doneId, turnId) {
|
|
339
376
|
const { events, fromId, toId } = turnId ? await gatherTurnEventsByTurnId(turnId) : await gatherTurnEvents(mind, session, doneId);
|
|
340
377
|
if (events.length === 0) return;
|
|
@@ -377,10 +414,14 @@ async function summarizeTurn(mind, session, channel, doneId, turnId) {
|
|
|
377
414
|
const toTime = events[events.length - 1].created_at;
|
|
378
415
|
let summaryText;
|
|
379
416
|
let deterministic;
|
|
380
|
-
const transcript = buildTranscript(events, parsedMeta);
|
|
417
|
+
const transcript = buildTranscript(events, parsedMeta, mind);
|
|
381
418
|
if (transcript.trim()) {
|
|
382
|
-
const summaryPrompt = await getPrompt("turn_summary");
|
|
383
|
-
const
|
|
419
|
+
const summaryPrompt = await getPrompt("turn_summary", { mind });
|
|
420
|
+
const identity = await getMindIdentityLine(mind);
|
|
421
|
+
const input = identity ? `${identity}
|
|
422
|
+
|
|
423
|
+
${transcript}` : transcript;
|
|
424
|
+
const aiResult = await aiCompleteUtility(summaryPrompt, input);
|
|
384
425
|
if (aiResult) {
|
|
385
426
|
summaryText = aiResult;
|
|
386
427
|
deterministic = false;
|
|
@@ -449,6 +490,62 @@ async function setSummaryId(turnId, summaryId) {
|
|
|
449
490
|
const db = await getDb();
|
|
450
491
|
await db.update(turns).set({ summary_id: summaryId }).where(eq(turns.id, turnId));
|
|
451
492
|
}
|
|
493
|
+
var MIND_TURN_SUMMARY_MAX_CHARS = 4e3;
|
|
494
|
+
async function supersedeTurnSummary(mind, turnId, content) {
|
|
495
|
+
const text = content.trim();
|
|
496
|
+
if (!text) return { status: "invalid", error: "content is required" };
|
|
497
|
+
if (text.length > MIND_TURN_SUMMARY_MAX_CHARS) {
|
|
498
|
+
return {
|
|
499
|
+
status: "invalid",
|
|
500
|
+
error: `content exceeds ${MIND_TURN_SUMMARY_MAX_CHARS} characters`
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
const db = await getDb();
|
|
504
|
+
const turn = await db.select().from(turns).where(eq(turns.id, turnId)).get();
|
|
505
|
+
if (!turn) return { status: "not_found" };
|
|
506
|
+
if (turn.mind !== mind) return { status: "forbidden" };
|
|
507
|
+
const existing = await db.select({ id: summaries.id, content: summaries.content, metadata: summaries.metadata }).from(summaries).where(
|
|
508
|
+
and(eq(summaries.mind, mind), eq(summaries.period, "turn"), eq(summaries.period_key, turnId))
|
|
509
|
+
).get();
|
|
510
|
+
const authoredAt = utcDateTimeStr(/* @__PURE__ */ new Date());
|
|
511
|
+
let created;
|
|
512
|
+
if (existing) {
|
|
513
|
+
const prevMeta = parseMeta(existing.metadata);
|
|
514
|
+
let superseded = prevMeta.superseded;
|
|
515
|
+
if (superseded === void 0) {
|
|
516
|
+
const captured = { content: existing.content };
|
|
517
|
+
if (typeof prevMeta.deterministic === "boolean")
|
|
518
|
+
captured.deterministic = prevMeta.deterministic;
|
|
519
|
+
superseded = captured;
|
|
520
|
+
}
|
|
521
|
+
const metadata = { ...prevMeta, author: "mind", authored_at: authoredAt, superseded };
|
|
522
|
+
await db.update(summaries).set({ content: text, metadata: JSON.stringify(metadata) }).where(eq(summaries.id, existing.id));
|
|
523
|
+
created = false;
|
|
524
|
+
} else {
|
|
525
|
+
const metadata = { author: "mind", authored_at: authoredAt };
|
|
526
|
+
const result = await db.insert(summaries).values({
|
|
527
|
+
mind,
|
|
528
|
+
period: "turn",
|
|
529
|
+
period_key: turnId,
|
|
530
|
+
content: text,
|
|
531
|
+
metadata: JSON.stringify(metadata)
|
|
532
|
+
}).returning({ id: summaries.id });
|
|
533
|
+
const summaryId = result[0]?.id;
|
|
534
|
+
if (summaryId != null && turn.summary_id == null) {
|
|
535
|
+
await setSummaryId(turnId, summaryId);
|
|
536
|
+
}
|
|
537
|
+
created = true;
|
|
538
|
+
}
|
|
539
|
+
publish(mind, {
|
|
540
|
+
mind,
|
|
541
|
+
type: "summary",
|
|
542
|
+
session: turn.thread ?? void 0,
|
|
543
|
+
content: text,
|
|
544
|
+
metadata: { author: "mind", authored_at: authoredAt },
|
|
545
|
+
turnId
|
|
546
|
+
});
|
|
547
|
+
return { status: "ok", created };
|
|
548
|
+
}
|
|
452
549
|
function getChildPeriod(period) {
|
|
453
550
|
switch (period) {
|
|
454
551
|
case "hour":
|
|
@@ -561,12 +658,32 @@ function trackProvisionalAttempt(metadata, prev) {
|
|
|
561
658
|
metadata.first_attempt_at = prev && typeof prev.first_attempt_at === "string" ? prev.first_attempt_at : (/* @__PURE__ */ new Date()).toISOString();
|
|
562
659
|
metadata.last_attempt_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
563
660
|
}
|
|
661
|
+
function childLabel(period, key2, createdAt) {
|
|
662
|
+
switch (period) {
|
|
663
|
+
case "hour": {
|
|
664
|
+
const d = parseDbTimestamp(createdAt);
|
|
665
|
+
const hh = String(d.getHours()).padStart(2, "0");
|
|
666
|
+
const mm = String(d.getMinutes()).padStart(2, "0");
|
|
667
|
+
return `${hh}:${mm}`;
|
|
668
|
+
}
|
|
669
|
+
case "day":
|
|
670
|
+
return `${key2.slice(11)}:00`;
|
|
671
|
+
case "week":
|
|
672
|
+
case "month":
|
|
673
|
+
return key2;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
564
676
|
async function gatherChildSummaries(mind, period, periodKey) {
|
|
565
677
|
const db = await getDb();
|
|
566
678
|
const childPeriod = getChildPeriod(period);
|
|
567
679
|
if (period === "hour") {
|
|
568
680
|
const { start: start2, end: end2 } = getTimeRange(periodKey, "hour");
|
|
569
|
-
const rows2 = await db.select({
|
|
681
|
+
const rows2 = await db.select({
|
|
682
|
+
id: summaries.id,
|
|
683
|
+
content: summaries.content,
|
|
684
|
+
key: summaries.period_key,
|
|
685
|
+
created_at: summaries.created_at
|
|
686
|
+
}).from(summaries).where(
|
|
570
687
|
and(
|
|
571
688
|
eq(summaries.mind, mind),
|
|
572
689
|
eq(summaries.period, childPeriod),
|
|
@@ -577,7 +694,8 @@ async function gatherChildSummaries(mind, period, periodKey) {
|
|
|
577
694
|
return {
|
|
578
695
|
texts: rows2.map((r) => r.content),
|
|
579
696
|
sourceIds: rows2.map((r) => r.id),
|
|
580
|
-
keys: rows2.map((r) => r.key)
|
|
697
|
+
keys: rows2.map((r) => r.key),
|
|
698
|
+
labels: rows2.map((r) => childLabel(period, r.key, r.created_at))
|
|
581
699
|
};
|
|
582
700
|
}
|
|
583
701
|
if (period === "day") {
|
|
@@ -591,7 +709,8 @@ async function gatherChildSummaries(mind, period, periodKey) {
|
|
|
591
709
|
return {
|
|
592
710
|
texts: rows2.map((r) => r.content),
|
|
593
711
|
sourceIds: rows2.map((r) => r.id),
|
|
594
|
-
keys: rows2.map((r) => r.key)
|
|
712
|
+
keys: rows2.map((r) => r.key),
|
|
713
|
+
labels: rows2.map((r) => childLabel(period, r.key, ""))
|
|
595
714
|
};
|
|
596
715
|
}
|
|
597
716
|
const { start, end } = getTimeRange(periodKey, period);
|
|
@@ -608,9 +727,20 @@ async function gatherChildSummaries(mind, period, periodKey) {
|
|
|
608
727
|
return {
|
|
609
728
|
texts: rows.map((r) => r.content),
|
|
610
729
|
sourceIds: rows.map((r) => r.id),
|
|
611
|
-
keys: rows.map((r) => r.key)
|
|
730
|
+
keys: rows.map((r) => r.key),
|
|
731
|
+
labels: rows.map((r) => childLabel(period, r.key, ""))
|
|
612
732
|
};
|
|
613
733
|
}
|
|
734
|
+
var SOUL_MAX_CHARS = 8e3;
|
|
735
|
+
async function readMindSoul(mind) {
|
|
736
|
+
try {
|
|
737
|
+
const dir = await resolveMindDir(mind);
|
|
738
|
+
const soul = await readFile(join(dir, "home", "SOUL.md"), "utf8");
|
|
739
|
+
return soul.length > SOUL_MAX_CHARS ? soul.slice(0, SOUL_MAX_CHARS) : soul;
|
|
740
|
+
} catch {
|
|
741
|
+
return "";
|
|
742
|
+
}
|
|
743
|
+
}
|
|
614
744
|
async function summarizePeriod(mind, period, periodKey, complete = aiCompleteUtility) {
|
|
615
745
|
const db = await getDb();
|
|
616
746
|
const existing = await db.select({ id: summaries.id, metadata: summaries.metadata }).from(summaries).where(
|
|
@@ -651,8 +781,18 @@ async function summarizePeriod(mind, period, periodKey, complete = aiCompleteUti
|
|
|
651
781
|
const entries = sources.texts.map((text, i) => ({ key: sources.keys[i], text }));
|
|
652
782
|
const promptKey = `meta_summary_${period}`;
|
|
653
783
|
const scopeInstruction = getScopeInstruction(mind);
|
|
654
|
-
|
|
655
|
-
|
|
784
|
+
let systemPrompt = await getPrompt(promptKey, { scope_instruction: scopeInstruction });
|
|
785
|
+
if (period === "week" || period === "month") {
|
|
786
|
+
const soul = await readMindSoul(mind);
|
|
787
|
+
if (soul.trim()) {
|
|
788
|
+
systemPrompt = `${systemPrompt}
|
|
789
|
+
|
|
790
|
+
For voice and perspective, this is the mind's own self-description (SOUL.md):
|
|
791
|
+
|
|
792
|
+
${soul.trim()}`;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
const userMessage = sources.texts.map((text, i) => `[${sources.labels[i]}] ${text}`).join("\n\n---\n\n");
|
|
656
796
|
let content;
|
|
657
797
|
let deterministic;
|
|
658
798
|
const metadata = {
|
|
@@ -1060,11 +1200,11 @@ var Summarizer = class {
|
|
|
1060
1200
|
}
|
|
1061
1201
|
};
|
|
1062
1202
|
async function reconcileWedgedTurns(idleMs) {
|
|
1063
|
-
const { sweepWedgedTurns: sweepWedgedTurns2, summarizeOrphanedTurns: summarizeOrphanedTurns2 } = await import("./turn-tracker-
|
|
1203
|
+
const { sweepWedgedTurns: sweepWedgedTurns2, summarizeOrphanedTurns: summarizeOrphanedTurns2 } = await import("./turn-tracker-HZDPMSCC.js");
|
|
1064
1204
|
const wedged = await sweepWedgedTurns2(idleMs);
|
|
1065
1205
|
if (wedged.length === 0) return;
|
|
1066
1206
|
summarizeOrphanedTurns2(wedged);
|
|
1067
|
-
const { tryGetDeliveryManager } = await import("./delivery-manager-
|
|
1207
|
+
const { tryGetDeliveryManager } = await import("./delivery-manager-7R2YIQ2W.js");
|
|
1068
1208
|
const dm = tryGetDeliveryManager();
|
|
1069
1209
|
if (!dm) return;
|
|
1070
1210
|
for (const t of wedged) {
|
|
@@ -1268,8 +1408,10 @@ export {
|
|
|
1268
1408
|
utcDateTimeStr,
|
|
1269
1409
|
parseUtcDateTime,
|
|
1270
1410
|
getUtcTimeRange,
|
|
1411
|
+
parseDbTimestamp,
|
|
1271
1412
|
SYSTEM_MIND,
|
|
1272
1413
|
summarizeTurn,
|
|
1414
|
+
supersedeTurnSummary,
|
|
1273
1415
|
initSummarizer,
|
|
1274
1416
|
markErrored,
|
|
1275
1417
|
takeErrored,
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// packages/daemon/src/lib/mind/memory-size.ts
|
|
4
|
+
import { readFileSync, statSync } from "fs";
|
|
5
|
+
import { resolve } from "path";
|
|
6
|
+
var MEMORY_SOFT_BUDGET_TOKENS = 5e3;
|
|
7
|
+
var MEMORY_HARD_CAP_TOKENS = 25e3;
|
|
8
|
+
var MAX_READ_BYTES = 1e6;
|
|
9
|
+
function getMemoryStatus(projectDir) {
|
|
10
|
+
const path = resolve(projectDir, "home", "MEMORY.md");
|
|
11
|
+
let bytes;
|
|
12
|
+
let chars;
|
|
13
|
+
try {
|
|
14
|
+
const size = statSync(path).size;
|
|
15
|
+
if (size > MAX_READ_BYTES) {
|
|
16
|
+
bytes = size;
|
|
17
|
+
chars = size;
|
|
18
|
+
} else {
|
|
19
|
+
const text = readFileSync(path, "utf-8");
|
|
20
|
+
bytes = size;
|
|
21
|
+
chars = text.length;
|
|
22
|
+
}
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
let softBudgetTokens = MEMORY_SOFT_BUDGET_TOKENS;
|
|
27
|
+
let hardCapTokens = MEMORY_HARD_CAP_TOKENS;
|
|
28
|
+
try {
|
|
29
|
+
const config = JSON.parse(
|
|
30
|
+
readFileSync(resolve(projectDir, "home", ".config", "config.json"), "utf-8")
|
|
31
|
+
);
|
|
32
|
+
if (typeof config?.memory?.softBudgetTokens === "number") {
|
|
33
|
+
softBudgetTokens = config.memory.softBudgetTokens;
|
|
34
|
+
}
|
|
35
|
+
if (typeof config?.memory?.hardCapTokens === "number") {
|
|
36
|
+
hardCapTokens = config.memory.hardCapTokens;
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
const estTokens = Math.round(chars / 4);
|
|
41
|
+
return {
|
|
42
|
+
bytes,
|
|
43
|
+
estTokens,
|
|
44
|
+
softBudgetTokens,
|
|
45
|
+
hardCapTokens,
|
|
46
|
+
overBudget: estTokens > softBudgetTokens,
|
|
47
|
+
overHardCap: estTokens > hardCapTokens
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function formatTokens(tokens) {
|
|
51
|
+
if (tokens < 1e3) return `~${tokens} tokens`;
|
|
52
|
+
return `~${(tokens / 1e3).toFixed(1).replace(/\.0$/, "")}k tokens`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export {
|
|
56
|
+
getMemoryStatus,
|
|
57
|
+
formatTokens
|
|
58
|
+
};
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
LAUNCHD_PLIST_LABEL,
|
|
4
4
|
LAUNCHD_PLIST_PATH,
|
|
5
5
|
USER_SYSTEMD_UNIT
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-CKPAVQNK.js";
|
|
7
7
|
import {
|
|
8
8
|
resolveVoluteBin
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OIOW3FPT.js";
|
|
10
10
|
|
|
11
11
|
// packages/daemon/src/lib/config/service-install.ts
|
|
12
12
|
import { execFile } from "child_process";
|
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
compactDateTime,
|
|
4
4
|
isCompact
|
|
5
5
|
} from "./chunk-7YJY3F2R.js";
|
|
6
|
+
import {
|
|
7
|
+
getClient,
|
|
8
|
+
urlOf
|
|
9
|
+
} from "./chunk-LOPXTW6H.js";
|
|
6
10
|
import {
|
|
7
11
|
resolveMindName
|
|
8
12
|
} from "./chunk-BTY4WNFE.js";
|
|
9
13
|
import {
|
|
10
14
|
daemonFetch
|
|
11
15
|
} from "./chunk-M74I3HHF.js";
|
|
12
|
-
import {
|
|
13
|
-
getClient,
|
|
14
|
-
urlOf
|
|
15
|
-
} from "./chunk-LOPXTW6H.js";
|
|
16
16
|
import {
|
|
17
17
|
command,
|
|
18
18
|
subcommands
|
|
@@ -279,7 +279,7 @@ var cmd = subcommands({
|
|
|
279
279
|
},
|
|
280
280
|
sleep: {
|
|
281
281
|
description: "Put a mind to sleep",
|
|
282
|
-
run: (args) => import("./mind-sleep-
|
|
282
|
+
run: (args) => import("./mind-sleep-24HV4RCA.js").then((m) => m.run(args))
|
|
283
283
|
},
|
|
284
284
|
wake: {
|
|
285
285
|
description: "Wake a sleeping mind",
|
|
@@ -79,6 +79,9 @@ function getSystemPages(db) {
|
|
|
79
79
|
)
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
+
function getMindsWithSites(db) {
|
|
83
|
+
return db.prepare("SELECT DISTINCT mind FROM published_pages WHERE mind != '_system' ORDER BY mind").all().map((r) => r.mind);
|
|
84
|
+
}
|
|
82
85
|
function syncSystemPages(db, pages, author) {
|
|
83
86
|
const existing = new Map(
|
|
84
87
|
db.prepare("SELECT file, hash FROM published_pages WHERE mind = '_system'").all().map((r) => [r.file, r.hash])
|
|
@@ -159,6 +162,7 @@ export {
|
|
|
159
162
|
getRecentPages,
|
|
160
163
|
getAllSites,
|
|
161
164
|
getSystemPages,
|
|
165
|
+
getMindsWithSites,
|
|
162
166
|
syncSystemPages,
|
|
163
167
|
syncPublishedPages
|
|
164
168
|
};
|
|
@@ -5,7 +5,10 @@ import {
|
|
|
5
5
|
} from "./chunk-L7BKTZ5U.js";
|
|
6
6
|
import {
|
|
7
7
|
recordOutbound
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-LGXVGIWN.js";
|
|
9
|
+
import {
|
|
10
|
+
recordSenderDeliveryFailure
|
|
11
|
+
} from "./chunk-3LHUXY3E.js";
|
|
9
12
|
import {
|
|
10
13
|
getOrCreateMindUser,
|
|
11
14
|
getUserByUsername
|
|
@@ -27,7 +30,7 @@ import {
|
|
|
27
30
|
import {
|
|
28
31
|
daemonConfigPath,
|
|
29
32
|
readDaemonToken
|
|
30
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-CKPAVQNK.js";
|
|
31
34
|
import {
|
|
32
35
|
readEnv,
|
|
33
36
|
sharedEnvPath
|
|
@@ -732,7 +735,21 @@ async function routeChannelOutbound(channelName, senderName, contentBlocks) {
|
|
|
732
735
|
if (!text) return;
|
|
733
736
|
const env = readEnv(sharedEnvPath());
|
|
734
737
|
env.VOLUTE_SENDER = senderName;
|
|
735
|
-
|
|
738
|
+
try {
|
|
739
|
+
await driver.send(
|
|
740
|
+
env,
|
|
741
|
+
bridgeInfo.externalChannel,
|
|
742
|
+
text,
|
|
743
|
+
images.length > 0 ? images : void 0
|
|
744
|
+
);
|
|
745
|
+
} catch (err) {
|
|
746
|
+
await recordSenderDeliveryFailure(
|
|
747
|
+
senderName,
|
|
748
|
+
channelName,
|
|
749
|
+
err instanceof Error && err.message ? err.message : String(err)
|
|
750
|
+
);
|
|
751
|
+
throw err;
|
|
752
|
+
}
|
|
736
753
|
logger_default.debug(`bridge outbound: sent to ${bridgeInfo.platform}:${bridgeInfo.externalChannel}`);
|
|
737
754
|
}
|
|
738
755
|
async function routeDMOutbound(conversationId, senderName, contentBlocks) {
|
|
@@ -768,6 +785,11 @@ async function routeDMOutbound(conversationId, senderName, contentBlocks) {
|
|
|
768
785
|
logger_default.debug(`bridge outbound DM: sent to ${platform}:${externalUserId}`);
|
|
769
786
|
} catch (err) {
|
|
770
787
|
logger_default.error(`bridge outbound DM failed for puppet ${puppet.username}`, logger_default.errorData(err));
|
|
788
|
+
await recordSenderDeliveryFailure(
|
|
789
|
+
senderName,
|
|
790
|
+
puppet.username,
|
|
791
|
+
err instanceof Error && err.message ? err.message : String(err)
|
|
792
|
+
);
|
|
771
793
|
}
|
|
772
794
|
}
|
|
773
795
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
logger_default
|
|
4
|
+
} from "./chunk-QUSMYGNQ.js";
|
|
2
5
|
import {
|
|
3
6
|
stateDir
|
|
4
7
|
} from "./chunk-H6X6CKDN.js";
|
|
@@ -7,6 +10,7 @@ import {
|
|
|
7
10
|
import { randomBytes } from "crypto";
|
|
8
11
|
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
9
12
|
import { basename, join, normalize, resolve } from "path";
|
|
13
|
+
var flog = logger_default.child("file-sharing");
|
|
10
14
|
function validateFilePath(filePath) {
|
|
11
15
|
if (!filePath) return "File path is required";
|
|
12
16
|
const normalized = normalize(filePath);
|
|
@@ -65,7 +69,7 @@ function listPending(receiver) {
|
|
|
65
69
|
try {
|
|
66
70
|
result.push(JSON.parse(readFileSync(metaPath, "utf-8")));
|
|
67
71
|
} catch (err) {
|
|
68
|
-
|
|
72
|
+
flog.warn(`skipping malformed pending entry ${entry.name}`, logger_default.errorData(err));
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
75
|
return result.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
@@ -77,7 +81,7 @@ function getPending(receiver, id) {
|
|
|
77
81
|
try {
|
|
78
82
|
return JSON.parse(readFileSync(metaPath, "utf-8"));
|
|
79
83
|
} catch (err) {
|
|
80
|
-
|
|
84
|
+
flog.warn(`failed to read pending metadata for ${id}`, logger_default.errorData(err));
|
|
81
85
|
return null;
|
|
82
86
|
}
|
|
83
87
|
}
|
|
@@ -94,6 +94,8 @@ function eventLabel(type, meta) {
|
|
|
94
94
|
return s("reason") ? `Notice: ${s("reason")}` : "Notice";
|
|
95
95
|
case "delivery_failed":
|
|
96
96
|
return "Delivery failed";
|
|
97
|
+
case "context_lost":
|
|
98
|
+
return "Context lost";
|
|
97
99
|
case "join_blocked":
|
|
98
100
|
return "Variant join blocked";
|
|
99
101
|
default:
|
|
@@ -103,6 +105,16 @@ function eventLabel(type, meta) {
|
|
|
103
105
|
return type.charAt(0).toUpperCase() + type.slice(1);
|
|
104
106
|
}
|
|
105
107
|
}
|
|
108
|
+
var NOTICE_KINDS = [
|
|
109
|
+
"turn_error",
|
|
110
|
+
"crash",
|
|
111
|
+
"budget",
|
|
112
|
+
"startup",
|
|
113
|
+
"extension",
|
|
114
|
+
"delivery_failed",
|
|
115
|
+
"context_lost",
|
|
116
|
+
"join_blocked"
|
|
117
|
+
];
|
|
106
118
|
async function recordNotice(input) {
|
|
107
119
|
const type = input.kind === "budget" ? "budget" : "notice";
|
|
108
120
|
await deliverEvent(input.mind, {
|
|
@@ -111,6 +123,7 @@ async function recordNotice(input) {
|
|
|
111
123
|
thread: input.thread,
|
|
112
124
|
delivery: "next-turn",
|
|
113
125
|
meta: {
|
|
126
|
+
...input.meta ?? {},
|
|
114
127
|
subtype: input.kind,
|
|
115
128
|
reason: input.reason,
|
|
116
129
|
...input.raw ? { raw: input.raw } : {}
|
|
@@ -244,7 +257,7 @@ async function deliverEvent(mind, input) {
|
|
|
244
257
|
return { id: eventId, delivered: false };
|
|
245
258
|
}
|
|
246
259
|
const baseName = await getBaseName(mind);
|
|
247
|
-
const { getSleepManagerIfReady } = await import("./sleep-manager-
|
|
260
|
+
const { getSleepManagerIfReady } = await import("./sleep-manager-KHI65FEX.js");
|
|
248
261
|
const sleepManager = getSleepManagerIfReady();
|
|
249
262
|
const sleeping = !input.force && sleepManager?.isSleeping(baseName);
|
|
250
263
|
const behavior = input.whileSleeping ?? "queue";
|
|
@@ -552,6 +565,7 @@ export {
|
|
|
552
565
|
MIND_LEVEL_THREAD,
|
|
553
566
|
parseMeta,
|
|
554
567
|
eventLabel,
|
|
568
|
+
NOTICE_KINDS,
|
|
555
569
|
recordNotice,
|
|
556
570
|
eventChannel,
|
|
557
571
|
deliverEvent,
|
|
@@ -561,6 +575,7 @@ export {
|
|
|
561
575
|
pendingEventsLine,
|
|
562
576
|
drainEvents,
|
|
563
577
|
formatEvents,
|
|
578
|
+
localHM,
|
|
564
579
|
clearDeliveredEvents,
|
|
565
580
|
latestFailureEvent,
|
|
566
581
|
latestEvent,
|