Repository navigation
feat(tui): make pet mode the main Codewhale view - #6920
Conversation
Replace the full-screen tank layout with the shared GPUI whale, current-session retained agents, streamed replies/errors and existing notices. Preserve composer/session state, route Enter through the existing agent transcript/approval event, and revalidate painted worker identities. Use the pet view motion policy and canonical completion clip without a second world, prompt or execution owner. Validation: focused pet/owner/audio/persistence tests 30 passed, 0 failed; keyboard routing 17 passed, 0 failed; draft/focus binding guard 1 passed, 0 failed. Scoped production Clippy passed with the three deliberate project-style allowances from CI; changed-path formatting passed. Library PR #23 merged after all 10 hosted checks passed; local component tests 5+1 passed and idle PTY 7/7 passed, with both 200-frame previews matching actual buffers. Earlier raw Clippy hit 20 findings in unchanged code covered by those documented style allowances; its failure receipt is retained. Updated two old test assumptions for native availability and context-owned Tab. macOS warned that the large unit-test binary exceeds the compact unwind section limit; test exit was 0. No full local suite, live providers, physical terminal/audio, installed release or simultaneous desktop-owner acceptance claimed. Stage only 13 declared paths. Saved foreign avatar hunks remain unstaged, including the two adjacent preview guards removed from the index by exact baseline subtraction. This feature stays separate from release-candidate PR #6907. Evidence: artifacts/ratatui-full-pet-20261008; SHA-6533.
| state.output_scroll = state | ||
| .output_scroll | ||
| .min(self.output.len().saturating_sub(usize::from(body.height))); |
There was a problem hiding this comment.
🟡 Streaming replies stop following new text
When a reply grows beyond the viewport, output_scroll stays at zero while new lines arrive. The user sees the beginning instead of the streaming tail until they scroll manually.
Learn more
The output pane displays an already-wrapped response and stores its current top line in output_scroll. On each redraw, the code clamps that top line only if it exceeds the maximum; it never advances it when streaming adds lines. A new response starts at offset zero, so once its lines fill the pane, later streamed content appears below the visible area. The user must scroll to see whether the reply has progressed.
Example: At 40×12, a response with 20 wrapped lines starts at line zero. When another 20 lines stream in, the visible pane still starts at line zero instead of showing the new lines.
Recommended fix: Track whether the reader has explicitly scrolled away from the tail in PetModeState. Follow appended lines while tail-follow is active, and preserve the existing offset once the reader scrolls up; reset tail-follow on a new turn.
Was this helpful? React with 👍 or 👎 to provide feedback.
| KeyCode::Tab | KeyCode::BackTab => (1..=agents.len()) | ||
| .map(|step| { | ||
| if key.code == KeyCode::BackTab || key.modifiers.contains(KeyModifiers::SHIFT) { | ||
| (index + agents.len() - step) % agents.len() | ||
| } else { | ||
| (index + step) % agents.len() | ||
| } |
| view.agent_words = SubagentViewWords { | ||
| title: tr(app.ui_locale, MessageId::SubagentsHeaderRoster), | ||
| empty: tr( | ||
| app.ui_locale, | ||
| MessageId::SubagentsNoCurrentSessionFleetWorkers, | ||
| ), | ||
| hints: "".into(), | ||
| open: "".into(), | ||
| message: "".into(), | ||
| stop: "".into(), | ||
| summary: Some(agents.len().to_string().into()), | ||
| steps_label: Some(tr(app.ui_locale, MessageId::SessionMetricsSteps)), | ||
| ..Default::default() | ||
| }; |
| let response = app | ||
| .history | ||
| .iter() | ||
| .skip(app.pet_watch.work_history_start) | ||
| .chain( | ||
| app.active_cell | ||
| .as_ref() | ||
| .into_iter() | ||
| .flat_map(|cell| cell.entries()), | ||
| ) | ||
| .rfind(|cell| { | ||
| matches!( | ||
| cell, | ||
| HistoryCell::Assistant { .. } | HistoryCell::Error { .. } | ||
| ) | ||
| }); |
There was a problem hiding this comment.
There was a problem hiding this comment.
🟡 Changes recommended
Streamed responses and long agent outputs currently incur repeated full-content processing that can stall the TUI.
1 open finding
What changed in this PR
Integrates the native Ratatui pet experience into the live TUI Engine session, combining animated whale rendering, streamed responses, notices, and retained agents.
Changes:
- Adds native pet, roster, response, and pixel-rendering components.
- Connects pet mode to live session state, motion policy, and agent transcripts.
- Adds keyboard, mouse, visibility, and rendering coverage.
| File | Description |
|---|---|
vendor/codewhale-ratatui/src/whale_motion/pixels.rs |
Adds bounded RGBA whale rendering. |
vendor/codewhale-ratatui/src/whale_motion/mod.rs |
Registers the pixel renderer. |
vendor/codewhale-ratatui/src/whale_motion/acting.rs |
Exposes completion-animation state. |
vendor/codewhale-ratatui/src/components/whale_pet.rs |
Adds the native whale widget. |
vendor/codewhale-ratatui/src/components/subagents.rs |
Adds retained-agent roster and detail views. |
vendor/codewhale-ratatui/src/components/pet_mode.rs |
Composes the full pet-mode surface. |
vendor/codewhale-ratatui/src/components/mod.rs |
Exports new components. |
vendor/codewhale-ratatui/src/avatar_sprite.rs |
Adds single-image sprite construction. |
crates/tui/src/tui/ui/tests.rs |
Extends shell-binding coverage. |
crates/tui/src/tui/shell_key_routing.rs |
Adds pet navigation bindings. |
crates/tui/src/tui/pet_watch/mod.rs |
Integrates native pet state and controls. |
crates/tui/src/tui/pet_watch/habitat.rs |
Routes modal input and transcript opening. |
crates/tui/src/tui/pet_watch/full.rs |
Projects live Engine state into pet mode. |
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
| if app.pet_watch.full_response_key != Some(key) { | ||
| app.pet_watch.full_response = None; | ||
| app.pet_watch.full_response_key = Some(key); |
Describe the actual session view and its controls under Unreleased. Link the shared component provenance and state its boundary from the separate 0.10.2 candidate; this satisfies the feature-note receipts required by the original feature commit without changing that candidate or claiming a release. Validation: the PR-scoped feature-note check passed for both required linked references (2 checked); changed-path whitespace check passed. Product code is unchanged from the 48 passing focused Engine checks and passing scoped production Clippy/formatting receipts. No Rust suite was repeated for prose. SHA-6533; Refs #6155. Evidence: artifacts/ratatui-full-pet-20261008/.
Apply the shared PetMode stream-follow correction: appended replies remain visible until the reader scrolls back, End or reaching the bottom resumes following, and the existing turn-start event resets the presentation state. Reuse canonical Director turn identity. Supply localized status/result words for the retained agent pane and leave unprojected event receipts blank; Enter continues to open the existing full transcript. Validation: 31 focused pet/owner/audio/persistence tests passed, 0 failed, including streamed-tail mutation through the real ActiveCell cache and French agent details. Prior 17 routing tests and 1 draft/focus guard remain green; their code was unchanged and they were not repeated. Scoped production Clippy with CI's deliberate style allowances and changed-path formatting passed. The matching shared library has 6 passing PetMode integration tests, locked all-target Clippy with warnings denied and formatting. No full local suite, installed release, physical terminal/audio or live provider journey claimed. Only three declared paths are staged. The avatar author's two preview guards are preserved unstaged by exact index-only baseline subtraction. The reading correction is separately reviewed in the shared library. SHA-6533; Refs #6155. Evidence: artifacts/ratatui-full-pet-20261008/.
Regenerate the packaged /change notes from the root changelog with the existing sync script. This repairs the missing generated copy reported by Version drift without changing product code, version numbers or the separate candidate. Validation: changelog sync check passed; the version-state gate passed with range audits advisory (40 global feature references checked; workspace, npm, binary pin and lockfile all 0.10.1); changed-path whitespace check passed. The PR-scoped feature-note check already passed for its 2 required references. Only 10 generated prose lines changed. The 49 focused Engine checks and scoped Clippy/formatting receipts are unchanged and were not repeated for prose. SHA-6533; Refs #6155. Evidence: artifacts/ratatui-full-pet-20261008/.
/pet on now selects the native whale backdrop with the existing composer, queue feedback and permission controls. F5, the painted hint and /pet inspect open the same replies/agents inspector; Escape returns to the existing draft. The standard transcript, metrics and work rail yield their space and hitboxes. Explicit tools and focused worker transcripts remain available on demand. Schedule native idle motion through the existing poll loop and honor the selected palette. Localize all new controls in 15 packs. Keep incremental reply formatting across streamed revisions and view changes using the actual source identity, revision and existing append receipt; unknown edits revoke provenance and rebuild correctly. No prompt/session/execution authority added. Validation: 54 focused pet tests, 17 routing tests and 1 draft/focus guard passed (72 checks, 0 failures); localization 54 passed, 0 failed. npm test: 1,317 passed, 7 skipped, 0 failed; npm run check:web passed. Changed Rust formatting and scoped production Clippy with CI's 3 style allowances passed. Five terminal sizes, both themes, composer paste/caret/mouse, queue visibility, approval ownership, idle deadlines and incremental/rewrite fallback are covered. Actual Engine buffer captures are under artifacts/ratatui-pet-main-20261008. The vendored PetMode matches merged codewhale-ratatui #25 (6f0ab44) exactly; its 8 focused tests and all 15 hosted checks passed. Stage only this slice's 31 paths, excluding the avatar author's two guard lines in pet_watch/mod.rs. Physical terminal/audio/provider and installed/released acceptance stay open. The 0.10.2 candidate #6907 is untouched. Refs #6920, #6155
Persist /pet on|off through Settings and the existing ordered background writer. Restore the main pet backdrop without the launch overlay. The Appearance setting reports saved and effective values separately; session only overrides and rejected values leave the startup choice alone. The inspector's c key and painted footer target invoke /copy, retaining its completed-answer receipt, raw Markdown, recovery backup and queued-vs-accepted clipboard wording. A bounded command receipt remains visible over Done. Hidden, resized and truncated footer targets are cleared before input. All three new labels are translated in the fifteen complete locale packs. Validation, final source: - Pet: 60 passed, 0 failed (restart/order/shutdown, malformed settings, drafts, real keyboard/pointer routes, copy authority and dark/light renderer). - Ordered writer: 9 passed; shell routing: 17 passed; /copy: 14 passed; toast lifecycle: 6 passed; localized settings schema: 1 passed. No failures. - Config schema: 4 passed; localization: 54 passed. Total: 165 passed, 0 failed. - npm test: 1,317 passed, 7 skipped, 0 failed (545 Node + 772 Vitest). - npm run check:web passed. Changed Rust formatting: 17 files passed. - Production TUI Clippy passed with -D warnings and the CI's existing uninlined_format_args, too_many_arguments and unnecessary_map_or allowances. Earlier local receipts retained: a test import used a retired private command path (E0433), then the first compiled run passed 58 and failed 1 because its unknown-key fixture assumed preservation beyond the existing serializer's contract. Tests now use the public command entry and supported preference annotations; malformed TOML remains byte-preserved. Final checks above pass. Stage only 35 declared paths. Preserve unrelated shared documentation/web/ avatar changes, including the two avatar guards in pet_watch/mod.rs. The shared library remains the merged #25 component; no new execution authority. This source slice updates #6920. Actual 0.10.2 candidate #6907 integration, local installed binary and live terminal/provider acceptance remain separate. Refs SHA-6533

/pet onmakes the animated GPUI whale the main Codewhale terminal view while retaining the normal message box, paste, caret, queued messages and permission controls. F5, the clickable replies hint or/pet inspectopens streamed replies, errors and the current session’s real agents. Escape returns to the same view and draft;/pet offrestores the standard shell.The selected view now survives restarts through the existing Settings store and ordered background writer. Appearance settings distinguish the saved choice from the live session. Invalid choices and session overrides do not change the startup preference; failed saves surface a localized warning and preserve malformed settings.
The inspector’s
ckey and visible footer action invoke the existing/copycommand. They copy the last completed assistant receipt with its original Markdown and recovery backup, including while a newer reply streams. Clipboard accepted/queued/failure wording comes from that command. Its transient result stays visible over the completed phase. Hidden or truncated controls leave no click targets. All new controls are translated in the 15 interface languages.Native animation wakes the existing event loop and follows theme/motion preferences. Stream formatting uses the existing incremental Markdown cache, actual cell revisions and append provenance. Worker opening revalidates current-session identity; missing usage stays unknown. Durable companion world, audio, sessions, prompts and execution keep their existing owners.
Validation of source
4434806df9d0be8d85fd8730bb126841aa17a41e:npm test: 1,317 passed, 7 skipped, 0 failed;npm run check:webpassed.The latest slice commits 35 declared paths; this review has 47 paths in total. The clean review ref applies exactly the tested edits while preserving main’s context: 15 updated blobs match source exactly, and 20 retain main’s existing context with identical changed lines. Projected changelogs and all 45 new translated values were checked. Foreign shared documentation/web/avatar work, including two avatar guard lines, is excluded. Hosted CI must qualify this review head.
The 0.10.2 candidate in #6907 is unchanged. Integration into that candidate, a locally installed 0.10.2 binary, real provider use and physical terminal/audio/desktop-owner acceptance remain open under SHA-6533. This PR does not claim release or installed-client qualification.
Refs #6155