Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion code_puppy/agents/event_stream_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ async def event_stream_handler(

from termflow import Parser as TermflowParser
from termflow import Renderer as TermflowRenderer
from termflow.render.style import RenderFeatures

# Disable OSC 52 clipboard integration to prevent cross-session clipboard pollution
# when multiple code-puppy instances are running concurrently
termflow_features = RenderFeatures(clipboard=False)

# Use the module-level console (set via set_streaming_console)
console = get_streaming_console()
Expand Down Expand Up @@ -190,7 +195,9 @@ async def _print_response_banner() -> None:
# Initialize termflow streaming for this text part
termflow_parsers[event.index] = TermflowParser()
termflow_renderers[event.index] = TermflowRenderer(
output=console.file, width=console.width
output=console.file,
width=console.width,
features=termflow_features,
)
termflow_line_buffers[event.index] = ""
# Handle initial content if present
Expand Down
9 changes: 6 additions & 3 deletions code_puppy/cli_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import argparse
import asyncio
import os
import platform
import sys
import time
import traceback
Expand Down Expand Up @@ -561,9 +562,11 @@ async def interactive_mode(message_renderer, initial_command: str = None) -> Non

except KeyboardInterrupt:
# Handle Ctrl+C - cancel input and continue
# Windows-specific: Reset terminal state after interrupt to prevent
# the terminal from becoming unresponsive (can't type characters)
reset_windows_terminal_full()
# Reset terminal to fix CSI u mode garbage (^[[27;5;99~)
if platform.system() != "Windows":
reset_unix_terminal()
else:
reset_windows_terminal_full()
# Stop wiggum mode on Ctrl+C
from code_puppy.command_line.wiggum_state import (
is_wiggum_active,
Expand Down
22 changes: 17 additions & 5 deletions code_puppy/terminal_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,16 +129,28 @@ def reset_windows_terminal_full() -> None:
def reset_unix_terminal() -> None:
"""Reset Unix/Linux/macOS terminal to sane state.

Uses the `reset` command to restore terminal sanity.
Silently fails if the command isn't available.
Disables CSI u / kitty keyboard protocol (fixes ^[[27;5;99~ from Ctrl+C)
and bracketed paste mode, then falls back to stty sane (or reset).
"""
if platform.system() == "Windows":
return

# Disable enhanced keyboard protocols left enabled by prompt_toolkit
try:
subprocess.run(["reset"], check=True, capture_output=True)
except (subprocess.CalledProcessError, FileNotFoundError):
pass # Silently fail if reset command isn't available
sys.stdout.write("\x1b[<u\x1b[>4;0m\x1b[?2004l\x1b[0m")
sys.stdout.flush()
except Exception:
pass

# stty sane is less disruptive than reset (preserves screen)
try:
subprocess.run(["stty", "sane"], capture_output=True, timeout=2)
except Exception:
# Fall back to reset if stty isn't available
try:
subprocess.run(["reset"], capture_output=True, timeout=2)
except Exception:
pass


def reset_terminal() -> None:
Expand Down
Loading