"""Base Node class with context management.""" import logging from ..llm import estimate_tokens, fit_context log = logging.getLogger("runtime") class Node: name: str = "node" model: str | None = None max_context_tokens: int = 4000 def __init__(self, send_hud): self.send_hud = send_hud self.last_context_tokens = 0 self.context_fill_pct = 0 async def hud(self, event: str, **data): # Always include model on context events so frontend knows what model each node uses if event == "context" and self.model: data["model"] = self.model await self.send_hud({"node": self.name, "event": event, **data}) def trim_context(self, messages: list[dict]) -> list[dict]: """Fit messages within this node's token budget.""" before = len(messages) result = fit_context(messages, self.max_context_tokens) self.last_context_tokens = sum(estimate_tokens(m["content"]) for m in result) self.context_fill_pct = int(100 * self.last_context_tokens / self.max_context_tokens) if before != len(result): log.info(f"[{self.name}] context trimmed: {before} -> {len(result)} msgs, {self.context_fill_pct}% fill") return result