@evolvingmachines/evolve 0.0.55-project-sable.20260916.db0bc0bb
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/LICENSE +201 -0
- package/README.md +25 -0
- package/dist/chunk-5GVMBEYI.js +11 -0
- package/dist/chunk-HQJI3HHU.js +1 -0
- package/dist/chunk-JS2UTK2I.js +427 -0
- package/dist/cli/index.cjs +73 -0
- package/dist/cli/index.d.cts +270 -0
- package/dist/cli/index.d.ts +270 -0
- package/dist/cli/index.js +54 -0
- package/dist/index.cjs +669 -0
- package/dist/index.d.cts +5023 -0
- package/dist/index.d.ts +5023 -0
- package/dist/index.js +230 -0
- package/dist/managed-modal-IJW62SSK.js +4 -0
- package/dist/resumable-HFSICSH3.js +1 -0
- package/dist/tar-GVC4KE52.js +1 -0
- package/dist/types-DlpTxdR_.d.cts +4777 -0
- package/dist/types-DlpTxdR_.d.ts +4777 -0
- package/dist/upload-KPYDMWFJ.js +1 -0
- package/docs-agents/SKILL.md +138 -0
- package/docs-agents/index.md +81 -0
- package/docs-agents/python/01-getting-started.md +511 -0
- package/docs-agents/python/02-configuration.md +855 -0
- package/docs-agents/python/03-runtime.md +899 -0
- package/docs-agents/python/04-streaming.md +451 -0
- package/docs-agents/python/05-swarm-pipeline.md +953 -0
- package/docs-agents/python/index.md +122 -0
- package/docs-agents/typescript/01-getting-started.md +494 -0
- package/docs-agents/typescript/02-configuration.md +841 -0
- package/docs-agents/typescript/03-runtime.md +864 -0
- package/docs-agents/typescript/04-streaming.md +478 -0
- package/docs-agents/typescript/05-swarm-pipeline.md +957 -0
- package/docs-agents/typescript/index.md +121 -0
- package/docs-evals/SKILL.md +112 -0
- package/docs-evals/cli-reference/agent.mdx +67 -0
- package/docs-evals/cli-reference/analysis.mdx +91 -0
- package/docs-evals/cli-reference/analyze.mdx +74 -0
- package/docs-evals/cli-reference/auth.mdx +60 -0
- package/docs-evals/cli-reference/check.mdx +146 -0
- package/docs-evals/cli-reference/dataset.mdx +133 -0
- package/docs-evals/cli-reference/index.mdx +108 -0
- package/docs-evals/cli-reference/job.mdx +239 -0
- package/docs-evals/cli-reference/run.mdx +196 -0
- package/docs-evals/cli-reference/secrets.mdx +95 -0
- package/docs-evals/cli-reference/skill.mdx +51 -0
- package/docs-evals/cli-reference/skills.mdx +81 -0
- package/docs-evals/cli-reference/trial.mdx +112 -0
- package/docs-evals/cli-reference/upload.mdx +36 -0
- package/docs-evals/core-concepts/agents.mdx +106 -0
- package/docs-evals/core-concepts/analyze.mdx +86 -0
- package/docs-evals/core-concepts/check.mdx +51 -0
- package/docs-evals/core-concepts/datasets.mdx +138 -0
- package/docs-evals/core-concepts/index.mdx +42 -0
- package/docs-evals/core-concepts/jobs.mdx +136 -0
- package/docs-evals/core-concepts/models.mdx +68 -0
- package/docs-evals/core-concepts/sandboxes.mdx +52 -0
- package/docs-evals/core-concepts/secrets.mdx +41 -0
- package/docs-evals/core-concepts/skills.mdx +42 -0
- package/docs-evals/core-concepts/tasks.mdx +216 -0
- package/docs-evals/core-concepts/trial-outputs.mdx +103 -0
- package/docs-evals/core-concepts/trials.mdx +103 -0
- package/docs-evals/core-concepts/upload.mdx +45 -0
- package/docs-evals/dashboard/checks.mdx +15 -0
- package/docs-evals/dashboard/datasets.mdx +24 -0
- package/docs-evals/dashboard/jobs.mdx +65 -0
- package/docs-evals/dashboard/traces.mdx +15 -0
- package/docs-evals/dashboard/trial-viewer.mdx +30 -0
- package/docs-evals/docs.json +180 -0
- package/docs-evals/getting-started/installation.mdx +56 -0
- package/docs-evals/getting-started/quick-start.mdx +85 -0
- package/docs-evals/index.mdx +36 -0
- package/docs-evals/sdk/python.mdx +139 -0
- package/docs-evals/sdk/typescript.mdx +141 -0
- package/docs-evals/sdk-reference/agents.mdx +105 -0
- package/docs-evals/sdk-reference/analyses.mdx +125 -0
- package/docs-evals/sdk-reference/auth.mdx +76 -0
- package/docs-evals/sdk-reference/checks.mdx +166 -0
- package/docs-evals/sdk-reference/datasets.mdx +305 -0
- package/docs-evals/sdk-reference/errors.mdx +199 -0
- package/docs-evals/sdk-reference/index.mdx +58 -0
- package/docs-evals/sdk-reference/jobs.mdx +731 -0
- package/docs-evals/sdk-reference/meta.mdx +52 -0
- package/docs-evals/sdk-reference/skills.mdx +68 -0
- package/docs-evals/sdk-reference/trials.mdx +232 -0
- package/docs-evals/sdk-reference/types.mdx +272 -0
- package/docs-evals/snippets/global-options.mdx +13 -0
- package/docs-evals/snippets/list-flags.mdx +23 -0
- package/harness-capabilities.json +430 -0
- package/hosted-error-codes.json +120 -0
- package/package.json +163 -0
- package/skills/create-adapter/SKILL.md +287 -0
- package/skills/create-task/SKILL.md +491 -0
- package/skills/evolve/SKILL.md +39 -0
- package/skills/publish/SKILL.md +142 -0
- package/skills/rewardkit/SKILL.md +330 -0
- package/spec/atif/README.md +45 -0
- package/spec/atif/trajectory.schema.json +865 -0
- package/spec/openapi.yaml +13447 -0
|
@@ -0,0 +1,731 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "jobs"
|
|
3
|
+
description: "Start, follow, and derive jobs."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`jobs()` returns the jobs client. Every job method takes a job id, and every derived run returns a new `Job`.
|
|
7
|
+
|
|
8
|
+
## start
|
|
9
|
+
|
|
10
|
+
<Tabs>
|
|
11
|
+
<Tab title="TypeScript">
|
|
12
|
+
```ts
|
|
13
|
+
start(
|
|
14
|
+
input: JobCreate,
|
|
15
|
+
options?: StartJobOptions,
|
|
16
|
+
): Promise<Job>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`JobCreate`: `datasets` (selectors: `name`, optional `version`, `task_names`, `exclude_task_names`, `n_tasks`), `agents` (arms: `name`, `model_name`, optional `version`, `reasoning_effort`, `kwargs`, `preset`, `skills`), and optional `job_name`, `n_attempts`, `n_concurrent_trials` (1 to 150), `max_trial_spend_usd`, `sandbox_provider`, `retry`, `analyze`, the five `*_timeout_multiplier` fields, `verifier_env` (`REWARDKIT_JUDGE` and `REWARDKIT_MODEL` only) and `secrets`. `agent_env` is in the shape but refused by the server.
|
|
20
|
+
|
|
21
|
+
The response is the [Job](/sdk-reference/types#job), with the resolved `max_trial_spend_usd`, `worst_case_spend_usd`, `retry`, `analyze` and multipliers. `options.idempotencyKey` makes a repeated call return the same job, with `idempotent_replay` true; a different request under a used key is refused with `idempotency_key_reused`.
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
const job = await jobs().start({
|
|
25
|
+
datasets: [{ name: "terminal-bench-4", version: "4.0", n_tasks: 5 }],
|
|
26
|
+
agents: [{ name: "codex", model_name: "gpt-5.5" }],
|
|
27
|
+
});
|
|
28
|
+
```
|
|
29
|
+
</Tab>
|
|
30
|
+
<Tab title="Python">
|
|
31
|
+
```python
|
|
32
|
+
async def start(
|
|
33
|
+
*,
|
|
34
|
+
datasets: List[DatasetSelector | dict],
|
|
35
|
+
agents: List[AgentArm | dict],
|
|
36
|
+
job_name=None,
|
|
37
|
+
n_attempts=None,
|
|
38
|
+
n_concurrent_trials=None,
|
|
39
|
+
max_trial_spend_usd=None,
|
|
40
|
+
sandbox_provider=None,
|
|
41
|
+
retry=None,
|
|
42
|
+
analyze=None,
|
|
43
|
+
timeout_multiplier=None,
|
|
44
|
+
agent_timeout_multiplier=None,
|
|
45
|
+
verifier_timeout_multiplier=None,
|
|
46
|
+
agent_setup_timeout_multiplier=None,
|
|
47
|
+
environment_build_timeout_multiplier=None,
|
|
48
|
+
agent_env=None,
|
|
49
|
+
verifier_env=None,
|
|
50
|
+
secrets=None,
|
|
51
|
+
idempotency_key=None,
|
|
52
|
+
) -> Job
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The same fields as TypeScript, as keyword arguments; `datasets` and `agents` take dicts or the `DatasetSelector` and `AgentArm` dataclasses, and `retry` is a `JobRetryConfigInput`. `idempotency_key` makes a repeated call return the same job, with `idempotent_replay` true; a different request under a used key is refused with `idempotency_key_reused`.
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
job = await jobs().start(
|
|
59
|
+
datasets=[{"name": "terminal-bench-4", "version": "4.0", "n_tasks": 5}],
|
|
60
|
+
agents=[{"name": "codex", "model_name": "gpt-5.5"}],
|
|
61
|
+
)
|
|
62
|
+
```
|
|
63
|
+
</Tab>
|
|
64
|
+
</Tabs>
|
|
65
|
+
|
|
66
|
+
## get
|
|
67
|
+
|
|
68
|
+
<Tabs>
|
|
69
|
+
<Tab title="TypeScript">
|
|
70
|
+
```ts
|
|
71
|
+
get(id: string): Promise<Job>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
One job in full.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
const job = await jobs().get("3e1f9a2c-…");
|
|
78
|
+
```
|
|
79
|
+
</Tab>
|
|
80
|
+
<Tab title="Python">
|
|
81
|
+
```python
|
|
82
|
+
async def get(id: str) -> Job
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
One job in full.
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
job = await jobs().get("3e1f9a2c-…")
|
|
89
|
+
```
|
|
90
|
+
</Tab>
|
|
91
|
+
</Tabs>
|
|
92
|
+
|
|
93
|
+
## list
|
|
94
|
+
|
|
95
|
+
<Tabs>
|
|
96
|
+
<Tab title="TypeScript">
|
|
97
|
+
```ts
|
|
98
|
+
list(options?: { search?: string; scope?: "my" | "shared"; limit?: number; cursor?: string }): JobList
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Your jobs, newest first. Await one page, or iterate every page.
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
for await (const job of jobs().list({ search: "nightly" })) {
|
|
105
|
+
console.log(job.id, job.status);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
</Tab>
|
|
109
|
+
<Tab title="Python">
|
|
110
|
+
```python
|
|
111
|
+
def list(
|
|
112
|
+
*,
|
|
113
|
+
search: Optional[str] = None,
|
|
114
|
+
scope: Optional[JobListScope] = None,
|
|
115
|
+
limit: Optional[int] = None,
|
|
116
|
+
cursor: Optional[str] = None,
|
|
117
|
+
)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Your jobs, newest first. Await one page, or iterate every page.
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
async for job in jobs().list(search="nightly"): print(job.id, job.status)
|
|
124
|
+
```
|
|
125
|
+
</Tab>
|
|
126
|
+
</Tabs>
|
|
127
|
+
|
|
128
|
+
## trials
|
|
129
|
+
|
|
130
|
+
<Tabs>
|
|
131
|
+
<Tab title="TypeScript">
|
|
132
|
+
```ts
|
|
133
|
+
trials(
|
|
134
|
+
id: string,
|
|
135
|
+
options?: { status?: TrialStatus[]; dataset?: string; limit?: number; cursor?: string },
|
|
136
|
+
): TrialList
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
A job's trials. `status` and `dataset` filter.
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
const failed = await jobs().trials(
|
|
143
|
+
job.id,
|
|
144
|
+
{ status: ["INFRASTRUCTURE_ERROR", "SCORING_ERROR"] },
|
|
145
|
+
);
|
|
146
|
+
```
|
|
147
|
+
</Tab>
|
|
148
|
+
<Tab title="Python">
|
|
149
|
+
```python
|
|
150
|
+
def trials(
|
|
151
|
+
id: str,
|
|
152
|
+
*,
|
|
153
|
+
status: Optional[List[str]] = None,
|
|
154
|
+
dataset: Optional[str] = None,
|
|
155
|
+
limit: Optional[int] = None,
|
|
156
|
+
cursor: Optional[str] = None,
|
|
157
|
+
)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
A job's trials. `status` and `dataset` filter.
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
failed = await jobs().trials(
|
|
164
|
+
job.id,
|
|
165
|
+
status=["INFRASTRUCTURE_ERROR", "SCORING_ERROR"],
|
|
166
|
+
)
|
|
167
|
+
```
|
|
168
|
+
</Tab>
|
|
169
|
+
</Tabs>
|
|
170
|
+
|
|
171
|
+
## tasks
|
|
172
|
+
|
|
173
|
+
<Tabs>
|
|
174
|
+
<Tab title="TypeScript">
|
|
175
|
+
```ts
|
|
176
|
+
tasks(
|
|
177
|
+
id: string,
|
|
178
|
+
options?: { limit?: number; cursor?: string },
|
|
179
|
+
): JobTaskRollupList
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
One row per task: its trial tally, mean reward and cost, the dataset it came from (`source`), and its latest quality check (`check`, null when never checked).
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
for await (const row of jobs().tasks(job.id)) {
|
|
186
|
+
console.log(row.task_name, row.mean_reward);
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
</Tab>
|
|
190
|
+
<Tab title="Python">
|
|
191
|
+
```python
|
|
192
|
+
def tasks(
|
|
193
|
+
id: str,
|
|
194
|
+
*,
|
|
195
|
+
limit: Optional[int] = None,
|
|
196
|
+
cursor: Optional[str] = None,
|
|
197
|
+
)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
One row per task: its trial tally, mean reward and cost, the dataset it came from (`source`), and its latest quality check (`check`, None when never checked).
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
async for row in jobs().tasks(job.id): print(row.task_name, row.mean_reward)
|
|
204
|
+
```
|
|
205
|
+
</Tab>
|
|
206
|
+
</Tabs>
|
|
207
|
+
|
|
208
|
+
## watch
|
|
209
|
+
|
|
210
|
+
<Tabs>
|
|
211
|
+
<Tab title="TypeScript">
|
|
212
|
+
```ts
|
|
213
|
+
watch(id: string, options?: { onEvent?: (event: JobEvent) => void; signal?: AbortSignal; reconnectDelayMs?: number; maxReconnectDelayMs?: number }): JobWatch
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The job's event stream. Await the handle for the final job, or iterate it for each event; one form per call, and `onEvent` fires in both. The stream replays from the beginning and reconnects on its own, backing off from `reconnectDelayMs` (default 1000) to `maxReconnectDelayMs` (default 30000). Every event type and payload is on [types](/sdk-reference/types#events); a `trial.settled` is not final while a `trial.retrying` can follow it.
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
const final = await jobs().watch(job.id);
|
|
220
|
+
```
|
|
221
|
+
</Tab>
|
|
222
|
+
<Tab title="Python">
|
|
223
|
+
```python
|
|
224
|
+
def watch(
|
|
225
|
+
id: str,
|
|
226
|
+
*,
|
|
227
|
+
on_event: Optional[Callable[[JobEvent], None]] = None,
|
|
228
|
+
timeout_s: Optional[float] = None,
|
|
229
|
+
reconnect_delay_s: float = 1.0,
|
|
230
|
+
max_reconnect_delay_s: float = MAX_WATCH_DELAY_SEC,
|
|
231
|
+
)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The job's event stream. Await the handle for the final job, or iterate it for each event; one form per call. The stream replays from the beginning and reconnects on its own, backing off from `reconnect_delay_s` to `max_reconnect_delay_s` (30 s). Every event type and payload is on [types](/sdk-reference/types#events); a `trial.settled` is not final while a `trial.retrying` can follow it.
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
final = await jobs().watch(job.id)
|
|
238
|
+
```
|
|
239
|
+
</Tab>
|
|
240
|
+
</Tabs>
|
|
241
|
+
|
|
242
|
+
## cancel
|
|
243
|
+
|
|
244
|
+
<Tabs>
|
|
245
|
+
<Tab title="TypeScript">
|
|
246
|
+
```ts
|
|
247
|
+
cancel(id: string): Promise<Job>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Request cancellation. A finished job is a no-op.
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
await jobs().cancel(job.id);
|
|
254
|
+
```
|
|
255
|
+
</Tab>
|
|
256
|
+
<Tab title="Python">
|
|
257
|
+
```python
|
|
258
|
+
async def cancel(id: str) -> Job
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Request cancellation. A finished job is a no-op.
|
|
262
|
+
|
|
263
|
+
```python
|
|
264
|
+
await jobs().cancel(job.id)
|
|
265
|
+
```
|
|
266
|
+
</Tab>
|
|
267
|
+
</Tabs>
|
|
268
|
+
|
|
269
|
+
## resume
|
|
270
|
+
|
|
271
|
+
<Tabs>
|
|
272
|
+
<Tab title="TypeScript">
|
|
273
|
+
```ts
|
|
274
|
+
resume(
|
|
275
|
+
id: string,
|
|
276
|
+
request?: { filter_error_types?: string[] },
|
|
277
|
+
options?: StartJobOptions,
|
|
278
|
+
): Promise<Job>
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
A new job over a finished job's failed or stopped trials; `source_jobs` records `action: "resume"`. The default set and the refusals are on [jobs](/core-concepts/jobs#derive-a-new-job). Supports `idempotencyKey`.
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
const next = await jobs().resume(
|
|
285
|
+
job.id,
|
|
286
|
+
{ filter_error_types: ["InfrastructureError"] },
|
|
287
|
+
);
|
|
288
|
+
```
|
|
289
|
+
</Tab>
|
|
290
|
+
<Tab title="Python">
|
|
291
|
+
```python
|
|
292
|
+
async def resume(
|
|
293
|
+
id: str,
|
|
294
|
+
*,
|
|
295
|
+
filter_error_types: Optional[List[str]] = None,
|
|
296
|
+
idempotency_key: Optional[str] = None,
|
|
297
|
+
) -> Job
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
A new job over a finished job's failed or stopped trials.
|
|
301
|
+
|
|
302
|
+
```python
|
|
303
|
+
next_job = await jobs().resume(
|
|
304
|
+
job.id,
|
|
305
|
+
filter_error_types=["InfrastructureError"],
|
|
306
|
+
)
|
|
307
|
+
```
|
|
308
|
+
</Tab>
|
|
309
|
+
</Tabs>
|
|
310
|
+
|
|
311
|
+
## retry
|
|
312
|
+
|
|
313
|
+
<Tabs>
|
|
314
|
+
<Tab title="TypeScript">
|
|
315
|
+
```ts
|
|
316
|
+
retry(
|
|
317
|
+
id: string,
|
|
318
|
+
request?: { trial_ids?: string[]; failed_only?: boolean },
|
|
319
|
+
options?: StartJobOptions,
|
|
320
|
+
): Promise<Job>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
A new job re-running selected trials: named ids, the failed ones, or all of them; `trial_ids` and `failed_only` together is refused. The named form works on a running job once every named trial has settled; the other two need a finished source. The rules are on [jobs](/core-concepts/jobs#derive-a-new-job).
|
|
324
|
+
|
|
325
|
+
```ts
|
|
326
|
+
const again = await jobs().retry(
|
|
327
|
+
job.id,
|
|
328
|
+
{ failed_only: true },
|
|
329
|
+
);
|
|
330
|
+
```
|
|
331
|
+
</Tab>
|
|
332
|
+
<Tab title="Python">
|
|
333
|
+
```python
|
|
334
|
+
async def retry(
|
|
335
|
+
id: str,
|
|
336
|
+
*,
|
|
337
|
+
trial_ids: Optional[List[str]] = None,
|
|
338
|
+
failed_only: Optional[bool] = None,
|
|
339
|
+
idempotency_key: Optional[str] = None,
|
|
340
|
+
) -> Job
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
A new job re-running selected trials: named ids, the failed ones, or all of them.
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
again = await jobs().retry(
|
|
347
|
+
job.id,
|
|
348
|
+
failed_only=True,
|
|
349
|
+
)
|
|
350
|
+
```
|
|
351
|
+
</Tab>
|
|
352
|
+
</Tabs>
|
|
353
|
+
|
|
354
|
+
## regrade
|
|
355
|
+
|
|
356
|
+
<Tabs>
|
|
357
|
+
<Tab title="TypeScript">
|
|
358
|
+
```ts
|
|
359
|
+
regrade(
|
|
360
|
+
id: string,
|
|
361
|
+
request?: { statuses?: TrialStatus[]; task_name?: string },
|
|
362
|
+
): Promise<Job>
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Verifier-only re-run of a finished job, in fresh separate verifier boxes under the recorded network policy. The result is a job with `is_regrade` true. Only settled separate-mode trials are eligible; `no_regradable_trials` when none are. See [jobs](/core-concepts/jobs#derive-a-new-job).
|
|
366
|
+
|
|
367
|
+
```ts
|
|
368
|
+
const regraded = await jobs().regrade(
|
|
369
|
+
job.id,
|
|
370
|
+
{ task_name: "tricky-task" },
|
|
371
|
+
);
|
|
372
|
+
```
|
|
373
|
+
</Tab>
|
|
374
|
+
<Tab title="Python">
|
|
375
|
+
```python
|
|
376
|
+
async def regrade(
|
|
377
|
+
id: str,
|
|
378
|
+
*,
|
|
379
|
+
statuses: Optional[List[str]] = None,
|
|
380
|
+
task_name: Optional[str] = None,
|
|
381
|
+
) -> Job
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Verifier-only re-run of a finished job. The result is a job.
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
regraded = await jobs().regrade(
|
|
388
|
+
job.id,
|
|
389
|
+
task_name="tricky-task",
|
|
390
|
+
)
|
|
391
|
+
```
|
|
392
|
+
</Tab>
|
|
393
|
+
</Tabs>
|
|
394
|
+
|
|
395
|
+
## analyze
|
|
396
|
+
|
|
397
|
+
<Tabs>
|
|
398
|
+
<Tab title="TypeScript">
|
|
399
|
+
```ts
|
|
400
|
+
analyze(
|
|
401
|
+
id: string,
|
|
402
|
+
request?: AnalyzeConfigInput,
|
|
403
|
+
): Promise<Job>
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Enqueue one trace analysis per trial and return at once with the job, its `stats.analysis.n_pending` counting the batch. `AnalyzeConfigInput`: `model_name`, `rubric`, `prompt`, `sandbox_provider`, `reasoning_effort`, `n_concurrent`, `passing`, `failing`, `n_trials`, all optional; `{}` is every default. Calling it again is the re-analysis path, one wave at a time. The same object on `start()` as `analyze` arms the embedded trigger.
|
|
407
|
+
|
|
408
|
+
```ts
|
|
409
|
+
await jobs().analyze(
|
|
410
|
+
job.id,
|
|
411
|
+
{
|
|
412
|
+
failing: true,
|
|
413
|
+
n_trials: 20,
|
|
414
|
+
},
|
|
415
|
+
);
|
|
416
|
+
```
|
|
417
|
+
</Tab>
|
|
418
|
+
<Tab title="Python">
|
|
419
|
+
```python
|
|
420
|
+
async def analyze(
|
|
421
|
+
id: str,
|
|
422
|
+
*,
|
|
423
|
+
model_name=None,
|
|
424
|
+
rubric: Optional[Rubric] = None,
|
|
425
|
+
prompt=None,
|
|
426
|
+
sandbox_provider=None,
|
|
427
|
+
reasoning_effort=None,
|
|
428
|
+
n_concurrent=None,
|
|
429
|
+
passing=None,
|
|
430
|
+
failing=None,
|
|
431
|
+
n_trials=None,
|
|
432
|
+
) -> Job
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
Enqueue one trace analysis per trial and return at once.
|
|
436
|
+
|
|
437
|
+
```python
|
|
438
|
+
await jobs().analyze(
|
|
439
|
+
job.id,
|
|
440
|
+
failing=True,
|
|
441
|
+
n_trials=20,
|
|
442
|
+
)
|
|
443
|
+
```
|
|
444
|
+
</Tab>
|
|
445
|
+
</Tabs>
|
|
446
|
+
|
|
447
|
+
## watchAnalysis
|
|
448
|
+
|
|
449
|
+
<Tabs>
|
|
450
|
+
<Tab title="TypeScript">
|
|
451
|
+
```ts
|
|
452
|
+
watchAnalysis(id: string, options?: { onStats?: (job: Job) => void; signal?: AbortSignal; pollIntervalMs?: number }): Promise<Job>
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
Poll until no analysis is pending, from `pollIntervalMs` (default 2000) doubling to 30 s while the tally stands still, `onStats` firing on every change. Resolves with the final job. A job that was never analyzed polls forever, so call it after `analyze()`. On a still-running job created with `analyze`, `n_pending` can touch 0 between trial settles, so the watch can return early.
|
|
456
|
+
|
|
457
|
+
```ts
|
|
458
|
+
const analyzed = await jobs().watchAnalysis(job.id);
|
|
459
|
+
```
|
|
460
|
+
</Tab>
|
|
461
|
+
<Tab title="Python">
|
|
462
|
+
```python
|
|
463
|
+
async def watch_analysis(
|
|
464
|
+
id: str,
|
|
465
|
+
*,
|
|
466
|
+
on_stats: Optional[Callable[[Job], None]] = None,
|
|
467
|
+
poll_interval_s: float = 2.0,
|
|
468
|
+
timeout_s: Optional[float] = None,
|
|
469
|
+
) -> Job
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
Poll until no analysis is pending. Resolves with the final job.
|
|
473
|
+
|
|
474
|
+
```python
|
|
475
|
+
analyzed = await jobs().watch_analysis(job.id)
|
|
476
|
+
```
|
|
477
|
+
</Tab>
|
|
478
|
+
</Tabs>
|
|
479
|
+
|
|
480
|
+
## compare
|
|
481
|
+
|
|
482
|
+
<Tabs>
|
|
483
|
+
<Tab title="TypeScript">
|
|
484
|
+
```ts
|
|
485
|
+
compare(ids: string[]): Promise<CompareResponse>
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
Two to ten jobs side by side: per-job aggregates and a per-task matrix, disagreement rows first. Means cover SCORED trials only, with `coverage` beside them. The shape is on [types](/sdk-reference/types#smaller-shapes).
|
|
489
|
+
|
|
490
|
+
```ts
|
|
491
|
+
const cmp = await jobs().compare([jobA.id, jobB.id]);
|
|
492
|
+
```
|
|
493
|
+
</Tab>
|
|
494
|
+
<Tab title="Python">
|
|
495
|
+
```python
|
|
496
|
+
async def compare(ids: List[str]) -> CompareResponse
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
Two to ten jobs side by side: per-job aggregates and a per-task matrix.
|
|
500
|
+
|
|
501
|
+
```python
|
|
502
|
+
cmp = await jobs().compare([job_a.id, job_b.id])
|
|
503
|
+
```
|
|
504
|
+
</Tab>
|
|
505
|
+
</Tabs>
|
|
506
|
+
|
|
507
|
+
## download
|
|
508
|
+
|
|
509
|
+
<Tabs>
|
|
510
|
+
<Tab title="TypeScript">
|
|
511
|
+
```ts
|
|
512
|
+
download(id: string): Promise<Buffer>
|
|
513
|
+
download(
|
|
514
|
+
id: string,
|
|
515
|
+
options: { to: string },
|
|
516
|
+
): Promise<string>
|
|
517
|
+
download(
|
|
518
|
+
id: string,
|
|
519
|
+
options: { stream: true },
|
|
520
|
+
): Promise<ReadableStream<Uint8Array>>
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
A finished job's results as one `.tar.gz` in the standard job layout: the bytes, the saved file's path, or a stream. The first two shapes are verified against the response's `Content-Length` and, when the server states one, its digest; `{ stream: true }` hands you the raw bytes to verify yourself.
|
|
524
|
+
|
|
525
|
+
```ts
|
|
526
|
+
const path = await jobs().download(
|
|
527
|
+
job.id,
|
|
528
|
+
{ to: "./results" },
|
|
529
|
+
);
|
|
530
|
+
```
|
|
531
|
+
</Tab>
|
|
532
|
+
<Tab title="Python">
|
|
533
|
+
```python
|
|
534
|
+
async def download(
|
|
535
|
+
id: str,
|
|
536
|
+
*,
|
|
537
|
+
to: Optional[str] = None,
|
|
538
|
+
)
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
A finished job's results as one `.tar.gz` in the standard job layout: the bytes, or with `to` the saved file's path.
|
|
542
|
+
|
|
543
|
+
```python
|
|
544
|
+
path = await jobs().download(
|
|
545
|
+
job.id,
|
|
546
|
+
to="./results",
|
|
547
|
+
)
|
|
548
|
+
```
|
|
549
|
+
</Tab>
|
|
550
|
+
</Tabs>
|
|
551
|
+
|
|
552
|
+
## upload
|
|
553
|
+
|
|
554
|
+
<Tabs>
|
|
555
|
+
<Tab title="TypeScript">
|
|
556
|
+
```ts
|
|
557
|
+
upload(source: string | { archive_url: string }, options?: { dataset?: string; onUploadProgress?: (sentBytes: number, totalBytes: number) => void; onRegistered?: (importId: string) => void }): Promise<JobImport>
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
Upload a job directory, its `.tar.gz`, or a public archive URL as a finished job. Returns the import record; follow it with `watchImport`. A large upload resumes after a dropped connection, and `onRegistered` hands you the import id as soon as it starts. A directory without `result.json` and `config.json` at its root is refused client-side.
|
|
561
|
+
|
|
562
|
+
```ts
|
|
563
|
+
const imp = await jobs().upload(
|
|
564
|
+
"./job-2026-08-27__12-00-00",
|
|
565
|
+
{ dataset: "terminal-bench-4@4.0" },
|
|
566
|
+
);
|
|
567
|
+
```
|
|
568
|
+
</Tab>
|
|
569
|
+
<Tab title="Python">
|
|
570
|
+
```python
|
|
571
|
+
async def upload(
|
|
572
|
+
dir_or_archive: Optional[str] = None,
|
|
573
|
+
*,
|
|
574
|
+
archive_url: Optional[str] = None,
|
|
575
|
+
dataset: Optional[str] = None,
|
|
576
|
+
on_upload_progress=None,
|
|
577
|
+
on_registered=None,
|
|
578
|
+
) -> JobImport
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
Upload a job directory, its `.tar.gz`, or a public archive URL as a finished job. Returns the import record.
|
|
582
|
+
|
|
583
|
+
```python
|
|
584
|
+
imp = await jobs().upload(
|
|
585
|
+
"./job-2026-08-27__12-00-00",
|
|
586
|
+
dataset="terminal-bench-4@4.0",
|
|
587
|
+
)
|
|
588
|
+
```
|
|
589
|
+
</Tab>
|
|
590
|
+
</Tabs>
|
|
591
|
+
|
|
592
|
+
## getImport, watchImport, listImports
|
|
593
|
+
|
|
594
|
+
<Tabs>
|
|
595
|
+
<Tab title="TypeScript">
|
|
596
|
+
```ts
|
|
597
|
+
getImport(id: string): Promise<JobImport>
|
|
598
|
+
watchImport(id: string, options?: { onStatus?: (jobImport: JobImport) => void; onProgress?: (progress: JobImportProgress, jobImport: JobImport) => void; pollIntervalMs?: number; signal?: AbortSignal }): Promise<JobImport>
|
|
599
|
+
listImports(options?: { status?: DatasetImportStatus; limit?: number; cursor?: string }): JobImportList
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
Read one upload, follow it until it settles, or list your uploads.
|
|
603
|
+
|
|
604
|
+
```ts
|
|
605
|
+
const done = await jobs().watchImport(imp.id);
|
|
606
|
+
```
|
|
607
|
+
</Tab>
|
|
608
|
+
<Tab title="Python">
|
|
609
|
+
```python
|
|
610
|
+
async def get_import(id: str) -> JobImport
|
|
611
|
+
async def watch_import(
|
|
612
|
+
id: str,
|
|
613
|
+
*,
|
|
614
|
+
on_status=None,
|
|
615
|
+
on_progress=None,
|
|
616
|
+
poll_interval_s: float = 2.0,
|
|
617
|
+
timeout_s: Optional[float] = None,
|
|
618
|
+
) -> JobImport
|
|
619
|
+
def list_imports(
|
|
620
|
+
*,
|
|
621
|
+
status: Optional[str] = None,
|
|
622
|
+
limit: Optional[int] = None,
|
|
623
|
+
cursor: Optional[str] = None,
|
|
624
|
+
)
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
Read one upload, follow it until it settles, or list your uploads.
|
|
628
|
+
|
|
629
|
+
```python
|
|
630
|
+
done = await jobs().watch_import(imp.id)
|
|
631
|
+
```
|
|
632
|
+
</Tab>
|
|
633
|
+
</Tabs>
|
|
634
|
+
|
|
635
|
+
## delete
|
|
636
|
+
|
|
637
|
+
<Tabs>
|
|
638
|
+
<Tab title="TypeScript">
|
|
639
|
+
```ts
|
|
640
|
+
delete(id: string): Promise<JobDeleteResult>
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
Permanently delete a job you created: its trials, traces, analyses and stored files. The receipt is `{ job_id, trials_deleted, analyses_deleted }`. The refusals are on [jobs](/core-concepts/jobs#stop-cancel-delete).
|
|
644
|
+
|
|
645
|
+
```ts
|
|
646
|
+
await jobs().delete(job.id);
|
|
647
|
+
```
|
|
648
|
+
</Tab>
|
|
649
|
+
<Tab title="Python">
|
|
650
|
+
```python
|
|
651
|
+
async def delete(id: str) -> JobDeleteResult
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
Permanently delete a job you created: its trials, traces, analyses and stored files.
|
|
655
|
+
|
|
656
|
+
```python
|
|
657
|
+
await jobs().delete(job.id)
|
|
658
|
+
```
|
|
659
|
+
</Tab>
|
|
660
|
+
</Tabs>
|
|
661
|
+
|
|
662
|
+
## grep
|
|
663
|
+
|
|
664
|
+
Search every trial's parsed trace in one pass. `q` is a case-insensitive regex over each event's type and content; a plain string is a plain substring. Items are per-trial groups with the exact `match_count` and the first five matching events, ordered by trial id; `limit` defaults to 50, at most 200. Keep paging while `hasMore` (`has_more` in Python) is true; a pattern too expensive to evaluate is refused with `invalid_input`.
|
|
665
|
+
|
|
666
|
+
<Tabs>
|
|
667
|
+
<Tab title="TypeScript">
|
|
668
|
+
```ts
|
|
669
|
+
grep(
|
|
670
|
+
id: string,
|
|
671
|
+
q: string,
|
|
672
|
+
options?: { type?: string; limit?: number; cursor?: string },
|
|
673
|
+
): Promise<JobGrepPage>
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
```ts
|
|
677
|
+
const hits = await jobs().grep(job.id, "permission denied");
|
|
678
|
+
```
|
|
679
|
+
</Tab>
|
|
680
|
+
<Tab title="Python">
|
|
681
|
+
```python
|
|
682
|
+
async def grep(
|
|
683
|
+
id: str,
|
|
684
|
+
q: str,
|
|
685
|
+
*,
|
|
686
|
+
type: Optional[str] = None,
|
|
687
|
+
cursor: Optional[str] = None,
|
|
688
|
+
limit: Optional[int] = None,
|
|
689
|
+
) -> JobGrepPage
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
```python
|
|
693
|
+
hits = await jobs().grep(job.id, "permission denied")
|
|
694
|
+
```
|
|
695
|
+
</Tab>
|
|
696
|
+
</Tabs>
|
|
697
|
+
|
|
698
|
+
## passAtK
|
|
699
|
+
|
|
700
|
+
<Tabs>
|
|
701
|
+
<Tab title="TypeScript">
|
|
702
|
+
```ts
|
|
703
|
+
import { passAtK } from "@evolvingmachines/evolve";
|
|
704
|
+
|
|
705
|
+
function passAtK(job: Job): { evals_key: string; points: { k: number; value: number }[] }[]
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
Reads `stats.evals[key].pass_at_k` off a job you already hold, as sorted numbers; no request is made. Groups that cannot answer are left out, so an empty array means the job has no pass@k to show.
|
|
709
|
+
|
|
710
|
+
```ts
|
|
711
|
+
for (const group of passAtK(job)) {
|
|
712
|
+
for (const point of group.points) console.log(group.evals_key, `pass@${point.k}`, point.value.toFixed(3));
|
|
713
|
+
}
|
|
714
|
+
```
|
|
715
|
+
</Tab>
|
|
716
|
+
<Tab title="Python">
|
|
717
|
+
```python
|
|
718
|
+
from evolve import pass_at_k
|
|
719
|
+
|
|
720
|
+
def pass_at_k(job: Job) -> List[PassAtKGroup]
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
Reads `stats["evals"][key]["pass_at_k"]` off a job you already hold, as sorted `PassAtKGroup(evals_key, points)` with `PassAtKPoint(k, value)`; no request is made. Groups that cannot answer are left out, so an empty list means the job has no pass@k to show.
|
|
724
|
+
|
|
725
|
+
```python
|
|
726
|
+
for group in pass_at_k(job):
|
|
727
|
+
for point in group.points:
|
|
728
|
+
print(group.evals_key, f"pass@{point.k}", f"{point.value:.3f}")
|
|
729
|
+
```
|
|
730
|
+
</Tab>
|
|
731
|
+
</Tabs>
|