feat: 微服务架构拆分和前后端优化

后端:
- 拆分出 agent_service, runtime_service, trading_service, news_service
- Gateway 模块化拆分 (gateway_*.py)
- 添加 domains/ 领域层
- 新增 control_client, runtime_client
- 更新 start-dev.sh 支持 split 服务模式

前端:
- 完善 API 服务层 (newsApi, tradingApi)
- 更新 vite.config.js
- Explain 组件优化

测试:
- 添加多个服务 app 测试

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-23 17:45:39 +08:00
parent 0f1bc2bb39
commit 3448667b79
54 changed files with 5440 additions and 2947 deletions

View File

@@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
"""Control-plane client for workspace, agent, and guard operations."""
from __future__ import annotations
import httpx
class ControlPlaneClient:
"""Async client for the agent control-plane API surface."""
def __init__(self, base_url: str = "http://localhost:8000/api"):
self.base_url = base_url.rstrip("/")
self._client: httpx.AsyncClient | None = None
async def __aenter__(self) -> "ControlPlaneClient":
self._client = httpx.AsyncClient(base_url=self.base_url, timeout=30.0)
return self
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
if self._client:
await self._client.aclose()
async def list_workspaces(self) -> dict:
response = await self._client.get("/workspaces")
response.raise_for_status()
return response.json()
async def get_workspace(self, workspace_id: str) -> dict:
response = await self._client.get(f"/workspaces/{workspace_id}")
response.raise_for_status()
return response.json()
async def list_agents(self, workspace_id: str) -> dict:
response = await self._client.get(
f"/workspaces/{workspace_id}/agents",
)
response.raise_for_status()
return response.json()
async def get_agent(self, workspace_id: str, agent_id: str) -> dict:
response = await self._client.get(
f"/workspaces/{workspace_id}/agents/{agent_id}",
)
response.raise_for_status()
return response.json()
async def fetch_pending_approvals(self) -> dict:
response = await self._client.get("/guard/pending")
response.raise_for_status()
return response.json()
async def approve_pending_approval(
self,
approval_id: str,
*,
one_time: bool = True,
expires_in_minutes: int = 30,
) -> dict:
response = await self._client.post(
"/guard/approve",
json={
"approval_id": approval_id,
"one_time": one_time,
"expires_in_minutes": expires_in_minutes,
},
)
response.raise_for_status()
return response.json()
async def deny_pending_approval(
self,
approval_id: str,
*,
reason: str = "Denied by client",
) -> dict:
response = await self._client.post(
"/guard/deny",
json={"approval_id": approval_id, "reason": reason},
)
response.raise_for_status()
return response.json()