[v2] ClientSession runs on JSONRPCDispatcher; BaseSession removed (#2838)

This commit is contained in:
Max 2026-06-15 14:46:34 +01:00 • committed by GitHub
commit 1012d60004
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -268,18 +268,15 @@ REQUIREMENTS: dict[str, Requirement] = {
divergence=Divergence(
note=(
"The spec says receivers of a cancellation SHOULD NOT send a response for the cancelled "
"request; the server sends an error response (code 0, 'Request cancelled'), which is what "
"unblocks the SDK client's pending call."
"request; both seats send an error response (code 0, 'Request cancelled') instead — the "
"server for cancelled client requests, and the client for cancelled server-initiated "
"requests — which is what unblocks the sender's pending call."
),
),
),
"protocol:cancel:initialize-not-cancellable": Requirement(
source=f"{SPEC_BASE_URL}/basic/utilities/cancellation#behavior-requirements",
behavior="The client never sends notifications/cancelled for the initialize request.",
deferred=(
"Not implemented in the SDK: the client has no public cancellation API at all, so no pathway "
"exists that could cancel initialize; there is no distinct behaviour to pin beyond that absence."
),
),
"protocol:cancel:late-response-ignored": Requirement(
source=f"{SPEC_BASE_URL}/basic/utilities/cancellation#behavior-requirements",
@ -287,14 +284,6 @@ REQUIREMENTS: dict[str, Requirement] = {
"A response that arrives after the sender issued notifications/cancelled is ignored; the "
"request stays failed and no error is raised."
),
divergence=Divergence(
note=(
"A response whose id matches no in-flight request is delivered to the message handler "
"as a RuntimeError rather than being silently ignored. The post-cancellation case is the "
"same code path; tested in its unknown-id form because that is deterministic without the "
"client-side cancellation API the SDK does not yet provide."
),
),
),
"protocol:cancel:server-survives": Requirement(
source="sdk",
@ -306,19 +295,6 @@ REQUIREMENTS: dict[str, Requirement] = {
"A server that abandons an in-flight server-initiated request (sampling, elicitation, roots) "
"cancels it, and the client stops processing the cancelled request."
),
divergence=Divergence(
note=(
"Abandoning a server-side send_request emits no cancellation notification, and the client "
"could not act on one anyway: client callbacks run inline in the receive loop, so a "
"cancellation is not even read until the callback has finished."
),
),
deferred=(
"Not implemented in the SDK: abandoning a server-side send_request emits no cancellation "
"notification (the same sender-side gap recorded on protocol:timeout:sends-cancellation), and "
"the client could not act on one anyway because client callbacks run inline in the receive "
"loop, so a cancellation would not even be read until the callback had already finished."
),
),
"protocol:cancel:unknown-id-ignored": Requirement(
source=f"{SPEC_BASE_URL}/basic/utilities/cancellation#error-handling",
@ -363,6 +339,27 @@ REQUIREMENTS: dict[str, Requirement] = {
source=f"{SPEC_BASE_URL}/basic#responses",
behavior="A request whose method has no registered handler is answered with a METHOD_NOT_FOUND error.",
),
"protocol:error:null-id": Requirement(
source="sdk",
behavior=(
"An error response carrying a null id — the JSON-RPC shape for a peer reporting a failure it "
"could not attribute to a request, such as a parse error — is surfaced to the application "
"rather than silently discarded."
),
divergence=Divergence(
note=(
"The dispatcher drops null-id error responses with a debug log; in v1, JSONRPCError.id was "
"non-nullable, so a null-id error response failed transport validation and the resulting "
"ValidationError was surfaced to message_handler as an exception. A typed fault channel "
"restoring visibility is planned before v2 stable."
),
),
deferred=(
"Not yet covered here: the current drop is pinned at the dispatcher level by "
"tests/shared/test_jsonrpc_dispatcher.py; an interaction-level test waits on the planned "
"fault channel."
),
),
"protocol:meta:related-task": Requirement(
source=f"{SPEC_BASE_URL}/basic/utilities/tasks#related-task-metadata",
behavior="Messages may carry related-task _meta associating them with a task.",
@ -466,11 +463,6 @@ REQUIREMENTS: dict[str, Requirement] = {
"When a request times out, the sender issues notifications/cancelled for that request before "
"failing the local call."
),
divergence=Divergence(
note=(
"The client only raises locally and sends nothing on timeout, so the server keeps running the handler."
),
),
),
"protocol:timeout:session-survives": Requirement(
source=f"{SPEC_BASE_URL}/basic/lifecycle#timeouts",