Module Structure
真实 API 层以生产 Agent/协议入口为被测对象,用显式模型×surface 矩阵、宿主可验证副作用和严格资源回收把“模型说完成了”提升为可发布证据。
Directory Layout
packages/cli/tests/integration/real-api/— 真实 Provider 能力、恢复、故障注入和跨表面轨迹packages/cli/tests/support/— Headless、raw PTY、production Web、ACP 驱动及透明代理packages/cli/tests/e2e/— 本地模拟 E2E;不承担付费发布资格packages/cli/scripts/qualification.ts、packages/cli/scripts/qualify.ts— 本地/生产门禁计划与顺序执行packages/cli/scripts/real-api-credentials.ts— 受限凭据文件解析和环境投影packages/cli/scripts/test-config.js—realApi与 38 个发布阻断 trajectory 的显式配置docs/testing/、docs/en/testing/— 双语资格契约和冻结候选证据
Key Entry Points
realApiQualificationinpackages/cli/scripts/test-config.js— 发布阻断文件白名单、90 分钟 watchdog 和 release 环境resolveRequiredDeepSeekQualificationModels()inpackages/cli/tests/integration/real-api/testConfig.ts— 强制解析 Flash/ProbuildRealApiRuntimeConfig()inpackages/cli/tests/integration/real-api/testConfig.ts— 为每个测试渠道生成隔离的生产 Runtime 配置packages/cli/tests/support/setup.real-api.ts— 初始化真实模型并避开普通测试 mockmaterializeRealApiEnvironment()inpackages/cli/scripts/real-api-credentials.ts— 合并显式环境与安全凭据文件startRecordingProviderProxy()inpackages/cli/tests/support/recordingProviderProxy.ts— 记录、阻塞和转发真实 Provider 请求
Branching Table
| 维度 | 分支 A | 分支 B |
|---|---|---|
| 启用状态 | 未设置 REAL_API_TEST=1 时大多数 trajectory 跳过 |
启用后若没有任何可用凭据则 setup/import fail closed |
| 执行集合 | test:real-api 运行完整 soak 集合,watchdog 60 分钟 |
test:real-api:qualification 只运行显式 38 文件白名单,watchdog 90 分钟 |
| 框架重试 | 普通 real-api project 允许一次 Vitest retry | REAL_API_RELEASE_MATRIX=1 时 retry 固定为 0 |
| 必需模型 | 普通 soak 使用当前已配置模型 | 发布资格强制 DeepSeek deepseek-v4-flash 与 deepseek-v4-pro |
| 可选 Provider | 默认排除 domestic 凭据并保留必需渠道 | REAL_API_INCLUDE_OPTIONAL_PROVIDERS=1 才把 domestic 加入付费环境 |
| surface 集合 | 某些高成本轨迹在 release helper 下移除 raw PTY,形成 6 格 | Browser、token-budget、large-prompt 等关键轨迹固定四 surface,形成 8 格 |
| 浏览器状态 | Chromium preflight 失败时顺序门禁立即停止 | preflight 成功后才进入付费 trajectory |
| 凭据来源 | 显式 Provider 环境变量形成调用方选择的渠道集合 | 无显式 key 时可从受限凭据文件或当前 Blade 凭据解析 |
Affected Scope
packages/cli/src/agent/— 真实循环、工具调用、完成策略和恢复行为的被测核心packages/cli/src/context/— durable transcript、compaction、inbox 与重放证据packages/cli/src/commands/— Headless/Print 与生产 CLI 子进程入口packages/cli/src/server/、packages/cli/web/src/— production server、SSE、GUI 与 Chromium 外层驱动packages/cli/src/acp/— 真实 ACP SDK 会话、terminal capability、load/fork/cancelpackages/cli/src/browser/— Agent Browser 与 Web Browser 的独立 Chromium 生命周期packages/cli/tests/integration/real-api/— 每项能力的模型×surface 资格矩阵packages/cli/tests/support/— 跨表面观察、故障代理、PTY marker 和资源回收工具packages/cli/scripts/— 发布白名单、凭据、总 timeout 与生产资格顺序docs/testing/— 对矩阵、宿主断言、禁止替代项和冻结证据的规范
Gotchas
- 普通
test:all不设置REAL_API_TEST,真实 API 文件即使被 Vitest 收集也会跳过;绿色结果不能解释为真实 Provider 已验证 (packages/cli/package.json,packages/cli/tests/integration/real-api/testConfig.ts) REAL_API_TEST=1且没有可用 Provider 凭据会在测试模块初始化阶段抛错,不会悄悄把真实测试降级成 mock (packages/cli/tests/integration/real-api/testConfig.ts,packages/cli/tests/support/setup.real-api.ts)- 发布阻断集合是
test-config.js中的显式文件白名单;新增 trajectory 但未同步白名单和其 source-contract 单测,不会进入 production qualification (packages/cli/scripts/test-config.js,packages/cli/tests/unit/scripts/test-runner.test.ts) - 普通 real-api 允许一次 framework retry,而发布矩阵固定为零;不能用本地重跑后的通过掩盖同一候选中的首次失败 (
packages/cli/vitest.config.ts,docs/testing/qualification.md) releaseBlockingSurfaces()会在 release mode 中移除pty,但少数完整矩阵故意不调用它;修改 surface 集合必须按 trajectory 契约检查 6/8 格断言,不能统一套一个数量 (packages/cli/tests/integration/real-api/testConfig.ts,packages/cli/tests/integration/real-api/foreground-bounded-output-trajectory.test.ts,packages/cli/tests/integration/real-api/browser-tool-trajectory.test.ts,git:6f738811)- 默认凭据文件仅在没有任何显式 Provider key 时自动加载;若环境只设置一个 key 且未显式指定凭据文件,其他默认文件渠道不会被隐式补齐 (
packages/cli/scripts/real-api-credentials.ts,docs/testing/qualification.md) - 凭据文件必须是当前用户拥有的普通文件、Unix mode
0600、不超过 64 KiB,且 URL 禁止非 loopback HTTP、userinfo、query 和 fragment (packages/cli/scripts/real-api-credentials.ts) - PTY 证据必须单调锁存已观察 marker,同时在 resize 后重新观察要求持续可见的事实;只检查最终 bounded tail 会把正确轨迹误判为失败 (
packages/cli/tests/unit/integration/raw-pty-marker-latching.test.ts,git:3775b292,git:2963c0b6)
Architecture
- production qualification 先完整执行 14 个无付费检查,再执行 Chromium preflight,最后运行付费白名单;执行器首错停止并确保 preflight 失败时不会产生 Provider 流量 (
packages/cli/scripts/qualification.ts,packages/cli/tests/unit/scripts/qualification.test.ts) - real-api setup 不加载普通
setup.ts的 I/O mock,而是配置独立存储根、真实模型凭据和生产 Store,使 trajectory 可以穿过真实文件、进程与网络边界 (packages/cli/tests/support/setup.real-api.ts) - 测试 Runtime 使用 qualification ID 派生稳定但不泄密的 model/provider ID,并把自定义渠道 key 放入专属哈希环境槽,避免 Claude/GPT/domestic 共用协议时串 key (
packages/cli/tests/integration/real-api/testConfig.ts) - 透明 Provider proxy 同时记录请求体、开始/结束时间和最大并发,并支持 host barrier;这让 retry、admission、stall 与零额外流量成为宿主事实而非模型文本 (
packages/cli/tests/support/recordingProviderProxy.ts)
Decisions
- 发布最低基线固定要求 DeepSeek Flash/Pro;Claude、GPT 用于特定跨 Provider 契约,domestic 默认只作为显式启用的 soak,通道不稳定不能降低必需模型标准 (
packages/cli/scripts/qualification.ts,docs/testing/qualification.md) - 高价值轨迹要求真实 Read/Edit/Write/Bash、durable event 或协议投影,再由宿主检查文件与测试结果;HTTP 200 或模型自述完成不构成资格证据 (
packages/cli/tests/integration/real-api/release-coding-trajectory.test.ts,packages/cli/tests/integration/real-api/agent-trajectory.test.ts)
Patterns
- 每个矩阵 cell 使用唯一 HOME、storage、workspace、Session ID 和 marker,并在
finally关闭 browser/server/proxy/ACP/PTY 后删除根目录,防止跨 cell 污染 (packages/cli/tests/integration/real-api/browser-tool-trajectory.test.ts) - 发布矩阵测试常先断言模型×surface 的精确 cell 数,再使用
.sequential()执行;这把意外过滤或新增分支变成导入期失败 (packages/cli/tests/integration/real-api/token-budget-handoff-trajectory.test.ts,packages/cli/tests/integration/real-api/browser-tool-trajectory.test.ts) - 失败诊断只保留有界、脱敏的宿主证据,最终还要扫描 transcript、DOM、PTY、ACP update 与代理记录中不存在 API key (
docs/testing/qualification.md,packages/cli/tests/integration/real-api/release-coding-trajectory.test.ts)
Branching Behavior
- 生产资格有显式 DeepSeek key 时默认补齐 Flash/Pro 模型列表;只从
~/.blade/auth.json取得 key 时仅投影REAL_API_TEST=1,模型解析留给 Blade 凭据存储 (packages/cli/scripts/qualification.ts,packages/cli/scripts/qualify.ts) - 非付费检查从子进程环境删除所有 Provider key/base/model、real-API 开关和凭据文件路径;付费检查才得到 materialized 环境 (
packages/cli/scripts/qualification.ts) - 自定义 Claude/GPT/domestic 渠道规范化为
/v1endpoint 并使用独立 provider 配置,DeepSeek 则沿用内置 provider 与模型级凭据槽 (packages/cli/tests/integration/real-api/testConfig.ts) - 发布模式下 surface 缩减是逐 trajectory 决策;固定 8 格的 Browser/大型 Prompt/Token handoff 测试由单测扫描源码防止误接
releaseBlockingSurfaces()(packages/cli/tests/unit/scripts/test-runner.test.ts) - Chromium 缺失或 sandbox 不可用时应在 browser preflight 失败,而不是由真实 Provider cell 边跑边下载或在付费请求后才失败 (
packages/cli/scripts/browser-check.ts,packages/cli/scripts/qualification.ts)