426e9eeabd
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
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
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) Has been cancelled
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) Has been cancelled
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) Has been cancelled
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) Has been cancelled
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) Has been cancelled
211 lines
6.9 KiB
Python
211 lines
6.9 KiB
Python
"""
|
|
Coding task evaluator for elizaOS app benchmarks.
|
|
|
|
Scores coding task results based on code presence, keyword coverage,
|
|
TypeScript patterns, and structural quality. Deterministic — no LLM calls.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import Any
|
|
|
|
|
|
def evaluate_coding_task(
|
|
task: dict[str, Any],
|
|
result: dict[str, Any],
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Evaluate a single coding task result.
|
|
|
|
Args:
|
|
task: Task definition with expected_keywords, evaluation criteria, etc.
|
|
result: Benchmark result with response, success, duration_ms, etc.
|
|
|
|
Returns:
|
|
Evaluation dict with score, breakdown, and feedback.
|
|
"""
|
|
max_score = task.get("max_score", 10)
|
|
response = result.get("response", "")
|
|
|
|
if not result.get("success") or not response:
|
|
return {
|
|
"task_id": task["id"],
|
|
"score": 0,
|
|
"max_score": max_score,
|
|
"pass": False,
|
|
"breakdown": {},
|
|
"feedback": result.get("error", "Task did not complete successfully"),
|
|
}
|
|
|
|
breakdown: dict[str, float] = {}
|
|
feedback_parts: list[str] = []
|
|
response_lower = response.lower()
|
|
|
|
# --- Code presence (0-1) ---
|
|
code_blocks = re.findall(r"```[\s\S]*?```", response)
|
|
inline_code = re.findall(r"`[^`]+`", response)
|
|
|
|
# Also detect unformatted code patterns
|
|
has_function_def = bool(re.search(
|
|
r"\b(function|const|let|var|class|interface|type|export|import|async)\b",
|
|
response,
|
|
))
|
|
has_braces = "{" in response and "}" in response
|
|
has_arrow = "=>" in response
|
|
|
|
if code_blocks:
|
|
code_presence = 1.0
|
|
elif has_function_def and has_braces:
|
|
code_presence = 0.8
|
|
elif has_function_def or inline_code:
|
|
code_presence = 0.5
|
|
else:
|
|
code_presence = 0.1
|
|
feedback_parts.append("No code found in response")
|
|
|
|
breakdown["code_presence"] = round(code_presence, 3)
|
|
|
|
# --- Extract code content for deeper analysis ---
|
|
code_content = ""
|
|
if code_blocks:
|
|
code_content = "\n".join(
|
|
re.sub(r"^```\w*\n?|```$", "", block, flags=re.MULTILINE)
|
|
for block in code_blocks
|
|
)
|
|
else:
|
|
code_content = response
|
|
|
|
code_lower = code_content.lower()
|
|
|
|
# --- Keyword coverage (0-1) ---
|
|
expected_keywords = task.get("expected_keywords", [])
|
|
if expected_keywords:
|
|
matched = [kw for kw in expected_keywords if kw.lower() in response_lower]
|
|
missing = [kw for kw in expected_keywords if kw.lower() not in response_lower]
|
|
keyword_score = len(matched) / len(expected_keywords)
|
|
breakdown["keyword_coverage"] = round(keyword_score, 3)
|
|
if missing:
|
|
feedback_parts.append(f"Missing keywords: {', '.join(missing)}")
|
|
else:
|
|
keyword_score = 0.5
|
|
breakdown["keyword_coverage"] = 0.5
|
|
|
|
# --- TypeScript quality signals (0-1) ---
|
|
ts_signals = 0
|
|
ts_max = 8
|
|
|
|
# Type annotations
|
|
if re.search(r":\s*(string|number|boolean|void|any|unknown|never)\b", code_content):
|
|
ts_signals += 1
|
|
# Generics
|
|
if re.search(r"<\s*\w+", code_content):
|
|
ts_signals += 1
|
|
# Interface or type alias
|
|
if re.search(r"\b(interface|type)\s+\w+", code_content):
|
|
ts_signals += 1
|
|
# Arrow functions
|
|
if "=>" in code_content:
|
|
ts_signals += 1
|
|
# Const/let (not var)
|
|
if re.search(r"\b(const|let)\b", code_content):
|
|
ts_signals += 1
|
|
# Error handling
|
|
if re.search(r"\b(try|catch|throw|Error)\b", code_content):
|
|
ts_signals += 1
|
|
# Async/await
|
|
if re.search(r"\b(async|await)\b", code_content):
|
|
ts_signals += 1
|
|
# Export
|
|
if re.search(r"\bexport\b", code_content):
|
|
ts_signals += 1
|
|
|
|
ts_quality = min(ts_signals / (ts_max * 0.6), 1.0) # 60% of signals = full score
|
|
breakdown["typescript_quality"] = round(ts_quality, 3)
|
|
|
|
# --- Completeness (0-1) — does the code look complete? ---
|
|
completeness_signals = 0
|
|
|
|
# Has a return statement or expression
|
|
if re.search(r"\breturn\b", code_content) or has_arrow:
|
|
completeness_signals += 1
|
|
# Has function/class definition
|
|
if re.search(r"\b(function|class)\s+\w+", code_content):
|
|
completeness_signals += 1
|
|
# Balanced braces (rough check)
|
|
open_braces = code_content.count("{")
|
|
close_braces = code_content.count("}")
|
|
if open_braces > 0 and abs(open_braces - close_braces) <= 1:
|
|
completeness_signals += 1
|
|
# Sufficient length
|
|
code_lines = [l for l in code_content.split("\n") if l.strip()]
|
|
if len(code_lines) >= 10:
|
|
completeness_signals += 1
|
|
elif len(code_lines) >= 5:
|
|
completeness_signals += 0.5
|
|
|
|
completeness = min(completeness_signals / 3.0, 1.0)
|
|
breakdown["completeness"] = round(completeness, 3)
|
|
|
|
# --- Explanation quality (0-1) — did they explain the code? ---
|
|
non_code_text = response
|
|
for block in code_blocks:
|
|
non_code_text = non_code_text.replace(block, "")
|
|
explanation_words = len(non_code_text.split())
|
|
|
|
if explanation_words >= 100:
|
|
explanation = 1.0
|
|
elif explanation_words >= 30:
|
|
explanation = 0.5 + 0.5 * ((explanation_words - 30) / 70)
|
|
else:
|
|
explanation = 0.2
|
|
breakdown["explanation"] = round(explanation, 3)
|
|
|
|
# --- Weighted final score ---
|
|
criteria = task.get("evaluation", {}).get("criteria", [])
|
|
if criteria:
|
|
score_map = {
|
|
"correctness": (code_presence + keyword_score + completeness) / 3,
|
|
"types": ts_quality,
|
|
"type_safety": ts_quality,
|
|
"edge_cases": keyword_score,
|
|
"code_quality": (ts_quality + completeness) / 2,
|
|
"complexity": ts_quality,
|
|
"completeness": completeness,
|
|
"timing": keyword_score,
|
|
"cancellation": keyword_score,
|
|
"singleton": keyword_score,
|
|
"circular_detection": keyword_score,
|
|
"error_reporting": keyword_score,
|
|
"computed": keyword_score,
|
|
"efficiency": ts_quality,
|
|
"examples": explanation,
|
|
"practical": explanation,
|
|
"recommendation": explanation,
|
|
}
|
|
total_weight = sum(c["weight"] for c in criteria)
|
|
weighted_sum = sum(
|
|
c["weight"] * score_map.get(c["name"], 0.5)
|
|
for c in criteria
|
|
)
|
|
final_ratio = weighted_sum / total_weight if total_weight > 0 else 0.5
|
|
else:
|
|
final_ratio = (
|
|
code_presence * 0.3
|
|
+ keyword_score * 0.2
|
|
+ ts_quality * 0.2
|
|
+ completeness * 0.2
|
|
+ explanation * 0.1
|
|
)
|
|
|
|
final_score = round(final_ratio * max_score, 1)
|
|
|
|
return {
|
|
"task_id": task["id"],
|
|
"score": final_score,
|
|
"max_score": max_score,
|
|
"pass": final_score >= max_score * 0.5,
|
|
"breakdown": breakdown,
|
|
"code_lines": len(code_lines),
|
|
"feedback": "; ".join(feedback_parts) if feedback_parts else "OK",
|
|
}
|