Commit Graph

340 Commits

  • Fix --no-skills flag not preventing skills from loading
    The --no-skills flag set options.skills = [] in main.ts, but the
    interactive mode UI would rediscover skills anyway because it called
    loadSkills() directly instead of using the already-loaded skills.
    
    Changes:
    - Add AgentSession.skills and AgentSession.skillWarnings properties
    - discoverSkills() now returns { skills, warnings } instead of Skill[]
    - Interactive mode uses session.skills instead of calling loadSkills()
    - Update SDK docs and examples for new return type
    
    Fixes #577
  • fix(coding-agent): --no-skills flag not preventing skills from loading (#577)
    The --no-skills flag set options.skills = [] in main.ts, but the interactive mode UI would rediscover skills anyway because it called loadSkills() directly.
    
    Changes:
    - Add AgentSession.skills and AgentSession.skillWarnings properties  
    - discoverSkills() now returns { skills, warnings } instead of Skill[]
    - Interactive mode uses session.skills instead of calling loadSkills()
    
    Co-authored-by: Carlos Villela <cv@lixo.org>
  • 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): add user_bash event and theme API extensions
    - user_bash event for intercepting ! and !! commands (#528)
    - Extensions can return { operations } or { result } to redirect/replace
    - executeBashWithOperations() for custom BashOperations execution
    - session.recordBashResult() for extensions handling bash themselves
    - Theme API: getAllThemes(), getTheme(), setTheme() on ctx.ui
    - mac-system-theme.ts example: sync with macOS dark/light mode
    - Updated ssh.ts to use user_bash event
  • fix(coding-agent): string systemPrompt now works as full replacement
    When passing a string systemPrompt to createAgentSession(), it is now
    used as-is without appending context files and skills. This matches the
    documented behavior: 'String replaces default, function receives default
    and returns final.'
    
    Previously, string systemPrompt would have context files and skills
    appended, causing duplication if they were already in the string.
    
    fixes #543
  • Allow extensions to modify system prompt in before_agent_start
    - Add systemPrompt to BeforeAgentStartEvent so extensions can see current prompt
    - Change systemPromptAppend to systemPrompt in BeforeAgentStartEventResult for full replacement
    - Extensions can now chain modifications (each sees the result of previous)
    - Update ssh.ts to replace local cwd with remote cwd in system prompt
    - Update pirate.ts, claude-rules.ts, preset.ts to use new API
    
    fixes #575
  • feat(coding-agent): add pluggable operations for remote tool execution
    Adds optional operations parameter to create*Tool functions enabling
    delegation to remote systems (SSH, containers, etc.):
    
    - ReadOperations: readFile, access, detectImageMimeType
    - WriteOperations: writeFile, mkdir
    - EditOperations: readFile, writeFile, access
    - BashOperations: exec (with streaming, signal, timeout)
    
    Add ssh.ts example demonstrating --ssh flag for remote execution.
    Built-in renderers used automatically for overrides without custom renderers.
    
    fixes #564
  • feat(coding-agent): add tool override support via extensions
    - Add setActiveTools() to ExtensionAPI for dynamic tool management
    - Extensions can now override, wrap, or disable built-in tools
    - Add tool-override.ts example demonstrating the pattern
    - Update documentation for tool override capabilities
  • Merge pull request #568 from tmustier/gemini-raw-stream
    fix: restore ESC interrupt after auto-retry and correct retry abort messaging
  • 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
  • fix: ESC key not interrupting during Working... state
    Three related fixes:
    
    1. google-gemini-cli: Handle abort signal in stream reading loop
       - Add abort event listener to cancel reader immediately when signal fires
       - Fix AbortError detection in retry catch block (fetch throws AbortError,
         not our custom message)
       - Swallow reader.cancel() rejection to avoid unhandled promise
    
    2. agent-session: Fix retry attempt counter showing 0 on cancel
       - abortRetry() was resetting _retryAttempt before the catch block could
         read it for the error message
    
    3. interactive-mode: Restore main escape handler on agent_start
       - When auto-retry starts, onEscape is replaced with retry-specific handler
       - auto_retry_end (which restores it) fires on turn_end, after streaming begins
       - Now restore immediately on agent_start if retry handler is still active
    
    Amended: suppress reader.cancel() rejection on abort.
  • feat(coding-agent): add --no-tools flag to disable built-in tools
    Add --no-tools flag that allows starting pi without any built-in tools,
    enabling extension-only tool setups (e.g., pi-ssh-remote).
    
    - Add --no-tools flag to CLI args parsing
    - Handle --tools '' (empty string) as equivalent to no tools
    - Fix system prompt to not show READ-ONLY mode when no tools (extensions may provide write capabilities)
    - Add tests for new flag and system prompt behavior
    
    fixes #555
  • refactor(coding-agent): unify tool and event handler context creation
    Tools now use ExtensionRunner.createContext() instead of a separate
    inline context factory. This ensures tools and event handlers share
    the same context, fixing ctx.shutdown() and other context methods.
    
    - Made ExtensionRunner.createContext() public
    - Changed wrapRegisteredTools to accept ExtensionRunner instead of getContext callback
    - Create ExtensionRunner when SDK custom tools are present (not just extensions)
    - Removed redundant inline context factory from sdk.ts
  • fix(coding-agent): make ctx.shutdown() work from extension tools
    The tool execution context was created with a no-op shutdown handler.
    Now it delegates to ExtensionRunner.shutdown() which uses the handler
    set by the mode via initialize().
  • Merge branch 'feat/custom-thinking-budgets'
    feat: add thinkingBudgets setting to customize token budgets per thinking level
    
    Allows users to override default token budgets for minimal/low/medium/high
    thinking levels via settings.json. Useful for token-based providers.
    
    closes #529
    
    Co-authored-by: Melih Mucuk <melih@monkeysteam.com>
  • refactor(coding-agent): simplify extension runtime architecture
    - Replace per-extension closures with shared ExtensionRuntime
    - Split context actions: ExtensionContextActions (required) + ExtensionCommandContextActions (optional)
    - Rename LoadedExtension to Extension, remove setter methods
    - Change runner.initialize() from options object to positional params
    - Derive hasUI from uiContext presence (no separate param)
    - Add warning when extensions override built-in tools
    - RPC and print modes now provide full command context actions
    
    BREAKING CHANGE: Extension system types and initialization API changed.
    See CHANGELOG.md for migration details.
  • fix: use defaultThinkingLevel from settings when enabledModels lacks explicit suffix (#540)
    When enabledModels is configured without thinking level suffixes (e.g.,
    'claude-opus-4-5' instead of 'claude-opus-4-5:high'), the scoped model's
    default 'off' thinking level was overriding defaultThinkingLevel from
    settings.
    
    Now thinkingLevel in ScopedModel is optional (undefined means 'not
    explicitly specified'). When passing to SDK, undefined values are filled
    with defaultThinkingLevel from settings.
  • 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
  • Merge pull request #513 from austinm911/fix/async-extension-factories
    feat(extensions): support async extension factory functions
  • fix: preserve externally-added settings when saving
    When a user edits settings.json while pi is running (e.g., adding
    enabledModels), those settings would be lost when pi saved other
    changes (e.g., changing thinking level via Shift+Tab).
    
    The fix re-reads the file before saving and merges the current file
    contents with in-memory changes, so external edits are preserved.
    
    Adds test coverage for SettingsManager.
  • 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.
  • Merge pull request #512 from nicobailon/feat/abort-signal-ui-dialogs
    Add AbortSignal support to extension UI dialogs
  • feat(extensions): support async extension factory functions
    Extensions can now use async initialization, enabling:
    - Dynamic imports (e.g., loading tools from external packages)
    - Async setup (config fetching, service connections)
    - Lazy-loaded dependencies
    
    Changes:
    - ExtensionFactory type now returns void | Promise<void>
    - loadExtensionFromFactory is now async, returns Promise<LoadedExtension>
    - All factory(api) calls are now awaited
    
    Backwards compatible: sync extensions continue to work unchanged.
  • Add ExtensionAPI methods, preset example, and TUI documentation improvements
    - ExtensionAPI: setModel(), getThinkingLevel(), setThinkingLevel() methods
    - New preset.ts example with plan/implement presets for model/thinking/tools switching
    - Export all UI components from pi-coding-agent for extension use
    - docs/tui.md: Common Patterns section with copy-paste code for SelectList, BorderedLoader, SettingsList, setStatus, setWidget, setFooter
    - docs/tui.md: Key Rules section for extension UI development
    - docs/extensions.md: Exhaustive example links for all ExtensionAPI methods and events
    - System prompt now references docs/tui.md for TUI development
    
    Fixes #509, relates to #347
  • Export truncation utilities for custom tools, add truncated-tool example
    - Export truncateHead, truncateTail, truncateLine, formatSize, DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES from package
    - Add examples/extensions/truncated-tool.ts showing proper output truncation with custom rendering
    - Document output truncation best practices in docs/extensions.md
  • 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
  • Extensions: add pi.sendUserMessage() for sending user messages
    Adds sendUserMessage() to the extension API, allowing extensions to send
    actual user messages (role: user) rather than custom messages. Unlike
    sendMessage(), this always triggers a turn and behaves as if the user
    typed the message.
    
    - Add SendUserMessageHandler type and sendUserMessage() to ExtensionAPI
    - Wire handler through loader, runner, and all modes
    - Implement via prompt() with expandPromptTemplates: false
    - Add send-user-message.ts example with /ask, /steer, /followup commands
    - Document in extensions.md
    
    fixes #483
  • Add ctx.ui.setFooter() for extensions to replace footer component
    Extensions can now replace the built-in footer with a custom component:
    - setFooter(factory) replaces with custom component
    - setFooter(undefined) restores built-in footer
    
    Includes example extension demonstrating context usage display.
    
    Closes #481
  • 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
  • feat(ai,agent,coding-agent): add sessionId for provider session-based caching
    - Add sessionId to StreamOptions for providers that support session-based caching
    - OpenAI Codex provider uses sessionId for prompt_cache_key and routing headers
    - Agent class now accepts and forwards sessionId to stream functions
    - coding-agent passes session ID from SessionManager and updates on session changes
    - Update ai package README with table of contents, OpenAI Codex OAuth docs, and env vars table
    - Increase Codex instructions cache TTL from 15 minutes to 24 hours
    - Add tests for sessionId forwarding in ai and agent packages
  • fix(coding-agent): improve bash tool error handling (#479)
    - Validate working directory exists before spawning to provide clear error message
    - Add spawn error handler to prevent uncaught exceptions when shell not found or cwd invalid
    - Add tests for both error scenarios
    
    Without these fixes, spawn errors (e.g., ENOENT from missing cwd or shell) would
    cause uncaught exceptions that crash the entire agent session instead of being
    returned as clean tool errors.
    
    Co-authored-by: robinwander <robinwander@users.noreply.github.com>
  • Expand configured extension directories from settings.json (#480)
    * Expand configured extension directories
    
    * Extract resolveExtensionEntries helper for directory resolution
    
    * Update CHANGELOG for extension directory resolution
  • feat: Add copy-link button to share viewer messages (#477)
    * feat: add copy-link button to share viewer messages
    
    Implements the feature requested in #437:
    
    - Add a small link icon button that appears on hovering over user/assistant
      messages in the share viewer
    - Clicking the button copies a shareable URL to clipboard with visual feedback
    - URL format: base?gistId&leafId=<active-leaf>&targetId=<message-id>
    - When loading a URL with leafId and targetId params:
      - Navigate to the specified leaf node
      - Scroll to and briefly highlight the target message
    
    This enables users to share links to specific messages within a session.
    
    * fix: preserve gist ID format and add clipboard fallback
    
    - Fix URL format to produce ?gistId&leafId=... instead of ?gistId=&leafId=...
      (preserves the bare key format expected by the backend)
    - Add execCommand fallback for clipboard copy on HTTP contexts where
      navigator.clipboard is unavailable
  • fix: clean up Codex thinking level handling
    - Remove per-thinking-level model variants (gpt-5.2-codex-high, etc.)
    - Remove thinkingLevels from Model type
    - Provider clamps reasoning effort internally
    - Omit reasoning field when thinking is off
    
    fixes #472