Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,12 +641,17 @@ def test_mixed_batch_cli_exposes_both_modes_and_ordered_results(capsys: Any) ->
exit_code = main(["demo", "tool-loop", "--case", "mixed-batch"])
records = _records(capsys.readouterr().out)
endings = [record for record in records if record.get("event") == "tool_execution_end"]
parallel_endings = [record for record in endings if record["batch_mode"] == "parallel"]
sequential_endings = [record for record in endings if record["batch_mode"] == "sequential"]

assert exit_code == 0
assert {record["batch_mode"] for record in endings} == {"parallel", "sequential"}
assert [record["tool_result"]["call_id"] for record in endings] == [
assert len(parallel_endings) == 2
assert {record["tool_result"]["call_id"] for record in parallel_endings} == {
"read-a",
"read-b",
}
assert [record["tool_result"]["call_id"] for record in sequential_endings] == [
"read-before",
"write",
"read-after",
Expand Down
37 changes: 28 additions & 9 deletions tests/test_tool_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,24 @@
)


class _ReadBFirstEnvironment(LocalCodingEnvironment):
def __init__(self, workspace: Path) -> None:
super().__init__(workspace)
self._read_b_completed = asyncio.Event()

async def read_text(
self,
path: str,
cancel_event: asyncio.Event | None = None,
) -> str:
if path == "a.txt":
await self._read_b_completed.wait()
content = await super().read_text(path, cancel_event)
if path == "b.txt":
self._read_b_completed.set()
return content


def test_process_group_helpers_bind_platform_apis_with_explicit_types(
monkeypatch: pytest.MonkeyPatch,
) -> None:
Expand Down Expand Up @@ -98,23 +116,24 @@ def test_pure_read_batch_is_parallel_but_model_results_keep_call_order(tmp_path:
workspace = tmp_path
(workspace / "a.txt").write_text("A", encoding="utf-8")
(workspace / "b.txt").write_text("B", encoding="utf-8")
runtime = ToolRuntime(LocalCodingEnvironment(workspace))

batch = asyncio.run(
runtime.execute_batch(
async def execute_batch() -> ToolBatchResult:
runtime = ToolRuntime(_ReadBFirstEnvironment(workspace))
return await runtime.execute_batch(
(
ToolCall("b", "read", {"path": "b.txt"}),
ToolCall("a", "read", {"path": "a.txt"}),
ToolCall("read-a", "read", {"path": "a.txt"}),
ToolCall("read-b", "read", {"path": "b.txt"}),
)
)
)

batch = asyncio.run(execute_batch())

assert batch.mode == "parallel"
assert set(batch.completion_order) == {"a", "b"}
assert tuple(result.call_id for result in batch.results) == ("b", "a")
assert batch.completion_order == ("read-b", "read-a")
assert tuple(result.call_id for result in batch.results) == ("read-a", "read-b")
assert tuple(result.output for result in batch.results) == (
{"content": "B"},
{"content": "A"},
{"content": "B"},
)


Expand Down