# Copyright 2026 zhaoxi826 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """KiloStar 统一异常体系。 设计原则:所有自定义异常归到两条主轴下。 - ``BusinessError``:业务可预期错误,HTTP 层映射 4xx;前端可读、可展示给用户。 - ``InfraError``:系统/基础设施失败错误,HTTP 层映射 5xx;通常需要落日志告警。 其下再细分为 ``RetryableError``(瞬时故障,可由 ``retry_on_retryable_error`` 自动重试) 与 ``NonRetryableError``(确定性失败,重试无意义)。 注意:用 ``InfraError`` 而非 ``SystemError`` 是为了避免与 Python 内置的 ``SystemError`` 冲突。 每个异常类都带 ``http_status`` 与 ``code`` 类属性,``api/__init__.py`` 的统一 handler 根据它们直接生成结构化响应,避免业务代码里硬编码状态码。 """ from __future__ import annotations class KiloStarError(Exception): """KiloStar 所有自定义异常的总根。""" http_status: int = 500 code: str = "kilostar_error" # ─── 主轴 1:业务可预期错误(4xx) ─────────────────────────────────────────── class BusinessError(KiloStarError): """业务层可预期错误的基类,HTTP 层默认 400。""" http_status = 400 code = "business_error" class DemandError(BusinessError): """需求/任务参数不合法或不满足前置条件时抛出。""" http_status = 400 code = "demand_error" # 用户域 ───────────────────────────────────────── class UserError(BusinessError): """用户域错误的基类。""" http_status = 400 code = "user_error" class UserNotExistError(UserError): """按用户名/ID 查询时用户不存在。""" http_status = 404 code = "user_not_exist" class UserPasswordError(UserError): """口令校验失败(旧密码错误、登录密码错误等)。""" http_status = 401 code = "user_password_error" # Provider 域 ───────────────────────────────────── class ProviderError(BusinessError): """模型 Provider 域错误的基类。""" http_status = 400 code = "provider_error" class ProviderNotExistError(ProviderError): """请求了一个未注册的 Provider 时抛出。""" http_status = 404 code = "provider_not_exist" class ModelNotExistError(BusinessError): """请求了一个未在 Provider 中注册的模型 ID 时抛出。""" http_status = 404 code = "model_not_exist" # Workflow 域 ───────────────────────────────────── class WorkflowExit(BusinessError): """工作流被显式终止(用户取消、上游决策跳出等),是预期内的退出信号。""" http_status = 400 code = "workflow_exit" # ─── 主轴 2:系统/基础设施失败错误(5xx) ──────────────────────────────────── class InfraError(KiloStarError): """系统/基础设施失败错误的基类,HTTP 层默认 500。""" http_status = 500 code = "infra_error" class RetryableError(InfraError): """瞬时故障(如网络抖动),可由 ``retry_on_retryable_error`` 自动重试。""" http_status = 503 code = "retryable_error" class NonRetryableError(InfraError): """确定性的系统失败,重试无意义。""" http_status = 500 code = "non_retryable_error" class WorkflowError(InfraError): """工作流执行期错误的基类,HTTP 层映射为 5xx。""" http_status = 500 code = "workflow_error"