This document provides a detailed overview of NebulaFlow’s architecture, including its component structure, execution model, and design patterns.
NebulaFlow is a VS Code extension that provides a visual workflow editor for LLM+CLI workflows. The architecture consists of two main components:
src/extension.ts): Runs in VS Code, manages the webview interface, and orchestrates workflow executionworkflow/Web/): React-based interface using React Flow for visual graph editingThe extension uses the Amp SDK and OpenRouter SDK for LLM operations and executes CLI commands through the Node.js child_process API. Execution is orchestrated in the extension with streaming output, approval system, and real-time event handling.
NebulaFlow follows a Vertical Slice Architecture where code is organized by features (slices) rather than technical layers. This maximizes context locality and keeps all code required to understand a feature within the fewest possible files and folders.
src/
extension.ts # VS Code extension entry point
workflow/
Application/ # Orchestration and message handling
register.ts # Extension activation and webview setup
messaging/ # Protocol converters and message handling
workflow-session.ts # Workflow session management
Core/ # Pure business logic (no side effects)
models.ts # Node types and data structures
Contracts/ # Shared protocol contracts
Protocol.ts # Message types for extension-webview communication
DataAccess/ # I/O operations (file system, storage)
fs.ts # File system operations for workflows/subflows
Execution/ # Node execution logic
Application/handlers/ # Workflow execution handler
Core/engine/ # Parallel scheduler
Core/execution/ # Input evaluation, output combination
Application/node-runners/ # Individual node executors
LLMIntegration/ # LLM provider integrations (Amp, OpenRouter)
Shared/ # Generic primitives (Host, Infrastructure)
Host/ # VS Code host adapter
Infrastructure/ # Messaging, workspace management
Web/ # Webview UI (React + React Flow)
components/ # React components
nodes/ # Node UI components
services/ # Protocol communication
WorkflowApp.tsx # Main webview application
Requests flow through these logical stages:
Example: Executing a workflow
nebulaFlow.openWorkflow command → webview sends execute_workflow messageExecuteWorkflow.ts handler validates nodes/edges, sets up execution contextexecuteCLINode runs shell commands, executeLLMNode calls Amp SDKExecution events stream in real-time from the extension to the webview:
node_execution_status events report running/completed/error statesnode_assistant_content streams LLM responses (text, thinking, tool use)node_output_chunk streams stdout/stderr from shell commandsCLI nodes require explicit user approval before execution:
pending_approval statenode_approved) or rejects (node_rejected)NebulaFlow uses a parallel scheduler that executes nodes when their dependencies are satisfied:
loop-start and loop-end nodesWorkflows can be paused and resumed from any node:
execution_paused event with stoppedAtNodeIdResumeDTO with seeds for variables, decisions, outputsNebulaFlow provides the following node types (defined in workflow/Core/models.ts and workflow/Web/components/nodes/Nodes.tsx):
NodeType.LLM): Interact with Large Language Models
NodeType.CLI): Execute shell commands
NodeType.INPUT): Input text data (formerly “Input Node”)
NodeType.ACCUMULATOR): Accumulate text across multiple inputs
NodeType.VARIABLE): Store and reference variables
NodeType.IF_ELSE): Branch workflow based on conditions
NodeType.LOOP_START): Begin a loop iteration
NodeType.LOOP_END): End a loop iteration
NodeType.PREVIEW): Display data for debugging
NodeType.SUBFLOW): Embed a reusable subflow
NodeType.SUBFLOW_INPUT): Define input ports for subflowsNodeType.SUBFLOW_OUTPUT): Define output ports for subflowsThe extension and webview communicate using a custom workflow message protocol defined in workflow/Core/Contracts/Protocol.ts. All messages extend BaseWorkflowMessage with a type field.
execute_workflow: Start workflow executionabort_workflow: Stop executionpause_workflow: Pause executionnode_approved / node_rejected: Approval responsessave_workflow: Persist workflow to diskload_workflow: Load workflow from diskexecution_started / execution_completed / execution_paused: Execution lifecyclenode_execution_status: Node state changesnode_output_chunk: Streaming CLI outputnode_assistant_content: Streaming LLM responsesworkflow_loaded: Workflow data loadedworkflow_saved: Save confirmationprovide_custom_nodes: Custom node definitionsstorage_scope: Storage configurationprovide_subflow: Subflow definitionWorkflowPayloadDTO: Contains nodes, edges, state, resume metadataNodeExecutionPayload: Node status, result, error informationAssistantContentItem: Structured LLM content (text, thinking, tool use)SubflowDefinitionDTO: Reusable workflow definitionnebulaFlow.storageScope: Choose between user or workspace storage (user |
workspace) |
nebulaFlow.globalStoragePath: Custom storage path for workflows/subflowschild_process, fs, path, events)npm run build:webview → Vite bundles React app into dist/webviews/npm run build:ext → Esbuild bundles extension + SDK into dist/extension.jsnpm run build → Both steps, auto-syncs SDK via sync:sdknpm run check (TS 5.x)npm run lint (Biome)npm run format (Biome)AMP_API_KEY environment variableSafety Levels: Configurable safety levels (safe |
advanced) |
provide_custom_nodes event