File size: 2,742 Bytes
f02fdcc | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | """
Working Context Memory β temporary state for the active task.
Holds structured text, latent state references, subgoal trees, and
immediate execution context. Enforces a maximum slot limit defined
by memory_max_working_context. Oldest items are evicted first.
"""
from collections import OrderedDict
from datetime import datetime, timezone
from typing import Any, Dict, List, Optional
from .models import MemoryItem, MemoryTier
from src.config import settings
class WorkingContextMemory:
def __init__(self):
self._slots: OrderedDict[str, MemoryItem] = OrderedDict()
self._subgoals: List[Dict[str, Any]] = []
# ββ Context slots βββββββββββββββββββββββββββββββββββββββββββββββββ
def set(self, item: MemoryItem) -> MemoryItem:
item.tier = MemoryTier.WORKING
if item.item_id in self._slots:
self._slots.move_to_end(item.item_id)
self._slots[item.item_id] = item
self._evict_if_full()
return item
def get(self, item_id: str) -> Optional[MemoryItem]:
return self._slots.get(item_id)
def all(self) -> List[MemoryItem]:
return list(self._slots.values())
def clear(self) -> None:
self._slots.clear()
self._subgoals.clear()
# ββ Subgoal tree ββββββββββββββββββββββββββββββββββββββββββββββββββ
def push_subgoal(self, goal: str, metadata: Optional[Dict[str, Any]] = None) -> None:
self._subgoals.append({
"goal": goal,
"status": "pending",
"created_at": datetime.now(timezone.utc).isoformat(),
"metadata": metadata or {},
})
def complete_subgoal(self, goal: str) -> None:
for sg in self._subgoals:
if sg["goal"] == goal and sg["status"] == "pending":
sg["status"] = "completed"
break
def pending_subgoals(self) -> List[Dict[str, Any]]:
return [sg for sg in self._subgoals if sg["status"] == "pending"]
def subgoal_tree(self) -> List[Dict[str, Any]]:
return list(self._subgoals)
# ββ Eviction ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def _evict_if_full(self) -> None:
while len(self._slots) > settings.memory_max_working_context:
self._slots.popitem(last=False) # evict oldest
@property
def utilization(self) -> float:
return len(self._slots) / settings.memory_max_working_context
|