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
7 changes: 4 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Core product traits right now:
Treat these as core constraints unless the owner explicitly changes the product direction.

- The app is a single exported client-side shell, not a backend product.
- Artifact payloads live in the URL fragment, using `#agent-render=v1.<codec>.<payload>` for `plain|lz|deflate`, `#agent-render=v1.arx.<dictVersion>.<payload>` for `arx`, and `#agent-render=v1.arx2.<dictVersion>.<payload>` for `arx2`.
- Artifact payloads live in the URL fragment, using the compact `#<tag><payload>` form where the single tag char identifies the codec: `p` plain, `l` lz, `d` deflate, `a` arx, `b` arx2. Legacy `#agent-render=v1.<codec>.<dictVersion>.<payload>` links still decode but are no longer emitted.
- The deployed host should not receive artifact contents as part of the initial page request.
- Supported artifact kinds are `markdown`, `code`, `diff`, `csv`, and `json`.
- Supported codecs are `plain`, `lz`, `deflate`, `arx`, and `arx2`.
Expand Down Expand Up @@ -83,8 +83,9 @@ Rules:
The fragment transport is part of the product surface, not an implementation detail.

Current rules:
- fragment key: `agent-render`
- format: `v1.<codec>.<payload>` for `plain|lz|deflate`, `v1.arx.<dictVersion>.<payload>` for `arx`, and `v1.arx2.<dictVersion>.<payload>` for `arx2`
- fragment key: `agent-render` (legacy decode path only; the compact form has no key)
- emitted format: compact `#<tag><payload>`, where the single tag char identifies the codec (`p` plain, `l` lz, `d` deflate, `a` arx, `b` arx2); the tag also encodes the active dictionary version for `arx`/`arx2`
- legacy format (still decodable, no longer emitted): `agent-render=v1.<codec>.<payload>` for `plain|lz|deflate`, `agent-render=v1.arx.<dictVersion>.<payload>` for `arx`, and `agent-render=v1.arx2.<dictVersion>.<payload>` for `arx2`
- codecs: `plain`, `lz`, `deflate`, `arx`, and `arx2`
- fragment size budget: `8192` characters
- decoded payload budget: `200000` characters
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ The fragment protocol keeps the JSON envelope stable and treats compression stri
- `lz` stores compressed JSON via `lz-string` when it produces a smaller fragment
- `deflate` stores deflate-compressed UTF-8 JSON bytes when it outperforms other codecs
- `arx` applies domain-dictionary substitution, brotli compression (quality 11), and binary-to-text encoding for best-in-class compression. Four wire shapes are candidates: base76 (ASCII, 77 fragment-safe chars), base64url (RFC 4648 `A-Za-z0-9-_` with a `B.` prefix for detection), base1k (Unicode, 1774 chars from U+00A1–U+07FF), and baseBMP (high-density Unicode, ~62k safe BMP code points from U+00A1–U+FFEF, ~15.92 bits/char). The async encoder tries all four and picks the shortest **transport** length (percent-encoded UTF-8 length for non-ASCII), so base64url can win over Unicode encodings on chat-style surfaces. baseBMP produces ~32% fewer characters than base1k and ~55% fewer than base76 for the same compressed bytes, achieving ~70% smaller fragments than deflate on typical payloads (~6.1x compression ratio for 8k markdown). Full pipeline timing is on the order of ~8–14ms for 8k payloads depending on the wire encoding. The substitution dictionary is served as a static file at `/arx-dictionary.json` so agents can fetch it for local compression; a pre-compressed `/arx-dictionary.json.br` variant is also available. The viewer tries the pre-compressed dictionary first on default ARX-family loads, falls back to the JSON file, and only loads external dictionaries when an ARX/ARX2/ARX3 encode or decode path needs them.
- `arx2` keeps the arx compression stack but replaces the JSON envelope with a compact tuple envelope and applies `/arx2-dictionary.json` as an overlay before the shared arx dictionary. The viewer tries `/arx2-dictionary.json.br` first for default overlay loads and falls back to JSON. It uses `v1.arx2.<dictVersion>.<payload>` and decodes back to the standard envelope before validation/rendering.
- `arx2` keeps the arx compression stack but replaces the JSON envelope with a compact tuple envelope and applies `/arx2-dictionary.json` as an overlay before the shared arx dictionary. The viewer tries `/arx2-dictionary.json.br` first for default overlay loads and falls back to JSON. It is emitted with the compact `b` tag (which encodes the dictionary version) and decodes back to the standard envelope before validation/rendering.
- `arx3` uses the same tuple envelope, overlay dictionary, shared arx dictionary, and brotli bytes as arx2, then allows the dense baseBMP wire to win by decoded visible character length. This deliberately optimizes copyable visible URL length for trusted Unicode-preserving surfaces; it is not a stronger compressed-byte format than arx2.
- packed wire mode (`p: 1`) shortens transport keys before compression, then unpacks back to the standard envelope during decode
- automatic async codec selection tries `arx3 -> arx2 -> arx -> deflate -> lz -> plain`; arx compares packed + non-packed candidates, while arx2/arx3 use tuple envelopes
Expand Down
16 changes: 9 additions & 7 deletions docs/payload-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,23 @@ Payload contents are untrusted user content. Viewers, agents, and automations sh
## Fragment shape

```text
#agent-render=v1.<codec>.<payload> (plain | lz | deflate)
#agent-render=v1.arx.<dictVersion>.<payload> (arx)
#agent-render=v1.arx2.<dictVersion>.<payload> (arx2)
#agent-render=v1.arx3.<dictVersion>.<payload> (arx3)
#p<payload> (plain)
#l<payload> (lz)
#d<payload> (deflate)
#a<payload> (arx)
#b<payload> (arx2)
#c<payload> (arx3)
```

The fragment protocol includes version and codec in the outer format so unsupported formats fail cleanly. Fragment URLs can look long because they carry the artifact payload in the browser-only fragment instead of sending it to the host during the page request.
The compact fragment is a single codec tag char followed by the payload. The tag encodes the codec (and, for `arx`/`arx2`/`arx3`, the active dictionary version) so unsupported formats fail cleanly. The legacy `#agent-render=v1.<codec>.<dictVersion>.<payload>` form still decodes for back-compatibility but is no longer emitted. Fragment URLs can look long because they carry the artifact payload in the browser-only fragment instead of sending it to the host during the page request.

Supported codecs:

- `plain` - base64url-encoded JSON
- `lz` - `lz-string` compressed JSON encoded for URL-safe transport
- `deflate` - deflate-compressed UTF-8 JSON bytes encoded as base64url
- `arx` - domain-dictionary substitution + brotli (quality 11) + binary-to-text encoding. arx fragments include dictionary version metadata in the outer format (`v1.arx.<dictVersion>.<payload>`) so links stay portable across dictionary updates. Four wire shapes are tried and the shortest **transport** size wins (see `computeTransportLength` in `fragment.ts` — non-ASCII Unicode may count longer after percent-encoding): **base76** (ASCII-only, 77 fragment-safe chars), **base64url** (standard RFC 4648 alphabet `A-Za-z0-9-_`, no padding, prefixed with `B.` for detection), **base1k** (Unicode, 1774 chars from U+00A1–U+07FF), and **baseBMP** (high-density Unicode, ~62k safe BMP code points from U+00A1–U+FFEF, ~15.92 bits/char). BaseBMP produces ~32% fewer characters than base1k and ~55% fewer than base76 for the same compressed bytes. BaseBMP payloads are prefixed with a U+FFF0 marker for detection. The viewer’s `arxDecompress` auto-detects the wire shape (including the rare case where a base76 length prefix is also `B.` — it tries base64url first and falls back to base76 if Brotli fails). The substitution dictionary is served at `/arx-dictionary.json` with a pre-compressed `/arx-dictionary.json.br` variant; the viewer tries the `.br` file first on default loads and falls back to JSON. The arx2 overlay dictionary follows the same `.br`-then-JSON default load pattern.
- `arx2` - tuple-envelope transport + arx2 overlay substitution + the shared arx dictionary + brotli (quality 11) + the same four binary-to-text wire shapes. arx2 fragments use `v1.arx2.<dictVersion>.<payload>`, where `dictVersion` is the shared arx dictionary version. Existing `arx` links remain valid; async auto-selection keeps arx2 as the conservative transport-measured tuple codec.
- `arx` - domain-dictionary substitution + brotli (quality 11) + binary-to-text encoding. The compact `a` tag encodes the active dictionary version so links stay portable across dictionary updates. Four wire shapes are tried and the shortest **transport** size wins (see `computeTransportLength` in `fragment.ts` — non-ASCII Unicode may count longer after percent-encoding): **base76** (ASCII-only, 77 fragment-safe chars), **base64url** (standard RFC 4648 alphabet `A-Za-z0-9-_`, no padding, prefixed with `B.` for detection), **base1k** (Unicode, 1774 chars from U+00A1–U+07FF), and **baseBMP** (high-density Unicode, ~62k safe BMP code points from U+00A1–U+FFEF, ~15.92 bits/char). BaseBMP produces ~32% fewer characters than base1k and ~55% fewer than base76 for the same compressed bytes. BaseBMP payloads are prefixed with a U+FFF0 marker for detection. The viewer’s `arxDecompress` auto-detects the wire shape (including the rare case where a base76 length prefix is also `B.` — it tries base64url first and falls back to base76 if Brotli fails). The substitution dictionary is served at `/arx-dictionary.json` with a pre-compressed `/arx-dictionary.json.br` variant; the viewer tries the `.br` file first on default loads and falls back to JSON. The arx2 overlay dictionary follows the same `.br`-then-JSON default load pattern.
- `arx2` - tuple-envelope transport + arx2 overlay substitution + the shared arx dictionary + brotli (quality 11) + the same four binary-to-text wire shapes. The compact `b` tag encodes the shared arx dictionary version. Existing `arx` links remain valid; async auto-selection keeps arx2 as the conservative transport-measured tuple codec.
- `arx3` - the same tuple envelope, overlay substitution, shared arx dictionary, and brotli bytes as arx2, with a different selection rule: baseBMP may win by decoded visible character length instead of conservative percent-encoded transport length. This is the compact visible URL mode for trusted surfaces that preserve Unicode fragments. If a platform rewrites, truncates, or previews links aggressively, prefer arx2/base64url or UUID mode instead.

The encoder now also supports a packed wire representation (`p: 1`) that shortens key names before compression. Packed mode is transport-only; decoded envelopes normalize back to the standard shape.
Expand Down
26 changes: 15 additions & 11 deletions docs/url-fragments.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,37 @@
agent-render links carry the artifact in the URL fragment:

```text
https://agent-render.com/#agent-render=v1.arx3.1.<compressed-payload>
https://agent-render.com/#c<compressed-payload>
```

Everything before `#` loads the static app. Everything after `#` is the artifact payload the browser decodes locally.

## What the parts mean

- `agent-render` tells the app this hash belongs to agent-render.
- `v1` is the payload format version.
- `arx3` is the compression codec.
- `1` is the arx dictionary version.
- The first character after `#` is a single codec tag. Here `c` means the `arx3` codec (and its active dictionary version).
- `<compressed-payload>` is the encoded artifact bundle.

Other links may use a shorter shape:
The tag char identifies the codec:

```text
#agent-render=v1.<codec>.<payload>
#p<payload> (plain)
#l<payload> (lz)
#d<payload> (deflate)
#a<payload> (arx)
#b<payload> (arx2)
#c<payload> (arx3)
```

where `<codec>` is `plain`, `lz`, or `deflate`. ARX-family links include the dictionary version:
For `arx`, `arx2`, and `arx3`, the tag also encodes the active dictionary version.

Older links may use the legacy shape, which the viewer still decodes:

```text
#agent-render=v1.arx.<dictVersion>.<payload>
#agent-render=v1.arx2.<dictVersion>.<payload>
#agent-render=v1.arx3.<dictVersion>.<payload>
#agent-render=v1.<codec>.<payload>
```

where `<codec>` is `plain`, `lz`, or `deflate`, and the ARX-family legacy links include the dictionary version (`#agent-render=v1.arx.<dictVersion>.<payload>`, `arx2`, `arx3`). These legacy links are no longer emitted.

## Why arx exists

Artifacts can be bigger than a comfortable URL. The ARX family keeps links shorter by applying agent-render substitution dictionaries, Brotli compression, tuple envelopes for arx2/arx3, and binary-to-text encoding. `arx3` favors compact visible Unicode fragments, so it can look especially strange even though the browser decodes it locally.
Expand Down
42 changes: 26 additions & 16 deletions skills/agent-render-linking/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,23 @@ Source repository:

Keep the artifact content in the URL fragment, not in normal query params.

Use this fragment shape:
Use the compact fragment shape `#<tag><payload>`, where `<tag>` is a single
character identifying the codec:

```text
#agent-render=v1.<codec>.<payload> (plain | lz | deflate)
#agent-render=v1.arx.<dictVersion>.<payload> (arx)
#agent-render=v1.arx2.<dictVersion>.<payload> (arx2)
#agent-render=v1.arx3.<dictVersion>.<payload> (arx3)
#p<payload> (plain)
#l<payload> (lz)
#d<payload> (deflate)
#a<payload> (arx)
#b<payload> (arx2)
#c<payload> (arx3)
```

The single tag char encodes the codec (and, for `arx`/`arx2`/`arx3`, the active
dictionary version); the payload follows immediately after it. The legacy
`#agent-render=v1.<codec>.<dictVersion>.<payload>` form still decodes, but the
viewer no longer emits it — always build the compact form.

Supported codecs:
- `plain`: base64url-encoded JSON envelope
- `lz`: `lz-string` compressed JSON encoded for URL-safe transport
Expand Down Expand Up @@ -166,31 +174,33 @@ Set `activeArtifactId` to the artifact that should open first.

## Link construction

Construct the final URL as:
Construct the final URL with the compact `#<tag><payload>` fragment:

```text
https://agent-render.com/#agent-render=v1.<codec>.<payload> (plain | lz | deflate)
https://agent-render.com/#agent-render=v1.arx.<dictVersion>.<payload> (arx)
https://agent-render.com/#agent-render=v1.arx2.<dictVersion>.<payload> (arx2)
https://agent-render.com/#agent-render=v1.arx3.<dictVersion>.<payload> (arx3)
https://agent-render.com/#p<payload> (plain)
https://agent-render.com/#l<payload> (lz)
https://agent-render.com/#d<payload> (deflate)
https://agent-render.com/#a<payload> (arx)
https://agent-render.com/#b<payload> (arx2)
https://agent-render.com/#c<payload> (arx3)
```

For `plain`:
1. Serialize the envelope as compact JSON
2. Base64url-encode it
3. Append it after `v1.plain.`
3. Prepend the tag `p` (the fragment is `#p<payload>`)

For `lz`:
1. Serialize the envelope as compact JSON
2. Compress with `lz-string` URL-safe encoding
3. Append it after `v1.lz.`
3. Prepend the tag `l` (the fragment is `#l<payload>`)

For `deflate`:
1. Serialize the envelope as compact JSON (or packed wire form)
2. Encode JSON to UTF-8 bytes
3. Deflate the bytes
4. Base64url-encode the compressed bytes
5. Append it after `v1.deflate.`
5. Prepend the tag `d` (the fragment is `#d<payload>`)

## Shared arx dictionaries

Expand All @@ -214,7 +224,7 @@ To use the dictionary for local `arx` encoding:
- Base1k uses 1774 Unicode code points (U+00A1–U+07FF, skipping combining diacriticals and soft hyphen). ~10.79 bits/char
- Base64url: standard `A-Za-z0-9-_` (no padding), prefix `B.` — ASCII-only, survives Discord/Slack/Teams-style handling better than Unicode-heavy fragments
- Base76 uses 77 ASCII fragment-safe characters. ~6.27 bits/char
5. Prepend `v1.arx.<dictVersion>.` to form the fragment payload (use the same dictionary version used for substitution)
5. Prepend the tag `a` to form the fragment (the compact tag encodes the active dictionary version, so use the same dictionary version for substitution)

The dictionary includes JSON envelope boilerplate patterns, JSON-escaped Markdown syntax, and programming-language patterns that are already present in the shipped corpus. The viewer tries the pre-compressed dictionary first on default ARX/ARX2/ARX3 encode or decode paths, falls back to the JSON file, and falls back again to its built-in table if external fetches fail.

Expand All @@ -235,9 +245,9 @@ Then apply substitutions in this order:
2. Fetch and apply `https://agent-render.com/arx-dictionary.json`
3. Brotli-compress at quality 11
4. Try baseBMP, base1k, base64url, and base76; choose the shortest transport representation
5. Prepend `v1.arx2.<dictVersion>.`, using the shared arx dictionary version
5. Prepend the tag `b` (the compact tag encodes the shared arx dictionary version)

For `arx3`, use the same tuple, substitution, and brotli bytes as arx2, then choose the baseBMP wire when the visible character count is the optimization target. Prepend `v1.arx3.<dictVersion>.`, using the shared arx dictionary version. Do not invent a new dictionary entry unless it is backed by corpus evidence and improves the benchmark gate.
For `arx3`, use the same tuple, substitution, and brotli bytes as arx2, then choose the baseBMP wire when the visible character count is the optimization target. Prepend the tag `c` (the compact tag encodes the shared arx dictionary version). Do not invent a new dictionary entry unless it is backed by corpus evidence and improves the benchmark gate.

## Practical limits

Expand Down
14 changes: 7 additions & 7 deletions skills/selfhosted-agent-render/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ POST /api/artifacts
Content-Type: application/json

{
"payload": "agent-render=v1.plain.<base64url-encoded-json>"
"payload": "p<base64url-encoded-json>"
}
```

Expand All @@ -49,7 +49,7 @@ Response (`201`):
}
```

The `payload` field is the same payload string used in fragment links — the fragment body after `#`. Use the same envelope format and codecs (`plain`, `lz`, `deflate`, `arx`, `arx2`, `arx3`) described in the `agent-render-linking` skill.
The `payload` field is the same payload string used in fragment links — the compact fragment body after `#` (a single codec tag char followed by the payload). Use the same envelope format and codecs (`plain`, `lz`, `deflate`, `arx`, `arx2`, `arx3`) described in the `agent-render-linking` skill. The legacy `agent-render=v1.<codec>.<payload>` form is also accepted for back-compatibility.

### Read an artifact

Expand All @@ -62,7 +62,7 @@ Response (`200`):
```json
{
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"payload": "agent-render=v1.plain.<payload>",
"payload": "p<payload>",
"created_at": "2025-04-07T12:00:00.000Z",
"updated_at": "2025-04-07T12:00:00.000Z",
"last_viewed_at": "2025-04-07T14:00:00.000Z",
Expand All @@ -79,7 +79,7 @@ PUT /api/artifacts/:id
Content-Type: application/json

{
"payload": "agent-render=v1.plain.<new-payload>"
"payload": "p<new-payload>"
}
```

Expand Down Expand Up @@ -242,13 +242,13 @@ Encode the envelope using the same codec pipeline as fragment links:

1. Serialize envelope as compact JSON
2. Encode with a codec (`plain` = base64url, `lz` = lz-string, `deflate` = deflate + base64url, or the async arx/arx2/arx3 pipelines)
3. Prepend `agent-render=v1.<codec>.`
3. Prepend the single-character codec tag (`p` plain, `l` lz, `d` deflate, `a` arx, `b` arx2, `c` arx3)
4. POST the resulting string as the `payload` field

For simple cases, `plain` codec is sufficient:

```text
agent-render=v1.plain.<base64url(JSON.stringify(envelope))>
p<base64url(JSON.stringify(envelope))>
```

## TTL behavior
Expand Down Expand Up @@ -357,7 +357,7 @@ PAYLOAD=$(echo -n '{"v":1,"codec":"plain","artifacts":[{"id":"demo","kind":"mark

curl -s -X POST http://localhost:3000/api/artifacts \
-H "Content-Type: application/json" \
-d "{\"payload\": \"agent-render=v1.plain.$PAYLOAD\"}"
-d "{\"payload\": \"p$PAYLOAD\"}"
```

## Cleanup guidance
Expand Down
Loading
Loading