@illuma-ai/code-sandbox 1.3.1 → 1.4.1

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/src/types.ts DELETED
@@ -1,375 +0,0 @@
1
- /**
2
- * @illuma-ai/code-sandbox — Type definitions
3
- *
4
- * Core types for the browser-native code sandbox.
5
- * Covers file maps, runtime states, imperative handle, and component props.
6
- */
7
-
8
- // ---------------------------------------------------------------------------
9
- // File System
10
- // ---------------------------------------------------------------------------
11
-
12
- /** A flat map of file paths to their string contents */
13
- export type FileMap = Record<string, string>;
14
-
15
- /** Represents a single file or directory node in the tree */
16
- export interface FileNode {
17
- name: string;
18
- path: string;
19
- type: "file" | "directory";
20
- children?: FileNode[];
21
- }
22
-
23
- /**
24
- * Change status for a file relative to the baseline (original) snapshot.
25
- *
26
- * - `new`: File exists in current but not in original
27
- * - `modified`: File exists in both but content differs
28
- * - `deleted`: File exists in original but not in current
29
- * - `unchanged`: File content is identical
30
- */
31
- export type FileChangeStatus = "new" | "modified" | "deleted" | "unchanged";
32
-
33
- // ---------------------------------------------------------------------------
34
- // Errors (structured error types for AI agent consumption)
35
- // ---------------------------------------------------------------------------
36
-
37
- /**
38
- * Categories of errors that can occur in the sandbox.
39
- *
40
- * - `process-stderr`: Output written to stderr by the Node.js process
41
- * - `process-exit`: Process exited with a non-zero code
42
- * - `runtime-exception`: Uncaught exception in the Node.js runtime (Nodepod)
43
- * - `browser-error`: JavaScript error in the preview iframe (window.onerror)
44
- * - `browser-unhandled-rejection`: Unhandled promise rejection in the iframe
45
- * - `browser-console-error`: console.error() calls in the iframe
46
- * - `compilation`: Syntax/import errors detected at module load time
47
- * - `network`: Failed HTTP requests from the preview (fetch/XHR errors)
48
- * - `boot`: Error during Nodepod boot, file writing, or dependency install
49
- */
50
- export type SandboxErrorCategory =
51
- | "process-stderr"
52
- | "process-exit"
53
- | "runtime-exception"
54
- | "browser-error"
55
- | "browser-unhandled-rejection"
56
- | "browser-console-error"
57
- | "compilation"
58
- | "network"
59
- | "boot";
60
-
61
- /**
62
- * A structured error emitted by the sandbox.
63
- *
64
- * Designed for AI agent consumption — includes enough context for the
65
- * agent to construct a targeted fix prompt (file path, line number,
66
- * surrounding code, stack trace).
67
- *
68
- * @see Ranger's auto-fix: client/src/components/Artifacts/Artifacts.tsx
69
- */
70
- export interface SandboxError {
71
- /** Unique ID for deduplication */
72
- id: string;
73
- /** Error category — determines how the agent should interpret it */
74
- category: SandboxErrorCategory;
75
- /** Human-readable error message (the "what") */
76
- message: string;
77
- /** Full stack trace if available */
78
- stack?: string;
79
- /** File path where the error occurred (relative to workdir) */
80
- filePath?: string;
81
- /** Line number in the file (1-indexed) */
82
- line?: number;
83
- /** Column number in the file (1-indexed) */
84
- column?: number;
85
- /** ISO 8601 timestamp */
86
- timestamp: string;
87
- /**
88
- * Surrounding source code lines for context.
89
- * Format: "lineNum: content" per line (e.g., "42: const x = foo();")
90
- * Typically ~10 lines centered on the error line.
91
- */
92
- sourceContext?: string;
93
- }
94
-
95
- // ---------------------------------------------------------------------------
96
- // Runtime (Nodepod lifecycle)
97
- // ---------------------------------------------------------------------------
98
-
99
- /** Boot stages shown during the loading animation */
100
- export type BootStage =
101
- | "initializing" // Nodepod.boot() in progress
102
- | "writing-files" // Writing project files to virtual FS
103
- | "installing" // npm install running
104
- | "starting" // Entry command executing (e.g., node server.js)
105
- | "ready" // Server is listening, preview iframe can load
106
- | "error"; // Something failed
107
-
108
- export interface BootProgress {
109
- stage: BootStage;
110
- message: string;
111
- /** 0-100 percent, approximate */
112
- percent: number;
113
- }
114
-
115
- /** Configuration for the Nodepod runtime */
116
- export interface RuntimeConfig {
117
- /** Project files to write into the virtual filesystem */
118
- files: FileMap;
119
- /** Command to start the dev server, e.g. "node server.js" */
120
- entryCommand: string;
121
- /** Working directory inside Nodepod (default: "/app") */
122
- workdir?: string;
123
- /** Environment variables passed to processes */
124
- env?: Record<string, string>;
125
- /** Port to watch for server readiness (default: 3000) */
126
- port?: number;
127
- }
128
-
129
- /** State exposed by the runtime to UI components */
130
- export interface RuntimeState {
131
- status: BootStage;
132
- progress: BootProgress;
133
- /** URL for the preview iframe once server is ready, e.g. "/__virtual__/3000/" */
134
- previewUrl: string | null;
135
- /** All terminal output lines (stdout + stderr) */
136
- terminalOutput: string[];
137
- /** Current files in the virtual FS (may differ from original after edits) */
138
- files: FileMap;
139
- /**
140
- * Baseline file snapshot — the files as they were before the latest
141
- * update (via updateFiles). Used by the diff viewer to show what changed.
142
- * Empty on first load (everything is "new"), populated after the first
143
- * file update.
144
- */
145
- originalFiles: FileMap;
146
- /**
147
- * Per-file change status relative to originalFiles.
148
- *
149
- * Only includes files that have a non-"unchanged" status.
150
- * Missing keys should be treated as "unchanged".
151
- */
152
- fileChanges: Record<string, FileChangeStatus>;
153
- /**
154
- * Monotonically increasing counter that triggers an iframe reload
155
- * without restarting the server process. Incremented when only
156
- * hot-reloadable files change (CSS, HTML, static assets).
157
- */
158
- previewReloadKey: number;
159
- /** Error message if status is 'error' */
160
- error: string | null;
161
- /**
162
- * All structured errors collected during this session.
163
- * New errors are appended — the array grows monotonically.
164
- * Use `errors[errors.length - 1]` to get the latest.
165
- */
166
- errors: SandboxError[];
167
- }
168
-
169
- // ---------------------------------------------------------------------------
170
- // Imperative Handle
171
- // ---------------------------------------------------------------------------
172
-
173
- /**
174
- * Imperative handle exposed by CodeSandbox via React.forwardRef.
175
- *
176
- * This is the primary API for host applications (like Ranger) to
177
- * control the sandbox programmatically. The sandbox is a "dumb renderer"
178
- * — the host pushes files in and reads state out.
179
- *
180
- * @example
181
- * ```tsx
182
- * const ref = useRef<CodeSandboxHandle>(null);
183
- *
184
- * // Push files from any source
185
- * ref.current?.updateFiles(fileMap);
186
- *
187
- * // Push a single file (e.g., agent modified one file)
188
- * ref.current?.updateFile('server.js', newContent);
189
- *
190
- * // Read current state
191
- * const files = ref.current?.getFiles();
192
- * const changes = ref.current?.getChangedFiles();
193
- * const errors = ref.current?.getErrors();
194
- * ```
195
- */
196
- export interface CodeSandboxHandle {
197
- /**
198
- * Replace the entire file set. Diffs against current files, writes only
199
- * changed files to Nodepod FS, and restarts the server if anything changed.
200
- *
201
- * The previous file set becomes `originalFiles` for diff tracking.
202
- *
203
- * @param files - Complete new file set
204
- * @param options - Optional: restartServer (default true)
205
- */
206
- updateFiles: (
207
- files: FileMap,
208
- options?: { restartServer?: boolean },
209
- ) => Promise<void>;
210
-
211
- /**
212
- * Update a single file. Writes to Nodepod FS and updates state.
213
- * Does NOT restart the server — call `restart()` manually if needed,
214
- * or use `updateFiles()` for bulk updates with auto-restart.
215
- *
216
- * @param path - File path (e.g., "server.js", "public/index.html")
217
- * @param content - New file content
218
- */
219
- updateFile: (path: string, content: string) => Promise<void>;
220
-
221
- /**
222
- * Force restart the server process. Kills the current process
223
- * and re-runs the entry command.
224
- */
225
- restart: () => Promise<void>;
226
-
227
- /**
228
- * Get the current file map (all files including edits).
229
- */
230
- getFiles: () => FileMap;
231
-
232
- /**
233
- * Get only files that have been modified relative to originalFiles.
234
- * Returns a FileMap containing only the changed files.
235
- */
236
- getChangedFiles: () => FileMap;
237
-
238
- /**
239
- * Get the per-file change status map (new/modified/deleted).
240
- * Missing keys should be treated as "unchanged".
241
- */
242
- getFileChanges: () => Record<string, FileChangeStatus>;
243
-
244
- /**
245
- * Get all structured errors collected during this session.
246
- */
247
- getErrors: () => SandboxError[];
248
-
249
- /**
250
- * Get the current runtime state snapshot.
251
- */
252
- getState: () => RuntimeState;
253
- }
254
-
255
- // ---------------------------------------------------------------------------
256
- // Component Props
257
- // ---------------------------------------------------------------------------
258
-
259
- /**
260
- * Props for the CodeSandbox component.
261
- *
262
- * The sandbox is a pure renderer — it receives files via props and
263
- * exposes an imperative handle for programmatic updates. It does NOT
264
- * interact with any storage backend directly.
265
- *
266
- * File sources (for initial load, pick ONE):
267
- * - `files` — pass a FileMap directly
268
- * - `template` — use a built-in template name (e.g., "fullstack-starter")
269
- *
270
- * For live updates after mount, use the imperative handle:
271
- * ```tsx
272
- * const ref = useRef<CodeSandboxHandle>(null);
273
- * <CodeSandbox ref={ref} files={initialFiles} />
274
- * // Later:
275
- * ref.current.updateFiles(newFiles);
276
- * ```
277
- */
278
- export interface CodeSandboxProps {
279
- /** Pass files directly (from any source) */
280
- files?: FileMap;
281
- /** OR use a built-in template name */
282
- template?: string;
283
- /** Command to start the dev server (default inferred from package.json or template) */
284
- entryCommand?: string;
285
- /** Port the server listens on (default: 3000) */
286
- port?: number;
287
- /** Environment variables */
288
- env?: Record<string, string>;
289
-
290
- // Callbacks
291
- /** Fires when a file is modified in the editor by the user */
292
- onFileChange?: (path: string, content: string) => void;
293
- /** Fires when the dev server is ready (initial boot or after restart) */
294
- onServerReady?: (port: number, url: string) => void;
295
- /** Fires on boot progress changes */
296
- onProgress?: (progress: BootProgress) => void;
297
- /** Fires on errors (legacy — simple string message) */
298
- onError?: (error: string) => void;
299
- /**
300
- * Fires when a structured error is detected.
301
- *
302
- * This is the primary error channel for AI agent integration.
303
- * Errors include file path, line number, source context, and category
304
- * so the agent can construct a targeted fix prompt.
305
- *
306
- * Max 2 auto-fix attempts per error is recommended (see Ranger pattern).
307
- */
308
- onSandboxError?: (error: SandboxError) => void;
309
- /**
310
- * Fires after updateFiles() completes (files written + server restarted).
311
- * Useful for the host to know when the sandbox has finished processing
312
- * a file push.
313
- */
314
- onFilesUpdated?: (fileChanges: Record<string, FileChangeStatus>) => void;
315
-
316
- // Layout
317
- /** CSS class name for the root element */
318
- className?: string;
319
- /** Height of the sandbox (default: '100vh') */
320
- height?: string;
321
- }
322
-
323
- export interface FileTreeProps {
324
- files: FileNode[];
325
- selectedFile: string | null;
326
- onSelectFile: (path: string) => void;
327
- /** Per-file change status for visual indicators (colored dots) */
328
- fileChanges?: Record<string, FileChangeStatus>;
329
- onCreateFile?: (path: string) => void;
330
- onCreateFolder?: (path: string) => void;
331
- onDeleteFile?: (path: string) => void;
332
- onRenameFile?: (oldPath: string, newPath: string) => void;
333
- }
334
-
335
- export interface CodeEditorProps {
336
- files: FileMap;
337
- /** Baseline files for diff comparison (empty = no diff available) */
338
- originalFiles: FileMap;
339
- /** Per-file change status for tab indicators */
340
- fileChanges: Record<string, FileChangeStatus>;
341
- activeFile: string | null;
342
- openFiles: string[];
343
- onSelectFile: (path: string) => void;
344
- onCloseFile: (path: string) => void;
345
- onFileChange: (path: string, content: string) => void;
346
- readOnly?: boolean;
347
- }
348
-
349
- export interface TerminalProps {
350
- output: string[];
351
- className?: string;
352
- /** Whether the terminal is collapsed to just its header bar */
353
- minimized?: boolean;
354
- /** Called when the user clicks the minimize/expand toggle */
355
- onToggleMinimize?: () => void;
356
- }
357
-
358
- export interface PreviewProps {
359
- url: string | null;
360
- className?: string;
361
- onRefresh?: () => void;
362
- /** Called when a JavaScript error occurs inside the preview iframe */
363
- onBrowserError?: (error: SandboxError) => void;
364
- /**
365
- * Monotonically increasing counter. When this changes, the iframe
366
- * is soft-reloaded (location.reload) without restarting the server.
367
- * Used for hot-reloading static asset changes (CSS, HTML, images).
368
- */
369
- reloadKey?: number;
370
- }
371
-
372
- export interface BootOverlayProps {
373
- progress: BootProgress;
374
- className?: string;
375
- }