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
91 lines
2.9 KiB
Python
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)
|