Split 1161-line monolith into agent/ package: auth, llm, types, process, runtime, api, and nodes/ (base, sensor, input, output, thinker, memorizer). No logic changes — pure structural split. uvicorn agent:app entrypoint unchanged. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
32 lines
1.1 KiB
Python
32 lines
1.1 KiB
Python
"""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):
|
|
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
|