Relax monolith ElicitRequestURLParams.elicitation_id for 2026-07-28 (#2913)
This commit is contained in:
parent
510832aa45
commit
1cec2d60f4
3 changed files with 34 additions and 4 deletions
|
|
@ -1868,7 +1868,9 @@ class CancelledNotificationParams(NotificationParams):
|
||||||
The ID of the request to cancel.
|
The ID of the request to cancel.
|
||||||
|
|
||||||
This MUST correspond to the ID of a request previously issued in the same direction.
|
This MUST correspond to the ID of a request previously issued in the same direction.
|
||||||
Required on the wire through 2025-06-18; optional from 2025-11-25.
|
Required on the wire through 2025-06-18; optional at 2025-11-25; required again from
|
||||||
|
2026-07-28, where it must name a request the client previously issued (servers send
|
||||||
|
this notification only to terminate a `subscriptions/listen` stream).
|
||||||
"""
|
"""
|
||||||
reason: str | None = None
|
reason: str | None = None
|
||||||
"""An optional string describing the reason for the cancellation."""
|
"""An optional string describing the reason for the cancellation."""
|
||||||
|
|
@ -1956,10 +1958,11 @@ class ElicitRequestURLParams(RequestParams):
|
||||||
url: str
|
url: str
|
||||||
"""The URL that the user should navigate to."""
|
"""The URL that the user should navigate to."""
|
||||||
|
|
||||||
elicitation_id: str
|
elicitation_id: str | None = None
|
||||||
"""The ID of the elicitation, which must be unique within the context of the server.
|
"""The ID of the elicitation, which must be unique within the context of the server.
|
||||||
|
|
||||||
The client MUST treat this ID as an opaque value.
|
The client MUST treat this ID as an opaque value. Required on the wire at
|
||||||
|
2025-11-25; removed at 2026-07-28.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
task: TaskMetadata | None = None
|
task: TaskMetadata | None = None
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@ async def test_elicitation_complete_notification_carries_the_elicited_id_back_to
|
||||||
returns; the same ordering already holds on in-memory and SSE transports.
|
returns; the same ordering already holds on in-memory and SSE transports.
|
||||||
"""
|
"""
|
||||||
elicitation_id = "auth-001"
|
elicitation_id = "auth-001"
|
||||||
elicited_ids: list[str] = []
|
elicited_ids: list[str | None] = []
|
||||||
received: list[IncomingMessage] = []
|
received: list[IncomingMessage] = []
|
||||||
|
|
||||||
async def collect(message: IncomingMessage) -> None:
|
async def collect(message: IncomingMessage) -> None:
|
||||||
|
|
|
||||||
|
|
@ -674,6 +674,33 @@ def test_embedded_input_request_entries_without_method_reject_at_the_surface_ste
|
||||||
methods.parse_server_result("tools/call", "2026-07-28", body)
|
methods.parse_server_result("tools/call", "2026-07-28", body)
|
||||||
|
|
||||||
|
|
||||||
|
def test_input_required_url_elicit_without_elicitation_id_parses_at_2026():
|
||||||
|
"""A 2026-07-28 `InputRequiredResult` embedding a URL-mode elicitation parses
|
||||||
|
through both the surface and monolith steps without `elicitationId`.
|
||||||
|
|
||||||
|
Spec-mandated: the field is required at 2025-11-25 only and removed at
|
||||||
|
2026-07-28; the monolith model carries it as optional so the superset can
|
||||||
|
accept both versions.
|
||||||
|
"""
|
||||||
|
body = {
|
||||||
|
"resultType": "input_required",
|
||||||
|
"inputRequests": {
|
||||||
|
"r1": {
|
||||||
|
"method": "elicitation/create",
|
||||||
|
"params": {"mode": "url", "message": "Please sign in", "url": "https://example.com/auth"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
parsed = methods.parse_server_result("tools/call", "2026-07-28", body)
|
||||||
|
assert isinstance(parsed, types.InputRequiredResult)
|
||||||
|
assert parsed.input_requests is not None
|
||||||
|
request = parsed.input_requests["r1"]
|
||||||
|
assert isinstance(request, types.ElicitRequest)
|
||||||
|
assert isinstance(request.params, types.ElicitRequestURLParams)
|
||||||
|
assert request.params.url == "https://example.com/auth"
|
||||||
|
assert request.params.elicitation_id is None
|
||||||
|
|
||||||
|
|
||||||
def test_none_params_omit_the_key_so_required_params_reject():
|
def test_none_params_omit_the_key_so_required_params_reject():
|
||||||
with pytest.raises(pydantic.ValidationError) as excinfo:
|
with pytest.raises(pydantic.ValidationError) as excinfo:
|
||||||
methods.parse_client_request("tools/call", "2025-11-25", None)
|
methods.parse_client_request("tools/call", "2025-11-25", None)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue