Chats: the change feed of your files
The change feed tells a client which of your files changed, as it happens. A change can come from anywhere: you in another tab, a chat that wrote a file with a tool, an upload, a trigger run, a connector, another API client, or another frontend of a cluster. The web UI uses it to refresh what it shows without a reload.
The files are the workspace of the chats, so the feed
needs the chats feature, which is on by default. When the server has no
files (no data path), the stream answers 409 with the type files_off.
Open the stream
The answer is a stream of server-sent events:
| Event | Data | Meaning |
|---|---|---|
change | revision, paths, kinds | Files in your home folder changed. |
resync | revision | Some changes were left out. Read again everything you show. |
pathsare inside your home folder, without a leading slash (pages/tasks/index.html). A move gives the old and the new path. A folder that a write created is a path too. You never see a path you cannot read, and never a path of another user.kindsare the kinds of the change sets:user(a change you made in the UI or the API),agent(a chat),uploadandundo.revisionis the revision of the newest change in the event. It is also the event id.- Changes that arrive close together come as one event. The feed reads the record of changes about once a second, so expect up to a second of delay.
- A comment line (
: ping) comes every 25 seconds, so that idle proxies keep the connection open.
Resume after a disconnect
Without a resume point the stream starts from now. To get the changes you
missed, send the last event id back: a browser EventSource sends it by itself
as the Last-Event-ID header when it reconnects, and a client that opens a new
stream can send ?after=<revision>.
When more than 500 changes to your files have happened since that revision, the stream
starts with a resync event instead of the changes.
Limits
- At most 8 open streams per user. One more answers
429. The web UI opens one stream per browser tab, whatever the number of pages that listen. - A client that does not read fast enough does not slow anything down: when
its queue is full, the queued events are replaced by one
resyncevent.
Several frontends
The feed keeps no state that frontends must share. Every change to a file is written, with a revision, to the record of changes of the workspace (the journal), and revisions are committed in order. In a cluster the journal is in the shared database, so each frontend reads the same record, and a change that any process made reaches the clients of every frontend. Nothing goes over the message bus: the bus delivers a message at most once, the journal does not lose one.
Each frontend reads the journal only while at least one client is connected to it: one small query per second, and one query per user whose files changed. The position in the journal of each frontend and of each client is kept in that process only. After a restart it starts again from the newest revision, and a client that reconnects gives its own position back.
A server without a database keeps the journal in a folder (the JSON index). That server runs alone, so the feed is local too.
In the web UI
Pages of the React UI listen through one shared stream per tab
(useWorkspaceFeed). They also refresh when the window gets the focus again
and when a chat turn ends, in case the stream was down. The Files page
reads the open folder again when something in it changes, so a file that a
chat or another tab writes shows up without a reload.
