@illuma-ai/code-sandbox 1.0.0 → 1.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.
@@ -1,11 +1,24 @@
1
1
  /**
2
- * CodeEditor — Monaco editor with file tabs.
2
+ * CodeEditor — Monaco editor with file tabs, diff mode, and change indicators.
3
3
  *
4
- * Uses @monaco-editor/react for the editor and renders a tab bar
5
- * of open files. Supports dark theme that matches the sandbox.
4
+ * Uses @monaco-editor/react for both the regular editor and diff editor.
5
+ * Renders a tab bar of open files with change status indicators:
6
+ * - Green dot: new file
7
+ * - Orange dot: modified file
8
+ * - Red dot: deleted file (shown as read-only)
9
+ *
10
+ * When diff mode is active, displays Monaco's side-by-side DiffEditor
11
+ * comparing the original file content (left) with the current content (right).
12
+ *
13
+ * @see @monaco-editor/react DiffEditor: https://github.com/suren-atoyan/monaco-react
6
14
  */
7
15
  import type { CodeEditorProps } from "../types";
8
16
  /**
9
- * CodeEditor component — Monaco editor with file tabs.
17
+ * CodeEditor component — Monaco editor with file tabs, diff view, and
18
+ * change status indicators.
19
+ *
20
+ * When `originalFiles` has content for the active file (meaning a prior
21
+ * version exists), a "Diff" toggle button appears in the tab bar. Clicking
22
+ * it switches to Monaco's DiffEditor showing the old (left) vs new (right).
10
23
  */
11
- export declare function CodeEditor({ files, activeFile, openFiles, onSelectFile, onCloseFile, onFileChange, readOnly, }: CodeEditorProps): import("react/jsx-runtime").JSX.Element;
24
+ export declare function CodeEditor({ files, originalFiles, fileChanges, activeFile, openFiles, onSelectFile, onCloseFile, onFileChange, readOnly, }: CodeEditorProps): import("react/jsx-runtime").JSX.Element;
@@ -15,5 +15,6 @@ import type { FileMap, FileNode, FileTreeProps } from "../types";
15
15
  export declare function buildFileTree(files: FileMap): FileNode[];
16
16
  /**
17
17
  * FileTree component — renders a collapsible tree of files and folders.
18
+ * Shows change status indicators (N/M/D) next to modified files.
18
19
  */
19
- export declare function FileTree({ files, selectedFile, onSelectFile }: FileTreeProps): import("react/jsx-runtime").JSX.Element;
20
+ export declare function FileTree({ files, selectedFile, onSelectFile, fileChanges, }: FileTreeProps): import("react/jsx-runtime").JSX.Element;
@@ -1,15 +1,27 @@
1
1
  /**
2
2
  * Preview — Full-width iframe that renders the Nodepod virtual server.
3
3
  *
4
- * Loads the URL from Nodepod's Service Worker proxy (/__virtual__/PORT/).
4
+ * Loads the URL from Nodepod's Service Worker proxy (/__preview__/PORT/).
5
5
  * The toolbar handles the URL bar and refresh — this is just the iframe.
6
+ *
7
+ * Error capture: After the iframe loads, we inject a small script that
8
+ * hooks `window.onerror`, `window.onunhandledrejection`, and
9
+ * `console.error` inside the iframe. These are relayed to the parent
10
+ * via `postMessage`, where we parse them into SandboxError objects
11
+ * and forward to the `onBrowserError` callback.
12
+ *
13
+ * The iframe and parent are same-origin (both served through the
14
+ * Nodepod Service Worker), so direct contentWindow access works.
6
15
  */
7
16
  import type { PreviewProps } from "../types";
8
17
  /**
9
18
  * Preview component — renders the dev server output in a full-width iframe.
10
19
  *
11
- * The URL points to /__virtual__/PORT/ which is intercepted by the
20
+ * The URL points to /__preview__/PORT/ which is intercepted by the
12
21
  * Nodepod Service Worker and proxied to the Express server running
13
22
  * in the Web Worker.
23
+ *
24
+ * After the iframe loads, an error-capture script is injected so that
25
+ * runtime errors inside the preview are surfaced to the AI agent.
14
26
  */
15
- export declare function Preview({ url, className }: PreviewProps): import("react/jsx-runtime").JSX.Element;
27
+ export declare function Preview({ url, className, onBrowserError }: PreviewProps): import("react/jsx-runtime").JSX.Element;
@@ -13,8 +13,9 @@
13
13
  *
14
14
  * @see bolt.diy: app/components/workbench/Workbench.client.tsx (reference)
15
15
  */
16
+ import React from "react";
16
17
  import "allotment/dist/style.css";
17
- import type { CodeSandboxProps } from "../types";
18
+ import type { CodeSandboxProps, CodeSandboxHandle } from "../types";
18
19
  /**
19
20
  * CodeSandbox — The main entrypoint component.
20
21
  *
@@ -25,4 +26,4 @@ import type { CodeSandboxProps } from "../types";
25
26
  * A compact toolbar row contains the view toggle and (in preview mode)
26
27
  * a URL bar with refresh button.
27
28
  */
28
- export declare function CodeSandbox(props: CodeSandboxProps): import("react/jsx-runtime").JSX.Element;
29
+ export declare const CodeSandbox: React.ForwardRefExoticComponent<CodeSandboxProps & React.RefAttributes<CodeSandboxHandle>>;
@@ -3,14 +3,38 @@
3
3
  *
4
4
  * Manages the Nodepod runtime instance and exposes reactive state
5
5
  * for all UI components (progress, files, terminal output, preview URL).
6
+ *
7
+ * The sandbox is a pure renderer — it receives files via props (initial
8
+ * load) and via the imperative handle (updateFiles/updateFile for live
9
+ * updates). It does NOT interact with any storage backend directly.
10
+ *
11
+ * Error exposure: wires the runtime's structured error system and the
12
+ * preview iframe's browser error capture into a unified `errors[]` array
13
+ * in state, and forwards each error to the `onSandboxError` callback
14
+ * so the AI agent can auto-fix.
6
15
  */
7
16
  import { NodepodRuntime } from "../services/runtime";
8
- import type { CodeSandboxProps, FileMap, RuntimeState } from "../types";
17
+ import type { CodeSandboxProps, FileChangeStatus, FileMap, RuntimeState, SandboxError } from "../types";
9
18
  /**
10
19
  * Hook that manages the full Nodepod runtime lifecycle.
11
20
  *
21
+ * The sandbox is a pure renderer — files come in via props or the
22
+ * imperative handle. No GitHub, no polling, no storage backends.
23
+ *
12
24
  * @param props - CodeSandbox component props
13
- * @returns Reactive runtime state + control functions
25
+ * @returns Reactive runtime state + control functions + imperative methods
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * // Direct files (fetched from any source by the host app)
30
+ * const runtime = useRuntime({ files: myFiles, entryCommand: 'node server.js' });
31
+ *
32
+ * // Later, push updated files from the host:
33
+ * await runtime.updateFiles(newFiles);
34
+ *
35
+ * // Or update a single file:
36
+ * await runtime.updateFile('server.js', newContent);
37
+ * ```
14
38
  */
15
39
  export declare function useRuntime(props: CodeSandboxProps): {
16
40
  state: RuntimeState;
@@ -19,7 +43,16 @@ export declare function useRuntime(props: CodeSandboxProps): {
19
43
  handleFileChange: (path: string, content: string) => Promise<void>;
20
44
  handleSelectFile: (path: string) => void;
21
45
  handleCloseFile: (path: string) => void;
46
+ handleBrowserError: (error: SandboxError) => Promise<void>;
22
47
  restart: () => Promise<void>;
48
+ updateFiles: (newFiles: FileMap, options?: {
49
+ restartServer?: boolean;
50
+ }) => Promise<void>;
51
+ updateFile: (path: string, content: string) => Promise<void>;
52
+ getFiles: () => FileMap;
23
53
  getChangedFiles: () => FileMap;
54
+ getFileChanges: () => Record<string, FileChangeStatus>;
55
+ getErrors: () => SandboxError[];
56
+ getState: () => RuntimeState;
24
57
  runtime: import("react").MutableRefObject<NodepodRuntime | null>;
25
58
  };