Commit graph

74 commits

Author SHA1 Message Date
Mario Zechner
dea7067593 style: format context file list on separate lines 2025-11-12 22:21:14 +01:00
Mario Zechner
b1c2c32e23 refactor: move context files to system prompt instead of user messages
- Context files now appended to system prompt
- Added current date/time to system prompt
- Added current working directory to system prompt
- Date/time and cwd placed at end of system prompt
- Updated README to reflect system prompt integration
2025-11-12 22:19:56 +01:00
Mario Zechner
dca3e1cc60 feat: hierarchical context file loading for monorepos
- Walk up parent directories to load all AGENT.md/CLAUDE.md files
- Load global context from ~/.pi/agent/AGENT.md or CLAUDE.md
- Load order: global → top-most parent → ... → cwd
- Prefer AGENT.md over CLAUDE.md in each directory
- Each context file injected as separate message
- Updated README with detailed documentation
2025-11-12 22:17:54 +01:00
Mario Zechner
812f2f43cd feat: defer session creation until first user+assistant message exchange
- Sessions are no longer created immediately on startup
- Session files only created after at least 1 user message and 1 assistant response
- Prevents empty session files when agent is launched and immediately quit
- Messages are queued until session is initialized
- Continue/resume modes properly mark sessions as already initialized
2025-11-12 22:06:02 +01:00
Mario Zechner
5e988b444b Remove event logging from session files - only save messages and state changes
Session reconstruction only needs:
- type: 'session' - session metadata
- type: 'message' - conversation history
- type: 'thinking_level_change' - thinking level changes
- type: 'model_change' - model changes

Events like agent_start/end, tool_execution_start/end are not needed for
session reconstruction and only added bloat. This reduces session file size
significantly and speeds up writes.
2025-11-12 21:56:29 +01:00
Mario Zechner
9e3e319f1a Add session export to HTML, improve tool error handling, and enhance RPC mode documentation 2025-11-12 21:55:10 +01:00
Mario Zechner
68092ccf01 Add --mode flag for CLI output control (text/json/rpc)
- text mode: only outputs final assistant message text (default)
- json mode: streams all events as JSON (same as session manager writes)
- rpc mode: JSON output + listens for JSON input on stdin for headless operation
- Suppress informational messages in json/rpc modes
2025-11-12 20:33:31 +01:00
Mario Zechner
c75f53f6f2 Improve edit tool diff display with context-aware rendering
- Add generateDiffString() function in edit tool to create unified diffs with line numbers and 4 lines of context
- Store only the formatted diff string in tool result details instead of full file contents
- Update tool-execution renderer to parse and colorize the diff string
- Filter out message_update events from session saving to prevent verbose session files
- Add markdown nested list and table rendering tests
2025-11-12 20:09:11 +01:00
Mario Zechner
2f0f0a913e Add proper truncation notices and comprehensive tests for read tool
**Improved output messages:**
1. File fits within limits: Just outputs content (no notices)
2. Lines get truncated: Shows "Some lines were truncated to 2000 characters for display"
3. File doesn't fit limit: Shows "N more lines not shown. Use offset=X to continue reading"
4. Offset beyond file: Shows "Error: Offset X is beyond end of file (N lines total)"
5. Both truncations: Combines both notices with ". " separator

**Comprehensive test coverage:**
- Files within limits (no notices)
- Large files (line truncation)
- Long lines (character truncation)
- Offset parameter
- Limit parameter
- Offset + limit together
- Invalid offset (out of bounds)
- Combined truncations (both notices)

All 17 tests passing ✓
2025-11-12 17:13:03 +01:00
Mario Zechner
c7a73d4f81 Add line limits and truncation to read tool
- Default limit of 2000 lines per read
- Maximum line length of 2000 characters (truncates longer lines)
- Add optional offset and limit parameters for pagination
- Show truncation notice with instruction to continue reading
- Plain text output (no line numbers)

Examples:
- `read path/to/file` - reads first 2000 lines
- `read path/to/file offset=2001` - continues from line 2001
- `read path/to/file limit=100` - reads only 100 lines

This prevents extremely large files from overwhelming context.
2025-11-12 16:53:05 +01:00
Mario Zechner
bb0b77af16 Match export output style to thinking level display
Changed export success/error messages to match the style used for thinking level changes:
- Use Spacer(1) instead of empty Text for proper blank line spacing
- Use chalk.dim() for success message instead of chalk.green()
- Add left padding (1, 0) to match other system messages
- Removed checkmark/x symbols for cleaner look

Now "Session exported to: filename.html" appears dimmed with proper spacing, just like "Thinking level: off"
2025-11-12 16:45:51 +01:00
Mario Zechner
5cab91f839 Make HTML export header minimal and stack info vertically
**Header improvements:**
- Changed title from "pi coding-agent session" to "pi v{version}"
- Smaller, more compact header (16px instead of 20px)
- Info items now stack vertically with consistent labels (80px width)
- Reduced padding and spacing for cleaner look
- Labels aligned to left, values aligned to baseline

The header is now much less cramped and easier to read.
2025-11-12 16:35:06 +01:00
Mario Zechner
1b81d803bf Add click-to-expand and system prompt display to HTML export
**Click-to-expand functionality:**
- Truncated tool outputs are now clickable to show full content
- Works for bash (>5 lines), read (>10 lines), write (>10 lines)
- Displays "... (N more lines) - click to expand" hint in cyan
- Smooth toggle between preview and full output
- Cursor changes to pointer on hover

**System prompt and tools display:**
- Added system prompt section with yellow header on dark brownish background
- Shows all available tools with names and descriptions
- Both sections appear before messages for context
- Subtle yellow/brown theme (rgb(60, 55, 40)) that's not too bright

The HTML export now provides better interactivity for large outputs and gives full context about the agent's configuration.
2025-11-12 16:32:20 +01:00
Mario Zechner
6b496e006e Rewrite HTML export to match TUI visual style exactly
Complete overhaul of export-html.ts to replicate the TUI renderer's visual design:

**Exact TUI color matching:**
- User messages: rgb(52, 53, 65) dark slate background
- Tool pending: rgb(40, 40, 50) dark blue-gray
- Tool success: rgb(40, 50, 40) dark green
- Tool error: rgb(60, 40, 40) dark red
- Body background: rgb(24, 24, 30) very dark
- Text colors matching chalk: cyan for paths, dimmed gray for output

**Tool formatting (matching ToolExecutionComponent):**
- bash: Bold `$ command`, dimmed output (max 5 lines)
- write: Bold header with cyan path, line count, content preview (max 10 lines)
- read: Bold header with cyan path, content preview (max 10 lines)
- edit: Bold header with cyan path, unified diff with line numbers
- All tools show "... (N more lines)" indicators

**Additional improvements:**
- Use session filename + .html for default output
- Shorten paths with tilde notation (~)
- Replace tabs with 3 spaces
- Monospace font matching terminal aesthetic
- Minimal, clean design with no borders/boxes
- Print-friendly styles

The HTML export now looks identical to the TUI version.
2025-11-12 16:27:12 +01:00
Mario Zechner
e467a80b5b Add /export command to export sessions as self-contained HTML
- Add exportSessionToHtml function that generates beautifully formatted HTML exports
- HTML includes session metadata, all messages, tool calls, tool results, thinking blocks, and images
- Support for ANSI color codes in tool output (converted to HTML)
- Self-contained with inline CSS (dark theme, responsive design, print-friendly)
- Add /export slash command to TUI with optional filename parameter
- Add agent and coding-agent to dev script for watch mode
- Increment coding-agent version to 0.6.1

Usage: /export [optional-filename.html]
2025-11-12 16:21:59 +01:00
Mario Zechner
09564f2940 Update coding-agent dependencies to 0.6.0 2025-11-12 14:36:59 +01:00
Mario Zechner
bf1a7d8571 Add 'pi' command alias and fix getApiKey import 2025-11-12 14:31:25 +01:00
Mario Zechner
00d8286523 Handle FinishReason.NO_IMAGE and fix optional chaining
- Add NO_IMAGE to error finish reasons in Google provider
- Fix non-null assertion after optional chaining in Anthropic provider
- Migrate biome config to 2.3.5
- Ignore Tailwind CSS file from biome checks
- Bump all packages to version 0.6.0
2025-11-12 10:58:03 +01:00
Mario Zechner
f147109da7 Fix coding agent tools to return error content instead of throwing
Tools now resolve with error messages in content blocks rather than
rejecting the promise. This matches the expected behavior where tools
always return a result, with errors indicated in the text content.

- read: Return error content for missing files
- edit: Return error content for missing files, text not found, multiple matches
- bash: Return error content for command failures, timeouts, and aborts
- All tools now include required details field in error results
2025-11-12 10:52:12 +01:00
Mario Zechner
84dcab219b Add image support in tool results across all providers
Tool results now use content blocks and can include both text and images.
All providers (Anthropic, Google, OpenAI Completions, OpenAI Responses)
correctly pass images from tool results to LLMs.

- Update ToolResultMessage type to use content blocks
- Add placeholder text for image-only tool results in Google/Anthropic
- OpenAI providers send tool result + follow-up user message with images
- Fix Anthropic JSON parsing for empty tool arguments
- Add comprehensive tests for image-only and text+image tool results
- Update README with tool result content blocks API
2025-11-12 10:45:56 +01:00
Mario Zechner
9dac37d836 Search through all messages in session, not just first message
- SessionManager now collects text from all user and assistant messages
- Added allMessagesText field containing concatenated message text
- Search now matches against all messages in a session
- More powerful session discovery (e.g., search "write file" finds any session discussing file writing)
2025-11-12 09:32:14 +01:00
Mario Zechner
101a6c4ef3 Add search, scrolling, spacing, and Ctrl+C exit to session selector
- Add search input at top - filters sessions as you type
- Add scrolling with max 5 visible sessions at a time
- Add scroll indicator showing position (e.g., (3/15))
- Add blank line spacing between session items
- Ctrl+C now exits process (process.exit(0)) instead of canceling
- Escape still cancels and returns to main menu
- Enter in search box selects current session
2025-11-12 09:28:53 +01:00
Mario Zechner
4a399805f5 Remove unused import 2025-11-12 09:26:01 +01:00
Mario Zechner
a6e300693d Redesign session selector with multi-line layout
- Custom SessionList component with 2 lines per item
- First line: message text (bold when selected)
- Second line: metadata (time · message count) in dim
- Blue › cursor for selected item
- Added "Resume Session" header
- Handle Ctrl+C (‹x03›) in SelectList for consistency
- Improved date formatting (38 minutes ago, 8 hours ago, etc.)
2025-11-12 09:25:40 +01:00
Mario Zechner
6b48e73607 Fix session selector: handle Ctrl+C and viewport width
- Add SIGINT handler to allow Ctrl+C to exit during session selection
- Remove hardcoded 60-char truncation, let SelectList handle dynamic truncation
- Simplify date format (5m, 2h, 3d instead of "5m ago")
- Make metadata more compact (5msg instead of "5 msgs")
2025-11-12 09:21:17 +01:00
Mario Zechner
458702b3a7 Add --resume flag with session selector
- New SessionSelectorComponent to browse and select sessions
- Lists sessions sorted by last modified date
- Shows first message, created/modified dates, message count
- Automatically truncates long messages and formats dates
- Adds --resume/-r flag to CLI
- Session selector integrates with main flow
2025-11-12 09:17:04 +01:00
Mario Zechner
7813e14492 Add model name to footer stats line (right-aligned) 2025-11-12 09:10:41 +01:00
Mario Zechner
95d040195c Add model selector TUI and update session management 2025-11-12 01:01:23 +01:00
Mario Zechner
bf5f4b17c0 Add custom session events for thinking level and model changes
Session manager changes:
- Add ThinkingLevelChangeEntry and ModelChangeEntry types
- Add saveThinkingLevelChange() and saveModelChange() methods
- Update loadThinkingLevel() to also check for thinking_level_change events
  (not just session headers)

TUI changes:
- Pass SessionManager to TuiRenderer constructor
- Call saveThinkingLevelChange() when user changes thinking level via /thinking
- Store session manager as instance variable for future use

This ensures thinking level changes during a session are persisted
and correctly restored on --continue.
2025-11-11 23:56:08 +01:00
Mario Zechner
02a21dd936 Fix viewport width issues in thinking selector and text rendering
Thinking selector fix:
- Replace hardcoded 50-character borders with DynamicBorder component
  that adjusts to viewport width
- Prevents crash when terminal is resized narrow

Text/Markdown rendering fixes:
- Fix Markdown wrapSingleLine to check if adding next character would
  exceed width BEFORE adding it (was checking AFTER, causing lines to
  be 1 character too long)
- Add word truncation in Text component for words longer than
  contentWidth (prevents long unbreakable words from exceeding width)

These fixes prevent "Rendered line exceeds terminal width" errors.
2025-11-11 23:52:18 +01:00
Mario Zechner
a3b3849188 Fix SelectList crash on narrow terminal and thinking level restoration
SelectList fixes:
- Use hardcoded visual width for arrow prefix instead of string length
  which includes ANSI codes
- Truncate scroll indicator text to prevent exceeding terminal width
- Fixes crash when terminal is resized narrow and arrow keys are pressed

Thinking level fix:
- Restore thinking level even if it's "off" (removed !== "off" check)
- This ensures the thinking level selector shows the correct state on continue
2025-11-11 23:47:59 +01:00
Mario Zechner
cef526ce4d Add padding to Aborted text for consistent spacing 2025-11-11 23:42:42 +01:00
Mario Zechner
dbee5b69ec Show "Aborted" text when aborting text generation during streaming
Update streaming component with final message in message_end event.
The final message includes the stopReason, which allows the component
to render "Aborted" text for aborted text generation.

Now behavior is consistent:
- Abort during text generation (no tool calls) → shows red "Aborted"
- Abort during tool call streaming → tool components turn red
2025-11-11 23:41:05 +01:00
Mario Zechner
1e857e0a6a Fix aborted tool display when continuing sessions
Two fixes for rendering aborted tools in --continue mode:

1. In renderInitialMessages: Check if assistant message was aborted/errored
   and immediately mark tool execution components as failed instead of
   leaving them in pending state.

2. In AssistantMessageComponent: Don't show "Aborted" text when there are
   tool calls in the message, since the tool execution components will
   show the error state themselves. This prevents duplicate error messages.

Now aborted tools show properly as red with "Operation aborted" message,
without the duplicate "Aborted" text above them.
2025-11-11 23:39:00 +01:00
Mario Zechner
2fdd304fbf Mark pending tool components as aborted when streaming is interrupted
When user presses Esc during tool argument streaming, the assistant
message ends with stopReason="aborted" but tool execution never starts.
Now we check for aborted/error stopReasons in message_end and update
all pending tool execution components to show red error state with
"Operation aborted" message.

This fixes the issue where tool components stayed stuck in blue/pending
state after aborting during JSON streaming.
2025-11-11 23:37:05 +01:00
Mario Zechner
594edec31b Make file operations properly abortable with async operations
Replace synchronous file operations with async Promise-based operations
that listen to abort signals during execution:
- read, write, edit now use fs/promises async APIs
- Add abort event listeners that reject immediately on abort
- Check abort status before and after each async operation
- Clean up event listeners properly

This ensures pressing Esc during file operations shows red error state.
2025-11-11 23:33:16 +01:00
Mario Zechner
e6b47799a4 Add abort signal handling to read, write, and edit tools
All tools now check the abort signal before executing and throw
"Operation aborted" error if the signal is already aborted.
This ensures consistent abort behavior across all tools.
2025-11-11 23:28:39 +01:00
Mario Zechner
001beff394 Fix tab rendering in TUI components
Replace tabs with 3 spaces for consistent rendering and width calculation:
- Updated visibleWidth() to normalize tabs before measuring
- Updated Text and Markdown components to replace tabs when rendering
- Updated tool-execution display for read/write tools to replace tabs

This fixes background color rendering issues when displaying files with tab indentation.
2025-11-11 23:24:48 +01:00
Mario Zechner
7beb354337 Add thinking level persistence and fix UI issues
- Save and restore thinking level when continuing sessions
- Fix thinking level confirmation message spacing and styling
- Fix thinking text wrapping to preserve ANSI formatting across lines
2025-11-11 23:18:40 +01:00
Mario Zechner
159075cad7 Improve tool execution rendering and error handling
- Show tool execution components immediately when tool calls appear in streaming
- Update components with streaming arguments as they come in
- Handle incomplete/partial arguments gracefully with optional chaining
- Fix error handling: tools now throw exceptions instead of returning error messages
- Fix bash abort handling to properly reject on abort/timeout
- Clean up error display
2025-11-11 23:05:58 +01:00
Mario Zechner
2d43b2f2e3 Don't show stats for assistant messages with only tool calls 2025-11-11 22:13:00 +01:00
Mario Zechner
ea8b8b7f54 Fix thinking trace styling when text wraps 2025-11-11 22:08:20 +01:00
Mario Zechner
3fcae75e93 Remove StreamingMessageComponent - just use AssistantMessageComponent
- StreamingMessageComponent was just a wrapper around AssistantMessageComponent
- AssistantMessageComponent now handles its own stats rendering
- Made AssistantMessageComponent updatable with updateContent()
- Removed duplicate stats handling code from tui-renderer
- All stats are now managed by the component itself
2025-11-11 22:04:42 +01:00
Mario Zechner
741add4411 Refactor TUI into proper components
- Create UserMessageComponent - handles user messages with spacing
- Create AssistantMessageComponent - handles complete assistant messages
- Create ThinkingSelectorComponent - wraps selector with borders
- Add setSelectedIndex to SelectList for preselecting current level
- Simplify tui-renderer by using dedicated components
- Much cleaner architecture - each message type is now a component
2025-11-11 21:55:29 +01:00
Mario Zechner
e2649341f0 Simplify assistant message spacing - just add spacer to components 2025-11-11 21:51:12 +01:00
Mario Zechner
f5176bb173 Fix double spacing before tool executions by removing bottom padding from assistant Markdown 2025-11-11 21:43:53 +01:00
Mario Zechner
f63ec78524 Add spacer above user messages (except first one) 2025-11-11 21:39:42 +01:00
Mario Zechner
0cceb346be Use Spacer component for blank line before tool execution 2025-11-11 21:37:11 +01:00
Mario Zechner
c061b4fba9 Simplify tool execution component structure with proper padding
- Use single Text component with paddingY=1 for green background box
- Add spacer line with transparent background at top
- Header and content in same component with blank line separator
- Move error markers to header line instead of after content
2025-11-11 21:35:11 +01:00
Mario Zechner
ba5299a39e Fix tool execution formatting and colors
- Add blank spacer line with no background before tool execution
- Apply colored background to header (read/write/edit line)
- Apply same colored background to content
- Use lighter gray (chalk.dim) for file content
- Show first 10 lines of content for write operations
- Use cyan color for file paths (matching markdown code color)
2025-11-11 21:32:00 +01:00