Watch
0
0
Fork
You've already forked hyperhive
0

turn: clear the resolved model on a turn that parsed nothing

This commit is contained in:
damocles 2026-10-21 21:19:36 +02:00 • committed by mara
commit c3ff0815ff

View file

@ -790,8 +790,9 @@ impl Sink for BusSink<'_> {
/// Apply a completed turn's parsed [`hive_claude::Telemetry`] to the bus:
/// per-inference context usage + cumulative cost, the resolved model id, and
/// the API-reported context window (the authoritative window for the auto-reset
/// watermark). Skips a degenerate turn that parsed nothing so it doesn't reset
/// the badges to zero.
/// watermark). A degenerate turn that parsed nothing leaves the usage badges
/// alone (it doesn't reset them to zero) but still replaces the resolved model,
/// so it is never credited to the previous turn's.
fn apply_telemetry(bus: &Bus, telemetry: &hive_claude::Telemetry) {
// On a degenerate turn that emitted a `result` but no `assistant` event,
// the per-inference `context` stays zero while `cost` (cumulative) is not.
@ -803,11 +804,13 @@ fn apply_telemetry(bus: &Bus, telemetry: &hive_claude::Telemetry) {
} else {
telemetry.context
};
// Recorded before the skip so a degenerate turn clears the previous
// turn's id instead of being credited to it.
bus.set_resolved_model(telemetry.model.clone());
if ctx.context_tokens() == 0 {
return;
}
bus.record_turn_usage(ctx, telemetry.cost);
bus.set_resolved_model(telemetry.model.clone());
if let Some(window) = telemetry.context_window {
bus.set_api_context_window(window);
}
@ -853,12 +856,22 @@ fn archive_session(bus: &Bus, session: &AgentSession) {
#[cfg(test)]
mod tests {
use super::{
PermissionAsk, TurnError, acp_permits, nonzero_or, parse_u64, report_compact,
runtime_error_to_turn, with_turn_end_compact,
PermissionAsk, TurnError, acp_permits, apply_telemetry, nonzero_or, parse_u64,
report_compact, runtime_error_to_turn, with_turn_end_compact,
};
use crate::events::{Bus, LiveEvent};
use hive_runtime::{AcpError, Error};
#[test]
fn a_turn_that_parsed_nothing_does_not_keep_the_previous_resolved_model() {
let bus = Bus::new();
bus.set_resolved_model(Some("claude-opus-4-8".to_owned()));
apply_telemetry(&bus, &hive_claude::Telemetry::default());
assert_eq!(bus.last_resolved_model(), None);
}
#[test]
fn an_absent_or_blank_value_is_not_a_number() {
assert_eq!(parse_u64(None), None);