feat: restore TUI provider cost footer baseline (APP-4952) - #14220
Conversation
Review feedback implemented + local E2E verification (APP-4952)All findings from a full cross-repo review have been implemented and validated locally end-to-end (local warp-server built from warpdotdev/warp-server#13244 + TUI built from this branch, deterministic llm-mock with non-zero provider cost). Changes in response to review (commits 28900ea, 6a910bf):
Validation: E2E testing plan & results (local, llm-mock):
Artifacts: asciinema recordings + footer captures at each checkpoint (terminal-text capture; no screen video available in the test environment). Deploy order: warpdotdev/warp-server#13244 must deploy before this ships — the GraphQL fragment addition here hard-fails against servers without the new schema field (this also affects devs on older local servers). Related: warpdotdev/warp-server#13244, warpdotdev/warp-proto-apis#349 Co-Authored-By: Oz oz-agent@warp.dev |
Update: descoped to GraphQL-only + re-verified E2E (local + cloud video)Scope change: the StreamFinished cumulative-cost field is deferred to upcoming stream-level cost work — warpdotdev/warp-proto-apis#349 is closed (branch retained as the starting point, including the FloatValue presence fix for Rust codegen). This PR pair now ships the restore fix GraphQL-only:
E2E round 3 (local, llm-mock): all pass on the reworked heads — $0.22 accumulated over 3 turns; same-profile restore shows $0.22 before prompting; follow-up → $0.30 (baseline + one increment, no double-count); fresh-profile (cross-device) restore shows $0.30 seeded purely from server data; GraphQL returned E2E round 4 (cloud agent, computer use, video-recorded): independently reproduced from scratch in an isolated cloud environment (own Postgres/Redis/Temporal + fake-GCS for transcripts), running the TUI in a visible terminal on video with per-checkpoint screenshots. All 6 checkpoints pass: non-zero first-turn cost, monotonic accumulation (4.5→13.5¢), resume token, same-profile restore baseline $0.14 pre-prompt, follow-up $0.18 with no double-count, and fresh-profile restore $0.18 pre-prompt matching GraphQL ( Deploy order still applies: server before client. Co-Authored-By: Oz oz-agent@warp.dev |
|
/oz-review |
|
I'm re-reviewing this pull request in response to a review request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
Define the client-only restore baseline, cloud fallback, and validation contract for APP-4952.\n\nCo-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
…regression test
- Add the spec-mandated regression test for the ticket's exact failing
sequence: a restored 3.2-cent server baseline plus a 1.2-cent follow-up
must display 4.4 cents, covering both restore constructors.
- Derive has_usage from the usage metadata's contents instead of its mere
presence. Local persistence always writes a metadata blob, so restored
zero-usage conversations previously surfaced a misleading footer entry
("Cost unavailable" / 0.0 credits) that used to be hidden.
- Make set_server_metadata consistent: usage evidence comes from the
snapshot's contents, and an absent provider-cost field never erases a
known baseline.
- Add view-level TUI tests: the footer usage entry stays hidden until a
conversation reports usage, and unknown historical cost renders
'Cost unavailable' (never $0.00) even with zero credits.
Co-Authored-By: Oz <oz-agent@warp.dev>
Bump warp_multi_agent_api to the proto rev that models StreamFinished's total_provider_cost_in_cents as google.protobuf.FloatValue, giving the Rust binding explicit presence (Option<f32>) so an absent field is distinguishable from a known zero. - StreamFinished reconciliation: when a response reports the server's cumulative provider cost, that snapshot is authoritative for the turn. It replaces local accumulation (the snapshot already includes the response's per-request costs, so nothing is counted twice) and recovers a restored legacy conversation's unknown baseline. Without the field (older server), per-request costs accumulate onto a known baseline as before. - set_server_metadata ordering guard: asynchronous GraphQL metadata snapshots may only seed or advance the displayed total, never regress it or re-add costs the stream already counted. - Shared-session hosts now forward the cumulative provider cost in the synthetic StreamFinished events they replay to viewers. - Tests: snapshot-supersedes-local (never 5.6 cents), unknown-baseline recovery via stream snapshot, stale-GraphQL-snapshot no-regression, and absent-field fallback to local accumulation (existing regression test). Co-Authored-By: Oz <oz-agent@warp.dev>
The cumulative provider-cost stream contract is deferred to separate work. Keep APP-4952 focused on restoring the server-authoritative GraphQL baseline and accumulating the existing per-request live deltas. - Restore warp_multi_agent_api to the branch's pre-stream pin. - Remove StreamFinished cumulative-cost reconciliation and synthetic shared-session forwarding. - Remove the stream-snapshot tests while retaining the exact 3.2 + 1.2 restore regression, absent-field fallback, and stale GraphQL snapshot no-regression coverage. - Keep the monotonic GraphQL metadata guard so asynchronous snapshots may advance but never regress a locally accumulated total. - Align the checked-in APP-4952 spec with the GraphQL-only scope. Co-Authored-By: Oz <oz-agent@warp.dev>
There was a problem hiding this comment.
Overview
This PR carries server-authoritative provider cost through persistence/GraphQL restore paths and updates the TUI usage footer to distinguish unknown historical cost from a known cumulative cost.
Concerns
usage_metadata_indicates_usagestill treatsSome(0.0)provider cost as no usage. That hides a known zero-cost baseline instead of displaying$0.00, so restored/server snapshot cases can still conflate real zero with an absent historical baseline.- The provided PR context does not include an attached TUI transcript, screenshot, or snapshot for the restored known-baseline, baseline-plus-follow-up, or legacy
Cost unavailablestates; the description says those specific states could not be captured. Because those are the user-visible states changed by this PR, please attach TUI verification for them before merge.
Verdict
Found: 0 critical, 2 important, 0 suggestions
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
| || metadata | ||
| .total_provider_cost_in_cents | ||
| .is_some_and(|cost| cost != 0.0) |
There was a problem hiding this comment.
Some(0.0) is a known provider-cost baseline, but this treats it as no usage, so a restored/server snapshot with cumulative zero hides the footer instead of switching from unknown to known $0.00.
| || metadata | |
| .total_provider_cost_in_cents | |
| .is_some_and(|cost| cost != 0.0) | |
| || metadata.total_provider_cost_in_cents.is_some() |
Master moved selected_conversation_usage_totals into terminal_session_view/statusline.rs during the footer refactor; port the has_usage gate there, drop the duplicate in terminal_session_view.rs, and convert the zero-credits view test to the FooterSegments::ordered API. Co-Authored-By: Oz <oz-agent@warp.dev>
1fa96c0 to
5b79f4d
Compare
…mmit Co-Authored-By: Oz <oz-agent@warp.dev>
Some(0.0) is only recorded once a turn has completed accounting, so a restored or server snapshot with a cumulative zero must surface the footer as a truthful $0.00 instead of being hidden as though no usage occurred. None remains the only unknown/hidden state. Co-Authored-By: Oz <oz-agent@warp.dev>
|
/oz-review |
|
I'm re-reviewing this pull request in response to a review request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
There was a problem hiding this comment.
Overview
This PR threads the server-authoritative nullable provider-cost baseline through persistence, GraphQL usage metadata conversion, AIConversation restore/live usage state, and the headless TUI footer so restored conversations can distinguish known cumulative cost from unknown historical cost.
Concerns
- This is a user-facing headless TUI output change, but the PR does not attach acceptable TUI evidence for the target restored states. The body says the restored historical-dollar baseline, baseline-plus-follow-up, and legacy/null
Cost unavailablestates could not be captured, and the linked run is not an attached terminal transcript,render_to_lines/TuiBuffersnapshot diff, or./script/run-tuicapture demonstrating those states. Please attach TUI evidence showing the restored known baseline before a follow-up, baseline plus live delta after a follow-up, and the legacy/nullCost unavailablestate.
Verdict
Found: 0 critical, 1 important, 0 suggestions
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
Summary
Restores the TUI provider-cost footer from the server-authoritative nullable
total_provider_cost_in_centssnapshot. Restored conversations now retain a known historical baseline, while legacy/null payloads explicitly renderCost unavailableinstead of$0.00; follow-up request deltas only accumulate when a baseline is known.Implementation
Noneand distinguishing known zero.AIConversationrestore constructors and the cloud conversation conversion path from persisted/server usage metadata.Verification
cargo check -p warp --all-targetspassed on the XL runner.cargo check -p warp_tui --all-targets, debugwarp-tui-ossbuild, and releasewarp-tui-devbuild passed.$formatting, credits mode, mode toggle, andCost unavailable).cargo fmt --all -- --check,cargo clippy -p warp --all-targets --tests -- -D warnings, andcargo clippy -p warp_tui --all-targets --tests -- -D warningspassed../script/presubmitpassed formatting, inline-module, clippy, clang-format, and WGSL checks. Its workspace nextest phase remains red only on unrelated headless-environment integration assumptions (X11 recording foreground visibility, SSH password prompts, remote-server 501 fixtures, notebook/UI integration fixtures, and one TUI startup-state test); no APP-4952 regression failed.Live TUI verification
The release TUI launched cleanly in a real XTerm PTY with the staging channel shim and inherited API-key login. Captured truthful screenshots show
Conversations / No conversations foundwithCould not load cloud conversations. Showing local conversations only.and a fresh-session footer of2.8 credits; no$0.00was rendered. The requested restored historical-dollar baseline, baseline-plus-follow-up, andCost unavailablelegacy/null states could not be captured because this service-account principal has no cloud conversation history (staging metadata listing returns 422 for the service-account UUID) and the local conversation list is empty after the harmless fresh prompt. Verification run: https://oz.staging.warp.dev/runs/019f91cc-ee9e-72d8-9368-1227f0b2dcecOriginating thread: https://linear.app/warpdotdev/issue/APP-4952/tui-cost-footer-shows-dollar00-after-conversation-restoration-ignores
Conversation: https://staging.warp.dev/conversation/09f38106-ab47-4561-8d43-d91f4c1a86c3
Run: https://oz.staging.warp.dev/runs/019f91cc-ee9e-72d8-9368-1227f0b2dcec
This PR was generated with Oz.