Commit graph

1482 commits

Author SHA1 Message Date
Mario Zechner
1625d127c7 Add CHANGELOG entry for #400 2026-01-03 00:13:25 +01:00
Mario Zechner
d0a4c37028 feat(agent): split queue into steer() and followUp() APIs
Breaking change: replaces queueMessage() with two separate methods:
- steer(msg): interrupt mid-run, delivered after current tool execution
- followUp(msg): wait until agent finishes before delivery

Also renames:
- queueMode -> steeringMode/followUpMode
- getQueuedMessages -> getSteeringMessages/getFollowUpMessages

Refs #403
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
1e7d991a25 Add changelog entry for terminal title feature (#407) 2026-01-02 22:02:24 +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
Mario Zechner
fd35d9188c fix(ai): add retry with server-provided delay for Gemini CLI rate limits, fixes #370 2026-01-02 10:45:59 +01:00
Mario Zechner
0d1424d8e5 Add [Unreleased] section for next cycle 2026-01-02 10:39:42 +01:00
Mario Zechner
d78a245cc8 Release v0.31.1 2026-01-02 10:39:08 +01:00
Mario Zechner
c10d99d2de fix: export type guard functions at runtime, fixes #397 2026-01-02 10:37:28 +01:00
cursive
d97a96493c
fix(tui): Strip OSC 8 hyperlink sequences in visibleWidth (#396) 2026-01-02 10:32:36 +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
e76ad7aebe Add [Unreleased] section for next cycle 2026-01-02 02:00:36 +01:00
Mario Zechner
3caf359402 Release v0.31.0 2026-01-02 01:59:59 +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
nathyong
6e4270a286 tui: only check for emojis in visibleWidth when necessary
The initial render of a session, and any re-draws caused by terminal
resizing are noticeably slow, especially on conversations with 20+
turns and many tool calls.

From profiling with `bun --cpu-prof` (available since bun 1.3.2), the
majority of the rendering (90%) is spent on detection of emojis in the
string-width library, running the expensive `/\p{RGI_Emoji}$/v`
regular expression on every individual grapheme cluster in the entire
scrollback. I believe it essentially expands to a fixed search against
every possible emoji sequence, hence the amount of CPU time spent in it.

This change replaces the `stringWidth` from string-width with a
`graphemeWidth` function that performs a similar check, but avoids
running the `/\p{RGI_Emoji}$/v` regex for emoji detection unless it
contains codepoints that could be emojis.

The `visibleWidth` function also has two more optimisations:
- Short-circuits string length detection for strings that are entirely
  printable ASCII characters
- Adds a cache for non-ASCII segments to avoid recomputing string length
  when resizing
2026-01-02 01:56:11 +01:00
Mario Zechner
02175d908b Update docs for ctx.ui.editor() and handoff example
- Added ctx.ui.editor() to hooks.md and custom-tools.md
- Added ctx.ui.editor() to CHANGELOG.md
- Added handoff.ts to examples/hooks/README.md
2026-01-02 01:26:21 +01:00
Mario Zechner
af4c66117b Fix BorderedLoader to pass theme to DynamicBorder
BorderedLoader receives theme as a parameter but was creating
DynamicBorder() without passing it, causing DynamicBorder to
fall back to the global theme variable which is undefined when
loaded via jiti (separate module cache).

Added doc comment to DynamicBorder explaining the jiti issue.
2026-01-02 01:21:07 +01:00
Mario Zechner
3ad5a168e7 Fix DynamicBorder crash when theme not initialized
Make DynamicBorder defensive against undefined theme by checking
at render time instead of relying on default parameter closure.
2026-01-02 01:15:45 +01:00
Mario Zechner
d51770a63d fix(coding-agent): prevent full re-renders during write tool streaming
Move line count from header to footer to avoid changing the first line
during streaming, which was triggering full screen re-renders in the
TUI's differential rendering logic.
2026-01-02 01:11:06 +01:00
Mario Zechner
91c52de8be Use serializeConversation in handoff hook
Properly handles all message types including tool calls, thinking,
and tool results instead of manual text extraction.
2026-01-02 00:45:03 +01:00
Mario Zechner
ace0063a00 Add handoff example hook
Transfers context to a new focused session instead of compacting.
User provides a goal, hook generates a prompt with relevant context,
creates a new session with parent tracking, and loads the prompt
as a draft in the editor for review.

Inspired by Amp's handoff feature.
2026-01-02 00:42:11 +01:00
Mario Zechner
5c37fe27c6 Remove unnecessary comments from types 2026-01-02 00:39:54 +01:00
Mario Zechner
a433e524a0 Add Clawd summary comments to hook and custom tool types 2026-01-02 00:32:38 +01:00
Mario Zechner
03159d2f4b Add agent state methods to CustomToolContext and fix abort signature
CustomToolContext now has:
- isIdle() - check if agent is streaming
- hasQueuedMessages() - check if user has queued messages
- abort() - abort current operation (fire-and-forget)

Changed abort() signature from Promise<void> to void in both
HookContext and CustomToolContext. The abort is fire-and-forget:
it calls session.abort() without awaiting, so the abort signal
is set immediately while waitForIdle() runs in the background.

Fixes #388
2026-01-02 00:31:23 +01:00
Mario Zechner
0d9fddec1e Split HookContext and HookCommandContext to prevent deadlocks
HookContext (all events):
- isIdle() - read-only state check
- hasQueuedMessages() - read-only state check
- abort() - fire-and-forget, does not wait

HookCommandContext (slash commands only):
- waitForIdle() - waits for agent to finish
- newSession(options?) - create new session
- branch(entryId) - branch from entry
- navigateTree(targetId, options?) - navigate session tree

Session control methods moved from HookAPI (pi.*) to HookCommandContext (ctx.*)
because they can deadlock when called from event handlers that run inside
the agent loop (tool_call, tool_result, context events).
2026-01-02 00:24:58 +01:00
Mario Zechner
ccdd7bd283 Add session management and agent state methods to hooks API
HookAPI additions:
- pi.newSession(options?) - create new session with optional setup callback
- pi.branch(entryId) - branch from a specific entry
- pi.navigateTree(targetId, options?) - navigate the session tree

HookContext additions:
- ctx.isIdle() - check if agent is streaming
- ctx.waitForIdle() - wait for agent to finish
- ctx.abort() - abort current operation
- ctx.hasQueuedMessages() - check for queued user messages

These enable hooks to programmatically manage sessions (handoff, templates)
and check agent state before showing interactive UI.

Fixes #388
2026-01-01 23:56:24 +01:00
Mario Zechner
484d7e06bb Consolidate session events: remove session_before_new/session_new, add reason field to switch events
- Remove session_before_new and session_new hook events
- Add reason: 'new' | 'resume' to session_before_switch and session_switch events
- Remove 'new' reason from custom tool onSession (use 'switch' for both /new and /resume)
- Rename reset() to newSession(options?) in AgentSession
- Add NewSessionOptions with optional parentSession for lineage tracking
- Rename branchedFrom to parentSession in SessionHeader
- Rename RPC reset command to new_session with optional parentSession
- Update example hooks to use new event structure
- Update documentation and changelog

Based on discussion in #293
2026-01-01 23:31:26 +01:00
Mario Zechner
1d9fa13d58 Fix crash on Unicode format characters in visibleWidth
Strip all Unicode format characters (category Cf) before passing to
string-width. These are invisible control characters that crash
string-width but have no visible width anyway.

Closes #390
2026-01-01 22:33:09 +01:00
Mario Zechner
7f0cd8bcb5 Remove extra spacer before loader in BorderedLoader 2026-01-01 22:30:19 +01:00
Mario Zechner
e9cf47d09d Add CHANGELOG entries for export theme colors and syntax highlighting 2026-01-01 22:28:44 +01:00
Mario Zechner
6267720660 Add theme-configurable HTML export colors (from PR #387)
- Add optional 'export' section to theme JSON with pageBg, cardBg, infoBg
- If not specified, colors are auto-derived from userMessageBg
- Add export colors to dark.json and light.json
- Update theme-schema.json and TypeBox schema
- Add documentation to docs/theme.md
- Add margin-top back to tool-output for spacing between header and content
2026-01-01 22:21:40 +01:00
Mario Zechner
d612bc45f5 Fix markdown code block default color to use --text not --mdCodeBlock
The mdCodeBlock color was being applied to all text in code blocks,
overriding hljs syntax highlighting for unspanned text.
2026-01-01 22:15:26 +01:00
Mario Zechner
28434ce3a6 Fix hljs v11 compound class selectors for functions/types 2026-01-01 22:07:04 +01:00
Mario Zechner
ecfedce25f Fix hljs color mappings to match TUI theme
- Add .hljs-function for syntaxFunction
- Separate .hljs-punctuation to use syntaxPunctuation (was using syntaxOperator)
2026-01-01 22:04:38 +01:00
Mario Zechner
0b31884385 Fix HTML escaping in markdown code blocks
Move HTML tag escaping from pre-parse to custom renderers.
This preserves < in code blocks while still escaping in text content.
2026-01-01 22:03:01 +01:00
Mario Zechner
dccdf91b8c Add ctx.ui.theme getter for styling status text with theme colors
- Add theme property to HookUIContext interface
- Implement in interactive, RPC, and no-op contexts
- Add status-line.ts example hook
- Document styling with theme colors in hooks.md
2026-01-01 21:58:01 +01:00
Mario Zechner
48ca55ab3c Remove test files, add out.html to gitignore 2026-01-01 21:50:32 +01:00
Mario Zechner
872205406e Remove padding from markdown code blocks 2026-01-01 21:50:23 +01:00
Mario Zechner
a9492837e8 Remove accidentally committed files 2026-01-01 21:42:28 +01:00
Mario Zechner
0ec8509de3 Fix markdown code block syntax highlighting
Marked v15 removed the highlight option from setOptions.
Use marked.use() with a custom renderer instead.
2026-01-01 21:42:18 +01:00
Mario Zechner
cafbca02f9 Update todo.md 2026-01-01 21:40:36 +01:00
Mario Zechner
95868ea5e9 Fix tool-output spacing by removing pre-wrap from container
The white-space: pre-wrap on .tool-output was preserving template
literal whitespace (newlines and indentation). The pre elements
inside still have pre-wrap for actual code content.
2026-01-01 21:40:16 +01:00
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
89db7ed024 Fix export HTML styling issues
- Match help-bar font size (11px) with header-info
- Add newline after 'Available Tools' header
- Remove excessive margin-top from tool-output
2026-01-01 21:34:07 +01:00
Mario Zechner
0addbfec4e Add /share command to README 2026-01-01 21:28:22 +01:00
Mario Zechner
738892eb7a Make /share cancellable with Escape, add CHANGELOG entries
- Use BorderedLoader for /share command so Escape cancels gist creation
- Add CHANGELOG entries for /share command and HTML export improvements
- Add todo.md with remaining export-html issues
2026-01-01 21:27:33 +01:00
Mario Zechner
93aaf8160e Remove unused imports and variables 2026-01-01 21:14:36 +01:00
Mario Zechner
3fa9eb58b8 Refactor export-html and add /share command
- Split template into separate files: template.html, template.css, template.js
- Add tree visualization sidebar for session navigation
- Fix HTML sanitization to prevent <style> tags breaking DOM
- Add DOM node caching for faster re-renders
- Fix tree indentation to match tree-selector.ts
- Add /share command to upload session as GitHub gist
- Support shittycodingagent.ai/session?{gistId} URLs

Closes #375, closes #380
2026-01-01 21:13:40 +01:00
Mario Zechner
1ed009e2cf Show edit diff before tool execution (fixes #393)
- Extract diff computation from edit.ts into shared edit-diff.ts
- ToolExecutionComponent computes and caches diff when args are complete
- Diff is visible while permission hooks block, before tool executes
2026-01-01 20:34:19 +01:00