Selector de agentes

This commit is contained in:
Jordan Diaz
2026-04-07 10:57:40 +00:00
parent 38ac9cecdc
commit c1a29bbbf8
30 changed files with 760 additions and 357 deletions

View File

@@ -33,6 +33,7 @@ class CreateSessionRequest(BaseModel):
default_factory=dict,
description="Per-project env vars for MCP servers (e.g. ACAI_WEB_URL, ACAI_PROJECT_DIR)",
)
agent_id: str = "acai"
class CreateSessionResponse(BaseModel):
@@ -43,6 +44,7 @@ class CreateSessionResponse(BaseModel):
class SendMessageRequest(BaseModel):
message: str
stream: bool = False
agent_id: str | None = None
class SessionResponse(BaseModel):
@@ -53,6 +55,7 @@ class SessionResponse(BaseModel):
completed_tasks: list[str] = Field(default_factory=list)
created_at: str
updated_at: str
agent_id: str = "acai"
# ------------------------------------------------------------------
@@ -70,6 +73,7 @@ def set_dependencies(
sse_emitter: Any,
claude_emitter: Any = None,
mcp_registry: Any = None,
agent_registry: Any = None,
) -> None:
_deps["storage"] = storage
_deps["model_adapter"] = model_adapter
@@ -78,6 +82,7 @@ def set_dependencies(
_deps["sse"] = sse_emitter
_deps["claude_sse"] = claude_emitter
_deps["mcp_registry"] = mcp_registry
_deps["agent_registry"] = agent_registry
def _get_storage():
@@ -92,7 +97,11 @@ def _get_mcp_registry():
return _deps["mcp_registry"]
def _build_orchestrator(mcp_manager) -> OrchestratorEngine:
def _get_agent_registry():
return _deps["agent_registry"]
def _build_orchestrator(mcp_manager, agent_profile) -> OrchestratorEngine:
"""Build an orchestrator with a session-specific MCPManager."""
return OrchestratorEngine(
model_adapter=_deps["model_adapter"],
@@ -100,6 +109,7 @@ def _build_orchestrator(mcp_manager) -> OrchestratorEngine:
mcp_client=mcp_manager,
memory_store=_deps["memory_store"],
sse_emitter=_deps["sse"],
agent_profile=agent_profile,
)
@@ -109,12 +119,18 @@ def _build_orchestrator(mcp_manager) -> OrchestratorEngine:
@router.post("/sessions", response_model=CreateSessionResponse, status_code=201)
async def create_session(body: CreateSessionRequest) -> CreateSessionResponse:
# Validar agent_id en el registry
agent_reg = _get_agent_registry()
if agent_reg and not agent_reg.get(body.agent_id):
raise HTTPException(status_code=400, detail="Agent not found")
storage = _get_storage()
session = SessionState(
project_profile=body.project_profile,
immutable_rules=body.immutable_rules,
metadata=body.metadata,
)
session.agent_id = body.agent_id
# Store mcp_env in session metadata for reconnection
if body.mcp_env:
session.metadata["mcp_env"] = body.mcp_env
@@ -161,8 +177,22 @@ async def send_message(
mcp_env = session.metadata.get("mcp_env", {})
mcp_manager = await registry.create_for_session(session_id, mcp_env)
# Cambiar agente mid-session si se solicita
if body.agent_id and body.agent_id != session.agent_id:
agent_reg_check = _get_agent_registry()
if agent_reg_check and agent_reg_check.get(body.agent_id):
session.agent_id = body.agent_id
# Resolver agent profile desde el registry
agent_reg = _get_agent_registry()
agent_profile = None
if agent_reg:
agent_profile = agent_reg.get(session.agent_id)
if not agent_profile:
agent_profile = agent_reg.get(agent_reg.default_agent_id)
from ..mcp.manager import MCPManager
orchestrator = _build_orchestrator(mcp_manager or MCPManager())
orchestrator = _build_orchestrator(mcp_manager or MCPManager(), agent_profile)
if body.stream:
asyncio.create_task(_execute_and_persist(orchestrator, storage, session, body.message))
@@ -258,6 +288,7 @@ async def get_session(session_id: str) -> SessionResponse:
completed_tasks=session.completed_tasks,
created_at=session.created_at.isoformat(),
updated_at=session.updated_at.isoformat(),
agent_id=session.agent_id,
)
@@ -320,6 +351,46 @@ async def get_context_debug(session_id: str) -> dict[str, Any]:
}
# ------------------------------------------------------------------
# GET /agents
# ------------------------------------------------------------------
@router.get("/agents")
async def list_agents() -> dict[str, Any]:
"""Lista todos los agentes disponibles."""
registry = _get_agent_registry()
return {
"agents": registry.list_agents(),
"default": registry.default_agent_id,
}
# ------------------------------------------------------------------
# GET /agents/{agent_id}
# ------------------------------------------------------------------
@router.get("/agents/{agent_id}")
async def get_agent(agent_id: str) -> dict[str, Any]:
"""Detalle completo de un agente, incluyendo system prompt."""
registry = _get_agent_registry()
profile = registry.get(agent_id)
if not profile:
raise HTTPException(status_code=404, detail="Agent not found")
return {
"id": profile.name,
"display_name": profile.display_name,
"description": profile.description,
"icon": profile.icon,
"category": profile.category,
"temperature": profile.temperature,
"max_tokens": profile.max_tokens,
"model_id": profile.model_id,
"system_prompt": profile.system_prompt,
"context_sections": profile.context_sections,
"stream_deltas": profile.stream_deltas,
}
# ------------------------------------------------------------------
# Knowledge Base
# ------------------------------------------------------------------