@hachej/boring-agent 0.1.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/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/chunk-W73RUHY3.js +77 -0
- package/dist/eval/index.d.ts +241 -0
- package/dist/eval/index.js +508 -0
- package/dist/front/index.d.ts +394 -0
- package/dist/front/index.js +5026 -0
- package/dist/front/styles.css +4712 -0
- package/dist/harness-CMiJ4kok.d.ts +62 -0
- package/dist/sandbox-handle-store-OPdvRwie.d.ts +283 -0
- package/dist/server/index.d.ts +327 -0
- package/dist/server/index.js +6649 -0
- package/dist/shared/index.d.ts +225 -0
- package/dist/shared/index.js +75 -0
- package/package.json +132 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { UIMessage, UIMessageChunk } from 'ai';
|
|
2
|
+
|
|
3
|
+
interface SessionStore {
|
|
4
|
+
list(ctx: SessionCtx): Promise<SessionSummary[]>;
|
|
5
|
+
create(ctx: SessionCtx, init?: {
|
|
6
|
+
title?: string;
|
|
7
|
+
}): Promise<SessionSummary>;
|
|
8
|
+
load(ctx: SessionCtx, sessionId: string): Promise<SessionDetail>;
|
|
9
|
+
delete(ctx: SessionCtx, sessionId: string): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Persist a snapshot of UI-layer messages so they survive server restarts.
|
|
12
|
+
* Called by the client after each completed turn. Optional — stores that
|
|
13
|
+
* don't implement it simply don't persist UI messages server-side.
|
|
14
|
+
*/
|
|
15
|
+
saveMessages?(ctx: SessionCtx, sessionId: string, messages: UIMessage[]): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
interface SessionCtx {
|
|
18
|
+
workspaceId: string;
|
|
19
|
+
userId?: string;
|
|
20
|
+
}
|
|
21
|
+
interface SessionSummary {
|
|
22
|
+
id: string;
|
|
23
|
+
title: string;
|
|
24
|
+
createdAt: string;
|
|
25
|
+
updatedAt: string;
|
|
26
|
+
turnCount: number;
|
|
27
|
+
}
|
|
28
|
+
interface SessionDetail extends SessionSummary {
|
|
29
|
+
messages: UIMessage[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface AgentHarness {
|
|
33
|
+
readonly id: string;
|
|
34
|
+
readonly placement: 'server' | 'browser';
|
|
35
|
+
/** Send a user message. Yields AI SDK UIMessage stream chunks. */
|
|
36
|
+
sendMessage(input: SendMessageInput, ctx: RunContext): AsyncIterable<UIMessageChunk>;
|
|
37
|
+
/** Session lifecycle; may delegate to an underlying runtime (e.g. pi's JSONL). */
|
|
38
|
+
sessions: SessionStore;
|
|
39
|
+
/**
|
|
40
|
+
* Resolved system prompt currently in effect for `sessionId`. Returns
|
|
41
|
+
* `undefined` when the underlying runtime hasn't yet instantiated a
|
|
42
|
+
* session (typical pre-first-turn state — pi creates lazily on first
|
|
43
|
+
* `sendMessage`). Optional so non-pi harnesses can opt out cleanly.
|
|
44
|
+
*/
|
|
45
|
+
getSystemPrompt?: (sessionId: string) => string | undefined;
|
|
46
|
+
}
|
|
47
|
+
interface SendMessageInput {
|
|
48
|
+
sessionId: string;
|
|
49
|
+
message: string;
|
|
50
|
+
thinkingLevel?: 'off' | 'low' | 'medium' | 'high';
|
|
51
|
+
model?: {
|
|
52
|
+
provider: string;
|
|
53
|
+
id: string;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
interface RunContext {
|
|
57
|
+
abortSignal: AbortSignal;
|
|
58
|
+
workdir: string;
|
|
59
|
+
userId?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type { AgentHarness as A, RunContext as R, SendMessageInput as S, SessionCtx as a, SessionDetail as b, SessionStore as c, SessionSummary as d };
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
interface Workspace {
|
|
2
|
+
readonly root: string;
|
|
3
|
+
readFile(relPath: string): Promise<string>;
|
|
4
|
+
writeFile(relPath: string, data: string): Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* Optional optimized read+metadata operation. Remote workspaces should
|
|
7
|
+
* implement this as one round trip when possible.
|
|
8
|
+
*/
|
|
9
|
+
readFileWithStat?(relPath: string): Promise<{
|
|
10
|
+
content: string;
|
|
11
|
+
stat: Stat;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Optional optimized write+metadata operation. Remote workspaces should
|
|
15
|
+
* implement this as one round trip when possible.
|
|
16
|
+
*/
|
|
17
|
+
writeFileWithStat?(relPath: string, data: string): Promise<Stat>;
|
|
18
|
+
unlink(relPath: string): Promise<void>;
|
|
19
|
+
readdir(relPath: string): Promise<Entry[]>;
|
|
20
|
+
stat(relPath: string): Promise<Stat>;
|
|
21
|
+
mkdir(relPath: string, opts?: {
|
|
22
|
+
recursive?: boolean;
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
rename(fromRelPath: string, toRelPath: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Optional change-event channel. Implementations that can observe
|
|
27
|
+
* out-of-band file changes (e.g. local fs via chokidar, or an
|
|
28
|
+
* in-process EventEmitter for sandbox-driven tool writes) return a
|
|
29
|
+
* watcher; implementations that can't observe changes (and don't
|
|
30
|
+
* want to fake it via polling) omit this method or leave it
|
|
31
|
+
* undefined.
|
|
32
|
+
*
|
|
33
|
+
* Frontends should always assume the method may be missing and
|
|
34
|
+
* degrade to "rely on tool-reported events + window-focus refetch."
|
|
35
|
+
* Calling `watch()` more than once on a single workspace must yield
|
|
36
|
+
* watchers that share the same underlying observation source —
|
|
37
|
+
* spawning N OS-level watchers per HTTP connection is not allowed.
|
|
38
|
+
*/
|
|
39
|
+
watch?(): WorkspaceWatcher;
|
|
40
|
+
/**
|
|
41
|
+
* Capability hint for hosts that want to render a UI affordance
|
|
42
|
+
* ("connected"/"polling"/"manual refresh"). Optional — absence
|
|
43
|
+
* means "treat as 'none' and consult `watch?` for the truth." When
|
|
44
|
+
* present this is purely advisory; the actual events flow through
|
|
45
|
+
* `watch()`.
|
|
46
|
+
*/
|
|
47
|
+
readonly fsCapability?: FsCapability;
|
|
48
|
+
}
|
|
49
|
+
type FsCapability = 'none' | 'best-effort' | 'strong';
|
|
50
|
+
interface Entry {
|
|
51
|
+
name: string;
|
|
52
|
+
kind: 'file' | 'dir';
|
|
53
|
+
}
|
|
54
|
+
interface Stat {
|
|
55
|
+
size: number;
|
|
56
|
+
mtimeMs: number;
|
|
57
|
+
kind: 'file' | 'dir';
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Single fs-event payload. `op` is the canonical mutation kind, the
|
|
61
|
+
* paths are workspace-relative, and `mtimeMs` is filled when the
|
|
62
|
+
* implementation can stat the result cheaply (lets the client run an
|
|
63
|
+
* idempotent staleness check without a follow-up stat request).
|
|
64
|
+
*/
|
|
65
|
+
interface WorkspaceChangeEvent {
|
|
66
|
+
op: 'write' | 'unlink' | 'rename' | 'mkdir';
|
|
67
|
+
path: string;
|
|
68
|
+
/** Set on rename only — the path before the move. */
|
|
69
|
+
oldPath?: string;
|
|
70
|
+
mtimeMs?: number;
|
|
71
|
+
}
|
|
72
|
+
interface WorkspaceWatcher {
|
|
73
|
+
/**
|
|
74
|
+
* Add a listener for change events. Returns an unsubscribe fn —
|
|
75
|
+
* the underlying observation source stays open until the workspace
|
|
76
|
+
* itself is disposed, so unsubscribing one listener is cheap and
|
|
77
|
+
* does NOT tear down the watcher.
|
|
78
|
+
*/
|
|
79
|
+
subscribe(listener: (event: WorkspaceChangeEvent) => void): () => void;
|
|
80
|
+
/**
|
|
81
|
+
* Tear down the underlying observation source (chokidar instance,
|
|
82
|
+
* sandbox emitter binding, …). Idempotent. Subscribers added after
|
|
83
|
+
* close are no-ops. Hosts call this on workspace disposal.
|
|
84
|
+
*/
|
|
85
|
+
close(): void;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Capabilities a sandbox advertises. Consumers use this set to decide
|
|
90
|
+
* whether a tool can run (e.g. `executeIsolatedCodeTool` only registers
|
|
91
|
+
* when `'isolated-code'` is present). Backends opt in by including the
|
|
92
|
+
* capability string in their `Sandbox.capabilities` array.
|
|
93
|
+
*
|
|
94
|
+
* Open string union — backends and downstream packages can extend it
|
|
95
|
+
* without modifying this file (TypeScript declaration-merging or just
|
|
96
|
+
* casting). New capabilities to expect over time:
|
|
97
|
+
* - `'gpu'` — backend can attach GPUs to isolated-code calls
|
|
98
|
+
* - `'persistent-fs'` — backend retains workspace state across sessions
|
|
99
|
+
* - `'snapshot'` — backend supports baking + restoring snapshots
|
|
100
|
+
* - `'network-allow'` — backend can apply egress allow/deny lists
|
|
101
|
+
*/
|
|
102
|
+
type SandboxCapability = 'exec' | 'isolated-code' | (string & {});
|
|
103
|
+
/**
|
|
104
|
+
* Where the sandbox actually executes — relative to the agent backend
|
|
105
|
+
* process running pi.
|
|
106
|
+
*
|
|
107
|
+
* - `'server'` — same process / same host as the agent backend (e.g.
|
|
108
|
+
* `DirectSandbox`, `BwrapSandbox`).
|
|
109
|
+
* - `'remote'` — a separate machine reached over the network (e.g.
|
|
110
|
+
* `VercelSandboxExec` Firecracker VM, SSH, Modal, Docker host
|
|
111
|
+
* accessed by API). Implementations must tolerate higher latency and
|
|
112
|
+
* handle abort by signalling the remote.
|
|
113
|
+
* - `'browser'` — runs in the user's browser (e.g. WASM bash,
|
|
114
|
+
* `JustBashSandbox`). Reserved for future browser-agent mode.
|
|
115
|
+
*/
|
|
116
|
+
type SandboxPlacement = 'server' | 'remote' | 'browser';
|
|
117
|
+
interface Sandbox {
|
|
118
|
+
/** Stable identifier for this sandbox instance. */
|
|
119
|
+
readonly id: string;
|
|
120
|
+
/** Where the sandbox runs relative to the agent backend. */
|
|
121
|
+
readonly placement: SandboxPlacement;
|
|
122
|
+
/**
|
|
123
|
+
* Provider name — e.g. `'direct'`, `'bwrap'`, `'vercel-sandbox'`,
|
|
124
|
+
* `'docker'`, `'modal'`, `'apple-container'`, `'ssh'`. Used for
|
|
125
|
+
* telemetry, diagnostics, and capability negotiation. Free-form
|
|
126
|
+
* convention: matches the runtime mode id where one exists.
|
|
127
|
+
*/
|
|
128
|
+
readonly provider: string;
|
|
129
|
+
/** Capabilities this sandbox advertises (used for tool gating). */
|
|
130
|
+
readonly capabilities: readonly SandboxCapability[];
|
|
131
|
+
/**
|
|
132
|
+
* Optional initialization hook. Some backends bind to a workspace +
|
|
133
|
+
* session at construction (Vercel: snapshot warm-up; Bwrap: bind
|
|
134
|
+
* mounts). Ephemeral backends (Direct, on-demand Docker exec) can
|
|
135
|
+
* omit this entirely.
|
|
136
|
+
*/
|
|
137
|
+
init?(ctx: {
|
|
138
|
+
workspace: Workspace;
|
|
139
|
+
sessionId: string;
|
|
140
|
+
}): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* Run a shell command. Required capability: `'exec'`.
|
|
143
|
+
*
|
|
144
|
+
* Implementations MUST honor `signal` for abort, `timeoutMs` for
|
|
145
|
+
* timeout, and `maxOutputBytes` for output truncation (and set
|
|
146
|
+
* `truncated: true` in the result when truncation fires).
|
|
147
|
+
*
|
|
148
|
+
* The optional `onStdout` / `onStderr` callbacks (when implemented)
|
|
149
|
+
* stream output incrementally as bytes arrive. When omitted,
|
|
150
|
+
* implementations buffer normally and surface output via
|
|
151
|
+
* `ExecResult.stdout` / `stderr` only. See `Sandbox.exec` streaming
|
|
152
|
+
* extension under bead [Phase 1.0].
|
|
153
|
+
*/
|
|
154
|
+
exec(cmd: string, opts?: ExecOptions): Promise<ExecResult>;
|
|
155
|
+
/**
|
|
156
|
+
* Run a self-contained snippet of code in an ephemeral sandbox
|
|
157
|
+
* instance. Capability: `'isolated-code'`. Optional — backends that
|
|
158
|
+
* cannot offer per-call isolation (`DirectSandbox`, `BwrapSandbox`)
|
|
159
|
+
* omit this method entirely.
|
|
160
|
+
*/
|
|
161
|
+
executeIsolatedCode?(input: IsolatedCodeInput): Promise<IsolatedCodeOutput>;
|
|
162
|
+
dispose?(): Promise<void>;
|
|
163
|
+
}
|
|
164
|
+
interface ExecOptions {
|
|
165
|
+
cwd?: string;
|
|
166
|
+
env?: Record<string, string>;
|
|
167
|
+
signal?: AbortSignal;
|
|
168
|
+
timeoutMs?: number;
|
|
169
|
+
maxOutputBytes?: number;
|
|
170
|
+
onHeartbeat?: (elapsedMs: number) => void;
|
|
171
|
+
onStdout?: (chunk: Uint8Array) => void;
|
|
172
|
+
onStderr?: (chunk: Uint8Array) => void;
|
|
173
|
+
}
|
|
174
|
+
interface ExecResult {
|
|
175
|
+
stdout: Uint8Array;
|
|
176
|
+
stderr: Uint8Array;
|
|
177
|
+
exitCode: number;
|
|
178
|
+
durationMs: number;
|
|
179
|
+
truncated: boolean;
|
|
180
|
+
stdoutEncoding?: 'utf-8' | 'binary';
|
|
181
|
+
stderrEncoding?: 'utf-8' | 'binary';
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Abstract resource hints for `executeIsolatedCode`. Backends round to
|
|
185
|
+
* their own size tiers (Vercel: `xxs`/…/`l`; Modal: `cpu`/`memory`
|
|
186
|
+
* floats; Docker: cgroups). Each field is a HINT, not a contract — a
|
|
187
|
+
* backend may ignore or clamp values it cannot honor.
|
|
188
|
+
*/
|
|
189
|
+
interface SandboxResources {
|
|
190
|
+
/** Requested logical CPU cores. Backend rounds up. */
|
|
191
|
+
cpuCores?: number;
|
|
192
|
+
/** Requested memory in MB. Backend rounds up. */
|
|
193
|
+
memoryMb?: number;
|
|
194
|
+
/**
|
|
195
|
+
* GPU class hint. Free-form vendor-specific token (e.g. `'t4'`,
|
|
196
|
+
* `'a10g'`, `'h100'`). Empty/omitted means CPU-only. Only honored
|
|
197
|
+
* when the sandbox advertises capability `'gpu'`.
|
|
198
|
+
*/
|
|
199
|
+
gpu?: string;
|
|
200
|
+
}
|
|
201
|
+
interface IsolatedCodeInput {
|
|
202
|
+
code: string;
|
|
203
|
+
language: 'python' | 'shell';
|
|
204
|
+
/**
|
|
205
|
+
* Container / snapshot identifier. Format is vendor-specific:
|
|
206
|
+
* Docker → image ref (`node:20`), Vercel → `snapshotId`, Modal →
|
|
207
|
+
* image name, Apple-container → bundle path. Treat as opaque.
|
|
208
|
+
*/
|
|
209
|
+
image?: string;
|
|
210
|
+
/**
|
|
211
|
+
* Per-call dependencies (npm/pip-style). Honored by backends that
|
|
212
|
+
* build environments on demand (Modal, Vercel snapshot-bake).
|
|
213
|
+
* Ignored by backends that require pre-built images (vanilla Docker
|
|
214
|
+
* exec).
|
|
215
|
+
*/
|
|
216
|
+
packages?: string[];
|
|
217
|
+
/** Reuse an existing sandbox handle if the backend supports it. */
|
|
218
|
+
sandboxId?: string;
|
|
219
|
+
/** Generic resource request. Backends round to their own size tiers. */
|
|
220
|
+
resources?: SandboxResources;
|
|
221
|
+
/**
|
|
222
|
+
* Backend-specific knobs that don't fit the generic shape — opaque
|
|
223
|
+
* pass-through. Example: Modal's `min_containers`, Docker's
|
|
224
|
+
* `--cap-add`, Vercel's `region`. Consumers should never read this
|
|
225
|
+
* field; it exists so callers can target a specific provider.
|
|
226
|
+
*/
|
|
227
|
+
vendorHints?: Record<string, unknown>;
|
|
228
|
+
/**
|
|
229
|
+
* @deprecated Use `resources` instead. Vercel-specific t-shirt
|
|
230
|
+
* sizes; kept for back-compat. Backends MAY map this to their own
|
|
231
|
+
* size taxonomy or ignore it. New consumers should use `resources`.
|
|
232
|
+
*/
|
|
233
|
+
vmSize?: 'xxs' | 'xs' | 's' | 'm' | 'l';
|
|
234
|
+
}
|
|
235
|
+
interface IsolatedCodeOutput {
|
|
236
|
+
sandboxId: string;
|
|
237
|
+
stdout: string;
|
|
238
|
+
stderr: string;
|
|
239
|
+
exitCode: number;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
type JSONSchema = Record<string, unknown>;
|
|
243
|
+
interface AgentTool {
|
|
244
|
+
name: string;
|
|
245
|
+
description: string;
|
|
246
|
+
/** Optional one-line prompt entry. Pi-built tools should preserve pi's snippet verbatim. */
|
|
247
|
+
promptSnippet?: string;
|
|
248
|
+
parameters: JSONSchema;
|
|
249
|
+
execute(params: Record<string, unknown>, ctx: ToolExecContext): Promise<ToolResult>;
|
|
250
|
+
}
|
|
251
|
+
interface ToolExecContext {
|
|
252
|
+
abortSignal: AbortSignal;
|
|
253
|
+
toolCallId: string;
|
|
254
|
+
onUpdate?: (partial: string) => void;
|
|
255
|
+
}
|
|
256
|
+
interface ToolResult {
|
|
257
|
+
content: Array<{
|
|
258
|
+
type: 'text';
|
|
259
|
+
text: string;
|
|
260
|
+
}>;
|
|
261
|
+
isError?: boolean;
|
|
262
|
+
details?: unknown;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
interface FileSearch {
|
|
266
|
+
search(glob: string, limit?: number): Promise<string[]>;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
interface SandboxHandleRecord {
|
|
270
|
+
workspaceId: string;
|
|
271
|
+
sandboxId: string;
|
|
272
|
+
snapshotId?: string;
|
|
273
|
+
createdAt: string;
|
|
274
|
+
lastUsedAt: string;
|
|
275
|
+
}
|
|
276
|
+
interface SandboxHandleStore {
|
|
277
|
+
get(workspaceId: string): Promise<SandboxHandleRecord | null>;
|
|
278
|
+
put(record: SandboxHandleRecord): Promise<void>;
|
|
279
|
+
delete(workspaceId: string): Promise<void>;
|
|
280
|
+
list(): Promise<SandboxHandleRecord[]>;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export type { AgentTool as A, Entry as E, FileSearch as F, IsolatedCodeInput as I, JSONSchema as J, Sandbox as S, ToolExecContext as T, Workspace as W, ExecOptions as a, ExecResult as b, IsolatedCodeOutput as c, SandboxCapability as d, SandboxHandleRecord as e, SandboxHandleStore as f, Stat as g, ToolResult as h };
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { S as Sandbox, f as SandboxHandleStore, e as SandboxHandleRecord, W as Workspace, F as FileSearch, A as AgentTool } from '../sandbox-handle-store-OPdvRwie.js';
|
|
2
|
+
import { Sandbox as Sandbox$1 } from '@vercel/sandbox';
|
|
3
|
+
import { FastifyInstance, FastifyRequest, FastifyPluginAsync } from 'fastify';
|
|
4
|
+
import { PackageSource } from '@mariozechner/pi-coding-agent';
|
|
5
|
+
|
|
6
|
+
declare function createDirectSandbox(): Sandbox;
|
|
7
|
+
|
|
8
|
+
declare function createBwrapSandbox(): Sandbox;
|
|
9
|
+
|
|
10
|
+
interface FileHandleStoreOptions {
|
|
11
|
+
storePath?: string;
|
|
12
|
+
}
|
|
13
|
+
declare class FileHandleStore implements SandboxHandleStore {
|
|
14
|
+
private readonly storePath;
|
|
15
|
+
constructor(opts?: FileHandleStoreOptions);
|
|
16
|
+
get(workspaceId: string): Promise<SandboxHandleRecord | null>;
|
|
17
|
+
put(record: SandboxHandleRecord): Promise<void>;
|
|
18
|
+
delete(workspaceId: string): Promise<void>;
|
|
19
|
+
list(): Promise<SandboxHandleRecord[]>;
|
|
20
|
+
private readStore;
|
|
21
|
+
private writeStore;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface ResolveSandboxCreateParams {
|
|
25
|
+
name?: string;
|
|
26
|
+
persistent?: boolean;
|
|
27
|
+
snapshotExpiration?: number;
|
|
28
|
+
source?: {
|
|
29
|
+
type: 'snapshot';
|
|
30
|
+
snapshotId: string;
|
|
31
|
+
} | {
|
|
32
|
+
type: 'tarball';
|
|
33
|
+
url: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
type VercelSandboxHandle = Sandbox$1 & {
|
|
37
|
+
sandboxId?: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
currentSnapshotId?: string;
|
|
40
|
+
sourceSnapshotId?: string;
|
|
41
|
+
};
|
|
42
|
+
interface VercelSandboxClient {
|
|
43
|
+
create(params?: ResolveSandboxCreateParams): Promise<VercelSandboxHandle>;
|
|
44
|
+
get(params: {
|
|
45
|
+
sandboxId?: string;
|
|
46
|
+
name?: string;
|
|
47
|
+
resume?: boolean;
|
|
48
|
+
}): Promise<VercelSandboxHandle>;
|
|
49
|
+
}
|
|
50
|
+
interface SandboxLifecycleLogger {
|
|
51
|
+
info?(message: string, metadata: Record<string, unknown>): void;
|
|
52
|
+
warn?(message: string, metadata: Record<string, unknown>): void;
|
|
53
|
+
}
|
|
54
|
+
type ExpiredSandboxPolicy = 'recreate' | 'error';
|
|
55
|
+
interface ResolveSandboxHandleOptions {
|
|
56
|
+
tarballUrl?: string;
|
|
57
|
+
maxIdleMs?: number;
|
|
58
|
+
now?: () => number;
|
|
59
|
+
logger?: SandboxLifecycleLogger;
|
|
60
|
+
expiredSandboxPolicy?: ExpiredSandboxPolicy;
|
|
61
|
+
}
|
|
62
|
+
declare function resolveSandboxHandle(workspaceId: string, store: SandboxHandleStore, vercel: VercelSandboxClient, opts?: ResolveSandboxHandleOptions): Promise<VercelSandboxHandle>;
|
|
63
|
+
|
|
64
|
+
interface VercelCommandResult {
|
|
65
|
+
exitCode: number;
|
|
66
|
+
stdout(opts?: {
|
|
67
|
+
signal?: AbortSignal;
|
|
68
|
+
}): Promise<string>;
|
|
69
|
+
stderr(opts?: {
|
|
70
|
+
signal?: AbortSignal;
|
|
71
|
+
}): Promise<string>;
|
|
72
|
+
}
|
|
73
|
+
interface VercelBakeSandbox {
|
|
74
|
+
runCommand(command: string, args?: string[], opts?: {
|
|
75
|
+
signal?: AbortSignal;
|
|
76
|
+
}): Promise<VercelCommandResult>;
|
|
77
|
+
snapshot(opts?: {
|
|
78
|
+
signal?: AbortSignal;
|
|
79
|
+
}): Promise<{
|
|
80
|
+
snapshotId: string;
|
|
81
|
+
}>;
|
|
82
|
+
stop?(opts?: {
|
|
83
|
+
signal?: AbortSignal;
|
|
84
|
+
}): Promise<void>;
|
|
85
|
+
}
|
|
86
|
+
interface VercelBakeClient {
|
|
87
|
+
create(params?: {
|
|
88
|
+
runtime?: string;
|
|
89
|
+
}): Promise<VercelBakeSandbox>;
|
|
90
|
+
}
|
|
91
|
+
interface BakeLogger {
|
|
92
|
+
info?: (...args: unknown[]) => void;
|
|
93
|
+
warn?: (...args: unknown[]) => void;
|
|
94
|
+
}
|
|
95
|
+
type SnapshotBakeStatus = 'skipped' | 'cache-hit' | 'baked' | 'failed';
|
|
96
|
+
type SnapshotBakeReason = 'snapshot-id-configured' | 'no-packages' | 'cache-hit' | 'baked' | 'bake-failed';
|
|
97
|
+
interface SnapshotBakeResult {
|
|
98
|
+
status: SnapshotBakeStatus;
|
|
99
|
+
reason: SnapshotBakeReason;
|
|
100
|
+
hash?: string;
|
|
101
|
+
snapshotId?: string;
|
|
102
|
+
error?: unknown;
|
|
103
|
+
}
|
|
104
|
+
interface SnapshotBakeOptions {
|
|
105
|
+
client: VercelBakeClient;
|
|
106
|
+
pythonPackages?: readonly string[];
|
|
107
|
+
systemPackages?: readonly string[];
|
|
108
|
+
setupCommands?: readonly string[];
|
|
109
|
+
snapshotId?: string;
|
|
110
|
+
runtime?: string;
|
|
111
|
+
cachePath?: string;
|
|
112
|
+
logger?: BakeLogger;
|
|
113
|
+
now?: () => Date;
|
|
114
|
+
}
|
|
115
|
+
declare function buildPackageHash(input: {
|
|
116
|
+
pythonPackages?: readonly string[];
|
|
117
|
+
systemPackages?: readonly string[];
|
|
118
|
+
}): string;
|
|
119
|
+
declare function buildSnapshotRecipeHash(input: {
|
|
120
|
+
runtime?: string;
|
|
121
|
+
pythonPackages?: readonly string[];
|
|
122
|
+
systemPackages?: readonly string[];
|
|
123
|
+
setupCommands?: readonly string[];
|
|
124
|
+
}): string;
|
|
125
|
+
declare function bakeSnapshotIfNeeded(opts: SnapshotBakeOptions): Promise<SnapshotBakeResult>;
|
|
126
|
+
|
|
127
|
+
declare const UV_SETUP_COMMANDS: readonly ["command -v uv >/dev/null 2>&1 || python3 -m pip install --upgrade uv", "uv --version"];
|
|
128
|
+
type DeploymentSnapshotStatus = 'skipped' | 'cache-hit' | 'baked' | 'failed';
|
|
129
|
+
interface DeploymentSnapshotRecipe {
|
|
130
|
+
/** Provider runtime/image selector. Example: Vercel's python3.13 runtime. */
|
|
131
|
+
runtime?: string;
|
|
132
|
+
/** OS packages to bake into the reusable runtime layer. */
|
|
133
|
+
systemPackages?: readonly string[];
|
|
134
|
+
/** Python packages to bake into the reusable runtime layer. */
|
|
135
|
+
pythonPackages?: readonly string[];
|
|
136
|
+
/** Ordered setup commands for runtime primitives such as uv. */
|
|
137
|
+
setupCommands?: readonly string[];
|
|
138
|
+
}
|
|
139
|
+
interface DeploymentSnapshotResult {
|
|
140
|
+
status: DeploymentSnapshotStatus;
|
|
141
|
+
reason: string;
|
|
142
|
+
hash?: string;
|
|
143
|
+
snapshotId?: string;
|
|
144
|
+
error?: unknown;
|
|
145
|
+
}
|
|
146
|
+
interface DeploymentSnapshotProvider {
|
|
147
|
+
prepareDeploymentSnapshot(recipe: DeploymentSnapshotRecipe): Promise<DeploymentSnapshotResult>;
|
|
148
|
+
}
|
|
149
|
+
interface BuildDeploymentSnapshotRecipeOptions extends DeploymentSnapshotRecipe {
|
|
150
|
+
/** Defaults true: install/check uv at deploy-time so workspaces boot fast. */
|
|
151
|
+
includeUv?: boolean;
|
|
152
|
+
}
|
|
153
|
+
declare function buildDeploymentSnapshotRecipe(opts?: BuildDeploymentSnapshotRecipeOptions): DeploymentSnapshotRecipe;
|
|
154
|
+
declare function prepareDeploymentSnapshot(provider: DeploymentSnapshotProvider, recipe: DeploymentSnapshotRecipe): Promise<DeploymentSnapshotResult>;
|
|
155
|
+
|
|
156
|
+
interface VercelDeploymentSnapshotOptions {
|
|
157
|
+
client: VercelBakeClient;
|
|
158
|
+
snapshotId?: string;
|
|
159
|
+
runtime?: string;
|
|
160
|
+
cachePath?: string;
|
|
161
|
+
logger?: BakeLogger;
|
|
162
|
+
now?: () => Date;
|
|
163
|
+
/**
|
|
164
|
+
* Extra deploy-time setup commands baked into the reusable snapshot.
|
|
165
|
+
* Use for runtime primitives such as uv or OS tools, not workspace content.
|
|
166
|
+
*/
|
|
167
|
+
setupCommands?: readonly string[];
|
|
168
|
+
pythonPackages?: readonly string[];
|
|
169
|
+
systemPackages?: readonly string[];
|
|
170
|
+
}
|
|
171
|
+
declare function createVercelDeploymentSnapshotProvider(opts: Omit<VercelDeploymentSnapshotOptions, 'runtime' | 'setupCommands' | 'pythonPackages' | 'systemPackages'>): DeploymentSnapshotProvider;
|
|
172
|
+
declare function prepareVercelDeploymentSnapshot(opts: VercelDeploymentSnapshotOptions): Promise<SnapshotBakeResult>;
|
|
173
|
+
|
|
174
|
+
declare function createNodeWorkspace(root: string): Workspace;
|
|
175
|
+
|
|
176
|
+
interface RuntimeTemplateContribution {
|
|
177
|
+
id: string;
|
|
178
|
+
path: string | URL;
|
|
179
|
+
target?: string;
|
|
180
|
+
}
|
|
181
|
+
interface RuntimePythonSpec {
|
|
182
|
+
id: string;
|
|
183
|
+
/** uv-compatible pyproject.toml. Console scripts declared here are exposed to the agent. */
|
|
184
|
+
projectFile: string | URL;
|
|
185
|
+
/** Extra workspace libraries to install into the same environment. */
|
|
186
|
+
extraLibs?: string[];
|
|
187
|
+
/** Env vars exported by command shims, e.g. plugin builtin paths. */
|
|
188
|
+
env?: Record<string, string | URL>;
|
|
189
|
+
}
|
|
190
|
+
interface RuntimeProvisioningContribution {
|
|
191
|
+
templateDirs?: RuntimeTemplateContribution[];
|
|
192
|
+
python?: RuntimePythonSpec[];
|
|
193
|
+
}
|
|
194
|
+
interface ProvisionRuntimeWorkspaceOptions {
|
|
195
|
+
workspaceRoot: string;
|
|
196
|
+
contributions?: Array<{
|
|
197
|
+
id: string;
|
|
198
|
+
provisioning?: RuntimeProvisioningContribution;
|
|
199
|
+
}>;
|
|
200
|
+
force?: boolean;
|
|
201
|
+
}
|
|
202
|
+
interface RuntimeWorkspaceProvisioningResult {
|
|
203
|
+
fingerprint: string;
|
|
204
|
+
changed: boolean;
|
|
205
|
+
env: Record<string, string>;
|
|
206
|
+
binDir: string;
|
|
207
|
+
}
|
|
208
|
+
declare function provisionRuntimeWorkspace({ workspaceRoot, contributions, force, }: ProvisionRuntimeWorkspaceOptions): Promise<RuntimeWorkspaceProvisioningResult>;
|
|
209
|
+
|
|
210
|
+
interface VercelSandboxWorkspace extends Workspace {
|
|
211
|
+
invalidateMetadataCache(): void;
|
|
212
|
+
}
|
|
213
|
+
interface VercelSandboxWorkspaceOptions {
|
|
214
|
+
onMutation?: () => void;
|
|
215
|
+
}
|
|
216
|
+
declare function createVercelSandboxWorkspace(sandbox: Sandbox$1, workspaceOpts?: VercelSandboxWorkspaceOptions): VercelSandboxWorkspace;
|
|
217
|
+
|
|
218
|
+
type RuntimeModeId = 'direct' | 'local' | 'vercel-sandbox';
|
|
219
|
+
interface RuntimeModeAdapter {
|
|
220
|
+
readonly id: RuntimeModeId;
|
|
221
|
+
create(ctx: ModeContext): Promise<RuntimeBundle>;
|
|
222
|
+
dispose?(): Promise<void>;
|
|
223
|
+
}
|
|
224
|
+
interface ModeContext {
|
|
225
|
+
workspaceRoot: string;
|
|
226
|
+
sessionId: string;
|
|
227
|
+
workspaceId?: string;
|
|
228
|
+
templatePath?: string;
|
|
229
|
+
}
|
|
230
|
+
interface RuntimeBundle {
|
|
231
|
+
workspace: Workspace;
|
|
232
|
+
sandbox: Sandbox;
|
|
233
|
+
fileSearch: FileSearch;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
declare function hasBwrap(): boolean;
|
|
237
|
+
declare function autoDetectMode(): RuntimeModeId;
|
|
238
|
+
declare function resolveMode(mode?: RuntimeModeId): RuntimeModeAdapter;
|
|
239
|
+
|
|
240
|
+
type PiPackageSource = PackageSource;
|
|
241
|
+
declare const PI_PACKAGE_RESOURCE_FILTERS: readonly ["extensions", "skills", "prompts", "themes"];
|
|
242
|
+
declare function piPackageSourceKey(source: PiPackageSource): string;
|
|
243
|
+
declare function compactPiPackages(sources: Array<PiPackageSource | undefined>): PiPackageSource[];
|
|
244
|
+
declare function mergePiPackageSources(base?: PiPackageSource[], additional?: PiPackageSource[]): PiPackageSource[];
|
|
245
|
+
|
|
246
|
+
interface PiResourceLoaderOptions {
|
|
247
|
+
noContextFiles?: boolean;
|
|
248
|
+
noSkills?: boolean;
|
|
249
|
+
additionalSkillPaths?: string[];
|
|
250
|
+
/**
|
|
251
|
+
* Additional native Pi package sources to enable for this agent runtime.
|
|
252
|
+
* These are applied as in-memory SettingsManager overrides, so host/plugin
|
|
253
|
+
* declarations do not mutate .pi/settings.json.
|
|
254
|
+
*/
|
|
255
|
+
piPackages?: PiPackageSource[];
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
interface CreateAgentAppOptions {
|
|
259
|
+
workspaceRoot?: string;
|
|
260
|
+
sessionId?: string;
|
|
261
|
+
templatePath?: string;
|
|
262
|
+
mode?: RuntimeModeId;
|
|
263
|
+
authToken?: string;
|
|
264
|
+
version?: string;
|
|
265
|
+
logger?: boolean;
|
|
266
|
+
extraTools?: AgentTool[];
|
|
267
|
+
/** When true, omit the six filesystem tools (read/write/edit/find/grep/ls). */
|
|
268
|
+
disableDefaultFileTools?: boolean;
|
|
269
|
+
/**
|
|
270
|
+
* Append-only addendum to the underlying agent's system prompt. Cannot
|
|
271
|
+
* replace the base prompt — host apps EXTEND it (e.g. document app-
|
|
272
|
+
* specific tools, panes, data conventions). Plumbed to pi-coding-agent
|
|
273
|
+
* via DefaultResourceLoader's `appendSystemPromptSource`.
|
|
274
|
+
*/
|
|
275
|
+
systemPromptAppend?: string;
|
|
276
|
+
/** Optional pi resource-loader isolation knobs. */
|
|
277
|
+
resourceLoaderOptions?: PiResourceLoaderOptions;
|
|
278
|
+
}
|
|
279
|
+
declare function createAgentApp(opts?: CreateAgentAppOptions): Promise<FastifyInstance>;
|
|
280
|
+
|
|
281
|
+
interface HeaderLike {
|
|
282
|
+
setHeader(name: string, value: string): void;
|
|
283
|
+
}
|
|
284
|
+
declare function applyCspHeaders(response: HeaderLike, opts?: {
|
|
285
|
+
dev?: boolean;
|
|
286
|
+
}): void;
|
|
287
|
+
|
|
288
|
+
interface RegisterAgentRoutesOptions {
|
|
289
|
+
workspaceRoot?: string;
|
|
290
|
+
sessionId?: string;
|
|
291
|
+
templatePath?: string;
|
|
292
|
+
mode?: RuntimeModeId;
|
|
293
|
+
version?: string;
|
|
294
|
+
extraTools?: AgentTool[];
|
|
295
|
+
getExtraTools?: (ctx: {
|
|
296
|
+
workspaceId: string;
|
|
297
|
+
workspaceRoot: string;
|
|
298
|
+
runtimeMode: RuntimeModeId;
|
|
299
|
+
}) => AgentTool[] | Promise<AgentTool[]>;
|
|
300
|
+
systemPromptAppend?: string;
|
|
301
|
+
resourceLoaderOptions?: PiResourceLoaderOptions;
|
|
302
|
+
registerHealthRoute?: boolean;
|
|
303
|
+
sandboxHandleStore?: SandboxHandleStore;
|
|
304
|
+
getWorkspaceId?: (request: FastifyRequest) => string | Promise<string>;
|
|
305
|
+
getWorkspaceRoot?: (workspaceId: string, request: FastifyRequest) => string | Promise<string>;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Fastify plugin that mounts agent routes onto a host app (typically core-built).
|
|
309
|
+
*
|
|
310
|
+
* Shape B counterpart to createAgentApp (Shape A). The host provides its own
|
|
311
|
+
* Fastify instance, auth, and stores; this plugin only adds routes + runtime.
|
|
312
|
+
* No auth middleware is registered — the host's authHook handles authentication.
|
|
313
|
+
*/
|
|
314
|
+
declare const registerAgentRoutes: FastifyPluginAsync<RegisterAgentRoutesOptions>;
|
|
315
|
+
|
|
316
|
+
interface LogFields {
|
|
317
|
+
[key: string]: unknown;
|
|
318
|
+
}
|
|
319
|
+
interface Logger {
|
|
320
|
+
debug(msg: string, fields?: LogFields): void;
|
|
321
|
+
info(msg: string, fields?: LogFields): void;
|
|
322
|
+
warn(msg: string, fields?: LogFields): void;
|
|
323
|
+
error(msg: string, fields?: LogFields): void;
|
|
324
|
+
}
|
|
325
|
+
declare function createLogger(prefix: string): Logger;
|
|
326
|
+
|
|
327
|
+
export { type CreateAgentAppOptions, type DeploymentSnapshotProvider, type DeploymentSnapshotRecipe, type DeploymentSnapshotResult, type DeploymentSnapshotStatus, FileHandleStore, type LogFields, type Logger, type ModeContext, PI_PACKAGE_RESOURCE_FILTERS, type PiPackageSource, type PiResourceLoaderOptions, type ProvisionRuntimeWorkspaceOptions, type RegisterAgentRoutesOptions, type RuntimeBundle, type RuntimeModeAdapter, type RuntimeModeId, type RuntimeProvisioningContribution, type RuntimePythonSpec, type RuntimeTemplateContribution, type RuntimeWorkspaceProvisioningResult, type SnapshotBakeOptions, type SnapshotBakeResult, UV_SETUP_COMMANDS, UV_SETUP_COMMANDS as VERCEL_UV_SETUP_COMMANDS, type VercelBakeClient, type VercelBakeSandbox, type VercelDeploymentSnapshotOptions, applyCspHeaders, autoDetectMode, bakeSnapshotIfNeeded, buildDeploymentSnapshotRecipe, buildPackageHash, buildSnapshotRecipeHash, compactPiPackages, createAgentApp, createBwrapSandbox, createDirectSandbox, createLogger, createNodeWorkspace, createVercelDeploymentSnapshotProvider, createVercelSandboxWorkspace, hasBwrap, mergePiPackageSources, piPackageSourceKey, prepareDeploymentSnapshot, prepareVercelDeploymentSnapshot, provisionRuntimeWorkspace, registerAgentRoutes, resolveMode, resolveSandboxHandle };
|