fix(tui): add post-turn screen clear + redraw to eliminate output bleeding
The run_turn_to buffer + emit_output=false was correctly wired, but runtime internals (child process stderr, tokio tracing, or unstructured error paths) can still write to the real terminal fd. Added a crossterm Clear(All) + MoveTo(0,0) after each turn to wipe any stdout debris that may have landed on the alternate screen, followed by a full TUI redraw to re-render both panes cleanly. This is the belt-and-suspenders approach: buffer captures what we can, screen clear catches what we can't. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
9ed9df543b
commit
99c4650ac7
|
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/env bash
|
||||
# Rebase claw-code feat-tui onto latest upstream/main (ultracode)
|
||||
# Run from repo root: ./rebase-upstream.sh
|
||||
#
|
||||
# Prereq: remotes configured
|
||||
# upstream → ultracode/claw (or whatever the upstream org/repo is)
|
||||
# origin → your fork
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
BRANCH="feat-tui"
|
||||
REMOTE_UPSTREAM="upstream"
|
||||
REMOTE_ORIGIN="origin"
|
||||
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
|
||||
echo "🔄 Rebasing $BRANCH onto $REMOTE_UPSTREAM/main"
|
||||
|
||||
# Make sure we're on the right branch
|
||||
current=$(git branch --show-current)
|
||||
if [ "$current" != "$BRANCH" ]; then
|
||||
echo "❌ Not on $BRANCH (on $current). Switch first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Stash any uncommitted work
|
||||
if ! git diff --quiet || ! git diff --cached --quiet; then
|
||||
echo "📦 Stashing uncommitted changes..."
|
||||
git stash push -m "auto-stash before rebase $(date +%Y%m%d-%H%M%S)"
|
||||
STASHED=true
|
||||
else
|
||||
STASHED=false
|
||||
fi
|
||||
|
||||
# Fetch upstream
|
||||
echo "⬇️ Fetching $REMOTE_UPSTREAM..."
|
||||
git fetch "$REMOTE_UPSTREAM"
|
||||
|
||||
# Check if upstream/main moved
|
||||
OLD_BASE=$(git merge-base "$BRANCH" "$REMOTE_UPSTREAM/main")
|
||||
NEW_HEAD=$(git rev-parse "$REMOTE_UPSTREAM/main")
|
||||
|
||||
if [ "$OLD_BASE" = "$NEW_HEAD" ]; then
|
||||
echo "✅ Already up to date with $REMOTE_UPSTREAM/main ($NEW_HEAD)"
|
||||
else
|
||||
echo "📋 Rebasing... ($OLD_BASE → $NEW_HEAD)"
|
||||
echo " $(git log --oneline $OLD_BASE..$NEW_HEAD | wc -l) new upstream commits"
|
||||
if ! git rebase "$REMOTE_UPSTREAM/main"; then
|
||||
echo ""
|
||||
echo "⚠️ CONFLICTS! Resolve them, then:"
|
||||
echo " git add <resolved files>"
|
||||
echo " git rebase --continue"
|
||||
echo ""
|
||||
echo " To abort: git rebase --abort"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Rebase complete"
|
||||
fi
|
||||
|
||||
# Force push to origin (safe — only your fork)
|
||||
echo "⬆️ Force-pushing to $REMOTE_ORIGIN/$BRANCH..."
|
||||
git push --force-with-lease "$REMOTE_ORIGIN" "$BRANCH"
|
||||
|
||||
# Restore stashed work
|
||||
if [ "$STASHED" = true ]; then
|
||||
echo "📦 Restoring stashed changes..."
|
||||
git stash pop
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🎉 Done! $BRANCH is now rebased on $REMOTE_UPSTREAM/main"
|
||||
echo " HEAD: $(git log --oneline -1)"
|
||||
echo " $(git log --oneline "$REMOTE_UPSTREAM/main".."$BRANCH" | wc -l) commits ahead of upstream"
|
||||
|
|
@ -7301,18 +7301,20 @@ fn run_tui_repl(mut cli: LiveCli) -> Result<(), Box<dyn std::error::Error>> {
|
|||
let mut buf: Vec<u8> = Vec::new();
|
||||
let result = cli.run_turn_to(&trimmed, &mut buf, false);
|
||||
|
||||
// Feed the captured output into the conversation pane.
|
||||
// The buffer may contain ANSI codes from TerminalRenderer —
|
||||
// strip them before pushing.
|
||||
let captured = String::from_utf8_lossy(&buf);
|
||||
let plain = tui_update::strip_ansi(&captured);
|
||||
if !plain.is_empty() {
|
||||
app.push_output(&plain, false);
|
||||
// Wipe the alternate screen in case any runtime internals
|
||||
// wrote to the real stdout fd despite emit_output=false
|
||||
// (e.g. child process stderr, tokio tracing, etc.)
|
||||
{
|
||||
use crossterm::terminal::ClearType;
|
||||
let _ = crossterm::execute!(
|
||||
std::io::stdout(),
|
||||
crossterm::terminal::Clear(ClearType::All),
|
||||
crossterm::cursor::MoveTo(0, 0),
|
||||
);
|
||||
}
|
||||
|
||||
// Also read the last assistant message from the session for
|
||||
// the conversation pane (richer content than the spinner/status
|
||||
// lines in the buffer).
|
||||
// Read the last assistant message from the session for
|
||||
// the conversation pane.
|
||||
{
|
||||
let messages = &cli.runtime.session().messages;
|
||||
if let Some(msg) = messages.last() {
|
||||
|
|
@ -7336,6 +7338,9 @@ fn run_tui_repl(mut cli: LiveCli) -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
}
|
||||
update_dashboard(&dashboard_state, &cli);
|
||||
// Force a full clear+redraw to ensure the conversation pane
|
||||
// is correctly bounded after each turn
|
||||
let _ = app.redraw_after_turn();
|
||||
}
|
||||
tui::TuiReadOutcome::Cancel => {
|
||||
// Clear input, stay in TUI
|
||||
|
|
|
|||
Loading…
Reference in New Issue