@evolvingmachines/evolve 0.0.55-project-sable.20260916.db0bc0bb → 0.0.56
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/cli/index.cjs +32 -32
- package/dist/cli/index.js +27 -27
- package/package.json +4 -6
- package/skills/evolve/SKILL.md +4 -3
- package/skills/evolve-evals/SKILL.md +112 -0
- package/{docs-evals → skills/evolve-evals/references}/cli-reference/run.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/cli-reference/skills.mdx +4 -4
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/agents.mdx +2 -2
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/analyze.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/jobs.mdx +3 -3
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/models.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/sandboxes.mdx +2 -2
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/secrets.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/core-concepts/trial-outputs.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/getting-started/quick-start.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/index.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/sdk/python.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/sdk/typescript.mdx +1 -1
- package/{docs-evals → skills/evolve-evals/references}/sdk-reference/errors.mdx +2 -2
- package/{docs-evals → skills/evolve-evals/references}/sdk-reference/jobs.mdx +2 -2
- package/docs-agents/SKILL.md +0 -138
- package/docs-agents/index.md +0 -81
- package/docs-agents/python/01-getting-started.md +0 -511
- package/docs-agents/python/02-configuration.md +0 -855
- package/docs-agents/python/03-runtime.md +0 -899
- package/docs-agents/python/04-streaming.md +0 -451
- package/docs-agents/python/05-swarm-pipeline.md +0 -953
- package/docs-agents/python/index.md +0 -122
- package/docs-agents/typescript/01-getting-started.md +0 -494
- package/docs-agents/typescript/02-configuration.md +0 -841
- package/docs-agents/typescript/03-runtime.md +0 -864
- package/docs-agents/typescript/04-streaming.md +0 -478
- package/docs-agents/typescript/05-swarm-pipeline.md +0 -957
- package/docs-agents/typescript/index.md +0 -121
- package/docs-evals/SKILL.md +0 -112
- package/docs-evals/docs.json +0 -180
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/agent.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/analysis.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/analyze.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/auth.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/check.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/dataset.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/index.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/job.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/secrets.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/skill.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/trial.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/cli-reference/upload.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/check.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/datasets.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/index.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/skills.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/tasks.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/trials.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/core-concepts/upload.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/dashboard/checks.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/dashboard/datasets.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/dashboard/jobs.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/dashboard/traces.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/dashboard/trial-viewer.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/getting-started/installation.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/agents.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/analyses.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/auth.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/checks.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/datasets.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/index.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/meta.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/skills.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/trials.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/sdk-reference/types.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/snippets/global-options.mdx +0 -0
- /package/{docs-evals → skills/evolve-evals/references}/snippets/list-flags.mdx +0 -0
|
@@ -1,864 +0,0 @@
|
|
|
1
|
-
# Runtime
|
|
2
|
-
|
|
3
|
-
## Methods
|
|
4
|
-
|
|
5
|
-
`run()` and `executeCommand()` are async and return `AgentResponse`. `status()` is synchronous and returns `SessionStatus`. `interrupt()` returns `Promise<boolean>`.
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
type AgentResponse = {
|
|
9
|
-
sandboxId: string;
|
|
10
|
-
sessionId?: string; // Dashboard session ID for traces/replays, when known
|
|
11
|
-
browser?: { liveUrl: string }; // Live browser URL, when remote browser is configured
|
|
12
|
-
runId?: string; // UUID for cost attribution (present for run(), undefined for executeCommand())
|
|
13
|
-
exitCode: number;
|
|
14
|
-
stdout: string;
|
|
15
|
-
stderr: string;
|
|
16
|
-
checkpoint?: CheckpointInfo; // Present when .withStorage() configured and run succeeded
|
|
17
|
-
};
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
### run
|
|
21
|
-
|
|
22
|
-
Runs the agent with a given prompt.
|
|
23
|
-
|
|
24
|
-
```ts
|
|
25
|
-
const result = await evolve.run({
|
|
26
|
-
prompt: "Analyze the data and create a report",
|
|
27
|
-
timeoutMs: 15 * 60 * 1000, // (optional) Default 1 hour
|
|
28
|
-
background: false, // (optional) Run in background
|
|
29
|
-
from: "ckpt_abc123", // (optional) Restore from checkpoint ID or "latest"
|
|
30
|
-
checkpointComment: "after analysis", // (optional) Label for the auto-checkpoint
|
|
31
|
-
resume: false, // (optional) Force a fresh conversation
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
console.log(result.exitCode);
|
|
35
|
-
console.log(result.stdout);
|
|
36
|
-
console.log(result.checkpoint?.id); // Checkpoint ID (if .withStorage() configured)
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
- If `timeoutMs` is omitted the agent uses the TypeScript default of 3_600_000 ms (1 hour).
|
|
40
|
-
- If `background` is `true`, the call returns immediately with a start handshake (`exitCode: 0`), not final completion. Completion is delivered asynchronously via `lifecycle` events (`run_background_complete` or `run_background_failed`), or by polling `status()`.
|
|
41
|
-
- If `from` is set, the SDK restores a checkpoint into a fresh sandbox before running. Pass a checkpoint ID or `"latest"` to restore the most recent. Requires `.withStorage()`. Cannot be used with `.withSession()`.
|
|
42
|
-
- If `checkpointComment` is set, the auto-checkpoint created after a successful run is labeled with this string. Requires `.withStorage()`.
|
|
43
|
-
- Calling `run()` multiple times maintains the agent context / history.
|
|
44
|
-
- `resume` overrides that. Omitted, the first run in a sandbox starts a fresh conversation and every run after it continues the previous one (an attached `withSession()` sandbox counts as "has already run"). Pass `resume: false` to force a fresh conversation in a sandbox the agent has already worked in — the shape a sequence of INDEPENDENT tasks against one shared sandbox needs, where the environment should persist but the context should not. Pass `resume: true` only when a previous run really happened; asking a CLI to continue a session that does not exist is its own kind of error.
|
|
45
|
-
- Calling `run()` while another run or command is active throws immediately. Call `interrupt()` first or wait for the active operation to finish.
|
|
46
|
-
|
|
47
|
-
### executeCommand
|
|
48
|
-
|
|
49
|
-
Runs a direct shell command in the sandbox working directory.
|
|
50
|
-
|
|
51
|
-
```ts
|
|
52
|
-
// Run shell command directly in sandbox
|
|
53
|
-
const result = await evolve.executeCommand("pytest", {
|
|
54
|
-
timeoutMs: 10 * 60 * 1000, // (optional) Default 1 hour
|
|
55
|
-
background: false, // (optional) Run in background
|
|
56
|
-
});
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
- If `background` is `true`, returns a start handshake (`exitCode: 0`). Completion arrives via `lifecycle` events (`command_background_complete` or `command_background_failed`).
|
|
60
|
-
|
|
61
|
-
### Streaming Events
|
|
62
|
-
|
|
63
|
-
Subscribe to real-time output from `run()` and `executeCommand()`:
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
evolve.on("content", (event: OutputEvent) => {
|
|
67
|
-
console.log(event.update.sessionUpdate, event.update);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
evolve.on("lifecycle", (event: LifecycleEvent) => {
|
|
71
|
-
console.log(event.reason, event.sandbox, event.agent);
|
|
72
|
-
});
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
| Event | Type | Description |
|
|
76
|
-
|-------|------|-------------|
|
|
77
|
-
| `content` | `OutputEvent` | Parsed ACP-style events (text, tools, plans) |
|
|
78
|
-
| `lifecycle` | `LifecycleEvent` | Sandbox and agent state transitions |
|
|
79
|
-
| `stdout` | `string` | Raw JSONL output |
|
|
80
|
-
| `stderr` | `string` | Error output |
|
|
81
|
-
|
|
82
|
-
For full type definitions, all event interfaces, browser live view, replay, and UI integration examples, see [Streaming Events](./04-streaming.md).
|
|
83
|
-
|
|
84
|
-
### Upload: Local → Sandbox
|
|
85
|
-
|
|
86
|
-
**Format:** `{ "destination": content }` — directories created automatically
|
|
87
|
-
|
|
88
|
-
| Method | Destination |
|
|
89
|
-
|--------|-------------|
|
|
90
|
-
| `uploadContext()` | `/home/user/workspace/context/{path}` |
|
|
91
|
-
| `uploadFiles()` | `/home/user/workspace/{path}` |
|
|
92
|
-
|
|
93
|
-
```ts
|
|
94
|
-
// Single file
|
|
95
|
-
await evolve.uploadContext({ "spec.json": JSON.stringify(data) });
|
|
96
|
-
|
|
97
|
-
// Multiple files
|
|
98
|
-
await evolve.uploadFiles({
|
|
99
|
-
"scripts/setup.sh": "#!/bin/bash\necho hello",
|
|
100
|
-
"data/input.csv": csvBuffer,
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// From local directory (helper)
|
|
104
|
-
import { readLocalDir } from "@evolvingmachines/evolve";
|
|
105
|
-
await evolve.uploadContext(readLocalDir("./input", true));
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
> **Setup alternative:** `withContext()` and `withFiles()` use the same format but upload on first `run()` instead of immediately.
|
|
109
|
-
|
|
110
|
-
### Download: Sandbox → Local
|
|
111
|
-
|
|
112
|
-
**Flow:** `getOutputFiles()` → `saveLocalDir()`
|
|
113
|
-
|
|
114
|
-
```ts
|
|
115
|
-
// Return type
|
|
116
|
-
interface OutputResult<T = unknown> {
|
|
117
|
-
files: FileMap; // All files from output/ folder
|
|
118
|
-
data: T | null; // Parsed result.json (if schema was set via withSchema())
|
|
119
|
-
error?: string; // Validation error message (if schema validation failed)
|
|
120
|
-
rawData?: string; // Raw result.json content when parse/validation failed (for debugging)
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
```ts
|
|
125
|
-
import { z } from "zod";
|
|
126
|
-
import { saveLocalDir } from "@evolvingmachines/evolve";
|
|
127
|
-
|
|
128
|
-
const ResultSchema = z.object({
|
|
129
|
-
summary: z.string(),
|
|
130
|
-
score: z.number(),
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
const evolve = new Evolve()
|
|
134
|
-
.withAgent({...})
|
|
135
|
-
.withSchema(ResultSchema); // Agent will be prompted to write result.json
|
|
136
|
-
|
|
137
|
-
await evolve.run({ prompt: "Analyze and score the document" });
|
|
138
|
-
|
|
139
|
-
const output = await evolve.getOutputFiles(true); // recursive=true for nested dirs
|
|
140
|
-
|
|
141
|
-
// Access all three fields
|
|
142
|
-
saveLocalDir("./output", output.files); // Save files locally
|
|
143
|
-
console.log(output.data); // { summary: "...", score: 85 }
|
|
144
|
-
console.log(output.error); // undefined (or validation error message)
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
- **`files`** — `FileMap` of all files from `output/` folder
|
|
148
|
-
- **`data`** — Parsed `result.json` validated against schema (null if no schema or validation failed)
|
|
149
|
-
- **`error`** — Validation error message if schema validation failed (undefined otherwise)
|
|
150
|
-
|
|
151
|
-
Files created before the last `run()` or `executeCommand()` are filtered out.
|
|
152
|
-
|
|
153
|
-
`saveLocalDir()` confines every entry to the target directory: a name whose resolved path escapes it (`../`, absolute) throws instead of writing outside the directory you chose — file names come from sandbox output and are not trusted.
|
|
154
|
-
|
|
155
|
-
### Session Controls
|
|
156
|
-
|
|
157
|
-
```ts
|
|
158
|
-
const sessionId = evolve.getSession(); // Returns sandbox ID (string) or null (sync)
|
|
159
|
-
|
|
160
|
-
const status = evolve.status(); // Synchronous snapshot of sandbox + agent state
|
|
161
|
-
// status.sandbox → "stopped" | "booting" | "ready" | "running" | "paused" | "error"
|
|
162
|
-
// status.agent → "idle" | "running" | "interrupted" | "error"
|
|
163
|
-
// status.hasRun → boolean (true after first run)
|
|
164
|
-
// status.sandboxId → string | null
|
|
165
|
-
// status.activeProcessId → string | null
|
|
166
|
-
// status.timestamp → string (ISO 8601)
|
|
167
|
-
|
|
168
|
-
const ok = await evolve.interrupt(); // Interrupts active run() or executeCommand() process; sandbox stays alive. Returns true/false.
|
|
169
|
-
|
|
170
|
-
// Steer a running task: interrupt, then reprompt in same session.
|
|
171
|
-
// The next run() auto-continues conversation history/context for this sandbox session.
|
|
172
|
-
void evolve.run({ prompt: "Do a full migration plan", background: true });
|
|
173
|
-
await evolve.interrupt();
|
|
174
|
-
await evolve.run({ prompt: "Change direction: only auth migration." });
|
|
175
|
-
|
|
176
|
-
await evolve.pause(); // Suspends sandbox (stops billing, preserves state)
|
|
177
|
-
await evolve.resume(); // Reactivates same sandbox
|
|
178
|
-
|
|
179
|
-
await evolve.kill(); // Destroys sandbox; next run() creates a new sandbox
|
|
180
|
-
|
|
181
|
-
await evolve.setSession("existing-sandbox-id"); // Sets sandbox ID; reconnection happens on next run()
|
|
182
|
-
|
|
183
|
-
// Checkpointing (requires .withStorage())
|
|
184
|
-
const checkpt = await evolve.checkpoint({ comment: "before refactor" }); // Explicit snapshot of current sandbox
|
|
185
|
-
const list = await evolve.listCheckpoints({ limit: 10 }); // List checkpoints, newest first
|
|
186
|
-
const files = await evolve.storage().downloadFiles("latest", { glob: ["workspace/**/*.ts"] }); // Download specific files
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
`withSession("sandbox-id")` is a builder method for initialization—it sets the sandbox ID before the first `run()`. `setSession()` is a runtime method that actively interrupts any running process, flushes the session log, resets checkpoint lineage, and switches to the new sandbox. They are **not** interchangeable: use `withSession()` when building, `setSession()` when switching mid-session.
|
|
190
|
-
|
|
191
|
-
**Provider caveats:**
|
|
192
|
-
- **E2B / Daytona** — full support for `pause()`, `resume()`, `interrupt()`.
|
|
193
|
-
- **Modal** — does not support `pause()`. `interrupt()` is effectively unsupported and returns `false` for active processes.
|
|
194
|
-
|
|
195
|
-
### getHost
|
|
196
|
-
|
|
197
|
-
Expose a forwarded port:
|
|
198
|
-
|
|
199
|
-
```ts
|
|
200
|
-
const url = await evolve.getHost(8000);
|
|
201
|
-
console.log(`Workspace service available at ${url}`);
|
|
202
|
-
```
|
|
203
|
-
---
|
|
204
|
-
|
|
205
|
-
## Workspace & Structured Output
|
|
206
|
-
|
|
207
|
-
Calling `run` or `executeCommand` for the first time provisions a sandbox with the following filesystem:
|
|
208
|
-
|
|
209
|
-
```
|
|
210
|
-
/home/user/workspace/
|
|
211
|
-
├── context/ # Input files (read-only) provided by the user
|
|
212
|
-
├── scripts/ # Your code goes here
|
|
213
|
-
├── temp/ # Scratch space
|
|
214
|
-
├── output/ # Final deliverables
|
|
215
|
-
└── CLAUDE.md # System prompt (or AGENT.md, GEMINI.md, QWEN.md depending on agent)
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
Files passed to `context` are uploaded to `context/`. Files passed to `files` are uploaded relative to the working directory.
|
|
219
|
-
|
|
220
|
-
## Filesystem Instructions
|
|
221
|
-
Evolve writes a default filesystem instructions to the agent's config file in the workspace (`CLAUDE.md`, `AGENT.md`, `GEMINI.md`, or `QWEN.md`):
|
|
222
|
-
|
|
223
|
-
```
|
|
224
|
-
## FILESYSTEM INSTRUCTIONS
|
|
225
|
-
|
|
226
|
-
You are running in a sandbox environment.
|
|
227
|
-
|
|
228
|
-
Present working directory: /home/user/workspace/
|
|
229
|
-
|
|
230
|
-
IMPORTANT - Directory structure:
|
|
231
|
-
/home/user/workspace/
|
|
232
|
-
├── context/ # Input files (read-only) provided by the user
|
|
233
|
-
├── scripts/ # Your code goes here
|
|
234
|
-
├── temp/ # Scratch space
|
|
235
|
-
└── output/ # Final deliverables
|
|
236
|
-
|
|
237
|
-
## OUTPUT RESULTS (DELIVERABLES) MUST BE SAVED to `output/` as files.
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
Any string passed to `systemPrompt` is automatically appended to the agent's config file in the workspace (`CLAUDE.md`, `AGENT.md`, `GEMINI.md`, or `QWEN.md`) after this default.
|
|
241
|
-
|
|
242
|
-
## Structured Output
|
|
243
|
-
|
|
244
|
-
When you provide a `schema`, Evolve instructs the agent to write structured JSON output.
|
|
245
|
-
|
|
246
|
-
```ts
|
|
247
|
-
import { z } from "zod";
|
|
248
|
-
|
|
249
|
-
const CREDataSchema = z.object({
|
|
250
|
-
property_name: z.string(),
|
|
251
|
-
units: z.number(),
|
|
252
|
-
total_rent: z.number(),
|
|
253
|
-
occupancy_rate: z.number(),
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
const evolve = new Evolve()
|
|
257
|
-
.withSchema(CREDataSchema)
|
|
258
|
-
.withContext({
|
|
259
|
-
"rent_roll.pdf": fs.readFileSync("rent_roll.pdf"),
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
await evolve.run({ prompt: "Extract CRE data from the rent roll" });
|
|
263
|
-
|
|
264
|
-
const output = await evolve.getOutputFiles();
|
|
265
|
-
console.log(output.data); // { property_name: '...', units: 120, ... }
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
When a schema is provided, `getOutputFiles()` automatically validates `output/result.json` and returns `OutputResult<T>` (see [Download: Sandbox → Local](#download-sandbox--local)).
|
|
269
|
-
|
|
270
|
-
```ts
|
|
271
|
-
// Type-safe access to validated data
|
|
272
|
-
if (output.data) {
|
|
273
|
-
console.log(output.data.property_name); // TypeScript knows the shape
|
|
274
|
-
} else {
|
|
275
|
-
console.error(output.error); // "Schema validation failed: ..."
|
|
276
|
-
console.log(output.rawData); // Raw JSON for debugging
|
|
277
|
-
}
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
The SDK automatically appends the following to the agent's config file in the workspace (`CLAUDE.md`, `AGENT.md`, `GEMINI.md`, or `QWEN.md`):
|
|
281
|
-
|
|
282
|
-
~~~
|
|
283
|
-
## STRUCTURED OUTPUT
|
|
284
|
-
|
|
285
|
-
Your final result MUST be saved to `output/result.json` following this schema:
|
|
286
|
-
|
|
287
|
-
```json
|
|
288
|
-
{
|
|
289
|
-
"type": "object",
|
|
290
|
-
"properties": {
|
|
291
|
-
"property_name": { "type": "string" },
|
|
292
|
-
"units": { "type": "integer" },
|
|
293
|
-
"total_rent": { "type": "number" },
|
|
294
|
-
"occupancy_rate": { "type": "number" }
|
|
295
|
-
},
|
|
296
|
-
"required": ["property_name", "units", "total_rent", "occupancy_rate"]
|
|
297
|
-
}
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
You are free to:
|
|
301
|
-
- Reason through the problem step by step
|
|
302
|
-
- Read and analyze context files
|
|
303
|
-
- Use any available tools
|
|
304
|
-
- Process incrementally
|
|
305
|
-
- Create intermediate files in `temp/` or `scripts/`
|
|
306
|
-
|
|
307
|
-
But your final `output/result.json` MUST conform to the schema above.
|
|
308
|
-
|
|
309
|
-
### OUTPUT RESULTS (DELIVERABLES) MUST BE WRITTEN to `output/result.json` as files.
|
|
310
|
-
### Never just state results as text.
|
|
311
|
-
~~~
|
|
312
|
-
|
|
313
|
-
---
|
|
314
|
-
|
|
315
|
-
## Session Management
|
|
316
|
-
|
|
317
|
-
**Multi-turn conversations** (most common):
|
|
318
|
-
|
|
319
|
-
```ts
|
|
320
|
-
const evolve = new Evolve()
|
|
321
|
-
.withAgent({...});
|
|
322
|
-
|
|
323
|
-
await evolve.run({ prompt: 'Analyze data.csv' });
|
|
324
|
-
const output1 = await evolve.getOutputFiles();
|
|
325
|
-
|
|
326
|
-
// Still same session, automatically maintains context / history
|
|
327
|
-
await evolve.run({ prompt: 'Now create visualization' });
|
|
328
|
-
const output2 = await evolve.getOutputFiles();
|
|
329
|
-
|
|
330
|
-
// Still same session, automatically maintains context / history
|
|
331
|
-
await evolve.run({ prompt: 'Export to PDF' });
|
|
332
|
-
const output3 = await evolve.getOutputFiles();
|
|
333
|
-
|
|
334
|
-
await evolve.kill(); // When done
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
**Pause and resume** (same instance):
|
|
338
|
-
|
|
339
|
-
```ts
|
|
340
|
-
const evolve = new Evolve()
|
|
341
|
-
.withAgent({...});
|
|
342
|
-
|
|
343
|
-
await evolve.run({ prompt: 'Start analysis' });
|
|
344
|
-
await evolve.pause(); // Suspend billing, keep state
|
|
345
|
-
// Do other work...
|
|
346
|
-
await evolve.resume(); // Reactivate same sandbox
|
|
347
|
-
await evolve.run({ prompt: 'Continue analysis' }); // Session intact
|
|
348
|
-
|
|
349
|
-
await evolve.kill(); // Kill the Sandbox when done
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
**Save and reconnect** (different script/session):
|
|
353
|
-
|
|
354
|
-
```ts
|
|
355
|
-
// Script 1: Save session for later
|
|
356
|
-
const evolve = new Evolve()
|
|
357
|
-
.withAgent({...});
|
|
358
|
-
|
|
359
|
-
await evolve.run({ prompt: 'Start analysis' });
|
|
360
|
-
|
|
361
|
-
const sessionId = evolve.getSession();
|
|
362
|
-
// Save to file, database, environment variable, etc.
|
|
363
|
-
fs.writeFileSync('session.txt', sessionId);
|
|
364
|
-
|
|
365
|
-
// Script 2: Reconnect to saved session
|
|
366
|
-
const savedId = fs.readFileSync('session.txt', 'utf-8');
|
|
367
|
-
|
|
368
|
-
const evolve2 = new Evolve()
|
|
369
|
-
.withAgent({...})
|
|
370
|
-
.withSession(savedId); // Reconnect
|
|
371
|
-
|
|
372
|
-
await evolve2.run({ prompt: 'Continue analysis' }); // Session continues from Script 1
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
**Switch between sandboxes** (same instance):
|
|
376
|
-
|
|
377
|
-
```ts
|
|
378
|
-
const evolve = new Evolve()
|
|
379
|
-
.withAgent({...});
|
|
380
|
-
|
|
381
|
-
// Work with first sandbox
|
|
382
|
-
await evolve.run({ prompt: 'Analyze dataset A' });
|
|
383
|
-
const sessionA = evolve.getSession();
|
|
384
|
-
|
|
385
|
-
// Switch to different sandbox
|
|
386
|
-
await evolve.setSession('existing-sandbox-b-id');
|
|
387
|
-
await evolve.run({ prompt: 'Analyze dataset B' }); // Now working with sandbox B
|
|
388
|
-
|
|
389
|
-
// Switch back to first sandbox
|
|
390
|
-
await evolve.setSession(sessionA);
|
|
391
|
-
await evolve.run({ prompt: 'Compare results' }); // Back to sandbox A
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
---
|
|
395
|
-
|
|
396
|
-
## Storage & Checkpointing
|
|
397
|
-
|
|
398
|
-
> **Gateway feature** — requires `EVOLVE_API_KEY`. Storage is fully managed by Evolve; no S3 buckets or AWS credentials needed.
|
|
399
|
-
|
|
400
|
-
Persist sandbox state beyond sandbox lifetime. Checkpoints archive specific directories under `/home/user/` to Evolve-managed storage and can be restored into a fresh sandbox.
|
|
401
|
-
|
|
402
|
-
**What gets checkpointed:**
|
|
403
|
-
- `/home/user/workspace/` — your project files
|
|
404
|
-
- `/home/user/.<agent>/` — agent settings and session history (e.g. `.claude/`, `.codex/`, `.gemini/`, `.qwen/`, `.kimi-code/`, `.factory/`)
|
|
405
|
-
- For OpenCode: XDG directories (`~/.local/share/opencode/`, `~/.config/opencode/`, `~/.local/state/opencode/`)
|
|
406
|
-
- For Kimi Code: `.kimi-code/config.toml` is excluded because Evolve rewrites gateway credentials before each run; session history and MCP config are still included.
|
|
407
|
-
|
|
408
|
-
**Key properties:**
|
|
409
|
-
- **Auto-checkpoint:** Every successful `run()` with `.withStorage()` creates a checkpoint automatically.
|
|
410
|
-
- **Content-addressed dedup:** Archives are hashed (SHA-256). Same content = skip upload.
|
|
411
|
-
- **Lineage tracking:** Each checkpoint records its `parentId`, forming a chain across runs and restores.
|
|
412
|
-
|
|
413
|
-
### Configuration
|
|
414
|
-
|
|
415
|
-
```ts
|
|
416
|
-
const evolve = new Evolve()
|
|
417
|
-
.withAgent({ type: "claude" })
|
|
418
|
-
.withStorage(); // Uses EVOLVE_API_KEY from env
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
### Auto-Checkpoint (via `run()`)
|
|
422
|
-
|
|
423
|
-
Every successful foreground `run()` auto-creates a checkpoint:
|
|
424
|
-
|
|
425
|
-
```ts
|
|
426
|
-
const result = await evolve.run({
|
|
427
|
-
prompt: "Build the report",
|
|
428
|
-
checkpointComment: "initial draft",
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
console.log(result.checkpoint?.id); // "ckpt_m5abc_xyz123"
|
|
432
|
-
console.log(result.checkpoint?.hash); // SHA-256 of archive
|
|
433
|
-
console.log(result.checkpoint?.comment); // "initial draft"
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
**Behavior notes:**
|
|
437
|
-
|
|
438
|
-
- **Non-fatal:** Auto-checkpoint failures are logged but never cause `run()` to throw. The run result will have `checkpoint: undefined`.
|
|
439
|
-
- **Foreground only:** Background runs (via `run({ background: true })`) skip auto-checkpointing entirely.
|
|
440
|
-
- **Exclusions:** The archive excludes `node_modules/`, `__pycache__/`, `*.pyc`, `.cache/`, `.npm/`, `.pip/`, `.venv/`, `venv/`, and `{workspace}/temp/` to keep snapshots lean.
|
|
441
|
-
- **Dedup:** Archives are content-addressed by SHA-256 hash. If the hash matches an existing archive in storage, the upload is skipped—only the metadata entry is written.
|
|
442
|
-
- **`from: "latest"` edge case:** If no checkpoints exist globally (across all sessions/tags), `from: "latest"` throws an error. Note that `"latest"` resolves to the globally newest checkpoint, not scoped to the current session tag. Use `storage().listCheckpoints()` first to check availability.
|
|
443
|
-
|
|
444
|
-
### Explicit Checkpoint
|
|
445
|
-
|
|
446
|
-
Snapshot at any point (between runs, after manual setup, etc.):
|
|
447
|
-
|
|
448
|
-
```ts
|
|
449
|
-
const checkpt = await evolve.checkpoint({ comment: "before refactor" });
|
|
450
|
-
console.log(checkpt.id); // "ckpt_m5def_abc456"
|
|
451
|
-
```
|
|
452
|
-
|
|
453
|
-
Requires an active sandbox (`run()` must have been called first).
|
|
454
|
-
|
|
455
|
-
### Restore from Checkpoint
|
|
456
|
-
|
|
457
|
-
Pass `from` to `run()` to restore a checkpoint into a fresh sandbox before running:
|
|
458
|
-
|
|
459
|
-
```ts
|
|
460
|
-
const result = await evolve.run({
|
|
461
|
-
prompt: "Continue where we left off",
|
|
462
|
-
from: "ckpt_m5abc_xyz123",
|
|
463
|
-
});
|
|
464
|
-
|
|
465
|
-
// Or restore the most recent checkpoint
|
|
466
|
-
const latest = await evolve.run({
|
|
467
|
-
prompt: "Pick up from latest state",
|
|
468
|
-
from: "latest",
|
|
469
|
-
});
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
- `from` creates a fresh sandbox, downloads the archive, verifies hash integrity, and extracts it.
|
|
473
|
-
- Cannot be used with `.withSession()` (restore requires a fresh sandbox).
|
|
474
|
-
- The restored checkpoint becomes the `parentId` for the next checkpoint, maintaining lineage.
|
|
475
|
-
- Agent type and workspace mode must match the checkpoint (model changes are fine).
|
|
476
|
-
|
|
477
|
-
### Listing & Browsing Checkpoints
|
|
478
|
-
|
|
479
|
-
**Instance method:**
|
|
480
|
-
|
|
481
|
-
```ts
|
|
482
|
-
const checkpoints = await evolve.listCheckpoints({
|
|
483
|
-
limit: 10, // (optional) default: 100, max: 500
|
|
484
|
-
tag: "my-session-tag", // (optional) filter by session tag
|
|
485
|
-
});
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
**Standalone `storage()` client** (no Evolve instance needed):
|
|
489
|
-
|
|
490
|
-
```ts
|
|
491
|
-
import { storage } from "@evolvingmachines/evolve";
|
|
492
|
-
|
|
493
|
-
const store = storage(); // Uses EVOLVE_API_KEY from env
|
|
494
|
-
```
|
|
495
|
-
|
|
496
|
-
The `storage()` factory returns a `StorageClient` with four methods:
|
|
497
|
-
|
|
498
|
-
```ts
|
|
499
|
-
// List checkpoints (newest first)
|
|
500
|
-
const list = await store.listCheckpoints({ limit: 10, tag: "my-session" });
|
|
501
|
-
|
|
502
|
-
// Get a single checkpoint by ID
|
|
503
|
-
const info = await store.getCheckpoint("ckpt_m5abc_xyz123");
|
|
504
|
-
|
|
505
|
-
// Download full checkpoint archive to a local directory
|
|
506
|
-
const outputDir = await store.downloadCheckpoint("ckpt_m5abc_xyz123", {
|
|
507
|
-
to: "./restored", // (optional) default: cwd
|
|
508
|
-
extract: true, // (optional) default: true — set false to keep raw .tar.gz
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
// Download specific files without extracting the full archive
|
|
512
|
-
const files = await store.downloadFiles("ckpt_m5abc_xyz123", {
|
|
513
|
-
files: ["workspace/output/result.json"], // (optional) exact paths
|
|
514
|
-
glob: ["workspace/**/*.ts"], // (optional) glob patterns
|
|
515
|
-
to: "./output", // (optional) save to disk
|
|
516
|
-
});
|
|
517
|
-
// files is a Record<string, Buffer> — relative path → file contents
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
Pass `"latest"` instead of a checkpoint ID to any method to resolve the most recent checkpoint.
|
|
521
|
-
|
|
522
|
-
**Downloading folders with glob patterns:**
|
|
523
|
-
|
|
524
|
-
```ts
|
|
525
|
-
const output = await store.downloadFiles(id, { glob: ["workspace/output/**"] });
|
|
526
|
-
const all = await store.downloadFiles(id, { glob: ["workspace/**"] });
|
|
527
|
-
|
|
528
|
-
// Save directly to disk
|
|
529
|
-
await store.downloadFiles(id, { glob: ["workspace/output/**"], to: "./local-output" });
|
|
530
|
-
```
|
|
531
|
-
|
|
532
|
-
> **Paths are relative to `/home/user/`** — use `workspace/...` not `/home/user/workspace/...`.
|
|
533
|
-
|
|
534
|
-
**Instance-bound `storage()` accessor:**
|
|
535
|
-
|
|
536
|
-
When you already have an Evolve instance, `evolve.storage()` returns a `StorageClient` with credentials automatically bound:
|
|
537
|
-
|
|
538
|
-
```ts
|
|
539
|
-
const store = evolve.storage();
|
|
540
|
-
const files = await store.downloadFiles("latest", { glob: ["workspace/report.*"] });
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
### Checkpoint Lineage
|
|
544
|
-
|
|
545
|
-
Each checkpoint records `parentId`. Consecutive runs build a chain:
|
|
546
|
-
|
|
547
|
-
```ts
|
|
548
|
-
const r1 = await evolve.run({ prompt: "Step 1" });
|
|
549
|
-
// r1.checkpoint.parentId → undefined (first)
|
|
550
|
-
|
|
551
|
-
const r2 = await evolve.run({ prompt: "Step 2" });
|
|
552
|
-
// r2.checkpoint.parentId → r1.checkpoint.id
|
|
553
|
-
```
|
|
554
|
-
|
|
555
|
-
Restoring from a checkpoint branches the lineage:
|
|
556
|
-
|
|
557
|
-
```ts
|
|
558
|
-
const r4 = await evolve.run({ prompt: "Branch from step 1", from: r1.checkpoint.id });
|
|
559
|
-
// r4.checkpoint.parentId → r1.checkpoint.id (not r3)
|
|
560
|
-
```
|
|
561
|
-
|
|
562
|
-
### Type Reference
|
|
563
|
-
|
|
564
|
-
```ts
|
|
565
|
-
interface CheckpointInfo {
|
|
566
|
-
id: string; // Checkpoint ID — pass as `from` to restore
|
|
567
|
-
hash: string; // SHA-256 of tar.gz archive
|
|
568
|
-
tag: string; // Session tag at checkpoint time
|
|
569
|
-
timestamp: string; // ISO 8601
|
|
570
|
-
sizeBytes?: number; // Archive size in bytes
|
|
571
|
-
agentType?: string; // "claude" | "codex" | "gemini" | "qwen" | "kimi" | "opencode" | "droid"
|
|
572
|
-
model?: string; // Model used
|
|
573
|
-
workspaceMode?: string; // "knowledge" | "swe"
|
|
574
|
-
parentId?: string; // Parent checkpoint ID (lineage)
|
|
575
|
-
comment?: string; // User-provided label
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
interface StorageClient {
|
|
579
|
-
listCheckpoints(options?: { limit?: number; tag?: string }): Promise<CheckpointInfo[]>;
|
|
580
|
-
getCheckpoint(id: string): Promise<CheckpointInfo>;
|
|
581
|
-
downloadCheckpoint(idOrLatest: string, options?: DownloadCheckpointOptions): Promise<string>;
|
|
582
|
-
downloadFiles(idOrLatest: string, options?: DownloadFilesOptions): Promise<FileMap>;
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
interface DownloadCheckpointOptions {
|
|
586
|
-
to?: string; // Output directory (default: cwd)
|
|
587
|
-
extract?: boolean; // Extract archive (default: true)
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
interface DownloadFilesOptions {
|
|
591
|
-
files?: string[]; // Exact file paths to extract
|
|
592
|
-
glob?: string[]; // Glob patterns to match files
|
|
593
|
-
to?: string; // Save to disk (default: in-memory only)
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
type FileMap = Record<string, Buffer>; // relative path → file contents
|
|
597
|
-
```
|
|
598
|
-
|
|
599
|
-
### End-to-End Example
|
|
600
|
-
|
|
601
|
-
```ts
|
|
602
|
-
import { Evolve, storage } from "@evolvingmachines/evolve";
|
|
603
|
-
|
|
604
|
-
// 1. Create and checkpoint
|
|
605
|
-
const evolve = new Evolve()
|
|
606
|
-
.withAgent({ type: "claude" })
|
|
607
|
-
.withStorage();
|
|
608
|
-
|
|
609
|
-
const r1 = await evolve.run({
|
|
610
|
-
prompt: "Create a file called report.txt with 'Draft v1'",
|
|
611
|
-
checkpointComment: "initial draft",
|
|
612
|
-
});
|
|
613
|
-
console.log("Checkpoint 1:", r1.checkpoint?.id);
|
|
614
|
-
|
|
615
|
-
// 2. Second run — auto-chains parentId
|
|
616
|
-
const r2 = await evolve.run({
|
|
617
|
-
prompt: "Append ' - reviewed' to report.txt",
|
|
618
|
-
checkpointComment: "reviewed",
|
|
619
|
-
});
|
|
620
|
-
console.log("Parent:", r2.checkpoint?.parentId); // → r1.checkpoint.id
|
|
621
|
-
|
|
622
|
-
await evolve.kill();
|
|
623
|
-
|
|
624
|
-
// 3. Restore into fresh sandbox
|
|
625
|
-
const evolve2 = new Evolve()
|
|
626
|
-
.withAgent({ type: "claude" })
|
|
627
|
-
.withStorage();
|
|
628
|
-
|
|
629
|
-
const r3 = await evolve2.run({
|
|
630
|
-
prompt: "Read report.txt — what does it say?",
|
|
631
|
-
from: r1.checkpoint!.id,
|
|
632
|
-
});
|
|
633
|
-
// Agent sees "Draft v1" (not the reviewed version)
|
|
634
|
-
|
|
635
|
-
await evolve2.kill();
|
|
636
|
-
|
|
637
|
-
// 4. Browse checkpoints and download files (no Evolve instance needed)
|
|
638
|
-
const store = storage();
|
|
639
|
-
const all = await store.listCheckpoints();
|
|
640
|
-
console.log(`${all.length} checkpoints (newest first)`);
|
|
641
|
-
|
|
642
|
-
const files = await store.downloadFiles("latest", { glob: ["workspace/report.*"] });
|
|
643
|
-
for (const [path, content] of Object.entries(files)) {
|
|
644
|
-
console.log(`${path}: ${content.toString()}`);
|
|
645
|
-
}
|
|
646
|
-
```
|
|
647
|
-
|
|
648
|
-
---
|
|
649
|
-
|
|
650
|
-
## Observability
|
|
651
|
-
|
|
652
|
-
Full execution traces—including tool calls, file operations (read/write/edit), text responses, and reasoning chunks—are logged to your Evolve dashboard at **https://dashboard.evolvingmachines.ai/traces** for debugging and replay.
|
|
653
|
-
|
|
654
|
-
Additionally, every run and command is logged locally to structured JSON lines under `~/.evolve-sdk/observability/sessions`. File name format:
|
|
655
|
-
|
|
656
|
-
```
|
|
657
|
-
{tag}_{provider}_{sandboxId}_{agent}_{timestamp}.jsonl
|
|
658
|
-
```
|
|
659
|
-
|
|
660
|
-
- `{tag}` – `my-prefix-` + 16 random hex characters (e.g. `my-prefix-a1b2c3d4e5f6g7h8`)
|
|
661
|
-
- `{provider}` – the sandbox provider (e.g. `e2b`)
|
|
662
|
-
- `{sandboxId}` – the active sandbox ID
|
|
663
|
-
- `{agent}` – the agent type (`codex`, `claude`, `gemini`, `qwen`, `kimi`, `opencode`, `droid`)
|
|
664
|
-
- `{timestamp}` – ISO timestamp with `:` and `.` replaced by `-`
|
|
665
|
-
|
|
666
|
-
Each file contains three entry types:
|
|
667
|
-
|
|
668
|
-
```json
|
|
669
|
-
{"_meta":{"tag":"my-prefix-a1b2c3d4","provider":"e2b","agent":"qwen","model":"qwen-coder-plus-latest","sandbox_id":"sbx_123","timestamp":"2025-10-26T20:15:17.984Z"}}
|
|
670
|
-
{"_prompt":{"text":"hello how are you?"}}
|
|
671
|
-
{"jsonrpc":"2.0","method":"session/update", ...}
|
|
672
|
-
```
|
|
673
|
-
|
|
674
|
-
- `_meta` – exactly one line per file (sandbox, agent, timestamp)
|
|
675
|
-
- `_prompt` – one line per `run()` call with the prompt text
|
|
676
|
-
- Raw JSON – every streamed payload (ACP notifications, stdout, etc.)
|
|
677
|
-
|
|
678
|
-
Attach your own prefix to make logs easy to search:
|
|
679
|
-
|
|
680
|
-
```ts
|
|
681
|
-
const evolve = new Evolve()
|
|
682
|
-
.withAgent({...})
|
|
683
|
-
.withSessionTagPrefix("my-project");
|
|
684
|
-
|
|
685
|
-
await evolve.run({ prompt: "Kick off analysis" });
|
|
686
|
-
|
|
687
|
-
console.log(evolve.getSessionTag()); // "my-project-ab12cd34"
|
|
688
|
-
console.log(evolve.getSessionTimestamp()); // Timestamp for first log file
|
|
689
|
-
|
|
690
|
-
await evolve.kill(); // Destroys sandbox A
|
|
691
|
-
|
|
692
|
-
await evolve.run({ prompt: "Start fresh" }); // New sandbox → new log file
|
|
693
|
-
|
|
694
|
-
console.log(evolve.getSessionTag()); // "my-project-f56789cd"
|
|
695
|
-
console.log(evolve.getSessionTimestamp()); // Timestamp for second log file
|
|
696
|
-
```
|
|
697
|
-
|
|
698
|
-
- `kill()` or `setSession()` flushes the current log; the next `run()` starts a
|
|
699
|
-
fresh file with the new sandbox id.
|
|
700
|
-
- Long-running sessions (pause/resume or ACP auto-resume) keep appending to the
|
|
701
|
-
current file, so you always have the full timeline.
|
|
702
|
-
- Logging is buffered inside the SDK, so it never blocks streaming output.
|
|
703
|
-
|
|
704
|
-
Use the tag together with the sandbox id to correlate logs with files saved in
|
|
705
|
-
`/output/`.
|
|
706
|
-
|
|
707
|
-
### Historical Sessions & Trace Download
|
|
708
|
-
|
|
709
|
-
The standalone `sessions()` client queries past sessions and downloads full
|
|
710
|
-
trace files programmatically — the API equivalent of the dashboard traces page.
|
|
711
|
-
|
|
712
|
-
```ts
|
|
713
|
-
import { sessions } from "@evolvingmachines/evolve";
|
|
714
|
-
|
|
715
|
-
const session = sessions(); // uses EVOLVE_API_KEY
|
|
716
|
-
|
|
717
|
-
const page = await session.list({
|
|
718
|
-
limit: 10,
|
|
719
|
-
state: "ended",
|
|
720
|
-
agent: "claude",
|
|
721
|
-
tagPrefix: "my-proj",
|
|
722
|
-
sort: "cost",
|
|
723
|
-
});
|
|
724
|
-
const page2 = await session.list({ cursor: page.nextCursor });
|
|
725
|
-
const info = await session.get(page.items[0].id);
|
|
726
|
-
const events = await session.events(info.id, { since: 50 });
|
|
727
|
-
const { gatewayCalls, total } = await session.transcript(info.id);
|
|
728
|
-
const path = await session.download(info.id, { to: "./traces" });
|
|
729
|
-
const replay = await session.browserReplay(info.id);
|
|
730
|
-
```
|
|
731
|
-
|
|
732
|
-
- `list()` returns `SessionPage { items: SessionInfo[], nextCursor, hasMore }`
|
|
733
|
-
- `get()` returns `SessionInfo` with `sandboxId`, `runtimeStatus`, `cost`, `stepCount`, `toolStats`, etc. — plus `usage`, the one-home reading (spend so far + token breakdown from the same gateway records, `provisional` marking numbers that can still grow); it carries the same keys a trial's `usage` does, and `null` means the meter never answered.
|
|
734
|
-
- `events()` returns parsed JSONL objects; pass `since` for delta fetching
|
|
735
|
-
- `transcript()` is the same read whole: `SessionTranscript { session, events, total, gatewayCalls, storedAt? }` — `total` counts every stored event (the next delta's `since`), and `gatewayCalls` are the gateway meter's per-call lines (`GatewayUsageEvent`: `update.usage.promptTokens`, `completionTokens`, `cachedTokens`, `costUsd`), in time order, the same line a trial's trace carries; they ride beside `events`, never inside them, and are the only per-call tokens and money a client should show. `storedAt` is the server's write instant of each event's row, one per entry of `events` and index-aligned: present on every row-served page (an empty page carries an empty list), absent when the transcript was served from its file. It places the gateway meter's calls under the harness's steps for harnesses whose lines carry no clock of their own (codex, kimi, qwen); a reader that does not place calls needs nothing from it. The session's total stays on `session.usage` / `session.cost`.
|
|
736
|
-
- `download()` streams the raw `.jsonl` trace to disk and returns the file path
|
|
737
|
-
- The CLI wraps the same client headless: `evolve session list` (`--state live|ended`, `--agent`, `--tag-prefix`, paged with `--limit`/`--cursor`, `-q` for ids, `--json` for the page) and `evolve session show <id>`
|
|
738
|
-
- `browserReplay()` waits for the managed browser replay and returns `replayUrl` plus `downloadUrl`
|
|
739
|
-
- Use `replayUrl` in your UI for browser playback
|
|
740
|
-
- Use `downloadUrl` when users need the raw `.mp4` file
|
|
741
|
-
- `suggestedStartSeconds`, when present, is the recommended replay start time in seconds and is already applied to `replayUrl`; keep the raw download unchanged
|
|
742
|
-
- `sizeBytes` and `readyAt`, when present, describe the raw recording size and replay readiness time
|
|
743
|
-
- `status` is `"ready"` once the call returns
|
|
744
|
-
|
|
745
|
-
```ts
|
|
746
|
-
const replay = await session.browserReplay(info.id, {
|
|
747
|
-
timeoutMs: 600_000, // optional; default 10 minutes
|
|
748
|
-
intervalMs: 5_000, // optional; default 5 seconds
|
|
749
|
-
});
|
|
750
|
-
```
|
|
751
|
-
|
|
752
|
-
For the full browser setup, live-view, cleanup, and replay flow, see
|
|
753
|
-
[Configuration → Browser Automation](./02-configuration.md#browser-automation).
|
|
754
|
-
|
|
755
|
-
Gateway-only — requires `EVOLVE_API_KEY`. In Direct Provider Key Mode, traces remain
|
|
756
|
-
available as local JSONL files in `~/.evolve-sdk/observability/sessions/`.
|
|
757
|
-
|
|
758
|
-
---
|
|
759
|
-
|
|
760
|
-
## Cost Tracking
|
|
761
|
-
|
|
762
|
-
Query per-run and per-session LLM spend. Requires gateway mode (`EVOLVE_API_KEY`). Supported for Claude and Codex agents.
|
|
763
|
-
|
|
764
|
-
Cost data may take 5–60s to appear while the gateway finishes metering (typically under 30s).
|
|
765
|
-
|
|
766
|
-
```ts
|
|
767
|
-
import { Evolve } from "@evolvingmachines/evolve";
|
|
768
|
-
import { createE2BProvider } from "@evolvingmachines/e2b";
|
|
769
|
-
|
|
770
|
-
const evolve = new Evolve()
|
|
771
|
-
.withAgent({ type: "claude" })
|
|
772
|
-
.withSandbox(createE2BProvider());
|
|
773
|
-
|
|
774
|
-
// Each run() returns a runId for cost attribution
|
|
775
|
-
const r1 = await evolve.run({ prompt: "Analyze the data" });
|
|
776
|
-
const r2 = await evolve.run({ prompt: "Write tests" });
|
|
777
|
-
|
|
778
|
-
// Session cost — all runs
|
|
779
|
-
const session = await evolve.getSessionCost();
|
|
780
|
-
console.log(session.totalCost); // 0.42 (USD)
|
|
781
|
-
console.log(session.totalTokens); // { prompt: 5000, completion: 2000, cached: 3200 }
|
|
782
|
-
console.log(session.runs.length); // 2
|
|
783
|
-
|
|
784
|
-
// Run cost — by ID (single API call)
|
|
785
|
-
const cost = await evolve.getRunCost({ runId: r1.runId! });
|
|
786
|
-
console.log(cost.cost, cost.model, cost.requests);
|
|
787
|
-
|
|
788
|
-
// Run cost — by index (1-based, negative = from end)
|
|
789
|
-
const first = await evolve.getRunCost({ index: 1 });
|
|
790
|
-
const last = await evolve.getRunCost({ index: -1 });
|
|
791
|
-
|
|
792
|
-
// Works after kill() for the most recent session
|
|
793
|
-
await evolve.kill();
|
|
794
|
-
const finalCost = await evolve.getSessionCost();
|
|
795
|
-
```
|
|
796
|
-
|
|
797
|
-
After `kill()` followed by another `run()` cycle, the previous session's cost is no longer queryable.
|
|
798
|
-
|
|
799
|
-
### Types
|
|
800
|
-
|
|
801
|
-
```ts
|
|
802
|
-
interface RunCost {
|
|
803
|
-
runId: string; // Matches AgentResponse.runId
|
|
804
|
-
index: number; // 1-based chronological position
|
|
805
|
-
cost: number; // USD as billed to your Evolve account
|
|
806
|
-
tokens: { prompt: number; completion: number; cached?: number }; // prompt INCLUDES cached
|
|
807
|
-
model: string; // Last observed model for this run
|
|
808
|
-
requests: number; // Number of LLM API requests
|
|
809
|
-
asOf: string; // ISO timestamp of query
|
|
810
|
-
isComplete: boolean; // False if calls still batching (5–60s)
|
|
811
|
-
truncated: boolean; // True if spend logs were capped
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
interface SessionCost {
|
|
815
|
-
sessionTag: string; // Matches evolve.getSessionTag()
|
|
816
|
-
totalCost: number; // USD across all runs
|
|
817
|
-
totalTokens: { prompt: number; completion: number; cached?: number };
|
|
818
|
-
runs: RunCost[]; // Chronological order
|
|
819
|
-
asOf: string;
|
|
820
|
-
isComplete: boolean;
|
|
821
|
-
truncated: boolean;
|
|
822
|
-
}
|
|
823
|
-
```
|
|
824
|
-
|
|
825
|
-
---
|
|
826
|
-
|
|
827
|
-
## Error Handling
|
|
828
|
-
|
|
829
|
-
Common errors and how to handle them:
|
|
830
|
-
|
|
831
|
-
| Error | Cause | Fix |
|
|
832
|
-
|-------|-------|-----|
|
|
833
|
-
| `No API key configured` | No `EVOLVE_API_KEY` or provider key in env | Set `EVOLVE_API_KEY` or pass `apiKey`/`providerApiKey` to `.withAgent()` |
|
|
834
|
-
| `No sandbox provider configured` | No sandbox provider key in env | Set `E2B_API_KEY`, `MODAL_TOKEN_ID`+`SECRET`, or `DAYTONA_API_KEY` |
|
|
835
|
-
| `Evolve agent config: "model" is empty` | `.withAgent({ model: "" })` — an empty string is not a model id | Pass a model id, or drop `model` to take the agent's default |
|
|
836
|
-
| `run() requires a non-empty "prompt" string` | `run()` called without a prompt | Pass `run({ prompt: "..." })` |
|
|
837
|
-
| `Operation already active` | Calling `run()` while another run is in progress | `await evolve.interrupt()` first, or wait for the active operation |
|
|
838
|
-
| `Cannot use 'from' with existing session` | `run({ from: "..." })` with `.withSession()` | Checkpoint restore requires a fresh sandbox — remove `.withSession()` |
|
|
839
|
-
| `No checkpoints found` | `run({ from: "latest" })` with no prior checkpoints | Create a checkpoint first, or use `storage().listCheckpoints()` to verify |
|
|
840
|
-
| `Schema validation failed: ...` | Agent's `result.json` doesn't match schema | Check `output.rawData` for the actual output; refine your prompt or schema |
|
|
841
|
-
| `Storage requires EVOLVE_API_KEY` | `.withStorage()` without gateway credentials | Set `EVOLVE_API_KEY` in your environment |
|
|
842
|
-
| Timeout (exit code -1) | Agent exceeded `timeoutMs` | Increase `timeoutMs` or simplify the prompt |
|
|
843
|
-
|
|
844
|
-
```ts
|
|
845
|
-
// Handling schema validation errors
|
|
846
|
-
const output = await evolve.getOutputFiles();
|
|
847
|
-
if (output.error) {
|
|
848
|
-
console.error("Validation failed:", output.error);
|
|
849
|
-
console.log("Raw output:", output.rawData); // Agent's actual JSON for debugging
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
// Handling run errors
|
|
853
|
-
try {
|
|
854
|
-
const result = await evolve.run({ prompt: "..." });
|
|
855
|
-
if (result.exitCode !== 0) {
|
|
856
|
-
console.error("Agent failed:", result.stderr);
|
|
857
|
-
}
|
|
858
|
-
} catch (err) {
|
|
859
|
-
// Thrown for: no API key, no sandbox, operation conflict, restore failure
|
|
860
|
-
console.error(err.message);
|
|
861
|
-
}
|
|
862
|
-
```
|
|
863
|
-
|
|
864
|
-
---
|