修复(AGC模型): 档位无可用模型改用独立错误码
- module-runtime 新增 MODEL_UNAVAILABLE / MODEL_UNAVAILABLE_FOR_TIER 常量,NoModelForTier.code() 由共用 MODEL_UNAVAILABLE 改为 MODEL_UNAVAILABLE_FOR_TIER(仍 503),与单个模型不可用的 422 区分 - 更新 resolve_error_codes_are_stable 与 api-server llm 单测;收窄 llm/model_access 模块注释 - 同步设计文档 §11.4 与决策日志
This commit is contained in:
@@ -628,11 +628,11 @@ flowchart TD
|
||||
### 11.4 实现落点(2026-10-03 编码约定)
|
||||
|
||||
- **`module-runtime`**:
|
||||
- 新增 `agc_model_access.rs`:权限档 `AgcModelAccess`(`basic` / `full`,`Default = Basic`)、越权错误码常量 `MODEL_NOT_AVAILABLE_FOR_PLAN`、解析错误 `AgcModelResolveError::{Unavailable, NoModelForTier, NotAvailableForPlan}`(`Unavailable` 与 `NoModelForTier` 复用 `MODEL_UNAVAILABLE` 码,分别映射 422 / 503),以及 `RuntimeProfileMembershipModelAccess → AgcModelAccess` 的映射。
|
||||
- 新增 `agc_model_access.rs`:权限档 `AgcModelAccess`(`basic` / `full`,`Default = Basic`)、错误码常量 `MODEL_NOT_AVAILABLE_FOR_PLAN` / `MODEL_UNAVAILABLE` / `MODEL_UNAVAILABLE_FOR_TIER`、解析错误 `AgcModelResolveError::{Unavailable, NoModelForTier, NotAvailableForPlan}`(分别对应 422 `MODEL_UNAVAILABLE`、503 `MODEL_UNAVAILABLE_FOR_TIER`、403 `MODEL_NOT_AVAILABLE_FOR_PLAN`),以及 `RuntimeProfileMembershipModelAccess → AgcModelAccess` 的映射。
|
||||
- `AgcModel` 末位追加 `#[serde(default)] access: AgcModelAccess`(存量目录 JSON 缺字段即 `Basic`,失败开放);`AgcModelCatalog` 新增 `available_models_for(access)`、`default_model_id_for(access)`、`resolve_requested_for(requested, access)`。
|
||||
- **默认模型语义**:优先取目录登记的 `default_model_id`;当它不在该档可用集合里时,回退到目录顺序里第一个可用项;该档一个可用模型都没有时返回 `Unavailable`。
|
||||
- **`spacetime-module`**:`external_generation_job` 追加 btree 索引 `(owner_user_id, status)`(`by_external_generation_job_owner_status`);`claim_external_generation_jobs_tx` 按账号解析 `concurrent_job_limit` 并在认领时过滤;上限解析走 `profile_membership.plan` → `profile_membership_plan.concurrent_job_limit`,缺会员行 / 缺目录行失败关闭到 `Normal`(=1)。
|
||||
- **`api-server`**:新增 `llm/model_access.rs`,调专用只读 procedure `get_profile_agc_model_access_and_return`(只读会员账期投影 + 档位目录 `model_access`,不刷新、不写库)并映射到 `AgcModelAccess`;`GET /api/llm/models` 按档过滤,`/api/llm/responses`、`/api/llm/chat/completions`、`/api/llm/anthropic/*` 全部按档解析,越权返回 403 + 错误码 `MODEL_NOT_AVAILABLE_FOR_PLAN`,该档无可用模型 / 所选模型不可用分别返回 503 / 422 + `MODEL_UNAVAILABLE`。`resolve_llm_router_client` 返回 `Result<_, AppError>`,会员目录 `503 + MODEL_ACCESS_UNAVAILABLE` 与上述模型解析错误都通过 typed `AppError` 透传,不再拍平成中文。
|
||||
- **`api-server`**:新增 `llm/model_access.rs`,调专用只读 procedure `get_profile_agc_model_access_and_return`(只读会员账期投影 + 档位目录 `model_access`,不刷新、不写库)并映射到 `AgcModelAccess`;`GET /api/llm/models` 按档过滤,`/api/llm/responses`、`/api/llm/chat/completions`、`/api/llm/anthropic/*` 全部按档解析,越权返回 403 + 错误码 `MODEL_NOT_AVAILABLE_FOR_PLAN`,所选模型不可用返回 422 + `MODEL_UNAVAILABLE`,该档无可用模型返回 503 + `MODEL_UNAVAILABLE_FOR_TIER`(与单个模型不可用区分,客户端只按 code 也能分辨)。`resolve_llm_router_client` 返回 `Result<_, AppError>`,会员目录 `503 + MODEL_ACCESS_UNAVAILABLE` 与上述模型解析错误都通过 typed `AppError` 透传,不再拍平成中文。
|
||||
- **后台**:`AdminAgcModel` 与后台「AGC 模型」页新增 `access` 字段(`basic` / `full`,缺省 `basic`),GET 回读、PUT 写入;`AdminAgcModel.access` 与 `AdminUpsertProfileMembershipPlanRequest.model_access` 一样用 `ProfileMembershipModelAccessToken`,未知 token 反序列化即拒;**不做**自动播种或代码内清单。
|
||||
- **性能说明(2026-10-03 已落地)**:账号档位走专用只读 procedure `get_profile_agc_model_access_and_return`(`9e397fe9c`),不再触发 `get_profile_recharge_center` 的账期 / 免费点刷新;`api-server` 于 `b0dc94b46` 切到该读。认领按账号折叠并发查询见 `c3c3fc5a2`。缺会员行 / 已过期按 `Normal`,缺档位目录行失败关闭到 `Basic`。
|
||||
- **列表契约(2026-10-03 修订)**:`shared-contracts` 新增 `llm_catalog.rs` 承载 `LlmModelsResponse` / `LlmModelSummary` / `LlmUnavailableModel` / `LlmModelUnavailableReason`(`plan_required` / `disabled` / `unknown`);`AgcAgentMode` / `AgcModelProtocol` 从 `module-runtime` 迁入 `shared-contracts` 并由 `module-runtime` re-export;整个目录 DTO 与枚举用 `#[cfg_attr(feature = "ts-bindings", derive(ts_rs::TS))]` 导出到 `packages/shared/src/contracts/generated/`,`revision` 标 `#[ts(as = "f64")]`,AGC 前端从 `@genarrative/shared` 根导入,删掉手写的 `ClientLlmModel`。
|
||||
|
||||
Reference in New Issue
Block a user