Skip to content

Commit 5510db2

Browse files
authored
feat: Increase default stdio buffer limit and allow configuration (#59)
* Increase default stdio buffer limit and allow configuration * Format * Lint
1 parent adaff6d commit 5510db2

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

src/acp/core.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from .interfaces import Agent, Client
1717

1818
__all__ = [
19+
"DEFAULT_STDIO_BUFFER_LIMIT_BYTES",
1920
"Agent",
2021
"AgentSideConnection",
2122
"Client",
@@ -28,13 +29,19 @@
2829
"run_agent",
2930
]
3031

32+
# Default to 50MB for agent/client data transfer.
33+
# The original stdio_streams default is 64KB, which is not large
34+
# enough for multimodal use-cases.
35+
DEFAULT_STDIO_BUFFER_LIMIT_BYTES = 50 * 1024 * 1024
36+
3137

3238
async def run_agent(
3339
agent: Agent,
3440
input_stream: Any = None,
3541
output_stream: Any = None,
3642
*,
3743
use_unstable_protocol: bool = False,
44+
stdio_buffer_limit_bytes: int = DEFAULT_STDIO_BUFFER_LIMIT_BYTES,
3845
**connection_kwargs: Any,
3946
) -> None:
4047
"""Run an ACP agent over the given input/output streams.
@@ -53,7 +60,7 @@ async def run_agent(
5360
from .stdio import stdio_streams
5461

5562
if input_stream is None and output_stream is None:
56-
output_stream, input_stream = await stdio_streams()
63+
output_stream, input_stream = await stdio_streams(limit=stdio_buffer_limit_bytes)
5764
conn = AgentSideConnection(
5865
agent,
5966
input_stream,

tests/real_user/test_stdio_limits.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import os
2+
import subprocess
13
import sys
4+
import tempfile
25
import textwrap
36

47
import pytest
@@ -39,3 +42,59 @@ async def test_spawn_stdio_transport_custom_limit_handles_large_line() -> None:
3942
) as (reader, _writer, _process):
4043
line = await reader.readline()
4144
assert len(line) == LARGE_LINE_SIZE + 1
45+
46+
47+
@pytest.mark.asyncio
48+
async def test_run_agent_stdio_buffer_limit() -> None:
49+
"""Test that run_agent with different buffer limits can handle appropriately sized messages."""
50+
with tempfile.TemporaryDirectory() as tmpdir:
51+
# Test 1: Small buffer (1KB) fails with large message (70KB)
52+
small_agent = os.path.join(tmpdir, "small_agent.py")
53+
with open(small_agent, "w") as f:
54+
f.write("""
55+
import asyncio
56+
from acp.core import run_agent
57+
from acp.interfaces import Agent
58+
59+
class TestAgent(Agent):
60+
async def list_capabilities(self):
61+
return {"capabilities": {}}
62+
63+
asyncio.run(run_agent(TestAgent(), stdio_buffer_limit_bytes=1024))
64+
""")
65+
66+
# Send a 70KB message - should fail with 1KB buffer
67+
large_msg = '{"jsonrpc":"2.0","method":"test","params":{"data":"' + "X" * LARGE_LINE_SIZE + '"}}\n'
68+
result = subprocess.run( # noqa: S603
69+
[sys.executable, small_agent], input=large_msg, capture_output=True, text=True, timeout=2
70+
)
71+
72+
# Should have errors in stderr about the buffer limit
73+
assert "Error" in result.stderr or result.returncode != 0, (
74+
f"Expected error with small buffer, got: {result.stderr}"
75+
)
76+
77+
# Test 2: Large buffer (200KB) succeeds with large message (70KB)
78+
large_agent = os.path.join(tmpdir, "large_agent.py")
79+
with open(large_agent, "w") as f:
80+
f.write(f"""
81+
import asyncio
82+
from acp.core import run_agent
83+
from acp.interfaces import Agent
84+
85+
class TestAgent(Agent):
86+
async def list_capabilities(self):
87+
return {{"capabilities": {{}}}}
88+
89+
asyncio.run(run_agent(TestAgent(), stdio_buffer_limit_bytes={LARGE_LINE_SIZE * 3}))
90+
""")
91+
92+
# Same message, but with a buffer 3x the size - should handle it
93+
result = subprocess.run( # noqa: S603
94+
[sys.executable, large_agent], input=large_msg, capture_output=True, text=True, timeout=2
95+
)
96+
97+
# With a large enough buffer, the agent should at least start successfully
98+
# (it may have other errors from invalid JSON-RPC, but not buffer overrun)
99+
if "LimitOverrunError" in result.stderr or "buffer" in result.stderr.lower():
100+
pytest.fail(f"Large buffer still hit limit error: {result.stderr}")

0 commit comments

Comments
 (0)