import operator
from typing import Annotated, TypedDict
from langgraph.graph import StateGraph, START, END

class Bad(TypedDict):
    results: list[str]

class Good(TypedDict):
    results: Annotated[list[str], operator.add]

def a(s): return {"results": ["A"]}
def b(s): return {"results": ["B"]}

for name, S in [("reducerなし", Bad), ("reducerあり", Good)]:
    g = StateGraph(S)
    g.add_node("a", a); g.add_node("b", b)
    g.add_edge(START, "a"); g.add_edge(START, "b")
    g.add_edge("a", END); g.add_edge("b", END)
    try:
        print(name, "->", g.compile().invoke({"results": []}))
    except Exception as e:
        print(name, "->", type(e).__name__, str(e)[:160].replace("\n"," "))

# 段数違い
class S3(TypedDict):
    log: Annotated[list[str], operator.add]
def mk(n): return lambda s: {"log": [n]}
def join(s): return {"log": ["join(seen=%s)" % ",".join(s["log"])]}
for label in ["個別edge", "リストedge"]:
    g = StateGraph(S3)
    for n in ["a","b","b2"]: g.add_node(n, mk(n))
    g.add_node("join", join)
    g.add_edge(START,"a"); g.add_edge(START,"b"); g.add_edge("b","b2")
    if label=="個別edge":
        g.add_edge("a","join"); g.add_edge("b2","join")
    else:
        g.add_edge(["a","b2"],"join")
    g.add_edge("join", END)
    print(label, g.compile().invoke({"log": []})["log"])
