Repository navigation
Releases: RobbsLuo/Coding2API
Release list
v0.10.1
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 行为与补列前一致)。升级必须重启后端。
v0.10.0
v0.10.0 修复版:出口排队重开与非流式保活、统计页重排与失败归因「已救回」,外加一批「静默出错」的收口。SCHEMA_VERSION 不变(29,无新列新表),升级必须重启后端。
v0.9.1 之后的 45 个提交以修复与收敛为主,但含新端点与新能力,故按 minor 发。
- 新端点
GET /api/stats/percentile-timeline(operator+):延迟分位时序,P50 中位数 + P95 上界两条线,给出「典型值 + 长尾」两层。只认latency/ttfb两个指标,其余显式 400。 - 排队重开(Qoder / TRAE 的
isQueued/RESOURCE_LIMIT):不冷却凭证、不换号,等retryAfterSeconds后在原号重开。轮次与单轮等待都有上限;已出帧的流不重开。排队不消耗换号预算(此前三次排队就把max_rotate吃满、直接 503)。 - 非流式保活(
NONSTREAM_KEEPALIVE_SECONDS,默认 0 = 关):stream=false聚合完成前一个字节都不发 → CDN / 反代空闲超时直接切连接。宽限期内完成仍是逐字节相同的 JSONResponse,超时才转 chunked 先吐空白心跳再补正文。 - 统计页重排:一张图一个系列;延迟另加分位图;时间轴补齐小时桶(稠密时间轴);口径说明折叠。
- 失败归因区分「已救回」:失败数是尝试口径(换号重试每次上游拒绝各落一行),只看它会把「已救回的尝试」读成「用户受损」。新增
rescued(同用户同request_id另有成功行),前端展示「未救回 = failures − rescued」。救援关联限定同用户——request_id取自入站X-Request-ID,客户端可伪造,只按 ID 关联会跨用户误判(已复现)。 - 图指标改语义化聚合:图表指标不再混算,口径写进 README / TECHNICAL。
一批「静默出错」的收口(每条都配了回归测试):
- Qoder 保活帧打断整条流:上游在流中发
{"headers":…,"body":"null"}保活,此前判成协议违规 → 抛异常 → 整条流失败,而模型其实已在正常输出,客户端只看到回复被截断。判据改用结构(json.loads后是None/ 空 dict / 空 list),保活帧直接跳过。 - 排队报文被漏判 → 好凭证被硬禁用:上游把「排队中」包成 403,排队标记藏在再序列化过的字符串里,
parse_queue_hint只认 dict/list → 漏判 → 403 落 DEAD → 可自愈的凭证被打进冷宫。改为下钻字符串 + 排队判据进classify_error_code(任何入口都不漏判)。 - 一条坏凭证连累整批(
凭证解密失败:APP_SECRET 是否被更换过?→ 500):解密失败早先直达顶层 → 整个聊天请求 500、整轮后台任务挂掉、整页模型列表 500。改为按路径分口径:批处理路径(选号、模型列表、后台任务、即时探测)捕获后跳过该凭证并记日志;单条探测端点照旧如实报 500——管理员该去处理这个号。 - 探活判死只影响展示,别名登记保留:上游目录撒谎(挂着某个模型但推理端点 404)时,判死把该 (渠道, 模型) 从模型列表摘掉;旧实现连别名登记一起摘,执行侧因「没有渠道登记该模型」回退成全部渠道扇出 → 请求被发到一堆根本没有该模型的上游,各回「无此模型」,负缓存写在从没有该模型的渠道上。现补登记回别名表:仍收窄到真正持有它的渠道,快速 503「该模型暂时不可用」。
- TLS 中断(
ssl.SSLError)不再逃成 internal_error:它不是httpx.TransportError,落不进任何分类分支 → 异常一路逃到出口,表现为一帧internal_error:不换号、不冷却、统计里零痕迹,失败归因面板完全看不到。归 SOFT(仍只认具体类,不放开到OSError整体——磁盘满也是 OSError 子类,误判会去冷却一个完全健康的凭证)。 - 国际站白名单混入国内站主机时一律拒绝:只校验「端点在白名单里」不够——把国内站主机加进国际站白名单后端点校验会通过,国际站账号的 Token 照样发往国内站网关(跨站发送即凭证泄露)。
- JSON 溢出成
inf的合法数字(1e999)→ 400 而非 500:字面量闸拦得住NaN/Infinity,拦不住合法 JSON 数字溢出;在解析层加parse_float守卫,三个出口共用一个入口。 - 指定凭证(pin)的类型与存在性校验:非字符串
credential_id→ 400(放任进 sqlite3 绑定 → 500);不存在的 id → 400 且不清掉别人的 pin(此前端点回 200,管理员以为已指定,实则把指定清空了)。 - 统计
metric取值域显式 400:未知取值此前静默回落到「请求次数」,客户端拼错参数会拿到一份「看起来正常」的图,错误被完全吞掉。 - 未匹配的
/api、/v1对任何 HTTP 方法都回统一 JSON 404:只注册 GET 时,未匹配的 POST 会落到 Starlette 的 405{"detail":…},与统一错误体形状不符。 ADMIN_USERNAMES只在引导期提权:库里已有活跃 admin 时不再改写任何人的角色。此前每次启动都无条件提权,管理台刚降级的用户重启后又变回 admin,「降级立即生效」被重启撤销。- 加载失败 ≠ 空数据:告警页此前在请求失败时显示「暂无告警记录…一切正常时保持空白」,用户会把故障读成「系统健康」。改为显式错误态;统计页同款问题一并修。
- 外链 scheme 白名单(
safeHttpUrl):管理台外链不再直接透传上游给的 URL。 - 冷却对齐上游正文点名的重置时刻:CodeBuddy 国际站 429+
6004只在 msg 文案里给恢复时刻、不给Retry-After头,原实现取不到 → 回落 600s 基数 → 到期重试再撞 429(实测一个号一天被爆 42 次)。 - 冷却日志区分账号级与模型级作用域:此前账号级冷却也打「模型 <名>」,读起来像只锁了这一个模型。
- 留存任务回收过期账号级冷却:过期
cooling_until永留库里,管理台列表按原始值下发 → 排序失真 + 幽灵记录。 - CodeArts 非 JSON 响应对外不带上游 URL:异常文本带 URL 只进日志。
- 用户名单渠道式交互收口:TRAE 回调打不开时改用粘贴链接完成登录(回调由浏览器打开,NAS / 远程部署里常直接「网络错误」);回调基址落在回环 / 通配主机时改用当前请求 origin;Cookie 不可用时按
loginTraceID反查发起人,绑定在那一次 pending 登录上。
其他:
- 探活判死不误伤扇出:
BLOCKED独立成model_not_found(原先并进invalid_request,读起来像客户端参数写错,实际是上游把模型下架了)。 - 签到失败不再是 500:上游拒绝(账号被禁用 / 登录过期)是这条凭证的真实答复,收成
ok=false+ 可读 message。 - 单渠道模型也下发
by_provider:此前只给多渠道,单渠道模型的原代号对外完全不可见(排障时看不到实际请求的 key)。 - provider 层去重(净减约 210 行):四家 OpenAI 兼容渠道的 SSE 解析骨架合一(zen / kilo / officeace / codebuddy,净减 177 行)、
AuthStateStore泛型化(4 份 owner/consume/cancel/cleanup 合一)、华为云系凭证字段合一、懒建连接池统一到LazyClients、pacer 的wait_turn+release配对收进paced()上下文管理器。 - 任务调度 / 仓储层的机械重复收敛:runner 的 12 分支周期 if-chain 改字典派发、repo 的 27 处
int(now if now is not None else time.time())收进_now()、executor 的 4 份排队重开逻辑收成_plan_queue_restart()。 - 依赖安全更新:body-parser 2.4.0(GHSA-27r3-jxmh-p828)、fast-uri 3.1.9、source-map-js 1.2.2(GHSA-68fv-2mgg-jv7q)、certifi 2026.10.19。
- CI 抗抖动:npm registry 的两处单点加显式重试;
pnpm audit与 Dockerfile 取 pnpm 本体两处都加重试。 - 前端依赖瘦身:
.npmrc加auto-install-peers=false,lock 从 1023 个包降到 601 个,pnpm audit --prod0 漏洞;DockerfileCOPY web/.npmrc(否则容器内 pnpm 退回默认autoInstallPeers=true,与 lockfile 不匹配直接ERR_PNPM_LOCKFILE_CONFIG_MISMATCH)。
文档(README 中英 / TECHNICAL / PROPOSAL)全量对齐当前代码:环境变量表覆盖 config.py 全部字段、schema 版本与表数、统计口径与图表指标语义、出口保活与排队重开的行为契约。
v0.9.1
v0.9.1 修复版:CodeArts 福利链路下线、模型列表按探活结论收敛、输出速度拆双口径,外加前端依赖瘦身与 CI 抗抖动。SCHEMA_VERSION 28 → 29(删除三列积分账),升级必须重启后端。
上游每日 1000 万免费 token 池已下线(活动落地页与官方文档均 404,客户端模型列表里已无福利模型),故全链路移除。积分账成为 CodeArts 唯一的额度来源,直接落在通用列(quota_remaining 等)上。
-
对外形状变化:
GET /v1/models不再下发benefit字段;凭证页不再把 CodeArts 拆成「内置 / 福利」两组,一个真实渠道一个组,组头写「积分合计」;额度探测响应不再带credits_remaining/credits_total。 -
DB:
schema.sql删掉credentials上的quota_credits_remaining/quota_credits_total/quota_credits_expiry_ladder;migrate.py新增_MIGRATION_COLUMN_DROPS(ALTER TABLE DROP COLUMN,列不存在时忽略,要求 SQLite ≥ 3.35),SCHEMA_VERSION升到 29。老库升级自动完成,无需手工迁移。 -
credit_events.ledger与?ledger=保留:账本由凭证渠道决定(codearts→credits,其余 →pool),每轮探测只记一条流水。 -
白名单去掉福利网关三主机;删掉
units.py/backfill.py与两个一次性折算脚本。 -
模型列表摘掉探活判死的 (渠道, 模型):判死且仍被
blocked负缓存锁着的条目才逐渠道抽掉(两个条件缺一不可——只看到期会让模型永久消失,只看判死不会自动恢复)。探活面板命中黑名单的行整条不返回;点名直连不受影响。 -
成本口径修正:OfficeAce 的快照日代号
deepseek-v4.1-flash-0930与 CodeBuddy 国际站的区域代号deepseek-v4.1-flash-sg在价表里查不到,cost_usd/cost_cny恒为 NULL(实测两条渠道共 3600+ 条)。改为逐 id 登记「代号 → 基础模型」,不做通用剥尾(OpenRouter 的-1017是另一个价位的快照,通用剥尾会把两套价格混成一个)。历史明细需scripts/backfill_cost.py --apply补齐。 -
模型名归一:CodeBuddy 的
Xiaomi MiMo-V2.6-Pro归到mimo-v2.6-pro,与 TRAE 的同名模型合并,不再多出一个xiaomi-mimo-v2.6-pro。 -
OfficeAce 登录:新增「换账号」(浏览器里留着上个华为云会话时会直接放行,导致「新增凭证」变成「同一账号再登一遍」);凭证昵称改为取
principal_urn末尾的用户名(此前退化成一串 32 位账号 ID);轮询失败透出上游可行动的原因(如「这个账号还没开通 OfficeAce 服务」),不再统一吞成「请重试」。 -
渠道展示名统一为 OfficeAce / CodeBuddy 国际 / Kilo。
-
输出速度拆「正文 / 总产出」双口径:
tps_visible= (output_tokens−reasoning_tokens) ÷ 生成时长,tps=output_tokens÷ 生成时长,两列同分母。思考 token 成批快吐,与正文混算会远高于屏幕刷新速度(实测占比 50–67% 时约 190 与 63 tok/s)。下沉到逐请求明细与实时流;主口径无样本时回落估算口径并前置≈。明细表顺带合并列:时间拆两行(时刻在上、日期在下),渠道 / 凭证合成一列。 -
凭证页渠道组头显示模型数与倍率:折叠态即可读「数量 + 最低倍率」,hover 展开逐条「模型名 + 该渠道倍率」(按渠道取,不拿合并值冒充)。最低倍率只统计收费模型,整组免费时写「全免」;未给倍率显示
—而非「免费」。浮层拆成两档表面:短提示走反色气泡,多行清单走 panel(描边 + 阴影、不出箭头)。 -
前端依赖瘦身:
@lobehub/icons把@lobehub/ui/antd声明为 peer,自动安装会拖进 400+ 个用不到的包。.npmrc加auto-install-peers=false,lock 从 1023 个包降到 601 个;真正需要的 peer(@testing-library/dom)显式声明。副产品:pnpm audit --prod从 1 条 low 变成 0 漏洞。纯删除,无版本漂移。 -
Dockerfile
COPY web/.npmrc:否则容器内 pnpm 退回默认autoInstallPeers=true,与 lockfile 的settings.autoInstallPeers: false不匹配,直接ERR_PNPM_LOCKFILE_CONFIG_MISMATCH。 -
CI 抗 npm registry 抖动:
pnpm audit与 Dockerfile 里 corepack 取 pnpm 本体两处都加了显式重试(审计端点偶发ERR_SOCKET_TIMEOUT,corepack 取 pnpm 偶发 503,且 corepack 自身不重试)。
README / README.en / TECHNICAL / PROPOSAL / AGENTS / SECURITY / design-system MASTER 全量对齐当前代码:schema 版本与表数、技术栈版本、热更设置数(60)、任务数(12)、环境变量表(覆盖 config.py 全部 96 个字段)、.npmrc 与 lockfile/Dockerfile 的耦合约束。
v0.9.0
v0.9.0 新增第八个渠道 officeAce(华为云果办 / AgentArts),覆盖对话、模型、额度、签到、刷新与登录全链路。SCHEMA_VERSION 不变(28),升级必须重启后端。
- 新渠道 officeAce(
officeace):点「登录 officeAce」走华为云授权,回调由云端承接(/v1/claw/auth/callback),本服务不监听端口、用户不粘链接,后端按 2.5s 轮询/v1/claw/auth/code取码(与官方桌面端同一机制)。前端补齐渠道标签、缩写、配色、图标、登录入口与额度口径;OFFICEACE_*三个环境变量已透传到 compose。 - 两套凭据、两个面、两种签名(本渠道唯一的复杂度来源):聊天用永不过期的
Basic model_app_key:model_app_secret;控制面(积分 / 签到 / 费率)用约 2h 的临时 AK/SK +security_token+project_id,由预刷新任务续期。控制面/v1/claw/*走华为云SDK-HMAC-SHA256;模型网关/v1/subscription*、/v1/model-token-rates只认V11-HMAC-SHA256(多一层 region 作用域 + 密钥派生)。混用的回包是APIG.0303/APIG.0624/ 恒 401verify ak sk signature fail,不告诉你哪一步错。refresh_token与client_id=pdp5_for_agentarts+ DPoP 私钥三者绑定、一次性轮换,且与 CodeArts 的票不通用。 - 错误分类:限流走伪 200(HTTP 200 +
data:{"error":…}),并有「首帧正常、第二帧才是错误」的第二种形态,故不能在首帧成功后停止检查。81004(该号没这个模型)/81009(名字不认)归BLOCKED并登记模型级负缓存(成功一次即撤销,同渠道同模型的其它凭证一并跳过);81111/81112/81114归限流,只冷却「该凭据 × 该模型」;14018归欠费。 - 不做主动模型探活:目录 34 个里实测只有 11 个真能用,但探活要真发推理、消耗积分,而额度是稀缺资源。模型级拒绝改由真实请求的
BLOCKED负缓存处理,比开机烧 34 次推理省得多。同理不做 credit 估算:上游给了cost_coefficient与tokens_per_point,但二者的叠乘关系官方未说明,凭空折算会与真实扣点对不上、并让跨渠道额度排序整体失真。 max_tokens改写:可用模型里 9/11 是推理模型,给 64 会被思考预算吃光、正文为空。≥16一律追加 1024 余量再夹到模型硬上限(glm-5*131072 /qwen3*65536 /deepseek-v4.1-flash393216);<16原样透传(探活的精确请求);未给不补。max_completion_tokens归一成max_tokens。- 积分即主账:单位
officeace_points(新用户一次性 4000 + 每日签到 1000),没有并行的 token 池,remaining/total直接是积分。每笔奖励独立到期,故额度口径写「逐笔到期」,调度仍按到期阶梯「快过期的先用」。 - 每日签到:
POST {gateway}/v1/subscription/bonus/claim是写操作(调用即真发积分),body 必须给 {} + JSONContent-Type——官方调用点是空 body,但实测那样回 500OfficeAce.11020001。上游对当日重复领取幂等,故不需要本地记「今天领过」。收获按bonus_skus的剩余量增量算(points是活动累计发放量,由多个渠道共同贡献,拿它当本次收获会虚高)。封账到下个北京时间 0 点,次日新活动一出现自动补签。 - 登录状态按 username 分键:
AuthStateStore做 reservation(begin/owner/session_entry/touch/consume/cancel/cleanup,带 TTL 与 pending 上限)。单槽全局态会让两个管理员的并发登录互相覆盖、把 A 的凭证记到 B 名下;并发轮询同一 state 时consume只有一路成功,另一路抛错——否则同一账号会出现两条重复凭证。 - 网关地址归一:
client-permission-validate下发的api_base带/v2,models.json里存的不带;统一去掉尾部/v2再拼端点,否则聊天拼出/v2/v2/chat/completions。网关主机每账号一个,故不进OFFICEACE_ALLOWED_ENDPOINTS(白名单只管控制面,带临时 AK/SK 签名的请求只发往白名单主机)。 - 单账号单用户:官方《套餐管理》明确「个人版面向个人用户,限制单账号单用户使用」,故本渠道不做多人共用,每个使用者各自添加自己的凭证。
其他改动(v0.8.0 之后):
- CodeBuddy 国际站模型列表按套餐探活过滤:
11158/11102判定为「该套餐不含此模型」并从列表剔除,限流错误保留(限流是临时的,不该让模型消失)。 - 模型列表连续失败退避:连续失败时逐步拉长重试间隔,避免往一个已经坏掉的上游持续打请求刷日志。
- 读体断开回 499:客户端在读请求体时断开,此前落到通用异常处理回 500 并记
error级日志;现按 499 记录,不再污染错误率。 - 传输层异常归类 + 上游错误码补全:把连接重置 / TLS 失败这类传输层故障与「上游明确拒绝」分开归类,探针与日志相应降噪。
- 签到 / 预刷新跳过用户软暂停的凭证:
enabled=0的凭证不再参与签到与预刷新轮次,口径与调度器is_selectable一致。 - benchmarks 浮动别名取同族最新快照的分:OpenRouter 把浮动别名钉在旧快照、并把该条换成 Non-reasoning 变体,导致智力分「掉」15 分;现按
canonical_slug的-YYYYMMDD归族取最新快照,显式带日期戳的 id 仍用自己的分。 - 默认模型改
deepseek-v4.1-flash,默认黑名单与线上生效值对齐。 - 前端:套餐明细弹层按可用高度封顶,不再被顶出视口。
已知限制:officeAce 上游账号尚未开通模型网关(client-permission-validate 返回 subscription: null),故聊天、模型列表、积分与签到的端到端验证是按协议文档 + mock 完成的;开通后用真实账号复核。cache_control 透传在该渠道同样未验证。
v0.8.0
v0.8.0 覆盖 v0.5.0 之后的全部改动(A/B/C/D/E 五批,SCHEMA_VERSION 25 → 28)。升级必须重启后端。
新增
模型面(批次 C)
- 主动探活 + 人工接管:真实请求失败只能证明「这次没打通」,分不清「上游真没这个模型」与「额度 / 限流 / 网络抖动」。新表
model_probes+ 后台任务(MODEL_PROBE_MINUTES,默认0= 关闭,可热更)只探仍被blocked负缓存锁住的 (渠道, 模型)——遍历全量模型表要真发几百次对话,耗的是用户额度,而负缓存才是唯一会静默避让一个模型 6–24h 的状态。- 三态判定:成功 → 清该渠道的
blocked负缓存(TTL 走完之外的唯一提前恢复入口);BLOCKED/INVALID→failed,保留负缓存并累加连续失败;额度 / 限流 / 网络 / 超时 / 空流 / 任何异常 →inconclusive,绝不禁用,且把连续失败归零(一串无关故障不该凑成「连续失败」判死好模型)。 - 与生产完全隔离:直连
provider.stream_chat,不经 executor,不写usage_events、不动冷却(除成功时清)、不改健康度、不参与选号。结论落独立的model_probes表——探测失败 ≠ 上游拒绝。 - 端点(operator + CSRF + 审计):
GET /api/models/probes、POST /api/models/probes/probe(立即探活,不受接管限制)、POST /api/models/probes/manual(on/off)。人工接管后自动探活整行跳过,接管不改负缓存。 - 「模型列表」页新增探活面板:三态结论、负缓存号数与最晚到期、最近探活 / 错误摘要、立即探活、接管 / 交还。
- 三态判定:成功 → 清该渠道的
- 模型可用性视图 + 一键黑名单:
GET /api/models/availability(operator)聚合最近 N 天(默认 7、可调 1–30)error_type为upstream_blocked/invalid_request的失败,按(渠道, 模型)给出失败次数、最近失败时刻与「是否已在黑名单」;「模型列表」页可切「疑似下线」筛选,行内「加入黑名单」把该模型追加进model_blocklist(读现值再写,不覆盖既有项)。 - 自定义模型别名(
MODEL_ALIASES,可热更):对外名=模型@渠道;对外名2=模型。列表与请求解析用同一份别名表(不会「列表有、请求 404」),条目带custom_alias: true;与真实 id / 自动别名撞车、目标不存在、渠道不持有该模型时该段记 ERROR 并跳过。 /v1/models补cost与reasoning_efforts:刊例价(输入 / 输出 / 缓存读,USD / 百万 token,缺价时整个字段缺失而不是 0)与生效中的推理档位。GET /v1/models/{id}单模型查询(OpenAI 同形):认原代号 / 归一键 / 展示名 / 自定义别名,带命名空间的原代号也能查;白名单外与不存在同为 404(无法用单查探测池内模型)。
配额与自助用量(批次 B)
usage_events.api_key_id(schema 26):把每条请求归属到发起它的 API Key,作为计量地基;老库补列后历史行为NULL= 未归属。- Key 级配额(schema 27):一个 JSON 字段六项独立,
0/ 留空 = 不限制——daily_requests/daily_tokens/daily_cost_usd/rpm/tpm/max_concurrency。当日类按北京时间自然日(与凭证护栏同口径),速率与并发是进程内滑动窗口(重启清零)。超限 429 +Retry-After指向可重试时刻。判定本身出异常时一律放行并记 warning——计量故障不能把正常请求打死。 GET /v1/usage?days=1|7|30自助用量:持 Key 的调用方查自己的用量、剩余额度与当前速率占用(只读本地明细,不触发上游,不含凭证昵称或池级信息)。
统计(批次 D)
- 失败归因:
GET /api/stats/errors(operator+)按(渠道, 模型, 错误类型)聚合ok=0明细;统计页「失败归因」面板点行即钻取到下方明细并自动加「只看失败」(GET /api/stats/events?ok=0),键盘 Enter / Space 同样触发。 - P50 / P90 / P99 分位:与 P95 同一套 SQL(一次子查询算完四档,nearest-rank,n 为有值样本数);分组表延迟列的表头有四档切换,不铺开四列。只统计成功请求。
- 请求明细实时流(SSE):明细面板「实时」开关打开后订阅
GET /api/stats/events/stream,展示当前筛选范围内刚落库的请求(与历史明细分开展示)。事件在StatsCollector.record事务提交后由进程内 hub 广播(不轮询数据库)。
引擎与出口(批次 A)
- 流式超时(默认关闭,可热更):
STREAM_FIRST_EVENT_TIMEOUT_SECONDS在出帧前超时则换号重试(此时切换安全);STREAM_IDLE_TIMEOUT_SECONDS在已出帧后超时则只发一帧错误收尾——半截输出不可回滚,换号会把两个账号的内容拼给客户端。首事件超时默认必须保持关闭:实测慢上下文首字可达 40–71s,默认值会误杀正常请求(推荐60;空闲推荐300)。 Retry-After解析:上游Retry-After(含Try again in 17h 59m这类文本式)→ 「何时恢复」的 epoch 秒,冷却按真实恢复时刻算,不再一律套固定 TTL。- 短冷却「等待续上」(
SHORT_COOLDOWN_WAIT_SECONDS,默认0):全池都在短冷却、最短剩余不超过该值时等待后重取一次,而不是直接 503;等待期间不占在途租约、不计入轮换预算。 n > 1显式 400:本网关的响应结构只能产出一条候选,此前静默只回一条,客户端以为拿到了 n 条。- 选号加入在途负载键:并发不再全压同一凭证。
cache_control原样透传(Anthropic):落点与 Anthropic 一致,只做结构校验、取值不解释;不带标记时映射结果与旧版逐字节一致。response_format语义收口(chat):text/json_object直通,json_schema展开。
会话与任务(批次 E)
- 会话粘性接受请求头标识:优先级 请求体显式键(
conversation_id/prompt_cache_key)> 请求头(x-session-id/x-opencode-session/x-session-affinity/conversation-id)> 消息前缀指纹兜底。头与指纹值都掺username再哈希(两用户同值不串号),头必须过字符白名单,非法则丢弃退回兜底。 - 签到定时(
CHECKIN_TIMES/CHECKIN_JITTER_MINUTES,可热更):本地时间HH:MM多时点,抖动在时点之前提前0..N分钟把多部署摊开;按「日期 + 时点」去重,抖动只改执行时刻不会跑两次。配了时点后循环改为每 60 秒醒一次(否则抖动 = 0 时窗只有一分钟,必然整天漏签)。留空 = 全天每 10 分钟检查(旧行为)。 - 服务端日志页(
/logs,仅管理员):GET /api/logs取最近若干行、GET /api/logs/streamSSE 先回放缓冲再推新行;级别筛选、关键字过滤、跟随最新、暂停与清空。没有任何写入或执行入口。每行发出前过脱敏白名单,命中token/secret/authorization/cookie/password/api_key或sk-…形状的整行丢弃(LOG_BUFFER_LINES,0= 关闭该页)。 - 请求级结构化日志(
REQUEST_LOG_ENABLED,logfmt):每个业务请求一行event=request request_id=… method=… route=… status=… duration_ms=…;路由用模板不用实际 ID,不写 query string / 请求体 / 用户名,靠request_id关联usage_events。静态资源与探针不记。
管理台
- CodeArts 内置组健康度改按积分账派生:凭证页把 CodeArts 拆成「内置 / 福利」两组、每组只讲一本账,但健康度一直读主账(每日 token 池),导致内置组出现「额度列显示积分还剩 99%、健康度却 0%」的自相矛盾。新增派生的
quota_credits_health(不参与调度,选号仍只读主账health),前端按展示组取对应账本的健康度。
变更
SCHEMA_VERSION25 → 28:新增model_probes表;usage_events.api_key_id、api_keys.quota两个新列(走幂等补列);新增索引idx_usage_key。老库启动时自动迁移,无需手工操作。- 新增可热更项:
MODEL_ALIASES、STREAM_FIRST_EVENT_TIMEOUT_SECONDS、STREAM_IDLE_TIMEOUT_SECONDS、SHORT_COOLDOWN_WAIT_SECONDS、MODEL_PROBE_MINUTES、CHECKIN_TIMES、CHECKIN_JITTER_MINUTES、LOG_BUFFER_LINES、REQUEST_LOG_ENABLED。 - TRAE 上下文压缩预算按实测抬到 1M:
_CHANNEL_WINDOW_FLOOR = {"trae": 1_048_576}。实测 1,450,000 字符(1,035,544 token)答对、1,470,000 字符报4022/4026,此前按更小的窗口提前压掉了本可用的上下文。 - 后台任务由 11 类增至 12 类(新增模型主动探活)。
修复
- CodeArts 积分账与主账健康度串台(见上「管理台」):同一行出现「额度 99% + 额度耗尽」的矛盾状态。
- 签到配了时点后整天漏签:轮询周期仍是 10 分钟、而抖动 = 0 时时窗只有一分钟。
升级
docker compose pull && docker compose up -d镜像:ghcr.io/robbsluo/coding2api:v0.8.0(同时更新 :latest)。
升级注意:
- 数据库 schema 从 v25 升至 v28,启动时自动幂等迁移(建
model_probes表 + 补两列 + 建索引)。升级后必须重启后端,否则会出现「新前端 + 旧后端」错配(新端点 404,页面弹出与真实原因无关的兜底文案)。 - 新增的后台探活默认关闭(
MODEL_PROBE_MINUTES=0)——探活会真发上游请求、消耗额度。要开请在「任务与配置」页填周期(热更,不必重启),实际建议 ≥60 分钟(负缓存本身 6h 起步)。 - 三个流式 / 冷却相关开关默认全关,升级后行为与旧版一致;要启用请按部署实际填(首事件超时推荐
60,空闲超时推荐300)。
v0.5.0
新增
- 侧栏数据提醒(导航角标):侧栏对应项上显示待办计数角标——凭证需重登/耗尽、未恢复告警、上次失败任务、异常上游源、待激活账号、本人将到期 Key、模型目录陈旧共 7 项,不点进去也能看到。单个聚合端点
GET /api/nav-badges一次返回、侧栏 60s 轮询;按角色裁剪 payload(缺失 = 无权看),只数「待办」而非页面总数(如告警只数resolved_at IS NULL)。 - CodeArts 双账本:CodeArts 内置模型走积分账、福利模型走每日 token 池,两本账并行且健康度只看主账;
credit_events.ledger区分两本账,管理台按账本分开读。福利模型带benefit标记(渠道徽章打「福」标),Model.benefit不能与credit_rate == 0混用。 - 运维告警迟滞 + 恢复通知 + 人工处置:
ALERT_FOR_TICKS/ALERT_CLEAR_TICKS进入/恢复迟滞;恢复时写resolved_at并外推status="resolved"webhook;告警页每行未恢复告警带「标记恢复」按钮(POST /api/alerts/{id}/resolve,admin + CSRF + 审计),用于规则已下线 / 误报等后台无法自动判定的情况。 - 上游状态页聚合:把各模型 / 网关提供方的官方状态页(OpenCode Zen、Kilo、DeepSeek、Together、Moonshot、MiniMax、OpenAI、Anthropic)归一化后并排展示,回答「这个报错是上游整体挂了还是本服务的凭证 / 额度问题」。8 源 / 4 种解析器;只做解释、不参与选号 / 熔断;快照只存内存、重启归零。
- 凭证级限额护栏:保留积分 / 每日 token / 每日 credit / 按模型四个可选护栏,判定在选号前完成,触顶的凭证不再参与对话流量。
- 凭证在途上限:单账号并发请求数上限,占满的号不再参与选号,避免把单账号打进上游限流 / 封号。
- 凭证运维标签:每条凭证可贴任意个标签,作为列表筛选的第四维(搜索 × 渠道 × 状态 × 标签)。标签只用于筛选与展示,不参与选号。
- 凭证批量运维:
POST /api/credentials/batch(probe / toggle / checkin / revive,一次最多 200 条),凭证页多选操作条;逐条隔离执行,toggle/revive落一条汇总审计。 - 后台任务手动触发:管理台「任务与配置」页每个任务卡片带「立即运行」(
POST /api/tasks/{key}/run,admin + CSRF),绕过时点窗口但绕过不了开关。 - Prometheus
/metrics:默认开、不鉴权,零依赖 text 格式;禁高基数标签。 - 统计增强:自定义时间范围(
since/until半开区间)、分组表延迟统计(均值 + P95)、明细钻取 + CSV 导出(公式注入防护)。 - 多模态图片输入归一化:三个出口(chat / Responses / Anthropic)统一归一到 chat
image_url,出站零改动(实测七渠道出站已原样透传)。 - reasoning 档位映射 + 出站剥离思考:
FORCE_DISABLE_THINKING/REASONING_EFFORT_MAP/ANTHROPIC_THINKING_EFFORTS三项热更,默认全关——上游接受性未逐一实测,只给机制不给策略。 - 窄屏表格转卡片:列多的表格(凭证 / 明细 / 模型列表等)在 <768px 由「一行 = 一张卡」呈现,DOM 不变、读屏语义与宽屏一致。
- CC Switch 一键导入深链:API Key 管理页创建后生成
ccswitch://导入深链(claude / codex / opencode 三个目标)。 - 列表统一分页:六个扁平列表接到同一套控件(页码文案、20/50/100、上下页),后端
LIMIT/OFFSET+total;用量明细保留游标分页。 - 部署模板:frp 反向隧道(frpc / frps)+ nginx 模板 + launchd / systemd / newsyslog 单元,token 走独立 600 权限文件、配置不含机器特定值。
变更
- Docker healthcheck 跟随
PORT:此前写死 8000,非默认端口的docker run部署永远不 healthy。 - compose 透传
TZ与extra_hosts:容器内代理跑在宿主时须写host.docker.internal。 - Playground 布局重构:模型选择器独立面板,请求 / 响应并排。
- 表格列按相关性重排:身份 → 状态 → 核心量化指标 → 次要元数据 → 时间 → 操作。
/healthz语义:ready=0时返回 503unavailable(此前恒 200);/health仍是纯存活探针恒 200。容器 healthcheck 应指/health。- pacer 定值间隔向上抖动 25%:避免多实例 / 多账号在同一时刻撞上游。
- CC Switch 行内导入 + 明细合并列 + 命中率列。
修复
- 运维告警恢复不再永久卡住:
AlertTask启动时从库里未恢复的行重建「告警中」集合(此前该状态纯进程内,重启后历史告警永远等不到resolve());resolve()改为标记该(rule, scope)全部未恢复行(同一次故障的「提醒」行一起收尾,否则角标数resolved_at IS NULL永远清不干净)。 - 会话 Cookie 的
Secure按请求实际协议动态判定:同一实例 LAN(http) 与隧道(https) 双入口下,写死任一侧都会打断另一侧。 - 流内业务错误暴露真实分类:CodeArts 业务错误内嵌在 HTTP 200 的 SSE 里,此前被分类器兜底成
upstream_protocol,真实类型(额度耗尽 / 请求无效 / 渠道错误)全被吞掉。 - Atom 解析改用
defusedxml(bandit B314)。 - 全量安全审查修复批次:
/authorize回调绑定改判loginTraceID(撤掉 Origin/Referer 同源启发式)、告警 webhook SSRF 校验、上游错误体有界读取、出站文案不回上游原文 / 内部 URL、SQLite 写事务显式BEGIN IMMEDIATE、迁移版本护栏、CSP 收紧等。 - 前端:checkbox 触摸目标从 16px 扩到约 40×32;表单 label 与控件关联;dev proxy 不再吞
/api-keys;StatsPage补上引用的Pagination组件。
升级
docker compose pull && docker compose up -d镜像:ghcr.io/robbsluo/coding2api:v0.5.0(同时更新 :latest)。
升级注意:/healthz 在凭证池耗尽时改为返回 503;请确认容器 healthcheck 指向 /health(恒 200)。数据库 schema 从 v18 升至 v25(新增 credential_limits 表与索引;credentials 的 CodeArts 积分列 / tags、alert_events.resolved_at、credit_events.ledger、usage_events.request_id 等列),启动时自动幂等迁移(补列 + 建索引 + 删遗留表),老库直接升级无需手工操作。升级后必须重启后端。
v0.4.3
新增
- 凭证池:筛选与按渠道分组。凭证多了以后,「找到某一个账号」拆成三层:筛选工具条(搜索 × 渠道 × 状态,纯前端收敛,不改后端排序)+ 按渠道分组(组头做成一张紧凑的「渠道仪表盘」:品牌图标 + 渠道名 + 账号数 + 状态分布 + 额度合计占比环 + 到期积分)+ 列头跟着展开区走(没有全局表头,列头渲染在每个展开的组内部并吸顶)。默认全折叠,首屏先看结构;筛选生效时自动展开命中渠道,清空回折叠总览。组顺序默认额度从高到低,可切回固定的全站渠道顺序。「成长中心」列只对支持的渠道(CodeBuddy)出现,其余渠道留空占位格以保持列数恒定(否则 auto 布局会重算列宽、下面展开的组整列错位)。到期积分次窗口只在比主窗口多时才出第二块——CodeArts 每日池当天清零、两窗口恒等,不再把同一个数字说两遍。
- 模型列表页:
available与「只看当前渠道」。GET /api/model-catalog每行新增available布尔,表示该模型是否当前渠道真能提供(口径与/v1/models一致:只算有可用凭证、过当前黑名单的渠道),判定复用价表 / 能力分同一套候选键。页面提供默认关闭的「只看当前渠道」开关,勾选后本地收窄到当前渠道获取到的模型(不重新请求)。「能力分」列头可点排序(按综合智能指数,无分数的行排末尾)。
变更
- 用量统计默认最近 24 小时(原 7 天):打开统计页的第一问题是「这个池子现在怎么样」,7 天会把当天的波动摊平。仍可切 7 天 / 30 天 / 全部。
- 测试目录按
src/结构重组:tests/镜像src/子包(api/ auth/ compat/ config/ db/ deploy/ engine/ provider/<渠道>/ scripts/ stats/ tasks/ webapp/)+helpers/+regression/,巨型文件拆分到 600 行以内;「真连上游」豁免从按文件名判定改为@pytest.mark.real_upstream(...),文件重命名/下沉后不再静默失效。测试数与覆盖门槛不变(后端 100% 行/分支)。 - 内部重构(行为零变更):
api/models.py拆出model_merge.py纯函数层;三个/v1出口共用dispatch_compat;7 个上游端点解析器表驱动化;scripts/抽出_common.py(backup()+ 与Database.transaction同语义的DbAdapter,去掉 6 份 backup / 4 份 adapter 副本)。
修复(安全加固批次)
- 流式首帧后不再换号:已向客户端出过帧还换凭证,会把两个上游的半截内容拼进同一条回复。
- 登录 CSRF:无 Cookie 的写端点(登录 /
/authorize)也校验 Origin/Referer。 - OAuth state store(codebuddy / codearts / qoder)补 TTL 判定,过期 reservation 不再可轮询 / 重放;TRAE 回调登录按发起人会话绑定 pending(单槽全局态会被并发登录互相覆盖,把 A 的凭证记到 B 名下)。
- 上游错误体有界读取(7 处非流式错误路径改
read_body_bounded,恶意上游不能撑爆内存);非流式聚合加事件条数上限(上游死循环输出不再无界增长到 OOM)。 - 出站文案不回上游原文 / 内部 URL:
UpstreamProtocolViolation加受控public_message,告警 webhook 外发只留scheme://host与异常类名。 - SQLite 写事务显式
BEGIN IMMEDIATE(deferred 下读改写会丢更新);Database.transaction嵌套调用只有最外层提交 / 回滚;Database.close关闭所有线程连接。 - 告警 webhook SSRF 校验(拒内网 / 回环 / 链路本地 / 保留 / 多播 / 未指定),env 提供的
ALERT_WEBHOOK_URL同样校验;多地址改并发投递并加总预算。 - 迁移版本护栏:库
user_version高于本程序时拒绝执行(此前会把版本号写回旧值)。 - 凭证昵称仅 admin/operator 可见;模型白名单在无法判定模型名时 fail closed;登录限流失败键加数量上限与淘汰(堵用户名维度内存 DoS);
APP_SECRET补低熵拒绝。 - 管理台:admin-only 路径加
RequireAdmin守卫(非 admin 直输地址不再落到一片 403);错误文案只透出后端受控 message,不再渲染网络层英文实现细节。 - 前端:CSP 收紧到
default-src/script-src 'self'(主题初始化移出内联脚本)+Referrer-Policy: same-origin;/index.html不再发 immutable 缓存头。 - CLI:
hash_password/create_user新增--password-stdin(密码不进 argv / shell 历史);create_user --list改为只读。
升级
docker compose pull && docker compose up -d无数据库 schema 变更(PRAGMA user_version 仍为 18),无需迁移。改过 src/ 的本地部署必须重启后端进程。镜像:ghcr.io/robbsluo/coding2api:v0.4.3(同时更新 :latest)。
v0.4.2
新增
- CodeBuddy 国际版渠道(Q76,第七个 provider):接入 www.codebuddy.ai。与国内站同协议(同一 Keycloak realm
copilot、同一组/v2//v3/billing路径),故src/provider/codebuddy/intl.py只是CodeBuddyProvider的数据类子类,协议解析 / 凭证规范化 / 事件分类 / 刷新全部复用国内站代码,零复制。两站凭证可同时在池里、各走各的端点与 pacer。为什么不是「改CODEBUDDY_API_ENDPOINT切站点」:endpoint 是进程级单值,切过去会让存量国内站凭证全部打到国际站(额度错配 / 403)。白名单互不含——两站 Token 由不同网关签发,把国内站地址填进国际站端点在启动时抛错而非悄悄发出去。新增配置:CODEBUDDY_INTL_API_ENDPOINT/CODEBUDDY_INTL_ALLOWED_ENDPOINTS/CODEBUDDY_INTL_CHAT_MIN_INTERVAL(热更、默认 5s、独立 pacer)。 - 模型能力排行(Artificial Analysis 指数):经 OpenRouter 公开接口抓取三项指数,在 Playground、模型列表页与
/v1/models展示能力分。
变更
- 模型目录改用 OpenRouter 单一数据源(Q55-Q57):把 models.dev 价格/元数据目录整体替换为 OpenRouter,一次抓取同时产出刊例价(成本估算)、明细元数据(「模型列表」页)与 Artificial Analysis 能力分,消除双数据源、双匹配口径、双后台任务。后台任务
price_catalog+benchmark_catalog合并为openrouter_catalog,配置price_catalog_minutes/benchmark_catalog_minutes/models_dev_url合并为openrouter_catalog_minutes(默认 1440、下限 60)。已知取舍:目录从 3536 条缩到 451 条;space-bunny/doubao-seed-2.1-turbo/qwen3.8-max失去刊例价(成本显示 —);family/open_weights/release_date上游不提供(接口保留但恒为null/false,页面不展示)。
修复
- 模型合并:渠道内重名导致国际站被挤出:
/v1/models曾冒出hy4-preview-codebuddy_intl/deepseek-v4.1-flash-codebuddy_intl后缀条目。根因不在国际站,是既有合并逻辑的缺陷——上游把多个模型共用一个展示名是常态(CB 的hy4-preview/hy4-preview-x都叫「Hy4 preview」),一遇渠道内重名就退回渠道限定键,代价是这些模型在本渠道内断了跨渠道合并。改判据为「重名时若本渠道存在某个 id 归一后等于该 label key 的模型,就用这个归一键当合并键」。实测/v1/models从 41 条收敛到 39 条,裸名同时挂两站;-x/-sg变体(真实不同的上游模型)仍各占一条。 - 上下文压缩按实际服务渠道取窗口(Q60 修订):压缩点从 API 层移到 executor 选号后。同名模型跨渠道窗口不同(qoder 180K vs codebuddy 1M),min 口径把大窗口渠道的会话反复误裁,前缀不稳定击穿上游前缀缓存(实测命中率 96%+ 跌到 7–16%)。
- OpenCode Zen 首次请求 503:
403 FreeTierError抖动在客户端内退避重试一次。 - 国际站首条 system 强制:国际站网关要求
messages[0]是 system prompt,否则整单 400 +11128。仅国际站装配时开require_leading_system,国内站出站 body 一个字节不变;判首条在developer→system归一之后,客户端自带 system 时不注入不覆盖。 - 国际站签到与成长中心按渠道关闭:签到是渠道侧就没有该活动(
active: false且活动字段全空),保留只会让后台任务每 10 分钟失败一次并触发噪音告警;成长中心无法验证(整个/v2/activity/*前缀挂在网关认证插件后)且含不可逆动作。活跃上报照常启用——它打的/v2/report与成长中心不是同一路径,实测可用。 - 管理台前端:Playground「当前选择」条渠道多时不再把右侧渠道指定控件挤下去;「请求量趋势」图例移到图表下方(与「按模型趋势」同口径);CodeBuddy 国际版凭证显示「活跃上报」入口(此前前端写死
provider === "codebuddy",后端能跑却看不到出口)。 - 模型列表页:去掉「提供方」列与「模型数」指标卡(前者恒为 id 前缀、信息重复)。
- 页头描述:去掉
max-w-4xl,与下方内容同宽同换行点。 - 默认黑名单:补录三条上游已下架模型(
hy4-preview-x/qwen3.8-flash/glyph-cluster)。
升级
docker compose pull && docker compose up -d无数据库 schema 变更(PRAGMA user_version 仍为 18)。新增渠道需在管理台「添加凭证」里登录 CodeBuddy 国际版账号(或粘贴 JSON);已有的国内站凭证不受影响。镜像:ghcr.io/robbsluo/coding2api:v0.4.2(同时更新 :latest)。
v0.4.1
新增
- 管理台列表排序(Q75):所有列表(凭证 / 用户 / API Key / 审计 / 告警 / 模型目录 / 积分记录 / 账号切换 / 分组统计 / 请求明细)列头可点击排序。默认按请求数或时间降序,点一次用该列「首次点击方向」(数值列先降序、文本列先升序),再点在同一列升降序间切换,当前列以箭头 +
aria-sort标注。排序一律由后端完成,所有GET列表端点统一接受sort(白名单键)+order(asc/desc):未知键或非法方向回落端点默认、不报错,sort是白名单键而非 SQL 列名,注入面为零。 - 按凭证统计维度:分组统计新增「按凭证」,读明细表(
usage_events,覆盖最近 90 天),凭证列显示渠道 icon + 昵称(无昵称回落 ID 前 12 位);凭证昵称来自共享池,仅 admin/operator 可见。
修复
- 模型候选只信模型目录缓存列表(Q74):收窄渠道全不可用时直接 503,不再把请求逐个扇出到未登记该模型的渠道(此前会对 CodeBuddy 写下 6 小时起步的 (凭证, 模型) 负缓存,客户端拿到误导性的 400)。推翻 Q21 旧决策。
- OpenCode Zen 门禁伪工具调用(Q73-adjacent):门禁注入的空壳伪
bash/read命中时,改为改写为客户端同义工具(bash→shell/execute、read→read_file)原样透传,无同义工具才丢弃并记 WARNING;修复「模型老是自动结束回合」。 - Anthropic 出口缓存 token:
/v1/messages流式与非流式补cache_read_input_tokens(此前命中缓存的输入被吞,Claude Code 缓存统计恒 0)。 - Responses
text.format映射:/v1/responses的text.format正确映射到 chatresponse_format(json_schema按官方形状展开),此前整块丢弃导致结构化输出失效。 - 静态资源缓存:
index.html改no-cache每次回源,assets/*改immutable永久缓存——修复「重新构建后浏览器加载旧 bundle」(新前端 + 旧后端的假故障)。
前端与运维
- 模型列表页:客户端分页(20/50/100,默认 50)+ 容器内滚动 + 表头吸顶(3536 条从 7 万 DOM 节点降到千级、搜索按键从约 1s 降到 6–11ms);四项单价合并一列两行,上下文/输出与模态/能力列允许折行。
- 任务与配置页:tab 紧凑模式 + 名称精简,十几个 tab 不再撑爆一行。
scripts/rollup_hourly.py:历史分组数据一次性重算(默认预览、写库前自动备份、幂等)。
升级
docker compose pull && docker compose up -d无数据库 schema 变更(PRAGMA user_version 仍为 18)。镜像:ghcr.io/robbsluo/coding2api:v0.4.1(同时更新 :latest)。
v0.4.0
新增
- 成本估算(Q70):按 models.dev 刊例价 × 热更汇率,为每个渠道 / 请求估算花费(人民币为主、美元为辅,一律前置
≈)。价表后台每日拉取落盘,写入时定值、历史不随价表变化重算;总览加「成本(估算)」卡片,按渠道表、明细表与图表各加成本列 / tab。历史明细可用scripts/backfill_cost.py --apply一次性回填。 - 管理台「模型列表」页(Q71):只读展示 models.dev 目录——名称 / id / 提供方 / 上下文·输出 / 模态 / 能力 / 知识截止 / 发布日期与四项单价,可搜索、可切人民币折算。
- CodeArts 每日签到领 1000 积分(Q72):纯 AK/SK 签名调通上游签到活动(
/v1/ops/delivery|claim|confirm),四态状态机(ELIGIBLE→claim+confirm,CLAIMED→补 confirm,CONFIRMED/CONSUMED→已签)。积分与 token 池并行两套账,前端凭证页放开 CodeArts 签到入口。 - 调度免费优先档:同义模型优先落免费渠道,space-bunny 不再落到付费 CodeBuddy。
- 命名规范表:Qoder DeepSeek-Flash 并入 DeepSeek V4.1 Flash(同模型异名归一)。
- 控制台改版「Control Plane」:导航与页面重构,修复无障碍与对比度;凭证操作结果改为顶部居中浮层提示(toast)。
性能与修复
- 流式 usage 帧:OpenAI 出口收尾补发 usage 帧(客户端 token 统计不再恒 0);上游未报 usage 时不再补发全空
Usage(避免把「未上报」误报成total_tokens: 0)。 - usage 解析:CodeArts / CodeBuddy 补 cached / reasoning details 链,缓存命中率不再恒 0%,思考内容不再被当正文输出。
- CodeArts:凭证生命周期修复(刷新节流 / STS 过期分类 / 一次性票终态 / 到期预警);预刷新窗口须宽于轮询周期,短寿命 token 不再恒标「即将到期」。
- Qoder:签到按活动窗口封账(每日 10:00 刷新)。
- executor:收窄后全不可用时区分成因,模型级冷却不再扇出到整条渠道。
- 安全加固:安全审查 H1-H2 / M1-M7 / L1-L8 全量闭合;两轮全项目评审修复(协议漂移 / OpenAI 数值校验 / 跨 provider 去重 / 文档漂移)。
- 前端:模型行渠道徽章换行后仍贴右,不再挤压模型名。
升级
docker compose pull && docker compose up -d数据库 schema 17 → 18(usage_events / usage_hourly 加成本列),老库启动时自动幂等补列,历史行为 NULL;如需回填历史成本,登录后执行 python scripts/backfill_cost.py --apply。
镜像:ghcr.io/robbsluo/coding2api:v0.4.0(同时更新 :latest)。