feat(routers): add API endpoints for agents and skills

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-04-08 00:12:32 +08:00
parent 74fdfc2652
commit dc9051debc
4 changed files with 71 additions and 1 deletions

View File

@@ -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,

View File

@@ -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"

View File

@@ -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)

View File

@@ -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()