mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-30 03:39:38 +02:00
StreamingHandler now yields SubgraphRunStream handles for each nested Pregel as it spawns. Each handle is a BaseRunStream wrapping a mini-mux built from the same transformer factories as the root — so sub.values, sub.messages, sub.subgraphs are populated by standard ValuesTransformer / MessagesTransformer / SubgraphTransformer instances at that subagent's scope. No routing or ChatModelStream assembly duplicated across transformers. Key pieces: - StreamLifecycleHandler (pregel/_lifecycle.py): callback handler attached at pregel stream / astream sites when "lifecycle" is in stream_modes. Emits started / running / completed / failed / interrupted events per nested Pregel via metadata-based detection (langgraph_checkpoint_ns + name != langgraph_node, excluding __start__/__end__ sentinels). Carries trigger_call_id from the parent task id. Root subgraph terminal state is emitted eagerly at __init__ and by SubgraphTransformer.finalize / fail. - StreamMux.make_child(scope) + factory-based construction. Mux takes a factory list; make_child produces a mini-mux at a new scope with fresh instances. bind_pump / bind_apump cascade through children so any subagent cursor drives the root pump. - StreamTransformer.scope (base attribute) + scope_exact class flag. Mux skips process() for out-of-scope events when scope_exact=True (default), so user transformers get scope-filtered events with no boilerplate. SubgraphTransformer opts out to receive cross-scope events for forwarding. - BaseRunStream shared base for GraphRunStream, AsyncGraphRunStream, and SubgraphRunStream. Provides extensions, native attrs, raw __iter__ / __aiter__, interleave. Root subclasses own the graph iterator and pump; SubgraphRunStream adds lifecycle metadata (path, status, error, checkpoint, trigger_call_id, graph_name). - SubgraphTransformer (stream/transformers.py) is now a thin discovery + forwarding dispatcher. On lifecycle.started at its scope + 1, it creates a SubgraphRunStream via parent_mux.make_child(ns). It forwards each event matching a direct-child's path into that child's mini-mux. Terminal lifecycle closes the mini-mux. - StreamMode literal extended with "lifecycle". pregel/remote.py filters it out of the SDK stream-mode list since wire-protocol support isn't landed yet. Tests: 16 new in test_stream_subgraph_transformer.py (unit + sync/async end-to-end including error + grandchild); existing Values/Messages namespace filter tests migrated through mux.push to reflect the new scope_exact contract.