Skip to content

feat: list turn-written files under each reply and open HTML in preview - #378

Open
thy950523 wants to merge 4 commits into
agegr:mainfrom
thy950523:feat/turn-written-files
Open

feat: list turn-written files under each reply and open HTML in preview#378
thy950523 wants to merge 4 commits into
agegr:mainfrom
thy950523:feat/turn-written-files

Conversation

@thy950523

@thy950523 thy950523 commented Aug 4, 2026

Copy link
Copy Markdown

Summary

When the agent writes files during a turn (generated reports, HTML pages, edited source), there is no easy way to open them from the chat. The reply usually omits the path, and even when a path appears it is plain text — nothing to click. The user has to switch to the file browser and locate the file manually.

This PR adds two things so that produced files are one click away:

  1. Written-file chips — one button per file produced by the turn's successful write/edit tool calls, shown under the final reply. Works even when the reply never names the file. The file list is derived entirely from tool calls; the reply text is never scanned.
  2. HTML preview by default.html files open in rendered-preview mode (live page via the existing preview pane), matching how markdown is already handled. Source view remains one click away.

Changes

New:

  • lib/turn-written-files.tsextractTurnWrittenFiles(content, toolResults, cwd): walks the turn's tool-call blocks, keeps write/edit calls whose result arrived without error, resolves paths against cwd, deduplicates in first-seen order.
  • lib/tool-names.tsisWriteToolName / isEditToolName predicates; recognizes Pi's built-in plain names plus common MCP-namespaced forms (mcp__server__write, str_replace, replace_editor).
  • components/TurnWrittenFiles.tsx — leaf component: one <button> per file → the existing preview path.
  • lib/turn-written-files.test.mjs + components/TurnWrittenFiles.test.mjs — 14 focused unit tests.

Edited:

  • components/ChatWindow.tsx — aggregate the turn's assistant blocks before rendering the final reply and pass the derived file list through (Pi stores each tool call as its own entry, so the extractor must see the whole turn).
  • components/MessageView.tsx — thread a writtenFiles prop to the assistant view; render TurnWrittenFiles under the reply.
  • components/FileViewer.tsx — one-clause change: treat html alongside markdown in the preview-by-default branch.
  • lib/i18n/messages/{en,zh-CN}.ts — two new strings.

Net: 10 files, +332 / −15.

Testing

  • node --test lib/turn-written-files.test.mjs components/TurnWrittenFiles.test.mjs — 14/14 pass.
  • Coverage: successful write/edit extraction, MCP-namespaced tool names, errored calls skipped, streaming (no result yet) skipped, write-then-edit dedup, relative-path resolution against cwd, non-writing tools ignored, reply-text-only paths ignored.

ScreenShot

image

thy950523 and others added 4 commits August 3, 2026 17:18
extractTurnWrittenFiles collects the distinct files an assistant turn
wrote, keeping only write/edit tool calls whose result arrived and did not
error, resolving each path against cwd and deduping by absolute path.

The tool call is the evidence that a file was written. A path the
assistant merely mentions in its reply is not, so the reply text is never
scanned; tests cover that case explicitly.

lib/tool-names.ts holds the write/edit name predicates so this and the
chat views stay in agreement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Renders one button per file, labelled with the basename and titled with
the full path, opening the file in the preview pane on click. Labels are
localized in en and zh-CN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Session preprocessing gives each tool call its own assistant entry, so the
final answer alone has no record of what the turn wrote. ChatWindow
aggregates the turn's assistant blocks, derives the file list, and passes
it to MessageView, which renders the row below the reply.

MessageView also drops its local isEditToolName in favour of the shared
predicate in lib/tool-names.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A generated page is usually more useful viewed than read as source, so
HTML now defaults to preview like markdown. Both already had a preview
mode; the source tab stays one click away.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@thy950523
thy950523 marked this pull request as ready for review August 4, 2026 08:02
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