fix(tui): preserve high-water mark in sidebar, add copy_cost_from helper
Sidebar cost total now uses displayed_session_cost_for_currency so the high-water mark protects against cost reversal during API reconciliation (#244). The session+agents breakdown is only shown when it matches the displayed total; otherwise a single total line is rendered. Add SessionMetadata::copy_cost_from to eliminate the last remaining manual four-field cost copy (fork-session path). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -2797,10 +2797,7 @@ fn fork_session(session_id: Option<String>, last: bool, workspace: &Path) -> Res
|
||||
saved.metadata.total_tokens,
|
||||
system_prompt.as_ref(),
|
||||
);
|
||||
forked.metadata.session_cost_usd = saved.metadata.session_cost_usd;
|
||||
forked.metadata.session_cost_cny = saved.metadata.session_cost_cny;
|
||||
forked.metadata.subagent_cost_usd = saved.metadata.subagent_cost_usd;
|
||||
forked.metadata.subagent_cost_cny = saved.metadata.subagent_cost_cny;
|
||||
forked.metadata.copy_cost_from(&saved.metadata);
|
||||
manager.save_session(&forked)?;
|
||||
|
||||
let source_title = saved.metadata.title.trim();
|
||||
|
||||
@@ -110,6 +110,16 @@ pub struct SessionMetadata {
|
||||
pub subagent_cost_cny: f64,
|
||||
}
|
||||
|
||||
impl SessionMetadata {
|
||||
/// Copy cost fields from another metadata (used when forking a session).
|
||||
pub fn copy_cost_from(&mut self, other: &SessionMetadata) {
|
||||
self.session_cost_usd = other.session_cost_usd;
|
||||
self.session_cost_cny = other.session_cost_cny;
|
||||
self.subagent_cost_usd = other.subagent_cost_usd;
|
||||
self.subagent_cost_cny = other.subagent_cost_cny;
|
||||
}
|
||||
}
|
||||
|
||||
/// A saved session containing full conversation history
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SavedSession {
|
||||
|
||||
@@ -671,16 +671,25 @@ fn render_context_panel(f: &mut Frame, area: Rect, app: &App) {
|
||||
)));
|
||||
|
||||
// ── Session cost ─────────────────────────────────────────────
|
||||
let displayed_total = app.displayed_session_cost_for_currency(app.cost_currency);
|
||||
let session_cost = app.session_cost_for_currency(app.cost_currency);
|
||||
let agent_cost = app.subagent_cost_for_currency(app.cost_currency);
|
||||
let total_cost = session_cost + agent_cost;
|
||||
lines.push(Line::from(Span::styled(
|
||||
let real_total = session_cost + agent_cost;
|
||||
// Only show the additive breakdown when it matches the displayed
|
||||
// total; when the high-water mark is in effect (post-reconciliation),
|
||||
// the breakdown would not sum to the displayed value (#244).
|
||||
let cost_line = if (displayed_total - real_total).abs() < 1e-9 {
|
||||
format!(
|
||||
"cost: {} (session {} + agents {})",
|
||||
app.format_cost_amount(total_cost),
|
||||
app.format_cost_amount(displayed_total),
|
||||
app.format_cost_amount(session_cost),
|
||||
app.format_cost_amount(agent_cost)
|
||||
),
|
||||
)
|
||||
} else {
|
||||
format!("cost: {}", app.format_cost_amount(displayed_total))
|
||||
};
|
||||
lines.push(Line::from(Span::styled(
|
||||
cost_line,
|
||||
Style::default().fg(palette::TEXT_MUTED),
|
||||
)));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user