diff options
Diffstat (limited to 'crates/dinggerd/assets/pi/pi-agent-state.ts')
| -rw-r--r-- | crates/dinggerd/assets/pi/pi-agent-state.ts | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/crates/dinggerd/assets/pi/pi-agent-state.ts b/crates/dinggerd/assets/pi/pi-agent-state.ts index e4e357d..fc70638 100644 --- a/crates/dinggerd/assets/pi/pi-agent-state.ts +++ b/crates/dinggerd/assets/pi/pi-agent-state.ts @@ -116,6 +116,9 @@ function savedImportance(ctx: any): Importance { // it comes back when the session does after a crash, a restart, or // `pi --session`. let draft = ""; +// How full the context window is, in percent, as pi's footer shows it; +// "" when unknown (right after compacting, before the next reply). +let context = ""; const draftDir = path.join(path.dirname(socketPath), "drafts"); // Enough to find the agent by it; the file keeps all of it. const reportedDraftChars = 500; @@ -178,6 +181,7 @@ async function report(state: AgentState | undefined, message?: string): Promise< extension: extensionVersion, ...(controlListening ? { control: controlPath } : {}), draft: draft.slice(0, reportedDraftChars), + context, seq: Date.now() * 1000, ...(sessionFile ? { agent_session_path: sessionFile } : {}), }, @@ -342,6 +346,26 @@ export default function (pi) { void report(undefined); } + /** Report how full the context window is, when that changed. */ + function checkContext(ctx: any, quiet = false): void { + let next = ""; + try { + const percent = ctx?.getContextUsage?.()?.percent; + if (typeof percent === "number" && Number.isFinite(percent)) { + next = percent.toFixed(1); + } + } catch { + return; + } + if (next === context) { + return; + } + context = next; + if (!quiet) { + void report(undefined); + } + } + function checkDraftSoon(): void { if (draftTimer) { clearTimeout(draftTimer); @@ -469,6 +493,8 @@ export default function (pi) { // Each session has its own: /new starts at normal, /resume brings its own back. importance = savedImportance(ctx); announceImportance(); + // The report below carries it. + checkContext(ctx, true); publishState(true); }); @@ -481,6 +507,15 @@ export default function (pi) { checkDraftSoon(); }); + // Each message fills the context (a prompt by pi's estimate, a reply by + // its usage); compacting empties it; another model or branch changes it. + for (const event of ["message_end", "session_compact", "model_select", "session_tree"]) { + pi.on(event, (_event, ctx) => { + latestCtx = ctx; + checkContext(ctx); + }); + } + pi.on("agent_settled", (_event, ctx) => { latestCtx = ctx; if (ctx?.isIdle?.() !== true) { @@ -488,6 +523,8 @@ export default function (pi) { } agentActive = false; + // The last reply's usage: message_end comes before pi counts it. + checkContext(ctx); publishState(); // Escape puts queued messages back into the input box. checkDraftSoon(); |
