Cline 评测框架:面向自主编码 Agent 的三层测试体系与 pass@k 度量实战
【免费下载链接】clineAutonomous coding agent as an SDK, IDE extension, or CLI assistant.项目地址: https://gitcode.com/GitHub_Trending/cl/cline
本篇指南基于仓库中的 evals/README.md 及配套源码,完整拆解 Cline 的分层评测系统:契约测试(无 LLM 调用)、Smoke 测试(真实 LLM 调用的分钟级验证)与 E2E 基准测试(cline-bench 生产级任务),并结合 evals/smoke-tests/run-smoke-tests.ts 与 evals/analysis/src/metrics.ts 的源码实现,讲清楚每一层的运行原理、参数含义与结果度量方式。读完后你可以独立运行各层评测、自定义测试场景,并能用 pass@k / pass^k / Flakiness 指标正确解读一次评测运行的结果。
一、整体架构:测试金字塔与目录结构
Cline 评测框架的定位是"分层度量系统在任意级别上的表现"(A layered testing system for measuring Cline's performance at different levels)。它把一个非确定性的 AI 编码 Agent 的质量问题拆成三个成本递增、保真度递增的层次:
| 层级 | 名称 | 位置 | 成本 | 是否调用 LLM |
|---|---|---|---|---|
| Layer 1 | 契约测试(Contract Tests / Unit) | src/core/api/transform/__tests__/ | 秒级 | 否 |
| Layer 2 | Smoke 测试 | evals/smoke-tests/ | 分钟级 | 是 |
| Layer 3 | E2E 测试(cline-bench) | evals/e2e/ + evals/cline-bench/ | 小时级 | 是 |
evals/ARCHITECTURE.md 中用一张 ASCII 测试金字塔图直观描述了这三层:底层是宽而快的契约测试,中间是 Smoke 测试,顶部是完整的 Agent E2E 任务。
顶层目录结构如下(继承自 evals/README.md):
evals/ ├── smoke-tests/ # Quick provider validation (minutes) │ ├── run-smoke-tests.ts │ └── scenarios/ # 5 curated test scenarios │ ├── e2e/ # Full E2E with cline-bench (hours) │ └── run-cline-bench.ts │ ├── cline-bench/ # Real-world tasks (git submodule) │ └── tasks/ # 12 production bug fixes │ ├── analysis/ # Metrics and reporting framework │ ├── src/ │ │ ├── metrics.ts # pass@k, pass^k calculations │ │ ├── classifier.ts # Failure pattern matching │ │ └── reporters/ # Markdown, JSON output │ └── patterns/ │ └── cline-failures.yaml │ └── baselines/ # Performance baselines for regression detection其中 evals/analysis/ 是贯穿各层的共享度量与报告框架:metrics.ts 负责 pass@k 等指标计算,classifier.ts 基于 cline-failures.yaml 做失败模式匹配,reporters/ 提供 Markdown 与 JSON 两种输出格式,cli.ts 则是对外的分析命令行入口。
重要现状说明(README 原文提示):Smoke 测试(Layer 2)当前处于"部分禁用"状态——评测框架正在切换到新的 SDK CLI。evals/smoke-tests/ 下的场景被完整保留,
npm run eval:smoke:run依然会对$PATH中现有的任意cline可执行文件生效(可通过npm i -g cline安装)。旧的 build-and-link 辅助脚本以及自动运行的cline-evals-regression.ymlCI 工作流已停用,直到有人把构建步骤接到新的 SDK CLI 上。
二、Layer 1:契约测试(无 LLM 调用)
契约测试位于src/core/api/transform/__tests__/,直接测试 API 转换逻辑,不产生任何 LLM 调用,因此快且确定性高。它覆盖三类能力:
- 思维链(Thinking trace)保留:跨 provider 消息转换时 reasoning/thinking 块不丢失;
- 工具调用解析:XML 与原生两种 tool call 格式的解析;
- Provider 格式转换:如 Anthropic
tool_use→ OpenAItool_calls的互转。
运行方式:
npm run test:unit -- --grep "Thinking\|Tool Call"evals/ARCHITECTURE.md 进一步说明了契约测试的来源:旧的evals/benchmarks/tool-precision/目录已被移除,其功能被src/core/**/__tests__/中的契约测试与 52 个 system prompt 快照测试覆盖,并随npm run test:unit一起运行。ARCHITECTURE.md 还列出了代表性用例树,例如thinking-traces.test.ts中的convertToOpenAiMessages preserves reasoning_details、convertToAnthropicMessage preserves thinking blocks,以及tool-parsing.test.ts中的 "Tool call ID truncation (>40 chars)" 等断言。
CI 定位:README 明确指出,当前 PR 门禁(gate)只跑契约测试,因为它零成本、零外部依赖,适合作为每次合并的硬性检查。
三、Layer 2:Smoke 测试——用真实 LLM 调用验证 Provider 链路
3.1 目标与场景清单
Smoke 测试位于 evals/smoke-tests/,目的是用真实 LLM 调用做跨 provider 的快速验证(分钟级),覆盖 3 次/场景的试验以产出 pass@k 指标,实际执行clineCLI 并带上--config、-y、-t、-m参数。
evals/smoke-tests/README.md 说明这些测试专门用于捕获以下类型的回归:
- 工具执行(read、write、edit 文件);
- Provider 响应解析;
- 工具链式调用(一次任务中多次工具操作);
- 基础代码生成。
其场景表如下:
| ID | 名称 | 测试内容 |
|---|---|---|
01-create-file | 创建简单文件 | write_to_file |
02-edit-file | 编辑已有文件 | replace_in_file |
03-read-summarize | 读取并总结 | read_file |
04-multi-file | 创建多个文件 | 多次工具调用 |
05-typescript-function | 生成 TypeScript | 代码生成 |
06-apply-patch | 编辑文件(GPT-5) | apply_patch工具、原生工具调用 |
07-edit-gemini | 编辑文件(Gemini) | Gemini 模型变体 |
从当前仓库的 evals/smoke-tests/scenarios/ 目录看,除上述场景外还存在08-openai-compat-gpt-oss-edit场景目录——README 中"5 curated scenarios"的描述对应的是基础 5 个通用场景,而 06 之后的编号场景用于覆盖特定模型/Provider 的差异化代码路径(如apply_patch仅 GPT-5 系模型走 Responses API 原生工具)。
3.2 前置条件与认证
Smoke 测试要求cline可执行文件在$PATH中可用——Runner 启动时会先执行which cline检查(见下文源码分析),找不到会直接提示"从 npm 安装 cline,或链接apps/cli中的 SDK CLI"并退出。
认证有两种方式(继承自 evals/smoke-tests/README.md):
# 交互式(本地开发推荐) cline auth # 带 API key(自动化场景) cline auth -p cline -k "$CLINE_API_KEY" -m anthropic/claude-sonnet-4.5README 中的最小运行示例:
# Set API key (Cline provider) export CLINE_API_KEY=sk-... # Run smoke tests npm run eval:smoke:run # Run specific scenario npm run eval:smoke:run -- --scenario 01-create-file # Run with specific model (overrides per-scenario models) npm run eval:smoke:run -- --model anthropic/claude-sonnet-4.5eval:smoke:run脚本的定义可以在 apps/vscode/package.json 中找到:"eval:smoke:run": "bun evals/smoke-tests/run-smoke-tests.ts",即直接用 Bun 运行 run-smoke-tests.ts。
3.3 完整参数表
Runner 头部注释声明了支持的全部选项:
| 参数 | 说明 | 默认值 |
|---|---|---|
--trials <n> | 每个测试的试验次数 | 3 |
--scenario <name> | 只运行指定场景 | 全部 |
--model <id> | 覆盖所有场景的模型 | 场景自身models字段或默认模型 |
--output <file> | 将 JSON 结果额外写入指定文件 | 不写 |
--parallel [limit] | 并发运行场景×模型任务,可指定并发上限 | 关闭,上限 4 |
--model会强制覆盖场景的models列表(见--model的注释:"overrides any per-scenario models"),典型用法:
# 用场景默认模型(GPT-5)跑 apply_patch 场景 npm run eval:smoke:run -- --scenario 06-apply-patch # 强制该场景换用指定模型 npm run eval:smoke:run -- --scenario 06-apply-patch --model openai/gpt-4o此外 Runner 支持从仓库根目录的.env/.env.local加载环境变量(loadEnvFiles()读取,且override: false,已存在的环境变量优先)。
3.4 场景定义:config.json 的完整字段
每个场景是evals/smoke-tests/scenarios/<name>/下的一个目录,必须包含config.json,可选包含template/起始文件目录。Runner 中的SmokeScenario接口(run-smoke-tests.ts)定义了对应 schema:
| 字段 | 必填 | 说明 |
|---|---|---|
name | 是 | 人类可读名称 |
description | 是 | 该场景测什么 |
prompt | 是 | 传给 Cline 的任务提示词 |
timeout | 是 | 超时秒数(同时作为 CLI-t参数与进程看门狗) |
expectedFiles | 否 | 任务完成后必须存在的文件列表 |
expectedContent | 否 | 内容断言数组:{ "file": "file1.txt", "contains": "expected text" } |
models | 否 | 场景专属模型列表(如apply_patch场景绑定 GPT-5) |
provider | 否 | Provider 覆盖,默认cline |
requiredEnv | 否 | 该场景运行所需的环境变量名列表,缺失时场景被跳过 |
auth | 否 | Provider 专属认证配置:apiKeyEnv、baseUrlEnv、modelId |
smoke-tests README 给出的最简config.json示例:
{ "name": "Human-readable name", "description": "What this tests", "prompt": "The task prompt for Cline", "expectedFiles": ["file1.txt"], "expectedContent": [ { "file": "file1.txt", "contains": "expected text" } ], "timeout": 60 }3.5 源码剖析:一次 Trial 的完整执行流程
从 run-smoke-tests.ts 的实现看,整个运行流程是"场景 × 模型 × 试验"三层循环:
- 加载与过滤:
loadScenarios()扫描scenarios/下每个目录的config.json;若未指定--scenario,则按requiredEnv过滤,缺失环境变量的场景被记入skippedByEnv并在输出中列出原因。 - 认证保障:
ensureScenarioAuth()对每个(provider, 模型, baseUrl, keyEnv)组合做幂等认证——调用cline auth --config ~/.cline -p <provider> -k <key> -m <modelId>,成功的组合写入configuredAuthCache避免重复执行。使用默认clineprovider 且未显式传 key 时,直接依赖开发者本机~/.cline已有的认证(configuredAuthCache之外的快速路径)。 - 执行 Trial(
runTrial()):- 每个 Trial 有独立工作目录
workspace-trial-N,先清空再重建,保证相互隔离; - 若场景带
template/,用fs.cpSync复制起始文件进工作目录; - 组装 CLI 命令:
cline --config ~/.cline -y -t <timeout> -m <model> <prompt>。其中-y是 YOLO 模式(自动批准所有操作、完成后退出),-t是 CLI 侧超时,-m显式指定模型以保证可复现(源码注释明确写道 "explicit model setting for determinism"); runClineWithTimeout()用spawn拉起子进程并设置看门狗:超时后直接SIGKILL并记录 "Timeout exceeded";非零退出码会被展开为Exit code: N加上 stderr 最后 3 行,方便定位失败原因;- 进程退出码为 0 后,先按
expectedFiles逐一fs.existsSync断言文件存在,再按expectedContent用content.includes(check.contains)断言文件包含期望文本,任一失败即记为 FAIL 并携带具体错误信息。
- 每个 Trial 有独立工作目录
- 日志落盘:每个 Trial 的 stdout/stderr 与状态写入
trial-N.log,格式固定为头部(Trial 编号、Status、Duration、Error)加## STDOUT/## STDERR两段。
3.6 结果输出
每次运行会在 evals/smoke-tests/results/ 下创建带时间戳的目录(形如2026-01-27T19-50-54-391Z),其中包含:
results/ ├── latest -> 2026-01-27T.../ # 指向最近一次运行的符号链接 └── 2026-01-27T19-50-54-391Z/ ├── report.json # 完整结构化结果 ├── summary.md # CI 友好的 Markdown 摘要 └── <scenario-id>/<model-id>/ ├── trial-1.log # 各 Trial 的 CLI stdout/stderr └── workspace-trial-N/ # 各 Trial 的工作目录summary.md由generateSummaryMarkdown()生成,包含总览表(Total / Passed / Failed / Flaky / Overall pass@k)、按场景×模型的结果表,以及仅列出的失败/不稳定 Trial 的错误详情——专为贴进 CI Job Summary 设计。
查看结果的常用命令(来自 ARCHITECTURE.md):
# View latest results cat evals/smoke-tests/results/latest/summary.md # Debug a failure cat evals/smoke-tests/results/latest/<scenario>/<model>/trial-1.log ls evals/smoke-tests/results/latest/<scenario>/<model>/workspace-trial-1/退出码语义:只要report.summary.failed > 0,Runner 就process.exit(1),使该命令可以直接用作 CI 的通过/失败判据。
四、Layer 3:E2E 测试——cline-bench + Harbor 的完整 Agent 评测
E2E 层位于 evals/e2e/,任务集来自 evals/cline-bench/(git 子模块),包含 12 个真实生产级 bug 修复任务,通过 Harbor 框架在 Docker/Daytona 沙箱中执行,定位为 Nightly CI 运行。
运行前提(README 与 run-cline-bench.ts 头部注释一致):Python 3.13(含 uv)、Harbor(uv tool install harbor安装)、Docker(本地执行)或DAYTONA_API_KEY(云执行)。
基本用法:
# Prerequisites: Python 3.13, Harbor, Docker npm run eval:e2e # Specific task npm run eval:e2e -- --tasks discord # Different provider npm run eval:e2e -- --provider openai --model gpt-4o4.1 Runner 参数与 Provider 映射
从 run-cline-bench.ts 的参数解析看,支持的完整选项比 README 示例更细:
| 参数 | 说明 | 默认值 |
|---|---|---|
--env <docker\|daytona> | 执行环境 | docker |
--provider <name> | 模型 Provider | anthropic |
--model <id> | 模型 ID | claude-sonnet-4-20250514 |
--tasks <pattern> | 任务过滤(子串匹配任务目录名) | all |
--trials <n> | 每个任务试验次数 | 1 |
--output <file> | 结果写 JSON 文件 | 不写 |
Provider 到 Harbor 模型前缀的映射在源码中显式定义(PROVIDER_MODEL_PREFIX):anthropic → anthropic、openrouter → openrouter、openai → openai-native、gemini → gemini(注释标明需特殊处理);API key 环境变量映射(PROVIDER_API_KEY_ENV)分别为ANTHROPIC_API_KEY、OPENROUTER_API_KEY、OPENAI_API_KEY、GEMINI_API_KEY,也接受兜底的API_KEY变量。
4.2 任务判定:Harbor 的 reward.txt
Runner 实际执行的 Harbor 命令为:
harbor run -p tasks/<taskId> -a cline-cli -m <provider-prefix>:<model> --env <env>其中-a cline-cli指定被评测的 agent 适配器。每个任务有 30 分钟硬超时(timeout: 30 * 60 * 1000)。任务是否通过不依赖 Harbor 的退出码,而是读取结果文件:Runner 扫描cline-bench/jobs/下最新的 job 目录,在 trial 子目录中查找verifier/reward.txt,当且仅当其内容等于"1"时判定为 PASS——这是典型的 SWE-bench 风格 verifier 判定。若 harbor 进程退出码非 0 或找不到 reward 文件,则记为 FAIL 并附 stderr。
运行前置检查(checkPrerequisites())会依次验证:python3 --version是否 3.13(不匹配仅警告)、which harbor是否存在(缺失则报错并提示uv tool install harbor)、docker info是否可用(不可用则警告建议--env daytona)。若evals/cline-bench子模块未初始化,会明确提示git submodule update --init。
五、指标体系:pass@k、pass^k 与 Flakiness 的精确公式
README 的指标表:
| 指标 | 公式 | 含义 |
|---|---|---|
| pass@k | P(≥1 of k passes) | 解题能力(solution finding capability) |
| pass^k | P(all k pass) | 可靠性(reliability) |
| Flakiness | Entropy of pass rate | 一致性(consistency) |
基于 3 次试验的状态判定:全过 →pass(可靠);全挂 →fail(坏了);混合 →flaky(需要调查)。
metrics.ts 给出了这些指标的无偏估计实现(文件头注释注明方法论参考 HumanEval 论文的 pass@k 估计):
// pass@k = 1 - C(n-c, k) / C(n, k) // 其中 n = 总试验数,c = 通过数,k = 抽样数 passAtK(trials: boolean[], k: number): number { const n = trials.length const c = trials.filter(Boolean).length if (n < k) throw new Error(`Cannot calculate pass@${k} with only ${n} trials`) if (c >= k) return 1.0 return 1 - this.binomial(n - c, k) / this.binomial(n, k) } // pass^k = C(c, k) / C(n, k) passCaretK(trials: boolean[], k: number): number { // ... if (c < k) return 0.0 return this.binomial(c, k) / this.binomial(n, k) } // Flakiness = 二值熵 -p*log2(p) - (1-p)*log2(1-p),p 为通过率 // 全过/全挂 → 0.0;通过率 50% → 1.0(最大方差) flakinessScore(trials: boolean[]): number { /* ... */ }几个值得注意的实现细节:
- 无偏组合估计而非简单频率:3 次试验中 2 次通过,直接说 "pass@3 ≈ 2/3" 会低估真实能力,组合公式
1 - C(1,3)/C(3,3)在 n=c+k 的边界情形会给出更保守或更真实的估计;metrics.ts 的注释例子即"2/3 通过 → pass@3 ≈ 96%"。 binomial()用迭代乘法避免阶乘溢出,并对k > n-k时取小优化;calculateTaskMetrics()对不足 3 次试验自动降级:只有trials.length >= 3才计算 pass@3 / pass^3,否则置 0——这解释了为什么 Runner 的终端输出在trials < 3时只打印pass@1标签("pass@3 is meaningless with fewer trials");getTaskStatus()的状态机极简:passCount === totalCount → "pass",passCount === 0 → "fail",其余 →"flaky",与 README 的三态描述完全对应。
六、失败分类:把 flaky 和 broken 区分开来
evals/analysis/patterns/cline-failures.yaml 定义了一套 Cline 专属的正则失败模式库(version 1.0),供 classifier.ts 对失败日志做模式匹配归因。分类覆盖了 Agent 评测中最常见的几类根因:
| 类别 | 示例模式 | 特征 |
|---|---|---|
provider_bug(Provider 集成缺陷) | gemini_signature:missing.?signature\|thoughtSignature(Gemini 原生工具调用需要 thoughtSignature);claude_tool_format:write_to_file.*missing.*content(Claude 工具参数抽取失败) | 指向具体的 provider 集成 bug |
transient(瞬时、可重试) | rate_limit:429\|rate.?limit\|quota.?exceeded;network_timeout:ECONNREFUSED\|ETIMEDOUT\|ENOTFOUND;model_overloaded:503\|service.?unavailable | 重试即可恢复,不应计入能力回归 |
harness(评测框架自身故障) | verifier.*failed\|missing.*test.*file | 是评测器坏了,不是 Agent 坏了 |
environment(沙箱故障) | docker.*failed\|container.*exit\|OCI.*runtime | Docker/Daytona 环境拉起失败 |
policy(安全策略拒绝) | content.*policy\|safety.*filter | 模型因内容策略拒绝执行 |
auth(认证错误,不可重试) | 401\|unauthorized\|invalid.?api.?key | 凭证问题 |
这套分类的价值在于:当 Nightly E2E 出现失败时,可以先把transient/harness/environment类失败与真实的模型能力回归分开,避免"因为 Docker 没起来而误判模型退化"。配套的分析产物还有 schemas/(harbor-output.ts、analysis-output.ts两个输出结构定义)、parsers/harbor.ts(解析 Harbor 输出)以及 reporters/markdown.ts / reporters/json.ts。指标与分类器的单元测试位于 evals/analysis/src/tests/(metrics.test.ts、classifier.test.ts)。
七、CI 集成现状
README 对 CI 集成给出了三条现状说明(这也是理解当前仓库状态的关键事实):
- 当前 PR 门禁:只跑契约测试(Layer 1);
- Smoke 测试 CI:临时禁用——原
cline-evals-regression.yml工作流在把构建步骤指向新 SDK CLI 之前不会自动运行; - Nightly E2E:尚未实现,见下节 TODO。
evals/ARCHITECTURE.md 补充了 CI 结果的查看方式(Job Summary 贴进 Actions、完整结果以smoke-test-results-<run_id>artifact 下载)以及重新启用 CI 的条件:旧工作流构建的是cli/下的遗留 CLI,只有将其构建步骤替换为apps/cli下的 SDK CLI 后才可以重新启用。
八、快速上手与扩展评测
8.1 Quick Start(继承自 README)
# Run all fast tests npm run test:unit npm run eval:smoke:run # Run E2E (requires setup) cd evals/cline-bench # Follow README.md for Harbor setup npm run eval:e2e8.2 添加新的测试
新增 Smoke 场景(三步):
- 创建
evals/smoke-tests/scenarios/<name>/config.json(字段见 3.4 节); - 可选:添加
template/目录放起始文件; - 运行验证:
npm run eval:smoke:run -- --scenario <name>。
新增契约测试:
- 在
src/core/api/transform/__tests__/下添加用例; - 运行:
npm run test:unit -- --grep "YourTest"。
新增 E2E 任务:按 README 指引,E2E 任务集由 cline-bench 子模块承载,新任务需贡献给该子模块仓库(evals/cline-bench,任务采用 SWE-bench 风格组织)。
8.3 已知 TODO(README 原文)
- Nightly E2E CI:为 cline-bench 测试添加定时工作流。要求:Docker runner、Harbor 配置、约 1–2 小时超时;应按 schedule(如 nightly)而非 per-PR 运行;E2E 环境使用独立 secrets。
- 原生工具调用 Smoke 测试:为 CLI 增加
native_tool_call_enabled设置的支持,以便用原生工具调用测试 Claude 4(当前只有 GPT-5 系列模型经 Responses API 自动使用原生工具)。
九、小结:如何把这套框架用起来
结合源码可以提炼出这套分层体系的工程决策逻辑:
- 契约测试守 PR:零 LLM 成本、确定性断言,验证"provider 消息格式转换不会丢 thinking 块、不会解析错 tool call"这类最底层的不变量;
- Smoke 测试守 provider 链路:用 8 个场景(基础 5 个 + 模型专属 3 个)× 默认 3 次试验,在分钟级内回答"这个 provider/模型今天能不能正常驱动 Cline 的工具执行",并用 pass@3 / pass^3 / flakiness 区分"偶尔失手"与"链路坏了";
- E2E 守真实能力:把 12 个生产级 bug 修复任务放进 Docker/Daytona 沙箱,以 verifier 的
reward.txt == "1"为唯一判据,定位在小时级成本下回答"Cline 作为自主编码 Agent 到底能不能修真实问题"; - 指标与分类兜底:metrics.ts 的组合数无偏估计 + cline-failures.yaml 的六类失败归因,让任何一层的失败结果都能被量化解读、且能区分"模型退步"与"环境抖动"。
需要提醒的适用前提:Layer 2 与 Layer 3 均要求真实 API 凭证与外部可执行环境(clineCLI 在$PATH、Python 3.13 + Harbor + Docker),并且由于评测框架正在向新 SDK CLI 迁移,自动化的 Smoke CI 目前处于停用状态——本地手动运行各层测试不受影响,但不要把"PR 门禁"理解为三层全跑。
相关资源索引:evals/README.md、evals/ARCHITECTURE.md、evals/smoke-tests/README.md、evals/e2e/README.md、evals/package.json。
【免费下载链接】clineAutonomous coding agent as an SDK, IDE extension, or CLI assistant.项目地址: https://gitcode.com/GitHub_Trending/cl/cline
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考