|
1 | 1 | /** |
2 | | - * Runtime side-channel notices: lifecycle hooks, MCP connection state and |
3 | | - * recorded permission grants. |
| 2 | + * Runtime side-channel notices: lifecycle hooks, MCP connection state, |
| 3 | + * recorded permission grants, and successful context compaction. |
4 | 4 | * |
5 | 5 | * These channels are chatter by default and only sometimes news. The split |
6 | 6 | * this module encodes: |
|
9 | 9 | * still be able to read after scrolling away (a hook that failed, an MCP |
10 | 10 | * server asking for authorization or refusing to connect); |
11 | 11 | * - a **flash** is for confirmation of something they just caused, true only |
12 | | - * for a moment (a hook that ran, a server that came up, a grant recorded); |
| 12 | + * for a moment (a hook that ran, a server that came up, a grant recorded, |
| 13 | + * a compaction that folded turns away); |
13 | 14 | * - **null** is for inventory and intermediate states (`hooks.loaded`, a |
14 | 15 | * server that is merely `connecting`) — the /hooks and /mcp panels own that. |
15 | 16 | * |
@@ -108,6 +109,19 @@ export function grantNotice(approval: Approval): RuntimeNotice { |
108 | 109 | }; |
109 | 110 | } |
110 | 111 |
|
| 112 | +export interface CompactionFoldInfo { |
| 113 | + readonly turnsBefore: number; |
| 114 | + readonly turnsAfter: number; |
| 115 | +} |
| 116 | + |
| 117 | +/** Confirmation that context compaction actually folded turns away. */ |
| 118 | +export function compactionNotice(info: CompactionFoldInfo): RuntimeNotice { |
| 119 | + return { |
| 120 | + kind: "flash", |
| 121 | + text: `context compacted · ${info.turnsBefore} → ${info.turnsAfter} turns`, |
| 122 | + }; |
| 123 | +} |
| 124 | + |
111 | 125 | // --------------------------------------------------------------------------- |
112 | 126 | // Emitter payload validation |
113 | 127 | // --------------------------------------------------------------------------- |
@@ -168,6 +182,17 @@ export function grantApproval(raw: unknown): Approval | null { |
168 | 182 | return parsed.approval as Approval; |
169 | 183 | } |
170 | 184 |
|
| 185 | +const compactionPayload = type({ |
| 186 | + turnsBefore: "number", |
| 187 | + turnsAfter: "number", |
| 188 | +}); |
| 189 | + |
| 190 | +export function compactionFoldInfo(raw: unknown): CompactionFoldInfo | null { |
| 191 | + const parsed = compactionPayload(raw); |
| 192 | + if (parsed instanceof type.errors) return null; |
| 193 | + return parsed; |
| 194 | +} |
| 195 | + |
171 | 196 | export interface SubAgentProgress { |
172 | 197 | readonly description: string; |
173 | 198 | readonly toolName: string; |
|
0 commit comments