@drej/agent 0.1.1 → 0.2.0

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/README.md ADDED
@@ -0,0 +1,331 @@
1
+ # @drej/agent
2
+
3
+ Run [Pi](https://pi.ai) coding agents inside isolated [drej](https://drej.dev) sandbox containers. Pi can read and write files, run shell commands, and execute scripts — streamed back through a simple TypeScript API.
4
+
5
+ ```bash
6
+ bun add @drej/agent
7
+ ```
8
+
9
+ **[Full documentation →](https://docs.drej.dev/docs/agent)**
10
+
11
+ ---
12
+
13
+ ## Quickstart
14
+
15
+ Create an agent spec (`agents/my-agent.json`):
16
+
17
+ ```json
18
+ {
19
+ "$schema": "https://registry.drej.dev/schema/agent-item.json",
20
+ "name": "my-agent",
21
+ "cli": "pi",
22
+ "model": "gemini-flash-latest",
23
+ "packages": ["python3"],
24
+ "env": { "GEMINI_API_KEY": "${GEMINI_API_KEY}" },
25
+ "resources": { "cpu": "1000m", "memory": "2Gi" }
26
+ }
27
+ ```
28
+
29
+ ```ts
30
+ import { Agent, textOnly } from "@drej/agent";
31
+
32
+ const agent = await Agent.load("./agents/my-agent.json");
33
+ try {
34
+ for await (const chunk of textOnly(agent.prompt("Write and run a Python hello world script."))) {
35
+ process.stdout.write(chunk);
36
+ }
37
+ } finally {
38
+ await agent.close();
39
+ }
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Agent spec
45
+
46
+ The spec JSON controls the agent's environment, model, and workspace setup.
47
+
48
+ | Field | Type | Description |
49
+ | ------------ | ------------------------ | --------------------------------------------------------------------- |
50
+ | `name` | `string` | Unique identifier, used as the sandbox session name |
51
+ | `cli` | `"pi"` | CLI to run (currently only `"pi"`) |
52
+ | `cliVersion` | `string?` | Pin to a specific Pi version, e.g. `"0.80.2"`. Defaults to latest. |
53
+ | `model` | `string?` | Model ID passed to Pi via `--model` |
54
+ | `provider` | `string?` | AI provider passed via `--provider`. Omit for direct Google API key. |
55
+ | `packages` | `string[]?` | APT packages to install before Pi. e.g. `["git", "python3"]` |
56
+ | `env` | `Record<string,string>?` | Env vars in the sandbox. Values may reference host env: `"${MY_KEY}"` |
57
+ | `resources` | `object?` | CPU/memory limits: `{ cpu: "1000m", memory: "2Gi" }` |
58
+ | `setup` | `SetupStep[]?` | Workspace setup steps (see below) |
59
+
60
+ ### Setup steps
61
+
62
+ `setup` runs bash commands after Pi CLI install, before the snapshot is taken. Changes to any step automatically invalidate the snapshot cache.
63
+
64
+ ```json
65
+ {
66
+ "name": "my-agent",
67
+ "cli": "pi",
68
+ "setup": [
69
+ { "name": "Create workspace", "run": "mkdir -p /workspace" },
70
+ { "name": "Install deps", "run": "npm install", "cwd": "/workspace" },
71
+ { "name": "Seed data", "run": "node scripts/seed.js", "cwd": "/workspace" }
72
+ ]
73
+ }
74
+ ```
75
+
76
+ Each step:
77
+
78
+ | Field | Type | Description |
79
+ | ------ | --------- | ----------------------------------------------------------------- |
80
+ | `name` | `string` | Human-readable label shown in logs and included in the setup hash |
81
+ | `run` | `string` | Bash command to execute |
82
+ | `cwd` | `string?` | Working directory. Runs as `cd <cwd> && <run>` |
83
+
84
+ ---
85
+
86
+ ## Snapshotting
87
+
88
+ On first load, `Agent.load()` installs the Pi CLI and any `setup` steps, then checkpoints the sandbox. Subsequent loads restore from that snapshot — skipping the install entirely.
89
+
90
+ ```
91
+ Load 1 (cold): sandbox → Pi install → setup steps → checkpoint → bridge ~50s
92
+ Load 2 (warm): snapshot restore → bridge ~5s
93
+ ```
94
+
95
+ The snapshot is invalidated automatically when `cli`, `cliVersion`, `packages`, or `setup` change.
96
+
97
+ ```ts
98
+ const agent = await Agent.load("./agents/my-agent.json");
99
+ console.log(agent.fromSnapshot); // false on first load, true after
100
+
101
+ // Force a full reinstall:
102
+ const agent = await Agent.load("./agents/my-agent.json", { rebuild: true });
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Streaming
108
+
109
+ `agent.prompt()` and `agent.bash()` return an `AgentStream` — an `AsyncIterable<AgentEvent>`:
110
+
111
+ ```ts
112
+ type AgentEvent =
113
+ | { type: "text"; text: string }
114
+ | { type: "tool_start"; toolCallId: string; toolName: string; args: unknown }
115
+ | { type: "tool_update"; toolCallId: string; toolName: string; partialResult: unknown }
116
+ | { type: "tool_end"; toolCallId: string; toolName: string; result: unknown; isError: boolean };
117
+ ```
118
+
119
+ Use `textOnly()` to filter to just the text chunks (equivalent to the old `PromptStream` behavior):
120
+
121
+ ```ts
122
+ import { Agent, textOnly } from "@drej/agent";
123
+
124
+ for await (const chunk of textOnly(agent.prompt("Summarise this repo."))) {
125
+ process.stdout.write(chunk);
126
+ }
127
+ ```
128
+
129
+ ### Tool call observability
130
+
131
+ Iterate the raw stream to see every tool Pi uses:
132
+
133
+ ```ts
134
+ for await (const ev of agent.prompt("Run /workspace/script.py with python3.")) {
135
+ switch (ev.type) {
136
+ case "text":
137
+ process.stdout.write(ev.text);
138
+ break;
139
+ case "tool_start":
140
+ console.log(`[tool] ${ev.toolName} args=${JSON.stringify(ev.args)}`);
141
+ break;
142
+ case "tool_end":
143
+ console.log(`[tool] ${ev.toolName} done isError=${ev.isError}`);
144
+ break;
145
+ }
146
+ }
147
+ ```
148
+
149
+ ---
150
+
151
+ ## API reference
152
+
153
+ ### Loading and lifecycle
154
+
155
+ #### `Agent.load(specPath, opts?)`
156
+
157
+ Load a spec, spin up a sandbox, install Pi, run setup steps, and return a ready `Agent`. Restores from snapshot on subsequent calls.
158
+
159
+ ```ts
160
+ const agent = await Agent.load("./agents/my-agent.json");
161
+ const agent = await Agent.load("./agents/my-agent.json", { rebuild: true });
162
+ ```
163
+
164
+ #### `Agent.resume(sandboxId, opts?)`
165
+
166
+ Reconnect to an existing sandbox after the host process has exited. Only restarts the bridge — Pi and the workspace are untouched.
167
+
168
+ ```ts
169
+ // Original process saved agent.sandboxId somewhere...
170
+ const agent = await Agent.resume(savedSandboxId);
171
+ // Or provide the spec explicitly:
172
+ const agent = await Agent.resume(savedSandboxId, { specPath: "./agents/my-agent.json" });
173
+ ```
174
+
175
+ #### `agent.close()`
176
+
177
+ Stop the sandbox container and release all resources. Always call in a `finally` block.
178
+
179
+ ---
180
+
181
+ ### Streaming
182
+
183
+ #### `agent.prompt(message, opts?)`
184
+
185
+ Send a message to Pi and stream the response as `AgentStream`.
186
+
187
+ ```ts
188
+ for await (const chunk of textOnly(agent.prompt("Explain this file."))) {
189
+ process.stdout.write(chunk);
190
+ }
191
+ ```
192
+
193
+ #### `agent.bash(command)`
194
+
195
+ Run a shell command inside Pi's working context and stream stdout as `AgentStream`.
196
+
197
+ ```ts
198
+ for await (const chunk of textOnly(agent.bash("ls -la /workspace"))) {
199
+ process.stdout.write(chunk);
200
+ }
201
+ ```
202
+
203
+ ---
204
+
205
+ ### Mid-flight control
206
+
207
+ #### `agent.steer(message)`
208
+
209
+ Redirect Pi's current response mid-flight. Pi acknowledges and adjusts.
210
+
211
+ ```ts
212
+ const stream = textOnly(agent.prompt("Write an essay on every sorting algorithm..."));
213
+ setTimeout(() => agent.steer("Stop — give me 3 bullet points instead."), 1500);
214
+ for await (const chunk of stream) process.stdout.write(chunk);
215
+ ```
216
+
217
+ #### `agent.followUp(message)`
218
+
219
+ Queue a message for Pi to process after it finishes the current task.
220
+
221
+ #### `agent.abort()`
222
+
223
+ Interrupt the current in-progress response immediately.
224
+
225
+ ---
226
+
227
+ ### Session management
228
+
229
+ #### `agent.newSession()`
230
+
231
+ Start a fresh Pi conversation, clearing all context. Filesystem and workspace are unchanged.
232
+
233
+ #### `agent.clone()`
234
+
235
+ Branch the current Pi session at the current position. Returns `{ cancelled: boolean }`.
236
+
237
+ #### `agent.fork(entryId)`
238
+
239
+ Branch from a specific message entry in the conversation history. Returns `{ text, cancelled }`.
240
+
241
+ #### `agent.switchSession(sessionPath)`
242
+
243
+ Switch Pi to a different session file on disk.
244
+
245
+ #### `agent.getMessages()`
246
+
247
+ Retrieve the full conversation history for the current session.
248
+
249
+ ```ts
250
+ const messages = await agent.getMessages();
251
+ console.log(messages.length, "messages");
252
+ ```
253
+
254
+ ---
255
+
256
+ ### Model control
257
+
258
+ #### `agent.setModel(provider, modelId)`
259
+
260
+ Switch Pi to a specific model. Returns the activated `PiModel`.
261
+
262
+ #### `agent.cycleModel()`
263
+
264
+ Cycle to the next configured model. Returns `{ model, thinkingLevel, isScoped }` or `null` if only one model is configured.
265
+
266
+ #### `agent.getAvailableModels()`
267
+
268
+ List all models available to Pi under the current provider configuration.
269
+
270
+ #### `agent.setThinkingLevel(level)`
271
+
272
+ Set Pi's reasoning level (`"low" | "medium" | "high"`). Only effective on models that support extended thinking.
273
+
274
+ #### `agent.cycleThinkingLevel()`
275
+
276
+ Cycle Pi's thinking level. Returns `{ level }` or `null` if the current model doesn't support thinking.
277
+
278
+ ---
279
+
280
+ ### Context management
281
+
282
+ #### `agent.setAutoCompaction(enabled)`
283
+
284
+ Enable or disable Pi's automatic context compaction.
285
+
286
+ #### `agent.compact(customInstructions?)`
287
+
288
+ Manually trigger Pi's context compaction. Returns `{ tokensBefore, estimatedTokensAfter }`.
289
+
290
+ ---
291
+
292
+ ### Environment and debugging
293
+
294
+ #### `agent.setEnv(vars)`
295
+
296
+ Set or update env vars in the running container. Restarts Pi so it picks up the new env.
297
+
298
+ ```ts
299
+ await agent.setEnv({ DATABASE_URL: "postgres://..." });
300
+ ```
301
+
302
+ #### `agent.getLogs()`
303
+
304
+ Retrieve recent bridge logs (ring-buffered, last 200 entries).
305
+
306
+ #### `agent.sandbox`
307
+
308
+ Direct access to the underlying `Sandbox` — run commands, read/write files, or inspect state independently of Pi.
309
+
310
+ ```ts
311
+ await agent.sandbox.writeFile("/workspace/input.txt", data);
312
+ const { stdout } = await agent.sandbox.exec("wc -l /workspace/input.txt");
313
+ const result = await agent.sandbox.readFile("/workspace/output.txt");
314
+ ```
315
+
316
+ ---
317
+
318
+ ## Properties
319
+
320
+ | Property | Type | Description |
321
+ | -------------------- | --------- | ---------------------------------------------- |
322
+ | `agent.sandboxId` | `string` | OpenSandbox container ID |
323
+ | `agent.name` | `string` | Agent name from the spec |
324
+ | `agent.sandbox` | `Sandbox` | Underlying drej `Sandbox` object |
325
+ | `agent.fromSnapshot` | `boolean` | `true` when restored from snapshot (fast path) |
326
+
327
+ ---
328
+
329
+ ## License
330
+
331
+ Apache 2.0
@@ -0,0 +1,341 @@
1
+ import { Sandbox } from "@drej/core";
2
+
3
+ //#region src/schema.d.ts
4
+ /**
5
+ * A single named setup step run inside the sandbox after Pi CLI install,
6
+ * before the snapshot is taken. The step is a bash shell command.
7
+ */
8
+ interface SetupStep {
9
+ /** Human-readable label shown in logs and included in the setup hash. */
10
+ name: string;
11
+ /** Shell command to run (bash). */
12
+ run: string;
13
+ /** If set, the command runs as `cd <cwd> && <run>`. */
14
+ cwd?: string;
15
+ }
16
+ /**
17
+ * JSON spec for an agent — typically loaded from an `agent.json` file on disk.
18
+ * Pass the path to `Agent.load(specPath)`.
19
+ *
20
+ * Environment variable references in `env` values are interpolated from
21
+ * `process.env` at load time: `"${MY_API_KEY}"` → `process.env.MY_API_KEY`.
22
+ */
23
+ interface AgentSpec {
24
+ $schema?: string;
25
+ /** Unique identifier for this agent. Used as the sandbox session name. */
26
+ name: string;
27
+ /** Human-readable display name. */
28
+ title?: string;
29
+ description?: string;
30
+ author?: string;
31
+ categories?: string[];
32
+ /** CLI to run inside the sandbox. Currently only `"pi"` is supported. */
33
+ cli: "pi";
34
+ /** Pin to a specific CLI version (e.g. `"0.80.2"`). Defaults to latest. */
35
+ cliVersion?: string;
36
+ /**
37
+ * AI provider passed to the CLI via `--provider`. For Pi with a direct Google
38
+ * API key, omit this (Pi defaults to the Google Generative AI endpoint).
39
+ */
40
+ provider?: string;
41
+ /**
42
+ * Model ID passed to the CLI via `--model`.
43
+ * For Pi 0.80.x with a free Google AI Studio key, use `"gemini-flash-latest"`
44
+ * (Pi's alias for gemini-3.5-flash via the direct Google Generative AI API).
45
+ */
46
+ model?: string;
47
+ /**
48
+ * APT packages to install in the sandbox before starting the CLI.
49
+ * Example: `["python3", "git"]`. `nodejs_22` and `nodejs` are silently ignored
50
+ * since the base image is `node:22`.
51
+ */
52
+ packages?: string[];
53
+ /**
54
+ * Environment variables available inside the sandbox.
55
+ * Values may reference host env vars: `{ GEMINI_API_KEY: "${GEMINI_API_KEY}" }`.
56
+ */
57
+ env?: Record<string, string>;
58
+ /**
59
+ * CPU/memory/GPU resource limits for the sandbox container.
60
+ * Falls back to defaults in `drej.config.json` if omitted.
61
+ */
62
+ resources?: {
63
+ cpu: string;
64
+ memory: string;
65
+ gpu?: string;
66
+ };
67
+ /** Arbitrary labels attached to the sandbox. */
68
+ metadata?: Record<string, string>;
69
+ /** Other agent specs to load as dependencies before this one. */
70
+ registryDependencies?: string[];
71
+ /**
72
+ * Setup steps run inside the sandbox after Pi CLI install, before the snapshot.
73
+ * Baked into the snapshot — any change to a step invalidates the cache automatically.
74
+ * Example: create directories, write seed files, install project dependencies.
75
+ */
76
+ setup?: SetupStep[];
77
+ }
78
+ declare function validateAgentSpec(data: unknown): AgentSpec;
79
+ //#endregion
80
+ //#region src/snapshots.d.ts
81
+ interface AgentSnapshotRecord {
82
+ specName: string;
83
+ setupHash: string;
84
+ /** OpenSandbox snapshot ID returned by `sb.checkpoint()`. Pass to `client.restoreSnapshot()`. */
85
+ snapshotId: string;
86
+ createdAt: number;
87
+ }
88
+ /**
89
+ * Hash of the fields that require re-installing the agent CLI:
90
+ * cli, cliVersion, and packages. Excludes env (hot-reloadable),
91
+ * model/provider (CLI flags only), and cosmetic fields.
92
+ */
93
+ declare function computeSetupHash(spec: AgentSpec): string;
94
+ /** Derive the agent-snapshots.json path from the ledger adapter path. */
95
+ declare function snapshotsPath(adapterPath: string): string;
96
+ /** File-backed store for agent snapshot records, keyed by specName + setupHash. */
97
+ declare class AgentSnapshotStore {
98
+ private readonly path;
99
+ constructor(path: string);
100
+ private _read;
101
+ private _write;
102
+ private _key;
103
+ get(specName: string, setupHash: string): Promise<AgentSnapshotRecord | null>;
104
+ save(record: AgentSnapshotRecord): Promise<void>;
105
+ /** Remove all snapshot records for the given spec name. */
106
+ delete(specName: string): Promise<void>;
107
+ list(): Promise<AgentSnapshotRecord[]>;
108
+ }
109
+ //#endregion
110
+ //#region src/types.d.ts
111
+ /**
112
+ * A single event emitted by an agent stream. Discriminated on `type`.
113
+ *
114
+ * - `text` — a chunk of Pi's text response (assistant prose)
115
+ * - `tool_start` — Pi started executing a tool (bash, file write, etc.)
116
+ * - `tool_update` — streaming progress from an in-flight tool execution
117
+ * - `tool_end` — a tool finished; `result` holds its output, `isError` whether it failed
118
+ */
119
+ type AgentEvent = {
120
+ type: "text";
121
+ text: string;
122
+ } | {
123
+ type: "tool_start";
124
+ toolCallId: string;
125
+ toolName: string;
126
+ args: unknown;
127
+ } | {
128
+ type: "tool_update";
129
+ toolCallId: string;
130
+ toolName: string;
131
+ partialResult: unknown;
132
+ } | {
133
+ type: "tool_end";
134
+ toolCallId: string;
135
+ toolName: string;
136
+ result: unknown;
137
+ isError: boolean;
138
+ };
139
+ /**
140
+ * Async iterable of structured agent events. Returned by `Agent.prompt()` and `Agent.bash()`.
141
+ *
142
+ * Use `textOnly()` to filter down to just the text chunks:
143
+ *
144
+ * ```ts
145
+ * for await (const chunk of textOnly(agent.prompt("Hello"))) {
146
+ * process.stdout.write(chunk);
147
+ * }
148
+ * ```
149
+ *
150
+ * Or iterate the full stream to observe tool calls:
151
+ *
152
+ * ```ts
153
+ * for await (const ev of agent.prompt("Build a widget")) {
154
+ * if (ev.type === "text") process.stdout.write(ev.text);
155
+ * else if (ev.type === "tool_start") console.log("Pi is running:", ev.toolName, ev.args);
156
+ * else if (ev.type === "tool_end") console.log("Tool done, isError:", ev.isError);
157
+ * }
158
+ * ```
159
+ */
160
+ type AgentStream = AsyncIterable<AgentEvent>;
161
+ /** Filter an `AgentStream` down to just text chunks. */
162
+ declare function textOnly(stream: AgentStream): AsyncIterable<string>;
163
+ /**
164
+ * @deprecated Use `AgentStream`. `PromptStream` will be removed in a future minor.
165
+ */
166
+ type PromptStream = AsyncIterable<string>;
167
+ /** A Pi model as returned by `getAvailableModels`, `setModel`, and `cycleModel`. */
168
+ interface PiModel {
169
+ id: string;
170
+ api: string;
171
+ [key: string]: unknown;
172
+ }
173
+ /** Thinking (reasoning) level supported by models that have extended thinking. */
174
+ type ThinkingLevel = "none" | "low" | "medium" | "high";
175
+ /** A single message in Pi's conversation history, as returned by `getMessages`. */
176
+ interface PiMessage {
177
+ role: "user" | "assistant";
178
+ [key: string]: unknown;
179
+ }
180
+ /** Result of a `compact` operation. */
181
+ interface CompactResult {
182
+ summary: string;
183
+ firstKeptEntryId: string;
184
+ tokensBefore: number;
185
+ estimatedTokensAfter: number;
186
+ }
187
+ //#endregion
188
+ //#region src/agent.d.ts
189
+ /**
190
+ * A live AI coding agent running inside an OpenSandbox container.
191
+ *
192
+ * Wraps a Pi CLI process (`pi --mode rpc --approve`) in an HTTP bridge so the
193
+ * host can send prompts and receive streamed responses over a stable API,
194
+ * while Pi manages its own tool use, file writes, and code execution inside the
195
+ * sandbox.
196
+ *
197
+ * Create an agent with `Agent.load(specPath)`. Always call `close()` when done
198
+ * to release the underlying sandbox container.
199
+ *
200
+ * @example
201
+ * ```ts
202
+ * import { Agent } from "@drej/agent";
203
+ *
204
+ * const agent = await Agent.load("./agents/my-agent.json");
205
+ * try {
206
+ * for await (const chunk of agent.prompt("Explain this codebase")) {
207
+ * process.stdout.write(chunk);
208
+ * }
209
+ * } finally {
210
+ * await agent.close();
211
+ * }
212
+ * ```
213
+ */
214
+ declare class Agent {
215
+ /** OpenSandbox container ID for this agent's sandbox. */
216
+ readonly sandboxId: string;
217
+ readonly name: string;
218
+ /**
219
+ * Direct access to the underlying `Sandbox` — full drej Sandbox API, bypasses Pi.
220
+ * Use this to read or write files, run shell commands, or inspect container state
221
+ * independently of the Pi conversation.
222
+ */
223
+ readonly sandbox: Sandbox;
224
+ /**
225
+ * `true` when this agent was loaded from a cached snapshot (fast path).
226
+ * `false` on the first load for a given spec, or after `{ rebuild: true }`.
227
+ */
228
+ readonly fromSnapshot: boolean;
229
+ private readonly _adapter;
230
+ private _env;
231
+ private constructor();
232
+ /**
233
+ * Load an agent spec from disk and return a fully initialised `Agent`.
234
+ *
235
+ * On first load the Pi CLI is installed inside a `node:22` sandbox, then
236
+ * the sandbox is checkpointed. Subsequent `load()` calls for the same spec
237
+ * restore from that snapshot — skipping the install and starting in ~3s instead
238
+ * of ~90s.
239
+ *
240
+ * Pass `{ rebuild: true }` to force a full reinstall (e.g. after changing
241
+ * the spec's `packages` or `cliVersion`).
242
+ *
243
+ * Logs timing for each phase to stdout via `[agent]` prefixed lines.
244
+ */
245
+ static load(specPath: string, opts?: {
246
+ rebuild?: boolean;
247
+ }): Promise<Agent>;
248
+ /**
249
+ * Reconnect to a previously-created agent whose host process has exited.
250
+ *
251
+ * The sandbox container must still be running. Pi and any installed packages
252
+ * are already present — only the bridge process needs to be restarted.
253
+ * Pi is started with `--continue` so it resumes the most recent session.
254
+ *
255
+ * @param sandboxId The sandbox ID returned by the original `Agent.load()`.
256
+ * @param opts.specPath Path to the agent spec JSON. If omitted, the ledger
257
+ * is queried for the sandbox name and the spec is loaded from
258
+ * `./agents/<name>.json`.
259
+ *
260
+ * @example
261
+ * ```ts
262
+ * // Original process:
263
+ * const agent = await Agent.load("./agents/hello-agent.json");
264
+ * console.log(agent.sandboxId); // save this
265
+ * // ... process exits ...
266
+ *
267
+ * // New process:
268
+ * const agent = await Agent.resume(savedSandboxId);
269
+ * for await (const chunk of agent.prompt("What did we discuss earlier?")) {
270
+ * process.stdout.write(chunk);
271
+ * }
272
+ * await agent.close();
273
+ * ```
274
+ */
275
+ static resume(sandboxId: string, opts?: {
276
+ specPath?: string;
277
+ }): Promise<Agent>;
278
+ /** Send a prompt to Pi and stream the response. Pi manages its own session context. */
279
+ prompt(message: string, opts?: {
280
+ streamingBehavior?: "steer" | "followUp";
281
+ }): AgentStream;
282
+ /** Run a shell command inside Pi's working context and stream stdout. */
283
+ bash(command: string): AgentStream;
284
+ /** Steer Pi's current response mid-flight. Waits for Pi's RPC acknowledgment. */
285
+ steer(message: string): Promise<void>;
286
+ /** Abort Pi's current operation. */
287
+ abort(): Promise<void>;
288
+ /** Queue a message to be sent to Pi after it finishes its current task. */
289
+ followUp(message: string): Promise<void>;
290
+ /** Start a fresh Pi session, clearing all prior context. */
291
+ newSession(): Promise<void>;
292
+ /** Set Pi's reasoning level (for models that support extended thinking). */
293
+ setThinkingLevel(level: ThinkingLevel): Promise<void>;
294
+ /** Enable or disable Pi's automatic context compaction. */
295
+ setAutoCompaction(enabled: boolean): Promise<void>;
296
+ /**
297
+ * Fork Pi's session at the given entry ID, creating a new branch.
298
+ * Returns the text of the forked message and whether the fork was cancelled.
299
+ */
300
+ fork(entryId: string): Promise<{
301
+ text: string;
302
+ cancelled: boolean;
303
+ }>;
304
+ /** Clone the current Pi session into a new branch at the current position. */
305
+ clone(): Promise<{
306
+ cancelled: boolean;
307
+ }>;
308
+ /** Switch Pi to a different session file on disk. */
309
+ switchSession(sessionPath: string): Promise<{
310
+ cancelled: boolean;
311
+ }>;
312
+ /** Switch Pi to a specific model. Returns the activated model. */
313
+ setModel(provider: string, modelId: string): Promise<PiModel>;
314
+ /** Cycle Pi to the next available model. Returns null if only one model is configured. */
315
+ cycleModel(): Promise<{
316
+ model: PiModel;
317
+ thinkingLevel: ThinkingLevel;
318
+ isScoped: boolean;
319
+ } | null>;
320
+ /** Cycle Pi's thinking level. Returns null if the current model doesn't support thinking. */
321
+ cycleThinkingLevel(): Promise<{
322
+ level: ThinkingLevel;
323
+ } | null>;
324
+ /** Manually trigger Pi's context compaction. */
325
+ compact(customInstructions?: string): Promise<CompactResult>;
326
+ /** Retrieve Pi's full conversation history for the current session. */
327
+ getMessages(): Promise<PiMessage[]>;
328
+ /** List all models available to Pi under the current provider configuration. */
329
+ getAvailableModels(): Promise<PiModel[]>;
330
+ /**
331
+ * Set or update env vars in the running container. Writes to /etc/drej-env and restarts
332
+ * the Pi subprocess so it picks up the new env. Waits until Pi is ready before returning.
333
+ */
334
+ setEnv(vars: Record<string, string>): Promise<void>;
335
+ /** Retrieve recent bridge logs (ring-buffered, last 200 entries). */
336
+ getLogs(): Promise<string>;
337
+ /** Delete the sandbox container and release all resources. Always call in a `finally` block. */
338
+ close(): Promise<void>;
339
+ }
340
+ //#endregion
341
+ export { Agent, type AgentEvent, type AgentSnapshotRecord, AgentSnapshotStore, type AgentSpec, type AgentStream, type CompactResult, type PiMessage, type PiModel, type PromptStream, type SetupStep, type ThinkingLevel, computeSetupHash, snapshotsPath, textOnly, validateAgentSpec };