Register sessions before RPC to prevent dropped events#664
Register sessions before RPC to prevent dropped events#664stephentoub wants to merge 4 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds cross-SDK unit tests to ensure sessions are inserted into the client’s sessions map before session.create / session.resume JSON-RPC requests are issued, and that failed RPCs clean up sessions correctly.
Changes:
- Python: async unit tests that monkeypatch the RPC request method and assert map state during RPC execution.
- Node.js: Vitest cases that spy on
sendRequestand validate session map registration and cleanup behavior. - Go: unit tests using an
io.Pipe()-backed fake JSON-RPC server to observe sessions map state during the request.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| python/test_client.py | Adds async tests asserting session registration timing and cleanup on RPC failures. |
| nodejs/test/client.test.ts | Adds Vitest tests verifying session map registration before RPC completion and cleanup on failure. |
| go/client_test.go | Adds a pipe-backed fake JSON-RPC server and unit tests validating registration timing and cleanup in Go client. |
✅ Cross-SDK Consistency ReviewThis PR successfully adds consistent test coverage across Node.js, Python, and Go SDKs. The tests verify session registration behavior uniformly across all three implementations. Test Coverage AnalysisAll three SDKs now include identical test scenarios:
Implementation ConsistencyThe tests follow language-idiomatic patterns while maintaining semantic equivalence:
.NET StatusThe PR description correctly notes that .NET tests are not included due to infrastructure limitations (
RecommendationNo consistency issues found. This PR maintains excellent cross-SDK parity for the three SDKs where test infrastructure supports it. The .NET exclusion is well-justified and documented. Generated by SDK Consistency Review Agent
|
4a9acba to
d0d848f
Compare
Cross-SDK Consistency ReviewThank you for this comprehensive fix across all four SDKs! The implementation is remarkably consistent across Node.js, Python, Go, and .NET - all follow the same pattern: ✅ Generate sessionId client-side (UUID) However, there's one inconsistency in test coverage: Missing .NET TestsThe PR includes comprehensive unit tests for Node.js (4 tests), Python (4 tests), and Go (4 tests), but no tests for .NET. The following test scenarios are covered in the other SDKs but missing for .NET:
Recommendation: Add equivalent unit tests to the .NET SDK (likely in
|
d0d848f to
624c8a7
Compare
Cross-SDK Consistency ReviewThank you for this comprehensive bug fix! The changes look well-implemented across all four SDKs with consistent patterns. However, I've identified one missing test coverage issue: ✅ Implementation ConsistencyThe core fix is implemented consistently across all four SDKs:
❌ Test Coverage GapIssue: The .NET SDK is missing the unit tests that were added to Node.js, Python, and Go. According to the PR description, "12 new unit tests across Node.js, Python, and Go" were added (4 tests × 3 languages). However, .NET has zero new tests added. Files modified:
Tests that should be added to .NET:
While the implementation in
RecommendationConsider adding the missing .NET unit tests to match the coverage provided in the other three SDKs. This would bring all SDKs to the same quality bar and ensure consistent behavior across the entire SDK suite.
|
Register sessions in the client's sessions map before issuing the session.create and session.resume RPC calls, so that events emitted by the CLI during the RPC (e.g. session.start, permission requests, tool calls) are not dropped. Previously, sessions were registered only after the RPC completed, creating a window where notifications for the session had no target. The session ID is now generated client-side (via UUID) rather than extracted from the server response. On RPC failure, the session is cleaned up from the map. Changes across all four SDKs (Node.js, Python, Go, .NET): - Generate sessionId client-side before the RPC - Create and register the session in the sessions map before the RPC - Set workspacePath from the RPC response after it completes - Remove the session from the map if the RPC fails Includes unit tests for Node.js, Python, and Go that verify: - Session is in the map when session.create RPC is called - Session is in the map when session.resume RPC is called - Session is cleaned up from map on RPC failure (create and resume) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
624c8a7 to
7310091
Compare
Cross-SDK Consistency ReviewThank you for this comprehensive fix across all four SDK implementations! The core functionality has been consistently implemented across Node.js, Python, Go, and .NET: ✅ Implementation Consistency
However, I noticed a test coverage inconsistency:
Recommendation: Add equivalent unit tests to the .NET SDK (
This would bring the .NET SDK test coverage in line with the other three implementations and ensure this critical race condition fix is properly validated across all platforms.
|
|
@SteveSandersonMS this PR addresses the issue I raised to you yesterday, where session start/resume events weren't being delivered in the SDK because they arrived before the session was added to the sessions dictionary. |
|
@stephentoub Excellent, thanks. Will review shortly. Interested in whether this might also address #490 |
Hmm... I don't think it will. We can look at that separately. |
|
@stephentoub The implementation looks great! Thanks very much for this. Only change I'm hoping for is doing the test coverage for all four languages in the existing E2E tests as it seems like it should be trivial to do that there, and will eliminate a lot of mocking and the fake JSON-RPC server. |
|
The short answer is, I think, "no", because of the other issue I mentioned to you: the API doesn't let you register an On handler until after you get back the session instance, and by then the start event will likely have already come. For folks to successfully/reliably handle start, there needs to be a way in the API to register a handler before / as part of creating the session, e.g. being able to pass a callback as part of the session config or doing it on the client instance before creating the session. |
To be sure I understand, are you saying the approach in this PR can't be covered by E2E tests because it doesn't behave in the way we want? Or that the implementation is correct and works but E2E tests don't suffice for some reason? If it's that we can't make it work reliably in E2E tests because it's inherently a race, then I would be very open to adding a |
That is my proposal.
The implementation is correct, in that the events are correctly delivered now. But a consumer and thus E2E test can't reliably listen to that event because them signing up their event listener races with it being delivered. Enabling a handler to be registered before session creation addresses that. |
Cross-SDK Consistency Review ✅I've reviewed PR #664 for consistency across all four SDK implementations (Node.js, Python, Go, .NET). Overall, this PR demonstrates excellent cross-SDK consistency! 🎉 ✅ Consistent Implementation Across All SDKsThe core fix has been implemented uniformly across all four languages:
📝 Minor ObservationThe PR description mentions:
However, I only observe modifications to existing e2e tests (the "should receive session events" test) in all four SDKs, not dedicated new unit tests for:
This is not a consistency issue - just noting that if these unit tests exist, they might not be in this diff or the PR description might be referring to test scenarios rather than distinct test functions. Either way, the e2e test modifications provide good coverage of the fix. 🎯 ConclusionNo cross-SDK consistency issues found. This PR maintains excellent feature parity across all four SDK implementations with parallel API design, equivalent behavior, and consistent naming (accounting for language conventions). Great work! 🚀
|
- Add missing blank lines between SessionConfig and AzureProviderOptions (ruff format) - Remove unnecessary quotes on SessionEvent type annotations (ruff lint UP037) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
@SteveSandersonMS would be great to land this. Another developer reported it to me as well. |
|
Summary
Register sessions in the client's sessions map before issuing the \session.create\ and \session.resume\ RPC calls, so that events emitted by the CLI during the RPC (e.g. \session.start, permission requests, tool calls) are not dropped. Previously, sessions were registered only after the RPC completed, creating a window where notifications for the session had no target.
Changes
Across all four SDKs (Node.js, Python, Go, .NET):
Tests
12 new unit tests across Node.js, Python, and Go:
Go tests use a fake JSON-RPC server via \io.Pipe()\ to verify map state during the RPC without needing a real CLI process. Node.js and Python tests mock the RPC layer and assert the session is present in the sessions map when the RPC is invoked.