39a575617b
Reorganize app/gateway/ with: - common/ - lifespan management - dependencies/ - FastAPI dependency injection (db, checkpointer, repositories, stream_bridge) - services/runs/ - run execution services (facade_factory, input adapters, store operations) - registrar.py - router registration - router.py - main router setup Simplify app.py to use the new modular structure. Remove deprecated utils.py. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
151 lines
5.0 KiB
Python
151 lines
5.0 KiB
Python
"""Facade factory - assembles RunsFacade with dependencies."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
from typing import TYPE_CHECKING
|
|
|
|
from fastapi import HTTPException, Request
|
|
|
|
from app.gateway.dependencies import get_checkpointer, get_stream_bridge
|
|
from deerflow.runtime.runs.facade import RunsFacade
|
|
from deerflow.runtime.runs.facade import RunsRuntime
|
|
from deerflow.runtime.runs.internal.execution.supervisor import RunSupervisor
|
|
from deerflow.runtime.runs.internal.planner import ExecutionPlanner
|
|
from deerflow.runtime.runs.internal.registry import RunRegistry
|
|
from deerflow.runtime.runs.internal.streams import RunStreamService
|
|
from deerflow.runtime.runs.internal.wait import RunWaitService
|
|
|
|
from app.infra.storage import StorageRunObserver, ThreadMetaStorage
|
|
from app.infra.storage.runs import RunDeleteRepository, RunReadRepository, RunWriteRepository
|
|
from .store import AppRunCreateStore, AppRunDeleteStore, AppRunQueryStore
|
|
|
|
if TYPE_CHECKING:
|
|
from deerflow.runtime.stream_bridge import StreamBridge
|
|
|
|
|
|
type AgentFactory = Callable[..., object]
|
|
|
|
|
|
# Module-level singleton registry (shared across requests)
|
|
_registry: RunRegistry | None = None
|
|
_supervisor: RunSupervisor | None = None
|
|
|
|
|
|
def _get_state(request: Request, attr: str, label: str):
|
|
value = getattr(request.app.state, attr, None)
|
|
if value is None:
|
|
raise HTTPException(status_code=503, detail=f"{label} not available")
|
|
return value
|
|
|
|
|
|
def get_registry() -> RunRegistry:
|
|
"""Get or create singleton registry."""
|
|
global _registry
|
|
if _registry is None:
|
|
_registry = RunRegistry()
|
|
return _registry
|
|
|
|
|
|
def get_supervisor() -> RunSupervisor:
|
|
"""Get or create singleton run supervisor."""
|
|
global _supervisor
|
|
if _supervisor is None:
|
|
_supervisor = RunSupervisor()
|
|
return _supervisor
|
|
|
|
|
|
def resolve_agent_factory(assistant_id: str | None) -> AgentFactory:
|
|
"""Resolve the agent factory callable from config."""
|
|
from deerflow.agents.lead_agent.agent import make_lead_agent
|
|
|
|
return make_lead_agent
|
|
|
|
|
|
def build_runs_facade(
|
|
*,
|
|
stream_bridge: "StreamBridge",
|
|
checkpointer: object,
|
|
store: object | None = None,
|
|
run_read_repo: RunReadRepository | None = None,
|
|
run_write_repo: RunWriteRepository | None = None,
|
|
run_delete_repo: RunDeleteRepository | None = None,
|
|
thread_meta_storage: ThreadMetaStorage | None = None,
|
|
run_event_store: object | None = None,
|
|
) -> RunsFacade:
|
|
"""
|
|
Build RunsFacade with all dependencies.
|
|
|
|
Args:
|
|
stream_bridge: StreamBridge instance
|
|
checkpointer: LangGraph checkpointer
|
|
store: Optional LangGraph runtime store
|
|
run_read_repo: Optional run repository for durable reads
|
|
run_write_repo: Optional run repository for durable writes
|
|
run_delete_repo: Optional run repository for durable deletes
|
|
thread_meta_storage: Optional thread metadata storage adapter
|
|
|
|
Returns:
|
|
Configured RunsFacade instance
|
|
"""
|
|
registry = get_registry()
|
|
planner = ExecutionPlanner()
|
|
supervisor = get_supervisor()
|
|
|
|
stream_service = RunStreamService(stream_bridge)
|
|
wait_service = RunWaitService(stream_service)
|
|
query_store = AppRunQueryStore(run_read_repo) if run_read_repo else None
|
|
create_store = (
|
|
AppRunCreateStore(run_write_repo, thread_meta_storage=thread_meta_storage)
|
|
if run_write_repo
|
|
else None
|
|
)
|
|
delete_store = AppRunDeleteStore(run_delete_repo) if run_delete_repo else None
|
|
|
|
# Build storage observer if repositories provided
|
|
storage_observer = None
|
|
if run_write_repo or thread_meta_storage:
|
|
storage_observer = StorageRunObserver(
|
|
run_write_repo=run_write_repo,
|
|
thread_meta_storage=thread_meta_storage,
|
|
)
|
|
|
|
return RunsFacade(
|
|
registry=registry,
|
|
planner=planner,
|
|
supervisor=supervisor,
|
|
stream_service=stream_service,
|
|
wait_service=wait_service,
|
|
runtime=RunsRuntime(
|
|
bridge=stream_bridge,
|
|
checkpointer=checkpointer,
|
|
store=store,
|
|
event_store=run_event_store,
|
|
agent_factory_resolver=resolve_agent_factory,
|
|
),
|
|
observer=storage_observer,
|
|
query_store=query_store,
|
|
create_store=create_store,
|
|
delete_store=delete_store,
|
|
)
|
|
|
|
|
|
def build_runs_facade_from_request(request: "Request") -> RunsFacade:
|
|
"""
|
|
Build RunsFacade from FastAPI request context.
|
|
|
|
Extracts dependencies from request.app.state.
|
|
"""
|
|
app_state = request.app.state
|
|
|
|
return build_runs_facade(
|
|
stream_bridge=get_stream_bridge(request),
|
|
checkpointer=get_checkpointer(request),
|
|
store=getattr(request.app.state, "store", None),
|
|
run_read_repo=getattr(app_state, "run_read_repo", None),
|
|
run_write_repo=getattr(app_state, "run_write_repo", None),
|
|
run_delete_repo=getattr(app_state, "run_delete_repo", None),
|
|
thread_meta_storage=getattr(app_state, "thread_meta_storage", None),
|
|
run_event_store=getattr(app_state, "run_event_store", None),
|
|
)
|