MCPcopy Index your code
hub / github.com/coder/mux / dispatch

Method dispatch

src/node/services/agentStatusService.ts:166–223  ·  view source on GitHub ↗
(tickStartedAt: number)

Source from the content-addressed store, hash-verified

164 }
165
166 private async dispatch(tickStartedAt: number): Promise<void> {
167 const focused = this.windowService.isFocused();
168 // One disk read per tick for streaming state across all workspaces.
169 // Cheap, and avoids N reads inside the inner loop.
170 const snapshots = await this.extensionMetadata.getAllSnapshots();
171
172 // Sort eligible workspaces by lastRanAt ascending. With MAX_CONCURRENT=1,
173 // a fixed iteration order would let the first workspace starve the rest;
174 // least-recently-run gives fair round-robin without an explicit queue.
175 const eligible: Array<{
176 id: string;
177 lastRanAt: number;
178 recency: number | null;
179 recencyAdvanced: boolean;
180 }> = [];
181 for (const [, projectConfig] of this.config.loadConfigOrDefault().projects) {
182 for (const ws of projectConfig.workspaces) {
183 const id = ws.id ?? ws.name;
184 if (typeof id !== "string" || id.length === 0) continue;
185 if (isWorkspaceArchived(ws.archivedAt, ws.unarchivedAt)) continue;
186 const state = this.tracked.get(id);
187 if (state?.inFlight) continue;
188 const snapshot = snapshots.get(id);
189 const recency = typeof snapshot?.recency === "number" ? snapshot.recency : null;
190 const recencyAdvanced = hasRecencyAdvanced(state, recency);
191 const interval = pickInterval(snapshot?.streaming === true, focused);
192 if (state && !recencyAdvanced && tickStartedAt - state.lastRanAt < interval) continue;
193 eligible.push({ id, lastRanAt: state?.lastRanAt ?? 0, recency, recencyAdvanced });
194 }
195 }
196 eligible.sort((a, b) => {
197 if (a.recencyAdvanced !== b.recencyAdvanced) {
198 // A user message is usually a task pivot. Put those workspaces ahead
199 // of ordinary cadence refreshes so stale pre-pivot statuses don't
200 // linger behind background idle work.
201 return a.recencyAdvanced ? -1 : 1;
202 }
203 return a.lastRanAt - b.lastRanAt;
204 });
205
206 for (const { id, recency } of eligible) {
207 if (this.stopped || this.inFlightPromises.size >= AGENT_STATUS_MAX_CONCURRENT) return;
208 const state = this.ensureState(id);
209 state.inFlight = true;
210 // Set lastRanAt at dispatch time (not after the async transcript
211 // build) so cadence is anchored to tick boundaries — see runTick.
212 state.lastRanAt = tickStartedAt;
213 // Forward the live streaming bit so the prompt can lock in
214 // present-progressive tense when the assistant is mid-response.
215 // Snapshots were already read once per tick above.
216 const streaming = snapshots.get(id)?.streaming === true;
217 const promise = this.runForWorkspace(id, recency, streaming).finally(() => {
218 state.inFlight = false;
219 this.inFlightPromises.delete(promise);
220 });
221 this.inFlightPromises.add(promise);
222 }
223 }

Callers 1

runTickMethod · 0.95

Calls 12

ensureStateMethod · 0.95
runForWorkspaceMethod · 0.95
isWorkspaceArchivedFunction · 0.90
hasRecencyAdvancedFunction · 0.85
pickIntervalFunction · 0.85
isFocusedMethod · 0.80
getAllSnapshotsMethod · 0.80
loadConfigOrDefaultMethod · 0.80
addMethod · 0.80
getMethod · 0.65
pushMethod · 0.65
deleteMethod · 0.45

Tested by

no test coverage detected