Skip to content

feat: add pi-toolview — compact tool output display - #11

Open
smarzban wants to merge 11 commits into
mainfrom
pi-toolview
Open

feat: add pi-toolview — compact tool output display#11
smarzban wants to merge 11 commits into
mainfrom
pi-toolview

Conversation

@smarzban

@smarzban smarzban commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Summary

Replaces pi's verbose built-in tool rendering with one-line summaries, expandable on demand (ctrl+o). Execution fully delegates to the originals, so the LLM still sees complete output.

Features

Feature Example
Smart paths src/utils.ts inside project, ~/code/file.ts under HOME, absolute otherwise
Bash timing ✓ · 42 lines · 12.3s — duration parsed from raw output
Write file size (156 lines · 4.2 KB) — catch accidental huge writes
Error emphasis ✗ exit 1 in red — also detects error keywords in output
Edit context hint +12 / -4 in parseConfig — enclosing function from diff
Per-tool control /toolview bash off — that tool reverts to verbose original

Commands

/toolview — show status · /toolview off — all verbose · /toolview <tool> off — one tool verbose · state persists in ~/.pi/agent/toolview.json

Before / after

Default pi shows full tool output inline — every line of bash, every file read, full diffs.

With pi-toolview:

$ npm test
✓ · 42 lines · 12.3s

read src/app.ts (offset=100, limit=50)
85 lines (truncated from 200)

edit src/utils.ts (3 changes)
+12 / -4 in parseConfig

write dist/output.js (156 lines · 4.2 KB)
Written

$ rm nonexistent
✗ exit 1 · 2 lines · 0.0s

Design notes

  • Re-registers each built-in tool with the same name; execute() delegates to original create*Tool(cwd) — only renderCall/renderResult are custom
  • LLM receives full, unmodified result.content; session state untouched
  • Falls back to original tool's renderer when disabled via /toolview
  • No cross-package dependencies

smarzban added 11 commits August 4, 2026 13:24
Replaces pi's verbose built-in tool rendering with one-line summaries,
expandable on demand (ctrl+o). Execution delegates to originals so the
LLM still sees complete output.

Features:
- Smart paths: relative inside cwd, ~/ under HOME, absolute otherwise
- Bash timing: parses duration from raw output (✓ · 42 lines · 12.3s)
- Write file size: byte count for sanity checks (156 lines · 4.2 KB)
- Error emphasis: ✗ prefix with red for exit codes and error keywords
- Edit context hint: extracts enclosing function/class from diff
- /toolview command: toggle on/off globally or per-tool, persisted
- Falls back to original verbose rendering when disabled
Timing: pi never puts duration in the output text; the built-in tracks it
via render state. Now uses the same context.state startedAt/endedAt
mechanism, so durations actually show (e.g. '· 12.3s').

Errors: non-zero exits arrive as isError results with a status suffix,
not 'exit code:' in text. Switch bash/read/edit/write to context.isError
and parse the real status line ('Command exited with code N').

Truncation markers: match pi's actual suffixes ([Showing lines X-Y...],
Command aborted/timed out) instead of made-up ones.

Command clip: keep head + tail with middle ellipsis so long env
assignments or 'cd /long/path &&' prefixes don't hide the real command.

Also: find shows '0 results' for no-match, grep/ls/read fallbacks pass
the real render context.
Switch all 7 tools to renderShell: 'self', dropping the default Box's
paddingY (one blank line top + bottom of each pill). Re-apply the
success/error/pending background color manually on each row so blocks
stay colored but sit tighter together.

Pi hardcodes a Spacer(1) above every tool block in the component
constructor, so one separator line between blocks remains and cannot be
removed by an extension.
Two related fixes:

Instant toggle (no reload): pi caches already-rendered tool blocks, so a
toggle only affected newly-rendered tools. The handler now calls
ctx.ui.setToolsExpanded(getToolsExpanded()) after each state change, which
re-runs renderCall/renderResult on every existing block. Toggling applies
immediately.

Original spacing when off: revert renderShell:'self' back to the default
tool Box. The self shell dropped the pill padding but also meant turning
toolview off rendered the original content in the tight frame instead of
the native box. With the default shell, off restores pi's exact original
look. Trade-off: 'on' uses the standard pill padding rather than the extra
tight self shell.
Re-apply renderShell:'self' on all 7 tools to drop the pill padding for
the tight look, with the success/error/pending background re-applied
manually. Keeps the instant-toggle refresh() so /toolview applies without
a reload.

Trade-off noted: with the self shell, turning a tool off renders the
original content in the tight frame rather than the native pill.
The off path called originals.X.renderCall, but createXTool returns an
AgentTool whose wrapToolDefinition drops renderCall/renderResult, so the
delegation threw 'renderCall is not a function' and pi silently fell back
to the bare tool name. Turning a tool off appeared to do nothing.

Use createXToolDefinition (which carries renderCall/renderResult) for the
off-fallback. Execution/description/parameters still come from the
AgentTool. Verified all 7 definitions expose both renderers.
… tools

The native bash/read/grep/find/ls renderers reuse context.lastComponent and
call container methods on it (.clear/.addChild). After a compact render that
slot holds toolview's plain Text, so the off-fallback threw 'component.clear
is not a function' and pi fell back to the bare tool name. Only edit survived
because it is self-shell native and builds fresh components.

Clear context.lastComponent before each off delegation so the native renderer
constructs a fresh component. Verified bash/grep/find/ls now render original
output; read/write/edit follow their native collapsed/expanded behavior.
The native per-tool renderResult functions are built for the Box shell and
render with no background or padding when drawn in the tight self frame, so
toggled-off tools hugged the left edge (read most visibly, since its content
is indented). Verified all seven native renderers lose their pill bg in the
self container.

Stop delegating off-mode to the native renderers. Each tool now draws its full
result content through the same row() pill (bg + padding): bash/grep/find/ls
output, read file content, write message, and edit's colored diff. Drop the
createXToolDefinition renderers and lastComponent clearing they required.
Compact (on) rendering is unchanged.
/toolview on only set enabled=true, leaving per-tool false entries in
state.tools, and isOn() checks both. So tools toggled off individually
stayed off after /toolview on. Both on and off now reset the per-tool
map so the global toggle is a true 'everything' toggle.
The on/off verbs were confusing since toolview itself is always active;
the toggle is between compact summaries and full output. compact/full
are now the primary verbs; on/off remain as aliases for compatibility.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant