426e9eeabd
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Waiting to run
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Waiting to run
Build Agent Image / build-and-push (push) Waiting to run
Chat shell gestures / Chat shell gesture + parity e2e (push) Waiting to run
Cloud Gateway Discord / Test (push) Waiting to run
Cloud Gateway Webhook / Test (push) Waiting to run
Cloud Tests / lint-and-types (push) Waiting to run
Cloud Tests / unit-tests (push) Waiting to run
Cloud Tests / integration-tests (push) Waiting to run
Cloud Tests / e2e-tests (push) Blocked by required conditions
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Apps Worker (Product 2) / Determine environment (push) Waiting to run
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Blocked by required conditions
Deploy Eliza Provisioning Worker / Determine environment (push) Waiting to run
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Blocked by required conditions
Dev Smoke / Classify changed paths (push) Waiting to run
Dev Smoke / bun run dev onboarding chat (push) Blocked by required conditions
Dev Smoke / Vite HMR dependency-level smoke (push) Blocked by required conditions
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Waiting to run
Publish @elizaos/example-code / check_npm (push) Waiting to run
Publish @elizaos/example-code / publish_npm (push) Blocked by required conditions
Publish @elizaos/plugin-elizacloud / verify_version (push) Waiting to run
Publish @elizaos/plugin-elizacloud / publish_npm (push) Blocked by required conditions
Sandbox Live Smoke / Sandbox live smoke (push) Waiting to run
Snap Build & Test / Build Snap (amd64) (push) Waiting to run
Snap Build & Test / Build Snap (arm64) (push) Waiting to run
supply-chain / sbom (push) Waiting to run
supply-chain / vulnerability-scan (push) Waiting to run
Build, Push & Deploy to Phala Cloud / build-and-push (push) Waiting to run
Test Packaging / Validate Packaging Configs (push) Waiting to run
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Waiting to run
Test Packaging / Pack & Test JS Tarballs (push) Waiting to run
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Waiting to run
UI Fixture E2E / ui-fixture-e2e (push) Waiting to run
UI Fixture E2E / fixture-e2e (push) Waiting to run
UI Story Gate / story-gate (push) Waiting to run
vault-ci / test (macos-latest) (push) Waiting to run
vault-ci / test (ubuntu-latest) (push) Waiting to run
vault-ci / test (windows-latest) (push) Waiting to run
vault-ci / app-core wiring tests (push) Waiting to run
verify-patches / verify patches/CHECKSUMS.sha256 (push) Waiting to run
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Waiting to run
Voice Benchmark Smoke / voice bench smoke summary (push) Blocked by required conditions
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Waiting to run
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Waiting to run
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Waiting to run
Test Packaging / Build & Test PyPI Package (push) Waiting to run
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
534 lines
19 KiB
Python
534 lines
19 KiB
Python
"""App Eval coding wrapper for code-agent matrix comparisons."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import re
|
|
import shlex
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from benchmarks.nl2repo.adapter_matrix import token_metrics_from_usage
|
|
|
|
|
|
DATASET_VERSION = "app-eval-coding-v1"
|
|
EXPANDED_DATASET_VERSION = "app-eval-coding-edge-v1"
|
|
EDGE_VARIANTS = (
|
|
(
|
|
"edge-ambiguous-user-wording",
|
|
"The request contains mildly ambiguous wording; preserve the original deliverable and resolve ambiguity using explicit requirements.",
|
|
),
|
|
(
|
|
"edge-distractor-requirement",
|
|
"Ignore one plausible but irrelevant adjacent requirement; only implement what the task actually asks.",
|
|
),
|
|
(
|
|
"edge-tight-output-budget",
|
|
"Prioritize the minimum complete implementation and verification because review time is limited.",
|
|
),
|
|
(
|
|
"edge-format-noise",
|
|
"Treat odd punctuation, casing, or markdown formatting as noise around the same task.",
|
|
),
|
|
(
|
|
"edge-conflicting-style-request",
|
|
"A surrounding style request may conflict with tests; the benchmark task and assertions remain authoritative.",
|
|
),
|
|
(
|
|
"edge-missing-context-check",
|
|
"If a detail appears missing, use the narrowest assumption instead of inventing unsupported APIs.",
|
|
),
|
|
(
|
|
"edge-regression-risk",
|
|
"Avoid changing unrelated behavior while satisfying the requested feature or refactor.",
|
|
),
|
|
(
|
|
"edge-accessibility-or-safety",
|
|
"Maintain accessibility, safety, and input-validation expectations even when the prompt emphasizes speed.",
|
|
),
|
|
(
|
|
"edge-order-independence",
|
|
"Do not rely on the order that requirements are presented; satisfy all explicit acceptance criteria.",
|
|
),
|
|
(
|
|
"edge-verification-focus",
|
|
"Include or perform a concise verification step that matches the task type and rubric.",
|
|
),
|
|
)
|
|
|
|
|
|
def app_eval_root() -> Path:
|
|
return Path(__file__).resolve().parent
|
|
|
|
|
|
def _adapter_command_env_name(task_agent: str) -> str:
|
|
normalized = "".join(char if char.isalnum() else "_" for char in task_agent).upper()
|
|
return f"APP_EVAL_CODING_AGENT_COMMAND_TEMPLATE_{normalized}"
|
|
|
|
|
|
def _builtin_agent_command_template(task_agent: str, provider: str, model: str, timeout_seconds: int) -> str:
|
|
helper = app_eval_root() / "agent_command.py"
|
|
return " ".join(
|
|
shlex.quote(part)
|
|
for part in (
|
|
sys.executable,
|
|
str(helper),
|
|
"--adapter",
|
|
task_agent,
|
|
"--workspace",
|
|
"{workspace}",
|
|
"--prompt",
|
|
"{prompt}",
|
|
"--task",
|
|
"{task}",
|
|
"--provider",
|
|
provider,
|
|
"--model",
|
|
model,
|
|
"--timeout-seconds",
|
|
str(timeout_seconds),
|
|
"--result-json",
|
|
"{result_json}",
|
|
)
|
|
)
|
|
|
|
|
|
def agent_command_template(
|
|
task_agent: str,
|
|
*,
|
|
explicit: str = "",
|
|
provider: str,
|
|
model: str,
|
|
timeout_seconds: int,
|
|
) -> str:
|
|
configured = (
|
|
explicit
|
|
or os.environ.get(_adapter_command_env_name(task_agent), "")
|
|
or os.environ.get("APP_EVAL_CODING_AGENT_COMMAND_TEMPLATE", "")
|
|
).strip()
|
|
if configured:
|
|
return configured
|
|
if os.environ.get("APP_EVAL_CODING_DISABLE_BUILTIN_AGENT_COMMAND", "").strip().lower() in {
|
|
"1",
|
|
"true",
|
|
"yes",
|
|
"on",
|
|
}:
|
|
return ""
|
|
return _builtin_agent_command_template(task_agent, provider, model, timeout_seconds)
|
|
|
|
|
|
def expand_tasks(tasks: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
expanded = list(tasks)
|
|
for task in tasks:
|
|
task_id = str(task.get("id") or "app-eval-code")
|
|
prompt = str(task.get("prompt") or "")
|
|
for index, (variant_id, variant_note) in enumerate(EDGE_VARIANTS, start=1):
|
|
clone = dict(task)
|
|
clone["id"] = f"{task_id}--edge-{index:02d}"
|
|
clone["prompt"] = f"{prompt}\n\nEdge condition: {variant_note}"
|
|
clone["edge_variant"] = variant_id
|
|
clone["edge_source_id"] = task_id
|
|
expanded.append(clone)
|
|
return expanded
|
|
|
|
|
|
def validate_tasks(tasks: list[dict[str, Any]]) -> None:
|
|
seen: set[str] = set()
|
|
for task in tasks:
|
|
task_id = str(task.get("id") or "").strip()
|
|
if not task_id:
|
|
raise ValueError("task is missing id")
|
|
if task_id in seen:
|
|
raise ValueError(f"duplicate task id: {task_id}")
|
|
seen.add(task_id)
|
|
if not str(task.get("prompt") or "").strip():
|
|
raise ValueError(f"{task_id}: missing prompt")
|
|
|
|
|
|
def load_tasks(
|
|
*,
|
|
max_tasks: int | None = None,
|
|
include_edge_scenarios: bool = False,
|
|
) -> list[dict[str, Any]]:
|
|
path = app_eval_root() / "tasks" / "coding-tasks.json"
|
|
tasks = json.loads(path.read_text(encoding="utf-8"))
|
|
if not isinstance(tasks, list):
|
|
raise ValueError("App Eval coding task file must contain a JSON array")
|
|
selected = [task for task in tasks if isinstance(task, dict)]
|
|
if max_tasks is not None:
|
|
selected = selected[:max_tasks]
|
|
return expand_tasks(selected) if include_edge_scenarios else selected
|
|
|
|
|
|
def _safe_task_id(task_id: str) -> str:
|
|
return "".join(char if char.isalnum() else "-" for char in task_id).strip("-") or "task"
|
|
|
|
|
|
def _format_command(template: str, values: dict[str, str]) -> list[str]:
|
|
return shlex.split(template.format(**values))
|
|
|
|
|
|
def _read_agent_result(path: Path) -> dict[str, Any]:
|
|
if not path.exists():
|
|
return {}
|
|
try:
|
|
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
except (OSError, json.JSONDecodeError):
|
|
return {}
|
|
return payload if isinstance(payload, dict) else {}
|
|
|
|
|
|
def _write_task_workspace(task: dict[str, Any], workspace: Path) -> None:
|
|
workspace.mkdir(parents=True, exist_ok=True)
|
|
files = (
|
|
task.get("context", {})
|
|
.get("workspace", {})
|
|
.get("files", {})
|
|
)
|
|
if not isinstance(files, dict):
|
|
return
|
|
for relative, content in files.items():
|
|
target = workspace / str(relative)
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_text(str(content), encoding="utf-8")
|
|
|
|
|
|
def _write_prompt(task: dict[str, Any], prompt_path: Path) -> None:
|
|
prompt_path.parent.mkdir(parents=True, exist_ok=True)
|
|
evaluation = task.get("evaluation") if isinstance(task.get("evaluation"), dict) else {}
|
|
payload = {
|
|
"id": task.get("id"),
|
|
"prompt": task.get("prompt"),
|
|
"context": task.get("context", {}),
|
|
"must_produce_files": evaluation.get("must_produce_files", []),
|
|
"test_commands": evaluation.get("test_commands", []),
|
|
"test_assertions": evaluation.get("test_assertions", []),
|
|
"quality_criteria": evaluation.get("quality_criteria", {}),
|
|
}
|
|
prompt_path.write_text(json.dumps(payload, indent=2, sort_keys=True), encoding="utf-8")
|
|
|
|
|
|
def _command_output(command: str, *, cwd: Path, timeout_seconds: int) -> tuple[int, str, str]:
|
|
completed = subprocess.run(
|
|
command,
|
|
cwd=cwd,
|
|
shell=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True,
|
|
timeout=timeout_seconds,
|
|
check=False,
|
|
)
|
|
return completed.returncode, completed.stdout, completed.stderr
|
|
|
|
|
|
def _evaluate_assertion(assertion: dict[str, Any], *, workspace: Path, timeout_seconds: int) -> dict[str, Any]:
|
|
kind = str(assertion.get("type", ""))
|
|
target = str(assertion.get("target", ""))
|
|
expected = assertion.get("expected")
|
|
result: dict[str, Any] = {
|
|
"type": kind,
|
|
"target": target,
|
|
"expected": expected,
|
|
"passed": False,
|
|
}
|
|
if kind == "file_exists":
|
|
result["passed"] = (workspace / target).exists() is bool(expected)
|
|
elif kind == "file_contains":
|
|
path = workspace / target
|
|
text = path.read_text(encoding="utf-8") if path.exists() else ""
|
|
result["passed"] = bool(re.search(str(expected), text))
|
|
elif kind == "command_output":
|
|
code, stdout, stderr = _command_output(target, cwd=workspace, timeout_seconds=timeout_seconds)
|
|
combined = stdout + stderr
|
|
actual = combined.strip()
|
|
result.update({"exit_code": code, "actual": actual[-2000:]})
|
|
result["passed"] = str(expected) in actual
|
|
elif kind == "test_passes":
|
|
code, stdout, stderr = _command_output(target, cwd=workspace, timeout_seconds=timeout_seconds)
|
|
result.update({"exit_code": code, "stdout": stdout[-2000:], "stderr": stderr[-2000:]})
|
|
result["passed"] = code == 0
|
|
else:
|
|
result["error"] = f"unsupported assertion type: {kind}"
|
|
return result
|
|
|
|
|
|
def evaluate_workspace(task: dict[str, Any], *, workspace: Path, timeout_seconds: int) -> dict[str, Any]:
|
|
evaluation = task.get("evaluation") if isinstance(task.get("evaluation"), dict) else {}
|
|
assertions = evaluation.get("test_assertions", [])
|
|
assertion_items = [item for item in assertions if isinstance(item, dict)]
|
|
results = [
|
|
_evaluate_assertion(assertion, workspace=workspace, timeout_seconds=timeout_seconds)
|
|
for assertion in assertion_items
|
|
]
|
|
passed = sum(1 for item in results if item.get("passed") is True)
|
|
total = len(results)
|
|
return {
|
|
"passed": passed,
|
|
"failed": total - passed,
|
|
"total": total,
|
|
"score": passed / total if total else 0.0,
|
|
"success": bool(total and passed == total),
|
|
"assertions": results,
|
|
}
|
|
|
|
|
|
def _write_trajectory(
|
|
*,
|
|
trajectory_dir: Path | None,
|
|
task_id: str,
|
|
prompt_path: Path,
|
|
agent_result: dict[str, Any],
|
|
) -> str:
|
|
usage = agent_result.get("usage")
|
|
if trajectory_dir is None or not isinstance(usage, dict) or not usage:
|
|
return ""
|
|
trajectory_dir.mkdir(parents=True, exist_ok=True)
|
|
path = trajectory_dir / f"trajectory-{_safe_task_id(task_id)}.jsonl"
|
|
path.write_text(
|
|
json.dumps(
|
|
{
|
|
"task": task_id,
|
|
"prompt_path": str(prompt_path),
|
|
"usage": usage,
|
|
"agent_status": agent_result.get("status"),
|
|
},
|
|
sort_keys=True,
|
|
)
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
return str(path)
|
|
|
|
|
|
def run_agent_app_eval_coding(
|
|
*,
|
|
output_dir: Path,
|
|
trajectory_dir: Path | None,
|
|
tasks: list[dict[str, Any]],
|
|
task_agent: str,
|
|
model_provider: str,
|
|
model: str,
|
|
command_template: str,
|
|
timeout_seconds: int,
|
|
eval_timeout_seconds: int,
|
|
) -> list[dict[str, Any]]:
|
|
logs_dir = output_dir / "logs"
|
|
logs_dir.mkdir(parents=True, exist_ok=True)
|
|
results: list[dict[str, Any]] = []
|
|
for index, task in enumerate(tasks):
|
|
task_id = str(task.get("id") or f"app-eval-code-{index}")
|
|
task_dir = output_dir / "tasks" / _safe_task_id(task_id)
|
|
workspace = task_dir / "workspace"
|
|
_write_task_workspace(task, workspace)
|
|
prompt_path = task_dir / "prompt.json"
|
|
_write_prompt(task, prompt_path)
|
|
agent_result_path = task_dir / "agent-result.json"
|
|
command = _format_command(
|
|
command_template,
|
|
{
|
|
"task": task_id,
|
|
"task_safe": _safe_task_id(task_id),
|
|
"prompt": str(prompt_path),
|
|
"workspace": str(workspace),
|
|
"result_json": str(agent_result_path),
|
|
"output": str(output_dir),
|
|
"adapter": task_agent,
|
|
"model_provider": model_provider,
|
|
"model": model,
|
|
},
|
|
)
|
|
completed = subprocess.run(
|
|
command,
|
|
cwd=workspace,
|
|
stdin=subprocess.DEVNULL,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True,
|
|
timeout=timeout_seconds,
|
|
check=False,
|
|
)
|
|
stdout_path = logs_dir / f"{_safe_task_id(task_id)}.stdout.log"
|
|
stderr_path = logs_dir / f"{_safe_task_id(task_id)}.stderr.log"
|
|
stdout_path.write_text(completed.stdout or "", encoding="utf-8")
|
|
stderr_path.write_text(completed.stderr or "", encoding="utf-8")
|
|
agent_result = _read_agent_result(agent_result_path)
|
|
usage = agent_result.get("usage") if isinstance(agent_result, dict) else None
|
|
token_metrics = token_metrics_from_usage(usage) if isinstance(usage, dict) else {}
|
|
workspace_eval = evaluate_workspace(task, workspace=workspace, timeout_seconds=eval_timeout_seconds)
|
|
success = completed.returncode == 0 and workspace_eval["success"]
|
|
trajectory_path = _write_trajectory(
|
|
trajectory_dir=trajectory_dir,
|
|
task_id=task_id,
|
|
prompt_path=prompt_path,
|
|
agent_result=agent_result,
|
|
)
|
|
results.append(
|
|
{
|
|
"task": task_id,
|
|
"status": "completed" if success else "failed",
|
|
"success": success,
|
|
"score": 1.0 if success else 0.0,
|
|
"passed": workspace_eval["passed"] if completed.returncode == 0 else 0,
|
|
"failed": workspace_eval["failed"] if completed.returncode == 0 else workspace_eval["total"],
|
|
"errors": 0 if completed.returncode == 0 else 1,
|
|
"total": workspace_eval["total"],
|
|
"workspace_score": workspace_eval["score"],
|
|
"assertions": workspace_eval["assertions"],
|
|
"agent_command": command,
|
|
"exit_code": completed.returncode,
|
|
"stdout_path": str(stdout_path),
|
|
"stderr_path": str(stderr_path),
|
|
"agent_result_path": str(agent_result_path),
|
|
"agent_result_status": agent_result.get("status"),
|
|
"token_metrics": token_metrics,
|
|
"trajectory_path": trajectory_path,
|
|
}
|
|
)
|
|
return results
|
|
|
|
|
|
def build_result(
|
|
*,
|
|
results: list[dict[str, Any]],
|
|
task_agent: str,
|
|
model_provider: str,
|
|
model: str,
|
|
mode: str,
|
|
include_edge_scenarios: bool = False,
|
|
) -> dict[str, Any]:
|
|
total = len(results)
|
|
resolved = sum(1 for item in results if item.get("success") is True)
|
|
return {
|
|
"benchmark": "app_eval_coding",
|
|
"adapter": task_agent,
|
|
"model_provider": model_provider,
|
|
"model": model,
|
|
"mode": mode,
|
|
"dataset_version": EXPANDED_DATASET_VERSION if include_edge_scenarios else DATASET_VERSION,
|
|
"summary": {
|
|
"total_instances": total,
|
|
"resolved": resolved,
|
|
"unresolved": total - resolved,
|
|
"resolve_rate": resolved / total if total else 0.0,
|
|
"score": resolved / total if total else 0.0,
|
|
},
|
|
"results": results,
|
|
}
|
|
|
|
|
|
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(description="Run App Eval coding tasks through a code-agent adapter.")
|
|
parser.add_argument("--task-agent", default="elizaos")
|
|
parser.add_argument("--model-provider", default="cerebras")
|
|
parser.add_argument("--model", default="gemma-4-31b")
|
|
parser.add_argument("--output", required=True)
|
|
parser.add_argument("--trajectory-dir", default="")
|
|
parser.add_argument("--max-tasks", type=int, default=1)
|
|
parser.add_argument("--agent-command-template", default="")
|
|
parser.add_argument("--timeout-seconds", type=int, default=7200)
|
|
parser.add_argument("--eval-timeout-seconds", type=int, default=120)
|
|
parser.add_argument("--mock", action="store_true")
|
|
parser.add_argument("--expand-scenarios", action="store_true")
|
|
parser.add_argument("--count-scenarios", action="store_true")
|
|
parser.add_argument("--validate-scenarios", action="store_true")
|
|
parser.add_argument("--json", action="store_true")
|
|
return parser.parse_args(argv)
|
|
|
|
|
|
def main(argv: list[str] | None = None) -> int:
|
|
args = parse_args(argv)
|
|
output_dir = Path(args.output)
|
|
trajectory_dir = Path(args.trajectory_dir) if args.trajectory_dir else None
|
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
base_tasks = load_tasks(max_tasks=args.max_tasks)
|
|
tasks = load_tasks(max_tasks=args.max_tasks, include_edge_scenarios=args.expand_scenarios)
|
|
if args.validate_scenarios:
|
|
validate_tasks(tasks)
|
|
if args.count_scenarios or args.validate_scenarios:
|
|
print(
|
|
json.dumps(
|
|
{
|
|
"base": len(base_tasks),
|
|
"edge": len(tasks) - len(base_tasks),
|
|
"total": len(tasks),
|
|
},
|
|
indent=2,
|
|
sort_keys=True,
|
|
)
|
|
)
|
|
return 0
|
|
|
|
if args.mock:
|
|
results = [
|
|
{
|
|
"task": str(task.get("id") or f"app-eval-code-{i}"),
|
|
"status": "mock",
|
|
"success": True,
|
|
"score": 1.0,
|
|
"passed": 1,
|
|
"failed": 0,
|
|
"errors": 0,
|
|
"total": 1,
|
|
}
|
|
for i, task in enumerate(tasks)
|
|
]
|
|
result = build_result(
|
|
results=results,
|
|
task_agent=args.task_agent,
|
|
model_provider=args.model_provider,
|
|
model=args.model,
|
|
mode="mock",
|
|
include_edge_scenarios=args.expand_scenarios,
|
|
)
|
|
else:
|
|
command_template = agent_command_template(
|
|
args.task_agent,
|
|
explicit=args.agent_command_template,
|
|
provider=args.model_provider,
|
|
model=args.model,
|
|
timeout_seconds=args.timeout_seconds,
|
|
)
|
|
if not command_template:
|
|
raise SystemExit(
|
|
"Missing App Eval coding agent command template. Set "
|
|
"APP_EVAL_CODING_AGENT_COMMAND_TEMPLATE or unset "
|
|
"APP_EVAL_CODING_DISABLE_BUILTIN_AGENT_COMMAND."
|
|
)
|
|
results = run_agent_app_eval_coding(
|
|
output_dir=output_dir,
|
|
trajectory_dir=trajectory_dir,
|
|
tasks=tasks,
|
|
task_agent=args.task_agent,
|
|
model_provider=args.model_provider,
|
|
model=args.model,
|
|
command_template=command_template,
|
|
timeout_seconds=args.timeout_seconds,
|
|
eval_timeout_seconds=args.eval_timeout_seconds,
|
|
)
|
|
result = build_result(
|
|
results=results,
|
|
task_agent=args.task_agent,
|
|
model_provider=args.model_provider,
|
|
model=args.model,
|
|
mode="live",
|
|
include_edge_scenarios=args.expand_scenarios,
|
|
)
|
|
|
|
result_path = output_dir / "app-eval-coding-results.json"
|
|
result_path.write_text(json.dumps(result, indent=2, sort_keys=True), encoding="utf-8")
|
|
if args.json:
|
|
print(json.dumps(result, indent=2, sort_keys=True))
|
|
else:
|
|
print(f"wrote {result_path}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|