diff --git a/apps/entities/appcenter.py b/apps/entities/appcenter.py new file mode 100644 index 0000000000000000000000000000000000000000..5445fb2808f03b4ec000e7c16fb3e53f831b47cb --- /dev/null +++ b/apps/entities/appcenter.py @@ -0,0 +1,52 @@ +"""应用中心相关 API 基础数据结构定义 + +Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved. +""" +from typing import Optional + +from pydantic import BaseModel, Field + +from apps.entities.enum_var import AppPermissionType +from apps.entities.flow import AppLink + + +class AppCenterCardItem(BaseModel): + """应用中心卡片数据结构""" + + app_id: str = Field(..., alias="appId", description="应用ID") + icon: str = Field(..., description="应用图标") + name: str = Field(..., description="应用名称") + description: str = Field(..., description="应用简介") + author: str = Field(..., description="应用作者") + favorited: bool = Field(..., description="是否已收藏") + published: bool = Field(default=True, description="是否已发布") + + +class AppPermissionData(BaseModel): + """应用权限数据结构""" + + type: AppPermissionType = Field( + default=AppPermissionType.PRIVATE, + alias="visibility", + description="可见性(public/private/protected)", + ) + users: Optional[list[str]] = Field( + None, + alias="authorizedUsers", + description="附加人员名单(如果可见性为部分人可见)", + ) + + +class AppData(BaseModel): + """应用信息数据结构""" + + icon: str = Field(default="", description="图标") + name: str = Field(..., max_length=20, description="应用名称") + description: str = Field(..., max_length=150, description="应用简介") + links: list[AppLink] = Field(default=[], description="相关链接", max_length=5) + first_questions: list[str] = Field( + default=[], alias="recommendedQuestions", description="推荐问题", max_length=3) + history_len: int = Field(3, alias="dialogRounds", ge=1, le=10, description="对话轮次(1~10)") + permission: AppPermissionData = Field( + default_factory=lambda: AppPermissionData(authorizedUsers=None), description="权限配置") + workflows: list[str] = Field(default=[], description="工作流ID列表") diff --git a/apps/entities/collection.py b/apps/entities/collection.py index 3f727790bad7424619dff82394c0df41c340a3f0..7e486e49322d69ac75990d2f83dfba81f2595c05 100644 --- a/apps/entities/collection.py +++ b/apps/entities/collection.py @@ -33,6 +33,13 @@ class UserDomainData(BaseModel): count: int +class AppUsageData(BaseModel): + """User表子项:应用使用情况数据""" + + count: int = 0 + last_used: float = Field(default_factory=lambda: round(datetime.now(tz=timezone.utc).timestamp(), 3)) + + class User(BaseModel): """用户信息 @@ -49,6 +56,7 @@ class User(BaseModel): kb_id: Optional[str] = None conversations: list[str] = [] domains: list[UserDomainData] = [] + app_usage: dict[str, AppUsageData] = {} class Conversation(BaseModel): @@ -174,6 +182,8 @@ class Domain(BaseModel): name: str definition: str updated_at: float = Field(default_factory=lambda: round(datetime.now(tz=timezone.utc).timestamp(), 3)) + + class NodeMetaData(BaseModel): """节点元数据""" pass diff --git a/apps/entities/enum_var.py b/apps/entities/enum_var.py index f87ee9fa31dcbca129aed61156d6ad71780ca2ce..d4ec50e68d9bb40ef74d7ef38253d5da3f61d7c9 100644 --- a/apps/entities/enum_var.py +++ b/apps/entities/enum_var.py @@ -95,3 +95,12 @@ class SaveType(str, Enum): APP = "app" SERVICE = "service" FLOW = "flow" + + +class SearchType(str, Enum): + """搜索类型""" + + ALL = "all" + NAME = "name" + DESCRIPTION = "description" + AUTHOR = "author" diff --git a/apps/entities/flow.py b/apps/entities/flow.py index d1b2111d033c624b865a508c2e2b218228aef39d..1846a0eb3a9776dc3b1b467a5c5988961a15633b 100644 --- a/apps/entities/flow.py +++ b/apps/entities/flow.py @@ -4,7 +4,7 @@ Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. """ from typing import Any, Optional -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, HttpUrl from apps.entities.enum_var import ( AppPermissionType, @@ -117,7 +117,7 @@ class AppLink(BaseModel): """App的相关链接""" title: str = Field(description="链接标题") - url: str = Field(description="链接URL") + url: HttpUrl = Field(..., description="链接地址") class AppPermission(BaseModel): diff --git a/apps/entities/pool.py b/apps/entities/pool.py index 1d06e674e5a158b256165758f5e488df9d607d62..a5bcc99d723b908f68bb4f28a3a0a2d23910b646 100644 --- a/apps/entities/pool.py +++ b/apps/entities/pool.py @@ -8,6 +8,7 @@ from typing import Any, Optional from pydantic import BaseModel, Field from apps.entities.enum_var import CallType +from apps.entities.flow import AppLink, AppPermission class PoolBase(BaseModel): @@ -72,6 +73,13 @@ class AppPool(PoolBase): collection: app """ - author: str + author: str = Field(description="作者的用户ID") + icon: str = Field(description="应用图标") + published: bool = Field(description="是否发布", default=False) + links: list[AppLink] = Field(description="相关链接", default=[]) + first_questions: list[str] = Field(description="推荐问题", default=[]) + history_len: int = Field(3, ge=1, le=10, description="对话轮次(1~10)") + permission: AppPermission = Field(description="应用权限配置", default=AppPermission()) flows: list[AppFlow] = Field(description="Flow列表", default=[]) + favorites: list[str] = Field(description="收藏此应用的用户列表", default=[]) hashes: dict[str, str] = Field(description="关联文件的hash值", default={}) diff --git a/apps/entities/request_data.py b/apps/entities/request_data.py index bdb8693ab350831525cc4a4035df405b1975d684..4282d02b2036d33ab2ca910f3f0f4aa5e40fbbde 100644 --- a/apps/entities/request_data.py +++ b/apps/entities/request_data.py @@ -6,8 +6,10 @@ from typing import Optional from pydantic import BaseModel, Field +from apps.entities.appcenter import AppData +from apps.entities.flow import EdgeItem, FlowItem, NodeItem, PositionItem from apps.entities.task import RequestDataPlugin -from apps.entities.flow import PositionItem,FlowItem,NodeItem,EdgeItem + class RequestDataFeatures(BaseModel): """POST /api/chat的features字段数据""" @@ -59,6 +61,18 @@ class AbuseProcessRequest(BaseModel): is_deletion: int +class CreateAppRequest(AppData): + """POST /api/app 请求数据结构""" + + app_id: Optional[str] = Field(None, alias="appId", description="应用ID") + + +class ModFavAppRequest(BaseModel): + """PUT /api/app/{appId} 请求数据结构""" + + favorited: bool = Field(..., description="是否收藏") + + class ClientSessionData(BaseModel): """客户端Session信息""" diff --git a/apps/entities/response_data.py b/apps/entities/response_data.py index fcb9c4d878a9dff6a445fa8081621e0982b5dbf7..f7ef82bf1b1d9bbee6fb8bae87fee49cce2decd5 100644 --- a/apps/entities/response_data.py +++ b/apps/entities/response_data.py @@ -6,6 +6,7 @@ from typing import Any, Optional from pydantic import BaseModel, Field +from apps.entities.appcenter import AppCenterCardItem, AppData from apps.entities.collection import Blacklist, Document, NodeMetaData from apps.entities.enum_var import DocumentStatus from apps.entities.flow import EdgeItem, FlowItem, NodeItem, PositionItem @@ -232,6 +233,77 @@ class GetKnowledgeIDRsp(ResponseData): result: GetKnowledgeIDMsg +class BaseAppOperationMsg(BaseModel): + """基础应用操作Result数据结构""" + + app_id: str = Field(..., alias="appId", description="应用ID") + + +class BaseAppOperationRsp(ResponseData): + """基础应用操作返回数据结构""" + + result: BaseAppOperationMsg + + +class GetAppPropertyMsg(AppData): + """GET /api/app/{appId} Result数据结构""" + + app_id: str = Field(..., alias="appId", description="应用ID") + published: bool = Field(..., description="是否已发布") + + +class GetAppPropertyRsp(ResponseData): + """GET /api/app/{appId} 返回数据结构""" + + result: GetAppPropertyMsg + + +class ModFavAppMsg(BaseModel): + """PUT /api/app/{appId} Result数据结构""" + + app_id: str = Field(..., alias="appId", description="应用ID") + favorited: bool = Field(..., description="是否已收藏") + + +class ModFavAppRsp(ResponseData): + """PUT /api/app/{appId} 返回数据结构""" + + result: ModFavAppMsg + + +class GetAppListMsg(BaseModel): + """GET /api/app Result数据结构""" + + page_number: int = Field(..., alias="currentPage", description="当前页码") + page_count: int = Field(..., alias="totalPages", description="总页数") + applications: list[AppCenterCardItem] = Field(..., description="应用列表") + + +class GetAppListRsp(ResponseData): + """GET /api/app 返回数据结构""" + + result: GetAppListMsg + + +class RecentAppListItem(BaseModel): + """GET /api/app/recent 列表项数据结构""" + + app_id: str = Field(..., alias="appId", description="应用ID") + name: str = Field(..., description="应用名称") + + +class RecentAppList(BaseModel): + """GET /api/app/recent Result数据结构""" + + applications: list[RecentAppListItem] = Field(..., description="最近使用的应用列表") + + +class GetRecentAppListRsp(ResponseData): + """GET /api/app/recent 返回数据结构""" + + result: RecentAppList + + class NodeMetaDataItem(BaseModel): """GET /api/flow/node/metadata 单个节点元数据结构""" api_id: str = Field(alias="apiId")