Skip to content

feat(extension): context usage donut and compaction#4283

Open
iscekic wants to merge 18 commits into
mainfrom
extension-context-compaction
Open

feat(extension): context usage donut and compaction#4283
iscekic wants to merge 18 commits into
mainfrom
extension-context-compaction

Conversation

@iscekic

@iscekic iscekic commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What

Adds context-usage visibility and context compaction to the browser-agent side panel, plus two small conversation-UX fixes.

Features

  • Context donut — a small SVG ring in the footer showing how full the model's context window is, driven by real gateway usage.prompt_tokens / model context_length. Hover/click opens a popover with the exact token counts and a Compact now button. Green < 70%, amber 70–90%, red ≥ 90%; grey when the model reports no context length.
  • Automatic compaction — after a turn reaches ≥ 85% of the context window, older events are summarized (one gateway call) into a single 🗜️ Compacted earlier context assistant message, keeping the last 2 exchanges verbatim.
  • Manual compaction — the Compact now button does the same on demand.

Small fixes

  • Per-conversation drafts — the message draft is kept per conversation; switching tabs preserves each conversation's in-progress text.
  • Remove close confirmation — closing a conversation tab no longer prompts; it closes immediately (the history delete confirmation is unchanged).

How it works

  • The streaming client sends stream_options: { include_usage: true } and parses the trailing usage chunk into KiloGatewayChatCompletion.usage; context_length is parsed from /models.
  • Usage flows up through an onUsage callback (runLlmTurn → turn runners → chat panel).
  • Per-conversation context usage and drafts are in-memory maps keyed by conversation id (reset on reload by design). All per-conversation state (usage, drafts, running/compacting ids) is keyed by conversation id and gated by the existing isCurrentRun() token, so parallel conversations don't interfere.
  • Compaction summarizes via the gateway with tools: []; splitEventsForCompaction always cuts on a user-message boundary so no tool-call/tool-result pair is orphaned.

Incidental fix: side-panel message-path trust check

While adding e2e coverage I found the background's isTrustedExtensionSender gated senders on sender.tab === undefined. That holds for the real side panel, but no message-flow e2e test could ever pass because the harness loads the side panel as a tab (so sender.tab is defined) and the background silently never responded — every message-sending test failed at "No tab selected". Changed the gate to trust the sender's extension origin (chrome-extension://<id>) instead: a content script shares the extension id but reports the host page's origin, so this is a stronger boundary and also lets the e2e suite drive the real message path. This unblocked the entire pre-existing message-flow e2e suite (safe mode, eval, run abort, etc.).

Testing

  • Unit (Vitest): 106 passing — usage parsing, context_length parsing, usage forwarding, context-usage helpers, splitEventsForCompaction/transcript rendering.
  • E2E (Playwright, Chrome): full suite green locally (49 tests) after the trust-check fix, including new coverage for the donut reflecting usage, auto-compaction at threshold, manual compaction, per-conversation drafts, and close-without-confirmation. Auto-compaction assertions read persisted storage to avoid the virtualized list's render timing.
    • Note: CI does not currently run the extension e2e suite (no workflow invokes e2e:chrome/e2e:firefox; the extension's verify is typecheck+lint+format+unit). These were run locally.
    • Firefox Selenium e2e has a separate pre-existing tab-detection limitation in headless and was not fully run; the close-without-confirm change is mirrored there.
  • typecheck, lint (0 errors), and format are clean.

iscekic added 11 commits June 26, 2026 14:56
- kilo-api-fixture: add contextLength to MockGatewayModel, include
  context_length in mocked model item when set; guard tool_choice/
  system_environment assertions for summarization calls (tools: [])
- context-usage.test.ts: donut shows "850 / 1,000 tokens (85%)" after
  reply with usage chunk; auto-compaction fires at ≥85% threshold;
  manual "Compact now" compacts seeded conversation
- conversation-drafts.test.ts: draft A / draft B persist across tab
  switches
- conversation-tabs.test.ts: remove dialog expectation on tab close;
  assert no dialog fires; remove dialog handlers from history-delete
  and history-reuse tests that used the old close-confirm flow
- firefox-selenium-e2e.ts: close-without-confirm — no alert expected
@iscekic iscekic self-assigned this Jun 26, 2026
Comment thread apps/extension/src/shared/agent-context-compaction.ts Outdated
Comment thread apps/extension/tests/e2e/context-usage.test.ts Outdated
@kilo-code-bot

kilo-code-bot Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
.github/workflows/extension-ci.yml 6 Path filters still omit root package.json, so a PR that only changes the pinned pnpm version or install hooks can skip the extension build/e2e jobs those changes affect.
apps/extension/src/shared/agent-context-compaction.ts 98 Compaction now serializes raw viewport screenshot dataUrl payloads into the transcript, spending about 2000 characters of the summary prompt on base64 instead of useful page state.
Files Reviewed (4 files)
  • .github/workflows/extension-ci.yml - 1 issue
  • apps/extension/src/shared/agent-context-compaction.test.ts - 0 issues
  • apps/extension/src/shared/agent-context-compaction.ts - 1 issue
  • apps/extension/tests/e2e/context-usage.test.ts - 0 issues

Fix these issues in Kilo Cloud

Previous Review Summaries (5 snapshots, latest commit 68a0c95)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 68a0c95)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
apps/extension/src/shared/agent-context-compaction.ts 37 Manual keep-0 compaction now summarizes the latest exchange too, but the transcript still drops tool arguments and results, so page state from the most recent turn can disappear after compaction.
Files Reviewed (3 files)
  • apps/extension/src/shared/agent-context-compaction.ts - 1 issue
  • apps/extension/src/shared/agent-context-compaction.test.ts - 0 issues
  • apps/extension/tests/e2e/local-backend-live.test.ts - 0 issues

Fix these issues in Kilo Cloud

Previous review (commit f1ad780)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
apps/extension/src/shared/agent-context-compaction.ts 65 Compaction transcripts still drop tool arguments and results, so the newly widened manual compaction path can summarize away page data the next turn needs.
Files Reviewed (4 files)
  • apps/extension/entrypoints/sidepanel/agent-chat-panel.tsx - 0 issues
  • apps/extension/src/shared/agent-context-compaction.ts - 1 issue
  • apps/extension/src/shared/agent-context-compaction.test.ts - 0 issues
  • apps/extension/tests/e2e/local-backend-live.test.ts - 0 issues

Fix these issues in Kilo Cloud

Previous review (commit 6233aac)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
.github/workflows/extension-ci.yml 6 Path filters omit root inputs like .nvmrc and package.json, so extension CI skips PRs that change the Node/tooling versions these jobs actually run with.
Files Reviewed (1 files)
  • .github/workflows/extension-ci.yml - 1 issue

Fix these issues in Kilo Cloud

Previous review (commit 15b017c)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • apps/extension/entrypoints/background.ts
  • apps/extension/entrypoints/sidepanel/app.tsx
  • apps/extension/tests/e2e/context-usage.test.ts

Previous review (commit da2a010)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
apps/extension/src/shared/agent-context-compaction.ts 49 Compaction transcript drops tool arguments and outputs, so the summary can lose the page data needed to continue the task.
apps/extension/tests/e2e/context-usage.test.ts 145 Manual compaction test never provides usage, leaving Compact now disabled and causing the new E2E path to fail.
Files Reviewed (21 files)
  • apps/extension/entrypoints/sidepanel/agent-chat-panel.tsx - 0 issues
  • apps/extension/entrypoints/sidepanel/agent-footer-controls.tsx - 0 issues
  • apps/extension/entrypoints/sidepanel/agent-llm-turn-runner.ts - 0 issues
  • apps/extension/entrypoints/sidepanel/agent-safe-llm-turn-runner.ts - 0 issues
  • apps/extension/entrypoints/sidepanel/context-donut.tsx - 0 issues
  • apps/extension/src/shared/agent-context-compaction.ts - 1 issue
  • apps/extension/src/shared/agent-context-compaction.test.ts - 0 issues
  • apps/extension/src/shared/agent-llm-turn-runner-core.ts - 0 issues
  • apps/extension/src/shared/agent-llm-turn-runner-core.test.ts - 0 issues
  • apps/extension/src/shared/context-usage.ts - 0 issues
  • apps/extension/src/shared/context-usage.test.ts - 0 issues
  • apps/extension/src/shared/kilo-api-client.ts - 0 issues
  • apps/extension/src/shared/kilo-api-client.test.ts - 0 issues
  • apps/extension/src/shared/kilo-gateway-chat-client.ts - 0 issues
  • apps/extension/src/shared/kilo-gateway-chat-stream-client.ts - 0 issues
  • apps/extension/src/shared/kilo-gateway-chat-stream-client.test.ts - 0 issues
  • apps/extension/tests/e2e/context-usage.test.ts - 1 issue
  • apps/extension/tests/e2e/conversation-drafts.test.ts - 0 issues
  • apps/extension/tests/e2e/conversation-tabs.test.ts - 0 issues
  • apps/extension/tests/e2e/firefox-selenium-e2e.ts - 0 issues
  • apps/extension/tests/e2e/kilo-api-fixture.ts - 0 issues

Fix these issues in Kilo Cloud


Reviewed by gpt-5.4-20260305 · Input: 86K · Output: 12.7K · Cached: 660.2K

Review guidance: REVIEW.md from base branch main

iscekic added 4 commits June 26, 2026 16:35
The eval/debugger message path gated senders on tab === undefined to tell the
side panel apart from content scripts. When the side panel runs as a tab (as
the e2e harness loads it) sender.tab is defined, so the background never
answered and tab listing/tools failed. Gate on the sender's extension origin
instead: a content script shares the extension id but reports the host page's
origin, while any extension page reports chrome-extension://<id>. This is a
stronger trust signal and lets the e2e suite drive the real message path.
Assert auto-compaction against persisted storage instead of the virtualized
conversation list (rows unmount while events are rewritten), and give the
manual-compaction turn a sub-threshold usage chunk so the donut enables
Compact now.
Fixes a pre-existing capitalized-comments lint error on the wrapped comment.
Adds a folder-gated workflow (apps/extension/**) covering the gaps the global
CI misses for the extension: the extension's own type-aware lint, the Firefox
MV3 build, and the Chrome Playwright e2e suite (which also builds Chrome).
Typecheck/format/unit also run here via the package's verify script for a
self-contained signal. Firefox Selenium e2e is excluded (unreliable headless).
Comment thread .github/workflows/extension-ci.yml
iscekic added 3 commits June 26, 2026 19:03
The "Compact now" button was enabled whenever usage was non-zero, but
manual compaction kept the last KEEP_RECENT_EXCHANGES (2) exchanges like
auto-compaction, so a conversation with <=2 user messages had nothing to
summarize and the click was a silent no-op. With a 1M-context frontier
model auto-compaction never fires, so this was the normal manual path.

Manual compaction now keeps only the latest exchange
(KEEP_RECENT_EXCHANGES_MANUAL=1), and the button gates on whether there is
summarizable history rather than on measured usage — so it is never
enabled-but-inert and also works after a reload, when in-memory usage has
reset. Auto-compaction is unchanged.

Verified with a live local-backend e2e (fl@fl.fl, kilo-auto/frontier):
a two-exchange conversation now compacts on click.
Drop the manual keep-one-exchange threshold and its disabled single-exchange
edge case. Manual "Compact now" now keeps no recent exchange (keep 0): it
summarizes the entire conversation and is enabled whenever there is anything
to summarize (at least one user message). Auto-compaction still keeps
KEEP_RECENT_EXCHANGES for continuity near the context limit.
- Compaction transcript now includes tool inputs (eval code, query/element)
  and result payloads (snapshot text, eval return, errors), each truncated to
  2000 chars, so the summary keeps facts that previously lived only in tool
  results.
- extension-ci.yml also runs on .nvmrc and pnpm-workspace.yaml changes, which
  alter the runtime and workspace/catalog graph the jobs build against.
- Clarify the manual-compaction e2e comment: the button is enabled by
  summarizable history, not by the donut's usage value.
// The result payload (snapshot text, eval return, element details) is often the only record.
return event.value === undefined
? 'Tool result (ok)'
: `Tool result (ok): ${truncateToolText(stringifyToolValue(event.value))}`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Screenshot payloads now consume the compaction transcript

get_viewport_screenshot stores a raw dataUrl in event.value, but this path serializes every successful tool result directly instead of collapsing screenshots to the same note/mediaType placeholder used by buildGatewayMessagesFromEvents(). After any screenshot turn, compaction will spend about 2000 characters of the summarization prompt on PNG base64 rather than the page facts the next turn needs.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant