self-bench 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile.sandbox +1 -1
- package/README.md +20 -0
- package/bun.lock +48 -0
- package/compose.yaml +7 -1
- package/dist/agent-smoke-main.js +3 -2
- package/dist/agent-smoke-main.js.map +1 -1
- package/dist/agent-smoke.d.ts +2 -1
- package/dist/agent-smoke.d.ts.map +1 -1
- package/dist/agent-smoke.js +6 -1
- package/dist/agent-smoke.js.map +1 -1
- package/dist/api.d.ts +24 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +25 -18
- package/dist/api.js.map +1 -1
- package/dist/build-metadata.js +1 -1
- package/dist/cli.js +67 -11
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +36 -10
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +89 -15
- package/dist/config.js.map +1 -1
- package/dist/contracts.d.ts +22 -2
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +31 -6
- package/dist/contracts.js.map +1 -1
- package/dist/eval-main.js +3 -2
- package/dist/eval-main.js.map +1 -1
- package/dist/evaluate.d.ts +2 -1
- package/dist/evaluate.d.ts.map +1 -1
- package/dist/evaluate.js +2 -1
- package/dist/evaluate.js.map +1 -1
- package/dist/harbor-environment.d.ts +2 -0
- package/dist/harbor-environment.d.ts.map +1 -0
- package/dist/harbor-environment.js +15 -0
- package/dist/harbor-environment.js.map +1 -0
- package/dist/harbor-results.d.ts.map +1 -1
- package/dist/harbor-results.js +2 -0
- package/dist/harbor-results.js.map +1 -1
- package/dist/process.d.ts +2 -1
- package/dist/process.d.ts.map +1 -1
- package/dist/process.js.map +1 -1
- package/dist/providers.d.ts +8 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +14 -0
- package/dist/providers.js.map +1 -0
- package/dist/reaudit-main.js +5 -5
- package/dist/reaudit-main.js.map +1 -1
- package/dist/repair-main.js +5 -5
- package/dist/repair-main.js.map +1 -1
- package/dist/sandbox-author.bundle.js +40 -6
- package/dist/sandbox-timeout.d.ts +11 -0
- package/dist/sandbox-timeout.d.ts.map +1 -0
- package/dist/sandbox-timeout.js +41 -0
- package/dist/sandbox-timeout.js.map +1 -0
- package/dist/sandbox-validation-repair.bundle.js +40 -6
- package/dist/sandbox.d.ts +2 -2
- package/dist/sandbox.d.ts.map +1 -1
- package/dist/sandbox.js +10 -3
- package/dist/sandbox.js.map +1 -1
- package/dist/temporal/activities.d.ts +2 -2
- package/dist/temporal/activities.d.ts.map +1 -1
- package/dist/temporal/activities.js +7 -1
- package/dist/temporal/activities.js.map +1 -1
- package/dist/temporal/worker-main.js +2 -2
- package/dist/temporal/worker-main.js.map +1 -1
- package/dist/terminal-prompts.d.ts +26 -0
- package/dist/terminal-prompts.d.ts.map +1 -0
- package/dist/terminal-prompts.js +137 -0
- package/dist/terminal-prompts.js.map +1 -0
- package/dist/terminal-reporter.d.ts +30 -0
- package/dist/terminal-reporter.d.ts.map +1 -0
- package/dist/terminal-reporter.js +90 -0
- package/dist/terminal-reporter.js.map +1 -0
- package/dist/validate-main.js +8 -2
- package/dist/validate-main.js.map +1 -1
- package/dist/vercel-cli.d.ts +64 -0
- package/dist/vercel-cli.d.ts.map +1 -0
- package/dist/vercel-cli.js +303 -0
- package/dist/vercel-cli.js.map +1 -0
- package/dist/vercel-command.d.ts +14 -0
- package/dist/vercel-command.d.ts.map +1 -0
- package/dist/vercel-command.js +93 -0
- package/dist/vercel-command.js.map +1 -0
- package/dist/vercel-executor.d.ts +14 -0
- package/dist/vercel-executor.d.ts.map +1 -0
- package/dist/vercel-executor.js +356 -0
- package/dist/vercel-executor.js.map +1 -0
- package/dist/vercel-fetch.d.ts +6 -0
- package/dist/vercel-fetch.d.ts.map +1 -0
- package/dist/vercel-fetch.js +39 -0
- package/dist/vercel-fetch.js.map +1 -0
- package/dist/vercel-profile.d.ts +34 -0
- package/dist/vercel-profile.d.ts.map +1 -0
- package/dist/vercel-profile.js +244 -0
- package/dist/vercel-profile.js.map +1 -0
- package/dist/vercel-runtime-image.d.ts +51 -0
- package/dist/vercel-runtime-image.d.ts.map +1 -0
- package/dist/vercel-runtime-image.js +123 -0
- package/dist/vercel-runtime-image.js.map +1 -0
- package/dist/vercel-setup-probe.d.ts +49 -0
- package/dist/vercel-setup-probe.d.ts.map +1 -0
- package/dist/vercel-setup-probe.js +151 -0
- package/dist/vercel-setup-probe.js.map +1 -0
- package/dist/vercel-setup.d.ts +42 -0
- package/dist/vercel-setup.d.ts.map +1 -0
- package/dist/vercel-setup.js +280 -0
- package/dist/vercel-setup.js.map +1 -0
- package/docs/evaluations.md +2 -0
- package/docs/operations.md +128 -6
- package/package.json +5 -1
- package/review/index.html +14 -0
- package/review/src/App.tsx +338 -0
- package/review/src/export-loader.test.ts +57 -0
- package/review/src/export-loader.ts +151 -0
- package/review/src/main.tsx +15 -0
- package/review/src/styles.css +162 -0
- package/review/src/types.ts +47 -0
- package/review/tsconfig.json +16 -0
- package/review/vite.config.ts +20 -0
- package/scripts/verify-package.ts +27 -3
- package/src/agent-smoke-main.ts +3 -2
- package/src/agent-smoke.ts +8 -2
- package/src/api.ts +31 -18
- package/src/cli.ts +72 -11
- package/src/config.ts +150 -25
- package/src/contracts.ts +33 -6
- package/src/eval-main.ts +3 -2
- package/src/evaluate.ts +5 -3
- package/src/harbor-environment.ts +17 -0
- package/src/harbor-results.ts +2 -0
- package/src/process.ts +3 -1
- package/src/providers.ts +22 -0
- package/src/reaudit-main.ts +8 -5
- package/src/repair-main.ts +8 -5
- package/src/sandbox-timeout.ts +56 -0
- package/src/sandbox.ts +15 -5
- package/src/temporal/activities.ts +9 -3
- package/src/temporal/worker-main.ts +2 -2
- package/src/terminal-prompts.ts +197 -0
- package/src/terminal-reporter.ts +126 -0
- package/src/validate-main.ts +9 -3
- package/src/vercel-cli.ts +403 -0
- package/src/vercel-command.ts +127 -0
- package/src/vercel-executor.ts +448 -0
- package/src/vercel-fetch.ts +45 -0
- package/src/vercel-profile.ts +319 -0
- package/src/vercel-runtime-image.ts +204 -0
- package/src/vercel-setup-probe.ts +229 -0
- package/src/vercel-setup.ts +419 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--bg: #f4f5f7;
|
|
3
|
+
--surface: #ffffff;
|
|
4
|
+
--border: #d8dce3;
|
|
5
|
+
--text: #1a1d23;
|
|
6
|
+
--muted: #6b7280;
|
|
7
|
+
--accent: #2563eb;
|
|
8
|
+
--danger: #dc2626;
|
|
9
|
+
--success: #059669;
|
|
10
|
+
--code-bg: #f1f3f5;
|
|
11
|
+
--font: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
|
|
12
|
+
--mono: "SF Mono", "Cascadia Code", "Fira Code", monospace;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@media (prefers-color-scheme: dark) {
|
|
16
|
+
:root {
|
|
17
|
+
--bg: #0d1117;
|
|
18
|
+
--surface: #161b22;
|
|
19
|
+
--border: #30363d;
|
|
20
|
+
--text: #e6edf3;
|
|
21
|
+
--muted: #8b949e;
|
|
22
|
+
--accent: #58a6ff;
|
|
23
|
+
--danger: #f85149;
|
|
24
|
+
--success: #3fb950;
|
|
25
|
+
--code-bg: #1c2128;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
30
|
+
|
|
31
|
+
body {
|
|
32
|
+
font-family: var(--font);
|
|
33
|
+
background: var(--bg);
|
|
34
|
+
color: var(--text);
|
|
35
|
+
font-size: 14px;
|
|
36
|
+
line-height: 1.5;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.app-shell { min-height: 100vh; display: flex; flex-direction: column; }
|
|
40
|
+
|
|
41
|
+
.topbar {
|
|
42
|
+
display: flex; justify-content: space-between; align-items: center;
|
|
43
|
+
padding: 16px 24px; border-bottom: 1px solid var(--border);
|
|
44
|
+
background: var(--surface);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.eyebrow {
|
|
48
|
+
font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
|
|
49
|
+
text-transform: uppercase; color: var(--muted);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.topbar h1 { font-size: 18px; font-weight: 600; margin-top: 2px; }
|
|
53
|
+
.topbar-actions { display: flex; gap: 8px; align-items: center; }
|
|
54
|
+
.token-input {
|
|
55
|
+
padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px;
|
|
56
|
+
background: var(--surface); color: var(--text); font-size: 12px; width: 180px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.error-banner {
|
|
60
|
+
padding: 12px 24px; background: var(--danger); color: #fff; font-size: 13px;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.workspace {
|
|
64
|
+
flex: 1; display: grid; grid-template-columns: 280px 1fr; gap: 16px;
|
|
65
|
+
padding: 16px 24px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.surface { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; }
|
|
69
|
+
|
|
70
|
+
.run-list { padding: 16px; overflow-y: auto; max-height: calc(100vh - 100px); }
|
|
71
|
+
|
|
72
|
+
.section-heading {
|
|
73
|
+
display: flex; justify-content: space-between; align-items: baseline;
|
|
74
|
+
margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid var(--border);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.section-heading h2 { font-size: 13px; font-weight: 600; }
|
|
78
|
+
.section-heading span { font-size: 11px; color: var(--muted); }
|
|
79
|
+
|
|
80
|
+
.run-row {
|
|
81
|
+
width: 100%; display: flex; flex-direction: column; gap: 2px;
|
|
82
|
+
padding: 10px 12px; margin-bottom: 6px; border: 1px solid var(--border);
|
|
83
|
+
border-radius: 6px; background: var(--surface); cursor: pointer; text-align: left;
|
|
84
|
+
font: inherit; color: inherit;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.run-row:hover { border-color: var(--accent); }
|
|
88
|
+
.run-row.selected { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
|
|
89
|
+
.run-row strong { font-size: 13px; }
|
|
90
|
+
.run-row span { font-size: 11px; color: var(--muted); }
|
|
91
|
+
.run-row small { font-size: 10px; color: var(--muted); }
|
|
92
|
+
|
|
93
|
+
.content { display: flex; flex-direction: column; gap: 16px; }
|
|
94
|
+
|
|
95
|
+
.empty {
|
|
96
|
+
padding: 64px 32px; text-align: center; display: flex; flex-direction: column;
|
|
97
|
+
align-items: center; gap: 8px; min-height: 400px; justify-content: center;
|
|
98
|
+
}
|
|
99
|
+
.empty h2 { font-size: 16px; font-weight: 600; }
|
|
100
|
+
.empty p { color: var(--muted); }
|
|
101
|
+
|
|
102
|
+
.summary {
|
|
103
|
+
display: flex; justify-content: space-between; align-items: center;
|
|
104
|
+
padding: 16px 20px;
|
|
105
|
+
}
|
|
106
|
+
.summary h2 { font-size: 16px; font-weight: 600; }
|
|
107
|
+
.summary .muted { font-size: 12px; color: var(--muted); margin-top: 2px; }
|
|
108
|
+
|
|
109
|
+
.review-grid { display: grid; grid-template-columns: 240px 1fr; gap: 16px; }
|
|
110
|
+
|
|
111
|
+
.task-list { padding: 16px; max-height: calc(100vh - 280px); overflow-y: auto; }
|
|
112
|
+
|
|
113
|
+
.task-row {
|
|
114
|
+
width: 100%; display: flex; justify-content: space-between; align-items: center;
|
|
115
|
+
padding: 8px 10px; margin-bottom: 4px; border: 1px solid var(--border);
|
|
116
|
+
border-radius: 5px; background: var(--surface); cursor: pointer; text-align: left;
|
|
117
|
+
font: inherit; color: inherit; font-size: 12px;
|
|
118
|
+
}
|
|
119
|
+
.task-row:hover { border-color: var(--accent); }
|
|
120
|
+
.task-row.selected { border-color: var(--accent); }
|
|
121
|
+
.task-row.removed { opacity: 0.5; }
|
|
122
|
+
.task-row.removed strong { text-decoration: line-through; }
|
|
123
|
+
.task-row span { font-size: 10px; color: var(--muted); }
|
|
124
|
+
|
|
125
|
+
.task-detail { padding: 20px 24px; max-height: calc(100vh - 280px); overflow-y: auto; }
|
|
126
|
+
|
|
127
|
+
.detail-header {
|
|
128
|
+
display: flex; justify-content: space-between; align-items: flex-start;
|
|
129
|
+
margin-bottom: 20px; padding-bottom: 16px; border-bottom: 1px solid var(--border);
|
|
130
|
+
}
|
|
131
|
+
.detail-header h2 { font-size: 18px; font-weight: 600; }
|
|
132
|
+
|
|
133
|
+
.detail-block { margin-bottom: 20px; }
|
|
134
|
+
.detail-block h3 {
|
|
135
|
+
font-size: 12px; font-weight: 600; letter-spacing: 0.04em;
|
|
136
|
+
text-transform: uppercase; color: var(--muted); margin-bottom: 6px;
|
|
137
|
+
}
|
|
138
|
+
.detail-block pre {
|
|
139
|
+
padding: 12px 16px; background: var(--code-bg); border-radius: 6px;
|
|
140
|
+
font-family: var(--mono); font-size: 12px; white-space: pre-wrap;
|
|
141
|
+
word-break: break-all; max-height: 400px; overflow-y: auto; line-height: 1.6;
|
|
142
|
+
}
|
|
143
|
+
.patch-files {
|
|
144
|
+
display: grid; gap: 10px; padding: 8px; max-height: 600px; overflow: auto;
|
|
145
|
+
background: var(--code-bg); border-radius: 6px;
|
|
146
|
+
}
|
|
147
|
+
.patch-files > div { overflow: hidden; border: 1px solid var(--border); border-radius: 4px; }
|
|
148
|
+
|
|
149
|
+
.button {
|
|
150
|
+
padding: 7px 14px; border: 1px solid var(--border); border-radius: 6px;
|
|
151
|
+
background: var(--surface); color: var(--text); font-size: 12px; font-weight: 500;
|
|
152
|
+
cursor: pointer; font-family: var(--font);
|
|
153
|
+
}
|
|
154
|
+
.button:hover { border-color: var(--accent); color: var(--accent); }
|
|
155
|
+
.button.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
|
|
156
|
+
.button.primary:hover { opacity: 0.9; color: #fff; }
|
|
157
|
+
.button.danger { color: var(--danger); border-color: var(--danger); }
|
|
158
|
+
.button.danger:hover { background: var(--danger); color: #fff; }
|
|
159
|
+
.button.undo { color: var(--success); border-color: var(--success); }
|
|
160
|
+
.button.undo:hover { background: var(--success); color: #fff; }
|
|
161
|
+
|
|
162
|
+
.muted { color: var(--muted); }
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface RunSummary {
|
|
2
|
+
runId: string;
|
|
3
|
+
status: string;
|
|
4
|
+
startedAt: string;
|
|
5
|
+
closedAt?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface TaskProgress {
|
|
9
|
+
taskId: string;
|
|
10
|
+
candidateId: string;
|
|
11
|
+
difficulty: "easy" | "medium" | "hard";
|
|
12
|
+
status: string;
|
|
13
|
+
reason?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface RunStatus {
|
|
17
|
+
runId: string;
|
|
18
|
+
phase: string;
|
|
19
|
+
requested: number;
|
|
20
|
+
accepted: number;
|
|
21
|
+
rejected: number;
|
|
22
|
+
tasks: TaskProgress[];
|
|
23
|
+
export?: { uri: string; sizeBytes: number; contentType: string };
|
|
24
|
+
error?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ExportManifest {
|
|
28
|
+
schemaVersion: number;
|
|
29
|
+
runId: string;
|
|
30
|
+
candidateCounts: Record<string, number>;
|
|
31
|
+
repository: { url: string; commit: string };
|
|
32
|
+
version: Record<string, unknown>;
|
|
33
|
+
acceptedCount: number;
|
|
34
|
+
tasks: { taskId: string; sha256: string }[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface ExportTask {
|
|
38
|
+
taskId: string;
|
|
39
|
+
files: Map<string, Uint8Array>;
|
|
40
|
+
textFiles: Map<string, string>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface LoadedExport {
|
|
44
|
+
manifest: ExportManifest;
|
|
45
|
+
tasks: ExportTask[];
|
|
46
|
+
taskArchives: Map<string, Uint8Array>;
|
|
47
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowSyntheticDefaultImports": true,
|
|
4
|
+
"esModuleInterop": true,
|
|
5
|
+
"jsx": "react-jsx",
|
|
6
|
+
"lib": ["DOM", "DOM.Iterable", "ES2023"],
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"moduleResolution": "Bundler",
|
|
9
|
+
"noEmit": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"target": "ES2022",
|
|
13
|
+
"types": ["bun", "vite/client"]
|
|
14
|
+
},
|
|
15
|
+
"include": ["src", "vite.config.ts"]
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import react from "@vitejs/plugin-react";
|
|
2
|
+
import { defineConfig } from "vite";
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
root: "review",
|
|
6
|
+
plugins: [react()],
|
|
7
|
+
build: {
|
|
8
|
+
outDir: "../dist/review",
|
|
9
|
+
emptyOutDir: true,
|
|
10
|
+
},
|
|
11
|
+
server: {
|
|
12
|
+
allowedHosts: ["avyays-mac-mini.tailf3cee5.ts.net"],
|
|
13
|
+
proxy: {
|
|
14
|
+
"/v1": "http://127.0.0.1:8080",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
preview: {
|
|
18
|
+
allowedHosts: ["avyays-mac-mini.tailf3cee5.ts.net"],
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -2,8 +2,14 @@ import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
|
|
5
|
+
const options = process.argv.slice(2);
|
|
6
|
+
const dockerBuild = options.length === 1 && options[0] === "--docker-build";
|
|
7
|
+
if (options.length > 0 && !dockerBuild) {
|
|
8
|
+
throw new Error(`unknown verify-package argument: ${options.join(" ")}`);
|
|
9
|
+
}
|
|
5
10
|
const root = resolve(import.meta.dir, "..");
|
|
6
11
|
const temporary = await mkdtemp(join(tmpdir(), "self-bench-package-"));
|
|
12
|
+
|
|
7
13
|
async function run(command: string, args: string[], cwd = root): Promise<string> {
|
|
8
14
|
const child = Bun.spawn([command, ...args], {
|
|
9
15
|
cwd,
|
|
@@ -42,15 +48,33 @@ try {
|
|
|
42
48
|
if (!help.includes("self-bench up")) {
|
|
43
49
|
throw new Error("installed self-bench did not print the expected CLI help");
|
|
44
50
|
}
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
const installedRoot = join(installRoot, "node_modules", packageJson.name);
|
|
52
|
+
for (const asset of [
|
|
53
|
+
".dockerignore",
|
|
54
|
+
"compose.yaml",
|
|
55
|
+
"Dockerfile",
|
|
56
|
+
"Dockerfile.sandbox",
|
|
57
|
+
"review/index.html",
|
|
58
|
+
"review/src/App.tsx",
|
|
59
|
+
"review/vite.config.ts",
|
|
60
|
+
"src/extensions/authoring.ts",
|
|
61
|
+
"src/skills/selfbench/SKILL.md",
|
|
62
|
+
]) {
|
|
63
|
+
await readFile(join(installedRoot, asset));
|
|
47
64
|
}
|
|
48
65
|
const installedPackage = JSON.parse(
|
|
49
|
-
await readFile(join(
|
|
66
|
+
await readFile(join(installedRoot, "package.json"), "utf8"),
|
|
50
67
|
) as { name: string; version: string };
|
|
51
68
|
if (installedPackage.name !== packageJson.name || installedPackage.version !== packageJson.version) {
|
|
52
69
|
throw new Error("installed package metadata does not match the workspace package");
|
|
53
70
|
}
|
|
71
|
+
if (dockerBuild) {
|
|
72
|
+
await run(
|
|
73
|
+
"docker",
|
|
74
|
+
["build", "--target", "build", "--file", join(installedRoot, "Dockerfile"), installedRoot],
|
|
75
|
+
installedRoot,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
54
78
|
console.log(`verified ${installedPackage.name}@${installedPackage.version}`);
|
|
55
79
|
} finally {
|
|
56
80
|
await rm(temporary, { recursive: true, force: true });
|
package/src/agent-smoke-main.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
4
|
import { smokeAllAdapters } from "./agent-smoke.js";
|
|
5
|
+
import { isHarborEnvironment } from "./providers.js";
|
|
5
6
|
|
|
6
7
|
const parsed = parseArgs({
|
|
7
8
|
options: {
|
|
@@ -27,8 +28,8 @@ Options:
|
|
|
27
28
|
-h, --help Show this help`);
|
|
28
29
|
process.exit(0);
|
|
29
30
|
}
|
|
30
|
-
const environment = parsed.values.environment;
|
|
31
|
-
if (environment
|
|
31
|
+
const environment = parsed.values.environment ?? "modal";
|
|
32
|
+
if (!isHarborEnvironment(environment)) {
|
|
32
33
|
throw new Error("--environment must be docker or modal");
|
|
33
34
|
}
|
|
34
35
|
const results = await smokeAllAdapters({
|
package/src/agent-smoke.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
|
+
import { harborChildEnvironment } from "./harbor-environment.js";
|
|
3
4
|
import { parallelMap } from "./parallel.js";
|
|
4
5
|
import { runCommand } from "./process.js";
|
|
6
|
+
import type { HarborEnvironment } from "./providers.js";
|
|
5
7
|
|
|
6
8
|
export const HARBOR_AGENT_ADAPTERS = [
|
|
7
9
|
"oracle",
|
|
@@ -48,7 +50,7 @@ export interface AdapterSmokeOptions {
|
|
|
48
50
|
readonly taskDirectory: string;
|
|
49
51
|
readonly jobsDirectory: string;
|
|
50
52
|
readonly harborPath?: string;
|
|
51
|
-
readonly environment?:
|
|
53
|
+
readonly environment?: HarborEnvironment;
|
|
52
54
|
readonly concurrency?: number;
|
|
53
55
|
}
|
|
54
56
|
|
|
@@ -99,7 +101,11 @@ export async function smokeAllAdapters(
|
|
|
99
101
|
"--yes",
|
|
100
102
|
"--quiet",
|
|
101
103
|
],
|
|
102
|
-
{
|
|
104
|
+
{
|
|
105
|
+
allowFailure: true,
|
|
106
|
+
env: harborChildEnvironment(),
|
|
107
|
+
timeoutMs: 60 * 60 * 1000,
|
|
108
|
+
},
|
|
103
109
|
);
|
|
104
110
|
const summary: AdapterSmokeResult = {
|
|
105
111
|
agent,
|
package/src/api.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { SelfBenchConfig } from "./config.js";
|
|
|
11
11
|
import {
|
|
12
12
|
artifactRefSchema,
|
|
13
13
|
type RunPhase,
|
|
14
|
+
type RunRequest,
|
|
14
15
|
type RunStatus,
|
|
15
16
|
repositoryRefSchema,
|
|
16
17
|
runRequestSchema,
|
|
@@ -68,26 +69,10 @@ export async function startApi(config: SelfBenchConfig): Promise<() => Promise<v
|
|
|
68
69
|
return;
|
|
69
70
|
}
|
|
70
71
|
if (request.method === "POST" && url.pathname === "/v1/runs") {
|
|
71
|
-
const
|
|
72
|
+
const workflowInput = buildRunRequest(
|
|
73
|
+
config,
|
|
72
74
|
JSON.parse((await readBody(request)).toString("utf8")),
|
|
73
75
|
);
|
|
74
|
-
const workflowInput = runRequestSchema.parse({
|
|
75
|
-
runId: submission.runId,
|
|
76
|
-
repository: submission.repository,
|
|
77
|
-
provenance: submission.provenance,
|
|
78
|
-
candidateCounts: submission.candidateCounts,
|
|
79
|
-
authoring: {
|
|
80
|
-
provider: "openai-codex",
|
|
81
|
-
model: submission.authoringModel,
|
|
82
|
-
reasoningEffort: "high",
|
|
83
|
-
},
|
|
84
|
-
version: {
|
|
85
|
-
selfbenchCommit: config.buildCommit ?? submission.selfbenchCommit,
|
|
86
|
-
executionBackend: config.execution.kind,
|
|
87
|
-
sandboxImage: config.execution.image,
|
|
88
|
-
schema: 1,
|
|
89
|
-
},
|
|
90
|
-
});
|
|
91
76
|
await client.workflow.start(selfBenchRunWorkflow, {
|
|
92
77
|
workflowId: workflowInput.runId,
|
|
93
78
|
taskQueue: config.temporal.taskQueue,
|
|
@@ -167,6 +152,34 @@ export async function startApi(config: SelfBenchConfig): Promise<() => Promise<v
|
|
|
167
152
|
};
|
|
168
153
|
}
|
|
169
154
|
|
|
155
|
+
export function buildRunRequest(
|
|
156
|
+
config: SelfBenchConfig,
|
|
157
|
+
submission: z.input<typeof submissionSchema>,
|
|
158
|
+
): RunRequest {
|
|
159
|
+
const parsed = submissionSchema.parse(submission);
|
|
160
|
+
return runRequestSchema.parse({
|
|
161
|
+
runId: parsed.runId,
|
|
162
|
+
repository: parsed.repository,
|
|
163
|
+
provenance: parsed.provenance,
|
|
164
|
+
candidateCounts: parsed.candidateCounts,
|
|
165
|
+
authoring: {
|
|
166
|
+
provider: "openai-codex",
|
|
167
|
+
model: parsed.authoringModel,
|
|
168
|
+
reasoningEffort: "high",
|
|
169
|
+
},
|
|
170
|
+
version: {
|
|
171
|
+
selfbenchCommit: config.buildCommit ?? parsed.selfbenchCommit,
|
|
172
|
+
executionBackend: config.execution.kind,
|
|
173
|
+
harborEnvironment: config.harborEnvironment,
|
|
174
|
+
sandboxImage: config.execution.image,
|
|
175
|
+
...(config.execution.kind === "vercel"
|
|
176
|
+
? { sandboxTimeoutCapMs: config.execution.timeoutCapMs }
|
|
177
|
+
: {}),
|
|
178
|
+
schema: 1,
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
170
183
|
async function queryStatus(
|
|
171
184
|
handle: ReturnType<Client["workflow"]["getHandle"]>,
|
|
172
185
|
): Promise<RunStatus | object> {
|
package/src/cli.ts
CHANGED
|
@@ -10,12 +10,20 @@ import type { ReadableStream as NodeReadableStream } from "node:stream/web";
|
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
11
|
import { parseArgs } from "node:util";
|
|
12
12
|
import { buildCommit } from "./build-metadata.js";
|
|
13
|
+
import { loadWorkerConfig } from "./config.js";
|
|
13
14
|
import { runCommand } from "./process.js";
|
|
14
15
|
import { collectGitHubPullRequestProvenance, collectRepositoryProvenance } from "./provenance.js";
|
|
16
|
+
import { isExecutionBackend, isHarborEnvironment, matchingHarborEnvironment } from "./providers.js";
|
|
15
17
|
import { type PolledRunStatus, waitForRun } from "./run-wait.js";
|
|
18
|
+
import { SetupCanceledError } from "./terminal-prompts.js";
|
|
19
|
+
import { applyVercelProfile } from "./vercel-profile.js";
|
|
20
|
+
import { setupVercel } from "./vercel-setup.js";
|
|
16
21
|
|
|
17
22
|
const [command, ...rest] = process.argv.slice(2);
|
|
18
23
|
switch (command) {
|
|
24
|
+
case "setup":
|
|
25
|
+
await setup(rest);
|
|
26
|
+
break;
|
|
19
27
|
case "up":
|
|
20
28
|
await up(rest);
|
|
21
29
|
break;
|
|
@@ -47,31 +55,74 @@ switch (command) {
|
|
|
47
55
|
throw new Error(`unknown command: ${command}`);
|
|
48
56
|
}
|
|
49
57
|
|
|
58
|
+
async function setup(args: string[]): Promise<void> {
|
|
59
|
+
const [provider, ...providerArgs] = args;
|
|
60
|
+
if (provider !== "vercel") {
|
|
61
|
+
fail("setup currently supports only: self-bench setup vercel");
|
|
62
|
+
}
|
|
63
|
+
const parsed = parseArgs({
|
|
64
|
+
args: providerArgs,
|
|
65
|
+
options: {
|
|
66
|
+
profile: { type: "string", default: "default" },
|
|
67
|
+
verbose: { type: "boolean", default: false },
|
|
68
|
+
},
|
|
69
|
+
strict: true,
|
|
70
|
+
});
|
|
71
|
+
try {
|
|
72
|
+
await setupVercel({
|
|
73
|
+
profileName: parsed.values.profile,
|
|
74
|
+
verbose: parsed.values.verbose,
|
|
75
|
+
});
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error instanceof SetupCanceledError) {
|
|
78
|
+
process.exitCode = 130;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
50
85
|
async function up(args: string[]): Promise<void> {
|
|
51
86
|
const parsed = parseArgs({
|
|
52
87
|
args,
|
|
53
88
|
options: {
|
|
54
89
|
backend: { type: "string", default: "docker" },
|
|
90
|
+
"harbor-environment": { type: "string" },
|
|
55
91
|
"modal-config": { type: "string" },
|
|
92
|
+
"vercel-profile": { type: "string" },
|
|
56
93
|
},
|
|
57
94
|
strict: true,
|
|
58
95
|
});
|
|
59
|
-
if (parsed.values.backend
|
|
60
|
-
fail('--backend must be "docker" or "
|
|
96
|
+
if (!isExecutionBackend(parsed.values.backend)) {
|
|
97
|
+
fail('--backend must be "docker", "modal", or "vercel"');
|
|
61
98
|
}
|
|
62
|
-
if (
|
|
63
|
-
|
|
99
|
+
if (
|
|
100
|
+
parsed.values["harbor-environment"] !== undefined &&
|
|
101
|
+
!isHarborEnvironment(parsed.values["harbor-environment"])
|
|
102
|
+
) {
|
|
103
|
+
fail('--harbor-environment must be "docker" or "modal"');
|
|
64
104
|
}
|
|
65
105
|
|
|
66
106
|
const projectRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
67
107
|
const composeFile = resolve(projectRoot, "compose.yaml");
|
|
68
108
|
const backend = parsed.values.backend;
|
|
69
|
-
const
|
|
109
|
+
const harborEnvironment =
|
|
110
|
+
parsed.values["harbor-environment"] ??
|
|
111
|
+
matchingHarborEnvironment(backend) ??
|
|
112
|
+
fail(`--harbor-environment is required with --backend ${backend}`);
|
|
113
|
+
const usesModal = backend === "modal" || harborEnvironment === "modal";
|
|
114
|
+
if (!usesModal && parsed.values["modal-config"] !== undefined) {
|
|
115
|
+
fail("--modal-config requires Modal generation or Harbor");
|
|
116
|
+
}
|
|
117
|
+
if (backend !== "vercel" && parsed.values["vercel-profile"] !== undefined) {
|
|
118
|
+
fail("--vercel-profile requires Vercel generation");
|
|
119
|
+
}
|
|
120
|
+
let environment: NodeJS.ProcessEnv = {
|
|
70
121
|
...process.env,
|
|
71
122
|
SELFBENCH_BUILD_COMMIT: await resolveSelfBenchCommit(),
|
|
72
123
|
SELFBENCH_EXECUTION_BACKEND: backend,
|
|
73
|
-
SELFBENCH_HARBOR_ENVIRONMENT:
|
|
74
|
-
...(
|
|
124
|
+
SELFBENCH_HARBOR_ENVIRONMENT: harborEnvironment,
|
|
125
|
+
...(usesModal
|
|
75
126
|
? {
|
|
76
127
|
SELFBENCH_MODAL_CONFIG_PATH: resolve(
|
|
77
128
|
parsed.values["modal-config"] ?? resolve(homedir(), ".modal.toml"),
|
|
@@ -79,6 +130,10 @@ async function up(args: string[]): Promise<void> {
|
|
|
79
130
|
}
|
|
80
131
|
: {}),
|
|
81
132
|
};
|
|
133
|
+
if (backend === "vercel") {
|
|
134
|
+
environment = await applyVercelProfile(environment, parsed.values["vercel-profile"]);
|
|
135
|
+
loadWorkerConfig(environment);
|
|
136
|
+
}
|
|
82
137
|
|
|
83
138
|
if (backend === "docker") {
|
|
84
139
|
await runCommand(
|
|
@@ -97,7 +152,9 @@ async function up(args: string[]): Promise<void> {
|
|
|
97
152
|
await runCommand("docker", ["compose", "--file", composeFile, "up", "-d", "--build"], {
|
|
98
153
|
env: environment,
|
|
99
154
|
});
|
|
100
|
-
console.log(
|
|
155
|
+
console.log(
|
|
156
|
+
`SelfBench is running with ${backend} generation and ${harborEnvironment} Harbor at http://127.0.0.1:8080`,
|
|
157
|
+
);
|
|
101
158
|
}
|
|
102
159
|
|
|
103
160
|
async function down(): Promise<void> {
|
|
@@ -340,7 +397,9 @@ function printHelp(): void {
|
|
|
340
397
|
console.log(`SelfBench creates durable tiered Harbor evaluations.
|
|
341
398
|
|
|
342
399
|
Usage:
|
|
343
|
-
self-bench
|
|
400
|
+
self-bench setup vercel [--profile NAME] [--verbose]
|
|
401
|
+
self-bench up [--backend docker|modal|vercel] [--harbor-environment docker|modal]
|
|
402
|
+
[--modal-config PATH] [--vercel-profile NAME]
|
|
344
403
|
self-bench down
|
|
345
404
|
self-bench run --repo PATH [--easy-count N] [--medium-count N] [--hard-count N]
|
|
346
405
|
[--model MODEL] [--run-id ID] [--wait] [--output OUTPUT.tar.gz]
|
|
@@ -349,8 +408,10 @@ Usage:
|
|
|
349
408
|
self-bench download RUN_ID OUTPUT.tar.gz
|
|
350
409
|
self-bench list
|
|
351
410
|
|
|
352
|
-
The up command starts the local stack and
|
|
353
|
-
|
|
411
|
+
The up command starts the local stack. Docker and Modal default Harbor to the matching backend; Vercel
|
|
412
|
+
requires --harbor-environment because Harbor does not support Vercel. Modal generation or Harbor uses
|
|
413
|
+
~/.modal.toml unless --modal-config overrides it. Run self-bench setup vercel once to create or select a
|
|
414
|
+
project, publish the pinned runtime image, verify access, and save an owner-only local profile.
|
|
354
415
|
|
|
355
416
|
The tier counts are candidate authoring budgets, not accepted-task targets. Rejected candidates are not
|
|
356
417
|
replaced, and the export contains only accepted tasks. The run command performs only repository metadata
|