Commit graph

752 commits

Author SHA1 Message Date
Helmut Januschka
ce88ebcd68 feat(hooks): add setWidgetComponent for custom TUI components
- New ctx.ui.setWidgetComponent(key, factory) method
- Allows custom Component to render as widget without taking focus
- Unlike custom(), widget components render inline above editor
- Components are disposed when cleared or replaced
- Falls back to no-op in RPC/print modes
2026-01-04 18:13:29 +01:00
Helmut Januschka
9b53b89bd5 fix(widgets): add max line limit and document multi-hook behavior
- Limit total widget lines to 10 to prevent viewport overflow/flicker
- Show '... (widget truncated)' when limit exceeded
- Document that multiple hooks stack widgets vertically
- Add caution about keeping widgets small
2026-01-04 18:13:29 +01:00
Helmut Januschka
4ecf3f9422 refactor(hooks): address PR feedback
- Rename getTools/setTools to getActiveTools/setActiveTools
- Add getAllTools to enumerate all configured tools
- Remove text_delta event (use turn_end/agent_end instead)
- Add shortcut conflict detection:
  - Skip shortcuts that conflict with built-in shortcuts (with warning)
  - Log warnings when hooks register same shortcut (last wins)
- Add note about prompt cache invalidation in setActiveTools
- Update plan-mode hook to use agent_end for [DONE:id] parsing
2026-01-04 18:13:29 +01:00
Helmut Januschka
d1eea3ac4e feat(hooks): add text_delta event for streaming text monitoring
- New text_delta hook event fires for each chunk of streaming text
- Enables real-time monitoring of agent output
- Plan-mode hook now updates todo progress as [DONE:id] tags stream in
- Each todo item has unique ID for reliable tracking
2026-01-04 18:13:28 +01:00
Helmut Januschka
dc44816051 feat(hooks): add setWidget API for multi-line status displays
- ctx.ui.setWidget(key, lines) for multi-line displays above editor
- Widgets appear below 'Working...' indicator, above editor
- Supports ANSI styling including strikethrough
- Added theme.strikethrough() method
- Plan-mode hook now shows todo list with checkboxes
- Completed items show checked box and strikethrough text
2026-01-04 18:13:28 +01:00
Helmut Januschka
056f40b00b feat(coding-agent): show hook shortcuts in /hotkeys command 2026-01-04 18:13:28 +01:00
Helmut Januschka
c956a726ed 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
2026-01-04 18:13:28 +01:00
Helmut Januschka
059292ead1 WIP: Add hook API for dynamic tool control with plan-mode hook example
- Add pi.getTools() and pi.setTools(toolNames) to HookAPI
- Hooks can now enable/disable tools dynamically
- Changes take effect on next agent turn

New example hook: plan-mode.ts
- Claude Code-style read-only exploration mode
- /plan command toggles plan mode on/off
- Plan mode tools: read, bash, grep, find, ls
- Edit/write tools disabled in plan mode
- Injects context telling agent about restrictions
- After each response, prompts to execute/stay/refine
- State persists across sessions
2026-01-04 18:13:28 +01:00
Armin Ronacher
5b95ccf830
Add consistent, configurable image placeholders (#442)
* Add consistent, configurable image placeholders

* Kill the placeholders
2026-01-04 18:12:55 +01:00
Aliou Diallo
0d477d39f9
fix(tui): expand paste markers when opening external editor (#444)
* fix(tui): expand paste markers when opening external editor

Add getExpandedText() method to Editor that substitutes paste markers
with actual content. Use it in Ctrl-G external editor flow so users
see full pasted content instead of [paste #N ...] placeholders.

* docs: add changelog entries for #444
2026-01-04 18:11:42 +01:00
Can Bölük
6ddfd1be13
fix(coding-agent): resolved UTF-8 corruption in bash executor output (#433)
- Fixed UTF-8 text corruption in bash executor by replacing Buffer.toString() with streaming TextDecoder.
2026-01-04 03:15:50 +01:00
Mario Zechner
5c5084481b feat(coding-agent): clipboard image paste support via Ctrl+V (fixes #419) 2026-01-04 01:05:22 +01:00
Mario Zechner
f49d2aac12 Use same header color for Available Tools as System Prompt 2026-01-03 23:05:32 +01:00
Mario Zechner
f9838bb5d4 Show first 10 lines of system prompt with click to expand for full content 2026-01-03 23:04:23 +01:00
Mario Zechner
f5e38c4007 Add click-to-expand for system prompt in HTML export 2026-01-03 23:02:30 +01:00
Mario Zechner
f090ec214a Fix missing spacer between text and tool calls in HTML export 2026-01-03 23:00:35 +01:00
Mario Zechner
e98524f1fc Fix missing spacer between text and tool calls in HTML export 2026-01-03 22:56:36 +01:00
Mario Zechner
f2b89d5ec5 Merge branch 'feat/ctrl-n-external-editor' - configurable keybindings (#405) 2026-01-03 22:51:12 +01:00
Ben Vargas
8f5466f42a
feat(coding-agent): add /quit and /exit slash commands to exit (#426)
Add new slash commands for gracefully exiting the interactive mode:
- /quit - exit the application
- /exit - alias for /quit (common CLI convention)

Both commands await shutdown() which emits session_shutdown events
to hooks and custom tools before exiting. Unlike Ctrl+C (twice) which
uses void (fire-and-forget), these commands properly wait for hooks
and tools to complete their shutdown handlers.
2026-01-03 22:38:55 +01:00
Mario Zechner
79c56475e0 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.
2026-01-03 16:58:57 +01:00
Evgeniy Skuridin
9b0ec02405
Fix version check URL typo (#423) 2026-01-03 16:55:38 +01:00
Armin Ronacher
69dc6b0788
More attempts to get an image under 5MB (#424) 2026-01-03 16:54:57 +01:00
Mario Zechner
e9cf3c1835 Fix slash commands and hook commands during streaming
- Hook commands now execute immediately during streaming (they manage their own LLM interaction via pi.sendMessage())
- File-based slash commands are expanded and queued via steer/followUp during streaming
- prompt() accepts new streamingBehavior option ('steer' or 'followUp') for explicit queueing during streaming
- steer() and followUp() now expand file-based slash commands and error on hook commands
- RPC prompt command accepts optional streamingBehavior field
- Updated docs: rpc.md, sdk.md, CHANGELOG.md

fixes #420
2026-01-03 15:36:54 +01:00
Helmut Januschka
f79256ac3b fix: update /hotkeys and startup hints to use configured keybindings
Both the startup instructions and /hotkeys command now display the
actual configured keybindings from keybindings.json instead of
hardcoded defaults.
2026-01-03 15:01:26 +01:00
Evgeniy Skuridin
8917a1f853
feat(coding-agent): add $ARGUMENTS syntax for slash commands (#418)
* feat(coding-agent): add $ARGUMENTS syntax for slash commands

* test(coding-agent): add tests for slash command argument substitution
2026-01-03 14:08:39 +01:00
cursive
9e3b1408f3
Copy OAuth login URL to clipboard for mobile SSH users (#415) 2026-01-03 09:43:25 +01:00
Helmut Januschka
7574fed2f2 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
2026-01-03 08:23:56 +01:00
Helmut Januschka
8f2682578b 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"
}
2026-01-03 08:23:56 +01:00
Mario Zechner
0f81b09625 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.
2026-01-03 04:23:59 +01:00
Mario Zechner
746ec9eb01 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
2026-01-03 04:14:35 +01:00
Mario Zechner
97af788344 Show 'In-memory' instead of 'File: undefined' for --no-session mode 2026-01-03 02:01:30 +01:00
Mario Zechner
42b1e06ad1 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
2026-01-03 01:59:08 +01:00
Mario Zechner
17b3a14bfa Fix slow /model selector by deferring OAuth token refresh
getAvailable() now uses hasAuth() which checks if auth is configured
without triggering OAuth token refresh. Refresh happens later when
the model is actually used.
2026-01-03 01:20:11 +01:00
Anton Kuzmenko
214e7dae15 Add Vertex AI provider with ADC support
- Implement google-vertex provider in packages/ai
- Support ADC (Application Default Credentials) via @google/generative-ai
- Add Gemini model catalog for Vertex AI
- Update packages/coding-agent to handle google-vertex provider
2026-01-03 01:11:03 +01:00
Mario Zechner
d747ec6e23 Enhance provider override to support baseUrl-only mode
Builds on #406 to support simpler proxy use case:
- Override just baseUrl to route built-in provider through proxy
- All built-in models preserved, no need to redefine them
- Full replacement still works when models array is provided
2026-01-03 01:06:08 +01:00
Yevhen Bobrov
243104fa18
Allow models.json to override built-in providers (#406)
* Allow models.json to override built-in providers

When a provider is defined in models.json with the same name as a
built-in provider (e.g., 'anthropic', 'google'), the built-in models
for that provider are completely replaced by the custom definition.

This enables users to:
- Use custom base URLs (proxies, self-hosted endpoints)
- Define a subset of models they want available
- Customize model configurations for built-in providers

Example usage in ~/.pi/agent/models.json:
{
  "providers": {
    "anthropic": {
      "baseUrl": "https://my-proxy.example.com/v1",
      "apiKey": "ANTHROPIC_API_KEY",
      "api": "anthropic-messages",
      "models": [...]
    }
  }
}

* Refactor model-registry for readability

- Extract CustomModelsResult type and emptyCustomModelsResult helper
- Extract loadBuiltInModels method with clear skip logic
- Simplify loadModels with destructuring and ternary
- Reduce repetition in error handling paths

* Refactor model-registry tests for readability

- Extract providerConfig() helper to hide irrelevant model fields
- Extract writeModelsJson() helper for file writing
- Extract getModelsForProvider() helper for filtering
- Move modelsJsonPath to beforeEach

Reduces test file from 262 to 130 lines while maintaining same coverage.
2026-01-03 00:59:59 +01:00
Mario Zechner
28fb502719 Add image auto-resize toggle to settings, changelog for #402 2026-01-03 00:42:02 +01:00
Mario Zechner
e82af9da47
Merge pull request #402 from mitsuhiko/image-resize
Added automatic image resizing
2026-01-03 00:39:26 +01:00
Mario Zechner
9f2e6ac5eb 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
2026-01-03 00:19:07 +01:00
Mario Zechner
8c227052d3 fix(coding-agent): export Theme and ThemeColor for hooks to use proper types 2026-01-03 00:13:26 +01:00
Mario Zechner
9d8230dfc6 feat(coding-agent): expose deliverAs option in hook sendMessage() API
- pi.sendMessage(msg, options?) now accepts { triggerTurn?, deliverAs? }
- deliverAs: 'steer' (default) or 'followUp' controls delivery timing
- Update all mode handlers to pass options through
- Update file-trigger example to use new API
- Update CHANGELOG
2026-01-03 00:13:26 +01:00
Mario Zechner
3ae02a6849 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
2026-01-03 00:13:25 +01:00
Mario Zechner
58c423ba36 feat(coding-agent): update AgentSession for steer()/followUp() API
- Rename queueMessage to steer(), add followUp()
- Split _pendingMessages into _steeringMessages and _followUpMessages
- Update sendHookMessage to accept deliverAs option
- Rename hasQueuedMessages to hasPendingMessages
- Rename queuedMessageCount to pendingMessageCount
- Update clearQueue() return type to { steering, followUp }
- Update UI to show steering vs follow-up messages differently

WIP: settings-manager, sdk, interactive-mode, rpc-mode still need updates
2026-01-03 00:13:25 +01:00
Armin Ronacher
345fa975f1
Handle ctrlc like escape in selectors (#400)
Cheers @nicokosi
2026-01-02 22:43:39 +01:00
Mario Zechner
5ef3cc90d1 Add guard against concurrent prompt() calls
Agent.prompt() and Agent.continue() now throw if called while already
streaming, preventing race conditions and corrupted state. Use
queueMessage() to queue messages during streaming, or await the
previous call.

AgentSession.prompt() has the same guard with a message directing
users to queueMessage().

Ref #403
2026-01-02 22:02:24 +01:00
Kao Félix
5c3c8e6f7e
Add terminal title support to TUI framework (#407)
Add setTitle() method to Terminal interface for setting window title.
Uses standard OSC escape sequence \x1b]0;...\x07 for broad terminal
compatibility (macOS Terminal, iTerm2, Kitty, WezTerm, Ghostty, etc.).

Changes:
- Add setTitle(title: string) to Terminal interface
- Implement in ProcessTerminal using OSC sequence
- Implement no-op in VirtualTerminal for testing
- Use in interactive mode to set title as "pi - <dirname>"
2026-01-02 22:00:34 +01:00
Armin Ronacher
4a32af2532 Added automatic image resizing 2026-01-02 12:01:56 +01:00
Mario Zechner
c10d99d2de fix: export type guard functions at runtime, fixes #397 2026-01-02 10:37:28 +01:00
Armin Ronacher
209d95870e
Fix arrow key in model selector prior to model loading (#398) 2026-01-02 10:31:48 +01:00
Mario Zechner
d9adf659ca Fix edit tool failing on files with UTF-8 BOM
Strip BOM before matching (LLM won't include invisible BOM in oldText),
restore on write.

Based on #394 by @prathamdby
2026-01-02 01:57:24 +01:00