butler/orchestrator/memory_bridge_ops.py
Rama main · réplica de lectura del repositorio original.
"""Memory bridge best-effort helpers (P0-A)."""
from __future__ import annotations
import logging
from pathlib import Path
from typing import TYPE_CHECKING, Any
from butler.core.best_effort import safe_best_effort
if TYPE_CHECKING:
from butler.orchestrator import ButlerOrchestrator
logger = logging.getLogger(__name__)
def refresh_project_facts_safe(project_memory: Any) -> None:
def _run() -> None:
project_memory.refresh_facts()
safe_best_effort(_run, label="memory_bridge.refresh_facts", default=None)
def close_tenant_memory_safe(mem: Any) -> None:
def _run() -> None:
mem.close()
safe_best_effort(_run, label="memory_bridge.close_tenant_memory", default=None)
def clear_memory_degradation_safe() -> None:
def _run() -> None:
from butler.ops.degradation_registry import clear_degradation
clear_degradation("memory")
safe_best_effort(_run, label="memory_bridge.clear_degradation", default=None)
def register_memory_degradation_safe(detail: str) -> None:
def _run() -> None:
from butler.ops.degradation_registry import register_degradation
register_degradation("memory", "初始化失败", detail=detail[:200])
safe_best_effort(_run, label="memory_bridge.register_degradation", default=None)
def initialize_memory_provider_loud(orch: ButlerOrchestrator) -> None:
"""Initialize memory provider; on failure set orch offline and register degradation."""
try:
from butler.memory.facade import ButlerMemoryService
provider = ButlerMemoryService()
provider.link_orchestrator(orch)
provider.initialize(
session_id=f"{orch.channel}:{orch.user_id}",
user_id=orch.user_id,
)
orch.memory_provider = provider
orch.memory_offline = False
orch._memory_init_error = ""
clear_memory_degradation_safe()
except Exception as exc:
logger.error(
"Butler memory provider unavailable: %s",
exc,
exc_info=exc,
)
orch.memory_provider = None
orch.memory_offline = True
orch._memory_init_error = f"{type(exc).__name__}: {exc}"
register_memory_degradation_safe(orch._memory_init_error)
def refresh_memory_provider_branches_safe(provider: Any) -> None:
def _run() -> None:
if hasattr(provider, "_turn_buffer"):
provider._turn_buffer.clear()
if hasattr(provider, "_reload_butler_global"):
provider._reload_butler_global()
if hasattr(provider, "_reload_project_branch"):
provider._reload_project_branch()
safe_best_effort(_run, label="memory_bridge.refresh_provider", default=None)
def design_context_block_safe(
workspace: Path,
*,
design_preset: str = "",
) -> str:
def _run() -> str:
from butler.core.design_md_sections import build_design_context_block
return str(
build_design_context_block(workspace, design_preset=design_preset) or ""
).strip()
result = safe_best_effort(_run, label="memory_bridge.design_context", default="")
return str(result or "").strip()
def outcome_context_block_safe(workspace: Path, *, project: str) -> str:
def _run() -> str:
from butler.experiments.outcomes import format_context_for_prompt
return str(format_context_for_prompt(workspace, project=project) or "").strip()
result = safe_best_effort(_run, label="memory_bridge.outcome_context", default="")
return str(result or "").strip()