sandlot 0.1.4 → 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/dist/browser/bundler.d.ts +68 -0
- package/dist/browser/bundler.d.ts.map +1 -0
- package/dist/browser/executor.d.ts +46 -0
- package/dist/browser/executor.d.ts.map +1 -0
- package/dist/browser/index.d.ts +9 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +2692 -0
- package/dist/browser/preset.d.ts +63 -0
- package/dist/browser/preset.d.ts.map +1 -0
- package/dist/commands/index.d.ts +20 -11
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/types.d.ts +31 -132
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/core/bundler-utils.d.ts +142 -0
- package/dist/core/bundler-utils.d.ts.map +1 -0
- package/dist/core/esm-types-resolver.d.ts +125 -0
- package/dist/core/esm-types-resolver.d.ts.map +1 -0
- package/dist/core/executor.d.ts +35 -0
- package/dist/core/executor.d.ts.map +1 -0
- package/dist/{fs.d.ts → core/fs.d.ts} +27 -29
- package/dist/core/fs.d.ts.map +1 -0
- package/dist/core/sandbox.d.ts +30 -0
- package/dist/core/sandbox.d.ts.map +1 -0
- package/dist/core/sandlot.d.ts +30 -0
- package/dist/core/sandlot.d.ts.map +1 -0
- package/dist/core/shared-module-registry.d.ts +46 -0
- package/dist/core/shared-module-registry.d.ts.map +1 -0
- package/dist/core/typechecker.d.ts +60 -0
- package/dist/core/typechecker.d.ts.map +1 -0
- package/dist/index.d.ts +11 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1399 -2010
- package/dist/node/bundler.d.ts +48 -0
- package/dist/node/bundler.d.ts.map +1 -0
- package/dist/node/executor.d.ts +48 -0
- package/dist/node/executor.d.ts.map +1 -0
- package/dist/node/index.d.ts +9 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +2646 -0
- package/dist/node/preset.d.ts +62 -0
- package/dist/node/preset.d.ts.map +1 -0
- package/dist/types.d.ts +525 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +16 -6
- package/src/browser/bundler.ts +294 -0
- package/src/browser/executor.ts +71 -0
- package/src/browser/index.ts +57 -0
- package/src/browser/preset.ts +179 -0
- package/src/commands/index.ts +526 -43
- package/src/commands/types.ts +82 -146
- package/src/core/bundler-utils.ts +630 -0
- package/src/core/esm-types-resolver.ts +432 -0
- package/src/core/executor.ts +161 -0
- package/src/{fs.ts → core/fs.ts} +59 -37
- package/src/core/sandbox.ts +621 -0
- package/src/core/sandlot.ts +77 -0
- package/src/core/shared-module-registry.ts +138 -0
- package/src/core/typechecker.ts +607 -0
- package/src/index.ts +104 -139
- package/src/node/bundler.ts +194 -0
- package/src/node/executor.ts +87 -0
- package/src/node/index.ts +39 -0
- package/src/node/preset.ts +178 -0
- package/src/types.ts +668 -0
- package/README.md +0 -243
- package/dist/build-emitter.d.ts +0 -47
- package/dist/build-emitter.d.ts.map +0 -1
- package/dist/builder.d.ts +0 -370
- package/dist/builder.d.ts.map +0 -1
- package/dist/bundler.d.ts +0 -152
- package/dist/bundler.d.ts.map +0 -1
- package/dist/commands/compile.d.ts +0 -13
- package/dist/commands/compile.d.ts.map +0 -1
- package/dist/commands/packages.d.ts +0 -17
- package/dist/commands/packages.d.ts.map +0 -1
- package/dist/commands/run.d.ts +0 -40
- package/dist/commands/run.d.ts.map +0 -1
- package/dist/commands.d.ts +0 -179
- package/dist/commands.d.ts.map +0 -1
- package/dist/fs.d.ts.map +0 -1
- package/dist/internal.d.ts +0 -79
- package/dist/internal.d.ts.map +0 -1
- package/dist/internal.js +0 -1942
- package/dist/loader.d.ts +0 -164
- package/dist/loader.d.ts.map +0 -1
- package/dist/packages.d.ts +0 -199
- package/dist/packages.d.ts.map +0 -1
- package/dist/runner.d.ts +0 -314
- package/dist/runner.d.ts.map +0 -1
- package/dist/sandbox-manager.d.ts +0 -261
- package/dist/sandbox-manager.d.ts.map +0 -1
- package/dist/sandbox.d.ts +0 -267
- package/dist/sandbox.d.ts.map +0 -1
- package/dist/shared-modules.d.ts +0 -148
- package/dist/shared-modules.d.ts.map +0 -1
- package/dist/shared-resources.d.ts +0 -102
- package/dist/shared-resources.d.ts.map +0 -1
- package/dist/ts-libs.d.ts +0 -85
- package/dist/ts-libs.d.ts.map +0 -1
- package/dist/typechecker.d.ts +0 -127
- package/dist/typechecker.d.ts.map +0 -1
- package/src/build-emitter.ts +0 -64
- package/src/builder.ts +0 -498
- package/src/bundler.ts +0 -575
- package/src/commands/compile.ts +0 -236
- package/src/commands/packages.ts +0 -154
- package/src/commands/run.ts +0 -245
- package/src/internal.ts +0 -119
- package/src/loader.ts +0 -229
- package/src/packages.ts +0 -936
- package/src/sandbox.ts +0 -398
- package/src/shared-modules.ts +0 -280
- package/src/shared-resources.ts +0 -166
- package/src/ts-libs.ts +0 -218
- package/src/typechecker.ts +0 -635
package/README.md
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
# Sandlot
|
|
2
|
-
|
|
3
|
-
Browser-based TypeScript sandbox with esbuild bundling and type checking. Designed for AI agent workflows where code needs to be written, validated, and executed in real-time, all in the browser.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install sandlot
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Quick Start
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
import { createBuilder, registerSharedModules } from "sandlot";
|
|
15
|
-
import * as React from "react";
|
|
16
|
-
|
|
17
|
-
// Share React with dynamic code to avoid duplicate instances
|
|
18
|
-
registerSharedModules({ react: React });
|
|
19
|
-
|
|
20
|
-
// Create a reusable builder
|
|
21
|
-
const runAgent = createBuilder({
|
|
22
|
-
sandboxOptions: { sharedModules: ["react"] },
|
|
23
|
-
build: async (sandbox, prompt) => {
|
|
24
|
-
// Your agent logic here - execute commands via sandbox.bash.exec()
|
|
25
|
-
await sandbox.bash.exec(
|
|
26
|
-
'echo "export const App = () => <div>Hello</div>" > /src/index.tsx',
|
|
27
|
-
);
|
|
28
|
-
await sandbox.bash.exec("build /src/index.tsx");
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
// Run with a prompt
|
|
33
|
-
const result = await runAgent("Create a counter component");
|
|
34
|
-
|
|
35
|
-
if (result.module?.App) {
|
|
36
|
-
// Use the generated component
|
|
37
|
-
const App = result.module.App as React.ComponentType;
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Builder API
|
|
42
|
-
|
|
43
|
-
The `createBuilder()` function is the primary API for agent workflows. It handles sandbox lifecycle, build capture, validation, and cancellation.
|
|
44
|
-
|
|
45
|
-
### `createBuilder(options)`
|
|
46
|
-
|
|
47
|
-
Returns a reusable builder function that can be called with different prompts.
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
const runAgent = createBuilder<T>({
|
|
51
|
-
// Sandbox configuration (pick one)
|
|
52
|
-
sandbox?: Sandbox, // Reuse an existing sandbox (state persists between calls)
|
|
53
|
-
sandboxOptions?: SandboxOptions, // Create fresh sandbox per call (isolated runs)
|
|
54
|
-
|
|
55
|
-
// Your agent logic
|
|
56
|
-
build: (sandbox: Sandbox, prompt: string) => Promise<T>,
|
|
57
|
-
});
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
#### Options
|
|
61
|
-
|
|
62
|
-
| Option | Type | Description |
|
|
63
|
-
| ---------------- | --------------------------------- | ------------------------------------------------------- |
|
|
64
|
-
| `sandbox` | `Sandbox` | Existing sandbox to reuse. Files persist between calls. |
|
|
65
|
-
| `sandboxOptions` | `SandboxOptions` | Options for creating fresh sandboxes per call. |
|
|
66
|
-
| `build` | `(sandbox, prompt) => Promise<T>` | Your agent logic. Receives the sandbox and prompt. |
|
|
67
|
-
|
|
68
|
-
### Calling the Builder
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
const result = await runAgent(prompt, options?);
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
#### Call Options
|
|
75
|
-
|
|
76
|
-
| Option | Type | Description |
|
|
77
|
-
| ---------- | --------------- | --------------------------------------------------------------- |
|
|
78
|
-
| `validate` | `(module) => M` | Validate exports during build. Errors are visible to the agent. |
|
|
79
|
-
| `timeout` | `number` | Max time in ms. Throws `AbortError` if exceeded. |
|
|
80
|
-
| `signal` | `AbortSignal` | For external cancellation. |
|
|
81
|
-
|
|
82
|
-
#### Result
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
interface BuildResult<T, M> {
|
|
86
|
-
result: T | undefined; // Return value from your build function
|
|
87
|
-
error: Error | null; // Error if build function threw
|
|
88
|
-
bundle: BundleResult | null; // The compiled JavaScript bundle
|
|
89
|
-
module: M | null; // Loaded module exports (validated if validate provided)
|
|
90
|
-
sandbox: Sandbox; // The sandbox used (for inspection or reuse)
|
|
91
|
-
}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### Validation
|
|
95
|
-
|
|
96
|
-
Validation runs as part of the `build` command. If it throws, the build fails and the agent sees the error, allowing it to fix the code and retry.
|
|
97
|
-
|
|
98
|
-
```typescript
|
|
99
|
-
const result = await runAgent("Create a counter", {
|
|
100
|
-
validate: (mod) => {
|
|
101
|
-
if (typeof mod.App !== "function") {
|
|
102
|
-
throw new Error("Must export an App component");
|
|
103
|
-
}
|
|
104
|
-
return { App: mod.App as React.ComponentType };
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
// result.module is typed as { App: React.ComponentType } | null
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
With Zod:
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
import { z } from "zod";
|
|
114
|
-
|
|
115
|
-
const Schema = z.object({
|
|
116
|
-
App: z.custom<React.ComponentType>((v) => typeof v === "function"),
|
|
117
|
-
initialCount: z.number().optional(),
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const result = await runAgent("Create a counter", {
|
|
121
|
-
validate: (mod) => Schema.parse(mod),
|
|
122
|
-
});
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### Cancellation
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
const controller = new AbortController();
|
|
129
|
-
|
|
130
|
-
const promise = runAgent("Create a dashboard", {
|
|
131
|
-
signal: controller.signal,
|
|
132
|
-
timeout: 60_000, // 1 minute
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
// Cancel on user action
|
|
136
|
-
cancelButton.onclick = () => controller.abort();
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
## Sandbox API
|
|
140
|
-
|
|
141
|
-
For lower-level control, use `createSandbox()` directly.
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
import { createSandbox } from "sandlot";
|
|
145
|
-
|
|
146
|
-
const sandbox = await createSandbox({
|
|
147
|
-
initialFiles: {
|
|
148
|
-
"/src/index.ts": "export const x = 1;",
|
|
149
|
-
"/tsconfig.json": JSON.stringify({ compilerOptions: { strict: true } }),
|
|
150
|
-
},
|
|
151
|
-
sharedModules: ["react", "react-dom/client"],
|
|
152
|
-
onBuild: (result) => console.log("Build succeeded:", result),
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
// Execute shell commands
|
|
156
|
-
await sandbox.bash.exec("tsc /src/index.ts"); // Type check
|
|
157
|
-
await sandbox.bash.exec("build /src/index.ts"); // Bundle
|
|
158
|
-
await sandbox.bash.exec("install lodash"); // Install package
|
|
159
|
-
await sandbox.bash.exec("list"); // List packages
|
|
160
|
-
|
|
161
|
-
// Access the last successful build
|
|
162
|
-
if (sandbox.lastBuild) {
|
|
163
|
-
const { bundle, module } = sandbox.lastBuild;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Serialize state for persistence
|
|
167
|
-
const state = sandbox.getState();
|
|
168
|
-
localStorage.setItem("project", JSON.stringify(state));
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### Sandbox Options
|
|
172
|
-
|
|
173
|
-
| Option | Type | Description |
|
|
174
|
-
| --------------- | ------------------------ | --------------------------------------------------- |
|
|
175
|
-
| `initialFiles` | `Record<string, string>` | Files to populate the filesystem with. |
|
|
176
|
-
| `sharedModules` | `string[]` | Modules to resolve from host (e.g., `['react']`). |
|
|
177
|
-
| `tsconfigPath` | `string` | Path to tsconfig.json (default: `/tsconfig.json`). |
|
|
178
|
-
| `onBuild` | `(result) => void` | Callback when a build succeeds. |
|
|
179
|
-
| `bashOptions` | `SandboxBashOptions` | Options for the just-bash shell (env, limits). |
|
|
180
|
-
|
|
181
|
-
## Shell Commands
|
|
182
|
-
|
|
183
|
-
The sandbox provides these built-in commands:
|
|
184
|
-
|
|
185
|
-
| Command | Description |
|
|
186
|
-
| ------------------------- | ----------------------------------- |
|
|
187
|
-
| `tsc [entry]` | Type check (uses tsconfig.json) |
|
|
188
|
-
| `build [entry] [options]` | Bundle (runs typecheck first) |
|
|
189
|
-
| `install <pkg>` | Install npm package (fetches types) |
|
|
190
|
-
| `uninstall <pkg>` | Remove package |
|
|
191
|
-
| `list` | List installed packages |
|
|
192
|
-
| `run <entry>` | Execute a script |
|
|
193
|
-
|
|
194
|
-
Build options: `--format <esm\|iife\|cjs>`, `--minify`, `--skip-typecheck`
|
|
195
|
-
|
|
196
|
-
## Shared Modules
|
|
197
|
-
|
|
198
|
-
To avoid duplicate library instances (important for React context/hooks), register shared modules before creating sandboxes:
|
|
199
|
-
|
|
200
|
-
```typescript
|
|
201
|
-
import { registerSharedModules } from "sandlot";
|
|
202
|
-
import * as React from "react";
|
|
203
|
-
import * as ReactDOM from "react-dom/client";
|
|
204
|
-
|
|
205
|
-
registerSharedModules({
|
|
206
|
-
react: React,
|
|
207
|
-
"react-dom/client": ReactDOM,
|
|
208
|
-
});
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
Then include them in `sharedModules` when creating a sandbox.
|
|
212
|
-
|
|
213
|
-
## Cross-Origin Isolation
|
|
214
|
-
|
|
215
|
-
For optimal esbuild-wasm performance, enable cross-origin isolation by adding these headers to your dev server:
|
|
216
|
-
|
|
217
|
-
```
|
|
218
|
-
Cross-Origin-Embedder-Policy: require-corp
|
|
219
|
-
Cross-Origin-Opener-Policy: same-origin
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
In Vite:
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
export default defineConfig({
|
|
226
|
-
plugins: [
|
|
227
|
-
{
|
|
228
|
-
name: "isolation",
|
|
229
|
-
configureServer: (server) => {
|
|
230
|
-
server.middlewares.use((_, res, next) => {
|
|
231
|
-
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
|
|
232
|
-
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
|
|
233
|
-
next();
|
|
234
|
-
});
|
|
235
|
-
},
|
|
236
|
-
},
|
|
237
|
-
],
|
|
238
|
-
});
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
## License
|
|
242
|
-
|
|
243
|
-
MIT
|
package/dist/build-emitter.d.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Build event emitter for sandbox environments.
|
|
3
|
-
*
|
|
4
|
-
* Simple typed event emitter for successful build results.
|
|
5
|
-
* Used internally by the sandbox to notify listeners when a build succeeds.
|
|
6
|
-
*/
|
|
7
|
-
import type { BuildOutput } from "./commands/types";
|
|
8
|
-
/**
|
|
9
|
-
* Simple typed event emitter for build results.
|
|
10
|
-
*
|
|
11
|
-
* Only emits on successful builds—build failures are communicated via
|
|
12
|
-
* the bash command's exit code and stderr.
|
|
13
|
-
*
|
|
14
|
-
* For most use cases, prefer using `createBuilder()` which handles
|
|
15
|
-
* build result capture automatically.
|
|
16
|
-
*/
|
|
17
|
-
export declare class BuildEmitter {
|
|
18
|
-
private listeners;
|
|
19
|
-
/**
|
|
20
|
-
* Emit a build result to all listeners.
|
|
21
|
-
* Called internally when a build command succeeds.
|
|
22
|
-
*/
|
|
23
|
-
emit: (result: BuildOutput) => Promise<void>;
|
|
24
|
-
/**
|
|
25
|
-
* Subscribe to build events. Returns an unsubscribe function.
|
|
26
|
-
*
|
|
27
|
-
* The callback is invoked each time a build succeeds, receiving
|
|
28
|
-
* the BuildOutput with the bundle and loaded module.
|
|
29
|
-
*
|
|
30
|
-
* @example
|
|
31
|
-
* ```ts
|
|
32
|
-
* let lastBuild: BuildOutput | null = null;
|
|
33
|
-
* const unsubscribe = sandbox.onBuild((result) => {
|
|
34
|
-
* lastBuild = result;
|
|
35
|
-
* });
|
|
36
|
-
*
|
|
37
|
-
* await sandbox.bash.exec('build /src/index.ts');
|
|
38
|
-
* unsubscribe();
|
|
39
|
-
*
|
|
40
|
-
* if (lastBuild) {
|
|
41
|
-
* const App = lastBuild.module.App as React.ComponentType;
|
|
42
|
-
* }
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
on(callback: (result: BuildOutput) => void | Promise<void>): () => void;
|
|
46
|
-
}
|
|
47
|
-
//# sourceMappingURL=build-emitter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"build-emitter.d.ts","sourceRoot":"","sources":["../src/build-emitter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;GAQG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,SAAS,CAA4D;IAE7E;;;OAGG;IACH,IAAI,GAAU,QAAQ,WAAW,KAAG,OAAO,CAAC,IAAI,CAAC,CAS/C;IAEF;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI;CAMxE"}
|
package/dist/builder.d.ts
DELETED
|
@@ -1,370 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* High-level builder for sandbox-based agent workflows.
|
|
3
|
-
*
|
|
4
|
-
* Provides a simple API that handles sandbox creation, build result capture,
|
|
5
|
-
* validation, and timeout/cancellation—letting the caller focus on their agent logic.
|
|
6
|
-
*/
|
|
7
|
-
import { type Sandbox, type SandboxOptions } from "./sandbox";
|
|
8
|
-
import type { BundleResult } from "./bundler";
|
|
9
|
-
/**
|
|
10
|
-
* Result of running a builder.
|
|
11
|
-
*
|
|
12
|
-
* @typeParam T - The return type of the build function
|
|
13
|
-
* @typeParam M - The type of the validated module (defaults to Record<string, unknown>)
|
|
14
|
-
*/
|
|
15
|
-
export interface BuildResult<T, M = Record<string, unknown>> {
|
|
16
|
-
/**
|
|
17
|
-
* Whatever the `build` function returned, or `undefined` if it threw.
|
|
18
|
-
*/
|
|
19
|
-
result: T | undefined;
|
|
20
|
-
/**
|
|
21
|
-
* The error thrown by the `build` function, or `null` if it succeeded.
|
|
22
|
-
*
|
|
23
|
-
* When an error occurs, the bundle and module may still be available
|
|
24
|
-
* if a build succeeded before the error was thrown.
|
|
25
|
-
*/
|
|
26
|
-
error: Error | null;
|
|
27
|
-
/**
|
|
28
|
-
* The last successful build result, or null if no build succeeded.
|
|
29
|
-
*
|
|
30
|
-
* This captures the bundle from any successful `build` command executed
|
|
31
|
-
* during the run. If multiple builds succeed, this contains the last one.
|
|
32
|
-
*
|
|
33
|
-
* **Important**: This is available even if the `build` function threw an error,
|
|
34
|
-
* as long as a build succeeded before the error occurred.
|
|
35
|
-
*/
|
|
36
|
-
bundle: BundleResult | null;
|
|
37
|
-
/**
|
|
38
|
-
* The loaded module exports, or null if no bundle was produced.
|
|
39
|
-
*
|
|
40
|
-
* When a build succeeds, the bundle is automatically loaded. If a `validate`
|
|
41
|
-
* function was provided, the module is passed through it and the result is
|
|
42
|
-
* available here with the validated type.
|
|
43
|
-
*
|
|
44
|
-
* @example Without validation
|
|
45
|
-
* ```ts
|
|
46
|
-
* const result = await runAgent("Create a counter");
|
|
47
|
-
* result.module // Record<string, unknown> | null
|
|
48
|
-
* ```
|
|
49
|
-
*
|
|
50
|
-
* @example With validation
|
|
51
|
-
* ```ts
|
|
52
|
-
* const result = await runAgent("Create a counter", {
|
|
53
|
-
* validate: (mod) => ({ App: mod.App as React.ComponentType }),
|
|
54
|
-
* });
|
|
55
|
-
* result.module // { App: React.ComponentType } | null
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
module: M | null;
|
|
59
|
-
/**
|
|
60
|
-
* The sandbox that was used.
|
|
61
|
-
*
|
|
62
|
-
* Useful when the builder created an ephemeral sandbox—you can inspect
|
|
63
|
-
* its state, save it, or reuse it for another build.
|
|
64
|
-
*/
|
|
65
|
-
sandbox: Sandbox;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Options passed when calling the builder function.
|
|
69
|
-
*
|
|
70
|
-
* @typeParam M - The type returned by the validate function (if provided)
|
|
71
|
-
*/
|
|
72
|
-
export interface BuildCallOptions<M = Record<string, unknown>> {
|
|
73
|
-
/**
|
|
74
|
-
* Validation function for the built module.
|
|
75
|
-
*
|
|
76
|
-
* When provided, this function runs as part of the build command—after
|
|
77
|
-
* bundling and loading, but before the build is considered successful.
|
|
78
|
-
* If validation throws, the build fails and the agent sees the error,
|
|
79
|
-
* giving it a chance to fix the code and try again.
|
|
80
|
-
*
|
|
81
|
-
* The return type determines the type of `result.module`.
|
|
82
|
-
*
|
|
83
|
-
* @example Simple validation
|
|
84
|
-
* ```ts
|
|
85
|
-
* const result = await runAgent("Create a counter", {
|
|
86
|
-
* validate: (mod) => {
|
|
87
|
-
* if (typeof mod.App !== 'function') {
|
|
88
|
-
* throw new Error("Module must export an App component");
|
|
89
|
-
* }
|
|
90
|
-
* return { App: mod.App as React.ComponentType };
|
|
91
|
-
* },
|
|
92
|
-
* });
|
|
93
|
-
* // If validation fails, agent sees: "Build failed: Validation error."
|
|
94
|
-
* // Agent can fix the code and try again
|
|
95
|
-
* result.module?.App // React.ComponentType (after successful build)
|
|
96
|
-
* ```
|
|
97
|
-
*
|
|
98
|
-
* @example With Zod
|
|
99
|
-
* ```ts
|
|
100
|
-
* import { z } from 'zod';
|
|
101
|
-
*
|
|
102
|
-
* const CounterSchema = z.object({
|
|
103
|
-
* App: z.custom<React.ComponentType>((v) => typeof v === 'function'),
|
|
104
|
-
* initialCount: z.number().optional(),
|
|
105
|
-
* });
|
|
106
|
-
*
|
|
107
|
-
* const result = await runAgent("Create a counter", {
|
|
108
|
-
* validate: (mod) => CounterSchema.parse(mod),
|
|
109
|
-
* });
|
|
110
|
-
* result.module?.App // React.ComponentType
|
|
111
|
-
* result.module?.initialCount // number | undefined
|
|
112
|
-
* ```
|
|
113
|
-
*/
|
|
114
|
-
validate?: (module: Record<string, unknown>) => M;
|
|
115
|
-
/**
|
|
116
|
-
* Maximum time in milliseconds for the build to complete.
|
|
117
|
-
*
|
|
118
|
-
* If the timeout is exceeded, the build is aborted and an error is thrown.
|
|
119
|
-
* The agent's partial work may still be available in the sandbox.
|
|
120
|
-
*
|
|
121
|
-
* @example
|
|
122
|
-
* ```ts
|
|
123
|
-
* const result = await runAgent("Create a complex dashboard", {
|
|
124
|
-
* timeout: 300_000, // 5 minutes
|
|
125
|
-
* });
|
|
126
|
-
* ```
|
|
127
|
-
*/
|
|
128
|
-
timeout?: number;
|
|
129
|
-
/**
|
|
130
|
-
* AbortSignal for cancelling the build.
|
|
131
|
-
*
|
|
132
|
-
* If the signal is aborted, the build stops and an error is thrown.
|
|
133
|
-
* Useful for user-initiated cancellation or external timeout management.
|
|
134
|
-
*
|
|
135
|
-
* @example
|
|
136
|
-
* ```ts
|
|
137
|
-
* const controller = new AbortController();
|
|
138
|
-
*
|
|
139
|
-
* // Start the build
|
|
140
|
-
* const promise = runAgent("Create a counter", {
|
|
141
|
-
* signal: controller.signal,
|
|
142
|
-
* });
|
|
143
|
-
*
|
|
144
|
-
* // Cancel after 10 seconds
|
|
145
|
-
* setTimeout(() => controller.abort(), 10_000);
|
|
146
|
-
*
|
|
147
|
-
* try {
|
|
148
|
-
* const result = await promise;
|
|
149
|
-
* } catch (err) {
|
|
150
|
-
* if (err.name === 'AbortError') {
|
|
151
|
-
* console.log('Build was cancelled');
|
|
152
|
-
* }
|
|
153
|
-
* }
|
|
154
|
-
* ```
|
|
155
|
-
*/
|
|
156
|
-
signal?: AbortSignal;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Options for creating a reusable builder function.
|
|
160
|
-
*/
|
|
161
|
-
export interface CreateBuilderOptions<T> {
|
|
162
|
-
/**
|
|
163
|
-
* Existing sandbox to reuse across all calls.
|
|
164
|
-
*
|
|
165
|
-
* When provided, the same sandbox is used for every call to the returned
|
|
166
|
-
* builder function. Files and state persist between runs—useful for
|
|
167
|
-
* iterative workflows where you want to build on previous work.
|
|
168
|
-
*
|
|
169
|
-
* @example
|
|
170
|
-
* ```ts
|
|
171
|
-
* const sandbox = await createSandbox({
|
|
172
|
-
* initialFiles: { '/src/utils.ts': 'export const PI = 3.14;' },
|
|
173
|
-
* });
|
|
174
|
-
*
|
|
175
|
-
* const runAgent = createBuilder({
|
|
176
|
-
* sandbox, // Reused across all calls
|
|
177
|
-
* build: async (sb, prompt) => myAgent.run(sb, prompt),
|
|
178
|
-
* });
|
|
179
|
-
*
|
|
180
|
-
* await runAgent("Create a circle component"); // Uses existing utils.ts
|
|
181
|
-
* await runAgent("Add a square component"); // Still has circle + utils
|
|
182
|
-
* ```
|
|
183
|
-
*/
|
|
184
|
-
sandbox?: Sandbox;
|
|
185
|
-
/**
|
|
186
|
-
* Options for creating fresh sandboxes (only used if `sandbox` is not provided).
|
|
187
|
-
*
|
|
188
|
-
* Each call to the returned builder function creates a new sandbox with
|
|
189
|
-
* these options. Use this when you want isolated runs.
|
|
190
|
-
*
|
|
191
|
-
* @example
|
|
192
|
-
* ```ts
|
|
193
|
-
* const runAgent = createBuilder({
|
|
194
|
-
* sandboxOptions: {
|
|
195
|
-
* sharedModules: ['react', 'react-dom/client'],
|
|
196
|
-
* },
|
|
197
|
-
* build: async (sandbox, prompt) => myAgent.run(sandbox, prompt),
|
|
198
|
-
* });
|
|
199
|
-
*
|
|
200
|
-
* // Each call gets a fresh sandbox
|
|
201
|
-
* await runAgent("Create a counter"); // Fresh sandbox
|
|
202
|
-
* await runAgent("Create a todo list"); // Another fresh sandbox
|
|
203
|
-
* ```
|
|
204
|
-
*/
|
|
205
|
-
sandboxOptions?: SandboxOptions;
|
|
206
|
-
/**
|
|
207
|
-
* The function to build with the sandbox and prompt.
|
|
208
|
-
*
|
|
209
|
-
* This receives the sandbox and the prompt string, and should return
|
|
210
|
-
* whatever result your agent produces.
|
|
211
|
-
*
|
|
212
|
-
* @example
|
|
213
|
-
* ```ts
|
|
214
|
-
* const runAgent = createBuilder({
|
|
215
|
-
* build: async (sandbox, prompt) => {
|
|
216
|
-
* const agent = new MyAgent({
|
|
217
|
-
* tools: { bash: sandbox.bash.exec },
|
|
218
|
-
* });
|
|
219
|
-
* return agent.run(prompt);
|
|
220
|
-
* },
|
|
221
|
-
* });
|
|
222
|
-
* ```
|
|
223
|
-
*/
|
|
224
|
-
build: (sandbox: Sandbox, prompt: string) => Promise<T>;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* The builder function returned by `createBuilder`.
|
|
228
|
-
*
|
|
229
|
-
* Can be called with just a prompt, or with options including validation,
|
|
230
|
-
* timeout, and abort signal.
|
|
231
|
-
*/
|
|
232
|
-
export interface BuilderFn<T> {
|
|
233
|
-
/**
|
|
234
|
-
* Run the builder with a prompt (no options).
|
|
235
|
-
* Module will be typed as `Record<string, unknown>`.
|
|
236
|
-
*/
|
|
237
|
-
(prompt: string): Promise<BuildResult<T>>;
|
|
238
|
-
/**
|
|
239
|
-
* Run the builder with a prompt and options.
|
|
240
|
-
* If `validate` is provided, module will be typed based on its return type.
|
|
241
|
-
*/
|
|
242
|
-
<M = Record<string, unknown>>(prompt: string, options: BuildCallOptions<M>): Promise<BuildResult<T, M>>;
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Create a reusable builder function for running prompts in a sandbox.
|
|
246
|
-
*
|
|
247
|
-
* This is the main API for sandlot. Define your agent logic once, then call
|
|
248
|
-
* the returned function with different prompts. Each call:
|
|
249
|
-
*
|
|
250
|
-
* 1. Creates a sandbox (or uses one you provide)
|
|
251
|
-
* 2. Sets up build result capture
|
|
252
|
-
* 3. Runs your build function with the prompt
|
|
253
|
-
* 4. Returns everything: your result, the bundle, the module, and the sandbox
|
|
254
|
-
*
|
|
255
|
-
* **Sandbox behavior:**
|
|
256
|
-
* - If you provide `sandbox`: The same sandbox is reused for every call
|
|
257
|
-
* (files persist, good for iteration)
|
|
258
|
-
* - If you provide `sandboxOptions` (or nothing): A fresh sandbox is created
|
|
259
|
-
* for each call (isolated runs)
|
|
260
|
-
*
|
|
261
|
-
* **Validation behavior:**
|
|
262
|
-
* When you provide a `validate` function, it runs as part of the build command.
|
|
263
|
-
* If validation fails, the build fails and the agent sees the error—giving it
|
|
264
|
-
* a chance to fix the code and try again. This is more powerful than post-hoc
|
|
265
|
-
* validation because the agent can iterate on validation errors.
|
|
266
|
-
*
|
|
267
|
-
* @example Basic usage
|
|
268
|
-
* ```ts
|
|
269
|
-
* import { createBuilder } from 'sandlot';
|
|
270
|
-
*
|
|
271
|
-
* const runAgent = createBuilder({
|
|
272
|
-
* sandboxOptions: { sharedModules: ['react', 'react-dom/client'] },
|
|
273
|
-
* build: async (sandbox, prompt) => {
|
|
274
|
-
* const agent = new MyAgent({ tools: { bash: sandbox.bash.exec } });
|
|
275
|
-
* return agent.run(prompt);
|
|
276
|
-
* },
|
|
277
|
-
* });
|
|
278
|
-
*
|
|
279
|
-
* // Use it multiple times with different prompts
|
|
280
|
-
* const result1 = await runAgent("Create a counter component");
|
|
281
|
-
* const result2 = await runAgent("Create a todo list");
|
|
282
|
-
*
|
|
283
|
-
* if (result1.module?.App) {
|
|
284
|
-
* const Counter = result1.module.App as React.ComponentType;
|
|
285
|
-
* }
|
|
286
|
-
* ```
|
|
287
|
-
*
|
|
288
|
-
* @example With validation (agent can fix validation errors)
|
|
289
|
-
* ```ts
|
|
290
|
-
* const runAgent = createBuilder({
|
|
291
|
-
* sandboxOptions: { sharedModules: ['react'] },
|
|
292
|
-
* build: async (sandbox, prompt) => myAgent.run(sandbox, prompt),
|
|
293
|
-
* });
|
|
294
|
-
*
|
|
295
|
-
* // Validation runs during build - agent sees errors and can fix them
|
|
296
|
-
* const counter = await runAgent("Create a counter", {
|
|
297
|
-
* validate: (mod) => {
|
|
298
|
-
* if (typeof mod.App !== 'function') {
|
|
299
|
-
* throw new Error("Must export an App component");
|
|
300
|
-
* }
|
|
301
|
-
* return { App: mod.App as React.ComponentType };
|
|
302
|
-
* },
|
|
303
|
-
* });
|
|
304
|
-
* // If agent's first attempt fails validation, it sees:
|
|
305
|
-
* // "Build failed: Validation error. Must export an App component"
|
|
306
|
-
* // Agent can then fix the code and run build again
|
|
307
|
-
* ```
|
|
308
|
-
*
|
|
309
|
-
* @example With Zod validation
|
|
310
|
-
* ```ts
|
|
311
|
-
* import { z } from 'zod';
|
|
312
|
-
*
|
|
313
|
-
* const CounterSchema = z.object({
|
|
314
|
-
* App: z.custom<React.ComponentType>((v) => typeof v === 'function'),
|
|
315
|
-
* initialCount: z.number().default(0),
|
|
316
|
-
* });
|
|
317
|
-
*
|
|
318
|
-
* const result = await runAgent("Create a counter", {
|
|
319
|
-
* validate: (mod) => CounterSchema.parse(mod),
|
|
320
|
-
* });
|
|
321
|
-
* // result.module is fully typed from Zod inference
|
|
322
|
-
* ```
|
|
323
|
-
*
|
|
324
|
-
* @example Iterative workflow with shared sandbox
|
|
325
|
-
* ```ts
|
|
326
|
-
* const sandbox = await createSandbox();
|
|
327
|
-
*
|
|
328
|
-
* const runAgent = createBuilder({
|
|
329
|
-
* sandbox, // Same sandbox for all calls
|
|
330
|
-
* build: async (sb, prompt) => myAgent.run(sb, prompt),
|
|
331
|
-
* });
|
|
332
|
-
*
|
|
333
|
-
* // First prompt creates initial component
|
|
334
|
-
* await runAgent("Create a button component");
|
|
335
|
-
*
|
|
336
|
-
* // Second prompt can build on the first
|
|
337
|
-
* await runAgent("Add a click counter to the button");
|
|
338
|
-
* ```
|
|
339
|
-
*
|
|
340
|
-
* @example With timeout
|
|
341
|
-
* ```ts
|
|
342
|
-
* // Complex tasks get more time
|
|
343
|
-
* const result = await runAgent("Create a full dashboard with charts", {
|
|
344
|
-
* timeout: 300_000, // 5 minutes
|
|
345
|
-
* });
|
|
346
|
-
* ```
|
|
347
|
-
*
|
|
348
|
-
* @example With abort signal for cancellation
|
|
349
|
-
* ```ts
|
|
350
|
-
* const controller = new AbortController();
|
|
351
|
-
*
|
|
352
|
-
* // Start the build
|
|
353
|
-
* const promise = runAgent("Create a counter", {
|
|
354
|
-
* signal: controller.signal,
|
|
355
|
-
* });
|
|
356
|
-
*
|
|
357
|
-
* // User clicks cancel button
|
|
358
|
-
* cancelButton.onclick = () => controller.abort();
|
|
359
|
-
*
|
|
360
|
-
* try {
|
|
361
|
-
* const result = await promise;
|
|
362
|
-
* } catch (err) {
|
|
363
|
-
* if (err.name === 'AbortError') {
|
|
364
|
-
* console.log('Build was cancelled by user');
|
|
365
|
-
* }
|
|
366
|
-
* }
|
|
367
|
-
* ```
|
|
368
|
-
*/
|
|
369
|
-
export declare function createBuilder<T>(options: CreateBuilderOptions<T>): BuilderFn<T>;
|
|
370
|
-
//# sourceMappingURL=builder.d.ts.map
|
package/dist/builder.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAiB,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C;;;;;GAKG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACzD;;OAEG;IACH,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC;IAEtB;;;;;OAKG;IACH,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAEpB;;;;;;;;OAQG;IACH,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAE5B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC;IAEjB;;;;;OAKG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwCG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAElD;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACzD;AAED;;;;;GAKG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B;;;OAGG;IACH,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAE1C;;;OAGG;IACH,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;CACzG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4HG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAiH/E"}
|