feat(host-agent): start local console by default
Tests / Test passed: 662

This commit is contained in:
2026-07-14 07:31:31 +08:00
parent a166ffd8a4
commit 8b7e5a2800
10 changed files with 101 additions and 152 deletions
+38 -51
View File
@@ -116,6 +116,11 @@ class HostAgentApplication:
return await claim
class _EmbeddedConsoleServer(uvicorn.Server):
def install_signal_handlers(self) -> None:
"""Host Agent owns process-level signal handling."""
def create_application(
*,
config: HostAgentConfig | None = None,
@@ -148,61 +153,49 @@ def create_application(
bootstrap_client.close()
client = HostAgentClient(resolved_config)
history_store: ConsoleHistoryStore | None = None
status_tracker: AgentStatusTracker | None = None
console_server: uvicorn.Server | None = None
history_store = ConsoleHistoryStore(
resolved_config.identity_path.parent / "host_console_history.sqlite3",
limit=resolved_config.console_history_limit,
)
status_tracker = AgentStatusTracker()
console_enrollment_client: HostAgentEnrollmentClient | None = None
if resolved_config.console_enabled:
history_store = ConsoleHistoryStore(
resolved_config.identity_path.parent / "host_console_history.sqlite3",
limit=resolved_config.console_history_limit,
)
status_tracker = AgentStatusTracker()
if resolved_config.enrollment_managed:
console_enrollment_client = HostAgentEnrollmentClient(resolved_config)
console_app = create_console_app(
config=resolved_config,
manager=resolved_manager,
config_store=config_store,
local_account_store=LocalAccountStore(resolved_config.local_account_path),
identity_store=resolved_identity_store,
history_store=history_store,
status_tracker=status_tracker,
session_manager=SessionManager(
ttl_seconds=resolved_config.console_session_ttl_seconds
),
enrollment_client=console_enrollment_client,
)
console_server = uvicorn.Server(
uvicorn.Config(
console_app,
host=resolved_config.console_bind_host,
port=resolved_config.console_port,
log_level="warning",
)
if resolved_config.enrollment_managed:
console_enrollment_client = HostAgentEnrollmentClient(resolved_config)
console_app = create_console_app(
config=resolved_config,
manager=resolved_manager,
config_store=config_store,
local_account_store=LocalAccountStore(resolved_config.local_account_path),
identity_store=resolved_identity_store,
history_store=history_store,
status_tracker=status_tracker,
session_manager=SessionManager(
ttl_seconds=resolved_config.console_session_ttl_seconds
),
enrollment_client=console_enrollment_client,
)
console_server = _EmbeddedConsoleServer(
uvicorn.Config(
console_app,
host=resolved_config.console_bind_host,
port=resolved_config.console_port,
log_level="warning",
)
)
heartbeat = HeartbeatSynchronizer(
resolved_manager,
client,
resolved_config,
status_tracker=status_tracker,
on_sync=(
(
lambda device_count: history_store.record_heartbeat(
device_count=device_count
)
)
if history_store is not None
else None
on_sync=lambda device_count: history_store.record_heartbeat(
device_count=device_count
),
policy_cache=HostPolicyCacheStore(
resolved_config.identity_path.parent / "host_governance_policy.json"
),
on_policy_sync=(
(lambda revision: history_store.record_policy_sync(revision=revision))
if history_store is not None
else None
on_policy_sync=lambda revision: history_store.record_policy_sync(
revision=revision
),
)
executor = AssignmentExecutor(
@@ -216,14 +209,8 @@ def create_application(
client,
active_runner,
status_tracker=status_tracker,
on_result=(
(
lambda assignment, result: _record_assignment_history(
history_store, assignment, result
)
)
if history_store is not None
else None
on_result=lambda assignment, result: _record_assignment_history(
history_store, assignment, result
),
)
return HostAgentApplication(
+1 -3
View File
@@ -29,7 +29,6 @@ class HostAgentConfig:
retry_backoff_seconds: float = 1.0
max_retry_backoff_seconds: float = 30.0
max_retry_attempts: int = 5
console_enabled: bool = False
console_bind_host: str = "127.0.0.1"
console_port: int = 8765
console_allow_non_loopback: bool = False
@@ -96,7 +95,6 @@ def load_host_agent_config(
"HOST_AGENT_MAX_RETRY_ATTEMPTS",
5,
),
console_enabled=_truthy(values, "HOST_AGENT_CONSOLE_ENABLED", False),
console_bind_host=values.get(
"HOST_AGENT_CONSOLE_BIND_HOST", "127.0.0.1"
).strip(),
@@ -122,7 +120,7 @@ def load_host_agent_config(
raise HostAgentConfigurationError(
"maximum retry backoff must not be less than initial backoff"
)
if config.console_enabled and (
if (
config.console_bind_host not in _LOOPBACK_BIND_HOSTS
and not config.console_allow_non_loopback
):