feat: fixed-bottom status bar with adaptive layout and resize watcher#245
feat: fixed-bottom status bar with adaptive layout and resize watcher#245MicalLee0415 wants to merge 14 commits into
Conversation
Add ModelPricing struct, lookup_pricing(), and estimate_cost() for computing API costs based on model name, input/output token counts, and optional per-model pricing overrides. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add StatusBarConfig struct with visible/style/refresh_interval_ms fields and optional per-model pricing overrides. Register in ConfigModel with serde defaults. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add statusbar.notice.hidden key across all 6 locales (en/zh/ja/de/fr/es). Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add statusbar module with Plan C adaptive layout (cwd, context tokens, I/O split, cost, request count, latency, state), ANSI scroll region management (enter/exit/reassert_after_resize), Ctrl+T toggle rendering, and 23 unit tests covering latency formatting, cwd shortening, progress bars, and state segments. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Bind Ctrl+T to a StatusToggleHandler that interrupts read_line so the main loop can toggle status bar visibility. Also add /token show and /token hide to slash command list. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add context_budget_state() accessor so the status bar can display current token usage and budget percentage. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Wire status bar into the main REPL loop: enter/exit fixed mode on startup/shutdown, render status bar each iteration, time AI API calls for latency display, detect terminal resize, and spawn a background polling thread (200ms interval) that re-asserts the ANSI scroll region during read_line when the terminal is resized — preventing the prompt and status bar from being stranded mid-screen. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
|
Thanks for the pull request. A maintainer will review it when available. Please keep the PR focused, explain the why in the description, and make sure local checks pass before requesting review. Contribution guide: https://github.com/AI-Shell-Team/aish/blob/main/CONTRIBUTING.md |
|
Template check passed. Thanks for updating the pull request description. |
Resolve conflict in crates/aish-shell/src/lib.rs: keep both pub mod status (from PR AI-Shell-Team#242) and pub mod statusbar (this PR).
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughAdds a persistent fixed-bottom ANSI status bar to the shell REPL displaying token usage, estimated cost, context budget, AI activity state, and API latency. New ChangesStatus Bar Feature
Sequence Diagram(s)sequenceDiagram
participant User
participant ShellReadline
participant AishShell
participant statusbar
participant ResizeWatcher
participant AiHandler
participant aish_llm_pricing
AishShell->>statusbar: enter_fixed_mode(lines)
AishShell->>statusbar: render_fixed(state, config)
AishShell->>ResizeWatcher: spawn(atomic_visible, term_h)
loop every 200ms
ResizeWatcher->>statusbar: reassert_after_resize(old_h, lines)
end
User->>ShellReadline: Ctrl+T
ShellReadline-->>AishShell: was_status_toggle_requested() = true
AishShell->>statusbar: exit_fixed_mode() or enter_fixed_mode()
User->>AishShell: AI command
AishShell->>statusbar: render_fixed(ai_active=true)
AishShell->>AiHandler: run AI turn
AiHandler-->>AishShell: result + token stats
AishShell->>aish_llm_pricing: estimate_cost(model, input, output)
aish_llm_pricing-->>AishShell: Option<f64>
AishShell->>statusbar: render_fixed(ai_active=false, latency_ms)
User->>AishShell: /token
AishShell->>statusbar: render_token_panel(state, config)
AishShell->>statusbar: exit_fixed_mode() [on shutdown]
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/aish-llm/src/pricing.rs`:
- Around line 57-62: The substring fallback matching in the loop that iterates
over table.iter() returns the first HashMap match, but HashMap iteration order
is non-deterministic which causes the same model string to map to different
prices across different runs. To fix this, collect the matching keys from the
HashMap iteration (where either lower.contains(key) or key.contains(&lower)),
sort them by specificity such as by length (preferring longer/more specific
matches), and return the pricing for the most specific match rather than
returning immediately on the first match found. This ensures deterministic and
specificity-based pricing selection regardless of HashMap iteration order.
In `@crates/aish-shell/src/app.rs`:
- Around line 3077-3080: The budget_policy field is hardcoded to "sliding" but
should reflect the actual active context budget behavior. Replace the hardcoded
"sliding".to_string() value for the budget_policy field with a dynamic value
derived from either context_budget_state() or self.config.context_auto_compact
so that the status display accurately reports whether context auto-compact is
enabled or disabled. Apply this fix to both occurrences of the budget_policy
field assignment around lines 3077-3080 and 3096-3099.
- Around line 1731-1749: The status bar toggle logic currently only handles
Ctrl+T in the top-level read_line method, but the read_line_after_slash_dismiss
method does not check for was_status_toggle_requested() before falling through
to handle_ctrl_c(). Add the same Ctrl+T status bar toggle check (matching the
logic shown in the diff with statusbar_visible toggling, enter_fixed_mode,
exit_fixed_mode, and render calls) in the read_line_after_slash_dismiss method
before the code that calls handle_ctrl_c(), so that interrupts matching the
status toggle condition are handled properly instead of being treated as Ctrl+C.
- Around line 1981-1987: The error-correction branch that calls
`handle_error_correction(...)` is missing the AI-active status tracking and
latency recording that exists in the main AI branch shown in the diff. Apply the
same pattern to the error-correction branch by setting `self.ai_active = true`,
conditionally calling `self.render_statusbar_fixed()` if
`self.statusbar_visible` is true, and capturing the start time with
`std::time::Instant::now()` before the error correction call. Alternatively,
extract the status initialization and latency tracking logic into a shared
helper method and call it from both the main AI branch and the error-correction
branch to reduce duplication.
- Around line 2379-2383: The resize watcher continues to monitor
statusbar_visible_atomic even during shutdown, which can cause it to reassert
the fixed scroll region after exit_fixed_mode() has reset it if a resize event
occurs. Before calling statusbar::exit_fixed_mode() in the shutdown sequence,
disable or stop the resize watcher first to prevent it from interfering with the
scroll region reset, then proceed with setting statusbar_visible to false and
calling exit_fixed_mode().
- Around line 2623-2635: The "hide" and "show" command handlers only update the
statusbar_visible field but fail to synchronize the resize-watcher atomic field,
causing inconsistency with Ctrl+T behavior. In both the "hide" handler (where
statusbar_visible is set to false) and the "show" handler (where
statusbar_visible is set to true), add corresponding updates to the
resize-watcher atomic field to ensure both visibility tracking mechanisms remain
in sync and prevent the watcher from reasserting the previous state on terminal
resize.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 7c897f97-5de8-4252-a0ed-ece4ab8464c4
📒 Files selected for processing (16)
.gitignorecrates/aish-config/src/lib.rscrates/aish-config/src/model.rscrates/aish-i18n/locales/de-DE.yamlcrates/aish-i18n/locales/en-US.yamlcrates/aish-i18n/locales/es-ES.yamlcrates/aish-i18n/locales/fr-FR.yamlcrates/aish-i18n/locales/ja-JP.yamlcrates/aish-i18n/locales/zh-CN.yamlcrates/aish-llm/src/lib.rscrates/aish-llm/src/pricing.rscrates/aish-shell/src/ai_handler.rscrates/aish-shell/src/app.rscrates/aish-shell/src/lib.rscrates/aish-shell/src/readline.rscrates/aish-shell/src/statusbar.rs
- pricing.rs: deterministic substring fallback (sort by specificity) - app.rs: sync statusbar_visible_atomic in /token hide/show - app.rs: set atomic=false before exit_fixed_mode on shutdown - app.rs: handle Ctrl+T in read_line_after_slash_dismiss - app.rs: add ai_active/latency tracking to error correction branch - app.rs: derive budget_policy from config instead of hardcoding
Summary
read_linecauses the prompt and output to break visually. (Issue [Feature] Token额度显示 #35)read_lineis blocking. Fields include model, cwd, context tokens, in/out token counts, request latency, and session state.Change Type
Scope
User-visible Changes
/token showand/token hideslash commands for explicit controlread_lineno longer leaves the prompt/status bar stranded mid-screenCompatibility
StatusBarConfigsection added toconfig.yaml(fields:visible,style,refresh_interval_ms,pricing). Existing configs without this section get sensible defaults; no migration neededTesting
cargo check --workspace— clean (1 pre-existing dead_code warning, unrelated)statusbarunit tests pass/token show,/token hideall confirmed workingChecklist
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Tests
Chores
AGENTS.md.