Add .gitignore, remove __pycache__ from tracking, and update MCP/orchestrator modules
- Add .gitignore to exclude .env, __pycache__, node_modules, and IDE files - Remove all __pycache__ bytecode files from version control - Add MCP config files (mcp.json, mcp.json.example) - Add MCP manager, registry, and config modules - Update routes, orchestrator engine, and agent base with latest changes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ from pydantic import BaseModel, Field
|
||||
|
||||
from ..models.context import MemoryDocument, MemoryType
|
||||
from ..models.session import SessionState, SessionStatus
|
||||
from ..orchestrator.engine import OrchestratorEngine
|
||||
from ..streaming.sse import EventType
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -28,6 +29,10 @@ class CreateSessionRequest(BaseModel):
|
||||
project_profile: dict[str, Any] = Field(default_factory=dict)
|
||||
immutable_rules: list[str] = Field(default_factory=list)
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
mcp_env: dict[str, str] = Field(
|
||||
default_factory=dict,
|
||||
description="Per-project env vars for MCP servers (e.g. ACAI_WEB_URL, ACAI_PROJECT_DIR)",
|
||||
)
|
||||
|
||||
|
||||
class CreateSessionResponse(BaseModel):
|
||||
@@ -59,32 +64,43 @@ _deps: dict[str, Any] = {}
|
||||
|
||||
def set_dependencies(
|
||||
storage: Any,
|
||||
orchestrator: Any,
|
||||
model_adapter: Any,
|
||||
context_engine: Any,
|
||||
memory_store: Any,
|
||||
sse_emitter: Any,
|
||||
context_engine: Any = None,
|
||||
memory_store: Any = None,
|
||||
mcp_registry: Any,
|
||||
) -> None:
|
||||
_deps["storage"] = storage
|
||||
_deps["orchestrator"] = orchestrator
|
||||
_deps["model_adapter"] = model_adapter
|
||||
_deps["context_engine"] = context_engine
|
||||
_deps["memory_store"] = memory_store
|
||||
_deps["sse"] = sse_emitter
|
||||
if context_engine:
|
||||
_deps["context_engine"] = context_engine
|
||||
if memory_store:
|
||||
_deps["memory_store"] = memory_store
|
||||
_deps["mcp_registry"] = mcp_registry
|
||||
|
||||
|
||||
def _get_storage():
|
||||
return _deps["storage"]
|
||||
|
||||
|
||||
def _get_orchestrator():
|
||||
return _deps["orchestrator"]
|
||||
|
||||
|
||||
def _get_sse():
|
||||
return _deps["sse"]
|
||||
|
||||
|
||||
def _get_mcp_registry():
|
||||
return _deps["mcp_registry"]
|
||||
|
||||
|
||||
def _build_orchestrator(mcp_manager) -> OrchestratorEngine:
|
||||
"""Build an orchestrator with a session-specific MCPManager."""
|
||||
return OrchestratorEngine(
|
||||
model_adapter=_deps["model_adapter"],
|
||||
context_engine=_deps["context_engine"],
|
||||
mcp_client=mcp_manager,
|
||||
memory_store=_deps["memory_store"],
|
||||
sse_emitter=_deps["sse"],
|
||||
)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# POST /sessions
|
||||
# ------------------------------------------------------------------
|
||||
@@ -97,8 +113,17 @@ async def create_session(body: CreateSessionRequest) -> CreateSessionResponse:
|
||||
immutable_rules=body.immutable_rules,
|
||||
metadata=body.metadata,
|
||||
)
|
||||
# Store mcp_env in session metadata for reconnection
|
||||
if body.mcp_env:
|
||||
session.metadata["mcp_env"] = body.mcp_env
|
||||
|
||||
await storage.create_session(session)
|
||||
|
||||
# Start per-session MCP servers with project-specific env
|
||||
registry = _get_mcp_registry()
|
||||
if registry.has_config:
|
||||
await registry.create_for_session(session.session_id, body.mcp_env)
|
||||
|
||||
sse = _get_sse()
|
||||
await sse.emit(
|
||||
EventType.SESSION_CREATED,
|
||||
@@ -126,7 +151,16 @@ async def send_message(
|
||||
if not session:
|
||||
raise HTTPException(status_code=404, detail="Session not found")
|
||||
|
||||
orchestrator = _get_orchestrator()
|
||||
# Get or create session's MCP manager
|
||||
registry = _get_mcp_registry()
|
||||
mcp_manager = registry.get_for_session(session_id)
|
||||
if not mcp_manager and registry.has_config:
|
||||
# Reconnect MCP (e.g. after server restart)
|
||||
mcp_env = session.metadata.get("mcp_env", {})
|
||||
mcp_manager = await registry.create_for_session(session_id, mcp_env)
|
||||
|
||||
from ..mcp.manager import MCPManager
|
||||
orchestrator = _build_orchestrator(mcp_manager or MCPManager())
|
||||
|
||||
if body.stream:
|
||||
asyncio.create_task(_execute_and_persist(orchestrator, storage, session, body.message))
|
||||
@@ -225,6 +259,10 @@ async def delete_session(session_id: str) -> dict[str, str]:
|
||||
if not deleted:
|
||||
raise HTTPException(status_code=404, detail="Session not found")
|
||||
|
||||
# Stop session's MCP servers
|
||||
registry = _get_mcp_registry()
|
||||
await registry.destroy_for_session(session_id)
|
||||
|
||||
sse = _get_sse()
|
||||
sse.cleanup_session(session_id)
|
||||
|
||||
@@ -373,3 +411,28 @@ async def delete_knowledge(doc_id: str) -> dict[str, str]:
|
||||
if not deleted:
|
||||
raise HTTPException(status_code=404, detail="Document not found")
|
||||
return {"status": "deleted", "id": doc_id}
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# MCP Management
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@router.get("/mcp/status")
|
||||
async def mcp_status() -> dict[str, Any]:
|
||||
"""Status of all MCP servers across sessions."""
|
||||
registry = _get_mcp_registry()
|
||||
return registry.get_status()
|
||||
|
||||
|
||||
@router.post("/mcp/reload")
|
||||
async def mcp_reload() -> dict[str, Any]:
|
||||
"""Hot-reload MCP config template (does not affect running sessions)."""
|
||||
registry = _get_mcp_registry()
|
||||
try:
|
||||
registry.load_config()
|
||||
return {
|
||||
"status": "reloaded",
|
||||
"servers": registry.server_names,
|
||||
}
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
Reference in New Issue
Block a user