Uploads
Single-file upload + text extraction for inline RAG injection. The chat handler embeds the returned ExtractedFile into the next chat completion's user message via packages.gateway.uploads.render_for_prompt, so an operator UI can drag-and-drop a PDF or DOCX into the chat box without separately ingesting it into the knowledge base.
This is the inline / one-shot path — for persistent RAG ingest, use the knowledge-base routes covered in 09 — Knowledge bases.
The router lives at packages/gateway/upload_routes.py.
Endpoints
| Method | Path | Auth | Summary |
|---|---|---|---|
| POST | /v1/uploads | Bearer | Accept one file; return its extracted text + metadata. |
POST /v1/uploads
Multipart multipart/form-data body with a single file field.
Returns ExtractedFile (packages/gateway/uploads.py:76):
{
"filename": "spec.pdf",
"mime_type": "application/pdf",
"byte_size": 124533,
"content": "Title page\n\nSection 1 …"
}The content field is plain UTF-8 text with the file's extracted prose — page breaks are flattened to blank lines.
curl -X POST -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
-F "file=@spec.pdf" \
http://localhost:8000/v1/uploadsSupported formats
The default install handles plain text, JSON, YAML, XML, TOML, Markdown, JavaScript, and shell scripts via the built-in MIME allowlist (packages/gateway/uploads.py). Operators who want PDF or DOCX support install one of the optional extras groups:
| Extra | What it adds |
|---|---|
bigwave[uploads-pdf] | pypdf — extracts text from application/pdf. |
bigwave[uploads-docx] | python-docx — extracts text from .docx. |
PDF / DOCX uploads return 400 Bad Request with "unsupported MIME" until the extra is installed; the route does not lazy-fail at extraction time.
Operator notes
- Size limit. Defaults to
DEFAULT_MAX_BYTES(packages/gateway/uploads.py). Override per-process by settingapp.state.uploads_max_bytesbefore the lifespan completes; the route reads it on every call. Oversize uploads return400with"upload <name> is N bytes; max is M bytes". - Image / audio / video. Returns
400withUnsupportedMimeError— multimodal handling is not part of this surface. Use a chat completion with an image part instead. - Workspace scoping. Auth is required (
AuthPrincipal) but the route does not persist anything per-workspace — extraction is stateless. The chat handler that embeds the result is the workspace boundary. - Errors.
400for missing filename, oversize, unsupported MIME, or extraction-library failure.extract_textraises subclasses ofUploadError; the route maps the message verbatim. - Streaming. Not supported. The whole file is read into memory, extracted, and returned. Stream large corpora through the knowledge-base ingest path instead.