from __future__ import annotations import os from collections.abc import Callable from dataclasses import dataclass, replace from device.manager import DeviceManager from runtime.executor import Executor, default_tool_registry from runtime.planner_config import PlannerConfig, load_config as load_planner_config from runtime.task import TaskRunner from storage.task_metadata import TaskMetadataStore from storage.timeline import Timeline from workflow.runner import WorkflowRunner from workflow.store import WorkflowStore @dataclass(frozen=True) class ExecutionFactories: task_runner_factory: Callable[[], TaskRunner] workflow_runner_factory: Callable[[], WorkflowRunner] workflow_store: WorkflowStore def create_execution_factories( manager: DeviceManager, *, workflow_store: WorkflowStore | None = None, metadata_store: TaskMetadataStore | None = None, timeline: Timeline | None = None, ) -> ExecutionFactories: shared_workflow_store = workflow_store or WorkflowStore() def create_task_runner() -> TaskRunner: return TaskRunner( executor=Executor(tools=default_tool_registry(manager=manager)), metadata_store=metadata_store, timeline=timeline, planner_config=_host_agent_planner_config(), ) def create_workflow_runner() -> WorkflowRunner: return WorkflowRunner( shared_workflow_store, task_runner_factory=create_task_runner, ) return ExecutionFactories( task_runner_factory=create_task_runner, workflow_runner_factory=create_workflow_runner, workflow_store=shared_workflow_store, ) def _host_agent_planner_config() -> PlannerConfig: """Host Agent defaults to the AI planner unless an operator opts out. `runtime.planner_config` defaults `enabled=False` for the shared Runtime library (local dev/tests/cloud dispatcher keep the deterministic stub planner unless asked). The Host Agent is the actual device-control path, so it flips that default on here -- an explicit `AI_PLANNER_ENABLED=false` still disables it. """ config = load_planner_config() if os.environ.get("AI_PLANNER_ENABLED") is None: config = replace(config, enabled=True) return config