Changeset 0.28.0.1 (#173)
This commit is contained in:
146
docs/ICD/utility.md
Normal file
146
docs/ICD/utility.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Export & Utility
|
||||
|
||||
### Health Check
|
||||
|
||||
```
|
||||
GET /health → { "status": "ok" }
|
||||
```
|
||||
|
||||
Public, no auth. Also available at `/api/v1/health`.
|
||||
|
||||
### Export
|
||||
|
||||
Convert markdown to PDF or DOCX via pandoc:
|
||||
|
||||
```
|
||||
POST /export
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"content": "# My Document\n\nBody text...",
|
||||
"format": "pdf|docx",
|
||||
"filename": "my-document"
|
||||
}
|
||||
```
|
||||
|
||||
Returns the binary file with appropriate Content-Type. Requires
|
||||
`pandoc` in the container (available in the unified and backend
|
||||
Docker images).
|
||||
|
||||
---
|
||||
|
||||
## 17b. Files & Storage
|
||||
|
||||
All binary content in Chat Switchboard flows through a single
|
||||
**ObjectStore** abstraction backed by PVC (filesystem) or S3. All
|
||||
file metadata lives in one `files` table. The old `attachments`
|
||||
table is dropped.
|
||||
|
||||
### Storage Backend
|
||||
|
||||
| Operation | Description |
|
||||
|-----------|-------------|
|
||||
| `Put(key, reader, size, contentType)` | Store a blob |
|
||||
| `Get(key)` → reader, size, contentType | Retrieve a blob |
|
||||
| `Delete(key)` | Remove a blob |
|
||||
| `DeletePrefix(prefix)` | Bulk remove (channel deletion) |
|
||||
| `Exists(key)` | Check without reading |
|
||||
| `Healthy()` | Backend health check |
|
||||
| `Stats()` | Aggregate metrics |
|
||||
|
||||
Backends: `pvc` (`STORAGE_PATH=/data/storage`) or `s3`
|
||||
(`S3_ENDPOINT`, `S3_BUCKET`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`).
|
||||
|
||||
### Key Namespacing
|
||||
|
||||
| Prefix | Pattern | What |
|
||||
|--------|---------|------|
|
||||
| `attachments/` | `attachments/{channel_id}/{file_id}_{filename}` | User uploads + AI outputs (legacy prefix retained for existing blobs) |
|
||||
| `kb/` | `kb/{kb_id}/{doc_id}_{filename}` | Knowledge base documents |
|
||||
| `exports/` | `exports/{user_id}/{export_id}_{filename}` | Chat/data exports |
|
||||
| `workspace/` | `workspace/{workspace_id}/{path}` | Workspace files |
|
||||
|
||||
### File Object
|
||||
|
||||
```sql
|
||||
CREATE TABLE files (
|
||||
id UUID PRIMARY KEY,
|
||||
channel_id UUID REFERENCES channels(id) ON DELETE CASCADE,
|
||||
message_id UUID REFERENCES messages(id) ON DELETE SET NULL,
|
||||
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
project_id UUID REFERENCES projects(id) ON DELETE SET NULL,
|
||||
origin TEXT NOT NULL DEFAULT 'user_upload'
|
||||
CHECK (origin IN ('user_upload','tool_output','system')),
|
||||
filename TEXT NOT NULL,
|
||||
content_type TEXT NOT NULL DEFAULT 'application/octet-stream',
|
||||
size_bytes BIGINT NOT NULL DEFAULT 0,
|
||||
storage_key TEXT NOT NULL,
|
||||
display_hint TEXT NOT NULL DEFAULT 'download'
|
||||
CHECK (display_hint IN ('inline','download','thumbnail')),
|
||||
extracted_text TEXT,
|
||||
metadata JSONB DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
**Origin:**
|
||||
|
||||
| Value | Who creates | Examples |
|
||||
|-------|-------------|---------|
|
||||
| `user_upload` | User via upload UI | PDF, image, doc attached to message |
|
||||
| `tool_output` | Tool execution during completion | DALL-E image, video gen, code artifact |
|
||||
| `system` | Platform | Export, avatar stored as file |
|
||||
|
||||
**Display hint:**
|
||||
|
||||
| Value | Frontend behavior |
|
||||
|-------|-------------------|
|
||||
| `inline` | Render in message stream (images, video, audio, HTML) |
|
||||
| `download` | Filename + size + download button |
|
||||
| `thumbnail` | Thumbnail preview, click to expand |
|
||||
|
||||
### Tool Output Flow
|
||||
|
||||
1. Tool executes (image gen, video render, etc.)
|
||||
2. Tool writes blob via `ObjectStore.Put`
|
||||
3. Tool creates file record: `POST /files` with `origin: "tool_output"`, `message_id` = current assistant message
|
||||
4. Tool result includes `file_id` reference
|
||||
5. WebSocket emits `file.created` event:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "file.created",
|
||||
"channel_id": "uuid",
|
||||
"message_id": "uuid",
|
||||
"file": { ...file object... }
|
||||
}
|
||||
```
|
||||
|
||||
6. Frontend renders inline based on `display_hint` + `content_type`
|
||||
|
||||
The event fires during streaming so the user sees the artifact
|
||||
before the completion finishes.
|
||||
|
||||
### Content Type → Display Hint Defaults
|
||||
|
||||
| Content Type | Default Hint | Rendering |
|
||||
|-------------|-------------|-----------|
|
||||
| `image/*` | `inline` | `<img>` in message, lightbox on click |
|
||||
| `video/*` | `inline` | `<video>` player |
|
||||
| `audio/*` | `inline` | `<audio>` player |
|
||||
| `text/html` | `inline` | Sandboxed iframe |
|
||||
| `application/pdf` | `thumbnail` | Thumb + PDF viewer on click |
|
||||
| `text/*`, `application/json` | `inline` | Syntax-highlighted code block |
|
||||
| Everything else | `download` | Filename + download button |
|
||||
|
||||
Tools can override the default hint explicitly.
|
||||
|
||||
### File Manager (Future Surface)
|
||||
|
||||
A user-scoped file browser backed by `GET /files?page=1&per_page=50`.
|
||||
Displays all files owned by the user across all channels, grouped by
|
||||
channel or date. Supports download and delete. Deleting a file that
|
||||
is referenced by a message replaces the inline render with a
|
||||
"file deleted" placeholder.
|
||||
Reference in New Issue
Block a user