Open c0pper opened 5 months ago
Was having the same issue...
so created a very hacky workaround (using a cursor.so) to get it working on windows...
I changed my local \site-packages\langgraph_cli\exec.py
to the below code and it has worked to create the docker image and containers.
ive only ran it once, so be warned...
import asyncio
import os
import sys
from contextlib import contextmanager
from typing import Callable, Optional, cast
import click.exceptions
@contextmanager
def Runner():
if hasattr(asyncio, "Runner"):
with asyncio.Runner() as runner:
yield runner
else:
class _Runner:
def __enter__(self):
return self
def __exit__(self, *args):
pass
def run(self, coro):
asyncio.run(coro)
yield _Runner()
async def subp_exec(
cmd: str,
*args: str,
input: Optional[str] = None,
wait: Optional[float] = None,
verbose: bool = False,
collect: bool = False,
on_stdout: Optional[Callable[[str], Optional[bool]]] = None,
) -> tuple[Optional[str], Optional[str]]:
if verbose:
cmd_str = f"+ {cmd} {' '.join(map(str, args))}"
if input:
print(cmd_str, " <\n", "\n".join(filter(None, input.splitlines())), sep="")
else:
print(cmd_str)
if wait:
await asyncio.sleep(wait)
try:
proc = await asyncio.create_subprocess_exec(
cmd,
*args,
stdin=asyncio.subprocess.PIPE if input else None,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
def signal_handler():
# make sure process exists, then terminate it
if proc.returncode is None:
proc.terminate()
loop = asyncio.get_event_loop()
signal_handlers_installed = False
if os.name != 'nt': # Skip signal handling on Windows
try:
loop.add_signal_handler(signal.SIGINT, signal_handler)
loop.add_signal_handler(signal.SIGTERM, signal_handler)
signal_handlers_installed = True
except NotImplementedError:
pass
empty_fut: asyncio.Future = asyncio.Future()
empty_fut.set_result(None)
stdout, stderr, _ = await asyncio.gather(
monitor_stream(
cast(asyncio.StreamReader, proc.stdout),
collect=True,
display=verbose,
on_line=on_stdout,
),
monitor_stream(
cast(asyncio.StreamReader, proc.stderr),
collect=True,
display=verbose,
),
proc._feed_stdin(input.encode()) if input else empty_fut, # type: ignore[attr-defined]
)
returncode = await proc.wait()
if (
returncode is not None
and returncode != 0 # success
and returncode != 130 # user interrupt
):
sys.stdout.write(stdout.decode() if stdout else "")
sys.stderr.write(stderr.decode() if stderr else "")
raise click.exceptions.Exit(returncode)
if collect:
return (
stdout.decode() if stdout else None,
stderr.decode() if stderr else None,
)
else:
return None, None
finally:
try:
if proc.returncode is None:
try:
os.kill(proc.pid, signal.SIGINT)
except (ProcessLookupError, KeyboardInterrupt):
pass
if signal_handlers_installed:
loop.remove_signal_handler(signal.SIGINT)
loop.remove_signal_handler(signal.SIGTERM)
except UnboundLocalError:
pass
async def monitor_stream(
stream: asyncio.StreamReader,
collect: bool = False,
display: bool = False,
on_line: Optional[Callable[[str], Optional[bool]]] = None,
) -> Optional[bytearray]:
if collect:
ba = bytearray()
def handle(line: bytes):
nonlocal on_line
nonlocal display
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)
if collect:
return ba
else:
return None
That did the trick, thanks a lot!
Issue Summary:
Attempting to run langgraph up on Windows results in the following error:
Steps to Reproduce:
Expected Behavior:
The langgraph up command should start successfully and execute without errors, leveraging Docker functionality on Windows.
Actual Behavior:
Encountered a NotImplementedError related to add_signal_handler and subsequent errors related to os.killpg and Event loop is closed.
Environment Details:
Additional Context:
I have Docker Desktop installed and running on my Windows machine. This issue prevents me from using langgraph-cli effectively for my development workflows.