butler/orchestrator/memory_bridge.py
Rama main · réplica de lectura del repositorio original.
"""Memory provider and project-memory wiring (ENG-12)."""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from butler.orchestrator import ButlerOrchestrator
from butler.memory import ButlerMemory, ProjectMemory
def reload_project_memory(orch: ButlerOrchestrator) -> None:
from butler.orchestrator.memory_bridge_ops import refresh_project_facts_safe
proj = orch.project_manager.get_current()
if proj is None:
orch._project_memory = None
else:
orch._project_memory = ProjectMemory(proj.workspace)
if orch._project_memory is not None:
refresh_project_facts_safe(orch._project_memory)
def get_butler_memory(orch: ButlerOrchestrator) -> ButlerMemory:
from butler.orchestrator.memory_bridge_ops import close_tenant_memory_safe
from butler.utilities.tenant import resolve_tenant_for_project
tid = resolve_tenant_for_project(
orch.project_manager.get_current(),
orch._settings,
)
with orch._memory_lock:
mem = orch._memory_by_tenant.get(tid)
if mem is None:
if len(orch._memory_by_tenant) >= 64:
oldest = next(iter(orch._memory_by_tenant))
evicted = orch._memory_by_tenant.pop(oldest, None)
if evicted is not None:
close_tenant_memory_safe(evicted)
mem = ButlerMemory(orch._settings.butler_home, tenant_id=tid)
orch._memory_by_tenant[tid] = mem
return mem
def initialize_memory_provider(orch: ButlerOrchestrator) -> None:
from butler.orchestrator.memory_bridge_ops import initialize_memory_provider_loud
initialize_memory_provider_loud(orch)
def refresh_memory_provider_for_project_switch(orch: ButlerOrchestrator) -> None:
from butler.orchestrator.memory_bridge_ops import refresh_memory_provider_branches_safe
provider = getattr(orch, "memory_provider", None)
if provider is None:
return
refresh_memory_provider_branches_safe(provider)
def build_memory_context(orch: ButlerOrchestrator, *, for_role: str = "default") -> str:
from pathlib import Path
from butler.orchestrator.memory_bridge_ops import (
design_context_block_safe,
outcome_context_block_safe,
)
current = orch.project_manager.current_project or ""
chunks: list[str] = []
bm = get_butler_memory(orch).get_system_context(current)
chunks.append(bm)
if orch._project_memory is not None:
pm_txt = orch._project_memory.get_context_for_agent(for_role)
chunks.append(f"## 当前项目记忆\n{pm_txt}")
proj = orch.project_manager.get_current()
if proj is not None:
design_block = design_context_block_safe(
Path(proj.workspace),
design_preset=str(getattr(proj, "design_preset", "") or ""),
)
if design_block:
chunks.append(design_block)
outcome_block = outcome_context_block_safe(
Path(proj.workspace),
project=str(proj.name or current or ""),
)
if outcome_block:
chunks.append(outcome_block)
return "\n\n".join(c for c in chunks if c and str(c).strip())
__all__ = [
"build_memory_context",
"get_butler_memory",
"initialize_memory_provider",
"refresh_memory_provider_for_project_switch",
"reload_project_memory",
]