- 智能体支持从广场收藏到「我的」(新增 agent_favorites 表与收藏/取消收藏接口) - 定时任务新增「必须生成Markdown文件」开关:注入提示词并校验生成的 .md 文件且正文超过100字,否则记为失败(存于 execution_context,无需迁移) - 聊天问答展示时间(年月日 时分):问题在右下角、回答在左下角 - 常用提示词改为与账号绑定(新增 user_custom_prompts 表与 /api/user-prompts 接口),仅在首页输入框上方以居中标签 + 轮播展示,齿轮置于最右侧管理 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
142 lines
5.2 KiB
Python
142 lines
5.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
|
|
|
|
@abstractmethod
|
|
async def set_featured(self, agent_id: str, order: int | None) -> dict[str, Any] | None:
|
|
"""Set or clear the homepage-selector featured rank for an agent.
|
|
|
|
Returns the updated row, or ``None`` if the agent does not exist.
|
|
Caller is responsible for authorization (admin) and for verifying
|
|
that ``published`` is true when ``order`` is not ``None``.
|
|
"""
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def list_featured(self, user_id: str) -> list[dict[str, Any]]:
|
|
"""Return featured + still-visible-to-``user_id`` agents, ordered by ``featured_order`` asc."""
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def list_by_ids(self, agent_ids: list[str], user_id: str) -> list[dict[str, Any]]:
|
|
"""Return rows for ``agent_ids`` visible to ``user_id``, preserving the input order."""
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def list_private(self) -> list[dict[str, Any]]:
|
|
"""Return every agent flagged ``is_private=True``.
|
|
|
|
Caller is responsible for authorization — typically the caller has
|
|
already verified the admin-configured private-square password.
|
|
"""
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def list_all(self) -> list[dict[str, Any]]:
|
|
"""Return every agent regardless of ownership/visibility.
|
|
|
|
Caller is responsible for authorization — typically the caller has
|
|
already verified ``system_role == "admin"``.
|
|
"""
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def update_any(self, agent_id: str, data: dict[str, Any]) -> dict[str, Any] | None:
|
|
"""Update any agent row by id, regardless of ownership.
|
|
|
|
Caller is responsible for authorization (admin only). Returns ``None``
|
|
if the agent does not exist.
|
|
"""
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def delete_any(self, agent_id: str) -> bool:
|
|
"""Delete any agent row by id, regardless of ownership.
|
|
|
|
Caller is responsible for authorization (admin only). Returns
|
|
``False`` if the agent does not exist.
|
|
"""
|
|
raise NotImplementedError
|
|
|
|
# --- Favorites ("收藏") ---
|
|
|
|
@abstractmethod
|
|
async def add_favorite(self, user_id: str, agent_id: str) -> None:
|
|
"""Bookmark ``agent_id`` for ``user_id``. Idempotent."""
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def remove_favorite(self, user_id: str, agent_id: str) -> bool:
|
|
"""Remove a bookmark. Returns ``False`` when none existed."""
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def list_favorite_ids(self, user_id: str) -> set[str]:
|
|
"""Return the set of agent ids ``user_id`` has favorited."""
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def delete_favorites_for_agent(self, agent_id: str) -> None:
|
|
"""Drop every user's favorite of ``agent_id`` (called on agent delete)."""
|
|
raise NotImplementedError
|