MCPcopy Index your code
hub / github.com/cloudflare/agents / AssistantDirectory

Class AssistantDirectory

examples/assistant/src/server.ts:157–580  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

155// registry wins.
156
157export class AssistantDirectory extends Agent<Env, DirectoryState> {
158 initialState: DirectoryState = { chats: [] };
159
160 /**
161 * Shared workspace for every chat under this directory. Backed by the
162 * directory's own SQLite so all of a user's files live in one place —
163 * a `hello.txt` written in chat A shows up verbatim in chat B.
164 *
165 * Children (`MyAssistant` facets) see this workspace through the
166 * `SharedWorkspace` proxy below, which forwards each call to
167 * `readFile` / `writeFile` / etc. here. See `SharedWorkspace`.
168 *
169 * The `onChange` hook fires on every mutation (create/update/delete)
170 * regardless of which chat's tool caused it. We rebroadcast to every
171 * client connected to this directory — that's every browser tab the
172 * user has open — so live UI like the file browser refreshes across
173 * chats and tabs without polling. See `_broadcastWorkspaceChange`.
174 *
175 * Security note: this means any tool running inside any chat has
176 * read-write access to every file this user owns. That's the point —
177 * a multi-chat assistant should remember what it did in previous
178 * chats — but extensions declared with `workspace: "read-write"`
179 * inherit the same reach. If you fork this example for a
180 * less-trusted extension surface, add gating here.
181 */
182 workspace = new Workspace({
183 sql: this.ctx.storage.sql,
184 name: () => this.name,
185 onChange: (event) => this._broadcastWorkspaceChange(event)
186 // r2: this.env.R2 — uncomment to spill large files to R2.
187 });
188
189 /**
190 * Fan-out: push workspace change events to every client connected to
191 * this directory. Each chat pane's `useAgent` connection to the
192 * directory (via `useChats()`) receives these; the client side
193 * treats them as signals to refresh workspace-backed UI.
194 *
195 * Deliberately a best-effort `broadcast` (not `setState`), so file
196 * churn doesn't trigger full `DirectoryState` re-broadcasts on every
197 * write. Does NOT notify sibling child facets — no tool in this
198 * example reacts server-side to another chat's writes. Add a
199 * parent → child RPC here if that use case shows up.
200 */
201 private _broadcastWorkspaceChange(event: WorkspaceChangeEvent): void {
202 this.broadcast(JSON.stringify({ type: "workspace-change", event }));
203 }
204
205 onStart() {
206 this.sql`CREATE TABLE IF NOT EXISTS chat_meta (
207 id TEXT PRIMARY KEY,
208 title TEXT NOT NULL,
209 updated_at INTEGER NOT NULL,
210 last_message_preview TEXT
211 )`;
212 this._refreshState();
213
214 // The directory owns cross-chat scheduled work. Facets can't

Callers

nothing calls this directly

Calls 2

callableFunction · 0.90

Tested by

no test coverage detected