Commit graph

157 commits

Author SHA1 Message Date
Prateek Sunal
9b2aa4a683
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>
2026-01-01 21:35:37 +01:00
Mario Zechner
506e63a969 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
2026-01-01 00:25:04 +01:00
Mario Zechner
6f7c10e323 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
2026-01-01 00:04:56 +01:00
Mario Zechner
f0ab8db40f Expand pi.sendMessage and registerMessageRenderer docs in hooks.md
- sendMessage: document storage timing, LLM context, TUI display
- registerMessageRenderer: document renderer signature, return null for default
2025-12-31 14:34:30 +01:00
Mario Zechner
17ed3fa605 Update rpc.md to match actual implementation
- AppMessage -> AgentMessage
- compact response shows full CompactionResult fields
- auto_compaction_start includes reason field
- auto_compaction_end includes willRetry field
- Fix source file references
2025-12-31 13:53:45 +01:00
Mario Zechner
ee64d29487 Fix sdk.md and rpc.md to match actual API
- Remove incorrect prompt(AppMessage) overload
- Change AppMessage to AgentMessage
- Change null to undefined for optional returns
- sendHookMessage returns Promise<void>
- Update rpc.md for entryId change
2025-12-31 13:50:01 +01:00
Mario Zechner
8fb936853b Add sdk.md intro, update CHANGELOG for branch() change 2025-12-31 13:48:22 +01:00
Mario Zechner
8e1e99ca05 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)
2025-12-31 13:47:34 +01:00
Mario Zechner
027d39aa33 Update custom-compaction example to use serializeConversation
Also fix docs to show convertToLlm is needed first.
2025-12-31 13:24:23 +01:00
Mario Zechner
75269add96 Export serializeConversation and document in compaction.md
Shows how to convert messages to text for custom summarization.
2025-12-31 13:21:55 +01:00
Mario Zechner
84b663276d Add creation hints to docs and update system prompt
- System prompt now instructs to read docs AND examples, follow cross-refs
- Each doc starts with 'pi can create X. Ask it to build one.'
2025-12-31 13:16:44 +01:00
Mario Zechner
4a37760f17 Fix tui.md theme colors - add comprehensive list 2025-12-31 13:09:19 +01:00
Mario Zechner
feca0976eb Update tui.md theming section to show getMarkdownTheme usage 2025-12-31 13:06:52 +01:00
Mario Zechner
20fbf40fac Add tui.md and improve TUI documentation
- New tui.md covers component system for hooks and custom tools
- Update hooks.md intro with 'Key capabilities' highlighting UI
- Update custom-tools.md intro with 'Key capabilities' highlighting UI
- Reference tui.md from both docs
2025-12-31 13:05:59 +01:00
Mario Zechner
29e0ed9cd1 Improve hooks.md UI documentation
- Add 'Key capabilities' section highlighting UI features
- Expand ctx.ui docs with custom component details
- Reference snake.ts example for custom UI
2025-12-31 13:02:28 +01:00
Mario Zechner
88e39471ea Remove hook execution timeouts
- Remove timeout logic from HookRunner
- Remove hookTimeout from Settings interface
- Remove getHookTimeout/setHookTimeout methods
- Update CHANGELOG.md and hooks.md

Timeouts were inconsistently applied and caused issues with
legitimate slow operations (LLM calls, user prompts). Users can
use Ctrl+C to abort hung hooks.
2025-12-31 12:57:54 +01:00
Mario Zechner
bab343b8bc Update hooks.md: clarify session_before_tree, document all sessionManager methods 2025-12-31 12:44:52 +01:00
Mario Zechner
57b066f135 Add source file references to compaction.md and clarify session_before_tree behavior 2025-12-31 12:41:53 +01:00
Mario Zechner
d103af4ca2 Fix: cumulative file tracking applies to both compaction and branch summarization 2025-12-31 12:38:25 +01:00
Mario Zechner
67af9d707f Clarify that compaction/branch details are hook-customizable 2025-12-31 12:36:28 +01:00
Mario Zechner
dfc63a7bac Note settings.json for compaction settings in compaction.md 2025-12-31 12:35:45 +01:00
Mario Zechner
679343de55 Add compaction.md and rewrite hooks.md
- New compaction.md covers auto-compaction and branch summarization
- Explains cut points, split turns, data model, file tracking
- Documents session_before_compact and session_before_tree hooks

- Rewritten hooks.md matches actual API (separate event names)
- Correct ctx.ui.custom() signature (returns handle, not callback)
- Documents all session events including tree events
- Adds sessionManager and modelRegistry usage
- Updates all examples to use correct API
2025-12-31 12:33:13 +01:00
Mario Zechner
19c4182c21 Reorder execute params: (toolCallId, params, onUpdate, ctx, signal?)
Optional signal now at the end for cleaner API
2025-12-31 12:14:28 +01:00
Mario Zechner
4c9c453646 Update CHANGELOG, README, and custom-tools.md for new CustomTool API
- Add custom tools API rework to CHANGELOG breaking changes
- Update docs/custom-tools.md with new types and signatures
- Update README quick example with correct execute signature
2025-12-31 12:10:37 +01:00
Mario Zechner
ff78ac2f84 Replace custom tool dispose() with shutdown session event
Breaking change: CustomAgentTool.dispose() removed. Use onSession with
reason 'shutdown' instead for cleanup.

- Add 'shutdown' to SessionEvent.reason for custom tools
- Remove dispose() method from CustomAgentTool interface
- Make emitToolSessionEvent() public on AgentSession
- Emit shutdown event to tools in InteractiveMode.shutdown()
- Update custom-tools.md with new API and examples
2025-12-31 02:55:45 +01:00
Mario Zechner
450d77fb79 Update hooks.md and session.md for consolidated HookContext
- HookEventContext renamed to HookContext (used for events and commands)
- RegisteredCommand.handler: (ctx) -> (args, ctx)
- before_compact: previousCompactions -> branchEntries, model moved to ctx.model
- ctx.exec -> pi.exec in examples
- ctx.sessionFile -> ctx.sessionManager.getSessionFile()
- CompactionPreparation: document turnPrefixMessages, isSplitTurn, previousSummary
- session.md: clarify details field for compaction/branch summary
2025-12-31 02:40:31 +01:00
Mario Zechner
d36e0ea2ab Update SDK and RPC docs, remove outdated files
- Remove hooks-v2.md, session-tree.md, UNRELEASED_OLD.md
- sdk.md: Update hook API (sendMessage, appendEntry, registerCommand, etc.)
- sdk.md: Update SessionManager with tree API
- sdk.md: Update AgentSession interface
- rpc.md: Fix attachments -> images in prompt command
2025-12-31 00:46:52 +01:00
Mario Zechner
a9479458ee Update CHANGELOG.md and docs for session tree release
CHANGELOG.md:
- Add /tree command, context event, before_agent_start event
- Add ui.custom(), branch summarization, selectedBg theme color
- Add snake game example hook
- Add external contributions: CRLF fix, bash on Unix, clickable OAuth, error messages
- Update theme requirements (50 total colors)

session.md:
- Complete rewrite for v2 tree structure
- Document all entry types with examples
- Add SessionManager API reference

hooks.md:
- Replace pi.send() with pi.sendMessage()
- Add pi.appendEntry(), pi.registerCommand(), pi.registerMessageRenderer()
- Move exec() from ctx to pi.exec()
- Add ui.custom() for custom TUI components
- Add context and before_agent_start events
- Update before_compact event fields
- Add ctx.sessionManager and ctx.modelRegistry
2025-12-31 00:39:20 +01:00
Mario Zechner
c0bf7800d9 Update session-tree-plan.md: tree selector details, theme.md done, add Before Release section 2025-12-30 22:42:25 +01:00
Mario Zechner
ae351257b6 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)
2025-12-30 22:42:25 +01:00
Mario Zechner
e7d438b59d Mark tree selector improvements as complete in plan 2025-12-30 22:42:25 +01:00
Mario Zechner
04ce66951e Add tree selector improvement notes to plan 2025-12-30 22:42:25 +01:00
Mario Zechner
4a9c53347e Update session-tree-plan.md with completed items
- Branch Summary Design: complete with fromId, fromHook, details fields
- Entry Labels: UI display and /label command complete in tree-selector
- UI Commands: /branch and /tree complete
2025-12-30 22:42:24 +01:00
Mario Zechner
4958271dd3 feat(coding-agent): implement /tree command for session tree navigation
- Add TreeSelectorComponent with ASCII tree visualization
- Add AgentSession.navigateTree() for switching branches
- Add session_before_tree/session_tree hook events
- Add SessionManager.resetLeaf() for navigating to root
- Change leafId from string to string|null for consistency with parentId
- Support optional branch summarization when switching
- Update buildSessionContext() to handle null leafId
- Add /tree to slash commands in interactive mode
2025-12-30 22:42:22 +01:00
Mario Zechner
59ce62bffc Tree spec 2025-12-30 22:42:22 +01:00
Mario Zechner
f43969b31a Update plan: mark before_agent_start as complete 2025-12-30 22:42:22 +01:00
Mario Zechner
bbdc350394 Add reference to #330 (Dynamic Context Pruning) in plan
Documents why context event was added and notes the type
inconsistency between ContextEvent (AgentMessage[]) and
ContextEventResult (Message[])
2025-12-30 22:42:22 +01:00
Mario Zechner
ae614f93e3 Add investigation item for context event vs before_agent_start
Reference: #324

Documents:
- Current context event behavior (AgentMessage[], transient)
- Proposed before_agent_start event (persistent, TUI visible)
- Key differences table
- Open design questions
- Need to verify AgentMessage vs Message abstraction level
2025-12-30 22:42:22 +01:00
Mario Zechner
1721bb8398 Mark Hook API Changes as complete in plan 2025-12-30 22:42:21 +01:00
Mario Zechner
204d27581b Cleanup: unify HookMessage naming and simplify SessionContext
- Rename HookAppMessage to HookMessage, isHookAppMessage to isHookMessage
- Remove entries array from SessionContext (use isHookMessage type guard instead)
- HookMessage.content now accepts string directly (not just array)
- Fix streamMessage type in AgentState (AppMessage, not Message)
- Rename CustomMessageComponent to HookMessageComponent
- Fix test hook to use pi.sendMessage
2025-12-30 22:42:20 +01:00
Mario Zechner
77fe3f1a13 Add context event for non-destructive message modification before LLM calls
- Add contextTransform option to Agent (runs before messageTransformer)
- Deep copy messages before passing to contextTransform (modifications are ephemeral)
- Add ContextEvent and ContextEventResult types
- Add emitContext() to HookRunner (chains multiple handlers)
- Wire up in sdk.ts when creating Agent with hooks

Enables dynamic context pruning: hooks can modify messages sent to LLM
without changing session data. See discussion #330.
2025-12-30 22:42:20 +01:00
Mario Zechner
9e165d1d81 Add context event TODO with dynamic context pruning example
Reference: https://github.com/badlogic/pi-mono/discussions/330
2025-12-30 22:42:20 +01:00
Mario Zechner
e25aef0594 Update plan: move exec to HookAPI, sessionManager/modelRegistry to contexts
- exec() moves from HookEventContext/HookCommandContext to HookAPI
- sessionManager/modelRegistry move from SessionEventBase to HookEventContext
- HookCommandContext keeps sessionManager/modelRegistry (command handlers need them)
- Both sendMessage and exec accessed via pi closure in command handlers
2025-12-30 22:42:19 +01:00
Mario Zechner
09e7e9196c Update plan: HookCommandContext without sendMessage (use pi closure) 2025-12-30 22:42:19 +01:00
Mario Zechner
60130a4c53 Expand documentation and examples sections in session-tree plan 2025-12-30 22:42:19 +01:00
Mario Zechner
ccfa1ac3bb Add documentation tasks to session-tree plan 2025-12-30 22:42:19 +01:00
Mario Zechner
30cd723411 Hook commands: remove string return, use sendMessage() for prompting
- Command handler now returns Promise<void> instead of Promise<string | undefined>
- To trigger LLM response, use sendMessage() with triggerTurn: true
- Simplify _tryExecuteHookCommand to return boolean

Added example hook and slash command in .pi/:
- .pi/hooks/test-command.ts - /greet command using sendMessage
- .pi/commands/review.md - file-based /review command
2025-12-30 22:42:18 +01:00
Mario Zechner
c8d9382aaa Move hook command execution to AgentSession.prompt()
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
2025-12-30 22:42:18 +01:00
Mario Zechner
ba185b0571 Hook API: replace send() with sendMessage(), add appendEntry() and registerCommand()
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
2025-12-30 22:42:18 +01:00
Mario Zechner
3ecaaa5937 Fix CustomMessageEntry content type to match UserMessage
content: string | (TextContent | ImageContent)[]

This matches the UserMessage type from pi-ai, so content can be
passed directly to AppMessage without conversion.
2025-12-30 22:42:18 +01:00