Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Describe and preserve what is already true in the repo today.
- The empty state explains the product and exposes sample fragment presets.
- A built-in link creator can generate fragment-based links locally in the browser.
- When a valid fragment is present, the app switches to a viewer-first artifact layout.
- The artifact stage toolbar exposes copy-to-clipboard, file download, and (for markdown) browser print-to-PDF.
- The artifact stage toolbar exposes copy-to-clipboard, file download, (for markdown) browser print-to-PDF, and an editor that regenerates a new fragment link from the currently open artifact.
- `activeArtifactId` controls which artifact opens first.
- Internal diff file navigation stays in UI state and does not repurpose the fragment.

Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to `agent-render` will be documented in this file.

The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project uses semantic versioning while it is published as tagged releases.

## [Unreleased]

### Added

- In-viewer edit-and-reshare: open any artifact, correct its content, and generate a new fragment link without leaving the viewer.

## [0.1.0] - 2026-05-05

### Added
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Built for the OpenClaw ecosystem, `agent-render` focuses on fragment-based shari
- Markdown, code, diff, CSV, and JSON all render in the static shell
- Fragment transport supports `plain`, `lz`, `deflate`, `arx`, `arx2`, `arx3`, and `arx4`, with automatic shortest-fragment selection across available wire formats
- The `arx` substitution dictionary is served at `/arx-dictionary.json` with a pre-compressed `/arx-dictionary.json.br` variant; the `arx2` tuple-envelope overlay is served at `/arx2-dictionary.json` with a pre-compressed `/arx2-dictionary.json.br` variant; `arx3` reuses those proven bytes and optimizes for compact visible Unicode fragments; `arx4` adds the curated context-mixer priors at `/arx4-priors.json` with a pre-compressed `/arx4-priors.json.br` variant
- The viewer toolbar copies artifact bodies to the clipboard, downloads them as files, and (for markdown) supports browser print-to-PDF
- The viewer toolbar copies artifact bodies to the clipboard, downloads them as files, (for markdown) supports browser print-to-PDF, and can edit the open artifact then reshare it as a new fragment link
- Deployment target: static hosting, including Cloudflare Pages

## Included Renderers
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ The static export also emits `sitemap.xml` at the site root (and under `NEXT_PUB

The viewer shell now routes all five artifact kinds through dynamically imported client-only renderers so the landing shell stays light and static-host friendly.

When a valid fragment is present, the shell switches into a viewer-first layout with bundle navigation beside the active artifact. The active artifact header includes copy, download, and markdown print actions. The landing/samples experience is only the empty state.
When a valid fragment is present, the shell switches into a viewer-first layout with bundle navigation beside the active artifact. The active artifact header includes copy, download, markdown print, and edit-and-reshare actions. Edit regenerates a new fragment link from the current artifact (or the current artifact inside a bundle) without writing anything to a server. The landing/samples experience is only the empty state.

Diff file navigation is intentionally internal UI state now. The URL fragment remains reserved for payload transport and active-artifact selection instead of being reused as an in-page file anchor system.

Expand Down
2 changes: 1 addition & 1 deletion docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Playwright visual tests live in `tests/e2e/visual.spec.ts`.

The suite is intentionally split by responsibility:

- browser tests protect exported-app behavior, fragment-driven rendering, downloads, clipboard copy, print flow, themes, and layout hierarchy (including mobile toolbar and default code-wrap checks in `tests/e2e/viewer.spec.ts`)
- browser tests protect exported-app behavior, fragment-driven rendering, downloads, clipboard copy, print flow, in-viewer edit-and-reshare, themes, and layout hierarchy (including mobile toolbar and default code-wrap checks in `tests/e2e/viewer.spec.ts`)
- visual tests protect empty state, artifact views, theme presentation, and compact-content spacing
- component tests protect selector/disclosure UI contracts
- unit tests protect transport codecs, envelope validation, diff parsing, and language inference
Expand Down
2 changes: 1 addition & 1 deletion skills/selfhosted-agent-render/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ Returns `200 { "status": "ok" }` when the server is up and the database is reach

## Viewer links

When a user visits `/{uuid}`, the server looks up the stored payload, injects it into the viewer page, and renders the same UI as the fragment-based product. All viewer features work: copy, download, print-to-PDF, diff modes, artifact switching, raw toggle.
When a user visits `/{uuid}`, the server looks up the stored payload, injects it into the viewer page, and renders the same UI as the fragment-based product. All viewer features work: copy, download, print-to-PDF, edit-and-reshare, diff modes, artifact switching, raw toggle. Edit-and-reshare emits a new static fragment link rather than updating the stored UUID payload, and generation fails if the edited artifact exceeds the fragment budget.

Construct viewer links as:

Expand Down
12 changes: 12 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,18 @@ select {
padding: 0.95rem;
}

.artifact-editor {
display: grid;
gap: 1.15rem;
padding: 1.5rem;
}

@media (min-width: 768px) {
.artifact-editor {
padding: 2rem 2.5rem;
}
}

.viewer-toolbar {
display: flex;
flex-wrap: wrap;
Expand Down
8 changes: 6 additions & 2 deletions src/components/viewer-shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -303,13 +303,16 @@ export function ViewerShell() {
useEffect(() => {
rendererReadyKeyRef.current = rendererReadyKey;

if (!activeArtifact) {
if (!rendererReadyKey) {
setRendererReady(true);
return;
}

// Reset only when the hash/artifact-id key changes. A later decode that only
// replaces artifact contents (same id, new fragment) must not clear a ready
// signal the remounted renderer already reported for that key.
setRendererReady(false);
}, [activeArtifact, rendererReadyKey]);
}, [rendererReadyKey]);

const markRendererReady = useCallback((readyKey: string) => {
if (rendererReadyKeyRef.current === readyKey) {
Expand Down Expand Up @@ -415,6 +418,7 @@ export function ViewerShell() {
fragmentLength={fragmentLength}
hash={hash}
onArtifactSelect={handleArtifactSelect}
onPreviewHash={setFragmentHash}
onRendererReady={markRendererReady}
rendererReadyKey={rendererReadyKey}
statusTone={statusTone}
Expand Down
Loading
Loading