fix(tui): refresh the context bar when auto-compaction starts
AutoCompactStarted carries the count the trigger fired on, but only AutoCompactCompleted refreshed the context bar, so the "N% full" banner sat next to a stale pre-turn number until the next stream update. Both lifecycle updates now refresh the bar, on the root view and on subagent views. Ported from upstream 1.0.12 (grok-build acp_handler/session_notification.rs). Claude-Session: https://claude.ai/code/session_01RUqV8HVGXcAETyYbZ2tPQ4
This commit is contained in:
1 parent
584d0fb77e
commit
a7b8438881
2 files changed
+51
-10
No files matched your search
@@ -45,6 +45,14 @@ pub(super) fn refresh_context_used(view: &mut AgentView, used: u64) {
|
||||
let total = view.session.models.get_context_window().unwrap_or(0);
|
||||
view.apply_context_used(used, total);
|
||||
}
|
||||
/// The count a compaction lifecycle update carries for the context bar: the banner's "N% full" must not sit next to a stale pre-turn number.
|
||||
pub(super) fn compaction_context_refresh(update: &XaiSessionUpdate) -> Option<u64> {
|
||||
match update {
|
||||
XaiSessionUpdate::AutoCompactStarted { tokens_used, .. } => Some(*tokens_used),
|
||||
XaiSessionUpdate::AutoCompactCompleted { tokens_after, .. } => Some(*tokens_after),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
/// Refresh the bar and record `used` as the confirmed count for a pending
|
||||
/// compaction message; call only from the `meta.totalTokens` path.
|
||||
pub(super) fn confirm_context_used(view: &mut AgentView, used: u64) {
|
||||
@@ -197,8 +205,10 @@ pub(super) fn handle_session_notification(notif: &acp::ExtNotification, app: &mu
|
||||
&mut agent.scrollback,
|
||||
is_api_key_auth,
|
||||
);
|
||||
if let XaiSessionUpdate::AutoCompactCompleted { tokens_after, .. } = update {
|
||||
refresh_context_used(agent, *tokens_after);
|
||||
if let Some(used) = compaction_context_refresh(update) {
|
||||
refresh_context_used(agent, used);
|
||||
}
|
||||
if let XaiSessionUpdate::AutoCompactCompleted { .. } = update {
|
||||
agent.todo.update_todos(Vec::new());
|
||||
}
|
||||
changed
|
||||
@@ -1071,10 +1081,7 @@ pub(super) fn handle_child_session_notification(
|
||||
| XaiSessionUpdate::AutoCompactFailed { .. }
|
||||
| XaiSessionUpdate::AutoCompactCancelled { .. }
|
||||
| XaiSessionUpdate::RetryState(_) => {
|
||||
let compact_tokens = match &update {
|
||||
XaiSessionUpdate::AutoCompactCompleted { tokens_after, .. } => Some(*tokens_after),
|
||||
_ => None,
|
||||
};
|
||||
let compact_tokens = compaction_context_refresh(&update);
|
||||
let mut changed = false;
|
||||
if let Some(child_view) = agent.subagent_views.get_mut(child_sid) {
|
||||
changed = apply_session_event(
|
||||
|
||||
@@ -576,9 +576,8 @@
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn child_compact_started_does_not_reset_context_used() {
|
||||
// Sibling variants in the same outer arm must not touch the numerator;
|
||||
// guards against accidental widening of the AutoCompactCompleted gate.
|
||||
fn child_compact_started_refreshes_context_used() {
|
||||
// AutoCompactStarted carries the count the trigger fired on; the child bar must show it.
|
||||
let mut agent = make_agent(Some("root-sess"));
|
||||
let child_sid = "child-sess-3";
|
||||
agent
|
||||
@@ -603,7 +602,17 @@
|
||||
let child_view = agent.subagent_views.get(child_sid).unwrap();
|
||||
assert_eq!(
|
||||
child_view.context_state.as_ref().map(|c| c.used),
|
||||
Some(90_000)
|
||||
Some(95_000)
|
||||
);
|
||||
// A sibling variant without a count leaves the numerator alone.
|
||||
let cancelled = XaiSessionUpdate::AutoCompactCancelled {
|
||||
reason: "user".into(),
|
||||
};
|
||||
let _ = handle_child_session_notification(cancelled, child_sid, &mut agent, false);
|
||||
let child_view = agent.subagent_views.get(child_sid).unwrap();
|
||||
assert_eq!(
|
||||
child_view.context_state.as_ref().map(|c| c.used),
|
||||
Some(95_000)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -693,5 +702,30 @@
|
||||
!session.model_incompatible,
|
||||
"non-encrypted_content error types must not set model_incompatible"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/// The banner's count must also refresh the context bar.
|
||||
#[test]
|
||||
fn auto_compact_started_refreshes_the_context_bar() {
|
||||
let mut app = make_app_with_agent("sess-1");
|
||||
let id = AgentId(0);
|
||||
app.agents.get_mut(&id).unwrap().apply_context_used(15_000, 262_144);
|
||||
let payload = SessionNotification {
|
||||
session_id: acp::SessionId::new("sess-1"),
|
||||
update: XaiSessionUpdate::AutoCompactStarted {
|
||||
tokens_used: 90_000,
|
||||
context_window: 262_144,
|
||||
percentage: 34,
|
||||
reason: "threshold".into(),
|
||||
},
|
||||
meta: None,
|
||||
};
|
||||
let notif = acp::ExtNotification::new(
|
||||
"kigi/session/update",
|
||||
std::sync::Arc::from(serde_json::value::to_raw_value(&payload).unwrap()),
|
||||
);
|
||||
let _ = handle_ext_notification(¬if, &mut app);
|
||||
let bar = app.agents[&id].context_state.as_ref().map(|c| (c.used, c.total));
|
||||
assert_eq!(bar, Some((90_000, 262_144)));
|
||||
}
|
||||
Reference in new issue
Block a user