feat(frontend):优化前端页面设计

This commit is contained in:
2026-05-29 16:44:17 +00:00
parent a83c5fa5bd
commit affe460180
80 changed files with 2670 additions and 2678 deletions
+35 -39
View File
@@ -14,46 +14,57 @@
from __future__ import annotations
import jwt
import os
from datetime import datetime, timedelta, timezone
from typing import Optional
from fastapi import HTTPException, status, Request
from typing import TYPE_CHECKING, Optional
import jwt
from fastapi import HTTPException, Request, status
from pydantic import BaseModel, ValidationError
from pwdlib import PasswordHash
if TYPE_CHECKING:
from kilostar.core.postgres_database.model.user import User
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24
_INSECURE_SECRETS = {"secret", "114514", "changethiskey12345"}
class TokenData(BaseModel):
"""TokenData 核心组件类。
这是一个领域数据模型或功能封装类,承载了 TokenData 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
"""JWT 解码后的用户身份载荷。"""
user_id: str
username: Optional[str] = None
exp: Optional[int] = None
SECRET_KEY = os.getenv("SECRET_KEY")
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24
def _get_secret_key() -> str:
"""读取并校验 SECRET_KEY 环境变量。
校验在首次实际使用 JWT 时进行,避免在模块导入阶段抛错,
从而把"环境约束""模块加载"解耦。
"""
key = os.getenv("SECRET_KEY")
if not key or key in _INSECURE_SECRETS:
raise RuntimeError(
"未提供有效的 SECRET_KEY 或使用了不安全的默认值,请设置一个高熵的随机字符串"
)
return key
if not SECRET_KEY or SECRET_KEY in {"secret", "114514"}:
raise RuntimeError("未提供有效的 SECRET_KEY 或使用了不安全的默认值")
password_hasher = PasswordHash.recommended()
class Accessor:
"""Accessor 核心组件类。
这是一个领域数据模型或功能封装类,承载了 Accessor 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
"""封装认证与口令哈希相关的静态工具方法。"""
@staticmethod
def _decode_token(token: str) -> TokenData:
"""执行与 decode token 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Args: token (str): 由认证中心颁发的 JWT 或长期访问令牌,用于跨服务调用时的身份自证与权限校验。
Returns: (TokenData): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
"""解码并校验 JWT,返回 TokenData;过期或无效时抛 401。"""
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
payload = jwt.decode(token, _get_secret_key(), algorithms=[ALGORITHM])
return TokenData(**payload)
except jwt.ExpiredSignatureError:
raise HTTPException(
@@ -68,31 +79,22 @@ class Accessor:
@staticmethod
def _create_access_token(data: dict) -> str:
"""创建并持久化新的 access token 实体。
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
Args: data (dict): 从客户端传递过来或由上游组件生成的核心业务数据体,通常需要进一步的清洗和结构化解析。
Returns: (str): 处理流程所输出的具体字符串产物,可能是新生成的 ID 序列、格式化好的文本片段或 LLM 推理的回答内容。"""
"""根据 payload 生成带过期时间的 JWT 访问令牌。"""
to_encode = data.copy()
expire = datetime.now(timezone.utc) + timedelta(
minutes=ACCESS_TOKEN_EXPIRE_MINUTES
)
to_encode.update({"exp": int(expire.timestamp())})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return jwt.encode(to_encode, _get_secret_key(), algorithm=ALGORITHM)
@staticmethod
def verify_password(plain_password: str, hashed_password: str) -> bool:
"""执行与 verify password 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Args: plain_password (str): 控制逻辑流向的具体字符串参数,指定了期望的 plain password 内容。 hashed_password (str): 控制逻辑流向的具体字符串参数,指定了期望的 hashed password 内容。
Returns: (bool): 一个布尔型结果标志,明确返回 True 表示该操作成功应用或条件达成,False 则表示失败或被拒绝。"""
"""校验明文口令是否匹配数据库中存储的哈希。"""
return password_hasher.verify(plain_password, hashed_password)
@staticmethod
def get_current_user(request: Request) -> TokenData:
"""检索并获取特定的 current user 数据集合或实例对象。
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
Args: request (Request): FastAPI 框架注入的原生 HTTP 请求对象,包含了完整的 Header 标头、查询参数和正文流。
Returns: (TokenData): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
"""从 Authorization Bearer 头解析当前请求的用户身份。"""
auth_header = request.headers.get("Authorization")
if not auth_header or not auth_header.startswith("Bearer "):
raise HTTPException(
@@ -103,11 +105,8 @@ class Accessor:
return Accessor._decode_token(token)
@staticmethod
def login_hashed_password(user: User, password: str) -> str:
"""执行与 login hashed password 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Args: user (User): 当前已通过鉴权流程的访问者实体对象,内部包含用户角色、权限层级及租户归属等核心元信息。 password (str): 控制逻辑流向的具体字符串参数,指定了期望的 password 内容。
Returns: (str): 处理流程所输出的具体字符串产物,可能是新生成的 ID 序列、格式化好的文本片段或 LLM 推理的回答内容。"""
def login_hashed_password(user: "User", password: str) -> str:
"""完成登录核验:找不到用户或密码错误抛 401,否则签发新令牌。"""
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
@@ -123,10 +122,7 @@ class Accessor:
@staticmethod
def hash_password(password: str) -> str:
"""执行与 hash password 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Args: password (str): 控制逻辑流向的具体字符串参数,指定了期望的 password 内容。
Returns: (str): 处理流程所输出的具体字符串产物,可能是新生成的 ID 序列、格式化好的文本片段或 LLM 推理的回答内容。"""
"""对明文口令做强哈希;空值或长度不足 6 位会抛 ValueError。"""
if not password:
raise ValueError("密码不能为空")
if len(password) < 6:
+8 -10
View File
@@ -18,19 +18,17 @@ import yaml
def print_banner() -> None:
"""执行与 print banner 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
"""在启动阶段输出 KiloStar 的 ASCII 横幅与版本/作者元信息。"""
with open("config/config.yml", "r") as config:
config = yaml.load(config, Loader=yaml.FullLoader)
version = config.get("version", "unknown")
kilostar_banner = """
██████╗ ██████╗ ███████╗████████╗ █████╗ ██████╗
██╔══██╗██╔══██╗██╔════╝╚══██╔══╝██╔══██╗██╔══██╗
█████╔╝██████╔╝█████╗ ██║ ████║██████╔╝
██╔═══╝ ██╔══████╔══╝ ██║ ██║ ██║██╔══██╗
██║ ██║ ██║███████╗ ██║ ██████╔╝██║ ██║
╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
kilostar_banner = r"""
██████╗██╗ ██████╗ ███████╗████████╗ █████╗ ██████╗
██║ ██╔╝██║██║ ██╔══██╗██╔════╝╚══██╔══╝██╔══██╗██╔══██╗
█████╔╝ ████║ ██║ ██║███████╗ ██║ ███████║██████╔╝
██╔═██╗ ████║ ██║ ██║╚════██║ ██║ ██╔══██║██╔══██╗
██║ ██╗██║███████╗╚██████╔╝███████║ ██║ ██║ ██║██║ ██║
╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝
"""
console = Console()
banner_colored = Text(kilostar_banner, style="gold3 bold")
+6 -10
View File
@@ -19,10 +19,7 @@ from kilostar.utils.ray_hook import ray_actor_hook
async def get_authority(user_id: str) -> UserAuthority:
"""检索并获取特定的 authority 数据集合或实例对象。
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
Args: user_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 user 实例。
Returns: (UserAuthority): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
"""通过 PostgresDatabase Actor 查出指定用户的 ``UserAuthority``;用户不存在时抛 401。"""
from kilostar.utils.error import UserNotExistError
postgres_database = ray_actor_hook("postgres_database").postgres_database
@@ -43,8 +40,10 @@ async def get_authority(user_id: str) -> UserAuthority:
class RoleChecker:
"""RoleChecker 核心组件类
这是一个领域数据模型或功能封装类,承载了 RoleChecker 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
"""FastAPI 依赖:在路由级别按 ``UserAuthority`` 做最低权限校验
例:``Depends(RoleChecker(allowed_roles=UserAuthority.ADMINISTRATOR))``。
"""
def __init__(self, **kwargs):
self.allowed_roles = kwargs.get(
@@ -54,10 +53,7 @@ class RoleChecker:
async def __call__(
self, token_data: Annotated[TokenData, Depends(Accessor.get_current_user)]
):
"""执行与 call 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Args: token_data (Annotated[TokenData, Depends(Accessor.get_current_user)]): 从客户端传递过来或由上游组件生成的核心业务数据体,通常需要进一步的清洗和结构化解析。
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
"""对当前请求执行权限比较,权限不足抛 403,否则把 ``TokenData`` 透传给路由。"""
user_authority = await get_authority(token_data.user_id)
if user_authority < self.allowed_roles:
raise HTTPException(
+11 -20
View File
@@ -14,75 +14,66 @@
class RetryableError(Exception):
"""基类:所有可重试错误(如网络断开、抖动等临时性故障)"""
"""基类:所有可重试错误(如网络断开、抖动等临时性故障)"""
pass
class NonRetryableError(Exception):
"""基类:所有不可重试错误(如数据验证失败、类型错误等业务逻辑故障)"""
"""基类:所有不可重试错误(如数据验证失败、类型错误等业务逻辑故障)"""
pass
class DemandError(NonRetryableError):
"""DemandError 核心组件类。
这是一个自定义异常类,专门用于在 Demand 相关业务流程中触发中断。它携带了精确的错误上下文与追溯代码,帮助最外层网关能够统一捕获并返回友好的前端错误提示。"""
"""需求/任务参数不合法或不满足前置条件时抛出。"""
pass
class ModelNotExistError(Exception):
"""ModelNotExistError 核心组件类。
这是一个自定义异常类,专门用于在 ModelNotExist 相关业务流程中触发中断。它携带了精确的错误上下文与追溯代码,帮助最外层网关能够统一捕获并返回友好的前端错误提示。"""
"""请求了一个未在 Provider 中注册的模型 ID 时抛出。"""
pass
class UserError(Exception):
"""UserError 核心组件类。
这是一个自定义异常类,专门用于在 User 相关业务流程中触发中断。它携带了精确的错误上下文与追溯代码,帮助最外层网关能够统一捕获并返回友好的前端错误提示。"""
"""用户相关错误的基类,HTTP 层会被统一映射为 4xx。"""
pass
class UserNotExistError(UserError):
"""UserNotExistError 核心组件类。
这是一个自定义异常类,专门用于在 UserNotExist 相关业务流程中触发中断。它携带了精确的错误上下文与追溯代码,帮助最外层网关能够统一捕获并返回友好的前端错误提示。"""
"""按用户名/ID 查询时用户不存在。"""
pass
class UserPasswordError(UserError):
"""UserPasswordError 核心组件类。
这是一个自定义异常类,专门用于在 UserPassword 相关业务流程中触发中断。它携带了精确的错误上下文与追溯代码,帮助最外层网关能够统一捕获并返回友好的前端错误提示。"""
"""口令校验失败(旧密码错误、登录密码错误等)。"""
pass
class ProviderError(Exception):
"""ProviderError 核心组件类。
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。"""
"""模型 Provider 相关错误的基类。"""
pass
class ProviderNotExistError(ProviderError):
"""ProviderNotExistError 核心组件类。
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。"""
"""请求了一个未注册的 Provider 时抛出。"""
pass
class WorkflowError(Exception):
"""WorkflowError 核心组件类。
这是一个自定义异常类,专门用于在 Workflow 相关业务流程中触发中断。它携带了精确的错误上下文与追溯代码,帮助最外层网关能够统一捕获并返回友好的前端错误提示。"""
"""工作流执行期错误的基类,HTTP 层会被统一映射为 5xx。"""
pass
class WorkflowExit(WorkflowError):
"""WorkflowExit 核心组件类。
这是一个领域数据模型或功能封装类,承载了 WorkflowExit 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
"""工作流被显式终止(用户取消、上游决策跳出等)时抛出,是预期内的退出信号。"""
pass
+7 -12
View File
@@ -24,10 +24,11 @@ _tool_cache: Dict[str, Callable] = {}
def _get_tool_func(tool_name: str) -> Callable | None:
"""检索并获取特定的 tool func 数据集合或实例对象
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
Args: tool_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
Returns: (Callable | None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
"""按名字从 ``kilostar/plugin/tool_plugin/<tool_name>/__init__.py`` 中加载工具函数
加载成功后会被缓存到模块级 ``_tool_cache``;找不到目录、找不到同名函数或
导入失败都会记录日志并返回 ``None``。
"""
func = _tool_cache.get(tool_name, None)
if func:
return func
@@ -72,19 +73,13 @@ def _get_tool_func(tool_name: str) -> Callable | None:
def del_tool_cache(tool_name: str) -> None:
"""执行与 del tool cache 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Args: tool_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
"""从内存缓存中移除某个工具,下次调用 ``load_tools_from_list`` 会重新从磁盘加载。"""
if tool_name in _tool_cache:
del _tool_cache[tool_name]
def load_tools_from_list(tool_names: List[str] | None) -> List[Callable]:
"""执行与 load tools from list 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Args: tool_names (List[str] | None): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
Returns: (List[Callable]): 经过筛选、排序或分页处理后的实体对象列表集合。"""
"""批量加载工具:传入工具名列表,返回成功加载到的函数对象列表(失败项被跳过)。"""
if not tool_names:
return []
+2 -11
View File
@@ -18,17 +18,11 @@ from loguru._logger import Logger
def setup_logger() -> Logger:
"""对现有的 setup logger 进行状态更新或属性覆盖。
基于增量变更原则,合并最新的配置或数据,并触发相关依赖组件的缓存刷新或事件通知。
Returns: (Logger): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
"""初始化全局 loguru logger,输出格式为 ``actor:(...) | trace_id:(...) : message``。"""
logger.remove()
def format_record(record):
# Format string for rich handler
"""执行与 format record 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Args: record: 参与 format record 逻辑运算或数据构建的上下文依赖对象。
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
actor = record["extra"].get("actor_name", "System")
trace_id = record["extra"].get("trace_id", "")
@@ -57,8 +51,5 @@ global_logger = setup_logger()
def get_logger(actor_name: str, trace_id: str = "") -> Logger:
"""检索并获取特定的 logger 数据集合或实例对象。
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
Args: actor_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。 trace_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 trace 实例。
Returns: (Logger): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
"""获取一个绑定了 actor_name 与可选 trace_id 的 logger,便于日志按 Actor/请求归类。"""
return global_logger.bind(actor_name=actor_name, trace_id=trace_id)
-3
View File
@@ -31,9 +31,6 @@ def pickle(cls: T) -> T:
def __reduce__(self):
# 1. 序列化:触发 Pydantic-core (Rust) 的极速序列化
"""执行与 reduce 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
data = self.model_dump_json()
# 2. 反序列化:告诉 Pickle 重建时调用 cls.model_validate_json
return cls.model_validate_json, (data,)
+6 -15
View File
@@ -16,31 +16,20 @@ from functools import lru_cache
class ActorList:
"""ActorList 核心组件类。
这是一个领域数据模型或功能封装类,承载了 ActorList 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
"""属性式访问的简易容器,用 ``a.actor_name`` 取代 ``d["actor_name"]``。"""
def __init__(self):
super().__setattr__("dict", {})
def __setattr__(self, key, value):
"""对现有的 setattr 进行状态更新或属性覆盖。
基于增量变更原则,合并最新的配置或数据,并触发相关依赖组件的缓存刷新或事件通知。
Args: key: 参与 setattr 逻辑运算或数据构建的上下文依赖对象。 value: 参与 setattr 逻辑运算或数据构建的上下文依赖对象。"""
self.dict[key] = value
def __getattr__(self, key):
"""检索并获取特定的 getattr 数据集合或实例对象。
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
Args: key: 参与 getattr 逻辑运算或数据构建的上下文依赖对象。
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
if key in self.dict:
return self.dict[key]
raise AttributeError(f"ActorList 对象没有属性 '{key}'")
def __delattr__(self, key):
"""执行与 delattr 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Args: key: 参与 delattr 逻辑运算或数据构建的上下文依赖对象。"""
if key in self.dict:
del self.dict[key]
else:
@@ -59,9 +48,11 @@ def clear_actor_cache():
def ray_actor_hook(*actor_names: str):
"""执行与 ray actor hook 相关的核心业务流转操作
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
"""按名字批量取出 Ray Actor 句柄,组装成一个 ``ActorList`` 返回
例:``actors = ray_actor_hook("postgres_database", "global_state_machine")``
随后即可用 ``actors.postgres_database`` 拿到对应句柄。
"""
actor_list = ActorList()
for actor_name in actor_names:
handle = _get_cached_actor_handle(actor_name)
+8 -14
View File
@@ -19,23 +19,20 @@ from kilostar.utils.error import RetryableError
def retry_on_retryable_error(max_retries=3, base_delay=1):
"""执行与 retry on retryable error 相关的核心业务流转操作
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Args: max_retries: 参与 retry on retryable error 逻辑运算或数据构建的上下文依赖对象。 base_delay: 参与 retry on retryable error 逻辑运算或数据构建的上下文依赖对象
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
"""指数退避重试装饰器:仅在抛出 ``RetryableError`` 时重试
同步/异步函数都支持。第 n 次重试前会 ``sleep(base_delay * 2**n)``
Args:
max_retries: 最多尝试次数(含首次),超过后会把最后一次异常重新抛出。
base_delay: 退避基准秒数。
"""
def decorator(func):
"""执行与 decorator 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Args: func: 参与 decorator 逻辑运算或数据构建的上下文依赖对象。
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
if asyncio.iscoroutinefunction(func):
@wraps(func)
async def async_wrapper(*args, **kwargs):
"""执行与 async wrapper 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
for attempt in range(max_retries):
try:
return await func(*args, **kwargs)
@@ -49,9 +46,6 @@ def retry_on_retryable_error(max_retries=3, base_delay=1):
@wraps(func)
def sync_wrapper(*args, **kwargs):
"""执行与 sync wrapper 相关的核心业务流转操作。
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
import time
for attempt in range(max_retries):