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,197 @@
|
|
|
1
|
+
import {
|
|
2
|
+
autocomplete,
|
|
3
|
+
cancel as cancelPrompt,
|
|
4
|
+
confirm as confirmPrompt,
|
|
5
|
+
isCancel,
|
|
6
|
+
password,
|
|
7
|
+
select as selectPrompt,
|
|
8
|
+
text as textPrompt,
|
|
9
|
+
} from "@clack/prompts";
|
|
10
|
+
|
|
11
|
+
export class SetupCanceledError extends Error {
|
|
12
|
+
constructor(message = "Setup canceled") {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "SetupCanceledError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface PromptChoice {
|
|
19
|
+
readonly value: string;
|
|
20
|
+
readonly label: string;
|
|
21
|
+
readonly hint?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface SetupPrompter {
|
|
25
|
+
select(message: string, choices: readonly PromptChoice[], defaultValue?: string): Promise<string>;
|
|
26
|
+
search(message: string, choices: readonly PromptChoice[], defaultValue?: string): Promise<string>;
|
|
27
|
+
text(message: string, defaultValue?: string): Promise<string>;
|
|
28
|
+
secret(message: string): Promise<string>;
|
|
29
|
+
confirm(message: string, defaultValue: boolean): Promise<boolean>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class TerminalPrompter implements SetupPrompter {
|
|
33
|
+
readonly #input: NodeJS.ReadStream;
|
|
34
|
+
readonly #output: NodeJS.WriteStream;
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
input: NodeJS.ReadStream = process.stdin,
|
|
38
|
+
output: NodeJS.WriteStream = process.stdout,
|
|
39
|
+
) {
|
|
40
|
+
this.#input = input;
|
|
41
|
+
this.#output = output;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async select(
|
|
45
|
+
message: string,
|
|
46
|
+
choices: readonly PromptChoice[],
|
|
47
|
+
defaultValue?: string,
|
|
48
|
+
): Promise<string> {
|
|
49
|
+
this.#assertChoices(message, choices);
|
|
50
|
+
return await this.#run((signal) =>
|
|
51
|
+
selectPrompt<string>({
|
|
52
|
+
message,
|
|
53
|
+
options: choices.map(toPromptOption),
|
|
54
|
+
maxItems: this.#visibleItemCount(),
|
|
55
|
+
showInstructions: true,
|
|
56
|
+
...(defaultValue !== undefined && choices.some(({ value }) => value === defaultValue)
|
|
57
|
+
? { initialValue: defaultValue }
|
|
58
|
+
: {}),
|
|
59
|
+
input: this.#input,
|
|
60
|
+
output: this.#output,
|
|
61
|
+
signal,
|
|
62
|
+
}),
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async search(
|
|
67
|
+
message: string,
|
|
68
|
+
choices: readonly PromptChoice[],
|
|
69
|
+
defaultValue?: string,
|
|
70
|
+
): Promise<string> {
|
|
71
|
+
this.#assertChoices(message, choices);
|
|
72
|
+
return await this.#run((signal) =>
|
|
73
|
+
autocomplete<string>({
|
|
74
|
+
message,
|
|
75
|
+
options: choices.map(toPromptOption),
|
|
76
|
+
placeholder: "Type to filter…",
|
|
77
|
+
maxItems: this.#visibleItemCount(),
|
|
78
|
+
filter: (query, option) =>
|
|
79
|
+
`${option.label ?? ""}\n${option.hint ?? ""}\n${option.value}`
|
|
80
|
+
.toLowerCase()
|
|
81
|
+
.includes(query.toLowerCase()),
|
|
82
|
+
...(defaultValue !== undefined && choices.some(({ value }) => value === defaultValue)
|
|
83
|
+
? { initialValue: defaultValue }
|
|
84
|
+
: {}),
|
|
85
|
+
input: this.#input,
|
|
86
|
+
output: this.#output,
|
|
87
|
+
signal,
|
|
88
|
+
}),
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async text(message: string, defaultValue?: string): Promise<string> {
|
|
93
|
+
return await this.#run((signal) =>
|
|
94
|
+
textPrompt({
|
|
95
|
+
message,
|
|
96
|
+
...(defaultValue === undefined ? {} : { placeholder: defaultValue, defaultValue }),
|
|
97
|
+
input: this.#input,
|
|
98
|
+
output: this.#output,
|
|
99
|
+
signal,
|
|
100
|
+
}),
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async secret(message: string): Promise<string> {
|
|
105
|
+
if (!this.#input.isTTY || !this.#input.setRawMode) {
|
|
106
|
+
throw new Error("secure token input requires an interactive terminal");
|
|
107
|
+
}
|
|
108
|
+
return await this.#run((signal) =>
|
|
109
|
+
password({
|
|
110
|
+
message,
|
|
111
|
+
// An empty mask keeps both the token and its length out of terminal output.
|
|
112
|
+
mask: "",
|
|
113
|
+
validate: (value) => (value?.trim() ? undefined : "Enter a project-scoped token."),
|
|
114
|
+
input: this.#input,
|
|
115
|
+
output: this.#output,
|
|
116
|
+
signal,
|
|
117
|
+
}),
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async confirm(message: string, defaultValue: boolean): Promise<boolean> {
|
|
122
|
+
return await this.#run((signal) =>
|
|
123
|
+
confirmPrompt({
|
|
124
|
+
message,
|
|
125
|
+
initialValue: defaultValue,
|
|
126
|
+
input: this.#input,
|
|
127
|
+
output: this.#output,
|
|
128
|
+
signal,
|
|
129
|
+
}),
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async #run<T>(prompt: (signal: AbortSignal) => Promise<T | symbol>): Promise<T> {
|
|
134
|
+
const controller = new AbortController();
|
|
135
|
+
const wasRaw = this.#input.isRaw;
|
|
136
|
+
const wasFlowing = this.#input.readableFlowing;
|
|
137
|
+
let inputFailure: Error | undefined;
|
|
138
|
+
const abort = (error: Error): void => {
|
|
139
|
+
inputFailure = error;
|
|
140
|
+
controller.abort(error);
|
|
141
|
+
};
|
|
142
|
+
const onEnd = (): void => abort(new SetupCanceledError("Setup canceled at end of input"));
|
|
143
|
+
const onError = (error: Error): void => abort(error);
|
|
144
|
+
this.#input.once("end", onEnd);
|
|
145
|
+
this.#input.once("error", onError);
|
|
146
|
+
if (this.#input.readableEnded) {
|
|
147
|
+
onEnd();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
const result = await prompt(controller.signal);
|
|
152
|
+
if (isCancel(result)) {
|
|
153
|
+
const error = inputFailure ?? new SetupCanceledError();
|
|
154
|
+
if (error instanceof SetupCanceledError) {
|
|
155
|
+
cancelPrompt("Setup canceled.", { output: this.#output, withGuide: true });
|
|
156
|
+
}
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
return result;
|
|
160
|
+
} finally {
|
|
161
|
+
this.#input.off("end", onEnd);
|
|
162
|
+
this.#input.off("error", onError);
|
|
163
|
+
if (this.#input.isTTY && this.#input.setRawMode && this.#input.isRaw !== wasRaw) {
|
|
164
|
+
this.#input.setRawMode(Boolean(wasRaw));
|
|
165
|
+
}
|
|
166
|
+
if (wasFlowing !== true) {
|
|
167
|
+
this.#input.pause();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
#assertChoices(message: string, choices: readonly PromptChoice[]): void {
|
|
173
|
+
if (choices.length === 0) {
|
|
174
|
+
throw new Error(`${message} has no available choices`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
#visibleItemCount(): number {
|
|
179
|
+
return Math.max(3, Math.min(8, (this.#output.rows ?? 20) - 6));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function isInteractiveTerminal(): boolean {
|
|
184
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function toPromptOption(choice: PromptChoice): {
|
|
188
|
+
readonly value: string;
|
|
189
|
+
readonly label: string;
|
|
190
|
+
readonly hint?: string;
|
|
191
|
+
} {
|
|
192
|
+
return {
|
|
193
|
+
value: choice.value,
|
|
194
|
+
label: choice.label,
|
|
195
|
+
...(choice.hint ? { hint: choice.hint } : {}),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { Writable } from "node:stream";
|
|
2
|
+
import { stripVTControlCharacters } from "node:util";
|
|
3
|
+
import { cancel as cancelPrompt, intro, log, outro, spinner } from "@clack/prompts";
|
|
4
|
+
import { type CommandOutputHandler, RollingOutput } from "./process.js";
|
|
5
|
+
import { SetupCanceledError } from "./terminal-prompts.js";
|
|
6
|
+
|
|
7
|
+
export interface SetupTaskLabels {
|
|
8
|
+
readonly pending: string;
|
|
9
|
+
readonly success: string;
|
|
10
|
+
readonly failure: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface SetupReporter {
|
|
14
|
+
intro(title: string): void;
|
|
15
|
+
message(message: string): void;
|
|
16
|
+
warn(message: string): void;
|
|
17
|
+
cancel(message: string): void;
|
|
18
|
+
task<T>(
|
|
19
|
+
labels: SetupTaskLabels,
|
|
20
|
+
operation: (onOutput: CommandOutputHandler) => Promise<T>,
|
|
21
|
+
): Promise<T>;
|
|
22
|
+
finish(title: string, details: readonly string[]): void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class TerminalSetupReporter implements SetupReporter {
|
|
26
|
+
readonly #output: Writable;
|
|
27
|
+
readonly #errorOutput: Writable;
|
|
28
|
+
readonly #verbose: boolean;
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
options: {
|
|
32
|
+
readonly output?: Writable;
|
|
33
|
+
readonly errorOutput?: Writable;
|
|
34
|
+
readonly verbose?: boolean;
|
|
35
|
+
} = {},
|
|
36
|
+
) {
|
|
37
|
+
this.#output = options.output ?? process.stdout;
|
|
38
|
+
this.#errorOutput = options.errorOutput ?? process.stderr;
|
|
39
|
+
this.#verbose = options.verbose ?? false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
intro(title: string): void {
|
|
43
|
+
intro(title, { output: this.#output, withGuide: true });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
message(message: string): void {
|
|
47
|
+
log.message(message, { output: this.#output, withGuide: true });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
warn(message: string): void {
|
|
51
|
+
log.warn(message, { output: this.#output, withGuide: true });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
cancel(message: string): void {
|
|
55
|
+
cancelPrompt(message, { output: this.#output, withGuide: true });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async task<T>(
|
|
59
|
+
labels: SetupTaskLabels,
|
|
60
|
+
operation: (onOutput: CommandOutputHandler) => Promise<T>,
|
|
61
|
+
): Promise<T> {
|
|
62
|
+
const captured = new RollingOutput();
|
|
63
|
+
const onOutput: CommandOutputHandler = (stream, chunk) => {
|
|
64
|
+
captured.push(Buffer.from(chunk));
|
|
65
|
+
if (this.#verbose) {
|
|
66
|
+
(stream === "stderr" ? this.#errorOutput : this.#output).write(chunk);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
if (this.#verbose) {
|
|
71
|
+
log.step(labels.pending, { output: this.#output, withGuide: true });
|
|
72
|
+
try {
|
|
73
|
+
const result = await operation(onOutput);
|
|
74
|
+
log.success(labels.success, { output: this.#output, withGuide: true });
|
|
75
|
+
return result;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error instanceof SetupCanceledError) {
|
|
78
|
+
this.cancel("Setup canceled.");
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
log.error(labels.failure, { output: this.#output, withGuide: true });
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const progress = spinner({ indicator: "timer", output: this.#output, withGuide: true });
|
|
87
|
+
progress.start(labels.pending);
|
|
88
|
+
try {
|
|
89
|
+
const result = await operation(onOutput);
|
|
90
|
+
progress.stop(labels.success);
|
|
91
|
+
return result;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (error instanceof SetupCanceledError) {
|
|
94
|
+
progress.cancel("Setup canceled.");
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
progress.error(labels.failure);
|
|
98
|
+
this.#showFailureOutput(captured.text());
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
finish(title: string, details: readonly string[]): void {
|
|
104
|
+
log.success(title, { output: this.#output, withGuide: true });
|
|
105
|
+
log.message([...details], {
|
|
106
|
+
output: this.#output,
|
|
107
|
+
spacing: 0,
|
|
108
|
+
withGuide: true,
|
|
109
|
+
});
|
|
110
|
+
outro("Vercel Sandbox is ready.", { output: this.#output, withGuide: true });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
#showFailureOutput(value: string): void {
|
|
114
|
+
const cleaned = stripVTControlCharacters(value)
|
|
115
|
+
.replace(/\r(?!\n)/g, "\n")
|
|
116
|
+
.trim();
|
|
117
|
+
if (!cleaned) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
log.message(["Command output:", ...cleaned.split("\n")], {
|
|
121
|
+
output: this.#output,
|
|
122
|
+
spacing: 0,
|
|
123
|
+
withGuide: true,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
package/src/validate-main.ts
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
import { access, mkdir, readdir, writeFile } from "node:fs/promises";
|
|
4
4
|
import { basename, join, resolve } from "node:path";
|
|
5
5
|
import { parseArgs } from "node:util";
|
|
6
|
+
import { harborChildEnvironment } from "./harbor-environment.js";
|
|
6
7
|
import { harborInfrastructureError, readHarborJobResult } from "./harbor-results.js";
|
|
7
8
|
import { parallelMap } from "./parallel.js";
|
|
8
9
|
import { runCommand } from "./process.js";
|
|
10
|
+
import { type HarborEnvironment, isHarborEnvironment } from "./providers.js";
|
|
9
11
|
|
|
10
12
|
const parsed = parseArgs({
|
|
11
13
|
options: {
|
|
@@ -33,7 +35,7 @@ Options:
|
|
|
33
35
|
const tasksDirectory = resolve(parsed.values.tasks ?? fail("--tasks is required"));
|
|
34
36
|
const jobsDirectory = resolve(parsed.values.jobs ?? fail("--jobs is required"));
|
|
35
37
|
const environment = parsed.values.environment ?? "modal";
|
|
36
|
-
if (environment
|
|
38
|
+
if (!isHarborEnvironment(environment)) {
|
|
37
39
|
throw new Error("--environment must be modal or docker");
|
|
38
40
|
}
|
|
39
41
|
const concurrency = positiveInteger(parsed.values.concurrency, "--concurrency");
|
|
@@ -90,7 +92,7 @@ async function runGate(
|
|
|
90
92
|
taskDirectory: string,
|
|
91
93
|
taskId: string,
|
|
92
94
|
agent: "nop" | "oracle",
|
|
93
|
-
environment:
|
|
95
|
+
environment: HarborEnvironment,
|
|
94
96
|
jobsDirectory: string,
|
|
95
97
|
): Promise<{ readonly passed: boolean; readonly rewards: Readonly<Record<string, number>> }> {
|
|
96
98
|
const jobName = `${taskId}-${agent}-${crypto.randomUUID().slice(0, 8)}`;
|
|
@@ -116,7 +118,11 @@ async function runGate(
|
|
|
116
118
|
"--yes",
|
|
117
119
|
"--quiet",
|
|
118
120
|
],
|
|
119
|
-
{
|
|
121
|
+
{
|
|
122
|
+
allowFailure: true,
|
|
123
|
+
env: harborChildEnvironment(),
|
|
124
|
+
timeoutMs: 4 * 60 * 60 * 1000,
|
|
125
|
+
},
|
|
120
126
|
);
|
|
121
127
|
if (process.exitCode !== 0) {
|
|
122
128
|
throw new Error(`Harbor ${agent} exited ${process.exitCode}: ${process.stderr.slice(-1_000)}`);
|