Files
xuhdandClaude Sonnet 4.6 40cd8a24af feat: admin skill public upload + user management page
- Admin users can choose to install skills to public (built-in) or custom category via UI radio selector in InstallSkillDialog
- Backend: SkillStorage.ainstall_skill_from_archive accepts target_category param; non-admin 403 on public install
- Backend: AgentStore/SkillStore add count_owned(user_id); UserRepository/LocalAuthProvider add list_users()
- Backend: GET /api/v1/auth/users endpoint (admin-only) returns all users with skill_count and agent_count
- Frontend: admin-only "用户管理" nav item in sidebar; /page/workspace/admin/users route with user table
- i18n: added sidebar.users and adminUsers section in zh-CN/en-US

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 20:40:23 +08:00

64 lines
2.2 KiB
Python

"""Abstract persistence API for custom agents."""
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any
class AgentStore(ABC):
@abstractmethod
async def list_visible(self, user_id: str) -> list[dict[str, Any]]:
raise NotImplementedError
@abstractmethod
async def get_visible(self, agent_id: str, user_id: str) -> dict[str, Any] | None:
raise NotImplementedError
@abstractmethod
async def get_any(self, agent_id: str) -> dict[str, Any] | None:
raise NotImplementedError
@abstractmethod
async def get_owned(self, agent_id: str, user_id: str) -> dict[str, Any] | None:
raise NotImplementedError
@abstractmethod
async def create(self, data: dict[str, Any]) -> dict[str, Any]:
raise NotImplementedError
@abstractmethod
async def ensure_builtin(self, data: dict[str, Any]) -> dict[str, Any]:
raise NotImplementedError
@abstractmethod
async def update(self, agent_id: str, user_id: str, data: dict[str, Any]) -> dict[str, Any] | None:
raise NotImplementedError
@abstractmethod
async def update_builtin(self, agent_id: str, data: dict[str, Any]) -> dict[str, Any] | None:
"""Update a built-in agent (user_id IS NULL).
Caller is responsible for authorization — this method does NOT check
any user identity and returns ``None`` if the target is not a built-in.
"""
raise NotImplementedError
@abstractmethod
async def delete(self, agent_id: str, user_id: str) -> bool:
raise NotImplementedError
@abstractmethod
async def delete_builtin(self, agent_id: str) -> bool:
"""Delete a built-in agent (user_id IS NULL).
Caller is responsible for authorization — this method does NOT check
any user identity and returns ``False`` if the target is not a built-in.
"""
raise NotImplementedError
@abstractmethod
async def count_owned(self, user_id: str) -> int:
"""Return the number of agents owned by ``user_id`` (user_id IS NOT NULL)."""
raise NotImplementedError