- 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
- 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
Major changes:
- Replace monolithic SessionEvent with reason discriminator with individual
event types: session_start, session_before_switch, session_switch,
session_before_new, session_new, session_before_branch, session_branch,
session_before_compact, session_compact, session_shutdown
- Each event has dedicated result type (SessionBeforeSwitchResult, etc.)
- HookHandler type now allows bare return statements (void in return type)
- HookAPI.on() has proper overloads for each event with correct typing
Additional fixes:
- AgentSession now always subscribes to agent in constructor (was only
subscribing when external subscribe() called, breaking internal handlers)
- Standardize on undefined over null throughout codebase
- HookUIContext methods return undefined instead of null
- SessionManager methods return undefined instead of null
- Simplify hook exports to 'export type * from types.js'
- Add detailed JSDoc for skipConversationRestore vs cancel
- Fix createBranchedSession to rebuild index in persist mode
- newSession() now returns the session file path
Updated all example hooks, tests, and emission sites to use new event types.
- Removed Attachment from agent package (now in web-ui/coding-agent)
- Agent.prompt now takes (text, images?: ImageContent[])
- Removed transports from web-ui (duplicate of agent package)
- Updated coding-agent to use local message types
- Updated mom package for new agent API
Remaining: Fix AgentInterface.ts to compose UserMessageWithAttachments
Hook commands registered via pi.registerCommand() are now handled in
AgentSession.prompt() alongside file-based slash commands. This:
- Removes duplicate tryHandleHookCommand from interactive-mode and rpc-mode
- All modes (interactive, RPC, print) share the same command handling logic
- AgentSession._tryExecuteHookCommand() builds CommandContext using:
- UI context from hookRunner (set by mode)
- sessionManager, modelRegistry from AgentSession
- sendMessage via sendHookMessage
- exec via exported execCommand
- Handler returning string uses it as prompt, undefined returns early
Also:
- Export execCommand from hooks/runner.ts
- Add getUIContext() and getHasUI() to HookRunner
- Make HookRunner.emitError() public for error reporting
Breaking changes to Hook API:
- pi.send(text, attachments?) replaced with pi.sendMessage(message, triggerTurn?)
- Creates CustomMessageEntry instead of user messages
- Properly handles queuing during streaming via agent loop
- Supports optional turn triggering when idle
- New pi.appendEntry(customType, data?) for hook state persistence
- New pi.registerCommand(name, options) for custom slash commands
- Handler types renamed: SendHandler -> SendMessageHandler, new AppendEntryHandler
Implementation:
- AgentSession.sendHookMessage() handles all three cases:
- Streaming: queues message with _hookData marker, agent loop processes it
- Not streaming + triggerTurn: appends to state/session, calls agent.continue()
- Not streaming + no trigger: appends to state/session only
- message_end handler routes based on _hookData presence to correct persistence
- HookRunner gains getRegisteredCommands() and getCommand() methods
New types: HookMessage<T>, RegisteredCommand, CommandContext
- Merge branch event into session with before_branch/branch reasons
- Add before_switch, before_clear, shutdown reasons
- before_* events can be cancelled with { cancel: true }
- Update RPC commands to return cancelled status
- Add shutdown event on process exit
- New example hooks: confirm-destructive, dirty-repo-guard, auto-commit-on-exit
fixes#278
- Custom tools: TypeScript modules that extend pi with new tools
- Custom TUI rendering via renderCall/renderResult
- User interaction via pi.ui (select, confirm, input, notify)
- Session lifecycle via onSession callback for state reconstruction
- Examples: todo.ts, question.ts, hello.ts
- Hook examples: permission-gate, git-checkpoint, protected-paths
- Session lifecycle centralized in AgentSession
- Works across all modes (interactive, print, RPC)
- Unified session event for hooks (replaces session_start/session_switch)
- Box component added to pi-tui
- Examples bundled in npm and binary releases
Fixes#190
- Add agentLoopContinue() to pi-ai for resuming from existing context
- Add Agent.continue() method and transport.continue() interface
- Simplify AgentSession compaction to two cases: overflow (auto-retry) and threshold (no retry)
- Remove proactive mid-turn compaction abort
- Merge turn prefix summary into main summary
- Add isCompacting property to AgentSession and RPC state
- Block input during compaction in interactive mode
- Show compaction count on session resume
- Rename RPC.md to rpc.md for consistency
Related to #128
- Move RPC files to modes/rpc/ directory
- Add properly typed RpcCommand and RpcResponse types
- Expose full AgentSession API via RPC commands:
- State: get_state
- Model: set_model, cycle_model, get_available_models
- Thinking: set_thinking_level, cycle_thinking_level
- Queue: set_queue_mode
- Compaction: compact, set_auto_compaction
- Bash: bash, abort_bash
- Session: get_session_stats, export_html, switch_session, branch, etc.
- Add RpcClient class for programmatic access
- Rewrite tests to use RpcClient instead of raw process spawning
- All commands support optional correlation ID for request/response matching