Files
coder/agent/agentfiles
Michael Suchacz 7c74fa3548 feat: add workspace file upload agent API (#27078)
## What

Adds a dedicated workspace-agent endpoint, `POST
/api/v0/upload-chat-file`, that streams a request body into the chat's
upload directory `~/.coder/chats/<chat-id>/files/<name>`, plus the SDK
plumbing to call it:

- `coderd/x/chatfiles`: upload-name sanitization
(`SanitizeWorkspaceUploadName`), collision suffixes (compound extensions
such as `.tar.gz` stay intact: `archive_2.tar.gz`), and the shared
`~/.coder/chats/<id>/files` path layout.
- `agent/agentfiles`: the HTTP handler. On Linux/macOS the directory
chain is opened with `openat(O_NOFOLLOW)`, so symlinked path components
are rejected. The body streams into a hidden `.<name>.upload-<random>`
temp file and is published under its final name only when complete, via
`linkat` over the `_2`, `_3`, ... collision sequence, so existing files
are never overwritten and a half-written file is never visible under its
final name. Filesystems without hard links fall back to an exclusive
placeholder plus `renameat`. Other platforms use an afero-based fallback
with the same semantics. Stale temp files older than an hour are swept
before each upload, and failures are logged with a structured warning.
- `codersdk/workspacesdk`: `AgentConn.UploadChatFile` + regenerated
`agentconnmock`.

## Why

Coder Agents chat can attach images/text/PDF to prompts, but arbitrary
files (zips, datasets, binaries) have nowhere to land where the agent's
tools can act on them. This is the agent-side foundation; the coderd
route that fronts it is stacked on top.

Design notes:

- There is deliberately no size cap; the resource profile matches
existing SSH/WebSocket proxying, and client cancellation aborts the
stream (a failed write removes the temp file, so no partial files
remain). Because the agent HTTP server uses fixed 20 s read/write
timeouts, the handler pushes both deadlines forward on every received
chunk, so a slow upload only fails after a 20 s stall. If the connection
does not support deadline changes, the agent logs one warning per
request.
- This endpoint is not gated by `CODER_AGENT_BLOCK_FILE_TRANSFER`. That
flag targets SSH-transport file tools (scp/rsync/sftp). Chat uploads are
an agent API capability like `write-file` and `edit-files`, which
already bypass the flag; the interaction is documented in the FAQ.

## How tested

- `go test ./agent/agentfiles ./coderd/x/chatfiles
./codersdk/workspacesdk` (unit + umask/symlink/collision integration
tests).
- UAT on a dogfood-style deployment (2026-09-21): uploads longer than 20
s went from 502 to 201 once the workspace agent was restarted on this
build; a coderd restart alone keeps the old agent running, so the
per-chunk deadline extension needs the agent rolled (older agents get
the 409 "Restart the workspace" from #27079).

Part of CODAGT-211. Stack: agent API (this PR) -> coderd endpoint -> UI.

> This PR was authored by Mux (AI) working on Mike's behalf.
2026-09-25 09:05:51 +02:00
..