Files
evotraders/backend/apps/runtime_service.py
cillin 16b54d5ccc feat(agent): complete EvoAgent integration for all 6 agent roles
Migrate all agent roles from Legacy to EvoAgent architecture:
- fundamentals_analyst, technical_analyst, sentiment_analyst, valuation_analyst
- risk_manager, portfolio_manager

Key changes:
- EvoAgent now supports Portfolio Manager compatibility methods (_make_decision,
  get_decisions, get_portfolio_state, load_portfolio_state, update_portfolio)
- Add UnifiedAgentFactory for centralized agent creation
- ToolGuard with batch approval API and WebSocket broadcast
- Legacy agents marked deprecated (AnalystAgent, RiskAgent, PMAgent)
- Remove backend/agents/compat.py migration shim
- Add run_id alongside workspace_id for semantic clarity
- Complete integration test coverage (13 tests)
- All smoke tests passing for 6 agent roles

Constraint: Must maintain backward compatibility with existing run configs
Constraint: Memory support must work with EvoAgent (no fallback to Legacy)
Rejected: Separate PM implementation for EvoAgent | unified approach cleaner
Confidence: high
Scope-risk: broad
Directive: EVO_AGENT_IDS env var still respected but defaults to all roles
Not-tested: Kubernetes sandbox mode for skill execution
2026-04-02 00:55:08 +08:00

91 lines
2.9 KiB
Python

# -*- coding: utf-8 -*-
"""Dedicated runtime service FastAPI surface."""
from __future__ import annotations
from fastapi import FastAPI
from backend.api import runtime_router
from backend.api.runtime import get_runtime_state, _check_gateway_health, _get_gateway_process_details
from backend.apps.cors import add_cors_middleware
def create_app() -> FastAPI:
"""Create the runtime service app."""
app = FastAPI(
title="大时代 Runtime Service",
description="Runtime lifecycle and gateway service surface extracted from the monolith",
version="0.1.0",
)
add_cors_middleware(app)
@app.get("/health")
async def health_check() -> dict[str, object]:
"""Health check for the runtime service with Gateway process status."""
runtime_state = get_runtime_state()
process = runtime_state.gateway_process
process_details = _get_gateway_process_details()
is_running = process is not None and process.poll() is None
# Determine overall health status
if is_running:
status = "healthy"
elif process is not None:
# Process existed but exited
status = "degraded"
else:
status = "healthy" # Service is healthy even without Gateway running
return {
"status": status,
"service": "runtime-service",
"gateway": {
"running": is_running,
"port": runtime_state.gateway_port,
"pid": process_details.get("pid"),
"process_status": process_details.get("status"),
"returncode": process_details.get("returncode"),
},
}
@app.get("/health/gateway")
async def gateway_health_check() -> dict[str, object]:
"""Detailed health check for the Gateway subprocess."""
health = _check_gateway_health()
return health
@app.get("/api/status")
async def api_status() -> dict[str, object]:
"""Service-level status payload for runtime orchestration."""
runtime_state = get_runtime_state()
process = runtime_state.gateway_process
process_details = _get_gateway_process_details()
is_running = process is not None and process.poll() is None
return {
"status": "operational",
"service": "runtime-service",
"runtime": {
"gateway_running": is_running,
"gateway_port": runtime_state.gateway_port,
"gateway_pid": process_details.get("pid"),
"gateway_process_status": process_details.get("status"),
"has_runtime_manager": runtime_state.runtime_manager is not None,
},
}
app.include_router(runtime_router)
return app
app = create_app()
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8003)