Skip to content

Commit a2ffa2e

Browse files
fix streaming server tool input events
1 parent 9aa85c8 commit a2ffa2e

4 files changed

Lines changed: 85 additions & 4 deletions

File tree

src/anthropic/lib/streaming/_beta_messages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ def build_events(
365365
)
366366
)
367367
elif event.delta.type == "input_json_delta":
368-
if content_block.type == "tool_use" or content_block.type == "mcp_tool_use":
368+
if isinstance(content_block, TRACKS_TOOL_INPUT):
369369
events_to_fire.append(
370370
build(
371371
BetaInputJsonEvent,

src/anthropic/lib/streaming/_messages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ def build_events(
360360
)
361361
)
362362
elif event.delta.type == "input_json_delta":
363-
if content_block.type == "tool_use":
363+
if isinstance(content_block, TRACKS_TOOL_INPUT):
364364
events_to_fire.append(
365365
build(
366366
InputJsonEvent,

tests/lib/streaming/test_beta_messages.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,20 @@
1212
from anthropic import Anthropic, AsyncAnthropic
1313
from anthropic._utils import assert_overloads_in_sync, assert_signatures_in_sync
1414
from anthropic._compat import PYDANTIC_V1
15+
from anthropic.types.beta.beta_usage import BetaUsage
1516
from anthropic.types.beta.beta_message import BetaMessage
1617
from anthropic.lib.streaming._beta_types import ParsedBetaMessageStreamEvent
1718
from anthropic.resources.messages.messages import DEPRECATED_MODELS
18-
from anthropic.lib.streaming._beta_messages import TRACKS_TOOL_INPUT, BetaMessageStream, BetaAsyncMessageStream
19+
from anthropic.lib.streaming._beta_messages import (
20+
TRACKS_TOOL_INPUT,
21+
BetaMessageStream,
22+
BetaAsyncMessageStream,
23+
build_events,
24+
)
25+
from anthropic.types.beta.parsed_beta_message import ParsedBetaMessage
26+
from anthropic.types.beta.beta_input_json_delta import BetaInputJSONDelta
27+
from anthropic.types.beta.beta_server_tool_use_block import BetaServerToolUseBlock
28+
from anthropic.types.beta.beta_raw_content_block_delta_event import BetaRawContentBlockDeltaEvent
1929

2030
from .helpers import get_response, to_async_iter
2131

@@ -473,3 +483,36 @@ def test_tracks_tool_input_type_alias_is_up_to_date() -> None:
473483
f"ContentBlock type {block_type.__name__} has an input property, "
474484
f"but is not included in TRACKS_TOOL_INPUT. You probably need to update the TRACKS_TOOL_INPUT type alias."
475485
)
486+
487+
488+
def test_server_tool_use_emits_input_json_event() -> None:
489+
message = ParsedBetaMessage(
490+
id="msg_123",
491+
type="message",
492+
role="assistant",
493+
content=[
494+
BetaServerToolUseBlock(
495+
id="srvtoolu_123",
496+
type="server_tool_use",
497+
name="web_search",
498+
input={"query": "Paris weather"},
499+
)
500+
],
501+
model="claude-sonnet-4-5",
502+
stop_reason=None,
503+
stop_sequence=None,
504+
usage=BetaUsage(input_tokens=10, output_tokens=1),
505+
)
506+
event = BetaRawContentBlockDeltaEvent(
507+
type="content_block_delta",
508+
index=0,
509+
delta=BetaInputJSONDelta(type="input_json_delta", partial_json='{"query":"Paris weather"}'),
510+
)
511+
512+
events = build_events(event=event, message_snapshot=message)
513+
514+
assert [stream_event.type for stream_event in events] == ["content_block_delta", "input_json"]
515+
input_json_event = events[1]
516+
assert input_json_event.type == "input_json"
517+
assert input_json_event.partial_json == '{"query":"Paris weather"}'
518+
assert input_json_event.snapshot == {"query": "Paris weather"}

tests/lib/streaming/test_messages.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,15 @@
1010
from anthropic import Stream, Anthropic, AsyncStream, AsyncAnthropic
1111
from anthropic._utils import assert_signatures_in_sync
1212
from anthropic._compat import PYDANTIC_V1
13+
from anthropic.types.usage import Usage
1314
from anthropic.lib.streaming import ParsedMessageStreamEvent
1415
from anthropic.types.message import Message
1516
from anthropic.resources.messages import DEPRECATED_MODELS
16-
from anthropic.lib.streaming._messages import TRACKS_TOOL_INPUT
17+
from anthropic.types.parsed_message import ParsedMessage
18+
from anthropic.types.input_json_delta import InputJSONDelta
19+
from anthropic.lib.streaming._messages import TRACKS_TOOL_INPUT, build_events
20+
from anthropic.types.server_tool_use_block import ServerToolUseBlock
21+
from anthropic.types.raw_content_block_delta_event import RawContentBlockDeltaEvent
1722

1823
from .helpers import get_response, to_async_iter
1924

@@ -349,3 +354,36 @@ def test_tracks_tool_input_type_alias_is_up_to_date() -> None:
349354
f"ContentBlock type {block_type.__name__} has an input property, "
350355
f"but is not included in TRACKS_TOOL_INPUT. You probably need to update the TRACKS_TOOL_INPUT type alias."
351356
)
357+
358+
359+
def test_server_tool_use_emits_input_json_event() -> None:
360+
message = ParsedMessage(
361+
id="msg_123",
362+
type="message",
363+
role="assistant",
364+
content=[
365+
ServerToolUseBlock(
366+
id="srvtoolu_123",
367+
type="server_tool_use",
368+
name="web_search",
369+
input={"query": "Paris weather"},
370+
)
371+
],
372+
model="claude-sonnet-4-5",
373+
stop_reason=None,
374+
stop_sequence=None,
375+
usage=Usage(input_tokens=10, output_tokens=1),
376+
)
377+
event = RawContentBlockDeltaEvent(
378+
type="content_block_delta",
379+
index=0,
380+
delta=InputJSONDelta(type="input_json_delta", partial_json='{"query":"Paris weather"}'),
381+
)
382+
383+
events = build_events(event=event, message_snapshot=message)
384+
385+
assert [stream_event.type for stream_event in events] == ["content_block_delta", "input_json"]
386+
input_json_event = events[1]
387+
assert input_json_event.type == "input_json"
388+
assert input_json_event.partial_json == '{"query":"Paris weather"}'
389+
assert input_json_event.snapshot == {"query": "Paris weather"}

0 commit comments

Comments
 (0)