43 Commits

  • Add ANSI-aware word wrapping to TUI components
    - Created shared wrapTextWithAnsi() function in utils.ts
    - Handles word-based wrapping while preserving ANSI escape codes
    - Properly tracks active ANSI codes across wrapped lines
    - Supports multi-byte characters (emoji, surrogate pairs)
    - Updated Markdown and Text components to use shared wrapping
    - Removed duplicate wrapping logic (158 lines total)
  • feat(coding-agent): add OAuth authentication for Claude Pro/Max
    - Add /login and /logout commands for OAuth flow
    - OAuth tokens stored in ~/.pi/agent/oauth.json with 0600 permissions
    - Auto-refresh tokens when expired (5min buffer)
    - Priority: OAuth > ANTHROPIC_OAUTH_TOKEN env > ANTHROPIC_API_KEY env
    - Fix model selector async loading and re-render
    - Add bracketed paste support to Input component for long codes
    - Update README.md with OAuth documentation
    - Add implementation docs and testing checklist
  • refactor(tui): Use explicit charCode check for unicode filtering
    - Use 'charCodeAt(0) >= 32' instead of open 'else' in handleInput()
    - Use same filter in handlePaste() for consistency
    - Prevents control characters while allowing all unicode
    - More explicit and safer than accepting everything
  • feat(tui): improve editor Ctrl/Alt word and line deletion shortcuts
    - Add Ctrl+W for word deletion (stops at whitespace/punctuation)
    - Add Ctrl+U for delete to start of line (merges with previous line at col 0)
    - Change Ctrl+K from delete entire line to delete to end of line (merges with next line at EOL)
    - Add Option+Backspace support in Ghostty (maps to Ctrl+W via ESC+DEL sequence)
    - Cmd+Backspace in Ghostty works as Ctrl+U (terminal sends same control code)
    - Update README and CHANGELOG with new keyboard shortcuts
    
    Fixes #2, Fixes #3
  • docs: simplify MCP section with clear stance and minimal example
    - State upfront: pi does not support MCP
    - Provide minimal working example (README + bash script)
    - Show simple usage pattern
    - Remove verbose explanations
    
    fix(tui): don't show duplicate URL when link text equals href
  • Improve edit tool diff display with context-aware rendering
    - Add generateDiffString() function in edit tool to create unified diffs with line numbers and 4 lines of context
    - Store only the formatted diff string in tool result details instead of full file contents
    - Update tool-execution renderer to parse and colorize the diff string
    - Filter out message_update events from session saving to prevent verbose session files
    - Add markdown nested list and table rendering tests
  • Redesign session selector with multi-line layout
    - Custom SessionList component with 2 lines per item
    - First line: message text (bold when selected)
    - Second line: metadata (time · message count) in dim
    - Blue › cursor for selected item
    - Added "Resume Session" header
    - Handle Ctrl+C (‹x03›) in SelectList for consistency
    - Improved date formatting (38 minutes ago, 8 hours ago, etc.)
  • Fix viewport width issues in thinking selector and text rendering
    Thinking selector fix:
    - Replace hardcoded 50-character borders with DynamicBorder component
      that adjusts to viewport width
    - Prevents crash when terminal is resized narrow
    
    Text/Markdown rendering fixes:
    - Fix Markdown wrapSingleLine to check if adding next character would
      exceed width BEFORE adding it (was checking AFTER, causing lines to
      be 1 character too long)
    - Add word truncation in Text component for words longer than
      contentWidth (prevents long unbreakable words from exceeding width)
    
    These fixes prevent "Rendered line exceeds terminal width" errors.
  • Fix SelectList crash on narrow terminal and thinking level restoration
    SelectList fixes:
    - Use hardcoded visual width for arrow prefix instead of string length
      which includes ANSI codes
    - Truncate scroll indicator text to prevent exceeding terminal width
    - Fixes crash when terminal is resized narrow and arrow keys are pressed
    
    Thinking level fix:
    - Restore thinking level even if it's "off" (removed !== "off" check)
    - This ensures the thinking level selector shows the correct state on continue
  • Fix tab rendering in TUI components
    Replace tabs with 3 spaces for consistent rendering and width calculation:
    - Updated visibleWidth() to normalize tabs before measuring
    - Updated Text and Markdown components to replace tabs when rendering
    - Updated tool-execution display for read/write tools to replace tabs
    
    This fixes background color rendering issues when displaying files with tab indentation.
  • Improve tool execution rendering and error handling
    - Show tool execution components immediately when tool calls appear in streaming
    - Update components with streaming arguments as they come in
    - Handle incomplete/partial arguments gracefully with optional chaining
    - Fix error handling: tools now throw exceptions instead of returning error messages
    - Fix bash abort handling to properly reject on abort/timeout
    - Clean up error display
  • Refactor TUI into proper components
    - Create UserMessageComponent - handles user messages with spacing
    - Create AssistantMessageComponent - handles complete assistant messages
    - Create ThinkingSelectorComponent - wraps selector with borders
    - Add setSelectedIndex to SelectList for preselecting current level
    - Simplify tui-renderer by using dedicated components
    - Much cleaner architecture - each message type is now a component
  • Replace Markdown with Text component for tool execution
    - Add background color support to Text component
    - Replace Markdown component with Text in ToolExecutionComponent
    - Use chalk.bold for formatting instead of markdown syntax
    - Remove unnecessary markdown parsing overhead
  • Add /thinking command and improve TUI UX
    - Add /thinking slash command with autocomplete for setting reasoning levels (off, minimal, low, medium, high)
    - Fix Ctrl+C behavior: remove hardcoded exit in TUI, let focused component handle it
    - Add empty lines before and after tool execution components for better visual separation
    - Fix stats rendering: display stats AFTER tool executions complete (matches web-ui behavior)
    - Remove "Press Ctrl+C again to exit" message, show "(esc to interrupt)" in loader instead
    - Add bash tool abort signal support with immediate SIGKILL on interrupt
    - Make Text and Markdown components return empty arrays when no actual text content
    - Add setCustomBgRgb() method to Markdown for dynamic background colors
  • Fix markdown streaming duplication by splitting newlines first
    - Added string-width library for proper terminal column width calculation
    - Fixed wrapLine() to split by newlines before wrapping (like Text component)
    - Fixed Loader interval leak by stopping before container removal
    - Changed loader message from 'Loading...' to 'Working...'
  • Clean up TUI package and refactor component structure
    - Remove old TUI implementation and components (LoadingAnimation, MarkdownComponent, TextComponent, TextEditor, WhitespaceComponent)
    - Rename components-new to components with new API (Loader, Markdown, Text, Editor, Spacer)
    - Move Text and Input components to separate files in src/components/
    - Add render caching to Text component (similar to Markdown)
    - Add proper ANSI code handling in Text component using stripVTControlCharacters
    - Update coding-agent to use new TUI API (requires ProcessTerminal, uses custom Editor subclass for key handling)
    - Remove old test files, keep only chat-simple.ts and virtual-terminal.ts
    - Update README.md with new minimal API documentation
    - Switch from tsc to tsgo for type checking
    - Update package dependencies across monorepo
  • Add line count to paste markers
    - Paste markers now show line count: [paste #1 +50 lines]
    - Update replacement logic to handle both old and new marker formats
    - Provides better visibility into paste size
  • Add padding to Text component and fix padding calculation
    - Add paddingX and paddingY support to Text component (default 1, 1)
    - Fix padding calculation bug in both Text and Markdown
    - Right padding now correctly fills to terminal width
    - Remove unused Spacer import from chat-simple
  • Fix terminal rendering and add improvements
    - Enable bracketed paste mode for handling large pastes
    - Fix editor duplicate line rendering bug at terminal width
    - Add padding support to Markdown component (paddingX/Y)
    - Add Spacer component for vertical spacing
    - Update chat-simple with spacers between messages
  • Add minimal TUI rewrite with differential rendering
    - New TUI implementation with 3-strategy differential rendering
    - Synchronized output (CSI 2026) for flicker-free updates
    - New components: Editor, Markdown, Loader, SelectList, Spacer
    - Editor: file autocomplete, slash commands, large paste markers
    - Markdown: RGB background colors, caching
    - Terminal: cursor movement, visibility, clear operations
    - Chat demo with color-coded messages
  • fix: Remove unused imports and add biome-ignore for false positive
    - Remove unused SlashCommand import from tui-renderer.ts
    - Add biome-ignore comment for previousRenderCommands which is actually used
  • feat(agent): Add /tokens command for cumulative token usage tracking
    Added /tokens slash command to TUI that displays session-wide token statistics.
    Key changes:
    - Fixed SessionManager to accumulate token usage instead of storing only last event
    - Added cumulative token tracking to TUI renderer alongside per-request totals
    - Implemented slash command infrastructure with /tokens autocomplete support
    - Fixed file autocompletion that was missing from Tab key handling
    - Clean minimal display format showing input/output/reasoning/cache/tool counts
    
    The /tokens command shows:
    Total usage
       input: 1,234
       output: 567
       reasoning: 89
       cache read: 100
       cache write: 50
       tool calls: 2
  • fix(tui): Fix garbled output when content exceeds viewport
    - Implemented new renderLineBased method that properly handles scrollback boundaries
    - Fixed ANSI code preservation in MarkdownComponent line wrapping
    - Added comprehensive test to reproduce and verify the fix
    - Root cause: PARTIAL rendering strategy couldn't position cursor in scrollback
    - Solution: Component-agnostic line comparison with proper viewport boundary handling
  • fix(tui): Container change detection for proper differential rendering
    Fixed rendering artifact where duplicate bottom borders appeared when components
    dynamically shifted positions (e.g., Ctrl+C in agent clearing status container).
    
    Root cause: Container wasn't reporting as "changed" when cleared (0 children),
    causing differential renderer to skip re-rendering that area.
    
    Solution: Container now tracks previousChildCount and reports changed when
    child count changes, ensuring proper re-rendering when containers are cleared.
    
    - Added comprehensive test reproducing the layout shift artifact
    - Fixed Container to track and report child count changes
    - All tests pass including new layout shift artifact test
  • fix(tui): Trigger initial render when start() is called
    The demos were not showing any output until user input because:
    - Components were added before ui.start() was called
    - addChild calls requestRender() but it returns early if \!isStarted
    - So no initial render happened until user input triggered one
    
    Now ui.start() triggers an initial render if components exist.
  • tui: Implement surgical differential rendering for minimal redraws
    - New renderDifferentialSurgical method with three strategies:
      - SURGICAL: Only update specific changed lines (1-2 lines per render)
      - PARTIAL: Clear and re-render from first change when line counts change
      - FULL: Clear scrollback and re-render all when changes above viewport
    - Preserves all content in scrollback buffer correctly
    - Reduces redraws from ~14 lines to ~1.3 lines for common updates
    - All 24 tests pass including scrollback preservation tests
    - Massive performance improvement: 90% reduction in unnecessary redraws
  • tui: Fix differential rendering to preserve scrollback buffer
    - renderDifferential now correctly handles content that exceeds viewport
    - When changes are above viewport, do full re-render with scrollback clear
    - When changes are in viewport, do partial re-render from change point
    - All tests pass, correctly preserves 100 items in scrollback
    - Issue: Still re-renders too much (entire tail from first change)
  • tui-double-buffer: Implement smart differential rendering with terminal abstraction
    - Create Terminal interface abstracting stdin/stdout operations for dependency injection
    - Implement ProcessTerminal for production use with process.stdin/stdout
    - Implement VirtualTerminal using @xterm/headless for accurate terminal emulation in tests
    - Fix TypeScript imports for @xterm/headless module
    - Move all component files to src/components/ directory for better organization
    - Add comprehensive test suite with async/await patterns for proper render timing
    - Fix critical TUI differential rendering bug when components grow in height
      - Issue: Old content wasn't properly cleared when component line count increased
      - Solution: Clear each old line individually before redrawing, ensure cursor at line start
    - Add test verifying terminal content preservation and text editor growth behavior
    - Update tsconfig.json to include test files in type checking
    - Add benchmark test comparing single vs double buffer performance
    
    The implementation successfully reduces flicker by only updating changed lines
    rather than clearing entire sections. Both TUI implementations maintain the
    same interface for backward compatibility.
  • Fix process.cwd() error when running from deleted directory
    - Defer process.cwd() call in logger to avoid initialization errors
    - Resolve log file path only when actually writing logs
    - Bump version to 0.5.2
  • Initial monorepo setup with npm workspaces and dual TypeScript configuration
    - Set up npm workspaces for three packages: pi-tui, pi-agent, and pi (pods)
    - Implemented dual TypeScript configuration:
      - Root tsconfig.json with path mappings for development and type checking
      - Package-specific tsconfig.build.json for clean production builds
    - Configured lockstep versioning with sync script for inter-package dependencies
    - Added comprehensive documentation for development and publishing workflows
    - All packages at version 0.5.0 ready for npm publishing