@illuma-ai/code-sandbox 1.0.0 → 1.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/src/types.ts CHANGED
@@ -20,6 +20,78 @@ export interface FileNode {
20
20
  children?: FileNode[];
21
21
  }
22
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
+
23
95
  // ---------------------------------------------------------------------------
24
96
  // Runtime (Nodepod lifecycle)
25
97
  // ---------------------------------------------------------------------------
@@ -64,8 +136,30 @@ export interface RuntimeState {
64
136
  terminalOutput: string[];
65
137
  /** Current files in the virtual FS (may differ from original after edits) */
66
138
  files: FileMap;
139
+ /**
140
+ * Baseline file snapshot — the files as they were before the latest
141
+ * update (initial load, or the version before the last GitHub poll).
142
+ *
143
+ * Used by the diff viewer to show what changed. Empty on first load
144
+ * (everything is "new"), populated after the first file update
145
+ * (GitHub poll, updateFiles, etc.).
146
+ */
147
+ originalFiles: FileMap;
148
+ /**
149
+ * Per-file change status relative to originalFiles.
150
+ *
151
+ * Only includes files that have a non-"unchanged" status.
152
+ * Missing keys should be treated as "unchanged".
153
+ */
154
+ fileChanges: Record<string, FileChangeStatus>;
67
155
  /** Error message if status is 'error' */
68
156
  error: string | null;
157
+ /**
158
+ * All structured errors collected during this session.
159
+ * New errors are appended — the array grows monotonically.
160
+ * Use `errors[errors.length - 1]` to get the latest.
161
+ */
162
+ errors: SandboxError[];
69
163
  }
70
164
 
71
165
  // ---------------------------------------------------------------------------
@@ -132,8 +226,18 @@ export interface CodeSandboxProps {
132
226
  onServerReady?: (port: number, url: string) => void;
133
227
  /** Fires on boot progress changes */
134
228
  onProgress?: (progress: BootProgress) => void;
135
- /** Fires on errors */
229
+ /** Fires on errors (legacy — simple string message) */
136
230
  onError?: (error: string) => void;
231
+ /**
232
+ * Fires when a structured error is detected.
233
+ *
234
+ * This is the primary error channel for AI agent integration.
235
+ * Errors include file path, line number, source context, and category
236
+ * so the agent can construct a targeted fix prompt.
237
+ *
238
+ * Max 2 auto-fix attempts per error is recommended (see Ranger pattern).
239
+ */
240
+ onSandboxError?: (error: SandboxError) => void;
137
241
 
138
242
  // Layout
139
243
  /** CSS class name for the root element */
@@ -146,6 +250,8 @@ export interface FileTreeProps {
146
250
  files: FileNode[];
147
251
  selectedFile: string | null;
148
252
  onSelectFile: (path: string) => void;
253
+ /** Per-file change status for visual indicators (colored dots) */
254
+ fileChanges?: Record<string, FileChangeStatus>;
149
255
  onCreateFile?: (path: string) => void;
150
256
  onCreateFolder?: (path: string) => void;
151
257
  onDeleteFile?: (path: string) => void;
@@ -154,6 +260,10 @@ export interface FileTreeProps {
154
260
 
155
261
  export interface CodeEditorProps {
156
262
  files: FileMap;
263
+ /** Baseline files for diff comparison (empty = no diff available) */
264
+ originalFiles: FileMap;
265
+ /** Per-file change status for tab indicators */
266
+ fileChanges: Record<string, FileChangeStatus>;
157
267
  activeFile: string | null;
158
268
  openFiles: string[];
159
269
  onSelectFile: (path: string) => void;
@@ -171,6 +281,8 @@ export interface PreviewProps {
171
281
  url: string | null;
172
282
  className?: string;
173
283
  onRefresh?: () => void;
284
+ /** Called when a JavaScript error occurs inside the preview iframe */
285
+ onBrowserError?: (error: SandboxError) => void;
174
286
  }
175
287
 
176
288
  export interface BootOverlayProps {