Files
metapi/docs/change-log.md
lengxiaouserandcita-777 a539f04645 feat: add proxy fixes and per-site concurrency
* feat: add proxy fixes and per-site concurrency

* docs: record branch push permission result

* docs: record fork preparation

* docs: record pull request link

* fix: address CodeRabbit proxy review findings

* test: update shared surface endpoint mocks

* docs: correct review validation count

* fix: preserve explicit route channel priorities

* fix: honor explicit channel priorities

* fix: honor priorities regardless of channel mode

* docs: record CodeRabbit follow-up validation

* docs: record route rebuild validation

* test: cover Gemini site endpoint concurrency

* fix: preserve versioned endpoint path handling

* chore: include merged site columns in schema snapshot

---------

Co-authored-by: cita-777 <juricek.chen@gmail.com>
2026-08-30 17:33:38 +08:00

16 KiB
Raw Permalink Blame History

Metapi 变更日志

这是当前项目的持续变更记录。后续每次新增功能、修复缺陷、调整接口或修改文档,都要在本文件追加一条记录,不能只修改代码而不记录。

记录规则

  • 每条记录使用日期、变更类型、需求来源、Issue 链接、实现范围、验证结果和交付物几个字段。
  • 有 GitHub Issue 时必须附上完整链接;没有 Issue 时标记为“本会话需求”,不要虚构编号。
  • 代码完成后再补充实际文件路径和测试结果,未验证的内容必须明确标记为“未验证”。
  • 采用追加方式维护历史记录,不覆盖已完成记录;如果后续修复同一问题,新增一条记录并链接到原记录。
  • PDF、截图、需求说明等交付物也要记录,但不能把交付物当成代码实现本身。

2026-08-03

1. 每个站点独立最大并发

  • 类型:功能实现
  • 需求来源:本会话需求,未提供 GitHub Issue 链接
  • 目标:允许每个站点单独设置最大并发;0 表示不限制;不同站点的请求不能共享同一个并发计数器。
  • 实现范围:
    • 数据库 sites.max_concurrency 字段,默认值为 0,同步更新 schema contract 和各数据库启动产物。
    • 站点创建、更新 API 支持 maxConcurrency,接受 0-100000 的整数,并拒绝越界或非整数值。
    • 站点管理页面增加最大并发输入框和表格列,保存后可以看到每个站点自己的限制值。
    • 代理请求通过站点级 lease/队列控制并发;达到上限时只等待当前站点,不阻塞其他站点。
  • 主要文件:
    • src/server/db/schema.ts
    • src/server/routes/api/sites.ts
    • src/server/services/proxyChannelCoordinator.ts
    • src/server/services/siteApiEndpointService.ts
    • src/server/proxy-core/surfaces/sharedSurface.ts
    • src/server/proxy-core/surfaces/geminiSurface.ts
    • src/web/pages/Sites.tsx
    • src/web/pages/helpers/sitesEditor.ts
  • 验证:
    • src/server/routes/api/sites.api-endpoints.test.ts 覆盖创建、更新和越界校验。
    • src/server/services/proxyChannelCoordinator.test.ts 覆盖同站点排队、不同站点隔离和 0 不限流。
    • 本地页面实际显示 concurrency-site 的最大并发为 1,其他站点显示“不限制”。
  • 状态:已完成并在当前本地服务中运行。

2. Rerank 代理接口

  • 类型:功能实现
  • 需求来源:GitHub Issue #591
  • 目标:新增 POST /v1/rerank,复用现有的鉴权、模型路由、站点 API 地址池、重试、用量解析、计费和代理日志链路。
  • 实现范围:
    • 增加 Rerank 路由,校验 model,将请求转发到选中的上游 /v1/rerank。
    • 支持站点 API 地址池、首字节超时、通道重试和失败切换。
    • 成功路径解析用量并记录计费;失败路径只记录通道失败和代理失败日志,不虚构用量或费用。
    • 路由已在 proxy router 中注册。
  • 主要文件:
    • src/server/routes/proxy/rerank.ts
    • src/server/routes/proxy/rerank.test.ts
    • src/server/routes/proxy/router.ts
  • 验证:
    • 缺少 model 返回 HTTP 400。
    • 未携带下游鉴权调用实际本地接口返回 HTTP 401,鉴权边界生效。
    • Rerank 路由单元测试覆盖上游 URL、请求体转发和成功日志。
  • 状态:已完成。要得到真实排序结果,还需要在本地配置支持 Rerank 的上游站点和下游 API Key。

3. 路由优先级与 P0/P1/P2

  • 类型:缺陷修复
  • 需求来源:GitHub Issue #590
  • 目标:新建通道进入当前路由的下一优先级;拖拽或批量更新后优先级保持连续并和页面展示一致。
  • 实现范围:
    • 创建通道时按当前路由已有最大优先级计算默认值,不再把所有新通道固定为 P0。
    • 批量保存时按路由压缩为连续的 P0、P1、P2 等层级。
    • 返回通道列表时按 priority、id 排序,确保 API 和页面顺序一致。
    • 保留优先级拖拽后的保存和路由决策刷新行为。
  • 主要文件:
    • src/server/routes/api/tokens.ts
    • src/web/pages/TokenRoutes.tsx
    • src/web/pages/token-routes/priorityRail.ts
    • src/web/pages/token-routes/RouteCard.tsx
  • 验证:
    • 前端优先级 helper 和拖拽相关测试通过。
    • 本地路由页面实际展开 deepseek-v4-pro,通道显示在 P0 优先级桶中。
    • API 返回顺序使用 priority、id 排序。
  • 状态:已完成并在当前本地服务中运行。

4. Coding Plan v3 URL 拼接

  • 类型:缺陷修复
  • 需求来源:GitHub Issue #586
  • 目标:当上游 Base URL 已经以 /v3 等版本段结尾时,不要把下游请求的 /v1 重复拼接到 URL 中。
  • 实现范围:
    • URL 拼接逻辑识别末尾 /vN 版本段。
    • .../api/coding/v3 加 /v1/chat/completions 后得到 .../api/coding/v3/chat/completions。
    • 保持已有 /v1、无版本后缀和其他平台路径行为不回归。
  • 主要文件:
    • src/server/proxy-core/orchestration/upstreamRequest.ts
  • 验证:
    • Coding Plan v3 URL 拼接单元测试覆盖 v3、v1、无版本后缀和现有特殊路径。
    • Rerank 测试中的 Coding Plan v3 上游地址实际拼接为 https://ark.cn-beijing.volces.com/api/coding/v3/rerank。
  • 状态:已完成。

5. 渠道失败隔离

  • 类型:缺陷修复
  • 需求来源:GitHub Issue #585
  • 目标:一个渠道失败时,只更新实际失败渠道的冷却和失败状态,不影响同凭据的其他渠道,也不误触发站点级运行时熔断。
  • 实现范围:
    • 429 用量限流只冷却本次实际失败的 channel。
    • 不再按同一凭据扩散 cooldownUntil 或失败状态。
    • 429 不再写入站点级运行时熔断;其他健康渠道仍可参与选择。
    • 成功恢复时只清理当前通道自身的失败状态。
  • 主要文件:
    • src/server/services/tokenRouter.ts
    • 相关 token router、proxy retry 和路由健康状态测试文件
  • 验证:
    • 单线程 Vitest 覆盖限流失败、普通失败、成功恢复和站点熔断边界。
    • 验证结论:失败通道进入冷却,同凭据其他通道不扩散,429 不写入站点级熔断。
  • 状态:已完成。

6. 需求文档和演示交付物

  • 类型:文档与交付物
  • 需求来源:本会话中提供的四个 GitHub Issue
  • 实现范围:
    • 需求说明:docs/plans/github-issues-591-590-586-585.md
    • 网页演示 PDF:output/pdf/metapi-issues-demo-2026-08-03.pdf
    • PDF 包含当前 run 页面截图、站点独立并发、路由 P0、Rerank 请求示例、Coding Plan v3 和渠道失败隔离说明。
  • 验证:
    • 前端 http://127.0.0.1:5174/ 返回 HTTP 200。
    • 后端 http://127.0.0.1:4000/health 返回 HTTP 200。
    • PDF 已渲染检查,共 6 页,中文正文和接口示例可读。
  • 状态:已完成。

7. 汇总验证

  • npm run typecheck:server:通过
  • npm run typecheck:web:通过
  • npm run typecheck:web:test:通过
  • npm run test:schema:unit:通过
  • npm run repo:drift-check:通过
  • 相关 Rerank、endpoint flow、路由优先级、tokenRouter、站点并发测试:使用单线程 Vitest 通过
  • 说明:本机并行 Vitest worker 曾出现 OOM/UNKNOWN,后续复测优先使用:
npx vitest run --pool=threads --poolOptions.threads.singleThread=true <test-file>

8. 建立持续变更日志

  • 类型:文档维护
  • 需求来源:本会话需求
  • 目标:把功能、修复、测试和交付物集中记录,作为后续改动的唯一开发日志。
  • 实现范围:新增本文件 docs/change-log.md,并提供 Issue 链接、文件路径、验证结果和后续追加模板。
  • 状态:已完成;后续每次代码或文档变更都追加到本文件。

2026-08-21

9. 提交到上游仓库的独立分支

  • 类型:版本交付
  • 需求来源:本会话需求:Metapi 仓库
  • 目标:将本地已完成的站点独立并发、Rerank 和四个 Issue 修复提交到上游仓库的独立分支,不直接修改 main。
  • 实现范围:以远程 main 为基线创建 codex/metapi-issues-591-590-586-585,迁移代码、测试、数据库迁移产物、需求文档、持续日志和演示 PDF。
  • 主要文件:
    • src/server/routes/proxy/rerank.ts
    • src/server/services/proxyChannelCoordinator.ts
    • src/server/services/tokenRouter.ts
    • src/server/db/schema.ts
    • docs/change-log.md
  • 验证:npm run typecheck:server、npm run typecheck:web、npm run typecheck:web:test、npm run test:schema:unit、npm run repo:drift-check 均通过;相关聚焦测试通过,tokenRouter.selection.test.ts 单独运行 26/26 通过。
  • 提交:本地提交 02e2308(feat: add proxy fixes and per-site concurrency)。
  • 推送结果:未推送;GitHub 返回 403 Permission to cita-777/metapi.git denied to lengxiaouser,当前凭据对该仓库没有写权限;远程分支尚未创建。
  • 状态:代码已验证并在本地分支就绪,等待具备该仓库写权限的凭据后重试。

10. 创建 Fork 并准备 Pull Request

  • 类型:版本交付
  • 需求来源:本会话需求
  • 目标:通过个人 Fork 提交变更,避免直接写入上游仓库。
  • 实现范围:已创建 lengxiaouser/metapi Fork,目标分支为 codex/metapi-issues-591-590-586-585,PR 基线为上游 main。
  • 验证:Fork 的 main 已通过 Git 远程读取确认,功能分支已成功推送。
  • 状态:已完成。

11. 创建上游 Pull Request

  • 类型:版本交付
  • 需求来源:本会话需求
  • 目标:请求上游仓库审核本次站点并发控制、Rerank 及四个 Issue 修复。
  • 实现范围:创建 PR #609,源分支为 lengxiaouser:codex/metapi-issues-591-590-586-585,目标为 cita-777:main。
  • 验证:GitHub API 返回 PR 编号 609,状态为 open;PR 描述已包含 Issue 链接、验证命令和变更范围。
  • 状态:已提交,等待上游审核。

2026-08-22

12. 修复 CodeRabbit PR 审查问题

  • 类型:缺陷修复与架构重构
  • 需求来源:CodeRabbit 对 PR #609 的审查;对应 Issue:#591、#590、#586、#585
  • 目标:修复站点并发租约释放、并发超时误判、路由通道优先级竞态、Rerank 路由职责过重和变更日志字段不完整等问题。
  • 实现范围:
    • 流式响应交接后暂停后台续租,按真实读取进度续租;读取失败先取消 reader,再释放站点租约。
    • 为本地站点排队超时增加显式 siteConcurrencyTimeout 标记,统一由 sharedSurface.ts 分类,避免把真实上游 503 当成站点排队超时。
    • 新增 routeChannelService.ts,用进程内串行锁和数据库事务统一处理自动通道、批量通道、单通道和批量优先级写入,并统一清理路由决策缓存。
    • 新增 rerankSurface.ts,通过 executeEndpointFlow() 承担 Rerank 的站点地址池、首字节超时、上游请求、用量计费、日志和失败重试;路由文件只保留校验与委托。
    • 修正 Rerank 记录:只有成功响应解析用量并计费,失败只写失败状态日志,费用和用量为零/未知不代表已发生计费。
  • 主要文件:
    • src/server/services/proxyChannelCoordinator.ts
    • src/server/services/siteApiEndpointService.ts
    • src/server/proxy-core/surfaces/sharedSurface.ts
    • src/server/proxy-core/surfaces/chatSurface.ts
    • src/server/proxy-core/surfaces/openAiResponsesSurface.ts
    • src/server/proxy-core/surfaces/geminiSurface.ts
    • src/server/proxy-core/surfaces/rerankSurface.ts
    • src/server/routes/proxy/rerank.ts
    • src/server/services/routeChannelService.ts
    • src/server/routes/api/tokens.ts
    • docs/change-log.md
  • 验证:
    • npm run typecheck:server:通过。
    • npx vitest run --pool=threads --poolOptions.threads.singleThread=true src/server/routes/proxy/rerank.test.ts src/server/services/siteApiEndpointService.test.ts src/server/services/proxyChannelCoordinator.test.ts:通过,24 个测试通过。
    • 路由优先级与共享 surface 回归测试:通过,tokens.batch.test.ts、tokens.route-update-rebuild.test.ts 共 21 个测试,sharedSurface.test.ts 与 sharedSurface.usage-source.test.ts 共 24 个测试。
    • Rerank 测试实际验证上游 URL 为 https://ark.cn-beijing.volces.com/api/coding/v3/rerank、请求体转发和成功日志;测试环境的 quota best-effort 查询因未创建 accounts 表输出告警,但不影响请求结果。
    • npm run typecheck:web:通过。
    • npm run typecheck:web:test:通过。
    • npm run test:schema:unit:通过,15 个测试通过。
    • npm run repo:drift-check:通过,新增违规 0 个;报告中的 5 项为既有 tracked debt。
  • 交付物:本地 checkout 中的修复代码和本变更日志;无新增 PDF 或截图。
  • 状态:已完成,等待提交并更新 PR。

13. 修复 CodeRabbit follow-up 审查问题

  • 类型:缺陷修复与文档修正
  • 需求来源:CodeRabbit 对 PR #609 的 follow-up 审查
  • 目标:修复 Issue 链接的 Markdown 空格,并确保手工通道传入的明确优先级不会被自动分配逻辑覆盖。
  • 实现范围:
    • 将 [ #591] 修正为 [#591],并确认 PR/Issue 链接均为合法 Markdown。
    • routeChannelService 区分明确优先级和自动候选:手工通道传入 priority: 0、priority: 3 等值时原样归一化保留;自动候选才分配下一个优先级。
    • 自动补齐候选不再把 priority: 0 当成显式优先级,避免所有自动通道固定在 P0。
  • 主要文件:
    • src/server/services/routeChannelService.ts
    • src/server/routes/api/tokens.ts
    • docs/change-log.md
  • 验证:
    • npm run typecheck:server:通过。
    • npx vitest run --pool=threads --poolOptions.threads.singleThread=true --hookTimeout=30000 src/server/routes/api/tokens.batch.test.ts:6 个测试通过。
    • npx vitest run --pool=threads --poolOptions.threads.singleThread=true --hookTimeout=30000 src/server/routes/api/tokens.route-update-rebuild.test.ts:15 个测试通过。
  • 交付物:代码与持续变更日志;无新增 PDF 或截图。
  • 状态:已完成,已推送到 PR 分支;本次日志修正随当前文档提交同步。

后续记录模板

复制下面模板追加到对应日期下,先记录需求来源,再补充实际实现和验证结果:

### YYYY-MM-DD - 简短标题

- **类型**:功能实现 / 缺陷修复 / 重构 / 文档
- **需求来源**:[Issue #N](https://github.com/cita-777/metapi/issues/N) 或本会话需求
- **目标**:
- **实现范围**:
- **主要文件**:
  - `path/to/file`
- **验证**:
- **交付物**:代码、文档、PDF、截图等;没有交付物时填写“无”。
- **状态**:进行中 / 已完成 / 阻塞