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.
Files changed (115) hide show
  1. package/dist/browser/bundler.d.ts +68 -0
  2. package/dist/browser/bundler.d.ts.map +1 -0
  3. package/dist/browser/executor.d.ts +46 -0
  4. package/dist/browser/executor.d.ts.map +1 -0
  5. package/dist/browser/index.d.ts +9 -0
  6. package/dist/browser/index.d.ts.map +1 -0
  7. package/dist/browser/index.js +2692 -0
  8. package/dist/browser/preset.d.ts +63 -0
  9. package/dist/browser/preset.d.ts.map +1 -0
  10. package/dist/commands/index.d.ts +20 -11
  11. package/dist/commands/index.d.ts.map +1 -1
  12. package/dist/commands/types.d.ts +31 -132
  13. package/dist/commands/types.d.ts.map +1 -1
  14. package/dist/core/bundler-utils.d.ts +142 -0
  15. package/dist/core/bundler-utils.d.ts.map +1 -0
  16. package/dist/core/esm-types-resolver.d.ts +125 -0
  17. package/dist/core/esm-types-resolver.d.ts.map +1 -0
  18. package/dist/core/executor.d.ts +35 -0
  19. package/dist/core/executor.d.ts.map +1 -0
  20. package/dist/{fs.d.ts → core/fs.d.ts} +27 -29
  21. package/dist/core/fs.d.ts.map +1 -0
  22. package/dist/core/sandbox.d.ts +30 -0
  23. package/dist/core/sandbox.d.ts.map +1 -0
  24. package/dist/core/sandlot.d.ts +30 -0
  25. package/dist/core/sandlot.d.ts.map +1 -0
  26. package/dist/core/shared-module-registry.d.ts +46 -0
  27. package/dist/core/shared-module-registry.d.ts.map +1 -0
  28. package/dist/core/typechecker.d.ts +60 -0
  29. package/dist/core/typechecker.d.ts.map +1 -0
  30. package/dist/index.d.ts +11 -16
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +1399 -2010
  33. package/dist/node/bundler.d.ts +48 -0
  34. package/dist/node/bundler.d.ts.map +1 -0
  35. package/dist/node/executor.d.ts +48 -0
  36. package/dist/node/executor.d.ts.map +1 -0
  37. package/dist/node/index.d.ts +9 -0
  38. package/dist/node/index.d.ts.map +1 -0
  39. package/dist/node/index.js +2646 -0
  40. package/dist/node/preset.d.ts +62 -0
  41. package/dist/node/preset.d.ts.map +1 -0
  42. package/dist/types.d.ts +525 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/package.json +16 -6
  45. package/src/browser/bundler.ts +294 -0
  46. package/src/browser/executor.ts +71 -0
  47. package/src/browser/index.ts +57 -0
  48. package/src/browser/preset.ts +179 -0
  49. package/src/commands/index.ts +526 -43
  50. package/src/commands/types.ts +82 -146
  51. package/src/core/bundler-utils.ts +630 -0
  52. package/src/core/esm-types-resolver.ts +432 -0
  53. package/src/core/executor.ts +161 -0
  54. package/src/{fs.ts → core/fs.ts} +59 -37
  55. package/src/core/sandbox.ts +621 -0
  56. package/src/core/sandlot.ts +77 -0
  57. package/src/core/shared-module-registry.ts +138 -0
  58. package/src/core/typechecker.ts +607 -0
  59. package/src/index.ts +104 -139
  60. package/src/node/bundler.ts +194 -0
  61. package/src/node/executor.ts +87 -0
  62. package/src/node/index.ts +39 -0
  63. package/src/node/preset.ts +178 -0
  64. package/src/types.ts +668 -0
  65. package/README.md +0 -243
  66. package/dist/build-emitter.d.ts +0 -47
  67. package/dist/build-emitter.d.ts.map +0 -1
  68. package/dist/builder.d.ts +0 -370
  69. package/dist/builder.d.ts.map +0 -1
  70. package/dist/bundler.d.ts +0 -152
  71. package/dist/bundler.d.ts.map +0 -1
  72. package/dist/commands/compile.d.ts +0 -13
  73. package/dist/commands/compile.d.ts.map +0 -1
  74. package/dist/commands/packages.d.ts +0 -17
  75. package/dist/commands/packages.d.ts.map +0 -1
  76. package/dist/commands/run.d.ts +0 -40
  77. package/dist/commands/run.d.ts.map +0 -1
  78. package/dist/commands.d.ts +0 -179
  79. package/dist/commands.d.ts.map +0 -1
  80. package/dist/fs.d.ts.map +0 -1
  81. package/dist/internal.d.ts +0 -79
  82. package/dist/internal.d.ts.map +0 -1
  83. package/dist/internal.js +0 -1942
  84. package/dist/loader.d.ts +0 -164
  85. package/dist/loader.d.ts.map +0 -1
  86. package/dist/packages.d.ts +0 -199
  87. package/dist/packages.d.ts.map +0 -1
  88. package/dist/runner.d.ts +0 -314
  89. package/dist/runner.d.ts.map +0 -1
  90. package/dist/sandbox-manager.d.ts +0 -261
  91. package/dist/sandbox-manager.d.ts.map +0 -1
  92. package/dist/sandbox.d.ts +0 -267
  93. package/dist/sandbox.d.ts.map +0 -1
  94. package/dist/shared-modules.d.ts +0 -148
  95. package/dist/shared-modules.d.ts.map +0 -1
  96. package/dist/shared-resources.d.ts +0 -102
  97. package/dist/shared-resources.d.ts.map +0 -1
  98. package/dist/ts-libs.d.ts +0 -85
  99. package/dist/ts-libs.d.ts.map +0 -1
  100. package/dist/typechecker.d.ts +0 -127
  101. package/dist/typechecker.d.ts.map +0 -1
  102. package/src/build-emitter.ts +0 -64
  103. package/src/builder.ts +0 -498
  104. package/src/bundler.ts +0 -575
  105. package/src/commands/compile.ts +0 -236
  106. package/src/commands/packages.ts +0 -154
  107. package/src/commands/run.ts +0 -245
  108. package/src/internal.ts +0 -119
  109. package/src/loader.ts +0 -229
  110. package/src/packages.ts +0 -936
  111. package/src/sandbox.ts +0 -398
  112. package/src/shared-modules.ts +0 -280
  113. package/src/shared-resources.ts +0 -166
  114. package/src/ts-libs.ts +0 -218
  115. 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
@@ -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
@@ -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"}