volute 0.38.0 → 0.40.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/{activity-events-N6HCHU4P.js → activity-events-OJZ7G5CG.js} +3 -3
- package/dist/{ai-service-C2YNARGH.js → ai-service-JMV4KZN4.js} +8 -4
- package/dist/{archive-AWIJTVQV.js → archive-BC2MTNPV.js} +3 -3
- package/dist/{auth-2QOOPMBX.js → auth-2IMZ6N5G.js} +4 -4
- package/dist/{chat-XL7CVWVJ.js → chat-O5QCGCUG.js} +2 -2
- package/dist/{chunk-A6FLW5XD.js → chunk-2AQCEQYN.js} +1 -1
- package/dist/{chunk-3F7XK5Q7.js → chunk-3XSFMN3H.js} +1 -1
- package/dist/{chunk-NGXQ2ESO.js → chunk-43PVCF4V.js} +3 -3
- package/dist/{chunk-N42QMDID.js → chunk-5VBXKFPO.js} +2 -2
- package/dist/{chunk-BIEWHAAM.js → chunk-76Q6YLJL.js} +1 -1
- package/dist/{chunk-5DPRTREW.js → chunk-B7YJUWMM.js} +3 -3
- package/dist/{chunk-XLBQYIHH.js → chunk-DNQPHLGM.js} +1 -1
- package/dist/{chunk-SNW2NPP4.js → chunk-FBV22PFY.js} +1 -1
- package/dist/{chunk-WC635OPK.js → chunk-FRJ73IWR.js} +1 -1
- package/dist/{chunk-PMMHVSCR.js → chunk-HAJHDGBV.js} +1 -1
- package/dist/{chunk-SZJWC2GA.js → chunk-HEZM5GCV.js} +2 -2
- package/dist/{chunk-PLL2FM7A.js → chunk-JSITYTIL.js} +6 -6
- package/dist/{chunk-CJ26DXZL.js → chunk-MHFAWJCC.js} +16 -0
- package/dist/{chunk-7AZQFSOV.js → chunk-PC55DGNX.js} +1 -1
- package/dist/{chunk-2NHRJ3YO.js → chunk-PDSA3ILI.js} +3 -3
- package/dist/{chunk-ORNY3MZR.js → chunk-PGX52NFO.js} +15 -1
- package/dist/{chunk-UIM5NHPP.js → chunk-PHR4XQPL.js} +3 -3
- package/dist/chunk-PIRL2HAO.js +124 -0
- package/dist/{chunk-JOJT34M2.js → chunk-PZTVQL3J.js} +2 -2
- package/dist/{chunk-GVVVMZ4J.js → chunk-RMZSICLS.js} +1 -1
- package/dist/{chunk-LQ6Z4FXN.js → chunk-S4YO5OWV.js} +1 -1
- package/dist/{chunk-TNZ5XQA4.js → chunk-SGC6CDXB.js} +2 -2
- package/dist/{chunk-LN67VPZJ.js → chunk-SOPMVTTW.js} +2 -2
- package/dist/{chunk-VUM2K6EN.js → chunk-T26YLQPU.js} +5 -5
- package/dist/{chunk-2TR2OPVA.js → chunk-WGRMLXTH.js} +8 -8
- package/dist/{chunk-TEZRVSSB.js → chunk-XUJR6NZW.js} +513 -335
- package/dist/cli.js +15 -15
- package/dist/{cloud-sync-PEM3IVI4.js → cloud-sync-5JF2Z7VM.js} +16 -16
- package/dist/{conversations-G6YRSABR.js → conversations-LUVHGQSS.js} +4 -4
- package/dist/{create-PN73742N.js → create-TDQM3SHV.js} +1 -1
- package/dist/{daemon-restart-6QONRBTK.js → daemon-restart-XHDJDOPQ.js} +8 -8
- package/dist/daemon.js +221 -118
- package/dist/{db-CBOCDYVA.js → db-2GIS7HSG.js} +2 -2
- package/dist/delivery-manager-L5WFP2ND.js +30 -0
- package/dist/{delivery-router-QTFEZ26O.js → delivery-router-IU4OMVKZ.js} +3 -3
- package/dist/down-KIJVZ3OC.js +17 -0
- package/dist/echo-text-TJWCUBPB.js +31 -0
- package/dist/{exec-ONYZEA5B.js → exec-BGMU7VXR.js} +4 -4
- package/dist/{export-JPDBQESV.js → export-RKUWSQSG.js} +3 -3
- package/dist/{extensions-P477XR46.js → extensions-VN5SEVRP.js} +16 -16
- package/dist/{files-LAQ3NXQK.js → files-J2CKZ6PK.js} +3 -3
- package/dist/{import-EROF27RH.js → import-KVY6BYXG.js} +6 -6
- package/dist/{isolation-G5J3MTKU.js → isolation-MM7YHK6J.js} +3 -3
- package/dist/{login-F6YMAVLE.js → login-OHM32QVD.js} +2 -2
- package/dist/{logout-HHPH52KZ.js → logout-74WBDMOE.js} +2 -2
- package/dist/{message-delivery-54IXVE5H.js → message-delivery-VBBAJX3J.js} +16 -16
- package/dist/{mind-G5HDKBKL.js → mind-PUPXDIYQ.js} +5 -5
- package/dist/{mind-activity-tracker-42ENM32S.js → mind-activity-tracker-7GE24YZE.js} +4 -4
- package/dist/mind-manager-4Q6KGZHL.js +30 -0
- package/dist/mind-service-7OD4PRO5.js +36 -0
- package/dist/{package-LYQHSDPG.js → package-6YPVWGD3.js} +1 -1
- package/dist/{registry-KMELPC3X.js → registry-L272BZJR.js} +2 -2
- package/dist/{sandbox-PQYEICEF.js → sandbox-BQAFYHLE.js} +6 -6
- package/dist/scheduler-7E22Q7IC.js +30 -0
- package/dist/{schema-K575EBPE.js → schema-HHYJDG7B.js} +3 -1
- package/dist/{seed-3KH4ZRJL.js → seed-4V2O7FQE.js} +1 -1
- package/dist/{seed-cmd-6A76SSAA.js → seed-cmd-JKDEW4MP.js} +2 -2
- package/dist/{seed-create-XXRRGZCO.js → seed-create-EPAO3H5F.js} +3 -3
- package/dist/{seed-sprout-HLMUH2AI.js → seed-sprout-EONCL4DU.js} +8 -8
- package/dist/{send-7CIP5GLS.js → send-232RAHPX.js} +3 -3
- package/dist/{service-RH6Q2XWR.js → service-AG5BKRUV.js} +5 -5
- package/dist/{service-install-AIQBLE6P.js → service-install-HVAEUBAH.js} +6 -6
- package/dist/{setup-PF7JSFMO.js → setup-IL7QJZN4.js} +3 -3
- package/dist/{setup-NPAZXBIJ.js → setup-PSA7LJ5U.js} +8 -8
- package/dist/{skills-NVOWS5NY.js → skills-SLEY5X6W.js} +6 -6
- package/dist/sleep-manager-27S7MKJO.js +34 -0
- package/dist/{spirit-ZFYG4JOH.js → spirit-7BUHSEO2.js} +8 -8
- package/dist/{sprout-FLBCETYG.js → sprout-JWQ57KF3.js} +1 -1
- package/dist/{status-TGOKAFW3.js → status-6GSOSYOD.js} +6 -6
- package/dist/system-chat-EIINIHFB.js +34 -0
- package/dist/{tailscale-LTYNKIPZ.js → tailscale-6MHNLBAX.js} +2 -2
- package/dist/up-4XS3RCPP.js +19 -0
- package/dist/{update-ZCTQ6UGY.js → update-BT2PY73H.js} +6 -6
- package/dist/{update-check-IKS7SGK5.js → update-check-Y3HBEMF2.js} +3 -3
- package/dist/{version-notify-764EXVQQ.js → version-notify-NFQMI5IY.js} +17 -17
- package/dist/web-assets/assets/index-DqHSW9Fr.css +1 -0
- package/dist/web-assets/assets/index-Jluza4c-.js +73 -0
- package/dist/web-assets/index.html +2 -2
- package/drizzle/0009_mind_notices.sql +14 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +1 -1
- package/templates/_base/.init/.local/hooks/pre-prompt/notices.ts +46 -0
- package/templates/_base/src/lib/context-breakdown.ts +281 -126
- package/templates/_base/src/lib/daemon-client.ts +5 -2
- package/templates/_base/src/lib/transparency.ts +5 -3
- package/templates/_base/src/lib/volute-server.ts +23 -0
- package/templates/claude/src/agent.ts +54 -16
- package/templates/claude/src/server.ts +1 -0
- package/templates/codex/src/agent.ts +51 -12
- package/templates/codex/src/server.ts +1 -0
- package/templates/pi/src/agent.ts +72 -13
- package/templates/pi/src/server.ts +1 -0
- package/dist/chunk-KXXJYY62.js +0 -112
- package/dist/delivery-manager-IMCRV6A3.js +0 -30
- package/dist/down-5XZWH4ZP.js +0 -17
- package/dist/echo-text-ADKLNTIA.js +0 -31
- package/dist/mind-manager-5G6P2EAT.js +0 -30
- package/dist/mind-service-FDATHL6X.js +0 -36
- package/dist/scheduler-ZRUZNQI5.js +0 -30
- package/dist/sleep-manager-VPPQXBPH.js +0 -34
- package/dist/system-chat-YUIT7RA6.js +0 -34
- package/dist/up-YRZAEZ3Z.js +0 -19
- package/dist/web-assets/assets/index-BI7hUTBr.js +0 -73
- package/dist/web-assets/assets/index-BJifO9h_.css +0 -1
|
@@ -120,12 +120,17 @@ export type ContextInfo = {
|
|
|
120
120
|
systemPrompt: number;
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
+
export type { ContextBlock, ContextMessage, ContextMessages } from "./context-breakdown.js";
|
|
124
|
+
|
|
125
|
+
import type { ContextMessages } from "./context-breakdown.js";
|
|
126
|
+
|
|
123
127
|
export function createVoluteServer(options: {
|
|
124
128
|
router: Router;
|
|
125
129
|
port: number;
|
|
126
130
|
name: string;
|
|
127
131
|
version: string;
|
|
128
132
|
getContextInfo?: () => ContextInfo | Promise<ContextInfo>;
|
|
133
|
+
getContextMessages?: () => ContextMessages | Promise<ContextMessages>;
|
|
129
134
|
}): Server {
|
|
130
135
|
const { router, port, name, version } = options;
|
|
131
136
|
|
|
@@ -162,6 +167,24 @@ export function createVoluteServer(options: {
|
|
|
162
167
|
return;
|
|
163
168
|
}
|
|
164
169
|
|
|
170
|
+
if (req.method === "GET" && url.pathname === "/context/messages") {
|
|
171
|
+
if (!options.getContextMessages) {
|
|
172
|
+
res.writeHead(404);
|
|
173
|
+
res.end("Not Found");
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
const messages = await options.getContextMessages();
|
|
178
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
179
|
+
res.end(JSON.stringify(messages));
|
|
180
|
+
} catch (err) {
|
|
181
|
+
log("server", "error in /context/messages:", err);
|
|
182
|
+
res.writeHead(500);
|
|
183
|
+
res.end("Internal Server Error");
|
|
184
|
+
}
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
165
188
|
if (req.method === "POST" && url.pathname === "/message") {
|
|
166
189
|
try {
|
|
167
190
|
const body = JSON.parse(await readBody(req)) as VoluteRequest;
|
|
@@ -8,7 +8,9 @@ import {
|
|
|
8
8
|
countSkillDescriptionTokens,
|
|
9
9
|
countSystemPromptTokens,
|
|
10
10
|
findClaudeSessionFile,
|
|
11
|
-
|
|
11
|
+
processClaudeSession,
|
|
12
|
+
readSdkInstructions,
|
|
13
|
+
readSkillDescriptions,
|
|
12
14
|
} from "./lib/context-breakdown.js";
|
|
13
15
|
import { daemonEmit } from "./lib/daemon-client.js";
|
|
14
16
|
import { runHooks } from "./lib/hook-loader.js";
|
|
@@ -30,7 +32,7 @@ import type {
|
|
|
30
32
|
VoluteContentPart,
|
|
31
33
|
VoluteEvent,
|
|
32
34
|
} from "./lib/types.js";
|
|
33
|
-
import type { ContextInfo } from "./lib/volute-server.js";
|
|
35
|
+
import type { ContextInfo, ContextMessages } from "./lib/volute-server.js";
|
|
34
36
|
|
|
35
37
|
type Session = {
|
|
36
38
|
name: string;
|
|
@@ -60,6 +62,7 @@ export function createMind(options: {
|
|
|
60
62
|
resolve: HandlerResolver;
|
|
61
63
|
waitForCommits: () => Promise<void>;
|
|
62
64
|
getContextInfo: () => ContextInfo;
|
|
65
|
+
getContextMessages: () => ContextMessages;
|
|
63
66
|
} {
|
|
64
67
|
const autoCommit = createAutoCommitHook(options.cwd);
|
|
65
68
|
const identityReload = createIdentityReloadHook(options.cwd);
|
|
@@ -369,6 +372,17 @@ export function createMind(options: {
|
|
|
369
372
|
});
|
|
370
373
|
}
|
|
371
374
|
|
|
375
|
+
/**
|
|
376
|
+
* Tell the daemon this turn failed so it can record a notice for the mind's next
|
|
377
|
+
* successful turn. Awaited before emitDone so the daemon flags the session errored
|
|
378
|
+
* (and thus won't mark notices delivered) before the done arrives.
|
|
379
|
+
*/
|
|
380
|
+
async function emitError(err: unknown) {
|
|
381
|
+
await daemonEmit({ type: "error", session: session.name, content: String(err) }).catch(
|
|
382
|
+
(e) => log("mind", `session "${session.name}": failed to emit error to daemon:`, e),
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
|
|
372
386
|
async function runStream(resume?: string) {
|
|
373
387
|
const q = createStream(session, streamAbort, preCompact.hook, resume);
|
|
374
388
|
session.currentQuery = q;
|
|
@@ -428,11 +442,13 @@ export function createMind(options: {
|
|
|
428
442
|
await runStream();
|
|
429
443
|
} catch (retryErr) {
|
|
430
444
|
log("mind", `session "${session.name}": stream consumer error:`, retryErr);
|
|
445
|
+
await emitError(retryErr);
|
|
431
446
|
emitDone();
|
|
432
447
|
sessions.delete(session.name);
|
|
433
448
|
}
|
|
434
449
|
} else {
|
|
435
450
|
log("mind", `session "${session.name}": stream consumer error:`, err);
|
|
451
|
+
await emitError(err);
|
|
436
452
|
emitDone();
|
|
437
453
|
sessions.delete(session.name);
|
|
438
454
|
}
|
|
@@ -543,26 +559,24 @@ export function createMind(options: {
|
|
|
543
559
|
const claudeMdTokens = countSdkInstructionTokens(options.cwd);
|
|
544
560
|
const skillDescTokens = countSkillDescriptionTokens([resolvePath(options.cwd, ".claude/skills")]);
|
|
545
561
|
|
|
562
|
+
function processSession(sessionName: string) {
|
|
563
|
+
const sessionId = sessionStore.load(sessionName);
|
|
564
|
+
const jsonlPath = sessionId ? findClaudeSessionFile(options.cwd, sessionId) : null;
|
|
565
|
+
return jsonlPath
|
|
566
|
+
? processClaudeSession(jsonlPath, systemPromptTokens, claudeMdTokens, skillDescTokens)
|
|
567
|
+
: null;
|
|
568
|
+
}
|
|
569
|
+
|
|
546
570
|
function getContextInfo(): ContextInfo {
|
|
547
571
|
return {
|
|
548
572
|
sessions: Array.from(sessions.values()).map((s) => {
|
|
549
573
|
try {
|
|
550
|
-
const
|
|
551
|
-
const jsonlPath = sessionId ? findClaudeSessionFile(options.cwd, sessionId) : null;
|
|
552
|
-
const parsed = jsonlPath
|
|
553
|
-
? parseClaudeSessionJSONL(
|
|
554
|
-
jsonlPath,
|
|
555
|
-
systemPromptTokens,
|
|
556
|
-
claudeMdTokens,
|
|
557
|
-
skillDescTokens,
|
|
558
|
-
)
|
|
559
|
-
: null;
|
|
560
|
-
|
|
574
|
+
const result = processSession(s.name);
|
|
561
575
|
return {
|
|
562
576
|
name: s.name,
|
|
563
|
-
contextTokens: parsed?.contextTokens ?? s.contextTokens,
|
|
577
|
+
contextTokens: result?.parsed?.contextTokens ?? s.contextTokens,
|
|
564
578
|
contextWindow: maxContextTokens,
|
|
565
|
-
breakdown: parsed?.breakdown,
|
|
579
|
+
breakdown: result?.parsed?.breakdown,
|
|
566
580
|
};
|
|
567
581
|
} catch (err) {
|
|
568
582
|
log("mind", `failed to get context breakdown for session "${s.name}":`, err);
|
|
@@ -573,5 +587,29 @@ export function createMind(options: {
|
|
|
573
587
|
};
|
|
574
588
|
}
|
|
575
589
|
|
|
576
|
-
|
|
590
|
+
function getContextMessages(): ContextMessages {
|
|
591
|
+
const skillsDir = resolvePath(options.cwd, ".claude/skills");
|
|
592
|
+
return {
|
|
593
|
+
preamble: {
|
|
594
|
+
systemPrompt: options.systemPrompt,
|
|
595
|
+
sdkInstructions: readSdkInstructions(options.cwd),
|
|
596
|
+
skillDescriptions: readSkillDescriptions([skillsDir]),
|
|
597
|
+
},
|
|
598
|
+
sessions: Array.from(sessions.values()).map((s) => {
|
|
599
|
+
try {
|
|
600
|
+
const result = processSession(s.name);
|
|
601
|
+
return { name: s.name, messages: result?.messages ?? [] };
|
|
602
|
+
} catch (err) {
|
|
603
|
+
log("mind", `failed to extract messages for session "${s.name}":`, err);
|
|
604
|
+
return { name: s.name, messages: [] };
|
|
605
|
+
}
|
|
606
|
+
}),
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// Pre-warm the main session so the SDK subprocess starts immediately
|
|
611
|
+
// instead of waiting for the first message (which adds minutes of latency).
|
|
612
|
+
getOrCreateSession("main");
|
|
613
|
+
|
|
614
|
+
return { resolve, waitForCommits: autoCommit.waitForCommits, getContextInfo, getContextMessages };
|
|
577
615
|
}
|
|
@@ -8,7 +8,9 @@ import {
|
|
|
8
8
|
countSkillDescriptionTokens,
|
|
9
9
|
countSystemPromptTokens,
|
|
10
10
|
findCodexSessionFile,
|
|
11
|
-
|
|
11
|
+
processCodexSession,
|
|
12
|
+
readSdkInstructions,
|
|
13
|
+
readSkillDescriptions,
|
|
12
14
|
} from "./lib/context-breakdown.js";
|
|
13
15
|
import { daemonEmit, daemonRestart, type EventType } from "./lib/daemon-client.js";
|
|
14
16
|
import { runHooks } from "./lib/hook-loader.js";
|
|
@@ -24,7 +26,7 @@ import type {
|
|
|
24
26
|
VoluteContentPart,
|
|
25
27
|
VoluteEvent,
|
|
26
28
|
} from "./lib/types.js";
|
|
27
|
-
import type { ContextInfo } from "./lib/volute-server.js";
|
|
29
|
+
import type { ContextInfo, ContextMessages } from "./lib/volute-server.js";
|
|
28
30
|
|
|
29
31
|
/** Minimal interface for a Codex SDK thread — typed to the methods we actually use */
|
|
30
32
|
type CodexThread = {
|
|
@@ -73,7 +75,11 @@ export function createMind(options: {
|
|
|
73
75
|
model?: string;
|
|
74
76
|
reasoningEffort?: "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
75
77
|
maxContextTokens?: number;
|
|
76
|
-
}): {
|
|
78
|
+
}): {
|
|
79
|
+
resolve: HandlerResolver;
|
|
80
|
+
getContextInfo: () => ContextInfo;
|
|
81
|
+
getContextMessages: () => ContextMessages;
|
|
82
|
+
} {
|
|
77
83
|
const sessions = new Map<string, CodexSession>();
|
|
78
84
|
const prompts = loadPrompts();
|
|
79
85
|
const maxContextTokens = options.maxContextTokens;
|
|
@@ -161,7 +167,11 @@ export function createMind(options: {
|
|
|
161
167
|
model: options.model,
|
|
162
168
|
modelReasoningEffort: options.reasoningEffort,
|
|
163
169
|
skipGitRepoCheck: true,
|
|
170
|
+
// Codex's native seatbelt sandbox panics on macOS due to a bug in the
|
|
171
|
+
// system-configuration Rust crate (SCDynamicStore NULL object). Use full
|
|
172
|
+
// access until upstream ships a fix (mullvad/system-configuration-rs#59).
|
|
164
173
|
sandboxMode: "danger-full-access",
|
|
174
|
+
networkAccessEnabled: true,
|
|
165
175
|
});
|
|
166
176
|
return;
|
|
167
177
|
} catch (err) {
|
|
@@ -176,7 +186,9 @@ export function createMind(options: {
|
|
|
176
186
|
model: options.model,
|
|
177
187
|
modelReasoningEffort: options.reasoningEffort,
|
|
178
188
|
skipGitRepoCheck: true,
|
|
189
|
+
// See comment in resumeThread above
|
|
179
190
|
sandboxMode: "danger-full-access",
|
|
191
|
+
networkAccessEnabled: true,
|
|
180
192
|
});
|
|
181
193
|
log("mind", `session "${session.name}": new thread started`);
|
|
182
194
|
} catch (err) {
|
|
@@ -593,21 +605,24 @@ export function createMind(options: {
|
|
|
593
605
|
const claudeMdTokens = countSdkInstructionTokens(options.cwd);
|
|
594
606
|
const skillDescTokens = countSkillDescriptionTokens([resolvePath(options.cwd, ".agents/skills")]);
|
|
595
607
|
|
|
608
|
+
function processSession(sessionName: string) {
|
|
609
|
+
const threadId = sessionStore.load(sessionName);
|
|
610
|
+
const jsonlPath = threadId ? findCodexSessionFile(threadId, options.mindDir) : null;
|
|
611
|
+
return jsonlPath
|
|
612
|
+
? processCodexSession(jsonlPath, systemPromptTokens, claudeMdTokens, skillDescTokens)
|
|
613
|
+
: null;
|
|
614
|
+
}
|
|
615
|
+
|
|
596
616
|
function getContextInfo(): ContextInfo {
|
|
597
617
|
return {
|
|
598
618
|
sessions: Array.from(sessions.values()).map((s) => {
|
|
599
619
|
try {
|
|
600
|
-
const
|
|
601
|
-
const jsonlPath = threadId ? findCodexSessionFile(threadId) : null;
|
|
602
|
-
const parsed = jsonlPath
|
|
603
|
-
? parseCodexSessionJSONL(jsonlPath, systemPromptTokens, claudeMdTokens, skillDescTokens)
|
|
604
|
-
: null;
|
|
605
|
-
|
|
620
|
+
const result = processSession(s.name);
|
|
606
621
|
return {
|
|
607
622
|
name: s.name,
|
|
608
|
-
contextTokens: parsed?.contextTokens ?? s.cumulativeInputTokens,
|
|
623
|
+
contextTokens: result?.parsed?.contextTokens ?? s.cumulativeInputTokens,
|
|
609
624
|
contextWindow: maxContextTokens,
|
|
610
|
-
breakdown: parsed?.breakdown,
|
|
625
|
+
breakdown: result?.parsed?.breakdown,
|
|
611
626
|
};
|
|
612
627
|
} catch (err) {
|
|
613
628
|
log("mind", `failed to get context breakdown for session "${s.name}":`, err);
|
|
@@ -622,5 +637,29 @@ export function createMind(options: {
|
|
|
622
637
|
};
|
|
623
638
|
}
|
|
624
639
|
|
|
625
|
-
|
|
640
|
+
function getContextMessages(): ContextMessages {
|
|
641
|
+
const skillsDir = resolvePath(options.cwd, ".agents/skills");
|
|
642
|
+
return {
|
|
643
|
+
preamble: {
|
|
644
|
+
systemPrompt: options.systemPrompt,
|
|
645
|
+
sdkInstructions: readSdkInstructions(options.cwd),
|
|
646
|
+
skillDescriptions: readSkillDescriptions([skillsDir]),
|
|
647
|
+
},
|
|
648
|
+
sessions: Array.from(sessions.values()).map((s) => {
|
|
649
|
+
try {
|
|
650
|
+
const result = processSession(s.name);
|
|
651
|
+
return { name: s.name, messages: result?.messages ?? [] };
|
|
652
|
+
} catch (err) {
|
|
653
|
+
log("mind", `failed to extract messages for session "${s.name}":`, err);
|
|
654
|
+
return { name: s.name, messages: [] };
|
|
655
|
+
}
|
|
656
|
+
}),
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// Pre-warm the main session so the thread is created immediately
|
|
661
|
+
// instead of waiting for the first message.
|
|
662
|
+
getOrCreateSession("main");
|
|
663
|
+
|
|
664
|
+
return { resolve, getContextInfo, getContextMessages };
|
|
626
665
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
1
|
+
import { readFileSync, watchFile } from "node:fs";
|
|
2
2
|
import { resolve as resolvePath } from "node:path";
|
|
3
3
|
import {
|
|
4
4
|
AuthStorage,
|
|
@@ -15,8 +15,11 @@ import {
|
|
|
15
15
|
countSkillDescriptionTokens,
|
|
16
16
|
countSystemPromptTokens,
|
|
17
17
|
findPiSessionFile,
|
|
18
|
-
|
|
18
|
+
processPiSession,
|
|
19
|
+
readSdkInstructions,
|
|
20
|
+
readSkillDescriptions,
|
|
19
21
|
} from "./lib/context-breakdown.js";
|
|
22
|
+
import { daemonEmit } from "./lib/daemon-client.js";
|
|
20
23
|
import { createEventHandler, emit } from "./lib/event-handler.js";
|
|
21
24
|
import { runHooks } from "./lib/hook-loader.js";
|
|
22
25
|
import { log } from "./lib/logger.js";
|
|
@@ -32,7 +35,7 @@ import type {
|
|
|
32
35
|
VoluteContentPart,
|
|
33
36
|
VoluteEvent,
|
|
34
37
|
} from "./lib/types.js";
|
|
35
|
-
import type { ContextInfo } from "./lib/volute-server.js";
|
|
38
|
+
import type { ContextInfo, ContextMessages } from "./lib/volute-server.js";
|
|
36
39
|
|
|
37
40
|
type PiAgentSession = Awaited<ReturnType<typeof createAgentSession>>["session"];
|
|
38
41
|
|
|
@@ -57,7 +60,11 @@ export function createMind(options: {
|
|
|
57
60
|
compactionMessage?: string;
|
|
58
61
|
maxContextTokens?: number;
|
|
59
62
|
subagents?: Record<string, SubagentConfig>;
|
|
60
|
-
}): {
|
|
63
|
+
}): {
|
|
64
|
+
resolve: HandlerResolver;
|
|
65
|
+
getContextInfo: () => ContextInfo;
|
|
66
|
+
getContextMessages: () => ContextMessages;
|
|
67
|
+
} {
|
|
61
68
|
const sessions = new Map<string, PiSession>();
|
|
62
69
|
const prompts = loadPrompts();
|
|
63
70
|
const today = new Date().toLocaleDateString("en-CA");
|
|
@@ -77,6 +84,29 @@ export function createMind(options: {
|
|
|
77
84
|
const authStorage = AuthStorage.create();
|
|
78
85
|
const modelRegistry = ModelRegistry.create(authStorage);
|
|
79
86
|
|
|
87
|
+
// The daemon centrally refreshes the system OAuth token and rewrites auth.json
|
|
88
|
+
// with the fresh token. Watch the file and reload so a running mind adopts the
|
|
89
|
+
// new token without a restart (mirrors the Claude Agent SDK credential reload).
|
|
90
|
+
// This is why the mind itself does not refresh the rotating grant.
|
|
91
|
+
const piAuthPath = process.env.PI_CODING_AGENT_DIR
|
|
92
|
+
? resolvePath(process.env.PI_CODING_AGENT_DIR, "auth.json")
|
|
93
|
+
: null;
|
|
94
|
+
if (piAuthPath) {
|
|
95
|
+
try {
|
|
96
|
+
watchFile(piAuthPath, { interval: 2000 }, (curr, prev) => {
|
|
97
|
+
if (curr.mtimeMs === prev.mtimeMs) return;
|
|
98
|
+
try {
|
|
99
|
+
authStorage.reload();
|
|
100
|
+
log("mind", "reloaded auth.json after credential refresh");
|
|
101
|
+
} catch (err) {
|
|
102
|
+
log("mind", "failed to reload auth.json:", err);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
} catch (err) {
|
|
106
|
+
log("mind", "failed to watch auth.json for credential refresh:", err);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
80
110
|
// --- Subagents (config-driven) ---
|
|
81
111
|
|
|
82
112
|
function loadSubagents(
|
|
@@ -457,8 +487,14 @@ export function createMind(options: {
|
|
|
457
487
|
} else {
|
|
458
488
|
session.agentSession.prompt(text, opts);
|
|
459
489
|
}
|
|
460
|
-
})().catch((err) => {
|
|
490
|
+
})().catch(async (err) => {
|
|
461
491
|
log("mind", `session "${sessionName}": prompt failed:`, err);
|
|
492
|
+
// Tell the daemon the turn failed (so it records a notice for the mind's next
|
|
493
|
+
// successful turn) before done, then complete the turn locally and on the daemon.
|
|
494
|
+
await daemonEmit({ type: "error", session: sessionName, content: String(err) }).catch(
|
|
495
|
+
() => {},
|
|
496
|
+
);
|
|
497
|
+
await daemonEmit({ type: "done", session: sessionName }).catch(() => {});
|
|
462
498
|
broadcast(session, { type: "done" });
|
|
463
499
|
});
|
|
464
500
|
|
|
@@ -489,20 +525,23 @@ export function createMind(options: {
|
|
|
489
525
|
const claudeMdTokens = countSdkInstructionTokens(options.cwd);
|
|
490
526
|
const skillDescTokens = countSkillDescriptionTokens([resolvePath(options.cwd, ".pi/skills")]);
|
|
491
527
|
|
|
528
|
+
function processSession(sessionName: string) {
|
|
529
|
+
const jsonlPath = findPiSessionFile(piSessionsDir, sessionName);
|
|
530
|
+
return jsonlPath
|
|
531
|
+
? processPiSession(jsonlPath, systemPromptTokens, claudeMdTokens, skillDescTokens)
|
|
532
|
+
: null;
|
|
533
|
+
}
|
|
534
|
+
|
|
492
535
|
function getContextInfo(): ContextInfo {
|
|
493
536
|
return {
|
|
494
537
|
sessions: Array.from(sessions.values()).map((s) => {
|
|
495
538
|
try {
|
|
496
|
-
const
|
|
497
|
-
const parsed = jsonlPath
|
|
498
|
-
? parsePiSessionJSONL(jsonlPath, systemPromptTokens, claudeMdTokens, skillDescTokens)
|
|
499
|
-
: null;
|
|
500
|
-
|
|
539
|
+
const result = processSession(s.name);
|
|
501
540
|
return {
|
|
502
541
|
name: s.name,
|
|
503
|
-
contextTokens: parsed?.contextTokens ?? s.contextTokens,
|
|
542
|
+
contextTokens: result?.parsed?.contextTokens ?? s.contextTokens,
|
|
504
543
|
contextWindow: maxContextTokens,
|
|
505
|
-
breakdown: parsed?.breakdown,
|
|
544
|
+
breakdown: result?.parsed?.breakdown,
|
|
506
545
|
};
|
|
507
546
|
} catch (err) {
|
|
508
547
|
log("mind", `failed to get context breakdown for session "${s.name}":`, err);
|
|
@@ -513,5 +552,25 @@ export function createMind(options: {
|
|
|
513
552
|
};
|
|
514
553
|
}
|
|
515
554
|
|
|
516
|
-
|
|
555
|
+
function getContextMessages(): ContextMessages {
|
|
556
|
+
const skillsDir = resolvePath(options.cwd, ".pi/skills");
|
|
557
|
+
return {
|
|
558
|
+
preamble: {
|
|
559
|
+
systemPrompt: options.systemPrompt,
|
|
560
|
+
sdkInstructions: readSdkInstructions(options.cwd),
|
|
561
|
+
skillDescriptions: readSkillDescriptions([skillsDir]),
|
|
562
|
+
},
|
|
563
|
+
sessions: Array.from(sessions.values()).map((s) => {
|
|
564
|
+
try {
|
|
565
|
+
const result = processSession(s.name);
|
|
566
|
+
return { name: s.name, messages: result?.messages ?? [] };
|
|
567
|
+
} catch (err) {
|
|
568
|
+
log("mind", `failed to extract messages for session "${s.name}":`, err);
|
|
569
|
+
return { name: s.name, messages: [] };
|
|
570
|
+
}
|
|
571
|
+
}),
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
return { resolve, getContextInfo, getContextMessages };
|
|
517
576
|
}
|
package/dist/chunk-KXXJYY62.js
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
readGlobalConfig
|
|
4
|
-
} from "./chunk-A6FLW5XD.js";
|
|
5
|
-
import {
|
|
6
|
-
logger_default
|
|
7
|
-
} from "./chunk-T2TP6ZC6.js";
|
|
8
|
-
import {
|
|
9
|
-
getBaseName,
|
|
10
|
-
readRegistry,
|
|
11
|
-
voluteHome,
|
|
12
|
-
voluteSystemDir,
|
|
13
|
-
voluteUserHome
|
|
14
|
-
} from "./chunk-2NHRJ3YO.js";
|
|
15
|
-
|
|
16
|
-
// packages/daemon/src/lib/mind/sandbox.ts
|
|
17
|
-
import { resolve } from "path";
|
|
18
|
-
var slog = logger_default.child("sandbox");
|
|
19
|
-
var sandboxManager = null;
|
|
20
|
-
function isSandboxEnabled() {
|
|
21
|
-
if (process.env.VOLUTE_SANDBOX === "0") return false;
|
|
22
|
-
return readGlobalConfig().setup?.isolation === "sandbox";
|
|
23
|
-
}
|
|
24
|
-
async function initSandbox() {
|
|
25
|
-
if (!isSandboxEnabled()) return;
|
|
26
|
-
try {
|
|
27
|
-
const { SandboxManager } = await import("@anthropic-ai/sandbox-runtime");
|
|
28
|
-
const config = {
|
|
29
|
-
network: {
|
|
30
|
-
allowedDomains: ["*"],
|
|
31
|
-
deniedDomains: [],
|
|
32
|
-
allowLocalBinding: true,
|
|
33
|
-
allowAllUnixSockets: true
|
|
34
|
-
},
|
|
35
|
-
filesystem: {
|
|
36
|
-
denyRead: [],
|
|
37
|
-
allowWrite: [],
|
|
38
|
-
denyWrite: []
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
await SandboxManager.initialize(config);
|
|
42
|
-
sandboxManager = SandboxManager;
|
|
43
|
-
} catch (err) {
|
|
44
|
-
slog.error(
|
|
45
|
-
"sandbox runtime not available \u2014 minds will run without sandbox isolation",
|
|
46
|
-
logger_default.errorData(err)
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
async function buildDenyRead(mindName, mindDir) {
|
|
51
|
-
const home = voluteHome();
|
|
52
|
-
const userHome = process.env.HOME || "";
|
|
53
|
-
const mindsDir = process.env.VOLUTE_MINDS_DIR || resolve(home, "minds");
|
|
54
|
-
const deny = [];
|
|
55
|
-
deny.push(voluteSystemDir());
|
|
56
|
-
const userVoluteHome = voluteUserHome();
|
|
57
|
-
if (userVoluteHome !== home) {
|
|
58
|
-
deny.push(userVoluteHome);
|
|
59
|
-
}
|
|
60
|
-
try {
|
|
61
|
-
const entries = await readRegistry();
|
|
62
|
-
for (const entry of entries) {
|
|
63
|
-
if (entry.name === await getBaseName(mindName)) continue;
|
|
64
|
-
const otherDir = resolve(mindsDir, entry.name);
|
|
65
|
-
if (otherDir !== mindDir) {
|
|
66
|
-
deny.push(otherDir);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
} catch (err) {
|
|
70
|
-
slog.warn("failed to read minds registry for deny-read list", logger_default.errorData(err));
|
|
71
|
-
}
|
|
72
|
-
if (userHome) {
|
|
73
|
-
deny.push(resolve(userHome, ".ssh"));
|
|
74
|
-
deny.push(resolve(userHome, ".aws"));
|
|
75
|
-
deny.push(resolve(userHome, ".gnupg"));
|
|
76
|
-
deny.push(resolve(userHome, ".config"));
|
|
77
|
-
}
|
|
78
|
-
return deny;
|
|
79
|
-
}
|
|
80
|
-
function shellEscape(s) {
|
|
81
|
-
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
82
|
-
}
|
|
83
|
-
async function wrapForSandbox(cmd, args, mindDir, mindName, allowWrite) {
|
|
84
|
-
if (!sandboxManager) return [cmd, args];
|
|
85
|
-
const denyRead = await buildDenyRead(mindName, mindDir);
|
|
86
|
-
const customConfig = {
|
|
87
|
-
filesystem: {
|
|
88
|
-
denyRead,
|
|
89
|
-
allowWrite: allowWrite ?? [mindDir],
|
|
90
|
-
denyWrite: []
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
try {
|
|
94
|
-
const shellCmd = [cmd, ...args].map(shellEscape).join(" ");
|
|
95
|
-
const wrapped = await sandboxManager.wrapWithSandbox(shellCmd, void 0, customConfig);
|
|
96
|
-
return ["bash", ["-c", wrapped]];
|
|
97
|
-
} catch (err) {
|
|
98
|
-
slog.error(
|
|
99
|
-
`failed to sandbox mind ${mindName} \u2014 running without isolation`,
|
|
100
|
-
logger_default.errorData(err)
|
|
101
|
-
);
|
|
102
|
-
return [cmd, args];
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export {
|
|
107
|
-
isSandboxEnabled,
|
|
108
|
-
initSandbox,
|
|
109
|
-
buildDenyRead,
|
|
110
|
-
shellEscape,
|
|
111
|
-
wrapForSandbox
|
|
112
|
-
};
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
DeliveryManager,
|
|
4
|
-
getDeliveryManager,
|
|
5
|
-
initDeliveryManager
|
|
6
|
-
} from "./chunk-TEZRVSSB.js";
|
|
7
|
-
import "./chunk-PMMHVSCR.js";
|
|
8
|
-
import "./chunk-2TR2OPVA.js";
|
|
9
|
-
import "./chunk-46DYYHN6.js";
|
|
10
|
-
import "./chunk-VUM2K6EN.js";
|
|
11
|
-
import "./chunk-5DPRTREW.js";
|
|
12
|
-
import "./chunk-CU6OFXMM.js";
|
|
13
|
-
import "./chunk-KXXJYY62.js";
|
|
14
|
-
import "./chunk-7AZQFSOV.js";
|
|
15
|
-
import "./chunk-GVVVMZ4J.js";
|
|
16
|
-
import "./chunk-3F7XK5Q7.js";
|
|
17
|
-
import "./chunk-SNW2NPP4.js";
|
|
18
|
-
import "./chunk-UIM5NHPP.js";
|
|
19
|
-
import "./chunk-N42QMDID.js";
|
|
20
|
-
import "./chunk-ORNY3MZR.js";
|
|
21
|
-
import "./chunk-A6FLW5XD.js";
|
|
22
|
-
import "./chunk-T2TP6ZC6.js";
|
|
23
|
-
import "./chunk-2NHRJ3YO.js";
|
|
24
|
-
import "./chunk-CJ26DXZL.js";
|
|
25
|
-
import "./chunk-K3NQKI34.js";
|
|
26
|
-
export {
|
|
27
|
-
DeliveryManager,
|
|
28
|
-
getDeliveryManager,
|
|
29
|
-
initDeliveryManager
|
|
30
|
-
};
|
package/dist/down-5XZWH4ZP.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
run,
|
|
4
|
-
stopDaemon
|
|
5
|
-
} from "./chunk-LN67VPZJ.js";
|
|
6
|
-
import "./chunk-TXSA4Q3V.js";
|
|
7
|
-
import "./chunk-O7IGP7ZW.js";
|
|
8
|
-
import "./chunk-TNZ5XQA4.js";
|
|
9
|
-
import "./chunk-3F7XK5Q7.js";
|
|
10
|
-
import "./chunk-SNW2NPP4.js";
|
|
11
|
-
import "./chunk-2NHRJ3YO.js";
|
|
12
|
-
import "./chunk-CJ26DXZL.js";
|
|
13
|
-
import "./chunk-K3NQKI34.js";
|
|
14
|
-
export {
|
|
15
|
-
run,
|
|
16
|
-
stopDaemon
|
|
17
|
-
};
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
clearEchoTextCache,
|
|
4
|
-
echoTextToChannel
|
|
5
|
-
} from "./chunk-PLL2FM7A.js";
|
|
6
|
-
import "./chunk-LQ6Z4FXN.js";
|
|
7
|
-
import "./chunk-TEZRVSSB.js";
|
|
8
|
-
import "./chunk-PMMHVSCR.js";
|
|
9
|
-
import "./chunk-2TR2OPVA.js";
|
|
10
|
-
import "./chunk-46DYYHN6.js";
|
|
11
|
-
import "./chunk-VUM2K6EN.js";
|
|
12
|
-
import "./chunk-5DPRTREW.js";
|
|
13
|
-
import "./chunk-CU6OFXMM.js";
|
|
14
|
-
import "./chunk-KXXJYY62.js";
|
|
15
|
-
import "./chunk-7AZQFSOV.js";
|
|
16
|
-
import "./chunk-GVVVMZ4J.js";
|
|
17
|
-
import "./chunk-3F7XK5Q7.js";
|
|
18
|
-
import "./chunk-SNW2NPP4.js";
|
|
19
|
-
import "./chunk-UIM5NHPP.js";
|
|
20
|
-
import "./chunk-N42QMDID.js";
|
|
21
|
-
import "./chunk-ORNY3MZR.js";
|
|
22
|
-
import "./chunk-A6FLW5XD.js";
|
|
23
|
-
import "./chunk-T2TP6ZC6.js";
|
|
24
|
-
import "./chunk-LGNUFVMR.js";
|
|
25
|
-
import "./chunk-2NHRJ3YO.js";
|
|
26
|
-
import "./chunk-CJ26DXZL.js";
|
|
27
|
-
import "./chunk-K3NQKI34.js";
|
|
28
|
-
export {
|
|
29
|
-
clearEchoTextCache,
|
|
30
|
-
echoTextToChannel
|
|
31
|
-
};
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
MindManager,
|
|
4
|
-
getMindManager,
|
|
5
|
-
initMindManager
|
|
6
|
-
} from "./chunk-TEZRVSSB.js";
|
|
7
|
-
import "./chunk-PMMHVSCR.js";
|
|
8
|
-
import "./chunk-2TR2OPVA.js";
|
|
9
|
-
import "./chunk-46DYYHN6.js";
|
|
10
|
-
import "./chunk-VUM2K6EN.js";
|
|
11
|
-
import "./chunk-5DPRTREW.js";
|
|
12
|
-
import "./chunk-CU6OFXMM.js";
|
|
13
|
-
import "./chunk-KXXJYY62.js";
|
|
14
|
-
import "./chunk-7AZQFSOV.js";
|
|
15
|
-
import "./chunk-GVVVMZ4J.js";
|
|
16
|
-
import "./chunk-3F7XK5Q7.js";
|
|
17
|
-
import "./chunk-SNW2NPP4.js";
|
|
18
|
-
import "./chunk-UIM5NHPP.js";
|
|
19
|
-
import "./chunk-N42QMDID.js";
|
|
20
|
-
import "./chunk-ORNY3MZR.js";
|
|
21
|
-
import "./chunk-A6FLW5XD.js";
|
|
22
|
-
import "./chunk-T2TP6ZC6.js";
|
|
23
|
-
import "./chunk-2NHRJ3YO.js";
|
|
24
|
-
import "./chunk-CJ26DXZL.js";
|
|
25
|
-
import "./chunk-K3NQKI34.js";
|
|
26
|
-
export {
|
|
27
|
-
MindManager,
|
|
28
|
-
getMindManager,
|
|
29
|
-
initMindManager
|
|
30
|
-
};
|