Skip to content

feat(app): open text file artifacts in the side panel with edit and save#2470

Open
benjaminshafii wants to merge 3 commits into
devfrom
feat/text-file-preview-panel
Open

feat(app): open text file artifacts in the side panel with edit and save#2470
benjaminshafii wants to merge 3 commits into
devfrom
feat/text-file-preview-panel

Conversation

@benjaminshafii

Copy link
Copy Markdown
Member

What

Text files (txt, log, json, yaml, toml, xml, ts/js/css, …) now open in the artifact side panel — readable in place, editable via the CodeMirror text editor, and saveable back to disk — instead of always bouncing to the OS default app.

Integrates user feedback from Jay (openwork-app feedback form):

"Can you add preview panel to view text files … it saves the hassle to open the files in the separate app and also helps to make changes to the file content before saving it"

How

The panel already rendered and edited text (PlainText, ArtifactTextEditor, save with optimistic concurrency), and the server already classifies/gates these files (isSupportedWorkspaceTextFilePath). The production change is one line: add "text" to SIDEBAR_ARTIFACT_FILE_PREVIEWS in open-target.ts. That unlocks the existing plumbing end to end: chat artifact chips, markdown-link "Open in panel", Cmd+K accessible items, the artifact rail, and panel tabs. It also resolves the latent inconsistency where link-action-menu.tsx already offered "Open in panel" for text but the gate silently opened externally.

Context: #2304 intentionally made unsupported files open externally so they wouldn't strand. That invariant is preserved — genuinely unsupported types (e.g. .zip) still open externally, now covered by tests with that boundary type instead of .tsx.

No server changes. Office formats (docx/pptx rendering) are deliberately out of scope — that needs real renderers and Jay was asked which formats he needs.

Changes

  • open-target.ts — add "text" to the sidebar preview set (the feature)
  • open-target.test.ts / artifacts.test.ts — text is now collectible/previewable; external-open boundary re-pinned with .zip
  • side-panel.tsx — dev-only eval control actions: eval.artifact_tabs.seed_text (seed a real .txt via the server) and eval.artifact_tabs.read_text_file (disk witness for saves)
  • evals/voiceovers/artifact-text-preview.md — approved 5-frame voiceover script (the spec)
  • evals/flows/artifact-text-preview.flow.mjs — coded fraimz flow: seed → tab opens → readable preview → Edit (line numbers, fix a typo via CodeMirror) → Save → re-read file from workspace to prove persistence

Tests run

  • pnpm --filter @openwork/app typecheck — pass
  • bun test scripts/open-target.test.ts scripts/artifacts.test.ts — 27 pass, 0 fail (55 assertions)
  • node evals/runner/run.mjs --flow artifact-text-preview --cdp-url http://127.0.0.1:9826 against the real Electron dev app — PASSED, all 5 frames + voiceover coverage (evals/results/2026-07-04T06-08-13-595Z/fraimz.html)

Fraimz proof (frames + screenshots + assertions) posted as a comment below.

Known cosmetic follow-ups (pre-existing, also affect markdown at narrow widths)

  • The header size label can crowd the Discard/Save buttons on very narrow panels
  • Header size label isn't refreshed after an inline save

Follow-up candidates from the same feedback

  • Extend the text extension allowlist (py/sh/etc.) in lockstep client+server once Jay confirms formats
  • Office file rendering (docx/pptx) needs a real renderer; slides tabs currently show "Preview unavailable"

Text-preview artifacts (txt, log, json, yaml, code) previously always
opened in the OS default app even though the artifact panel already
knows how to render and edit text. Add "text" to the sidebar preview
set so they open inline like markdown/sheets/PDFs, with the existing
Edit -> Save (optimistic concurrency) plumbing.

Feedback from Jay: preview text files in a dedicated panel and tweak
them before saving instead of bouncing to an external app.

- keep genuinely unsupported files (e.g. .zip) opening externally and
  cover that boundary in tests
- add dev-only eval seeds (seed_text, read_text_file witness)
- add artifact-text-preview fraimz flow + approved voiceover
@vercel

vercel Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openwork-app Ready Ready Preview, Comment Jul 4, 2026 2:12pm
openwork-den Ready Ready Preview, Comment Jul 4, 2026 2:12pm
openwork-den-worker-proxy Ready Ready Preview, Comment Jul 4, 2026 2:12pm
openwork-landing Ready Ready Preview, Comment, Open in v0 Jul 4, 2026 2:12pm

Rerunning against an already-open panel served the previous run's saved
content (staleTime: Infinity) and produced duplicate frames. The seed
action now resets state (close tab + drop the cached artifact query)
before reopening, frame 1 restores a neutral panel, and the script is
tightened to four visually distinct frames.
@benjaminshafii

Copy link
Copy Markdown
Member Author

fraimz — ✅ PASSED

1 passed · 0 failed · 0 skipped — run 2026-07-04T14-09-41-801Z

Full frame proof with validated screenshots: evals/results/2026-07-04T14-09-41-801Z/fraimz.html (re-run: pnpm fraimz --flow artifact-text-preview)

✅ artifact-text-preview — Text file artifacts open in the side panel and can be edited and saved

User-facing flow demo

artifact-text-preview-01-booted.png

1. **OpenWork is ready on a session with the text-artifact seed action enabled** - 📸 [`artifact-text-preview-02-text-artifact-readable.png`](https://b8tgacyg507ru26g.public.blob.vercel-storage.com/fraimz/2026-07-04T14-09-41-801Z/artifact-text-preview-02-text-artifact-readable-9GvXlZ4qZg3xSkH9F7wvOOnqa4SkT5.png) — 5 validations passed

artifact-text-preview-02-text-artifact-readable.png

2. **A saved plain-text file opens as a readable artifact tab with an Edit affordance** - 📸 [`artifact-text-preview-03-text-editor-corrected.png`](https://b8tgacyg507ru26g.public.blob.vercel-storage.com/fraimz/2026-07-04T14-09-41-801Z/artifact-text-preview-03-text-editor-corrected-uSx7vJQmZV8WWUsVAuEvqz9PLKhRnI.png) — 5 validations passed

artifact-text-preview-03-text-editor-corrected.png

3. **Edit mode shows a line-numbered text editor and accepts the budget correction** - 📸 [`artifact-text-preview-04-text-save-persisted.png`](https://b8tgacyg507ru26g.public.blob.vercel-storage.com/fraimz/2026-07-04T14-09-41-801Z/artifact-text-preview-04-text-save-persisted-1L5O0bkeW21feTVYqyUu0MkskCeYY3.png) — 4 validations passed

artifact-text-preview-04-text-save-persisted.png

4. **Saving returns to preview mode and persists the corrected text on disk** - ✅ Script frame 1 narrated: "This is OpenWork on a working session. On the right sits the side panel, where files the" - ✅ Script frame 2 narrated: "The agent has just saved plain-text meeting notes, and the file opens right in the panel" - ✅ Script frame 3 narrated: "One click on Edit turns the preview into a real text editor with line numbers. The budge" - ✅ Script frame 4 narrated: "Save writes the change back and the panel returns to the clean preview with the correcte"

When BLOB_READ_WRITE_TOKEN is set, --pr uploads each frame screenshot
to Vercel Blob (fraimz/<run-id>/...) and embeds the images inline in
the PR comment, so reviewers see the validated frames without checking
out the run directory. Without a token (or on upload failure) the
comment stays text-only and posting never fails.

Also harden the text-preview flow boot: if the app restores a route
that does not mount the session shell (e.g. settings), navigate home
and wait for session.create_task to register before using it.
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