feat: goose2 context window usage in chat input#8613
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2daa5f8de9
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e8c5a5daf7
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
e8c5a5d to
76f16f2
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 76f16f2a27
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 98ef122fc1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: af15de93bd
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5c2366caf2
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| contextTokens={tokenState.accumulatedTotal} | ||
| contextLimit={tokenState.contextLimit} |
There was a problem hiding this comment.
Refresh context limit when the model changes
This new UI binds context usage directly to tokenState.contextLimit, but that value is only updated from usage_update notifications; changing models via acpSetModel does not immediately refresh token limits. As a result, after switching to a model with a very different context window, the ring/popover can keep showing the old denominator until the next prompt/load, making the displayed percentage and compacting signal inaccurate. Trigger a limit refresh on model change (or emit/consume an update that carries the new context limit).
Useful? React with 👍 / 👎.
81c05c8 to
01eede6
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2f10a30043
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| let mut response = PromptResponse::new(stop_reason); | ||
| if let Some(usage) = build_prompt_usage(&session) { | ||
| response = response.usage(usage); |
There was a problem hiding this comment.
Omit usage from cancelled prompt responses
When was_cancelled is true, this path still attaches build_prompt_usage(&session) to the PromptResponse. If cancellation happens before the canceled turn writes fresh metrics, session.total_tokens/input_tokens/output_tokens can still reflect the previous completed turn, so ACP clients that sum per-turn response.usage will overcount costs/tokens on each cancel. Skip setting response.usage for cancelled turns (or derive usage from the canceled turn itself) to avoid reporting stale usage.
Useful? React with 👍 / 👎.
Signed-off-by: Taylor Ho <taylorkmho@gmail.com> (cherry picked from commit 35d7813)
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Render the base track with the neutral border color so it stays visible behind the foreground arc on dark surfaces. Remove the old inner fill and exaggerated scaling so the ring maps directly to actual usage. Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Wire the context usage popover to a shared Compact now button and show a dedicated compacting state while the command runs. Refresh the transcript from ACP session replay after /compact so the UI reflects the compacted history, and cover the new behavior with chat hook and popover tests. Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Filter manual compact command messages out of replayed history so /compact never shows up in the visible transcript after a compaction. Cover the doubled /compact replay case with a hook regression test to keep the compact popover action internal to the chat UI. Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Use the shared secondary button treatment for the compact action and remove the secondary variant's default shadow so the popover button sits flat with the rest of the control surface. Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Use the shared progress indicator in the context popover and compress the usage metrics into a cleaner, left-aligned layout. Trim extra spacing around the compact action and shorten the button label in the localized chat copy. Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Document that the temporary /compact trigger should be removed once goose2 adds first-class slash command support. Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2f10a30 to
142865f
Compare
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 17888f63a8
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| return () => { | ||
| prepared.delete(sessionId); | ||
| if (previousEntry) { | ||
| prepared.set(sessionId, previousEntry); |
There was a problem hiding this comment.
Guard rollback so it doesn't undo newer registrations
Make the rollback returned by registerSession conditional on the current mapping still matching the registration being rolled back. Right now it always runs prepared.delete(sessionId) and restores the previous entry, so if two acpLoadSession calls overlap for the same local session, a later failure from the older call can clobber the mapping established by the newer successful call; subsequent sends then fail with “Session not prepared” because getGooseSessionId points to stale/cleared state.
Useful? React with 👍 / 👎.
baxen
left a comment
There was a problem hiding this comment.
LGTM! tested this and works on historical and new sessions
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Category: improvement
User Impact: Goose2 users can now see context window usage in the chat input and compact a conversation directly from that popover.
Problem: goose2 already had the backend data needed for context tracking, but the UI still surfaced it unreliably for draft chats because early ACP usage updates could arrive before the local session mapping existed. Even when the indicator showed up, compacting context still depended on typing a hidden slash command, and
just devcould quietly boot a differentgoosebinary than the one in this worktree.Solution: Emit and return usage from ACP session lifecycle events, buffer early usage updates until the chat session is registered locally, and pass the selected provider into draft session creation so the context limit resolves immediately. On top of that, turn the ring into a compact popover with a slim progress bar, tighter metrics, and a first-class compact action, refresh replayed history after compaction so
/compactstays invisible, and force goose2 dev to launch against this branch's localgoosebinary.File changes
crates/goose-acp/src/server.rs
Emits
usage_updatenotifications when sessions are created, loaded, and prompted, and includes per-turn prompt usage in the ACP response. This gives goose2 a stable source of context-window state instead of waiting for later replay events.ui/goose2/justfile
Builds the local
gooseCLI during setup and makesjust devprefer the worktree's debug or release binary. That keeps the frontend pointed at the matching backend code while testing the context indicator locally.ui/goose2/src/features/chat/hooks/tests/useChat.test.ts
Adds hook coverage for compacting a prepared conversation, reloading replayed history, hiding manual
/compactechoes, and surfacing the right error when a session has not been prepared yet.ui/goose2/src/features/chat/hooks/useChat.ts
Adds
compactConversation()to send/compact, reload the ACP session, replace the visible transcript with replayed history, and strip the internal compact command back out of the UI. It also introduces the dedicatedcompactingchat state and the user-facing error path for unprepared sessions.ui/goose2/src/features/chat/ui/ChatInput.tsx
Threads the new compact-context props through the shared chat input so both the home and chat compositions can render the updated toolbar contract.
ui/goose2/src/features/chat/ui/ChatInputToolbar.tsx
Turns the context ring into a popover that now uses a slim progress bar, compact token totals, and a concise percentage readout alongside the shared
Compactaction. The control still matches the neighboring toolbar popovers, but the latest layout reads faster at a glance.ui/goose2/src/features/chat/ui/ChatView.tsx
Wires the compact action from
useChat()into the toolbar, only enables it when the session is actually compactable, and passes the compacting state down so the popover can reflect in-flight work.ui/goose2/src/features/chat/ui/ContextRing.tsx
Simplifies the ring styling so the neutral track stays visible and the foreground arc maps directly to real usage. The result is more legible on light and dark surfaces and easier to scan at a glance.
ui/goose2/src/features/chat/ui/LoadingGoose.tsx
Maps the new
compactingchat state to dedicated loading copy instead of reusing the generic responding label.ui/goose2/src/features/chat/ui/tests/ChatInput.test.tsx
Covers the refined popover metrics layout, the shortened
Compactaction label, and the hidden state when no context limit is available.ui/goose2/src/features/chat/ui/tests/LoadingGoose.test.tsx
Adds regression coverage for the new compacting loading message so that state keeps its own visible copy.
ui/goose2/src/shared/api/acp.ts
Registers the local-to-goose session mapping before loading ACP history and rolls that mapping back if the load fails. That keeps replay refreshes from leaving bad session state behind.
ui/goose2/src/shared/api/acpApi.ts
Passes the chosen provider into
newSession()metadata so draft sessions can resolve the right model context limit as soon as they are created.ui/goose2/src/shared/api/acpNotificationHandler.test.ts
Exercises the race where a
usage_updatearrives before the local draft session is registered, and locks in the rule that only usage updates are buffered.ui/goose2/src/shared/api/acpNotificationHandler.ts
Buffers early
usage_updatenotifications until goose2 knows which local chat session they belong to, then replays them through the correct live or replay path. That removes the draft-session race that made the ring appear inconsistent.ui/goose2/src/shared/api/acpSessionTracker.ts
Adds session-registration listeners, notifies them whenever a goose session is bound locally, and exposes unregister cleanup. This gives the notification layer a deterministic point to flush buffered usage updates.
ui/goose2/src/shared/i18n/locales/en/chat.json
Adds English copy for the context popover and the compacting state, then refines the CTA copy from
Compact nowtoCompactfor the tighter layout.ui/goose2/src/shared/i18n/locales/es/chat.json
Adds the matching Spanish strings for the same popover and compacting copy, including the shorter
CompactarCTA.ui/goose2/src/shared/ui/button.tsx
Removes the default shadow from the shared secondary button so the compact action sits flush with the rest of the popover surface.
ui/goose2/src/test/mocks/goose-sdk.ts
Drops an unused mock constructor to clear the lint noise introduced while touching the chat tests.
Reproduction Steps
ui/goose2, runjust setupand thenjust dev.Compactaction with sizing that still matches the project and attachment popovers.Compactand verify the loading state switches toCompacting conversation..., then the transcript refreshes without showing a visible/compactuser message.just devreportsUsing local goose binary:from this worktree.Screenshots
Context usage popover with the refined metrics layout:
Attachment popover spacing reference:
Project popover spacing reference: