Commit Graph

116 Commits

  • feat(coding-agent): add FooterDataProvider for git branch and extension statuses
    Expose data that extensions cannot otherwise access: git branch and
    extension statuses from setStatus(). Token stats, model info, etc.
    remain computable via ctx.sessionManager and ctx.model.
  • feat(tui): add overlay compositing for ctx.ui.custom() (#558)
    Adds overlay rendering capability to the TUI, enabling floating modal
    components that render on top of existing content without clearing the screen.
    
    - Add showOverlay(), hideOverlay(), hasOverlay() methods to TUI
    - Implement ANSI-aware line compositing via extractSegments()
    - Support overlay stack (multiple overlays, later on top)
    - Add { overlay: true } option to ctx.ui.custom()
    - Add overlay-test.ts example extension
    
    Also fixes pre-existing bug where bash tool output cached visual lines
    at fixed terminal width, causing crashes on terminal resize.
    
    Co-authored-by: Nico Bailon <nico.bailon@gmail.com>
  • feat(coding-agent): use built-in renderers for tool overrides without custom renderers
    When overriding a built-in tool (read, bash, edit, write, grep, find, ls)
    without providing renderCall/renderResult, the built-in renderer is now
    used automatically. This allows wrapping built-in tools for logging or
    access control without reimplementing the UI (syntax highlighting, diffs, etc.).
  • fix: show retry attempt count when aborting during retry
    When aborting a retry attempt, surface the retry-aware abort message
    in the assistant output and tool results instead of a generic "Aborted".
    
    - Set errorMessage for aborted streaming messages
    - Render abort message without forcing a leading newline when no content
  • feat(coding-agent): add ctx.ui.setEditorComponent() extension API
    - Add setEditorComponent() to ctx.ui for custom editor components
    - Add CustomEditor base class for extensions (handles app keybindings)
    - Add keybindings parameter to ctx.ui.custom() factory (breaking change)
    - Add modal-editor.ts example (vim-like modes)
    - Add rainbow-editor.ts example (animated text highlighting)
    - Update docs: extensions.md, tui.md Pattern 7
    - Clean up terminal on TUI render errors
  • feat(coding-agent): add timeout option to extension dialogs with live countdown
    Extension UI dialogs (select, confirm, input) now support a timeout option
    that auto-dismisses with a live countdown display. Simpler alternative to
    manually managing AbortSignal for timed dialogs.
    
    Also adds ExtensionUIDialogOptions type export and updates RPC mode to
    forward timeout to clients.
  • fix: OAuth token refresh failure returns undefined instead of throwing
    When OAuth refresh fails during model discovery, getApiKey() now returns
    undefined instead of throwing. This allows the app to start and fall back
    to other providers, so the user can /login to re-authenticate.
    
    fixes #498
  • Merge PR #492: Add blockImages setting
    - Setting controls filtering at convertToLlm layer
    - Images are always stored in session, filtered dynamically based on current setting
    - Toggle mid-session works: LLM sees/doesn't see images already in session
    - Fixed SettingsManager.save() to handle inMemory mode for all setters
    
    Closes #492
  • Add blockImages setting to prevent images from being sent to LLM providers
    - Setting controls filtering at convertToLlm layer (defense-in-depth)
    - Images are always stored in session, filtered dynamically based on current setting
    - Toggle mid-session works: LLM sees/doesn't see images already in session
    - Fixed SettingsManager.save() to handle inMemory mode for all setters
    
    Closes #492
  • Improve OAuth login UI with consistent dialog component
    - Add LoginDialogComponent with proper borders (top/bottom DynamicBorder)
    - Refactor all OAuth providers to use racing approach (browser callback vs manual paste)
    - Add onEscape handler to Input component for cancellation
    - Add abortable sleep for GitHub Copilot polling (instant cancel on Escape)
    - Show OS-specific click hint (Cmd+click on macOS, Ctrl+click elsewhere)
    - Clear content between login phases (fixes GitHub Copilot two-phase flow)
    - Use InteractiveMode's showStatus/showError for result messages
    - Reorder providers: Anthropic, ChatGPT, GitHub Copilot, Gemini CLI, Antigravity
  • Merge hooks and custom-tools into unified extensions system (#454)
    Breaking changes:
    - Settings: 'hooks' and 'customTools' arrays replaced with 'extensions'
    - CLI: '--hook' and '--tool' flags replaced with '--extension' / '-e'
    - API: HookMessage renamed to CustomMessage, role 'hookMessage' to 'custom'
    - API: FileSlashCommand renamed to PromptTemplate
    - API: discoverSlashCommands() renamed to discoverPromptTemplates()
    - Directories: commands/ renamed to prompts/ for prompt templates
    
    Migration:
    - Session version bumped to 3 (auto-migrates v2 sessions)
    - Old 'hookMessage' role entries converted to 'custom'
    
    Structural changes:
    - src/core/hooks/ and src/core/custom-tools/ merged into src/core/extensions/
    - src/core/slash-commands.ts renamed to src/core/prompt-templates.ts
    - examples/hooks/ and examples/custom-tools/ merged into examples/extensions/
    - docs/hooks.md and docs/custom-tools.md merged into docs/extensions.md
    
    New test coverage:
    - test/extensions-runner.test.ts (10 tests)
    - test/extensions-discovery.test.ts (26 tests)
    - test/prompt-templates.test.ts
  • feat(coding-agent): add hook API for CLI flags, shortcuts, and tool control
    Hook API additions:
    - pi.getTools() / pi.setTools(toolNames) - dynamically enable/disable tools
    - pi.registerFlag(name, options) / pi.getFlag(name) - register custom CLI flags
    - pi.registerShortcut(shortcut, options) - register keyboard shortcuts
    
    Plan mode hook (examples/hooks/plan-mode.ts):
    - /plan command or Shift+P shortcut to toggle
    - --plan CLI flag to start in plan mode
    - Read-only tools: read, bash, grep, find, ls
    - Bash restricted to non-destructive commands (blocks rm, mv, git commit, etc.)
    - Interactive prompt after each response: execute, stay, or refine
    - Shows plan indicator in footer when active
    - State persists across sessions
  • Fix non-PNG images not displaying in Kitty protocol terminals
    JPEG/GIF/WebP images were not rendering in terminals using the Kitty
    graphics protocol (Kitty, Ghostty, WezTerm) because it requires PNG
    format (f=100). Non-PNG images are now converted to PNG using sharp
    before being sent to the terminal.
  • feat: use keybindings in all selectors and lists
    Update all selector/list components to use EditorKeybindingsManager:
    - model-selector, session-selector, oauth-selector, user-message-selector
    - hook-selector, hook-input, hook-editor, tree-selector
    - select-list, settings-list, cancellable-loader
    
    This allows users to configure selectUp, selectDown, selectConfirm,
    selectCancel actions in keybindings.json
  • feat: configurable keybindings for all editor and app actions
    All keybindings configurable via ~/.pi/agent/keybindings.json
    
    Editor actions:
    - cursorUp, cursorDown, cursorLeft, cursorRight
    - cursorWordLeft, cursorWordRight, cursorLineStart, cursorLineEnd
    - deleteCharBackward, deleteCharForward, deleteWordBackward
    - deleteToLineStart, deleteToLineEnd
    - newLine, submit, tab
    - selectUp, selectDown, selectConfirm, selectCancel
    
    App actions:
    - interrupt, clear, exit, suspend
    - cycleThinkingLevel, cycleModelForward, cycleModelBackward
    - selectModel, expandTools, toggleThinking, externalEditor
    
    Also adds support for numpad Enter key (Kitty protocol codepoint 57414
    and SS3 M sequence)
    
    Example emacs-style keybindings.json:
    {
      "cursorUp": ["up", "ctrl+p"],
      "cursorDown": ["down", "ctrl+n"],
      "cursorLeft": ["left", "ctrl+b"],
      "cursorRight": ["right", "ctrl+f"],
      "deleteCharForward": ["delete", "ctrl+d"],
      "cycleModelForward": "ctrl+o"
    }
  • Fix edit tool diff not showing in TUI
    The async diff preview computation could race with tool execution,
    causing editDiffPreview to contain an error (file already modified)
    while the actual tool result had the correct diff in details.diff.
    
    Fix: prioritize result.details.diff over editDiffPreview when the
    tool has executed successfully. The preview is only used before
    tool execution completes.
  • Add shell commands without context contribution (!! prefix)
    Use !!command to execute bash commands that are shown in the TUI and
    saved to session history but excluded from LLM context, compaction
    summaries, and branch summaries.
    
    - Add excludeFromContext field to BashExecutionMessage
    - Filter excluded messages in convertToLlm()
    - Parse !! prefix in interactive mode
    - Use dim border color for excluded commands
    
    fixes #414
  • feat(coding-agent): configurable double-escape action (tree vs branch)
    Add doubleEscapeAction setting to choose whether double-escape with an
    empty editor opens /tree (default) or /branch.
    
    - Add setting to Settings interface and SettingsManager
    - Add to /settings UI for easy toggling
    - Update interactive-mode to respect the setting
    - Document in README.md settings table
    
    fixes #404
  • docs: update README.md, hooks.md, and CHANGELOG for steer()/followUp() API
    - Fix settings-selector descriptions to explain one-at-a-time vs all
    - Update README.md message queuing section, settings example, and table
    - Update hooks.md: hasPendingMessages, sendMessage options, triggerTurn example
    - Add Theme/ThemeColor export and hasPendingMessages rename to CHANGELOG
  • feat(coding-agent): complete steer()/followUp() migration
    - Update settings-manager with steeringMode/followUpMode (migrates old queueMode)
    - Update sdk.ts to use new mode options
    - Update settings-selector UI to show both modes
    - Add Alt+Enter keybind for follow-up messages
    - Update RPC API: steer/follow_up commands, set_steering_mode/set_follow_up_mode
    - Update rpc-client with new methods
    - Delete dead code: queue-mode-selector.ts
    - Update tests for new API
    - Update mom/context.ts stubs
    - Update web-ui example
  • Fix BorderedLoader to pass theme to DynamicBorder
    BorderedLoader receives theme as a parameter but was creating
    DynamicBorder() without passing it, causing DynamicBorder to
    fall back to the global theme variable which is undefined when
    loaded via jiti (separate module cache).
    
    Added doc comment to DynamicBorder explaining the jiti issue.
  • Fix DynamicBorder crash when theme not initialized
    Make DynamicBorder defensive against undefined theme by checking
    at render time instead of relying on default parameter closure.
  • fix(coding-agent): prevent full re-renders during write tool streaming
    Move line count from header to footer to avoid changing the first line
    during streaming, which was triggering full screen re-renders in the
    TUI's differential rendering logic.
  • Hooks can render custom status (#385)
    * Add ctx.ui.setStatus(key, text) API for hooks to display status in footer
    
    - Add setStatus to HookUIContext interface
    - Implement in interactive mode (FooterComponent)
    - Implement in RPC mode (fire-and-forget)
    - Add no-op implementations for headless contexts
    - Multiple statuses displayed on single line, sorted by key
    - Supports ANSI styling (hooks handle their own colors)
    
    * Remove setStatus from changelog for now
    
    * Fix hook status API to follow TUI rules
    
    - Sanitize status text: replace newlines, tabs, carriage returns with spaces
    - Truncate combined status line to terminal width using truncateToWidth
    - Update JSDoc to document sanitization and truncation behavior
    - Remove unused createHookUIContext method
    - Add missing setStatus to test mock
    
    * Add setStatus to changelog
    
    * Use dim ellipsis for hook status truncation for consistency with footer style
    
    ---------
    
    Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
  • Show edit diff before tool execution (fixes #393)
    - Extract diff computation from edit.ts into shared edit-diff.ts
    - ToolExecutionComponent computes and caches diff when args are complete
    - Diff is visible while permission hooks block, before tool executes
  • Fix characters (#372)
    * Fix cat command
    
    * Fix text rendering crash from undefined code points in bash output
    
    * Revert unintentional model parameter changes from fix cat command commit
  • Footer shows full session stats after compaction
    FooterComponent now iterates over all session entries for cumulative
    token usage and cost, not just post-compaction messages.
    
    fixes #322
  • Add thinkingText theme token, fix streaming toggle bug
    - Add configurable thinkingText color for thinking blocks (defaults to muted)
    - Make 'Thinking...' label italic when collapsed
    - Fix Ctrl+T during streaming hiding the current message
    - Track streamingMessage to properly re-render on toggle
    
    Based on #366 by @paulbettner
  • Add setEditorText/getEditorText to hook UI context, improve custom() API
    - Add setEditorText() and getEditorText() to HookUIContext for prompt generator pattern
    - custom() now accepts async factories for fire-and-forget work
    - Add CancellableLoader component to tui package
    - Add BorderedLoader component for hooks with cancel UI
    - Export HookAPI, HookContext, HookFactory from main package
    - Update all examples to import from packages instead of relative paths
    - Update hooks.md and custom-tools.md documentation
    
    fixes #350
  • Change branch() to use entryId instead of entryIndex
    - AgentSession.branch(entryId: string) now takes entry ID
    - SessionBeforeBranchEvent.entryId replaces entryIndex
    - getUserMessagesForBranching() returns entryId
    - Update RPC types and client
    - Update UserMessageSelectorComponent
    - Update hook examples and tests
    - Update docs (hooks.md, sdk.md)
  • Rework custom tools API with CustomToolContext
    - CustomAgentTool renamed to CustomTool
    - ToolAPI renamed to CustomToolAPI
    - ToolContext renamed to CustomToolContext
    - ToolSessionEvent renamed to CustomToolSessionEvent
    - Added CustomToolContext parameter to execute() and onSession()
    - CustomToolFactory now returns CustomTool<any, any> for type compatibility
    - dispose() replaced with onSession({ reason: 'shutdown' })
    - Added wrapCustomTool() to convert CustomTool to AgentTool
    - Session exposes setToolUIContext() instead of leaking internals
    - Fix ToolExecutionComponent to sync with toolOutputExpanded state
    - Update all custom tool examples for new API
  • Fix tree selector: proper selectedBg theme color, correct filter logic
    - Add selectedBg theme color for active line highlight
    - Fix filter modes:
      - no-tools: default minus tool results (still hides label/custom)
      - user-only: just user messages
      - labeled-only: just labeled entries
      - all: everything
    - Update theme.md with new color tokens (50 total)
  • Tree selector improvements: active line highlight and tool filter
    - Add inverse background highlight for selected/active line
    - Add 'no-tools' filter mode to hide tool results
    - Add isShiftCtrlO to cycle filters backwards
    - Filter order: default → no-tools → user-only → labeled-only → all
  • Fix branch summarization abort handling and tree navigation
    - Check response.stopReason instead of catching errors for abort detection
    - Return result object from _generateBranchSummary instead of throwing
    - Fix summary attachment: attach to navigation target position, not old branch
    - Support root-level summaries (parentId=null) in branchWithSummary
    - Remove setTimeout hack for re-showing tree selector on abort
  • Fix tree selector gutter alignment, add page navigation, improve styling
    - Fix gutter/connector alignment by tracking gutter positions with GutterInfo
    - Convert recursive markContains to iterative to avoid stack overflow
    - Add left/right arrow keys for page up/down navigation
    - Consistent assistant message styling (green prefix, appropriate status colors)
    - Remove leaf marker (*), active path bullets are sufficient
    - Add Expandable interface for toggle expansion
    - Fix BranchSummaryMessageComponent expansion toggle