Summary
Visual Studio can remain indefinitely in the running state after the Copilot CLI has completed a response.
The CLI verbose log shows that it forwarded the terminal, ephemeral session.idle event. The .NET SDK subscription receives the preceding events, including the final assistant.turn_end, but never receives SessionIdleEvent.
Because session.idle is ephemeral, it cannot be recovered later through GetEventsAsync(). The client therefore has no authoritative completion signal and continues waiting.
Environment
- GitHub.Copilot.SDK:
1.0.1
- Copilot CLI runtime:
1.0.61
- Windows ARM64
- Visual Studio Agent and Agent (Preview) modes
The current SDK 1.0.7 still does not expose a durable idle wait or event-dispatch flush API.
Observed behavior
The CLI log ends with:
Forwarding event ... assistant.turn_end
Forwarding event ... session.idle (ephemeral)
The .NET subscriber observes assistant.turn_end, but not session.idle. The operation remains active even though the runtime has finished.
The absence of session.idle from events.jsonl is expected because the event is ephemeral; it does not explain why the live subscriber missed it.
Why assistant.turn_end is insufficient
In multi-turn tool workflows, an intermediate assistant.turn_end can be followed immediately by another assistant.turn_start. Completion also needs to account for sub-agents, attached shells, queued messages, and follow-up notification turns.
Requested fix
Please provide an authoritative completion contract owned by the runtime/SDK, for example:
await session.WaitForIdleAsync(cancellationToken);
It should:
- Wait for turns, sub-agents, attached shells, queued work, and follow-up turns to settle.
- Resolve only when the runtime is fully idle.
- Ensure preceding session events have crossed the .NET SDK FIFO dispatch queue.
- Surface session errors and transport failures.
- Remain correct if the live
session.idle notification is dropped.
- Support cancellation without leaving an orphaned waiter.
An equivalent session.waitForIdle runtime RPC combined with an SDK dispatch barrier would also work.
Regression test
Add a .NET test where a multi-turn response completes, the live session.idle notification is deliberately dropped, and the completion wait still resolves only after all preceding assistant and tool events have been delivered.
Related
Summary
Visual Studio can remain indefinitely in the running state after the Copilot CLI has completed a response.
The CLI verbose log shows that it forwarded the terminal, ephemeral
session.idleevent. The .NET SDK subscription receives the preceding events, including the finalassistant.turn_end, but never receivesSessionIdleEvent.Because
session.idleis ephemeral, it cannot be recovered later throughGetEventsAsync(). The client therefore has no authoritative completion signal and continues waiting.Environment
1.0.11.0.61The current SDK
1.0.7still does not expose a durable idle wait or event-dispatch flush API.Observed behavior
The CLI log ends with:
The .NET subscriber observes
assistant.turn_end, but notsession.idle. The operation remains active even though the runtime has finished.The absence of
session.idlefromevents.jsonlis expected because the event is ephemeral; it does not explain why the live subscriber missed it.Why
assistant.turn_endis insufficientIn multi-turn tool workflows, an intermediate
assistant.turn_endcan be followed immediately by anotherassistant.turn_start. Completion also needs to account for sub-agents, attached shells, queued messages, and follow-up notification turns.Requested fix
Please provide an authoritative completion contract owned by the runtime/SDK, for example:
It should:
session.idlenotification is dropped.An equivalent
session.waitForIdleruntime RPC combined with an SDK dispatch barrier would also work.Regression test
Add a .NET test where a multi-turn response completes, the live
session.idlenotification is deliberately dropped, and the completion wait still resolves only after all preceding assistant and tool events have been delivered.Related
processQueuedItems()lacks error handling —session.idlemay never be emitted #794 - identifies missingsession.idleand silent notification drops, but its proposed fallback did not shipsession.idlesendAndWaitreturns prematurely when orchestrator dispatches sub-agents viataskand ends its turn #1275 -assistant.turn_endalone is not a completion signal