Skip to content

fix(chat): show a shell command's text instead of escaped JSON - #1396

Merged
agegr merged 2 commits into
agegr:mainfrom
sirenkovladd:fix/bash-command-readable
Oct 29, 2026
Merged

agegr merged 2 commits into
agegr:mainfrom
sirenkovladd:fix/bash-command-readable

Conversation

@sirenkovladd

@sirenkovladd sirenkovladd commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Reproduce on main: run any multi-line bash call (e.g. a heredoc script) and expand its card. Finished calls show JSON.stringify output with \n escapes; while the call streams, the card shows the raw rawInput JSON. Newlines never render as line breaks.

Cause: the expanded card only had a dedicated view for write text, codemode scripts and patches; everything else fell back to JSON text, which by spec escapes newlines inside strings.

Change:

  • bash/powershell calls (new isBashToolName, matching lib/tool-names.ts conventions) with exactly { command, timeout? } now show the command text with real line breaks, finished and while streaming. Streaming input decodes the command string up to the last chunk (mid-escape cuts included); unparseable input, empty commands and calls with extra arguments keep the old view, so nothing is hidden.
  • The header previews the command's first line plus (timeout Ns), as pi's TUI shows $ followed by the command and a timeout suffix; while streaming it shows the partial command instead of "Generating parameters" once it parses.
  • Mirrored in demo/; topic note updated in docs/agents/sessions.md.

Checks: MessageView 51/51 (3 new tests), tsc --noEmit clean, eslint clean (main + demo configs). Full npm test: 2870/2873 — the 2 failures (rpc-manager-chat-only model naming, worktree listing) reproduce on clean main and are unrelated.


Before
image

After
image

sirenkovladd and others added 2 commits October 22, 2026 22:05
…of a shell special case

Main already shows a finished bash call's command as a row whose block keeps
its real line breaks (lib/tool-fields.ts, agegr#1324); only input still streaming
fell back to the raw JSON with `\n` escapes. Rather than a bash/powershell
name list, a second view and a hand-written partial string decoder, feed the
streamed text through pi-ai's parseStreamingJson() (the partial arguments
pi's TUI hands renderCall while a call streams) into the existing rows.

Structural like the rows themselves: any tool whose arguments so far are
flat gets them as rows (a multi-line command, a codemode script, a write's
text); nothing parsed yet or a nested argument begun keeps the raw text.
The parse runs only for an expanded card. The demo has no pi-ai and calls
partial-json, the parser parseStreamingJson() wraps.

Reverts the PR's isBashToolName, BashCommandView, header preview and decoder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@agegr

agegr commented Oct 29, 2026

Copy link
Copy Markdown
Owner

Thanks for this. I checked it against current main. Since #1324, a finished bash call already shows command as a row whose block keeps the real line breaks, so the finished-call half no longer reproduces (your "before" screenshot predates that). What is still wrong is the streaming phase: until toolcall_end, the card shows the raw JSON with \n escapes, while pi's TUI already renders the partial arguments.

I pushed a slimmer version on top. Instead of a bash/powershell name list, a second view and a hand-written partial-string decoder, the streamed input now goes through pi-ai's own parseStreamingJson() into the existing argument rows. That function produces the same partial arguments pi's TUI renders. It works for every tool whose arguments so far are flat (a multi-line command, a codemode script), and keeps the raw text otherwise. It also covers cases the decoder fell back to raw on or cut short: an invalid escape like \$, or timeout arriving before command.

The header keeps the plain command preview, and the timeout stays a row as on main. The demo uses partial-json, the parser parseStreamingJson() wraps. Tests and the sessions note are updated. I also checked it live with a mock provider streaming a bash call slowly.

@agegr
agegr merged commit fc08031 into agegr:main Oct 29, 2026
4 checks passed
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.

2 participants