fix(sdk): await session.idle after Copilot send() to prevent premature stage completion - #617
Conversation
…e stage completion After the sendAndWait→send refactor (#614), Copilot stages were marked complete while the agent was still processing because send() is fire-and-forget. Wrap send() at the executor level to block until session.idle (or session.error), matching Claude query() and OpenCode session.prompt() blocking semantics.
Review —
|
Summary
After the
sendAndWait→sendrefactor (#614), Copilot workflow stages were completing prematurely becausesend()is fire-and-forget — it returns immediately after queuing the message, before the agent finishes processing. This fix wrapssend()at the executor level to block untilsession.idle(orsession.error), aligning Copilot's blocking semantics with Claude'squery()and OpenCode'ssession.prompt().Key Changes
src/sdk/runtime/executor.ts: InterceptscopilotSession.send()after session initialization (step 12a) to wrap the native fire-and-forget call with a promise that resolves onsession.idleor rejects onsession.errornativeSend()is called to prevent a race condition where the agent could finish before the listener attachesunsubIdle/unsubError) in a sharedcleanup()callback to prevent leakssendAndWait()because_dispatchEventbroadcasts to all registered handlers independentlyRoot Cause
The
sendAndWait→sendrefactor (#614) moved the waiting responsibility out of the SDK method, but the executor did not compensate by adding its own wait. This left Copilot stages without the blocking guarantee that Claude and OpenCode already had.Testing
getMessages()returns complete conversation data instead of partial results