Add json and csv artifact kinds with interactive viewers
Gap 1 from planning/2026-09-02-artifact_kind_gaps_for_frequent_agent_output.md. Chose new first-class kinds over riding on html_fragment, resolving that doc's open design question in favor of filtering support, raw-source preservation (like markdown's .md sidecar), and server-owned validation. - json: validated with json.loads at post time (400 on invalid JSON), rendered with renderjson (collapsible tree), vendored locally. - csv: parsed server-side with the stdlib csv module into columns/rows and handed to Grid.js as plain data - no client-side CSV-parsing plugin needed, keeping normalization server-owned. Vendored locally (MIT). - Both preserve their original text as a sidecar file, generalizing what was previously markdown-only handling (storage.py's SIDECAR_SUFFIXES) so disk-size accounting, eviction cleanup, and ?raw=1 all cover json/csv too. - Raw JSON is embedded in a <script type="application/json"> block with `</script` occurrences escaped (safe because JSON's \/ escape round-trips correctly) - verified with a live </script>-injection payload against the actual running server, not just unit tests. New migration (0012) for the KIND_CHOICES change - SQLite doesn't enforce choices at the schema level, but Django's migration state tracks it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
af9ecf28a9
commit
e5d2f192df
12 changed files with 476 additions and 18 deletions
14
docs/api.md
14
docs/api.md
|
|
@ -35,6 +35,12 @@ Currently supported kinds:
|
|||
| `image` | Multipart file | Browser image preview | No |
|
||||
| `pdf` | Multipart file | Browser PDF preview | No |
|
||||
| `binary` | Multipart file | Stored and downloadable | No |
|
||||
| `json` | JSON text | Interactive collapsible tree view (must be valid JSON) and original text is preserved | Yes |
|
||||
| `csv` | JSON text | Interactive sortable/searchable table (parsed server-side) and original text is preserved | Yes |
|
||||
|
||||
`json` and `csv` content is required to be a JSON/DRF **string** field even
|
||||
though the value itself is JSON/CSV text — i.e. `{"kind": "json", "content":
|
||||
"{\"a\": 1}"}`, not a nested JSON object in the request body.
|
||||
|
||||
## Source Fields
|
||||
|
||||
|
|
@ -84,15 +90,17 @@ Required fields:
|
|||
| Field | Notes |
|
||||
|---|---|
|
||||
| `source` | Required. Max 80 characters. |
|
||||
| `kind` | One of `html_fragment`, `html_full`, `markdown`, `deck`. |
|
||||
| `kind` | One of `html_fragment`, `html_full`, `markdown`, `deck`, `json`, `csv`. |
|
||||
| `title` | Required. Max 200 characters. |
|
||||
| `content` | Required text content. Must match the shape `kind` implies — see below. |
|
||||
|
||||
`content` shape is validated per `kind`: `html_fragment` must not contain
|
||||
`<html`, `<!doctype`, or `<body` (body-only HTML, wrapped in a theme
|
||||
server-side); `html_full` must contain `<html`; `deck` must contain
|
||||
`<section`; `markdown` must not be blank or whitespace-only. A mismatch
|
||||
returns `400`.
|
||||
`<section`; `markdown` must not be blank or whitespace-only; `json` must be
|
||||
valid JSON (`json.loads` must succeed). `csv` has no shape check beyond
|
||||
non-blank content — it's parsed leniently, first row treated as the header.
|
||||
A mismatch returns `400`.
|
||||
|
||||
Optional fields:
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue