From b81612c292fff0c466c567aa3c297e70e1f4dded Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Sun, 21 Jul 2024 12:16:37 -0700 Subject: [PATCH 1/2] cli: Fix crash when subprocess has a very long stdout/stderr line --- libs/cli/langgraph_cli/exec.py | 31 ++++++++++++++++++---- libs/cli/tests/unit_tests/test_config.json | 2 +- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/libs/cli/langgraph_cli/exec.py b/libs/cli/langgraph_cli/exec.py index b32eb44c3..3c9557bbe 100644 --- a/libs/cli/langgraph_cli/exec.py +++ b/libs/cli/langgraph_cli/exec.py @@ -131,21 +131,42 @@ async def monitor_stream( if collect: ba = bytearray() - def handle(line: bytes): + def handle(line: bytes, overrun: bool): nonlocal on_line nonlocal display + if display: + sys.stdout.buffer.write(line) + if overrun: + return if collect: ba.extend(line) - if display: - sys.stdout.write(line.decode()) if on_line: if on_line(line.decode()): on_line = None display = True - async for line in stream: - await asyncio.to_thread(handle, line) + """Adpated from asyncio.StreamReader.readline() to handle LimitOverrunError.""" + sep = b"\n" + seplen = len(sep) + while True: + try: + line = await stream.readuntil(sep) + overrun = False + except asyncio.IncompleteReadError as e: + line = e.partial + overrun = False + except asyncio.LimitOverrunError as e: + if stream._buffer.startswith(sep, e.consumed): + line = stream._buffer[: e.consumed + seplen] + else: + line = stream._buffer.clear() + overrun = True + stream._maybe_resume_transport() + await asyncio.to_thread(handle, line, overrun) + if line == b"": + break + if collect: return ba else: diff --git a/libs/cli/tests/unit_tests/test_config.json b/libs/cli/tests/unit_tests/test_config.json index 8062b1719..642b30ded 100644 --- a/libs/cli/tests/unit_tests/test_config.json +++ b/libs/cli/tests/unit_tests/test_config.json @@ -2,7 +2,7 @@ "python_version": "3.12", "pip_config_file": "pipconfig.txt", "dockerfile_lines": [ - "ARG meow" + "ARG meow=woof" ], "dependencies": [ "langchain_openai", From 34407d9de135733d8cbac37f7244212bfb54872e Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Sun, 21 Jul 2024 12:19:19 -0700 Subject: [PATCH 2/2] Update exec.py --- libs/cli/langgraph_cli/exec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/cli/langgraph_cli/exec.py b/libs/cli/langgraph_cli/exec.py index 3c9557bbe..d6282ccfe 100644 --- a/libs/cli/langgraph_cli/exec.py +++ b/libs/cli/langgraph_cli/exec.py @@ -146,7 +146,7 @@ async def monitor_stream( on_line = None display = True - """Adpated from asyncio.StreamReader.readline() to handle LimitOverrunError.""" + """Adapted from asyncio.StreamReader.readline() to handle LimitOverrunError.""" sep = b"\n" seplen = len(sep) while True: