feat(pheby): accept inbound chat attachments
This commit is contained in:
+37
-3
@@ -1,7 +1,7 @@
|
||||
# Pheby Protocol v1 — Specification
|
||||
|
||||
JSON messages over WebSocket, plus one authenticated HTTPS endpoint for
|
||||
attachment downloads. Every message (both directions) carries a `"type"`.
|
||||
JSON messages over WebSocket, plus authenticated HTTPS endpoints for
|
||||
attachment uploads and downloads. Every message (both directions) carries a `"type"`.
|
||||
Client→server requests MAY carry a `"request_id"` (any client-chosen string);
|
||||
the direct reply echoes it. Server→client events are broadcast to all
|
||||
authenticated connections (single-user app — typically one client).
|
||||
@@ -145,6 +145,15 @@ message (the agent sees the whole transcript).
|
||||
→ { "type": "chat.send", "conversation_id": "a1b2…", "text": "What's the weather?", "request_id": "r6" }
|
||||
```
|
||||
|
||||
`attachment_ids` is an optional list of up to 10 distinct inbound upload IDs
|
||||
from `POST /attachments` in the **same conversation**. The adapter rejects
|
||||
unknown, already-sent, or cross-conversation IDs. Upload first, then include
|
||||
all IDs in the single `chat.send`; a rejected active run leaves them retryable.
|
||||
The `text` field is still required and nonblank (for file-only sends, provide
|
||||
a short caption). A successful send anchors the attachments to the user turn
|
||||
and broadcasts `attachment.added`. Small text files are included in agent
|
||||
context; other files remain available to the agent as local media paths.
|
||||
|
||||
### Server → Client run lifecycle
|
||||
|
||||
```json
|
||||
@@ -316,7 +325,31 @@ metadata so it can be restored after the gateway restarts.
|
||||
|
||||
---
|
||||
|
||||
## Attachments (agent → client deliverables)
|
||||
## Attachments (both directions)
|
||||
|
||||
### Client → agent uploads
|
||||
|
||||
```
|
||||
POST /attachments?conversation_id=a1b2…&filename=notes.md
|
||||
Authorization: Bearer <PHEBY_SECRET>
|
||||
Content-Type: text/markdown
|
||||
|
||||
# Raw file bytes, not multipart or JSON
|
||||
```
|
||||
|
||||
Returns `201 {"attachment": {"attachment_id": "<32 hex chars>", ...}}`.
|
||||
The descriptor contains `direction: "inbound"`, `message_id: null`, and the
|
||||
same fields as agent deliverables below. An upload is **not** broadcast or
|
||||
listed in conversation history until `chat.send` successfully claims it;
|
||||
an unused upload expires with normal retention. Limit: 64 MiB per file.
|
||||
Missing credentials → 401; bad conversation ID or empty body → 400;
|
||||
oversize body → 413. The file picker may select up to 10 files per message.
|
||||
The server keeps only registered copies in adapter-owned storage and never
|
||||
trusts a client-provided path. Markdown and other small `text/*` files
|
||||
(up to 100 KiB) are inlined into the agent's turn; the conversation history
|
||||
returns just the user's original message text.
|
||||
|
||||
### Agent → client deliverables
|
||||
|
||||
When the agent produces a file (image, document, audio, video… via Hermes's
|
||||
normal `MEDIA:` deliverable pipeline), the server copies it into
|
||||
@@ -332,6 +365,7 @@ adapter-managed storage and broadcasts:
|
||||
"size": 48213,
|
||||
"kind": "image" | "voice" | "video" | "audio" | "document",
|
||||
"inline_image": false,
|
||||
"direction": "outbound",
|
||||
"conversation_id": "a1b2…",
|
||||
"message_id": "draft-8c1f…" | null,
|
||||
"created_at": "2026-09-02T18:30:00+00:00",
|
||||
|
||||
Reference in New Issue
Block a user