volute 0.33.0 → 0.34.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-D5VBM7JW.js → accept-TW6V4WI4.js} +6 -6
- package/dist/{activity-events-XJO3P4RR.js → activity-events-BN7V6KCC.js} +4 -4
- package/dist/{ai-service-SBY2WG7O.js → ai-service-PSILB5WD.js} +5 -5
- package/dist/{api-client-YPKOZP2O.js → api-client-XUXOB7LI.js} +1 -1
- package/dist/api.d.ts +426 -3
- package/dist/{archive-INXYFVCW.js → archive-C2VEMQOR.js} +4 -4
- package/dist/{auth-GKCDSO4T.js → auth-ZFZXJZDQ.js} +5 -5
- package/dist/{bridge-TXWWPPOJ.js → bridge-O753D5F4.js} +6 -6
- package/dist/{chat-U5ZOME3O.js → chat-BHYX7DJ4.js} +9 -9
- package/dist/{chunk-M7UL5S3Q.js → chunk-2IOP6PHB.js} +1 -1
- package/dist/{chunk-NPKSDYA2.js → chunk-47XDEWWV.js} +5 -5
- package/dist/{chunk-RSX4OPZY.js → chunk-47ZPNLF4.js} +7 -7
- package/dist/{chunk-RPZZSXV3.js → chunk-4JSR7YO7.js} +20 -1
- package/dist/{chunk-N432I7QH.js → chunk-6OWJXUAR.js} +1 -1
- package/dist/{chunk-I5KY25PQ.js → chunk-6WAWMWR5.js} +1 -1
- package/dist/{chunk-NNB4WIG7.js → chunk-7F2SW2KD.js} +2 -2
- package/dist/chunk-7KJOFUNN.js +22 -0
- package/dist/{chunk-7J3HEVR7.js → chunk-B2BVAIZ4.js} +15 -9
- package/dist/{chunk-VH33ZWMW.js → chunk-BDK73LK6.js} +1 -1
- package/dist/{chunk-QTUVYI7W.js → chunk-BFWHBQK4.js} +1 -1
- package/dist/{chunk-JYVGHWEJ.js → chunk-BM474GX6.js} +3 -3
- package/dist/{chunk-LOEJ4HPQ.js → chunk-BTWAGDV5.js} +1 -1
- package/dist/{chunk-A2A4KLFE.js → chunk-CVL5IGIR.js} +596 -40
- package/dist/{chunk-RVGLDGMI.js → chunk-E5C7OWZ2.js} +20 -22
- package/dist/chunk-FYCALD4Q.js +23 -0
- package/dist/{chunk-SKLSMHXO.js → chunk-IS7WJ56Q.js} +1 -1
- package/dist/{chunk-2NGTS5UU.js → chunk-M3K5AARV.js} +1 -1
- package/dist/{chunk-ALEF47VT.js → chunk-MLOQKQNB.js} +1 -1
- package/dist/{chunk-C7I35G4R.js → chunk-N3DNFPVA.js} +41 -5
- package/dist/{chunk-LRCG2JLP.js → chunk-N7BLAHNE.js} +5 -1
- package/dist/{chunk-UKVWJRKN.js → chunk-PLDWHR4D.js} +1 -1
- package/dist/{chunk-3Z2DPESO.js → chunk-TAHX36HZ.js} +126 -81
- package/dist/{chunk-KIEPMIM5.js → chunk-U5BTYSAL.js} +1 -1
- package/dist/{chunk-GY5HBI7A.js → chunk-V45JXOWY.js} +2 -2
- package/dist/{chunk-JUKK7FPS.js → chunk-V6ZCNULL.js} +2 -2
- package/dist/{chunk-KVK2DLWI.js → chunk-XWXBJQBE.js} +2 -2
- package/dist/cli.js +23 -23
- package/dist/{clock-BVH3V6E3.js → clock-3X4DSC2N.js} +40 -25
- package/dist/{cloud-sync-4NWLMFVH.js → cloud-sync-TG3TIX5H.js} +21 -21
- package/dist/{config-H2H4UIF7.js → config-OROA5DUA.js} +4 -4
- package/dist/connectors/discord-bridge.js +1 -1
- package/dist/connectors/slack-bridge.js +1 -1
- package/dist/connectors/telegram-bridge.js +1 -1
- package/dist/{conversations-AWI5SZW2.js → conversations-HL2JP5GI.js} +5 -5
- package/dist/{create-YWD2TIP4.js → create-3SEKKI6P.js} +6 -6
- package/dist/{create-2FK7Z46Y.js → create-UOSOQ2HN.js} +4 -4
- package/dist/daemon-client-WOAQXXBM.js +12 -0
- package/dist/{daemon-restart-GOBUKLX7.js → daemon-restart-5ABHNXJZ.js} +9 -9
- package/dist/daemon.js +1747 -688
- package/dist/{db-RA45JBFG.js → db-PLEDCBHZ.js} +1 -1
- package/dist/db-RYX3SS2W.js +9 -0
- package/dist/{delete-QTGWEDBI.js → delete-KYOVWR23.js} +3 -3
- package/dist/delivery-manager-2BR5NZKF.js +32 -0
- package/dist/{delivery-router-FL45JL7N.js → delivery-router-D5ELDMS2.js} +4 -4
- package/dist/down-QVFN4UPK.js +15 -0
- package/dist/{env-JCOF2222.js → env-R34DT7XL.js} +12 -8
- package/dist/exec-DVLXKRIO.js +17 -0
- package/dist/{export-SUYRLI5Q.js → export-6ZXAXATG.js} +6 -6
- package/dist/extension-PM42QCID.js +97 -0
- package/dist/extensions-BBGVL5JC.js +38 -0
- package/dist/{files-65PMW5IK.js → files-VQV2VZQO.js} +7 -7
- package/dist/{import-DDUFE7AY.js → import-MK2I2T6F.js} +5 -5
- package/dist/{isolation-LLAYQYDY.js → isolation-62MKDZN3.js} +4 -4
- package/dist/{join-I5QEE3LG.js → join-DGYHTJUH.js} +3 -3
- package/dist/lib-DYEZMGW7.js +6588 -0
- package/dist/{list-JQ463EDA.js → list-C644WTHV.js} +18 -10
- package/dist/{login-D7ETSU4R.js → login-IIGEQPHL.js} +6 -6
- package/dist/{login-RIJF2F4G.js → login-KZQLMAWE.js} +4 -4
- package/dist/{logout-5MLHZALK.js → logout-AGTZVRGP.js} +4 -4
- package/dist/{logout-UZJRGY4Z.js → logout-KD6GXIJJ.js} +4 -4
- package/dist/message-delivery-V3R6NXJP.js +42 -0
- package/dist/{mind-IOJFLEM5.js → mind-BI4EPBVZ.js} +19 -19
- package/dist/{mind-activity-tracker-F6O4Q2SL.js → mind-activity-tracker-2ACNHA7B.js} +5 -5
- package/dist/mind-history-WOYFLQAI.js +264 -0
- package/dist/{mind-list-WUPMQDYQ.js → mind-list-6VPM7GUQ.js} +4 -4
- package/dist/mind-manager-MWW3BTS4.js +32 -0
- package/dist/{mind-profile-P67FEHOY.js → mind-profile-WPG42U5Y.js} +2 -2
- package/dist/mind-service-VIKZJK2M.js +38 -0
- package/dist/{mind-sleep-WW2IX7JT.js → mind-sleep-XDISJY74.js} +6 -6
- package/dist/{mind-status-L3EFFRPR.js → mind-status-7FTZWPZF.js} +4 -4
- package/dist/{mind-wake-VSSGW465.js → mind-wake-KIIKEI3A.js} +6 -6
- package/dist/{package-U3VFO273.js → package-V2WHWVG6.js} +8 -5
- package/dist/{read-EBY56C33.js → read-H5C26YO7.js} +20 -10
- package/dist/{read-stdin-HQJ7774D.js → read-stdin-PIRM6A2Y.js} +1 -1
- package/dist/{register-HD74C4TT.js → register-J27WP33N.js} +6 -6
- package/dist/{registry-PJ4S5PHQ.js → registry-UYV5S6QT.js} +3 -3
- package/dist/{reject-UJKFBHRO.js → reject-OEANJYIA.js} +6 -6
- package/dist/{restart-3UCMRUVC.js → restart-V5EGYBJG.js} +4 -4
- package/dist/{sandbox-GJOK4QLQ.js → sandbox-SI5HMBP3.js} +5 -5
- package/dist/scheduler-AGG3L2FO.js +32 -0
- package/dist/{schema-PA3M5ZKH.js → schema-ETMABTW4.js} +4 -2
- package/dist/{seed-QDYVLG74.js → seed-WNGI6PNW.js} +2 -2
- package/dist/{seed-check-S2IX25RL.js → seed-check-PXTH7YXS.js} +2 -2
- package/dist/{seed-cmd-DKOUFEAU.js → seed-cmd-VENFTGS3.js} +4 -4
- package/dist/{seed-create-4XBBOLRH.js → seed-create-663ALOKH.js} +6 -6
- package/dist/{seed-sprout-GQEIIQRT.js → seed-sprout-EH3AGKAI.js} +12 -12
- package/dist/{send-QIV2INHB.js → send-7FUUUZZH.js} +23 -10
- package/dist/{setup-TISPCO22.js → setup-GGMKENLN.js} +4 -4
- package/dist/{setup-XMCBE3LF.js → setup-Z3DEVWV7.js} +11 -11
- package/dist/{skill-PSQGRRJX.js → skill-DKNYJS4P.js} +14 -10
- package/dist/skills/plan-coordinator/SKILL.md +60 -0
- package/dist/skills/volute-mind/SKILL.md +7 -221
- package/dist/skills/volute-mind/references/extensions.md +37 -0
- package/dist/skills/volute-mind/references/integrations.md +48 -0
- package/dist/skills/volute-mind/references/routing.md +86 -0
- package/dist/skills/volute-mind/references/sleep.md +33 -0
- package/dist/skills/volute-mind/references/variants.md +31 -0
- package/dist/{skills-7FV7EJTE.js → skills-Q6VZ2UGD.js} +11 -7
- package/dist/sleep-manager-BJK2ROPX.js +36 -0
- package/dist/spirit-4JP4TY4C.js +23 -0
- package/dist/{split-STOROBYJ.js → split-3YPMS2CL.js} +3 -3
- package/dist/{sprout-WKLZXUIQ.js → sprout-E3HJIV2Z.js} +2 -2
- package/dist/{start-K2NCUUCG.js → start-W3TPKX4D.js} +4 -4
- package/dist/{status-3JBTFSMI.js → status-4OVFXFEJ.js} +7 -7
- package/dist/{stop-H26JZDXF.js → stop-GTT6YWYO.js} +4 -4
- package/dist/system-channel-DXD2JBOU.js +36 -0
- package/dist/system-chat-TYLOL7SX.js +36 -0
- package/dist/{systems-XRI52VCH.js → systems-AYLO727G.js} +7 -7
- package/dist/{tailscale-XHQBZROW.js → tailscale-ZEUK7GKZ.js} +3 -3
- package/dist/{template-hash-A6VVKOXJ.js → template-hash-EJRTKE36.js} +1 -1
- package/dist/up-PA7F2CXE.js +18 -0
- package/dist/{update-UD543CXX.js → update-HG4LCUSG.js} +7 -7
- package/dist/{update-check-ZD6OOIYQ.js → update-check-X3YG4WVP.js} +4 -4
- package/dist/{upgrade-O4Q7WJM3.js → upgrade-YGNIDICG.js} +3 -3
- package/dist/{variant-7TGZHOU3.js → variant-MZUMRTQO.js} +1 -1
- package/dist/{version-notify-NBI2MTJO.js → version-notify-YCH4UVQ2.js} +19 -19
- package/dist/{volute-config-HD7WWUQC.js → volute-config-WBKYJGYQ.js} +1 -1
- package/dist/web-assets/assets/index-DiiwC-CZ.css +1 -0
- package/dist/web-assets/assets/index-d6y5b9Ij.js +75 -0
- package/dist/web-assets/ext-theme.css +48 -9
- package/dist/web-assets/index.html +2 -2
- package/drizzle/0005_meta_summaries.sql +15 -0
- package/drizzle/meta/0005_snapshot.json +7 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +7 -4
- package/packages/extensions/plan/dist/ui/assets/index-CJj2gZnZ.css +1 -0
- package/packages/extensions/plan/dist/ui/assets/index-FMEJmvQz.js +61 -0
- package/packages/extensions/plan/dist/ui/index.html +14 -0
- package/packages/extensions/plan/skills/plan/SKILL.md +43 -0
- package/packages/extensions/plan/skills/plan/scripts/plan-hook.sh +37 -0
- package/templates/_base/home/VOLUTE.md +12 -19
- package/templates/_base/src/lib/context-breakdown.ts +450 -0
- package/templates/_base/src/lib/format-prefix.ts +17 -0
- package/templates/_base/src/lib/hook-loader.ts +8 -2
- package/templates/_base/src/lib/router.ts +75 -33
- package/templates/_base/src/lib/routing.ts +4 -1
- package/templates/_base/src/lib/startup.ts +16 -8
- package/templates/_base/src/lib/types.ts +2 -1
- package/templates/_base/src/lib/volute-server.ts +69 -8
- package/templates/claude/.init/CLAUDE.md +4 -10
- package/templates/claude/package.json.tmpl +1 -0
- package/templates/claude/src/agent.ts +100 -32
- package/templates/claude/src/lib/hooks/reply-instructions.ts +27 -7
- package/templates/claude/src/lib/stream-consumer.ts +2 -2
- package/templates/claude/src/server.ts +1 -0
- package/templates/codex/package.json.tmpl +1 -0
- package/templates/codex/src/agent.ts +80 -8
- package/templates/codex/src/server.ts +1 -4
- package/templates/pi/package.json.tmpl +1 -0
- package/templates/pi/src/agent.ts +115 -36
- package/templates/pi/src/lib/event-handler.ts +22 -7
- package/templates/pi/src/lib/reply-instructions-extension.ts +23 -4
- package/templates/pi/src/lib/subagents.ts +20 -17
- package/templates/pi/src/server.ts +2 -5
- package/dist/chunk-K3NQKI34.js +0 -10
- package/dist/daemon-client-6QXHZ7US.js +0 -12
- package/dist/db-F34YLV7D.js +0 -9
- package/dist/delivery-manager-PFAKEJTC.js +0 -32
- package/dist/down-FWWTEKXM.js +0 -15
- package/dist/extension-OBTGKQQD.js +0 -175
- package/dist/extensions-KYNTVTMO.js +0 -30
- package/dist/history-DKCDI3JO.js +0 -128
- package/dist/message-delivery-DFF5SJRM.js +0 -42
- package/dist/mind-manager-NBJF5D26.js +0 -32
- package/dist/mind-service-2MQ6UK5N.js +0 -38
- package/dist/scheduler-ZZ7XGQG6.js +0 -32
- package/dist/sleep-manager-JTXSN7NV.js +0 -36
- package/dist/spirit-VRONKFMF.js +0 -23
- package/dist/system-chat-JAPOJ3KE.js +0 -36
- package/dist/up-M5AS6SBV.js +0 -18
- package/dist/web-assets/assets/index-CWJrVveV.css +0 -1
- package/dist/web-assets/assets/index-DJt14FRI.js +0 -75
|
@@ -10,12 +10,19 @@ import {
|
|
|
10
10
|
SettingsManager,
|
|
11
11
|
} from "@mariozechner/pi-coding-agent";
|
|
12
12
|
import { extractImages, extractText } from "./lib/content.js";
|
|
13
|
+
import {
|
|
14
|
+
countSdkInstructionTokens,
|
|
15
|
+
countSkillDescriptionTokens,
|
|
16
|
+
countSystemPromptTokens,
|
|
17
|
+
findPiSessionFile,
|
|
18
|
+
parsePiSessionJSONL,
|
|
19
|
+
} from "./lib/context-breakdown.js";
|
|
13
20
|
import { createEventHandler, emit } from "./lib/event-handler.js";
|
|
14
21
|
import { runHooks } from "./lib/hook-loader.js";
|
|
15
22
|
import { log } from "./lib/logger.js";
|
|
16
23
|
import { createReplyInstructionsExtension } from "./lib/reply-instructions-extension.js";
|
|
17
24
|
import { resolveModel } from "./lib/resolve-model.js";
|
|
18
|
-
import { loadPrompts, type SubagentConfig } from "./lib/startup.js";
|
|
25
|
+
import { getStartupContext, loadPrompts, type SubagentConfig } from "./lib/startup.js";
|
|
19
26
|
import { createSubagentExtension, type SubagentDefinition } from "./lib/subagents.js";
|
|
20
27
|
import type {
|
|
21
28
|
HandlerMeta,
|
|
@@ -25,6 +32,7 @@ import type {
|
|
|
25
32
|
VoluteContentPart,
|
|
26
33
|
VoluteEvent,
|
|
27
34
|
} from "./lib/types.js";
|
|
35
|
+
import type { ContextInfo } from "./lib/volute-server.js";
|
|
28
36
|
|
|
29
37
|
type PiAgentSession = Awaited<ReturnType<typeof createAgentSession>>["session"];
|
|
30
38
|
|
|
@@ -36,7 +44,8 @@ type PiSession = {
|
|
|
36
44
|
unsubscribe?: () => void;
|
|
37
45
|
messageIds: (string | undefined)[];
|
|
38
46
|
currentMessageId?: string;
|
|
39
|
-
messageChannels: Map<string, string>;
|
|
47
|
+
messageChannels: Map<string, { channel: string; sender?: string }>;
|
|
48
|
+
contextTokens: number;
|
|
40
49
|
};
|
|
41
50
|
|
|
42
51
|
export function createMind(options: {
|
|
@@ -48,7 +57,7 @@ export function createMind(options: {
|
|
|
48
57
|
compactionMessage?: string;
|
|
49
58
|
maxContextTokens?: number;
|
|
50
59
|
subagents?: Record<string, SubagentConfig>;
|
|
51
|
-
}): { resolve: HandlerResolver } {
|
|
60
|
+
}): { resolve: HandlerResolver; getContextInfo: () => ContextInfo } {
|
|
52
61
|
const sessions = new Map<string, PiSession>();
|
|
53
62
|
const prompts = loadPrompts();
|
|
54
63
|
const today = new Date().toLocaleDateString("en-CA");
|
|
@@ -109,13 +118,40 @@ export function createMind(options: {
|
|
|
109
118
|
? createSubagentExtension(subagents, { cwd: options.cwd, model, authStorage, modelRegistry })
|
|
110
119
|
: undefined;
|
|
111
120
|
|
|
121
|
+
// --- Startup context (loaded once, injected on first turn per session) ---
|
|
122
|
+
|
|
123
|
+
const startupContextPromise = getStartupContext().catch(() => null);
|
|
124
|
+
|
|
112
125
|
// --- Dynamic hook extension ---
|
|
113
126
|
|
|
114
127
|
const hooksDir = resolvePath(options.cwd, ".local/hooks");
|
|
115
128
|
|
|
116
129
|
function createDynamicHookExtension(session: PiSession): ExtensionFactory {
|
|
130
|
+
let startupContextInjected = false;
|
|
131
|
+
const pendingToolArgs = new Map<string, Record<string, unknown>>();
|
|
132
|
+
|
|
117
133
|
return (pi) => {
|
|
134
|
+
pi.on("tool_execution_start", (event) => {
|
|
135
|
+
pendingToolArgs.set(event.toolCallId, event.args);
|
|
136
|
+
});
|
|
137
|
+
|
|
118
138
|
pi.on("before_agent_start", async () => {
|
|
139
|
+
const parts: string[] = [];
|
|
140
|
+
|
|
141
|
+
// Inject startup context on the first turn of each session
|
|
142
|
+
if (!startupContextInjected) {
|
|
143
|
+
startupContextInjected = true;
|
|
144
|
+
const startupContext = await startupContextPromise;
|
|
145
|
+
if (startupContext) {
|
|
146
|
+
emit(session, {
|
|
147
|
+
type: "context",
|
|
148
|
+
content: startupContext,
|
|
149
|
+
metadata: { source: "startup-context" },
|
|
150
|
+
});
|
|
151
|
+
parts.push(startupContext);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
119
155
|
try {
|
|
120
156
|
const result = await runHooks(hooksDir, "pre-prompt", {
|
|
121
157
|
event: "pre-prompt",
|
|
@@ -127,26 +163,32 @@ export function createMind(options: {
|
|
|
127
163
|
content: result.additionalContext,
|
|
128
164
|
metadata: { source: "dynamic:pre-prompt", ...result.metadata },
|
|
129
165
|
});
|
|
130
|
-
|
|
131
|
-
message: {
|
|
132
|
-
customType: "dynamic-hook",
|
|
133
|
-
content: result.additionalContext,
|
|
134
|
-
display: true,
|
|
135
|
-
},
|
|
136
|
-
};
|
|
166
|
+
parts.push(result.additionalContext);
|
|
137
167
|
}
|
|
138
168
|
} catch (err) {
|
|
139
169
|
log("mind", "dynamic pre-prompt hook failed:", err);
|
|
140
170
|
}
|
|
171
|
+
|
|
172
|
+
if (parts.length > 0) {
|
|
173
|
+
return {
|
|
174
|
+
message: {
|
|
175
|
+
customType: "dynamic-hook",
|
|
176
|
+
content: parts.join("\n\n"),
|
|
177
|
+
display: true,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
141
181
|
return {};
|
|
142
182
|
});
|
|
143
183
|
|
|
144
|
-
pi.on("tool_execution_end", async (event
|
|
184
|
+
pi.on("tool_execution_end", async (event) => {
|
|
185
|
+
const toolInput = pendingToolArgs.get(event.toolCallId);
|
|
186
|
+
pendingToolArgs.delete(event.toolCallId);
|
|
145
187
|
try {
|
|
146
188
|
const result = await runHooks(hooksDir, "post-tool-use", {
|
|
147
189
|
event: "post-tool-use",
|
|
148
190
|
tool_name: event.toolName,
|
|
149
|
-
tool_input:
|
|
191
|
+
tool_input: toolInput,
|
|
150
192
|
});
|
|
151
193
|
if (result.additionalContext) {
|
|
152
194
|
emit(session, {
|
|
@@ -175,6 +217,7 @@ export function createMind(options: {
|
|
|
175
217
|
listeners: new Set(),
|
|
176
218
|
messageIds: [],
|
|
177
219
|
messageChannels: new Map(),
|
|
220
|
+
contextTokens: 0,
|
|
178
221
|
};
|
|
179
222
|
sessions.set(name, session);
|
|
180
223
|
|
|
@@ -280,29 +323,33 @@ export function createMind(options: {
|
|
|
280
323
|
createEventHandler(session, {
|
|
281
324
|
cwd: options.cwd,
|
|
282
325
|
broadcast: (event) => broadcast(session, event),
|
|
283
|
-
onContextTokens:
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
);
|
|
298
|
-
// Send compaction warning; compaction will follow after the mind finishes its response turn
|
|
299
|
-
session.messageIds.push(undefined);
|
|
300
|
-
session.agentSession.prompt(compactionMessage, {
|
|
301
|
-
streamingBehavior: "followUp",
|
|
302
|
-
});
|
|
303
|
-
}
|
|
326
|
+
onContextTokens: (tokens: number) => {
|
|
327
|
+
session.contextTokens = tokens;
|
|
328
|
+
if (
|
|
329
|
+
maxContextTokens &&
|
|
330
|
+
tokens >= maxContextTokens &&
|
|
331
|
+
!compactionTriggered &&
|
|
332
|
+
!compactionInProgress
|
|
333
|
+
) {
|
|
334
|
+
if (!session.agentSession) {
|
|
335
|
+
log(
|
|
336
|
+
"mind",
|
|
337
|
+
`session "${session.name}": compaction threshold hit but session not ready`,
|
|
338
|
+
);
|
|
339
|
+
return;
|
|
304
340
|
}
|
|
305
|
-
|
|
341
|
+
compactionTriggered = true;
|
|
342
|
+
log(
|
|
343
|
+
"mind",
|
|
344
|
+
`session "${session.name}": ${tokens} tokens >= ${maxContextTokens} — triggering compaction`,
|
|
345
|
+
);
|
|
346
|
+
// Send compaction warning; compaction will follow after the mind finishes its response turn
|
|
347
|
+
session.messageIds.push(undefined);
|
|
348
|
+
session.agentSession.prompt(compactionMessage, {
|
|
349
|
+
streamingBehavior: "followUp",
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
},
|
|
306
353
|
onTurnEnd: maxContextTokens
|
|
307
354
|
? () => {
|
|
308
355
|
try {
|
|
@@ -378,7 +425,10 @@ export function createMind(options: {
|
|
|
378
425
|
|
|
379
426
|
// Track channel for reply instructions
|
|
380
427
|
if (meta.channel) {
|
|
381
|
-
session.messageChannels.set(meta.messageId,
|
|
428
|
+
session.messageChannels.set(meta.messageId, {
|
|
429
|
+
channel: meta.channel,
|
|
430
|
+
sender: meta.sender,
|
|
431
|
+
});
|
|
382
432
|
}
|
|
383
433
|
|
|
384
434
|
// Track messageId (must be pushed before prompt)
|
|
@@ -433,5 +483,34 @@ export function createMind(options: {
|
|
|
433
483
|
return handler;
|
|
434
484
|
}
|
|
435
485
|
|
|
436
|
-
|
|
486
|
+
const piSessionsDir = resolvePath(options.mindDir, ".mind/pi-sessions");
|
|
487
|
+
const systemPromptTokens = countSystemPromptTokens(options.systemPrompt);
|
|
488
|
+
const claudeMdTokens = countSdkInstructionTokens(options.cwd);
|
|
489
|
+
const skillDescTokens = countSkillDescriptionTokens([resolvePath(options.cwd, ".pi/skills")]);
|
|
490
|
+
|
|
491
|
+
function getContextInfo(): ContextInfo {
|
|
492
|
+
return {
|
|
493
|
+
sessions: Array.from(sessions.values()).map((s) => {
|
|
494
|
+
try {
|
|
495
|
+
const jsonlPath = findPiSessionFile(piSessionsDir, s.name);
|
|
496
|
+
const parsed = jsonlPath
|
|
497
|
+
? parsePiSessionJSONL(jsonlPath, systemPromptTokens, claudeMdTokens, skillDescTokens)
|
|
498
|
+
: null;
|
|
499
|
+
|
|
500
|
+
return {
|
|
501
|
+
name: s.name,
|
|
502
|
+
contextTokens: parsed?.contextTokens ?? s.contextTokens,
|
|
503
|
+
contextWindow: maxContextTokens,
|
|
504
|
+
breakdown: parsed?.breakdown,
|
|
505
|
+
};
|
|
506
|
+
} catch (err) {
|
|
507
|
+
log("mind", `failed to get context breakdown for session "${s.name}":`, err);
|
|
508
|
+
return { name: s.name, contextTokens: s.contextTokens, contextWindow: maxContextTokens };
|
|
509
|
+
}
|
|
510
|
+
}),
|
|
511
|
+
systemPrompt: systemPromptTokens,
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
return { resolve, getContextInfo };
|
|
437
516
|
}
|
|
@@ -1,14 +1,29 @@
|
|
|
1
|
+
import type { AgentSessionEvent } from "@mariozechner/pi-coding-agent";
|
|
1
2
|
import { flushFileChanges, trackFileChange } from "./auto-commit.js";
|
|
2
3
|
import { daemonEmit, type EventType } from "./daemon-client.js";
|
|
3
4
|
import { log, warn } from "./logger.js";
|
|
4
5
|
import { filterEvent, loadTransparencyPreset } from "./transparency.js";
|
|
5
6
|
import type { VoluteEvent } from "./types.js";
|
|
6
7
|
|
|
8
|
+
/** Minimal shape of the messages in an agent_end event (subset of AgentMessage). */
|
|
9
|
+
type AgentEndMessage = {
|
|
10
|
+
role?: string;
|
|
11
|
+
errorMessage?: string;
|
|
12
|
+
usage?: {
|
|
13
|
+
input?: number;
|
|
14
|
+
output?: number;
|
|
15
|
+
cacheWrite?: number;
|
|
16
|
+
cache_creation?: number;
|
|
17
|
+
cacheRead?: number;
|
|
18
|
+
cache_read?: number;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
7
22
|
export type EventSession = {
|
|
8
23
|
name: string;
|
|
9
24
|
messageIds: (string | undefined)[];
|
|
10
25
|
currentMessageId?: string;
|
|
11
|
-
messageChannels: Map<string, string>;
|
|
26
|
+
messageChannels: Map<string, { channel: string; sender?: string }>;
|
|
12
27
|
};
|
|
13
28
|
|
|
14
29
|
export type EventHandlerOptions = {
|
|
@@ -26,7 +41,7 @@ export function emit(
|
|
|
26
41
|
event: { type: EventType; content?: string; metadata?: Record<string, unknown> },
|
|
27
42
|
) {
|
|
28
43
|
const channel = session.currentMessageId
|
|
29
|
-
? session.messageChannels.get(session.currentMessageId)
|
|
44
|
+
? session.messageChannels.get(session.currentMessageId)?.channel
|
|
30
45
|
: undefined;
|
|
31
46
|
const filtered = filterEvent(preset, {
|
|
32
47
|
...event,
|
|
@@ -38,7 +53,7 @@ export function emit(
|
|
|
38
53
|
}
|
|
39
54
|
|
|
40
55
|
export function createEventHandler(session: EventSession, options: EventHandlerOptions) {
|
|
41
|
-
const toolArgs = new Map<string,
|
|
56
|
+
const toolArgs = new Map<string, Record<string, unknown>>();
|
|
42
57
|
let textBuf = "";
|
|
43
58
|
let thinkingBuf = "";
|
|
44
59
|
|
|
@@ -63,7 +78,7 @@ export function createEventHandler(session: EventSession, options: EventHandlerO
|
|
|
63
78
|
|
|
64
79
|
let sessionStarted = false;
|
|
65
80
|
|
|
66
|
-
return (event:
|
|
81
|
+
return (event: AgentSessionEvent) => {
|
|
67
82
|
try {
|
|
68
83
|
if (!sessionStarted && event.type === "agent_start") {
|
|
69
84
|
sessionStarted = true;
|
|
@@ -108,7 +123,7 @@ export function createEventHandler(session: EventSession, options: EventHandlerO
|
|
|
108
123
|
// Auto-commit file changes in home/
|
|
109
124
|
if ((event.toolName === "edit" || event.toolName === "write") && !event.isError) {
|
|
110
125
|
const args = toolArgs.get(event.toolCallId);
|
|
111
|
-
const filePath =
|
|
126
|
+
const filePath = typeof args?.path === "string" ? args.path : undefined;
|
|
112
127
|
if (filePath) {
|
|
113
128
|
trackFileChange(filePath, options.cwd);
|
|
114
129
|
}
|
|
@@ -124,7 +139,7 @@ export function createEventHandler(session: EventSession, options: EventHandlerO
|
|
|
124
139
|
log("mind", `session "${session.name}": turn done`);
|
|
125
140
|
// Log any error messages from the agent
|
|
126
141
|
if (event.messages) {
|
|
127
|
-
for (const msg of event.messages as
|
|
142
|
+
for (const msg of event.messages as AgentEndMessage[]) {
|
|
128
143
|
if (msg.errorMessage) {
|
|
129
144
|
warn("mind", `session "${session.name}": agent error: ${msg.errorMessage}`);
|
|
130
145
|
}
|
|
@@ -136,7 +151,7 @@ export function createEventHandler(session: EventSession, options: EventHandlerO
|
|
|
136
151
|
let inputTokens = 0;
|
|
137
152
|
let outputTokens = 0;
|
|
138
153
|
let lastInputTokens = 0;
|
|
139
|
-
for (const msg of event.messages as
|
|
154
|
+
for (const msg of event.messages as AgentEndMessage[]) {
|
|
140
155
|
if (msg.role === "assistant" && msg.usage) {
|
|
141
156
|
inputTokens += msg.usage.input ?? 0;
|
|
142
157
|
outputTokens += msg.usage.output ?? 0;
|
|
@@ -4,7 +4,7 @@ import { log } from "./logger.js";
|
|
|
4
4
|
import { loadPrompts } from "./startup.js";
|
|
5
5
|
|
|
6
6
|
export function createReplyInstructionsExtension(
|
|
7
|
-
messageChannels: Map<string, string>,
|
|
7
|
+
messageChannels: Map<string, { channel: string; sender?: string }>,
|
|
8
8
|
emitContext?: (
|
|
9
9
|
session: EventSession,
|
|
10
10
|
event: { type: "context"; content: string; metadata: Record<string, unknown> },
|
|
@@ -18,12 +18,31 @@ export function createReplyInstructionsExtension(
|
|
|
18
18
|
try {
|
|
19
19
|
if (fired) return {};
|
|
20
20
|
|
|
21
|
-
const
|
|
22
|
-
if (!
|
|
21
|
+
const entry = messageChannels.values().next().value;
|
|
22
|
+
if (!entry) return {};
|
|
23
23
|
|
|
24
24
|
fired = true;
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
// System messages don't need reply instructions
|
|
27
|
+
if (entry.sender === "volute") {
|
|
28
|
+
const content = "This is a system message — no reply is needed.";
|
|
29
|
+
if (emitContext && session) {
|
|
30
|
+
emitContext(session, {
|
|
31
|
+
type: "context",
|
|
32
|
+
content,
|
|
33
|
+
metadata: { source: "reply-instructions" },
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
message: {
|
|
38
|
+
customType: "reply-instructions",
|
|
39
|
+
content,
|
|
40
|
+
display: true,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const content = prompts.reply_instructions.replace(/\$\{channel\}/g, entry.channel);
|
|
27
46
|
if (emitContext && session) {
|
|
28
47
|
emitContext(session, {
|
|
29
48
|
type: "context",
|
|
@@ -72,12 +72,26 @@ export function createSubagentExtension(
|
|
|
72
72
|
reject(new Error(`Subagent "${name}" timed out after 5 minutes`));
|
|
73
73
|
}, 300_000);
|
|
74
74
|
|
|
75
|
-
session.subscribe((event
|
|
76
|
-
if (event.type === "
|
|
75
|
+
session.subscribe((event) => {
|
|
76
|
+
if (event.type === "agent_end") {
|
|
77
77
|
clearTimeout(timeout);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
// Check for error messages first
|
|
79
|
+
for (const msg of event.messages ?? []) {
|
|
80
|
+
const m = msg as { errorMessage?: string };
|
|
81
|
+
if (m.errorMessage) {
|
|
82
|
+
reject(new Error(`Subagent "${name}" error: ${m.errorMessage}`));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
for (const msg of event.messages ?? []) {
|
|
87
|
+
const m = msg as { role?: string; content?: { type: string; text?: string }[] };
|
|
88
|
+
if (m.role === "assistant" && m.content) {
|
|
89
|
+
for (const block of m.content) {
|
|
90
|
+
if (block.type === "text" && block.text) textParts.push(block.text);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
resolve();
|
|
81
95
|
return;
|
|
82
96
|
}
|
|
83
97
|
if (event.type === "turn_end") {
|
|
@@ -86,17 +100,6 @@ export function createSubagentExtension(
|
|
|
86
100
|
session.abort();
|
|
87
101
|
}
|
|
88
102
|
}
|
|
89
|
-
if (event.type === "agent_end") {
|
|
90
|
-
clearTimeout(timeout);
|
|
91
|
-
for (const msg of event.messages ?? []) {
|
|
92
|
-
if (msg.role === "assistant" && msg.content) {
|
|
93
|
-
for (const block of msg.content) {
|
|
94
|
-
if (block.type === "text") textParts.push(block.text);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
resolve();
|
|
99
|
-
}
|
|
100
103
|
});
|
|
101
104
|
});
|
|
102
105
|
|
|
@@ -122,7 +125,7 @@ export function createSubagentExtension(
|
|
|
122
125
|
};
|
|
123
126
|
}
|
|
124
127
|
|
|
125
|
-
const TOOL_MAP: Record<string,
|
|
128
|
+
const TOOL_MAP: Record<string, (typeof codingTools)[number]> = {
|
|
126
129
|
Read: readTool,
|
|
127
130
|
Write: writeTool,
|
|
128
131
|
Bash: bashTool,
|
|
@@ -4,7 +4,6 @@ import { createFileHandlerResolver } from "./lib/file-handler.js";
|
|
|
4
4
|
import { log, setLevel } from "./lib/logger.js";
|
|
5
5
|
import { createRouter } from "./lib/router.js";
|
|
6
6
|
import {
|
|
7
|
-
handleStartupContext,
|
|
8
7
|
loadConfig,
|
|
9
8
|
loadPackageInfo,
|
|
10
9
|
loadSystemPrompt,
|
|
@@ -45,15 +44,13 @@ const server = createVoluteServer({
|
|
|
45
44
|
port,
|
|
46
45
|
name: pkg.name,
|
|
47
46
|
version: pkg.version,
|
|
47
|
+
getContextInfo: mind.getContextInfo,
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
server.listen(port,
|
|
50
|
+
server.listen(port, () => {
|
|
51
51
|
const addr = server.address();
|
|
52
52
|
const actualPort = typeof addr === "object" && addr ? addr.port : port;
|
|
53
53
|
log("server", `listening on :${actualPort}`);
|
|
54
|
-
await handleStartupContext((content) =>
|
|
55
|
-
router.route([{ type: "text", text: content }], { channel: "system" }),
|
|
56
|
-
);
|
|
57
54
|
});
|
|
58
55
|
|
|
59
56
|
setupShutdown();
|
package/dist/chunk-K3NQKI34.js
DELETED
package/dist/db-F34YLV7D.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
DeliveryManager,
|
|
4
|
-
getDeliveryManager,
|
|
5
|
-
initDeliveryManager
|
|
6
|
-
} from "./chunk-3Z2DPESO.js";
|
|
7
|
-
import "./chunk-SKLSMHXO.js";
|
|
8
|
-
import "./chunk-LOEJ4HPQ.js";
|
|
9
|
-
import "./chunk-RVGLDGMI.js";
|
|
10
|
-
import "./chunk-GY5HBI7A.js";
|
|
11
|
-
import "./chunk-7J3HEVR7.js";
|
|
12
|
-
import "./chunk-G53F3JA4.js";
|
|
13
|
-
import "./chunk-OYAKCAVY.js";
|
|
14
|
-
import "./chunk-2NGTS5UU.js";
|
|
15
|
-
import "./chunk-A2A4KLFE.js";
|
|
16
|
-
import "./chunk-PB65JZK2.js";
|
|
17
|
-
import "./chunk-JYVGHWEJ.js";
|
|
18
|
-
import "./chunk-KVK2DLWI.js";
|
|
19
|
-
import "./chunk-C7I35G4R.js";
|
|
20
|
-
import "./chunk-QTUVYI7W.js";
|
|
21
|
-
import "./chunk-YUIHSKR6.js";
|
|
22
|
-
import "./chunk-KIEPMIM5.js";
|
|
23
|
-
import "./chunk-VH33ZWMW.js";
|
|
24
|
-
import "./chunk-N432I7QH.js";
|
|
25
|
-
import "./chunk-LRCG2JLP.js";
|
|
26
|
-
import "./chunk-RPZZSXV3.js";
|
|
27
|
-
import "./chunk-K3NQKI34.js";
|
|
28
|
-
export {
|
|
29
|
-
DeliveryManager,
|
|
30
|
-
getDeliveryManager,
|
|
31
|
-
initDeliveryManager
|
|
32
|
-
};
|
package/dist/down-FWWTEKXM.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
run,
|
|
4
|
-
stopDaemon
|
|
5
|
-
} from "./chunk-JUKK7FPS.js";
|
|
6
|
-
import "./chunk-NNB4WIG7.js";
|
|
7
|
-
import "./chunk-KIEPMIM5.js";
|
|
8
|
-
import "./chunk-VH33ZWMW.js";
|
|
9
|
-
import "./chunk-LRCG2JLP.js";
|
|
10
|
-
import "./chunk-RPZZSXV3.js";
|
|
11
|
-
import "./chunk-K3NQKI34.js";
|
|
12
|
-
export {
|
|
13
|
-
run,
|
|
14
|
-
stopDaemon
|
|
15
|
-
};
|