refactor(bedrock): block_index resolves, callers own the current-index state
The helper wrote current_block_index for every event and the stop branch immediately undid it; make it a pure resolver and assign in the start/delta branches only. The test's replay tail re-covered ordering the sidecar assertion already pins — dropped.
This commit is contained in:
@@ -829,12 +829,10 @@ def stream_converse_with_callbacks(
|
||||
def block_index(payload: Dict[str, Any], *, new_block: bool = False) -> int:
|
||||
"""Index of the block a contentBlock* event addresses. Without ``contentBlockIndex`` (test doubles,
|
||||
proxies) a start opens a fresh slot and a delta/stop continues the current one."""
|
||||
nonlocal current_block_index
|
||||
idx = payload.get("contentBlockIndex")
|
||||
if not isinstance(idx, int):
|
||||
idx = len(stream_blocks) if new_block or current_block_index is None else current_block_index
|
||||
current_block_index = idx
|
||||
return idx
|
||||
if isinstance(idx, int):
|
||||
return idx
|
||||
return len(stream_blocks) if new_block or current_block_index is None else current_block_index
|
||||
|
||||
def flush_text() -> None:
|
||||
if current_text_buffer:
|
||||
@@ -849,7 +847,7 @@ def stream_converse_with_callbacks(
|
||||
break
|
||||
if "contentBlockStart" in event:
|
||||
start_event = event["contentBlockStart"]
|
||||
idx = block_index(start_event, new_block=True)
|
||||
idx = current_block_index = block_index(start_event, new_block=True)
|
||||
start = start_event.get("start", {})
|
||||
if "toolUse" in start:
|
||||
has_tool_use = True
|
||||
@@ -860,7 +858,7 @@ def stream_converse_with_callbacks(
|
||||
on_tool_start(current_tool["name"])
|
||||
elif "contentBlockDelta" in event:
|
||||
delta_event = event["contentBlockDelta"]
|
||||
idx = block_index(delta_event)
|
||||
idx = current_block_index = block_index(delta_event)
|
||||
delta = delta_event.get("delta", {})
|
||||
if "text" in delta:
|
||||
text = delta["text"]
|
||||
|
||||
@@ -508,7 +508,7 @@ class TestNormalizeConverseStreamEvents:
|
||||
the text into one block per delta and let the toolUse start (index 1) overwrite the second fragment
|
||||
and sort into the middle — a ``[text, toolUse, text...]`` sidecar Claude 5 on Bedrock rejects on
|
||||
replay as "does not support assistant message prefill"."""
|
||||
from agent.bedrock_adapter import convert_messages_to_converse, normalize_converse_stream_events
|
||||
from agent.bedrock_adapter import normalize_converse_stream_events
|
||||
result = normalize_converse_stream_events({"stream": list(self._LIVE_TEXT_THEN_TOOL_EVENTS)})
|
||||
msg = result.choices[0].message
|
||||
assert msg.content == "I'll echo banana now."
|
||||
@@ -517,15 +517,6 @@ class TestNormalizeConverseStreamEvents:
|
||||
{"toolUse": {"toolUseId": "tooluse_1", "name": "echo", "input": {"s": "banana"}}},
|
||||
]
|
||||
assert [tc.function.name for tc in msg.tool_calls] == ["echo"]
|
||||
# The sidecar is authoritative on replay: the next turn must go out as text THEN toolUse, nothing after.
|
||||
_, converse = convert_messages_to_converse([
|
||||
{"role": "user", "content": "echo banana"},
|
||||
{"role": "assistant", "content": msg.content, "bedrock_content_blocks": msg.bedrock_content_blocks,
|
||||
"tool_calls": [{"id": "tooluse_1", "type": "function", "function": {"name": "echo", "arguments": '{"s": "banana"}'}}]},
|
||||
{"role": "tool", "tool_call_id": "tooluse_1", "content": "banana"},
|
||||
])
|
||||
assert [list(b)[0] for b in converse[1]["content"]] == ["text", "toolUse"]
|
||||
assert converse[1]["content"][0]["text"] == "I'll echo banana now."
|
||||
|
||||
def test_events_without_content_block_index_fall_back_to_arrival_order(self):
|
||||
"""Proxies/test doubles may omit contentBlockIndex: deltas continue the current block, a start opens a
|
||||
|
||||
Reference in New Issue
Block a user