From dc9051debc49d47b8d1b0a5ce92b8b62a62ecc71 Mon Sep 17 00:00:00 2001 From: "WIN-JHFT4D3SIVT\\caoxiaozhu" Date: Wed, 8 Apr 2026 00:12:32 +0800 Subject: [PATCH] feat(routers): add API endpoints for agents and skills Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- backend/app/routers/agent.py | 55 +++++++++++++++++++++++++++++ backend/app/routers/conversation.py | 3 ++ backend/app/routers/skill.py | 12 +++++++ backend/app/routers/system.py | 2 +- 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/backend/app/routers/agent.py b/backend/app/routers/agent.py index 70df2cf..f007153 100644 --- a/backend/app/routers/agent.py +++ b/backend/app/routers/agent.py @@ -6,6 +6,7 @@ from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db +from app.agents.learning.store import LearningArtifactStore, SessionRetrospectiveStore from app.agents.registry import load_builtin_registry_indexes from app.agents.runtime_metrics import coerce_cost_thresholds, estimate_token_cost, is_cost_budget_warning from app.models.agent import Agent @@ -37,6 +38,7 @@ from app.schemas.agent import ( AgentVisibilityVerifierOut, ) from app.services.agent_service import _extract_continuity_snapshot +from app.services.runtime_observability import build_runtime_observability_report router = APIRouter(prefix="/api/agents", tags=["Agent"]) @@ -662,6 +664,59 @@ async def get_visibility_tools( return _build_tool_governance(state, conversation_id=conversation_id) +@router.get("/visibility/debug") +async def get_visibility_debug( + conversation_id: str, + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + state = await _get_visibility_state(conversation_id, current_user=current_user, db=db) + observability = build_runtime_observability_report( + state=state, + feature_flags=dict(state.get("feature_flags") or {}), + ) + retrospective_store = SessionRetrospectiveStore(db) + artifact_store = LearningArtifactStore(db) + recent_retrospectives = await retrospective_store.list_recent( + user_id=current_user.id, + limit=5, + ) + recent_artifacts = await artifact_store.list_recent( + user_id=current_user.id, + limit=10, + ) + + return { + "conversation_id": conversation_id, + "observability": observability, + "skill_shortlist": list(state.get("skill_shortlist") or []), + "retrospective_shortlist": list(state.get("retrospective_shortlist") or []), + "merge_report": state.get("merge_report"), + "verification_report": state.get("verification_report"), + "recent_retrospectives": [ + { + "id": item.id, + "task_type": item.task_type, + "summary": item.summary_text, + "execution_mode": item.execution_mode, + "verification_status": item.verification_status, + "recorded_at": item.recorded_at.isoformat() if item.recorded_at else None, + } + for item in recent_retrospectives + ], + "recent_learning_artifacts": [ + { + "id": item.id, + "artifact_type": item.artifact_type, + "artifact_key": item.artifact_key, + "summary": item.summary_text, + "recorded_at": item.recorded_at.isoformat() if item.recorded_at else None, + } + for item in recent_artifacts + ], + } + + @router.post("", response_model=AgentOut, status_code=201) async def create_agent( data: AgentCreate, diff --git a/backend/app/routers/conversation.py b/backend/app/routers/conversation.py index c86d934..cea647d 100644 --- a/backend/app/routers/conversation.py +++ b/backend/app/routers/conversation.py @@ -145,6 +145,9 @@ async def chat_stream( except ValueError as exc: yield f"event: error\ndata: {json.dumps({'error': str(exc)}, ensure_ascii=False)}\n\n" return + except Exception as exc: + yield f"event: error\ndata: {json.dumps({'error': str(exc)}, ensure_ascii=False)}\n\n" + return yield f"event: metadata\ndata: {json.dumps({'conversation_id': conv_id, 'message_id': msg_id})}\n\n" diff --git a/backend/app/routers/skill.py b/backend/app/routers/skill.py index b7663b2..6bb7126 100644 --- a/backend/app/routers/skill.py +++ b/backend/app/routers/skill.py @@ -29,6 +29,10 @@ async def create_skill( visibility=data.visibility, team_id=data.team_id, is_active=data.is_active, + status=data.status, + scope=data.scope, + effectiveness=data.effectiveness, + review_after=data.review_after, owner_id=current_user.id, ) db.add(skill) @@ -103,6 +107,14 @@ async def update_skill( skill.team_id = data.team_id if data.is_active is not None: skill.is_active = data.is_active + if data.status is not None: + skill.status = data.status + if data.scope is not None: + skill.scope = data.scope + if data.effectiveness is not None: + skill.effectiveness = data.effectiveness + if data.review_after is not None: + skill.review_after = data.review_after await db.commit() await db.refresh(skill) diff --git a/backend/app/routers/system.py b/backend/app/routers/system.py index 3430c86..d37f56b 100644 --- a/backend/app/routers/system.py +++ b/backend/app/routers/system.py @@ -12,4 +12,4 @@ async def get_system_status(): @router.get('/config') async def get_system_config(): """Get public system configuration.""" - return SystemService().get_config() + return await SystemService().get_config()