This commit is contained in:
seb
2026-10-07 20:36:50 +02:00
parent 857963b1c3
commit a29ad50b74
18 changed files with 1024 additions and 220 deletions

View File

@@ -4,42 +4,70 @@ Protected. Requires a valid session cookie (`credentials: 'include'`).
Get a virtual filesystem file
Returns a file the model produced in the `javascript_execute` sandbox
(virtual filesystem), for the authenticated user's selected company.
Returns a file from the virtual filesystem for the authenticated user's selected company.
Commonly used to retrieve artifacts generated by the model in the `javascript_execute` sandbox or uploaded by users.
Embed the returned URL in chat markdown to display a generated image:
`![title](/api/vfs/example.png)`.
### URL Format
Accepts:
- Relative VFS paths: `example.png`, `reports/summary.pdf`
- Full endpoint paths: `/vfs/example.png`, `/api/vfs/example.png` (leading `api/` and `vfs/` prefixes are automatically stripped)
- Absolute URLs: `https://.../api/vfs/example.png`
- Traversal (`..`), null bytes (`\0`), and backslashes (`\`) are strictly forbidden and rejected with HTTP 400.
Images are returned as a 250x250 aspect-preserving preview unless requested with
`download=1` or `raw=1`.
Browser-compatible files (HTML, CSS, JS, JSON, PDF, text, images, media) are served
inline so they open directly in the browser; other files are sent as downloads.
### Image Previews & Thumbnails
Supported raster images (`image/png`, `image/jpeg`, `image/gif`, `image/webp`, `image/avif`, `image/bmp`)
are automatically transformed into a **250×250 aspect-preserving preview thumbnail** (WebP format, quality 88):
- Scaled to fit within a 250×250 box without distortion (e.g. 2000×100 becomes 250×13).
- Images whose larger edge is below 100px are upscaled to 100px for icon legibility.
- A translucent dark metadata strip (`#101317`, max 50% height) with monospace text (`DejaVu Sans Mono`)
is rendered along the bottom edge, displaying original dimensions and file size.
- Served with `Content-Security-Policy: default-src 'none'; sandbox`.
- Use `?raw=1` (or `?raw=true`) to bypass preview generation and return the original unmodified image inline.
### Inline vs Attachment
- Browser-compatible types (HTML, CSS, JS, JSON, PDF, text, images, audio, video, fonts, WASM)
are served with `Content-Disposition: inline; filename="..."` so they open directly in modern browsers.
- Non-browser/binary types default to `Content-Disposition: attachment; filename="..."`.
- Use `?download=1` (or `?download=true`) to force file download with `Content-Disposition: attachment`.
### Caching & Conditional Requests
- Generates weak ETags (`W/"thumb-..."` for previews, `W/"<timestamp>-<mode>"` for originals).
- Sets `Cache-Control: private, max-age=0, must-revalidate`.
- Supports `If-None-Match` conditional requests returning HTTP `304 Not Modified`.
## Path parameters
| Param | Required | Type | Description |
|-------|----------|------|-------------|
| `path` | yes | string | VFS file path (e.g. `example.png`, `labels/a.png`) |
| `path` | yes | string | VFS file path (e.g. `example.png`, `charts/graph.svg`) |
## Query parameters
| Param | Required | Type | Description |
|-------|----------|------|-------------|
| `download` | no | boolean | Force file download with Content-Disposition: attachment.
|
| `raw` | no | boolean | Return original unmodified image inline without generating a preview thumbnail.
|
| `download` | no | boolean | Force file download with Content-Disposition: attachment (1 or true). |
| `raw` | no | boolean | Return original unmodified image inline without generating a preview thumbnail (1 or true). |
## Response `200`
File bytes
File bytes. Served inline for browser-renderable formats or as a download.
Includes headers:
- `Content-Type`: MIME type of file, or `image/webp` for previews
- `Content-Length`: Size of served payload in bytes
- `Content-Disposition`: `inline; filename="..."` or `attachment; filename="..."`
- `Cache-Control`: `private, max-age=0, must-revalidate`
- `ETag`: Weak ETag identifier
- `X-Content-Type-Options`: `nosniff`
- `Content-Security-Policy`: `default-src 'none'; sandbox` (for preview thumbnails)
## Errors
| Status | Description |
|--------|-------------|
| 400 | Invalid path, or no company selected — `{"error":"…"}` |
| 304 | Not modified (If-None-Match matched ETag) |
| 400 | Invalid path, path escapes VFS boundary, or no company selected — `{"error":"…"}` |
| 401 | Unauthorized — `{"error":"…"}` |
| 403 | Not authorized — `{"error":"…"}` |
| 404 | File not found — `{"error":"…"}` |