From 7286e63ec5f93b256745359527077b423f0094df Mon Sep 17 00:00:00 2001 From: can1357 Date: Wed, 13 May 2026 06:15:28 +0200 Subject: [PATCH] fix(coding-agent/acp): delayed bootstrap notifications by 50ms to avoid race - Zed dispatches RPC responses and notifications on separate async tasks, so `setTimeout(0)` lost the race against the session registration handler. - Dropped `available_commands_update` left the slash-command palette empty (#1015; zed-industries/zed#55965). --- packages/coding-agent/src/modes/acp/acp-agent.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/coding-agent/src/modes/acp/acp-agent.ts b/packages/coding-agent/src/modes/acp/acp-agent.ts index 69ab38dd7..2a3556c9b 100644 --- a/packages/coding-agent/src/modes/acp/acp-agent.ts +++ b/packages/coding-agent/src/modes/acp/acp-agent.ts @@ -1124,6 +1124,18 @@ export class AcpAgent implements Agent { } #scheduleBootstrapUpdates(sessionId: string): void { + // Delay the bootstrap so the client has time to handle the `session/new` + // (or `session/load` / `session/resume`) RPC response and register the + // new sessionId before we start firing notifications against it. Zed's + // agent-client-protocol reader dispatches responses and notifications + // to different async tasks; sending the first `available_commands_update` + // from `setTimeout(0)` reliably loses the race against the response + // handler and Zed logs `Received session notification for unknown + // session` then drops the update — leaving the slash-command palette + // empty (#1015 follow-up; see zed-industries/zed#55965 for the same + // race biting other ACP agents). 50ms is invisible to the operator and + // large enough that the response future has scheduled before our timer + // fires on stdio-only transports. setTimeout(() => { if (this.#connection.signal.aborted) { return; @@ -1133,7 +1145,7 @@ export class AcpAgent implements Agent { return; } void this.#emitBootstrapUpdates(sessionId, record); - }, 0); + }, 50); } async #emitBootstrapUpdates(sessionId: string, record: ManagedSessionRecord): Promise {