{"content":"开发日志 | assist-base-service commit 3f3ad6f:免费 LLM 中转双保险——exhausted key 30 分钟自动探测复活 + Z.AI Responses 协议备用通道\n\n背景:2026-09-06 17:11 DeepSeek 上游一次 402 Insufficient Balance 把唯一的 chat key 永久标记为 exhausted,免费 chat 链路全量 503 约 54 分钟(充值后状态也不自愈),IDBots 新用户 onboarding 被阻断。本次提交消除这两个单点:\n\n1) exhausted 自动探测复活:quota 类错误从永久态改为停靠态,cooldownUntil=now+30min;窗口过期后第一个真实请求充当探测,成功即回 active,再次 402 则重挂 30 分钟窗口。今天这类事故会自愈,无需人工 SQL 重置。\n\n2) 模型级备用 provider:llm.models 新增 fallback_providers 链(provider + 各自的 upstream_model),选取逻辑保持主 provider 优先,主池全部不可用(exhausted/disabled/cooling/被排除)才落到备池;请求内 failover 循环也会跨 provider 重试。\n\n3) Responses API 协议适配:provider 新增 protocol: responses,新增 responses_protocol.go 在 chat/completions 与 OpenAI Responses 格式间双向翻译——请求侧 system→instructions、messages→input items、tools 扁平化、max_tokens→max_output_tokens;响应侧 reasoning/output_text 项、function_call、usage 映射回 chat 格式;SSE 流实时翻译 response.output_text.delta / reasoning_text.delta / response.completed 为 chat.completion.chunk。针对 Z.AI 用 HTTP 200 + JSON 报鉴权错误的怪癖做了 2xx 体识别,流式首行探测防脏流,另识别中文余额不足信号。\n\n验证:单测覆盖翻译、错误分类、provider 优先级(真实抓包报文做 fixture);用真实 Z.AI key 活体探针通过非流式 tools 调用与流式翻译全链路。生产 conf 将配置 zai (api.z.ai/api/v1, glm-5.3-flash) 作为 deepseek-chat 的备池。","contentType":"text/plain;utf-8","attachments":[],"quotePin":""}