diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..a76c889 --- /dev/null +++ b/src/main.py @@ -0,0 +1,62 @@ +import questionary +from langgraph.graph import StateGraph, START +from langgraph.checkpoint.memory import InMemorySaver +from langgraph.types import interrupt, Command +from typing import TypedDict, List + +class State(TypedDict): + human_value: str | None + foo: str + +# Node that triggers interrupt +async def interrupt_node(state: State) -> State: + # Trigger interrupt with question and options + payload = { + "type": "confirm", + "question": "Do you want to continue?", + "allow_responds": ["yes", "no"], + } + # interrupt returns None, execution pauses until resume + interrupt(payload) + # After resume, state will contain human_value set by resume payload + return state + +# Simple node to finish +async def finish_node(state: State) -> State: + return state + +# Build graph +graph = StateGraph(State) +graph.add_node("interrupt", interrupt_node) +graph.add_node("finish", finish_node) +graph.set_entry_point("interrupt") +graph.add_edge("interrupt", "finish") +# Compile with checkpoint +checkpoint = InMemorySaver() +graph = graph.compile(checkpointer=checkpoint) + +# Run graph with interrupt handling +async def main(): + thread_id = "thread-1" + config = {"configurable": {"thread_id": thread_id}} + # Start stream + async for chunk in graph.stream({}, config): + if "__interrupt__" in chunk: + # Get interrupt payload + interrupt_payload = chunk["__interrupt__"][0].value + # Show question to user + answer = questionary.select( + interrupt_payload["question"], + choices=interrupt_payload["allow_responds"], + ).ask() + # Resume with answer + resume_payload = {"human_value": answer} + async for _ in graph.stream(Command(resume=resume_payload), config): + pass + else: + # Final state + print("Final state:", chunk) + +if __name__ == "__main__": + import asyncio + asyncio.run(main())