- agent/node_pool.py: NodePool class creates shared stateless node instances, excludes stateful roles (sensor, memorizer, ui) - agent/nodes/base.py: _current_hud contextvar for per-task HUD isolation, Node.hud() checks contextvar first, falls back to instance callback - 15/15 engine tests green (4 new Phase 2 tests pass) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
51 lines
1.6 KiB
Python
51 lines
1.6 KiB
Python
"""NodePool: shared stateless node instances across all sessions.
|
|
|
|
Stateless nodes (InputNode, PANode, ExpertNode, etc.) hold no per-session
|
|
state — only config (model, system prompt). They can safely serve multiple
|
|
concurrent sessions. Session-specific HUD routing uses contextvars.
|
|
|
|
Stateful nodes (SensorNode, MemorizerNode, UINode) hold conversational
|
|
state and must be created per-session.
|
|
"""
|
|
|
|
import logging
|
|
|
|
from .engine import load_graph, instantiate_nodes
|
|
|
|
log = logging.getLogger("runtime")
|
|
|
|
# Roles that hold per-session state — always created fresh per Runtime
|
|
STATEFUL_ROLES = frozenset({"sensor", "memorizer", "ui"})
|
|
|
|
|
|
async def _noop_hud(data: dict):
|
|
"""Placeholder HUD — shared nodes use contextvars for session routing."""
|
|
pass
|
|
|
|
|
|
class NodePool:
|
|
"""Shared node instances for stateless LLM nodes.
|
|
|
|
Usage:
|
|
pool = NodePool("v4-eras")
|
|
# Shared nodes (one instance, all sessions):
|
|
input_node = pool.shared["input"]
|
|
# Stateful nodes must be created per-session (not in pool)
|
|
"""
|
|
|
|
def __init__(self, graph_name: str = "v4-eras"):
|
|
self.graph = load_graph(graph_name)
|
|
self.graph_name = graph_name
|
|
|
|
# Instantiate all nodes with noop HUD (shared nodes use contextvars)
|
|
all_nodes = instantiate_nodes(self.graph, send_hud=_noop_hud)
|
|
|
|
# Split: shared (stateless) vs excluded (stateful)
|
|
self.shared = {
|
|
role: node for role, node in all_nodes.items()
|
|
if role not in STATEFUL_ROLES
|
|
}
|
|
|
|
log.info(f"[pool] created for graph '{graph_name}': "
|
|
f"{len(self.shared)} shared, {len(STATEFUL_ROLES)} stateful")
|