@evolvingmachines/sdk 0.0.51 → 0.0.52-project-sable.20260726.6e95f36
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/dist/chunk-IHBQMTA4.js +6 -0
- package/dist/hosted/cli.cjs +89 -0
- package/dist/hosted/cli.d.cts +56 -0
- package/dist/hosted/cli.d.ts +56 -0
- package/dist/hosted/cli.js +84 -0
- package/dist/index.cjs +444 -63
- package/dist/index.d.cts +880 -365
- package/dist/index.d.ts +880 -365
- package/dist/index.js +439 -63
- package/dist/tar-WPIXS3E6.js +1 -0
- package/dist/types-BeJrn1lR.d.cts +1351 -0
- package/dist/types-BeJrn1lR.d.ts +1351 -0
- package/package.json +15 -7
|
@@ -0,0 +1,1351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public types for the hosted benchmarks/jobs API.
|
|
3
|
+
*/
|
|
4
|
+
/** Configuration for the benchmarks() / jobs() factories */
|
|
5
|
+
interface HostedClientConfig {
|
|
6
|
+
/** API key (default: process.env.EVOLVE_API_KEY) */
|
|
7
|
+
apiKey?: string;
|
|
8
|
+
/** API base URL override (default: the Evolve dashboard API) */
|
|
9
|
+
baseUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* ONE page shape for every collection on this surface — top level or nested.
|
|
13
|
+
*
|
|
14
|
+
* `nextCursor` means one thing everywhere: pass it back as the next call's
|
|
15
|
+
* `cursor` for the next page, and `null` means there is no next page. It never
|
|
16
|
+
* echoes where you already are, so a poller can always tell it has caught up.
|
|
17
|
+
*/
|
|
18
|
+
interface Page<T> {
|
|
19
|
+
items: T[];
|
|
20
|
+
nextCursor: string | null;
|
|
21
|
+
hasMore: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A value you can `await`, with the rest of the promise surface attached.
|
|
25
|
+
*
|
|
26
|
+
* The dual-use handles below were `PromiseLike` alone, which is enough for
|
|
27
|
+
* `await` and nothing else — so `client.list().catch(...)` was a compile error
|
|
28
|
+
* two lines after `await client.list()` compiled fine, and `.finally()` for a
|
|
29
|
+
* spinner was unavailable. A handle that is 90% of a promise is worse than one
|
|
30
|
+
* that is none of it, because the missing 10% is only discovered at the call
|
|
31
|
+
* site that needed it.
|
|
32
|
+
*
|
|
33
|
+
* `then`/`catch`/`finally` all return real Promises, so anything chained off a
|
|
34
|
+
* handle behaves exactly like promise code from that point on.
|
|
35
|
+
*/
|
|
36
|
+
interface Awaitable<T> extends PromiseLike<T> {
|
|
37
|
+
catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null): Promise<T | TResult>;
|
|
38
|
+
finally(onfinally?: (() => void) | null): Promise<T>;
|
|
39
|
+
}
|
|
40
|
+
/** Cursor + page-size options, accepted by every paged call */
|
|
41
|
+
interface PageOptions {
|
|
42
|
+
/** Max items per page */
|
|
43
|
+
limit?: number;
|
|
44
|
+
/** Cursor from a previous page's nextCursor */
|
|
45
|
+
cursor?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Job lifecycle status (wire values, as the API emits them).
|
|
49
|
+
*/
|
|
50
|
+
type JobStatus = "QUEUED" | "RUNNING" | "CANCELLING" | "COMPLETED" | "CANCELLED" | "FAILED";
|
|
51
|
+
/**
|
|
52
|
+
* Trial status law: a valid reward (including 0) = SCORED; verifier crash or
|
|
53
|
+
* out-of-domain reward = SCORING_ERROR (never a fabricated zero);
|
|
54
|
+
* INFRASTRUCTURE_ERROR: the trial was lost before a result was recorded;
|
|
55
|
+
* INDETERMINATE: the platform cannot tell whether the trial completed.
|
|
56
|
+
*/
|
|
57
|
+
type TrialStatus = "QUEUED" | "RUNNING" | "SCORING" | "SCORED" | "SCORING_ERROR" | "INFRASTRUCTURE_ERROR" | "INDETERMINATE" | "CANCELLED";
|
|
58
|
+
/** Benchmark version lifecycle state (wire values) */
|
|
59
|
+
type BenchmarkVersionState = "DRAFT" | "IMPORTING" | "BUILDING" | "VALIDATING" | "READY" | "FAILED" | "ARCHIVED";
|
|
60
|
+
/** One immutable version of a benchmark — one shape on every surface */
|
|
61
|
+
interface BenchmarkVersion {
|
|
62
|
+
version: string;
|
|
63
|
+
state: BenchmarkVersionState;
|
|
64
|
+
createdAt: string;
|
|
65
|
+
taskCount: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* One provider's verdict for a task: runnable there, or refused with the
|
|
69
|
+
* limitation named (e.g. a multi-container task on a provider that cannot
|
|
70
|
+
* host its services, or declared resources above the provider's ceiling).
|
|
71
|
+
*/
|
|
72
|
+
type TaskProviderVerdict = {
|
|
73
|
+
ok: true;
|
|
74
|
+
} | {
|
|
75
|
+
ok: false;
|
|
76
|
+
reason: string;
|
|
77
|
+
};
|
|
78
|
+
/** Public task fields only — instructions, environments, and tests never leave the server */
|
|
79
|
+
interface Task {
|
|
80
|
+
taskKey: string;
|
|
81
|
+
agentTimeoutSec: number;
|
|
82
|
+
verifierTimeoutSec: number;
|
|
83
|
+
/**
|
|
84
|
+
* Where the task can run, per sandbox provider. Advisory for planning a
|
|
85
|
+
* job's provider choice — creating a job whose tasks include
|
|
86
|
+
* one refused on the chosen provider is rejected with the same reason, so
|
|
87
|
+
* nothing is ever spent on a trial that cannot execute.
|
|
88
|
+
*/
|
|
89
|
+
providers: Record<EvalSandboxProvider, TaskProviderVerdict>;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* A benchmark in the shared catalog.
|
|
93
|
+
*
|
|
94
|
+
* list() returns the summary fields; get() additionally populates versions,
|
|
95
|
+
* selectedVersion, tasks, createdAt, and updatedAt.
|
|
96
|
+
*/
|
|
97
|
+
interface Benchmark {
|
|
98
|
+
name: string;
|
|
99
|
+
title: string | null;
|
|
100
|
+
description: string | null;
|
|
101
|
+
/** The active version, or null when none is active */
|
|
102
|
+
activeVersion: BenchmarkVersion | null;
|
|
103
|
+
/** All versions, newest first (get() only) */
|
|
104
|
+
versions?: BenchmarkVersion[];
|
|
105
|
+
/** The version whose tasks are listed below (get() only) */
|
|
106
|
+
selectedVersion?: BenchmarkVersion | null;
|
|
107
|
+
/**
|
|
108
|
+
* One page of the selected version's tasks (get() only). Paged like every
|
|
109
|
+
* other collection: a SWE-bench-scale benchmark has thousands of tasks, so
|
|
110
|
+
* pass { limit, cursor } to get() and follow nextCursor.
|
|
111
|
+
*/
|
|
112
|
+
tasks?: Page<Task>;
|
|
113
|
+
/**
|
|
114
|
+
* Where this benchmark's git source points now, versus what its active
|
|
115
|
+
* version was built from — the data behind a "new version available" badge.
|
|
116
|
+
* Null when there is nothing to watch (an uploaded corpus, a seeded one, or
|
|
117
|
+
* one imported before provenance was recorded); null is never "up to date".
|
|
118
|
+
*
|
|
119
|
+
* Nothing here imports anything. A new version is always a row you create.
|
|
120
|
+
*/
|
|
121
|
+
upstream: UpstreamStatus | null;
|
|
122
|
+
/** get() only */
|
|
123
|
+
createdAt?: string;
|
|
124
|
+
/** get() only */
|
|
125
|
+
updatedAt?: string;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* A benchmark's active version resolved to a runnable shape.
|
|
129
|
+
*
|
|
130
|
+
* Unlike Benchmark, `version` and `tasks` are non-optional: benchmarks()
|
|
131
|
+
* .getActive() throws NoActiveVersionError when there is no active version,
|
|
132
|
+
* so callers never branch on a missing active version.
|
|
133
|
+
*/
|
|
134
|
+
interface ActiveBenchmark {
|
|
135
|
+
name: string;
|
|
136
|
+
title: string | null;
|
|
137
|
+
description: string | null;
|
|
138
|
+
/** The active version (always present) */
|
|
139
|
+
activeVersion: BenchmarkVersion;
|
|
140
|
+
/** The active version string (identical to activeVersion.version) */
|
|
141
|
+
version: string;
|
|
142
|
+
/** One page of the active version's tasks */
|
|
143
|
+
tasks: Page<Task>;
|
|
144
|
+
/** All versions, newest first */
|
|
145
|
+
versions: BenchmarkVersion[];
|
|
146
|
+
createdAt: string;
|
|
147
|
+
updatedAt: string;
|
|
148
|
+
}
|
|
149
|
+
/** One agent: harness + model (+ optional pinned harness version and effort) */
|
|
150
|
+
interface JobAgent {
|
|
151
|
+
/** A built-in harness ("claude", "codex", ...) or a registered custom harness name */
|
|
152
|
+
harness: string;
|
|
153
|
+
model: string;
|
|
154
|
+
/**
|
|
155
|
+
* Pin the harness version. Omitted (or null) resolves the latest at dispatch
|
|
156
|
+
* time; the version that actually ran is recorded on every trial as
|
|
157
|
+
* `resolvedHarnessVersion`. Rejected at creation when the pin is not an exact
|
|
158
|
+
* version (`invalid_input`), when the version is not published
|
|
159
|
+
* (`harness_version_not_found`), or when the harness is a custom one — those
|
|
160
|
+
* are versioned by the content of their own source (`invalid_input`).
|
|
161
|
+
*/
|
|
162
|
+
harnessVersion?: string | null;
|
|
163
|
+
/**
|
|
164
|
+
* How hard the model is asked to think. The accepted values are published at
|
|
165
|
+
* `meta.limits.job.reasoningEfforts`, and omitted (or null) takes the value
|
|
166
|
+
* published beside them as `defaultReasoningEffort` — read them from the
|
|
167
|
+
* capability document rather than hardcoding either.
|
|
168
|
+
*
|
|
169
|
+
* PART OF THE AGENT'S IDENTITY, like the harness, the model and the version
|
|
170
|
+
* pin: the same harness and model at "low" and at "high" are two systems,
|
|
171
|
+
* they de-duplicate separately, and every trial echoes the effort back on
|
|
172
|
+
* `trial.agent`. An effort a harness cannot apply is refused at creation
|
|
173
|
+
* (`invalid_input`) rather than recorded and never sent — see
|
|
174
|
+
* `HarnessCapability.effortSupport`.
|
|
175
|
+
*/
|
|
176
|
+
reasoningEffort?: string | null;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Sandbox provider a hosted job runs on. Named `EvalSandboxProvider` to
|
|
180
|
+
* avoid colliding with the core SDK's `SandboxProvider` (the sandbox-abstraction
|
|
181
|
+
* interface).
|
|
182
|
+
*/
|
|
183
|
+
type EvalSandboxProvider = "e2b" | "daytona" | "modal";
|
|
184
|
+
/** Where a trial's verifier executed: a separate pristine box, or inside the agent box */
|
|
185
|
+
type VerifierMode = "separate" | "shared";
|
|
186
|
+
/** The input contract for creating a job */
|
|
187
|
+
interface JobInput {
|
|
188
|
+
/**
|
|
189
|
+
* Benchmark reference: "name@version" for a pinned run, or a bare "name" —
|
|
190
|
+
* a bare name resolves server-side to the benchmark's active READY version.
|
|
191
|
+
* Responses always echo the resolved "name@version".
|
|
192
|
+
*/
|
|
193
|
+
benchmark: string;
|
|
194
|
+
/** Task keys to run (omitted = every task of the version) */
|
|
195
|
+
tasks?: string[];
|
|
196
|
+
agents: JobAgent[];
|
|
197
|
+
/** Runs per task x agent (default: 1) */
|
|
198
|
+
runsPerTask?: number;
|
|
199
|
+
/** Parallel trials (default: 1) */
|
|
200
|
+
concurrency?: number;
|
|
201
|
+
/**
|
|
202
|
+
* Hard model-spend cap in USD for EACH TRIAL — the platform's only spend
|
|
203
|
+
* enforcement, applied as the budget of the gateway key that trial runs on.
|
|
204
|
+
* Optional: omitted, the server applies its own default ($200,
|
|
205
|
+
* operator-tunable). The response echoes the RESOLVED cap either way, so an
|
|
206
|
+
* omitted one is never invisible, and states the resulting worst case for
|
|
207
|
+
* the job as a whole.
|
|
208
|
+
*/
|
|
209
|
+
maxTrialSpendUsd?: number;
|
|
210
|
+
/** Sandbox provider to run on (optional; server default: `e2b`) */
|
|
211
|
+
sandboxProvider?: EvalSandboxProvider;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Trial count histogram by status. EVERY status is present, zeros included, so
|
|
215
|
+
* a status bar can be drawn straight off the response without hardcoding the
|
|
216
|
+
* enum and discovering a new status only when a bar goes missing.
|
|
217
|
+
*/
|
|
218
|
+
type TrialCounts = Record<TrialStatus, number>;
|
|
219
|
+
/** How many trials there are, and how they break down by status */
|
|
220
|
+
interface TrialTally {
|
|
221
|
+
total: number;
|
|
222
|
+
byStatus: TrialCounts;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Why a job FAILED — the same {code, message} grammar as an API failure, and
|
|
226
|
+
* deliberately NOT under the key `error`, which on this surface means "this
|
|
227
|
+
* request failed". `if (body.error) throw` stays correct on a healthy read of a
|
|
228
|
+
* failed job.
|
|
229
|
+
*/
|
|
230
|
+
interface JobFailure {
|
|
231
|
+
/** Stable machine-readable cause, e.g. "job_execution_failed" */
|
|
232
|
+
code: string;
|
|
233
|
+
message: string;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* A job = tasks x agents x runsPerTask.
|
|
237
|
+
*
|
|
238
|
+
* ONE shape from every call — run, get, cancel, rerunFailed and each list row
|
|
239
|
+
* are the same fields, so a job card renders from any of them without knowing
|
|
240
|
+
* where it came from. Nothing here is optional and nothing is "get() only".
|
|
241
|
+
*/
|
|
242
|
+
interface Job {
|
|
243
|
+
id: string;
|
|
244
|
+
status: JobStatus;
|
|
245
|
+
/** "name@version" */
|
|
246
|
+
benchmark: string;
|
|
247
|
+
agents: JobAgent[];
|
|
248
|
+
runsPerTask: number;
|
|
249
|
+
concurrency: number;
|
|
250
|
+
/** The resolved per-trial cap every trial of this job runs under */
|
|
251
|
+
maxTrialSpendUsd: number;
|
|
252
|
+
/**
|
|
253
|
+
* The most this job can cost: its trial count times the per-trial cap. There
|
|
254
|
+
* is no job-wide budget, so this product is the real ceiling — stated here
|
|
255
|
+
* rather than left to you to multiply.
|
|
256
|
+
*/
|
|
257
|
+
worstCaseSpendUsd: number;
|
|
258
|
+
/** Sandbox provider this job runs on */
|
|
259
|
+
sandboxProvider: EvalSandboxProvider;
|
|
260
|
+
/** What the trials have actually spent so far (reporting, not a limit) */
|
|
261
|
+
spentUsd: number;
|
|
262
|
+
createdAt: string;
|
|
263
|
+
updatedAt: string;
|
|
264
|
+
/** Entity cardinality only — the parts of a job that have no status of their own */
|
|
265
|
+
counts: {
|
|
266
|
+
agents: number;
|
|
267
|
+
tasks: number;
|
|
268
|
+
};
|
|
269
|
+
/** How many trials, and the status histogram (all statuses, zeros included) */
|
|
270
|
+
trials: TrialTally;
|
|
271
|
+
/** Mean reward over SCORED trials only; null when none. Zero is a reward. */
|
|
272
|
+
meanReward: number | null;
|
|
273
|
+
/** Why the job FAILED, or null. Never the key `error` — see JobFailure. */
|
|
274
|
+
failure: JobFailure | null;
|
|
275
|
+
/** The job whose failed trials this one reruns; null for an original job */
|
|
276
|
+
sourceJobId: string | null;
|
|
277
|
+
/** True when the server replayed an existing job for this Idempotency-Key */
|
|
278
|
+
idempotentReplay: boolean;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Where a trial's spend figure came from: "measured" is the measured model
|
|
282
|
+
* spend reported by the platform; "assumed_cap" means spend could not be
|
|
283
|
+
* measured for this trial, so the per-trial cap is reported.
|
|
284
|
+
*/
|
|
285
|
+
type SpendSource = "measured" | "assumed_cap";
|
|
286
|
+
/**
|
|
287
|
+
* Open-ended per-harness detail recorded for a trial: bundle identity, token
|
|
288
|
+
* counts, whatever the harness found worth keeping.
|
|
289
|
+
*
|
|
290
|
+
* SPEND IS NO LONGER HERE. spentUsd and spendSource are first-class fields of
|
|
291
|
+
* Trial, because they are columns on the server rather than keys in an untyped
|
|
292
|
+
* blob — so a client reads them off the trial and there is exactly one place
|
|
293
|
+
* each fact is stated. The one spend-adjacent key that remains is the CAP,
|
|
294
|
+
* which is history rather than a queryable dimension: it is the cap THIS
|
|
295
|
+
* trial's key carried, which can differ from the job's current cap for a trial
|
|
296
|
+
* settled before a change.
|
|
297
|
+
*/
|
|
298
|
+
interface ModelUsage {
|
|
299
|
+
/** The per-trial model-spend cap that applied to this trial */
|
|
300
|
+
maxTrialSpendUsd?: number;
|
|
301
|
+
[key: string]: unknown;
|
|
302
|
+
}
|
|
303
|
+
/** One task x one agent x one runNumber */
|
|
304
|
+
interface Trial {
|
|
305
|
+
id: string;
|
|
306
|
+
taskKey: string;
|
|
307
|
+
agent: JobAgent;
|
|
308
|
+
/** 1-based user-requested run number */
|
|
309
|
+
runNumber: number;
|
|
310
|
+
status: TrialStatus;
|
|
311
|
+
/** The reward-file reward; null until scored */
|
|
312
|
+
reward: number | null;
|
|
313
|
+
/** Named metrics map (reward.json sub-scores) */
|
|
314
|
+
metrics: Record<string, number> | null;
|
|
315
|
+
/** Phase where an infrastructure failure occurred, when status is a failure */
|
|
316
|
+
failurePhase: string | null;
|
|
317
|
+
/** Failure detail (truncated to 2000 chars in list responses) */
|
|
318
|
+
failureDetail: string | null;
|
|
319
|
+
/** Wall-clock per phase, e.g. { agentMs, verifyMs } */
|
|
320
|
+
phaseTimingsMs: Record<string, number> | null;
|
|
321
|
+
/** Open-ended per-harness detail (bundle identity, token counts). Never spend. */
|
|
322
|
+
modelUsage: ModelUsage | null;
|
|
323
|
+
/** Sandbox provider the trial executed on; null until it has executed */
|
|
324
|
+
sandboxProvider: EvalSandboxProvider | null;
|
|
325
|
+
/** Where the verifier ran; null until recorded */
|
|
326
|
+
verifierMode: VerifierMode | null;
|
|
327
|
+
/**
|
|
328
|
+
* What this trial's model calls cost, in USD. NULL means the trial never ran
|
|
329
|
+
* (QUEUED, CANCELLED) — never zero. Zero is a real measurement, and it only
|
|
330
|
+
* appears when no gateway key was ever minted for the trial.
|
|
331
|
+
*/
|
|
332
|
+
spentUsd: number | null;
|
|
333
|
+
/** Whether spentUsd was measured or is the cap charged conservatively */
|
|
334
|
+
spendSource: SpendSource | null;
|
|
335
|
+
/**
|
|
336
|
+
* A mid-run reading of this trial's spend, and a LAGGING LOWER BOUND rather
|
|
337
|
+
* than its cost: the gateway settles 40-70s behind the calls that incurred
|
|
338
|
+
* the spend and the platform samples the trial's key every ~120s, so this
|
|
339
|
+
* number is always behind and `liveSpendAt` is how far. Null is "no reading
|
|
340
|
+
* yet", never $0.
|
|
341
|
+
*
|
|
342
|
+
* It is NOT cleared when the trial settles — what remains is the last
|
|
343
|
+
* mid-run sample, stale by construction. On a terminal trial read spentUsd
|
|
344
|
+
* and spendSource; those are the settled truth, and the only one.
|
|
345
|
+
*/
|
|
346
|
+
liveSpentUsd: number | null;
|
|
347
|
+
/** When that reading was taken — show its age, never the figure alone */
|
|
348
|
+
liveSpendAt: string | null;
|
|
349
|
+
/** Harness version actually resolved and used for the trial; null until resolved */
|
|
350
|
+
resolvedHarnessVersion: string | null;
|
|
351
|
+
/** Reference to the agent session/trace, when recorded */
|
|
352
|
+
sessionRef: string | null;
|
|
353
|
+
createdAt: string;
|
|
354
|
+
updatedAt: string;
|
|
355
|
+
}
|
|
356
|
+
/** Fields every job event carries, whatever its type. */
|
|
357
|
+
interface JobEventBase {
|
|
358
|
+
/** Monotonic sequence number (SSE id; the Last-Event-ID resume position) */
|
|
359
|
+
seq: number;
|
|
360
|
+
}
|
|
361
|
+
/** The job's resolved creation inputs, echoed so a watcher that joined late knows what it is watching. */
|
|
362
|
+
interface JobCreatedData {
|
|
363
|
+
/** Resolved "name@version", never the caller's bare name */
|
|
364
|
+
benchmark: string;
|
|
365
|
+
taskCount: number;
|
|
366
|
+
agents: JobAgent[];
|
|
367
|
+
runsPerTask: number;
|
|
368
|
+
concurrency: number;
|
|
369
|
+
maxTrialSpendUsd: number;
|
|
370
|
+
sandboxProvider: EvalSandboxProvider;
|
|
371
|
+
trialCount: number;
|
|
372
|
+
}
|
|
373
|
+
interface JobCancellingData {
|
|
374
|
+
jobId: string;
|
|
375
|
+
/** Queued trials cancelled outright by the request */
|
|
376
|
+
cancelledTrials: number;
|
|
377
|
+
/** Trials still in flight, which wind down on their own before the job settles */
|
|
378
|
+
activeTrials: number;
|
|
379
|
+
}
|
|
380
|
+
interface JobCancelledData {
|
|
381
|
+
jobId: string;
|
|
382
|
+
/** Total queued trials cancelled across the request and the settle */
|
|
383
|
+
cancelledTrials: number;
|
|
384
|
+
}
|
|
385
|
+
interface JobCompletedData {
|
|
386
|
+
jobId: string;
|
|
387
|
+
/**
|
|
388
|
+
* Always 0. Retained for wire compatibility: a QUEUED trial now blocks the
|
|
389
|
+
* COMPLETED settle outright, so the "undispatched trial" concept has no
|
|
390
|
+
* referent under trial-level claiming.
|
|
391
|
+
*/
|
|
392
|
+
undispatched: number;
|
|
393
|
+
}
|
|
394
|
+
interface TrialRunningData {
|
|
395
|
+
trialId: string;
|
|
396
|
+
taskKey: string;
|
|
397
|
+
}
|
|
398
|
+
interface TrialScoringData {
|
|
399
|
+
trialId: string;
|
|
400
|
+
/** Bytes of agent stdout retained for the failure detail */
|
|
401
|
+
capturedBytes: number;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* A mid-run spend sample landed on a still-live trial. Emitted only when the
|
|
405
|
+
* reading actually updated a RUNNING/SCORING row, so a poll that raced the
|
|
406
|
+
* settle never fires one.
|
|
407
|
+
*/
|
|
408
|
+
interface TrialSpendData {
|
|
409
|
+
trialId: string;
|
|
410
|
+
taskKey: string;
|
|
411
|
+
/** The same lagging lower bound as Trial.liveSpentUsd — not the trial's cost */
|
|
412
|
+
liveSpentUsd: number;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* A trial reached a terminal status. `reward` is present only on the scored
|
|
416
|
+
* path; `failurePhase` only on a failure. `attemptId`/`attemptPhase` appear
|
|
417
|
+
* only when the REAPER settled the trial (its worker died), which is exactly
|
|
418
|
+
* the case where knowing which attempt and which phase is worth having.
|
|
419
|
+
*/
|
|
420
|
+
interface TrialSettledData {
|
|
421
|
+
trialId: string;
|
|
422
|
+
taskKey: string;
|
|
423
|
+
status: TrialStatus;
|
|
424
|
+
/** The reward-file reward. Zero is a reward; absent means the trial did not score. */
|
|
425
|
+
reward?: number | null;
|
|
426
|
+
failurePhase?: string;
|
|
427
|
+
attemptId?: string;
|
|
428
|
+
attemptPhase?: string | null;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* One server-sent event from jobs().watch(), as a DISCRIMINATED UNION on `type`.
|
|
432
|
+
*
|
|
433
|
+
* `data: Record<string, unknown>` was the worst-typed line in this SDK: it is
|
|
434
|
+
* the payload of the headline docs example, and it told a reader nothing about
|
|
435
|
+
* what a trial.settled actually carries. Switching on `type` now narrows `data`.
|
|
436
|
+
*
|
|
437
|
+
* Every member below was read off its emit site in the server, not inferred:
|
|
438
|
+
* job.created api/jobs/route.ts, api/jobs/[id]/rerun-failed/route.ts
|
|
439
|
+
* job.running worker/runner.ts, worker/reaper.ts
|
|
440
|
+
* job.cancelling api/jobs/[id]/cancel/route.ts
|
|
441
|
+
* job.cancelled worker/settle.ts, api/jobs/[id]/cancel/route.ts
|
|
442
|
+
* job.completed worker/settle.ts
|
|
443
|
+
* trial.* worker/executor.ts, worker/runner.ts, worker/reaper.ts
|
|
444
|
+
*
|
|
445
|
+
* job.failed is declared terminal by the event stream and by this SDK, but NO
|
|
446
|
+
* SERVER PATH EMITS IT and nothing sets a job's status to FAILED. It stays in
|
|
447
|
+
* the union because both consumers already treat it as terminal — removing it
|
|
448
|
+
* is the breaking half of a change nobody asked for — so treat it as RESERVED
|
|
449
|
+
* rather than expected.
|
|
450
|
+
*/
|
|
451
|
+
type JobEvent = (JobEventBase & {
|
|
452
|
+
type: "job.created";
|
|
453
|
+
data: JobCreatedData;
|
|
454
|
+
}) | (JobEventBase & {
|
|
455
|
+
type: "job.running";
|
|
456
|
+
data: {
|
|
457
|
+
jobId: string;
|
|
458
|
+
};
|
|
459
|
+
}) | (JobEventBase & {
|
|
460
|
+
type: "job.cancelling";
|
|
461
|
+
data: JobCancellingData;
|
|
462
|
+
}) | (JobEventBase & {
|
|
463
|
+
type: "job.cancelled";
|
|
464
|
+
data: JobCancelledData;
|
|
465
|
+
}) | (JobEventBase & {
|
|
466
|
+
type: "job.completed";
|
|
467
|
+
data: JobCompletedData;
|
|
468
|
+
}) | (JobEventBase & {
|
|
469
|
+
type: "job.failed";
|
|
470
|
+
data: {
|
|
471
|
+
jobId: string;
|
|
472
|
+
};
|
|
473
|
+
}) | (JobEventBase & {
|
|
474
|
+
type: "trial.running";
|
|
475
|
+
data: TrialRunningData;
|
|
476
|
+
}) | (JobEventBase & {
|
|
477
|
+
type: "trial.scoring";
|
|
478
|
+
data: TrialScoringData;
|
|
479
|
+
}) | (JobEventBase & {
|
|
480
|
+
type: "trial.spend";
|
|
481
|
+
data: TrialSpendData;
|
|
482
|
+
}) | (JobEventBase & {
|
|
483
|
+
type: "trial.settled";
|
|
484
|
+
data: TrialSettledData;
|
|
485
|
+
});
|
|
486
|
+
/**
|
|
487
|
+
* The handle returned by jobs().watch(). It is both:
|
|
488
|
+
* - a promise for the final Job — `await client.watch(id)` resolves once
|
|
489
|
+
* the job reaches a terminal status (the original form); and
|
|
490
|
+
* - an async iterable of events — `for await (const event of client.watch(id))`
|
|
491
|
+
* yields each JobEvent and completes on the terminal event.
|
|
492
|
+
*
|
|
493
|
+
* Pick one form per call: both drive the same underlying SSE stream, so a
|
|
494
|
+
* single handle should not be awaited and iterated at once.
|
|
495
|
+
*/
|
|
496
|
+
interface JobWatch extends Awaitable<Job>, AsyncIterable<JobEvent> {
|
|
497
|
+
}
|
|
498
|
+
/** Cursor page of jobs (newest first) */
|
|
499
|
+
type JobPage = Page<Job>;
|
|
500
|
+
/**
|
|
501
|
+
* The handle returned by jobs().list(). Both:
|
|
502
|
+
* - a promise for a single JobPage — `await client.list({ limit })`
|
|
503
|
+
* returns one page (the original form); and
|
|
504
|
+
* - an async iterable — `for await (const item of client.list())` walks every
|
|
505
|
+
* job across cursor pages, fetching the next page for you.
|
|
506
|
+
*/
|
|
507
|
+
interface JobList extends Awaitable<JobPage>, AsyncIterable<Job> {
|
|
508
|
+
}
|
|
509
|
+
/** Cursor page of trials */
|
|
510
|
+
type TrialPage = Page<Trial>;
|
|
511
|
+
/**
|
|
512
|
+
* The handle returned by jobs().trials(). Both:
|
|
513
|
+
* - a promise for a single TrialPage — `await client.trials(id, { limit })`
|
|
514
|
+
* returns one page (the original form); and
|
|
515
|
+
* - an async iterable — `for await (const trial of client.trials(id))` walks
|
|
516
|
+
* every trial across cursor pages, fetching the next page for you.
|
|
517
|
+
*/
|
|
518
|
+
interface TrialList extends Awaitable<TrialPage>, AsyncIterable<Trial> {
|
|
519
|
+
}
|
|
520
|
+
/** Cursor page of benchmarks */
|
|
521
|
+
type BenchmarkPage = Page<Benchmark>;
|
|
522
|
+
/** Dual-use handle from benchmarks().list(): await one page, or iterate them all */
|
|
523
|
+
interface BenchmarkList extends Awaitable<BenchmarkPage>, AsyncIterable<Benchmark> {
|
|
524
|
+
}
|
|
525
|
+
/** Options for benchmarks().listImports() */
|
|
526
|
+
interface ListImportsOptions extends PageOptions {
|
|
527
|
+
/** Only imports in this status */
|
|
528
|
+
status?: BenchmarkImportStatus;
|
|
529
|
+
/** Only imports of this benchmark name */
|
|
530
|
+
benchmark?: string;
|
|
531
|
+
}
|
|
532
|
+
/** Cursor page of benchmark imports */
|
|
533
|
+
type BenchmarkImportPage = Page<BenchmarkImport>;
|
|
534
|
+
/** Dual-use handle from benchmarks().listImports(): await one page, or iterate them all */
|
|
535
|
+
interface BenchmarkImportList extends Awaitable<BenchmarkImportPage>, AsyncIterable<BenchmarkImport> {
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* A custom-harness upsert body. Same shape as CustomHarnessInput minus `name`,
|
|
539
|
+
* which the upsert takes as its first argument — the name is the resource
|
|
540
|
+
* identity, not a field of it.
|
|
541
|
+
*/
|
|
542
|
+
type CustomHarnessUpsertInput = CustomHarnessSourceInput & {
|
|
543
|
+
/** Command run headless with `sh -c` at the task working directory */
|
|
544
|
+
runCommand: string;
|
|
545
|
+
/** Env injected at RUN time only; may not override the run contract's keys */
|
|
546
|
+
env?: Record<string, string>;
|
|
547
|
+
};
|
|
548
|
+
/** Cursor page of custom harnesses */
|
|
549
|
+
type CustomHarnessPage = Page<CustomHarness>;
|
|
550
|
+
/** Dual-use handle from customHarnesses().list(): await one page, or iterate them all */
|
|
551
|
+
interface CustomHarnessList extends Awaitable<CustomHarnessPage>, AsyncIterable<CustomHarness> {
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Full detail of one trial — jobs().trial(id, trialId).
|
|
555
|
+
* Same shape as a list row, plus the owning job; unlike list rows,
|
|
556
|
+
* failureDetail is untruncated here.
|
|
557
|
+
*/
|
|
558
|
+
interface TrialDetail extends Trial {
|
|
559
|
+
/** The job this trial belongs to */
|
|
560
|
+
jobId: string;
|
|
561
|
+
}
|
|
562
|
+
/** One trace event of a trial (seq-ordered timeline) */
|
|
563
|
+
interface TrialTraceEvent {
|
|
564
|
+
/** Monotonic sequence number (the ?after= resume position) */
|
|
565
|
+
seq: number;
|
|
566
|
+
/** Event type */
|
|
567
|
+
type: string;
|
|
568
|
+
data: Record<string, unknown>;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* One page of a trial's trace — jobs().trialTrace().
|
|
572
|
+
*
|
|
573
|
+
* Same envelope as every other collection, and nextCursor means the same
|
|
574
|
+
* thing: pass it back as { cursor } for the next page, and NULL MEANS CAUGHT
|
|
575
|
+
* UP. To resume a poll later, keep the last event's `seq` and pass it as
|
|
576
|
+
* { cursor } — the trace's cursor IS its position in the seq timeline.
|
|
577
|
+
*/
|
|
578
|
+
type TrialTracePage = Page<TrialTraceEvent>;
|
|
579
|
+
/** Scored-trial coverage behind an aggregate (means cover SCORED trials only) */
|
|
580
|
+
interface ComparisonCoverage {
|
|
581
|
+
scored: number;
|
|
582
|
+
total: number;
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* One (taskKey x job) cell of the compare matrix. status is the shared
|
|
586
|
+
* TrialStatus when the cell's trials agree, "MIXED" when they differ, and
|
|
587
|
+
* "MISSING" when the job has no trials for the task.
|
|
588
|
+
*/
|
|
589
|
+
interface ComparisonCell {
|
|
590
|
+
jobId: string;
|
|
591
|
+
status: TrialStatus | "MIXED" | "MISSING";
|
|
592
|
+
/** Mean reward over the cell's SCORED trials; null when none. Zero is a reward. */
|
|
593
|
+
meanReward: number | null;
|
|
594
|
+
coverage: ComparisonCoverage;
|
|
595
|
+
}
|
|
596
|
+
/** One matrix row of jobs().compare(): a task across the compared jobs */
|
|
597
|
+
interface ComparisonTaskRow {
|
|
598
|
+
taskKey: string;
|
|
599
|
+
/** True when the jobs' cells differ in status or reward for this task */
|
|
600
|
+
disagreement: boolean;
|
|
601
|
+
/** Cells in the caller's job-id order */
|
|
602
|
+
cells: ComparisonCell[];
|
|
603
|
+
}
|
|
604
|
+
/** Per-job aggregate of jobs().compare() */
|
|
605
|
+
interface ComparisonAggregate {
|
|
606
|
+
id: string;
|
|
607
|
+
/** "name@version" */
|
|
608
|
+
benchmark: string;
|
|
609
|
+
status: JobStatus;
|
|
610
|
+
/** Mean reward over SCORED trials only; null when none. Zero is a reward. */
|
|
611
|
+
meanReward: number | null;
|
|
612
|
+
coverage: ComparisonCoverage;
|
|
613
|
+
spentUsd: number;
|
|
614
|
+
agents: JobAgent[];
|
|
615
|
+
createdAt: string;
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Result of jobs().compare([ids]): per-job aggregates plus a
|
|
619
|
+
* per-task matrix (disagreement rows first).
|
|
620
|
+
*/
|
|
621
|
+
interface JobComparison {
|
|
622
|
+
/** Aggregates in the caller's id order */
|
|
623
|
+
jobs: ComparisonAggregate[];
|
|
624
|
+
taskMatrix: ComparisonTaskRow[];
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* A regrade result's verdict status. Mirrors the reward law: a valid reward
|
|
628
|
+
* (including 0) = SCORED; verifier crash/out-of-domain = SCORING_ERROR; no
|
|
629
|
+
* reward file = INDETERMINATE; a verifier box lost before a durable verdict =
|
|
630
|
+
* INFRASTRUCTURE_ERROR. QUEUED/RUNNING while the regrade is in flight.
|
|
631
|
+
*/
|
|
632
|
+
type RegradeStatus = "QUEUED" | "RUNNING" | "SCORED" | "SCORING_ERROR" | "INFRASTRUCTURE_ERROR" | "INDETERMINATE";
|
|
633
|
+
/** A regrade job's derived status: QUEUED until any result starts, then RUNNING, then COMPLETED. */
|
|
634
|
+
type RegradeJobStatus = "QUEUED" | "RUNNING" | "COMPLETED";
|
|
635
|
+
/**
|
|
636
|
+
* One regrade of one source trial: the verifier re-run against that trial's
|
|
637
|
+
* RECORDED inputs, in a fresh separate verifier box. The agent phase is never
|
|
638
|
+
* re-run, and the source trial is never modified — `sourceReward`/`sourceStatus`
|
|
639
|
+
* are immutable snapshots taken when the regrade was created.
|
|
640
|
+
*/
|
|
641
|
+
interface RegradeResult {
|
|
642
|
+
/** Regrade result id */
|
|
643
|
+
id: string;
|
|
644
|
+
/** The source trial this regrade re-scored (immutable) */
|
|
645
|
+
sourceTrialId: string;
|
|
646
|
+
/** The source trial's task key */
|
|
647
|
+
taskKey: string;
|
|
648
|
+
status: RegradeStatus;
|
|
649
|
+
/** The regrade's reward-file reward; null until scored */
|
|
650
|
+
reward: number | null;
|
|
651
|
+
/** Named metrics map (reward.json sub-scores) */
|
|
652
|
+
metrics: Record<string, number> | null;
|
|
653
|
+
/** The recorded source-trial reward at regrade time (immutable snapshot) */
|
|
654
|
+
sourceReward: number | null;
|
|
655
|
+
/** The recorded source-trial status at regrade time (immutable snapshot) */
|
|
656
|
+
sourceStatus: string;
|
|
657
|
+
/** reward − sourceReward when both are real numbers, else null (Harbor's per-trial delta) */
|
|
658
|
+
rewardDelta: number | null;
|
|
659
|
+
/** Where the verifier ran — always "separate" (regrade only re-runs separate verifiers) */
|
|
660
|
+
verifierMode: VerifierMode;
|
|
661
|
+
/**
|
|
662
|
+
* Content digest of the resolved target verifier spec — the "verifier
|
|
663
|
+
* version". A digest equal to the source trial's own verifier reproduces the
|
|
664
|
+
* recorded reward; a different digest is a genuine new-verifier prediction.
|
|
665
|
+
* Null until the regrade runs.
|
|
666
|
+
*/
|
|
667
|
+
verifierDigest: string | null;
|
|
668
|
+
/** Provider box id of the verifier sandbox, recorded for provenance */
|
|
669
|
+
verifierSandboxId: string | null;
|
|
670
|
+
failurePhase: string | null;
|
|
671
|
+
failureDetail: string | null;
|
|
672
|
+
phaseTimingsMs: Record<string, number> | null;
|
|
673
|
+
createdAt: string;
|
|
674
|
+
/** When the regrade settled; null while QUEUED/RUNNING */
|
|
675
|
+
settledAt: string | null;
|
|
676
|
+
}
|
|
677
|
+
/** The filter applied when selecting source trials for a per-job regrade */
|
|
678
|
+
interface RegradeFilter {
|
|
679
|
+
status?: string[];
|
|
680
|
+
taskKey?: string;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* A regrade job's results: how many there are in the WHOLE job, how they break
|
|
684
|
+
* down by status (every status, zeros included), and one page of them.
|
|
685
|
+
*
|
|
686
|
+
* One key named for the collection rather than a `counts` object sitting beside
|
|
687
|
+
* a separately-named array — and paged, because a regrade of a 10,000-trial job
|
|
688
|
+
* holds 10,000 results.
|
|
689
|
+
*/
|
|
690
|
+
interface RegradeResultsPage extends Page<RegradeResult> {
|
|
691
|
+
/** Results in the whole job, not in this page */
|
|
692
|
+
total: number;
|
|
693
|
+
byStatus: Record<RegradeStatus, number>;
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* A regrade job = a collection of regrade results. A per-trial regrade holds
|
|
697
|
+
* one result; a per-job regrade holds one per eligible source trial. The
|
|
698
|
+
* job's `status` is derived from the whole result set, never from one page.
|
|
699
|
+
*/
|
|
700
|
+
interface RegradeJob {
|
|
701
|
+
id: string;
|
|
702
|
+
/** The job the source trials belong to */
|
|
703
|
+
sourceJobId: string;
|
|
704
|
+
status: RegradeJobStatus;
|
|
705
|
+
/** Sandbox provider the verifier boxes run on (copied from the source job) */
|
|
706
|
+
sandboxProvider: EvalSandboxProvider;
|
|
707
|
+
/** The filter applied to select source trials (per-job regrade), or null */
|
|
708
|
+
filter: RegradeFilter | null;
|
|
709
|
+
/** How many results, their status histogram, and one page of them */
|
|
710
|
+
results: RegradeResultsPage;
|
|
711
|
+
createdAt: string;
|
|
712
|
+
updatedAt: string;
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Source for benchmarks().import(): EITHER a git repository pinned to a ref, OR
|
|
716
|
+
* a local corpus directory (tarred deterministically on the client and
|
|
717
|
+
* uploaded).
|
|
718
|
+
*
|
|
719
|
+
* A UNION, not three optional fields. The old shape accepted `{}` and accepted
|
|
720
|
+
* both branches at once and threw at run time — exactly where a first-time user
|
|
721
|
+
* errs, and the one place a type could have said so first. `?: never` on the
|
|
722
|
+
* absent branch's keys is what makes `{ gitUrl, directory }` a compile error
|
|
723
|
+
* rather than a run-time one; a bare union would happily accept the excess
|
|
724
|
+
* property through a variable.
|
|
725
|
+
*
|
|
726
|
+
* Note that `ref` is REQUIRED on the git branch. It always was, in the sense
|
|
727
|
+
* that the server refuses without it — the type simply used to disagree.
|
|
728
|
+
*/
|
|
729
|
+
type BenchmarkImportSource = {
|
|
730
|
+
/** A git repository URL (https://, ssh://, or git@). */
|
|
731
|
+
gitUrl: string;
|
|
732
|
+
/** A pinned branch, tag, or commit. Required: an unpinned import is not reproducible. */
|
|
733
|
+
ref: string;
|
|
734
|
+
directory?: never;
|
|
735
|
+
} | {
|
|
736
|
+
/** A local Harbor-layout corpus directory — tarred + gzipped and uploaded. */
|
|
737
|
+
directory: string;
|
|
738
|
+
gitUrl?: never;
|
|
739
|
+
ref?: never;
|
|
740
|
+
};
|
|
741
|
+
/** Input for benchmarks().import() */
|
|
742
|
+
interface BenchmarkImportInput {
|
|
743
|
+
source: BenchmarkImportSource;
|
|
744
|
+
/** Catalog benchmark name the import creates or extends */
|
|
745
|
+
benchmarkName: string;
|
|
746
|
+
/** Version label for the imported benchmark version */
|
|
747
|
+
version: string;
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* Benchmark import job status.
|
|
751
|
+
*
|
|
752
|
+
* These are the SAME four words a job and a regrade use, and that is the point:
|
|
753
|
+
* an import used to speak a private IMPORTING/IMPORTED/FAILED vocabulary, so a
|
|
754
|
+
* status chip rendering all three had to carry a translation table for three
|
|
755
|
+
* spellings of the same four ideas.
|
|
756
|
+
*
|
|
757
|
+
* Terminal: "COMPLETED" (the corpus landed as a benchmark version; it becomes
|
|
758
|
+
* runnable once the platform activates it) and "FAILED".
|
|
759
|
+
*/
|
|
760
|
+
type BenchmarkImportStatus = "QUEUED" | "RUNNING" | "COMPLETED" | "FAILED";
|
|
761
|
+
/**
|
|
762
|
+
* A benchmark import job. Terminal statuses: "COMPLETED" and "FAILED".
|
|
763
|
+
*
|
|
764
|
+
* Self-describing: every response names the benchmark@version being imported,
|
|
765
|
+
* and every route that returns one — the 202 from import(), getImport(), and
|
|
766
|
+
* listImports() — returns this same shape, so a caller can render the row it
|
|
767
|
+
* just created without a follow-up read.
|
|
768
|
+
*/
|
|
769
|
+
interface BenchmarkImport {
|
|
770
|
+
/** Import job id */
|
|
771
|
+
id: string;
|
|
772
|
+
/** Job status */
|
|
773
|
+
status: BenchmarkImportStatus;
|
|
774
|
+
/** Catalog benchmark name the import creates or extends */
|
|
775
|
+
benchmarkName: string;
|
|
776
|
+
/** Version label of the imported version */
|
|
777
|
+
version: string;
|
|
778
|
+
/**
|
|
779
|
+
* Why the import failed, when status is "FAILED"; null otherwise.
|
|
780
|
+
*
|
|
781
|
+
* Named `failure` and NOT `error`, deliberately: `error` is the key the
|
|
782
|
+
* FAILURE envelope uses, so the obvious client idiom `if (body.error) throw`
|
|
783
|
+
* has to stay correct on a perfectly healthy read of a failed import.
|
|
784
|
+
*/
|
|
785
|
+
failure: BenchmarkImportFailure | null;
|
|
786
|
+
/** Number of tasks parsed, once counted */
|
|
787
|
+
taskCount?: number;
|
|
788
|
+
createdAt?: string;
|
|
789
|
+
updatedAt?: string;
|
|
790
|
+
}
|
|
791
|
+
/** Structured failure detail for a FAILED import. */
|
|
792
|
+
interface BenchmarkImportFailure {
|
|
793
|
+
/** Stable machine-readable cause; "import_failed" when none was recorded. */
|
|
794
|
+
code: string;
|
|
795
|
+
/** What went wrong, e.g. "2/113 task(s) failed to parse" */
|
|
796
|
+
message: string;
|
|
797
|
+
/** Per-task parse/validation failures, when the corpus was reachable */
|
|
798
|
+
failures?: {
|
|
799
|
+
taskKey: string;
|
|
800
|
+
error: string;
|
|
801
|
+
}[];
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* Where a custom harness's executables came from: a publicly fetchable install
|
|
805
|
+
* script run in a throwaway builder sandbox, or a tarball uploaded from a local
|
|
806
|
+
* directory. Echoed on every response; the SDK never guesses it.
|
|
807
|
+
*/
|
|
808
|
+
type CustomHarnessSource = "install_script" | "tarball";
|
|
809
|
+
/**
|
|
810
|
+
* A private harness registered by the caller. Once registered, its `name` is
|
|
811
|
+
* usable in `agents[].harness` exactly like a built-in ("claude",
|
|
812
|
+
* "codex", ...).
|
|
813
|
+
*
|
|
814
|
+
* Private to its owner: another user's name reads as
|
|
815
|
+
* `custom_harness_not_found`, never as a permission error — existence is never
|
|
816
|
+
* leaked.
|
|
817
|
+
*/
|
|
818
|
+
interface CustomHarness {
|
|
819
|
+
/** The harness name to put in agents[].harness */
|
|
820
|
+
name: string;
|
|
821
|
+
/** How the executables were produced */
|
|
822
|
+
source: CustomHarnessSource;
|
|
823
|
+
/** The command run headless with `sh -c` at the task working directory */
|
|
824
|
+
runCommand: string;
|
|
825
|
+
/**
|
|
826
|
+
* Caller-declared env injected at RUN time only. It may not override the run
|
|
827
|
+
* contract's own keys (see the docs) — the server rejects that at
|
|
828
|
+
* registration with `custom_harness_invalid_env`.
|
|
829
|
+
*/
|
|
830
|
+
env: Record<string, string>;
|
|
831
|
+
createdAt: string;
|
|
832
|
+
updatedAt: string;
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* The two sources a custom harness's executables can come from. A union, not
|
|
836
|
+
* two optional fields — see BenchmarkImportSource for why `?: never` is
|
|
837
|
+
* load-bearing rather than decorative.
|
|
838
|
+
*/
|
|
839
|
+
type CustomHarnessSourceInput = {
|
|
840
|
+
/**
|
|
841
|
+
* The install script itself (not a path). It runs in a throwaway builder
|
|
842
|
+
* sandbox that has internet and ZERO secrets, so everything it fetches
|
|
843
|
+
* must be publicly fetchable, and it must leave executables in
|
|
844
|
+
* `$PREFIX/bin`.
|
|
845
|
+
*/
|
|
846
|
+
installScript: string;
|
|
847
|
+
directory?: never;
|
|
848
|
+
} | {
|
|
849
|
+
/**
|
|
850
|
+
* A local directory holding the harness — tarred + gzipped and uploaded.
|
|
851
|
+
* Same build rules as an install script.
|
|
852
|
+
*/
|
|
853
|
+
directory: string;
|
|
854
|
+
installScript?: never;
|
|
855
|
+
};
|
|
856
|
+
/**
|
|
857
|
+
* Input for customHarnesses().create(): a name, a run command, and EXACTLY ONE
|
|
858
|
+
* source. The source half is a union, so omitting both or passing both is a
|
|
859
|
+
* compile error rather than a 400 the caller discovers at run time.
|
|
860
|
+
*/
|
|
861
|
+
type CustomHarnessInput = CustomHarnessSourceInput & {
|
|
862
|
+
/** Harness name; also the value used later in agents[].harness */
|
|
863
|
+
name: string;
|
|
864
|
+
/** Command run headless with `sh -c` at the task working directory */
|
|
865
|
+
runCommand: string;
|
|
866
|
+
/** Env injected at RUN time only; may not override the run contract's keys */
|
|
867
|
+
env?: Record<string, string>;
|
|
868
|
+
};
|
|
869
|
+
/** Options for jobs().run() and rerunFailed() */
|
|
870
|
+
interface RunJobOptions {
|
|
871
|
+
/**
|
|
872
|
+
* Idempotency-Key header value: retries with the same key return the
|
|
873
|
+
* original job (idempotentReplay: true) instead of creating a new one.
|
|
874
|
+
*/
|
|
875
|
+
idempotencyKey?: string;
|
|
876
|
+
}
|
|
877
|
+
/** Options for jobs().list() (default page 50, max 200) */
|
|
878
|
+
interface ListJobsOptions extends PageOptions {
|
|
879
|
+
}
|
|
880
|
+
/** Options for jobs().trials() (default page 50, max 200) */
|
|
881
|
+
interface ListTrialsOptions extends PageOptions {
|
|
882
|
+
/** Only trials in these statuses (e.g. the failures behind a rerun decision) */
|
|
883
|
+
status?: TrialStatus[];
|
|
884
|
+
}
|
|
885
|
+
/** Options for benchmarks().list() (default page 50, max 200) */
|
|
886
|
+
interface ListBenchmarksOptions extends PageOptions {
|
|
887
|
+
}
|
|
888
|
+
/** Options for customHarnesses().list() (default page 50, max 200) */
|
|
889
|
+
interface ListCustomHarnessesOptions extends PageOptions {
|
|
890
|
+
}
|
|
891
|
+
/** Options for benchmarks().get() / getActive(): pages the TASK list (default 200, max 500) */
|
|
892
|
+
interface GetBenchmarkOptions extends PageOptions {
|
|
893
|
+
}
|
|
894
|
+
/** Options for jobs().regradeJob(): pages the RESULT list (default 50, max 200) */
|
|
895
|
+
interface RegradeJobOptions extends PageOptions {
|
|
896
|
+
}
|
|
897
|
+
/** Options for jobs().listRegrades() (default page 50, max 200) */
|
|
898
|
+
interface ListRegradesOptions extends PageOptions {
|
|
899
|
+
/** Only regrades of this job (the SOURCE job's id) */
|
|
900
|
+
jobId?: string;
|
|
901
|
+
}
|
|
902
|
+
/** Cursor page of regrade jobs */
|
|
903
|
+
type RegradePage = Page<RegradeJob>;
|
|
904
|
+
/**
|
|
905
|
+
* The handle returned by jobs().listRegrades(). Both:
|
|
906
|
+
* - a promise for a single RegradePage — `await client.listRegrades()` returns
|
|
907
|
+
* one page; and
|
|
908
|
+
* - an async iterable — `for await (const regrade of client.listRegrades())`
|
|
909
|
+
* walks every regrade across cursor pages, fetching the next page for you.
|
|
910
|
+
*/
|
|
911
|
+
interface RegradeList extends Awaitable<RegradePage>, AsyncIterable<RegradeJob> {
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* Options for jobs().regrade() (per-job): narrow the set of
|
|
915
|
+
* source trials. A trial is regradable only if it recorded separate-mode verifier
|
|
916
|
+
* inputs; these filters further restrict that set.
|
|
917
|
+
*/
|
|
918
|
+
interface RegradeOptions {
|
|
919
|
+
/** Only regrade source trials in these statuses */
|
|
920
|
+
status?: TrialStatus[];
|
|
921
|
+
/** Only regrade source trials of this task */
|
|
922
|
+
taskKey?: string;
|
|
923
|
+
}
|
|
924
|
+
/** Options for jobs().trialTrace() and trialTraceEvents() */
|
|
925
|
+
interface TrialTraceOptions extends PageOptions {
|
|
926
|
+
/**
|
|
927
|
+
* Resume position: events with seq strictly greater than this cursor (omit =
|
|
928
|
+
* from the beginning). A trace cursor IS a seq, so to resume a poll later
|
|
929
|
+
* pass the last event's `seq` here as a string.
|
|
930
|
+
*/
|
|
931
|
+
cursor?: string;
|
|
932
|
+
/** Max events per page (server default: 200, max: 1000) */
|
|
933
|
+
limit?: number;
|
|
934
|
+
}
|
|
935
|
+
/** Options for benchmarks().watchImport() */
|
|
936
|
+
interface WatchImportOptions {
|
|
937
|
+
/** Called on every observed status change (including the first status seen) */
|
|
938
|
+
onStatus?: (benchmarkImport: BenchmarkImport) => void;
|
|
939
|
+
/** Abort the watch (rejects with the abort reason) */
|
|
940
|
+
signal?: AbortSignal;
|
|
941
|
+
/** Poll interval between getImport() calls (default: 2000ms) */
|
|
942
|
+
pollIntervalMs?: number;
|
|
943
|
+
}
|
|
944
|
+
/** Options for jobs().watch() */
|
|
945
|
+
interface WatchJobOptions {
|
|
946
|
+
/** Called for every event (replayed + live) */
|
|
947
|
+
onEvent?: (event: JobEvent) => void;
|
|
948
|
+
/** Abort the watch (rejects with the abort reason) */
|
|
949
|
+
signal?: AbortSignal;
|
|
950
|
+
/** Initial reconnect backoff (default: 1000ms; doubles up to maxReconnectDelayMs) */
|
|
951
|
+
reconnectDelayMs?: number;
|
|
952
|
+
/** Backoff ceiling (default: 30000ms) */
|
|
953
|
+
maxReconnectDelayMs?: number;
|
|
954
|
+
}
|
|
955
|
+
/** Options for jobs().export() */
|
|
956
|
+
interface ExportJobOptions {
|
|
957
|
+
/** Directory to save the archive into (returns the file path) */
|
|
958
|
+
to?: string;
|
|
959
|
+
/** Return the raw response stream instead of a Buffer */
|
|
960
|
+
stream?: boolean;
|
|
961
|
+
/**
|
|
962
|
+
* Export layout. Omit for the canonical research archive; "harbor" requests
|
|
963
|
+
* the Harbor job-layout bundle (?format=harbor on the export endpoint).
|
|
964
|
+
*/
|
|
965
|
+
format?: "harbor";
|
|
966
|
+
}
|
|
967
|
+
/** Client for the shared benchmark catalog */
|
|
968
|
+
interface BenchmarksClient {
|
|
969
|
+
/**
|
|
970
|
+
* List benchmarks with their active versions (cursor-paged). Await the
|
|
971
|
+
* result for one page, or `for await` it to walk the whole catalog.
|
|
972
|
+
*/
|
|
973
|
+
list(options?: ListBenchmarksOptions): BenchmarkList;
|
|
974
|
+
/**
|
|
975
|
+
* Get one benchmark: all versions + one page of the selected version's tasks.
|
|
976
|
+
* ref is "name" (active version's tasks) or "name@version"; { limit, cursor }
|
|
977
|
+
* page the tasks.
|
|
978
|
+
*/
|
|
979
|
+
get(ref: string, options?: GetBenchmarkOptions): Promise<Benchmark>;
|
|
980
|
+
/**
|
|
981
|
+
* Get a benchmark's active version resolved to a runnable shape: unlike
|
|
982
|
+
* get(), `version` and `tasks` are guaranteed present. Throws
|
|
983
|
+
* NoActiveVersionError when the benchmark has no active version. Use get()
|
|
984
|
+
* for the full multi-version detail with optional fields.
|
|
985
|
+
*/
|
|
986
|
+
getActive(name: string, options?: GetBenchmarkOptions): Promise<ActiveBenchmark>;
|
|
987
|
+
/**
|
|
988
|
+
* Start a benchmark import job from a git source pinned to a ref.
|
|
989
|
+
* Returns immediately; poll with getImport()/watchImport().
|
|
990
|
+
*/
|
|
991
|
+
import(input: BenchmarkImportInput): Promise<BenchmarkImport>;
|
|
992
|
+
/** Get an import job's status (error and taskCount when available) */
|
|
993
|
+
getImport(id: string): Promise<BenchmarkImport>;
|
|
994
|
+
/**
|
|
995
|
+
* Poll getImport() until the job reaches a terminal status ("IMPORTED" or
|
|
996
|
+
* "FAILED") and resolve with the final import.
|
|
997
|
+
*/
|
|
998
|
+
watchImport(id: string, options?: WatchImportOptions): Promise<BenchmarkImport>;
|
|
999
|
+
/**
|
|
1000
|
+
* List the caller's own imports, newest first (cursor-paged). This is how you
|
|
1001
|
+
* find an import again after losing the id that import() returned — without
|
|
1002
|
+
* it, closing a tab made a running import permanently unwatchable.
|
|
1003
|
+
*
|
|
1004
|
+
* Await for one page, or `for await` to walk them all. { status } filters on
|
|
1005
|
+
* the import vocabulary ("IMPORTING" | "IMPORTED" | "FAILED"); { benchmark }
|
|
1006
|
+
* narrows to one benchmark name.
|
|
1007
|
+
*/
|
|
1008
|
+
listImports(options?: ListImportsOptions): BenchmarkImportList;
|
|
1009
|
+
/**
|
|
1010
|
+
* Delete a benchmark you own, with every version, task, and archived
|
|
1011
|
+
* solution. Refused (benchmark_in_use) while any job still references it —
|
|
1012
|
+
* a benchmark is never deleted out from under a job that measured against it,
|
|
1013
|
+
* and `err.details.sampleJobIds` names the jobs blocking it. A platform
|
|
1014
|
+
* benchmark is refused with benchmark_not_owned; a name you cannot see is a
|
|
1015
|
+
* plain not-found.
|
|
1016
|
+
*/
|
|
1017
|
+
delete(name: string): Promise<void>;
|
|
1018
|
+
}
|
|
1019
|
+
/** Client for the caller's own private (bring-your-own) harnesses */
|
|
1020
|
+
interface CustomHarnessesClient {
|
|
1021
|
+
/**
|
|
1022
|
+
* Register a private harness. Provide either an install script
|
|
1023
|
+
* (`{ installScript }`) or a local directory (`{ directory }`), never both.
|
|
1024
|
+
* The name is then usable in `agents[].harness` like a built-in.
|
|
1025
|
+
*/
|
|
1026
|
+
create(input: CustomHarnessInput): Promise<CustomHarness>;
|
|
1027
|
+
/**
|
|
1028
|
+
* List the caller's registered custom harnesses (cursor-paged). Await the
|
|
1029
|
+
* result for one page, or `for await` it to walk them all.
|
|
1030
|
+
*/
|
|
1031
|
+
list(options?: ListCustomHarnessesOptions): CustomHarnessList;
|
|
1032
|
+
/** Get one custom harness by name */
|
|
1033
|
+
get(name: string): Promise<CustomHarness>;
|
|
1034
|
+
/** Delete a custom harness. Past jobs keep their recorded harness. */
|
|
1035
|
+
delete(name: string): Promise<void>;
|
|
1036
|
+
/**
|
|
1037
|
+
* Register or replace a harness in ONE call, under the name you give.
|
|
1038
|
+
*
|
|
1039
|
+
* Use this instead of delete()+create() to change an existing registration:
|
|
1040
|
+
* the pair leaves a window where the harness does not exist, and anything
|
|
1041
|
+
* naming it in that window fails for a change that was only ever meant to be
|
|
1042
|
+
* an edit. This is a full replacement, not a patch — every field comes from
|
|
1043
|
+
* this call, and an omitted `env` becomes empty.
|
|
1044
|
+
*/
|
|
1045
|
+
upsert(name: string, input: CustomHarnessUpsertInput): Promise<CustomHarness>;
|
|
1046
|
+
}
|
|
1047
|
+
/** Client for hosted jobs */
|
|
1048
|
+
interface JobsClient {
|
|
1049
|
+
/**
|
|
1050
|
+
* Create a job. benchmark may be a bare "name" (resolved to the
|
|
1051
|
+
* active READY version) or a pinned "name@version". Supports Idempotency-Key.
|
|
1052
|
+
*/
|
|
1053
|
+
run(input: JobInput, options?: RunJobOptions): Promise<Job>;
|
|
1054
|
+
/** Get one job */
|
|
1055
|
+
get(id: string): Promise<Job>;
|
|
1056
|
+
/**
|
|
1057
|
+
* List the caller's jobs, newest first (cursor-paged). Await the
|
|
1058
|
+
* result for one page, or `for await` it to walk every job across
|
|
1059
|
+
* cursor pages transparently.
|
|
1060
|
+
*/
|
|
1061
|
+
list(options?: ListJobsOptions): JobList;
|
|
1062
|
+
/**
|
|
1063
|
+
* List a job's trials (cursor-paged; { status } filters, e.g. to
|
|
1064
|
+
* the failed trials). Await the result for one page, or `for await` it to
|
|
1065
|
+
* walk every trial across cursor pages transparently.
|
|
1066
|
+
*/
|
|
1067
|
+
trials(id: string, options?: ListTrialsOptions): TrialList;
|
|
1068
|
+
/** Get one trial's full detail (untruncated failureDetail) */
|
|
1069
|
+
trial(id: string, trialId: string): Promise<TrialDetail>;
|
|
1070
|
+
/** Get one page of a trial's trace; resume with { cursor: page.nextCursor } */
|
|
1071
|
+
trialTrace(id: string, trialId: string, options?: TrialTraceOptions): Promise<TrialTracePage>;
|
|
1072
|
+
/**
|
|
1073
|
+
* Iterate a trial's trace events, fetching pages under the hood until
|
|
1074
|
+
* the currently available trace is drained. Resume later by passing the
|
|
1075
|
+
* last seen seq as { cursor }.
|
|
1076
|
+
*/
|
|
1077
|
+
trialTraceEvents(id: string, trialId: string, options?: TrialTraceOptions): AsyncIterableIterator<TrialTraceEvent>;
|
|
1078
|
+
/**
|
|
1079
|
+
* Watch a job's event stream (SSE). Replays from the beginning,
|
|
1080
|
+
* resumes with Last-Event-ID on reconnect (exponential backoff), and
|
|
1081
|
+
* finishes on the terminal event.
|
|
1082
|
+
*
|
|
1083
|
+
* The returned handle is dual-use: `await client.watch(id)` resolves with the
|
|
1084
|
+
* final Job, or `for await (const event of client.watch(id))` iterates
|
|
1085
|
+
* the events. The `onEvent` callback still fires in both forms.
|
|
1086
|
+
*/
|
|
1087
|
+
watch(id: string, options?: WatchJobOptions): JobWatch;
|
|
1088
|
+
/** Request cancellation. Idempotent; a terminal job is a no-op. */
|
|
1089
|
+
cancel(id: string): Promise<Job>;
|
|
1090
|
+
/**
|
|
1091
|
+
* Create a NEW linked job of only the failed (and never-dispatched)
|
|
1092
|
+
* trials of a terminal job. Supports Idempotency-Key.
|
|
1093
|
+
*/
|
|
1094
|
+
rerunFailed(id: string, options?: RunJobOptions): Promise<Job>;
|
|
1095
|
+
/**
|
|
1096
|
+
* Regrade a terminal job: re-run the verifier of every REGRADABLE trial
|
|
1097
|
+
* (settled separate-mode trials, which recorded their verifier inputs) against
|
|
1098
|
+
* those recorded inputs, in fresh separate verifier boxes. The agent phase is
|
|
1099
|
+
* never re-run and the source trials are never modified. `options` narrows the
|
|
1100
|
+
* set by status and/or task. Returns a new regrade job (one result per trial).
|
|
1101
|
+
*/
|
|
1102
|
+
regrade(id: string, options?: RegradeOptions): Promise<RegradeJob>;
|
|
1103
|
+
/**
|
|
1104
|
+
* Regrade one settled trial: re-run its verifier against its recorded
|
|
1105
|
+
* inputs in a fresh separate verifier box. Refused (regrade_source_ineligible)
|
|
1106
|
+
* for shared-mode or pre-persistence trials. Returns a regrade job with one
|
|
1107
|
+
* result.
|
|
1108
|
+
*/
|
|
1109
|
+
regradeTrial(id: string, trialId: string): Promise<RegradeJob>;
|
|
1110
|
+
/**
|
|
1111
|
+
* Read ONE regrade job by the REGRADE's id (the id returned by regrade() or
|
|
1112
|
+
* regradeTrial(), and echoed in their Location header) — with one page of its
|
|
1113
|
+
* per-trial results, their lineage and reward deltas.
|
|
1114
|
+
*
|
|
1115
|
+
* Renamed from regradeJob(). That name read as a verb, sat directly beside
|
|
1116
|
+
* regrade() which IS that verb, and took a parameter called jobId that was
|
|
1117
|
+
* not a job id — so the natural call, regradeJob(someJobId), compiled and
|
|
1118
|
+
* 404'd.
|
|
1119
|
+
*/
|
|
1120
|
+
getRegrade(regradeId: string, options?: RegradeJobOptions): Promise<RegradeJob>;
|
|
1121
|
+
/**
|
|
1122
|
+
* List the caller's regrade jobs, newest first (cursor-paged); { jobId }
|
|
1123
|
+
* narrows to the regrades OF ONE JOB — the question regradeJob(jobId) looked
|
|
1124
|
+
* like it answered and did not. Await for one page, or `for await` to walk
|
|
1125
|
+
* them all.
|
|
1126
|
+
*/
|
|
1127
|
+
listRegrades(options?: ListRegradesOptions): RegradeList;
|
|
1128
|
+
/**
|
|
1129
|
+
* Side-by-side comparison of 2-5 owned jobs: per-job
|
|
1130
|
+
* aggregates plus a per-task matrix with disagreement rows first.
|
|
1131
|
+
*/
|
|
1132
|
+
compare(ids: string[]): Promise<JobComparison>;
|
|
1133
|
+
/**
|
|
1134
|
+
* Download the full research archive (gzipped JSON) of a terminal
|
|
1135
|
+
* job. Default: Buffer. { to } saves to a directory and returns the
|
|
1136
|
+
* file path. { stream: true } returns the raw response stream.
|
|
1137
|
+
* { format: "harbor" } selects the Harbor job-layout bundle instead of the
|
|
1138
|
+
* canonical archive (composable with any of the delivery shapes).
|
|
1139
|
+
*/
|
|
1140
|
+
export(id: string, options?: {
|
|
1141
|
+
format?: "harbor";
|
|
1142
|
+
}): Promise<Buffer>;
|
|
1143
|
+
export(id: string, options: {
|
|
1144
|
+
to: string;
|
|
1145
|
+
format?: "harbor";
|
|
1146
|
+
}): Promise<string>;
|
|
1147
|
+
export(id: string, options: {
|
|
1148
|
+
stream: true;
|
|
1149
|
+
format?: "harbor";
|
|
1150
|
+
}): Promise<ReadableStream<Uint8Array>>;
|
|
1151
|
+
export(id: string, options?: ExportJobOptions): Promise<Buffer | string | ReadableStream<Uint8Array>>;
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Every error code the hosted API can return, as a closed list.
|
|
1155
|
+
*
|
|
1156
|
+
* This exists so a typo cannot compile. `err.code === "insufficient_creidts"`
|
|
1157
|
+
* used to typecheck (code was `string`) and then silently never match, which is
|
|
1158
|
+
* the worst shape a bug can take: the branch looks handled and never runs.
|
|
1159
|
+
*
|
|
1160
|
+
* It mirrors HOSTED_API_ERROR_CODES on the server and is published verbatim at
|
|
1161
|
+
* GET /api/meta as `errorCodes`. A server newer than this SDK may send a code
|
|
1162
|
+
* that is not listed here — `EvolveApiError.code` widens to string for exactly
|
|
1163
|
+
* that case, so an unknown code is still readable, just not narrowable.
|
|
1164
|
+
*/
|
|
1165
|
+
declare const HOSTED_ERROR_CODES: readonly ["missing_authorization", "invalid_api_key", "credential_service_unavailable", "rate_limited", "insufficient_credits", "invalid_json", "invalid_input", "invalid_limit", "invalid_status", "invalid_cursor", "invalid_after", "invalid_format", "invalid_ids", "invalid_multipart", "idempotency_key_reused", "benchmark_not_found", "benchmark_version_not_found", "benchmark_name_taken", "benchmark_in_use", "benchmark_not_owned", "no_active_version", "version_not_ready", "unknown_task_keys", "no_tasks", "custom_harness_not_found", "custom_harness_name_taken", "custom_harness_name_reserved", "custom_harness_invalid_name", "custom_harness_source_required", "custom_harness_source_conflict", "custom_harness_invalid_env", "custom_harness_too_large", "custom_harness_limit_reached", "harness_version_not_found", "job_too_large", "provider_unsupported", "job_not_found", "job_not_terminal", "no_failed_runs", "trial_not_found", "concurrent_update", "regrade_source_ineligible", "no_regradable_runs", "regrade_not_found", "import_not_found", "import_too_large", "invalid_archive", "internal_error"];
|
|
1166
|
+
/** One of the API's stable error codes. */
|
|
1167
|
+
type HostedErrorCode = (typeof HOSTED_ERROR_CODES)[number];
|
|
1168
|
+
/** True when `value` is a code this SDK version knows about (narrowing guard). */
|
|
1169
|
+
declare function isHostedErrorCode(value: unknown): value is HostedErrorCode;
|
|
1170
|
+
/** A closed vocabulary a client renders, with the members that end it. */
|
|
1171
|
+
interface StatusVocabulary {
|
|
1172
|
+
values: string[];
|
|
1173
|
+
/** Members after which nothing more happens — a watcher may stop here. */
|
|
1174
|
+
terminal: string[];
|
|
1175
|
+
description: string;
|
|
1176
|
+
}
|
|
1177
|
+
/** One model a harness can drive. */
|
|
1178
|
+
interface HarnessModel {
|
|
1179
|
+
alias: string;
|
|
1180
|
+
modelId: string;
|
|
1181
|
+
description: string | null;
|
|
1182
|
+
}
|
|
1183
|
+
/** One harness the platform can run. */
|
|
1184
|
+
interface HarnessCapability {
|
|
1185
|
+
name: string;
|
|
1186
|
+
/** false = registered but not runnable; `reason` says why. */
|
|
1187
|
+
runnable: boolean;
|
|
1188
|
+
reason: string | null;
|
|
1189
|
+
/**
|
|
1190
|
+
* What the local SDK would run if no model were named. The hosted API always
|
|
1191
|
+
* requires an explicit model, so this is a picker's pre-selection, not a
|
|
1192
|
+
* server-side default.
|
|
1193
|
+
*/
|
|
1194
|
+
defaultModel: string | null;
|
|
1195
|
+
models: HarnessModel[];
|
|
1196
|
+
/**
|
|
1197
|
+
* What this harness does with `agents[].reasoningEffort`: "level" = the value
|
|
1198
|
+
* reaches the CLI as one, "binary" = thinking on/off only (a level is refused
|
|
1199
|
+
* at creation), "none" = no effort input at all (any effort is refused). Grey
|
|
1200
|
+
* the control out instead of learning the refusal from a POST.
|
|
1201
|
+
*/
|
|
1202
|
+
effortSupport: "level" | "binary" | "none";
|
|
1203
|
+
/** Whether `agents[].harnessVersion` may pin this harness. */
|
|
1204
|
+
versionPinnable: boolean;
|
|
1205
|
+
/**
|
|
1206
|
+
* Newest published version, for a "your pin is out of date" badge. Null means
|
|
1207
|
+
* "not known right now", never "up to date".
|
|
1208
|
+
*/
|
|
1209
|
+
latestVersion: string | null;
|
|
1210
|
+
}
|
|
1211
|
+
/** One sandbox provider, its ceilings, and what it refuses. */
|
|
1212
|
+
interface ProviderCapability {
|
|
1213
|
+
name: string;
|
|
1214
|
+
default: boolean;
|
|
1215
|
+
sizing: {
|
|
1216
|
+
maxCpus: number;
|
|
1217
|
+
maxMemoryMb: number;
|
|
1218
|
+
maxStorageMb: number;
|
|
1219
|
+
storage: "sized" | "fixed";
|
|
1220
|
+
};
|
|
1221
|
+
refuses: {
|
|
1222
|
+
capability: string;
|
|
1223
|
+
reason: string;
|
|
1224
|
+
}[];
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* The capability document: everything a client would otherwise hardcode.
|
|
1228
|
+
*
|
|
1229
|
+
* Public and cacheable — no API key needed, so a signed-out page can populate
|
|
1230
|
+
* its own harness picker.
|
|
1231
|
+
*/
|
|
1232
|
+
interface CapabilityDocument {
|
|
1233
|
+
/** Bumped when a FIELD changes meaning, never when a value changes. */
|
|
1234
|
+
schemaVersion: number;
|
|
1235
|
+
harnesses: HarnessCapability[];
|
|
1236
|
+
customHarnesses: {
|
|
1237
|
+
namePattern: string;
|
|
1238
|
+
maxNameLength: number;
|
|
1239
|
+
maxRunCommandLength: number;
|
|
1240
|
+
maxInstallScriptLength: number;
|
|
1241
|
+
maxEnvEntries: number;
|
|
1242
|
+
maxPerUser: number;
|
|
1243
|
+
maxUploadBytes: number;
|
|
1244
|
+
/** Built-in names a registration may not reuse. */
|
|
1245
|
+
reservedNames: string[];
|
|
1246
|
+
/** Env keys the platform owns; declaring one is refused at registration. */
|
|
1247
|
+
reservedEnvKeys: string[];
|
|
1248
|
+
};
|
|
1249
|
+
sandboxProviders: ProviderCapability[];
|
|
1250
|
+
/** Constraints that hold on EVERY provider. */
|
|
1251
|
+
platformConstraints: {
|
|
1252
|
+
capability: string;
|
|
1253
|
+
reason: string;
|
|
1254
|
+
}[];
|
|
1255
|
+
networkModes: string[];
|
|
1256
|
+
statuses: {
|
|
1257
|
+
job: StatusVocabulary;
|
|
1258
|
+
trial: StatusVocabulary;
|
|
1259
|
+
import: StatusVocabulary;
|
|
1260
|
+
regradeJob: StatusVocabulary;
|
|
1261
|
+
regradeResult: StatusVocabulary;
|
|
1262
|
+
benchmarkVersion: StatusVocabulary;
|
|
1263
|
+
};
|
|
1264
|
+
limits: {
|
|
1265
|
+
job: {
|
|
1266
|
+
maxRunsPerTask: number;
|
|
1267
|
+
maxAgents: number;
|
|
1268
|
+
maxTrials: number;
|
|
1269
|
+
concurrency: {
|
|
1270
|
+
default: number;
|
|
1271
|
+
max: number;
|
|
1272
|
+
};
|
|
1273
|
+
defaultMaxTrialSpendUsd: number;
|
|
1274
|
+
defaultSandboxProvider: string;
|
|
1275
|
+
defaultSizing: {
|
|
1276
|
+
cpus: number;
|
|
1277
|
+
memoryMb: number;
|
|
1278
|
+
storageMb: number;
|
|
1279
|
+
};
|
|
1280
|
+
/** Every agent must name a model; the server applies no default. */
|
|
1281
|
+
modelRequired: boolean;
|
|
1282
|
+
/**
|
|
1283
|
+
* Phase wall-clocks a task INHERITS when its own config declares none —
|
|
1284
|
+
* a task that declares its own always wins, so these fill in rather than
|
|
1285
|
+
* cap. Published because nothing else here says how long a trial may run.
|
|
1286
|
+
*/
|
|
1287
|
+
defaultAgentTimeoutSec: number;
|
|
1288
|
+
defaultVerifierTimeoutSec: number;
|
|
1289
|
+
/** Values `agents[].reasoningEffort` accepts, and the one an omitted effort takes. */
|
|
1290
|
+
reasoningEfforts: string[];
|
|
1291
|
+
defaultReasoningEffort: string;
|
|
1292
|
+
};
|
|
1293
|
+
pagination: {
|
|
1294
|
+
collections: {
|
|
1295
|
+
default: number;
|
|
1296
|
+
max: number;
|
|
1297
|
+
};
|
|
1298
|
+
benchmarkTasks: {
|
|
1299
|
+
default: number;
|
|
1300
|
+
max: number;
|
|
1301
|
+
};
|
|
1302
|
+
regradeResults: {
|
|
1303
|
+
default: number;
|
|
1304
|
+
max: number;
|
|
1305
|
+
};
|
|
1306
|
+
};
|
|
1307
|
+
uploads: {
|
|
1308
|
+
benchmarkArchiveBytes: number;
|
|
1309
|
+
customHarnessTarballBytes: number;
|
|
1310
|
+
};
|
|
1311
|
+
benchmarkNames: {
|
|
1312
|
+
pattern: string;
|
|
1313
|
+
maxNameLength: number;
|
|
1314
|
+
maxVersionLength: number;
|
|
1315
|
+
maxGitUrlLength: number;
|
|
1316
|
+
maxGitRefLength: number;
|
|
1317
|
+
};
|
|
1318
|
+
/** How many items an error MESSAGE names before "and N more". */
|
|
1319
|
+
maxItemsNamedInErrorMessage: number;
|
|
1320
|
+
};
|
|
1321
|
+
errorCodes: string[];
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1324
|
+
* Where a benchmark's git source points now, versus what its active version was
|
|
1325
|
+
* built from. Null on a benchmark whose source cannot be re-resolved — an
|
|
1326
|
+
* uploaded corpus, a seeded one, or one imported before provenance was
|
|
1327
|
+
* recorded. Null is "nothing to watch", never "up to date".
|
|
1328
|
+
*/
|
|
1329
|
+
interface UpstreamStatus {
|
|
1330
|
+
/** The ref the active version was imported from. */
|
|
1331
|
+
ref: string;
|
|
1332
|
+
/** The commit the active version was built from. */
|
|
1333
|
+
currentCommit: string;
|
|
1334
|
+
/** Where the ref points upstream now; null when the last check failed. */
|
|
1335
|
+
latestCommit: string | null;
|
|
1336
|
+
/** True when upstream has moved off the built-from commit. Branch on this. */
|
|
1337
|
+
moved: boolean;
|
|
1338
|
+
/**
|
|
1339
|
+
* Always null today. Counting commits between two SHAs needs the commit
|
|
1340
|
+
* graph, i.e. a real fetch per benchmark per check; the watcher deliberately
|
|
1341
|
+
* only does a reference advertisement. Reserved so a host comparison API
|
|
1342
|
+
* could fill it later without a wire change.
|
|
1343
|
+
*/
|
|
1344
|
+
behindBy: number | null;
|
|
1345
|
+
/** When the cached answer was taken; null before the first check. */
|
|
1346
|
+
checkedAt: string | null;
|
|
1347
|
+
/** Why the last check failed. Show "could not check", not "up to date". */
|
|
1348
|
+
error: string | null;
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
export { type BenchmarkImportStatus as $, type Awaitable as A, type BenchmarksClient as B, type CustomHarnessesClient as C, type ComparisonAggregate as D, type EvalSandboxProvider as E, type ComparisonCell as F, type ComparisonCoverage as G, type HostedClientConfig as H, type ComparisonTaskRow as I, type JobsClient as J, type JobComparison as K, type ListImportsOptions as L, type ModelUsage as M, type RegradeResult as N, type RegradeStatus as O, type ProviderCapability as P, type RegradeJobStatus as Q, type RegradeJob as R, type StatusVocabulary as S, type Task as T, type UpstreamStatus as U, type VerifierMode as V, type RegradeFilter as W, type RegradeOptions as X, type BenchmarkImport as Y, type BenchmarkImportInput as Z, type BenchmarkImportSource as _, type CapabilityDocument as a, type BenchmarkImportFailure as a0, type CustomHarness as a1, type CustomHarnessInput as a2, type CustomHarnessSource as a3, type SpendSource as a4, type JobPage as a5, type JobList as a6, type TrialPage as a7, type TrialList as a8, type RunJobOptions as a9, type ListJobsOptions as aa, type ListTrialsOptions as ab, type TrialTraceOptions as ac, type WatchJobOptions as ad, type WatchImportOptions as ae, type ExportJobOptions as af, type HostedErrorCode as b, HOSTED_ERROR_CODES as c, type HarnessCapability as d, type HarnessModel as e, type BenchmarkImportList as f, type BenchmarkImportPage as g, type CustomHarnessUpsertInput as h, isHostedErrorCode as i, type Benchmark as j, type ActiveBenchmark as k, type BenchmarkVersion as l, type BenchmarkVersionState as m, type TaskProviderVerdict as n, type JobAgent as o, type JobInput as p, type Job as q, type JobStatus as r, type Trial as s, type TrialDetail as t, type TrialStatus as u, type TrialCounts as v, type TrialTraceEvent as w, type TrialTracePage as x, type JobEvent as y, type JobWatch as z };
|