Repository navigation
v0.10.1:备份/恢复与批量导入、月度账单与飞书/Slack 告警、用户级策略收口 Playground,外加单实例锁与出口粘性。SCHEMA_VERSION 29 → 30(users 补 allowed_models / quota,幂等补列),升级必须重启后端。
v0.10.0 之后的 46 个提交。按维护期口径发 patch,但含新端点与新能力。
新增能力
- 备份 / 恢复管理(端点 + 管理台
/backups页):下载只认backups/内的普通*.sqlite3,拒绝路径分隔符与符号链接;运维脚本写库前自动备份,只留最近 5 份。 - 批量凭证导入(
POST /api/credentials/batch-import):一次 ≤100 条,逐条校验并隔离失败,返回带index的 created / skipped / failed;同渠道解密后内容完全一致去重。前端支持 JSON 数组 / JSONL / 选文件,失败行回填 JSONL 重试。 - 月度账单(
GET /api/billing,operator):按人读小时汇总、按 Key 读明细并补归属用户与 Key 名;json/csv(带 BOM)/jsonl(逐条明细),两种导出都写ACTION_DATA_EXPORT审计。 - 三类新告警:预算分层(
ALERT_BUDGET_CNY/ALERT_BUDGET_LEVELS,按本地自然月可定价成本打 50/80/95/100% 档,只报当前最高档,升级时旧档由迟滞状态机写成已恢复,100% 为 critical)、单 Key 用量暴涨、非工作时段请求(后两者默认阈值 0 = 关闭)。 - 告警出口扩到飞书 / Slack:飞书按
msg_type=text、Slack 按{text}组包,多渠道并发,单个失败不影响其它渠道。 - 用户级策略(
SCHEMA_VERSION30):users新增allowed_models/quota,空串 = 不限制。会话 Cookie 只回答「你是谁」,不回答「你能用哪些模型、一天用多少」——viewer 用 Playground 直调任意模型可整体绕过 Key 的模型白名单与配额,现 Playground 与/v1共用同一套校验,配额按 username 聚合(Playground 的api_key_id为 NULL 也计入)。用户管理页可直接编辑,写操作落ACTION_USER_POLICY审计。 - 全局 kill switch(
gateway_paused,热更):所有 Key 鉴权的/v1立即 503,管理面保留;开与关两个方向都落审计,原因只进日志不回显。 - 凭证出口池(
CREDENTIAL_PROXY_POOL):按sha256(credential_id)取模分配,重启不漂移;LazyClients按(流/短,代理)分池,因为 httpx 的代理是连接池级参数。优先级:凭证池 →PROVIDER_PROXIES[渠道]→ 直连;未配池时行为逐字节不变。 - 冷却到期半开探测:到期先进
HALF_OPEN,只放行 1 个探测请求,成功才全量回池。 - Zen 门禁配置化 + 渠道 ToS 风险登记:
ZEN_USER_AGENT/ZEN_API_ROOT/ZEN_GATE_TOOLS全部可配,默认值保持实测通过的形态;ToS 按 green / gray / red 登记理由,导入凭证响应与列表透出、审计写等级,新增渠道漏登记启动即失败。
引擎与兼容层
- DSML 回读:DeepSeek V3.2/V4 偶发把工具调用写成 DSML 文本,解析单/双竖线两种方言、V4「自闭合 invoke 带 string」与缺外层包装的裸 invoke 块;流式增量过滤,普通正文零缓冲、跨 chunk 分片不断、未闭合标记收尾原样放行。回读出调用时
finish_reason由stop改写为tool_calls(否则客户端不执行),tool_calls缺id按 index 补并记忆。 - 坏参数 fail-closed:非流式下坏
arguments判InvalidToolArguments(kind=INVALID)→ 换上游重试、最终 400,不冷却凭证、不把坏 JSON 递给客户端。 - 用量对账:成功请求正文体量与上报
output_tokens明显不符时 WARNING(上游吞 usage / 静默替换模型的间接信号),只告警不改响应。 - 截断流留痕:
error_type=truncated_stream,凭证照常save_success(上游没报错);档位降级与 tool 输出压缩(默认关,不破坏前缀缓存);上游model观测,Qoder 回auto视为占位名忽略。 - 会话粘性接受
session_id请求体键。 - TRAE 从元数据帧补回真实模型名;CodeBuddy 国际站指纹对齐官方 CLI、
11158归model_not_found、探活结果落盘。
信道判死语义修正
11140账号受限不再永久禁用:新增ErrKind.RESTRICTED,先于 DEAD 判定,落 2h 冷却(采用上游Retry-After,夹 24h),当前请求跳该渠道其余凭证继续试其它渠道;窗口内(10 分钟)第二次命中升级为渠道级 24h 暂停,只冷却不禁用。统计新增account_restricted(前端「账号被上游限制」)。保留 DEAD +disabled_reason:真 session 失效仍按原语义硬禁用。- 硬禁用写入可操作原因:
ErrorOutcome新增disabled_reason,CodeBuddy11140写受控文案「账号存在异常行为,已被限制使用」,不再一律session dead——重登无效,只能申诉或换号。 - 探活判死即隐藏、复探恢复:判死隐藏不再要求「同时仍挂 blocked 负缓存」,人工「立即探活」判死时也会隐藏;
failed_rows()每轮把判死行一起复探,用上游原名;恢复入口收敛为「复探成功」。 - Qoder 流内信封与 HTTP 错误同一判据:
classify_error_code增加 401/403 分支,有会话失效标记 → DEAD,否则 → QUEUE/RESTRICTED,403 不再一律判死。
运维
- 单实例锁:SQLite 允许多进程并发写(WAL + 忙等),起两个实例不报错只会安静互相覆盖——同一凭证被探两次、同一小时汇总写两遍。
src/instance_lock.py对DATA_DIR取 flock,run()在build_app之前调用(后者会建库/迁移/应用待恢复备份)。锁文件常驻不删,进程被 SIGKILL 时内核自动释放。取锁失败以退出码 0 返回并打印持有者 PID:launchdKeepAlive.SuccessfulExit=false、systemdRestart=on-failure、composerestart都只在非零退出时重拉,非零会变回崩溃循环。launchd 改条件KeepAlive,systemdExecStart从 uvicorn CLI 改为src.main(否则绕过锁),TimeoutStopSec与 launchdExitTimeOut补到 95s。 - 日志轮转改截断式 +
scripts/rotate-logs.sh(拷贝 → 压缩成功 → 截断,任一步失败都不动原文件);去掉 BSD 专用stat,Linux CI 才能真跑;tool输出压缩日志降 DEBUG。
前端
全局错误边界(顶层兜住登录/路由/chunk 失败,Layout 内再兜一层保留侧栏)+ 首启向导;任务与配置两级 tab、配置分组细化;明细表排序改列头下拉,渠道/凭证合并一列;额度包明细只展示剩余 > 0 的包;模型趋势 Y 轴上限取全部在画线的公共最大值;告警规则数量与文案对齐七类。
文档
新增四张图(请求主链路 / 账号流 / 数据模型 / 权限矩阵);33 篇 md 逐篇对照 src/、web/src/、scripts/、compose 校正:schema 30、表清单 13 张(补 model_probes)、可热更配置 77 项、管理台 15 页、告警七类。
升级
SCHEMA_VERSION 29 → 30:users 补 allowed_models / quota(默认 '' = 不限制,老库幂等补列,补列后 Playground 行为与补列前一致)。升级必须重启后端。