✨ feat(vscode): 代码阅读加 FastAPI 接口卡片:请求表(URL、方法、路径 / 查询参数、请求头、Cookie、请求体)、按状态码的响应表(成功、responses、函数里抛的异常、自动带的 422);别的文件里的异常状态码、类型别名经工作区索引和语言扩展查
This commit is contained in:
1 parent
1dfc0c7b1e
commit
0798f7d1c7
18 files changed
+1745
-28
No files matched your search
@@ -0,0 +1,111 @@
|
||||
"""技能商店用户端路由.
|
||||
|
||||
注: prefix 不带 /api/v1, create_app include 时叠 settings.API_V1_PREFIX.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from luffy_agent.core.db import get_db, get_redis
|
||||
from luffy_agent.sandbox.deps import get_sandbox_registry
|
||||
from luffy_agent.skill_hub import service
|
||||
from luffy_agent.skill_hub.models import HubSkillStatus
|
||||
from luffy_agent.skill_hub.rate_limit import check_mutation_rate
|
||||
from luffy_agent.skill_hub.repositories import hub_skill_repository
|
||||
from luffy_agent.skill_hub.schemas import (
|
||||
AppSkillItem,
|
||||
HubSkillDetail,
|
||||
HubSkillListItem,
|
||||
)
|
||||
from luffy_agent.user.auth.deps import get_current_user
|
||||
from luffy_agent.user.models import User
|
||||
|
||||
skill_hub_router = APIRouter(prefix="/skill-hub", tags=["skill-hub"])
|
||||
|
||||
|
||||
@skill_hub_router.get("/skills", response_model=list[HubSkillListItem])
|
||||
async def list_skills(
|
||||
db: Annotated[AsyncSession, Depends(get_db)],
|
||||
_: Annotated[User, Depends(get_current_user)],
|
||||
query: Annotated[str | None, Query(max_length=80)] = None,
|
||||
tag: Annotated[str | None, Query(max_length=40)] = None,
|
||||
skip: Annotated[int, Query(ge=0)] = 0,
|
||||
limit: Annotated[int, Query(ge=1, le=100)] = 50,
|
||||
) -> list[HubSkillListItem]:
|
||||
rows = await hub_skill_repository.list_published(
|
||||
db, q=query, tag=tag, skip=skip, limit=limit
|
||||
)
|
||||
return [HubSkillListItem.model_validate(row) for row in rows]
|
||||
|
||||
|
||||
@skill_hub_router.get("/skills/{slug}", response_model=HubSkillDetail)
|
||||
async def get_skill(
|
||||
slug: str,
|
||||
db: Annotated[AsyncSession, Depends(get_db)],
|
||||
_: Annotated[User, Depends(get_current_user)],
|
||||
) -> HubSkillDetail:
|
||||
skill = await hub_skill_repository.get_by_slug(db, slug)
|
||||
if skill is None or skill.status != HubSkillStatus.PUBLISHED:
|
||||
raise HTTPException(status_code=404, detail=f"技能不存在: {slug}")
|
||||
return HubSkillDetail.model_validate(skill)
|
||||
|
||||
|
||||
@skill_hub_router.get("/apps/{app_id}/skills", response_model=list[AppSkillItem])
|
||||
async def list_installed(
|
||||
app_id: str,
|
||||
db: Annotated[AsyncSession, Depends(get_db)],
|
||||
current_user: Annotated[User, Depends(get_current_user)],
|
||||
) -> list[AppSkillItem]:
|
||||
rows = await service.list_app_skills(db, user_id=current_user.id, app_id=app_id)
|
||||
return [
|
||||
AppSkillItem(
|
||||
slug=skill.slug,
|
||||
name=skill.name,
|
||||
description=skill.description,
|
||||
version=record.version,
|
||||
installed_at=record.installed_at,
|
||||
)
|
||||
for record, skill in rows
|
||||
]
|
||||
|
||||
|
||||
@skill_hub_router.post("/apps/{app_id}/skills/{slug}", status_code=204)
|
||||
async def install(
|
||||
app_id: str,
|
||||
slug: str,
|
||||
request: Request,
|
||||
db: Annotated[AsyncSession, Depends(get_db)],
|
||||
current_user: Annotated[User, Depends(get_current_user)],
|
||||
) -> None:
|
||||
await check_mutation_rate(get_redis(), user_id=current_user.id)
|
||||
registry = get_sandbox_registry(request)
|
||||
await service.install_skill(
|
||||
db,
|
||||
user_id=current_user.id,
|
||||
app_id=app_id,
|
||||
slug=slug,
|
||||
sandbox_registry=registry,
|
||||
)
|
||||
|
||||
|
||||
@skill_hub_router.delete("/apps/{app_id}/skills/{slug}", status_code=204)
|
||||
async def uninstall(
|
||||
app_id: str,
|
||||
slug: str,
|
||||
request: Request,
|
||||
db: Annotated[AsyncSession, Depends(get_db)],
|
||||
current_user: Annotated[User, Depends(get_current_user)],
|
||||
) -> None:
|
||||
await check_mutation_rate(get_redis(), user_id=current_user.id)
|
||||
registry = get_sandbox_registry(request)
|
||||
await service.uninstall_skill(
|
||||
db,
|
||||
user_id=current_user.id,
|
||||
app_id=app_id,
|
||||
slug=slug,
|
||||
sandbox_registry=registry,
|
||||
)
|
||||
Reference in new issue
Block a user