fix: 三端联调测试 2 P0 + 6 P1 + 2 P2 修复
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

P0-1: SaaS relay 模型别名解析 — "glm-4-flash" → "glm-4-flash-250414" (resolve_model)
P0-2: config.rs interpolate_env_vars UTF-8 修复 (chars 迭代器替代 bytes as char)
      + DB 启动编码检查 + docker-compose UTF-8 编码参数

P1-3: UI 模型选择器覆盖 Agent 默认模型 (model_override 全链路: TS→Tauri→Rust kernel)
P1-6: 知识搜索管道修复 — seed_knowledge 创建 chunks + 默认分类 (seed/uploaded/distillation)
P1-7: 用量限额从当前 Plan 读取 (非 stale usage 表)
P1-8: relay 双维度配额检查 (relay_requests + input_tokens)

P2-9: SSE 路径 token 计数修复 — 流结束检测替代固定 500ms sleep + billing increment
This commit is contained in:
iven
2026-04-14 00:17:08 +08:00
parent 0903a0d652
commit 4c3136890b
13 changed files with 234 additions and 49 deletions

View File

@@ -152,8 +152,8 @@ pub async fn chat_completions(
}
ModelResolution::Group(candidates)
} else {
// 向后兼容:直接模型查找
let target_model = state.cache.get_model(model_name)
// 向后兼容:直接模型查找 + 别名解析(如 "glm-4-flash" → "glm-4-flash-250414"
let target_model = state.cache.resolve_model(model_name)
.ok_or_else(|| SaasError::NotFound(format!("模型 {} 不存在或未启用", model_name)))?;
// 获取 provider 信息 — 使用内存缓存消除 DB 查询
@@ -218,7 +218,7 @@ pub async fn chat_completions(
ModelResolution::Direct(ref candidate) => {
// 单 Provider 直接路由(向后兼容)
match service::execute_relay(
&state.db, &task.id, &candidate.provider_id,
&state.db, &task.id, &ctx.account_id, &candidate.provider_id,
&candidate.base_url, &request_body, stream,
max_attempts, retry_delay_ms, &enc_key,
true, // 独立调用,管理 task 状态
@@ -233,7 +233,7 @@ pub async fn chat_completions(
// SSE 一旦开始流式传输,中途上游断连不会触发 failoverSSE 协议固有限制)。
service::sort_candidates_by_quota(&state.db, candidates).await;
service::execute_relay_with_failover(
&state.db, &task.id, candidates,
&state.db, &task.id, &ctx.account_id, candidates,
&request_body, stream,
max_attempts, retry_delay_ms, &enc_key
).await
@@ -553,11 +553,12 @@ pub async fn retry_task(
// 异步执行重试 — 根据解析结果选择执行路径
let db = state.db.clone();
let task_id = id.clone();
let account_id_for_spawn = task.account_id.clone();
let handle = tokio::spawn(async move {
let result = match model_resolution {
ModelResolution::Direct(ref candidate) => {
service::execute_relay(
&db, &task_id, &candidate.provider_id,
&db, &task_id, &account_id_for_spawn, &candidate.provider_id,
&candidate.base_url, &body, stream,
max_attempts, base_delay_ms, &enc_key,
true,
@@ -566,7 +567,7 @@ pub async fn retry_task(
ModelResolution::Group(ref mut candidates) => {
service::sort_candidates_by_quota(&db, candidates).await;
service::execute_relay_with_failover(
&db, &task_id, candidates,
&db, &task_id, &account_id_for_spawn, candidates,
&body, stream,
max_attempts, base_delay_ms, &enc_key,
).await