Add harness app: agent orchestrator with cluster deployment

- Next.js app for orchestrating coding agent benchmarks (Claude Code, Codex, OpenCode)
- Dockerfile installs git, gh CLI, and agent CLIs for headless execution
- K8s deployment with workspace volume, sealed credentials for Claude + OpenCode
- Traefik IngressRoute at harness.coreworlds.io with internal-only middleware + TLS
- CI pipeline path filter for harness builds
- Fix OpenCode runtime flags (subcommand-based headless mode)
This commit is contained in:
Julia McGhee
2026-03-21 15:26:09 +00:00
parent 9e7077cd82
commit 6dde7c8aef
46 changed files with 4675 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
import { NextRequest, NextResponse } from "next/server";
import {
getCuratedModels,
getEnabledModels,
upsertCuratedModel,
removeCuratedModel,
toggleModelEnabled,
updateModelCost,
CuratedModel,
} from "@/lib/model-store";
export async function GET(request: NextRequest) {
const enabledOnly = request.nextUrl.searchParams.get("enabled") === "true";
return NextResponse.json(enabledOnly ? getEnabledModels() : getCuratedModels());
}
export async function POST(request: NextRequest) {
const body = await request.json();
if (body.action === "toggle" && body.id) {
const result = toggleModelEnabled(body.id);
if (!result) return NextResponse.json({ error: "not found" }, { status: 404 });
return NextResponse.json(result);
}
if (body.action === "update-cost" && body.id) {
const result = updateModelCost(body.id, body.costPer1kInput, body.costPer1kOutput);
if (!result) return NextResponse.json({ error: "not found" }, { status: 404 });
return NextResponse.json(result);
}
if (!body.id || !body.provider) {
return NextResponse.json({ error: "id and provider are required" }, { status: 400 });
}
const model: CuratedModel = {
id: body.id,
name: body.name || body.id,
provider: body.provider,
enabled: body.enabled ?? true,
contextWindow: body.contextWindow,
costPer1kInput: body.costPer1kInput,
costPer1kOutput: body.costPer1kOutput,
};
return NextResponse.json(upsertCuratedModel(model), { status: 201 });
}
export async function DELETE(request: NextRequest) {
const id = request.nextUrl.searchParams.get("id");
if (!id) return NextResponse.json({ error: "id required" }, { status: 400 });
removeCuratedModel(id);
return NextResponse.json({ ok: true });
}