Skip to content

docs(architecture): 整体架构总览 + 请求生命周期(#167 Phase 2 第三批)#180

Merged
g1331 merged 3 commits into
masterfrom
docs/phase2-architecture-batch
May 23, 2026
Merged

docs(architecture): 整体架构总览 + 请求生命周期(#167 Phase 2 第三批)#180
g1331 merged 3 commits into
masterfrom
docs/phase2-architecture-batch

Conversation

@g1331
Copy link
Copy Markdown
Owner

@g1331 g1331 commented May 23, 2026

Summary

完成 issue #167 Phase 2 第一批最后两篇架构文档:

  • docs/guide/architecture/overview.md 整体架构总览:单进程拓扑示意、目录分层、src/lib/services/ 服务模块按 9 个职责域归类、20 张数据库表汇总、对外入口边界、i18n 路由结构、关键依赖版本、Docker 与 GitHub Actions 入口
  • docs/guide/architecture/request-lifecycle.md 请求生命周期:把 POST /api/proxy/v1/chat/completions 拆为 7 个阶段(HTTP 分发 / CORS / 鉴权 / 路由能力解析 / 候选过滤与选路 / 转发与流式 / 日志计费响应),每一阶段挂上 src/...:line 引用

同时修订 docs/guide/usage/invoke-models.md 一处事实错误:

  • 旧文档声称代理层「追加 AutoRouter 自身的请求 ID 与命中上游 ID」响应头
  • 实际 src/app/api/proxy/v1/[...path]/route.ts:3192 之后未注入任何 X-AutoRouter-* 自定义头,仅 SSE 时强制写入 Content-Type / Cache-Control / Connection 三个标准头
  • 修正为:请求 ID 与命中上游 ID 只通过管理后台「请求日志」回查

事实校验

两篇正文里出现的所有 src/...:line 引用、函数名、RouteCapability 枚举、表名、依赖版本均由 Explore 子代理直接读源码采证。wrapStreamWithConnectionTracking 行号、handleProxy 入口、failoverHistory 写入点、shouldRecordFixture 决策点、requestBillingSnapshots upsert 等关键事实均与 master 当前代码一致。

Phase 2 进度

类别 已合入
部署侧 4 / 4(PR #177 + PR #179
使用侧 4 / 4(PR #178
架构侧 0 / 2(本 PR)

本 PR 合入后,issue #167 Phase 2 第一批 10 篇全部到位。

Test plan

  • pnpm docs:build 通过(无新增警告,既有 vueuse #__PURE__env 高亮回退 warning 已在以前的批次中存在)
  • pnpm format:check 通过
  • pre-commit 钩子通过(prettier / large file / EOF / trailing whitespace)
  • Docs CI(PR workflow)
  • 人工 review 两篇正文的事实准确性

按既定规则:CI 通过即停,不自合并,等 review。

完成 issue #167 Phase 2 第一批最后两篇:

- `docs/guide/architecture/overview.md` 整体架构总览:进程拓扑、目录分层、`src/lib/services/` 服务模块清单(按 9 个职责域归类)、20 张数据库表汇总、对外入口边界、i18n 路由结构、关键依赖版本、Docker 与 GHA 入口
- `docs/guide/architecture/request-lifecycle.md` 请求生命周期:把 `POST /api/proxy/v1/chat/completions` 的内部流程拆为 7 个阶段(HTTP 分发 / CORS / 鉴权 / 路由能力解析 / 候选过滤与选路 / 转发与流式 / 日志计费响应),每个阶段挂上 `src/...:line` 引用

同时修订 `docs/guide/usage/invoke-models.md` 中一处事实错误:
- 旧文档声称代理层「追加 AutoRouter 自身的请求 ID 与命中上游 ID」响应头;实际 `route.ts:3192` 之后未注入任何 `X-AutoRouter-*` 自定义头,仅 SSE 时强制写入 `Content-Type` / `Cache-Control` / `Connection`。请求 ID 与命中上游 ID 只通过管理后台「请求日志」回查
@codecov
Copy link
Copy Markdown

codecov Bot commented May 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.13%. Comparing base (496febe) to head (0c284d7).
⚠️ Report is 4 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #180   +/-   ##
=======================================
  Coverage   74.13%   74.13%           
=======================================
  Files         145      145           
  Lines       11043    11043           
  Branches     3832     3832           
=======================================
  Hits         8187     8187           
  Misses       1657     1657           
  Partials     1199     1199           
Flag Coverage Δ
verify 74.13% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

g1331 added 2 commits May 23, 2026 19:52
按 review 反馈逐条核对源码并修正:

- [P2] request-lifecycle.md 阶段二「CORS 与 OPTIONS」:
  grep `Access-Control-Allow` 全仓无匹配,`corsOrigins` 字段只在
  `src/lib/utils/config.ts` 被读,没有任何代码读取后输出 CORS 响应头。
  把「需要把对应 origin 加入 CORS_ORIGINS」的旧描述修订为
  「CORS_ORIGINS 在当前实现中没有运行期效果,浏览器侧直连需要前置反向代理」。
  overview.md `CORS_ORIGINS` 字段说明与时序总览同步修订。

- [P2] invoke-models.md「响应行为:透传 + 改写」与 request-lifecycle.md 阶段七:
  代理层并非 1:1 复制上游 header。`proxy-client.ts:216` 的 filterHeaders
  会去 hop-by-hop header,`proxy-client.ts:1157-1159` 在 undici 已解压响应体时
  额外删除 `content-encoding` 与 `content-length`。修订两处文档统一口径。

- [P3] request-lifecycle.md 阶段四「模型提取」结尾:
  `filterCandidatesByModelRules`(`route.ts:591-600`)在 originalModel 为 null
  时返回全部候选,请求会被转发到上游而非本地被拒绝。把「模型名缺失或无法解析
  直接返回 400」修订为说明 model 为 null 时仍会进入选路、400 来自上游。

- [P3] overview.md 首段持久化范围:
  `recordTrafficFixture`(`traffic-recorder.ts:517`、`:529-530`)把 fixture JSON
  写到磁盘(默认 `data/traffic-recordings`,可由 `RECORDER_FIXTURES_DIR` 覆盖);
  数据库 `trafficRecordings` 表仅保存 `fixture_path` 等索引。修订首段说明
  录制功能的持久化分两处,并提醒备份规划要同时覆盖数据库与该磁盘目录。

env-reference.md:80 中 `CORS_ORIGINS` 的描述与同类问题为先前文档遗留,不在
本 PR 范围内,留待后续单独修订。
- [P2] request-lifecycle.md 阶段六「失败转移」 + invoke-models.md「failover
  对调用方无感」:
  原文笼统说「转发或流读取过程中重新选下一条候选」与「failover 对调用方
  无感」,与流式实现不符。`forwardWithFailover`(`route.ts:1289`)一旦
  `result.isStream === true` 就直接 `return` 包装好的流(`route.ts:1651`),
  中途读流失败由 `wrapStreamWithConnectionTracking` 的回调(`route.ts:1618-1649`)
  交给 `settleStreamRuntimeFailureForCircuitBreaker` 处理——只记录日志与
  熔断失败,不会回到选路阶段。修订两处文档显式区分「首字节前的失败(可重试)」
  与「流开始后的中断(不可重试)」,并说明调用方需要自行处理「上游 stream
  中断」错误。

- [P3] invoke-models.md「响应行为」与 request-lifecycle.md 阶段七的响应
  header 描述:
  上一轮修订错把响应头过滤指到 `proxy-client.ts:216` / `:995` 的 filterHeaders。
  实际上那里处理的是请求侧 inbound header;响应头由 `proxy-client.ts:1147-1153`
  的 inline 循环按 `HOP_BY_HOP_HEADERS` 过滤。修订两处文档指向正确代码位置,
  并显式标注「与请求侧 filterHeaders 不是同一段代码」避免读者再混淆。
@g1331 g1331 merged commit b31124f into master May 23, 2026
14 checks passed
@g1331 g1331 deleted the docs/phase2-architecture-batch branch May 23, 2026 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant