Skip to content

Latest commit

 

History

History
220 lines (178 loc) · 11 KB

File metadata and controls

220 lines (178 loc) · 11 KB
name Basic dev agent
description Used for general purpose NodeDev development

NodeDev - Copilot Instructions

  1. You must always read the documentation files when they are related to your current task. They are described in the "Documentation" section of this document.
  2. You must always run the tests and make sure they are passing before you consider your job as completed, no matter how long you have been at the task or any following instruction to make it short or end the task early.
  3. Disabling, removing, skipping, deleting, bypassing or converting to warnings ANY tests IS NOT ALLOWED and is not considered the right way of fixing a problematic test. The test must be functional and actually testing what it is intended to test.
  4. Document newly added content or concepts in this .github/agents/basicAgent.agent.md file or any related documentation file.
  5. When the user corrects major mistakes done during your development, document them in this file to ensure it is never done again.
  6. You must always install playwright BEFORE trying to run the tests. build the projects and install playwright. If you struggle (take multiple iterations to do it), document the steps you took in this file to make it easier next time.

Programming style

  1. Always use C# nullable
  2. Prefer small polymorphic classes rather than big helper style classes
  3. Write many tests for any newly added feature, whether in the core as unit tests or in the UI as e2e tests

Overview

NodeDev is a visual programming environment built with Blazor and Blazor.Diagrams. It allows users to create software using a node-based visual interface instead of traditional text-based code. The system generates native IL code for near-native execution performance.

Architecture

Core Components

  • NodeDev.Core: Core business logic, node definitions, graph management, type system, IL code generation, and debugging infrastructure (in Debugger/ folder)
  • NodeDev.Blazor: UI components built with Blazor (Razor components, diagrams, project explorer)
  • NodeDev.Blazor.Server: Server-side Blazor hosting
  • NodeDev.Blazor.MAUI: MAUI-based desktop application wrapper
  • NodeDev.Tests: Unit tests for core functionality
  • NodeDev.EndToEndTests: Playwright-based E2E tests with Reqnroll (SpecFlow successor)
  • NodeDev.ScriptRunner: Console application that executes compiled user code as a separate process, serving as the target for the ICorDebug debugging infrastructure

UI Structure

The main UI consists of:

  • AppBar: Top toolbar with project controls (New, Open, Save, Options, Run, Run with Debug)
  • ProjectExplorer: Left panel showing project structure (classes, methods, properties)
  • GraphCanvas: Central canvas where nodes are placed and connected
  • ClassExplorer: Shows details of the currently selected class
  • DebuggerConsolePanel: Bottom panel with tabs for Console Output and Debug Callbacks

Graph System

  • Uses Blazor.Diagrams library for visual node editing
  • GraphNodeModel: Represents a node in the diagram (wraps Core.Node)
  • GraphPortModel: Represents input/output ports on nodes
  • GraphCanvas: Main component managing the diagram, node creation, and connections

Node System

  • Flow Nodes: Control execution (Entry, Return, Branch, While, For, etc.) - have Exec connections
  • Data Nodes: Compute values without flow (Math operations, comparisons) - no Exec connections
  • Mixed Nodes: Both Exec and data (DeclareVariable, SetProperty, etc.)
  • Generic Types: Automatically resolve based on connections (T, T1, T2 → concrete types)

Testing

  • E2E tests use Playwright with Reqnroll for BDD-style scenarios
  • Tests start a Blazor Server instance and automate browser interactions
  • Components use data-test-id attributes for test targeting
  • Mouse event sequences critical for drag operations: MoveAsync → DownAsync → MoveAsync(with steps) → UpAsync

Installing Playwright for E2E Tests

Before running E2E tests, Playwright browsers must be installed:

  1. Build the test project first:

    dotnet build src/NodeDev.EndToEndTests/NodeDev.EndToEndTests.csproj
  2. Install Playwright Chromium browser:

    cd src/NodeDev.EndToEndTests
    pwsh bin/Debug/net10.0/playwright.ps1 install chromium
  3. The browser will be installed to ~/.cache/ms-playwright/

Important: Playwright must be reinstalled after:

  • Cleaning the build output
  • Updating the Playwright NuGet package
  • Running tests in a fresh CI environment

Without Playwright installed, all E2E tests will fail with browser launch errors.

ICorDebug Testing Requirements

The debugger integration tests require the dbgshim library to be available. This is obtained automatically via the Microsoft.Diagnostics.DbgShim NuGet package which is referenced by NodeDev.Core.

How it works:

  • The Microsoft.Diagnostics.DbgShim NuGet package (v9.0.652701) is included as a dependency in NodeDev.Core
  • When the package is restored, it downloads platform-specific native libraries:
    • microsoft.diagnostics.dbgshim.linux-x64 for Linux x64
    • microsoft.diagnostics.dbgshim.win-x64 for Windows x64
    • And other platform variants
  • The DbgShimResolver class automatically finds the library in the NuGet packages cache

Location of dbgshim library:

  • NuGet cache: ~/.nuget/packages/microsoft.diagnostics.dbgshim.linux-x64/[version]/runtimes/linux-x64/native/libdbgshim.so
  • Windows: ~/.nuget/packages/microsoft.diagnostics.dbgshim.win-x64/[version]/runtimes/win-x64/native/dbgshim.dll

Running the debugger tests:

# Build and restore packages
dotnet build src/NodeDev.Tests/NodeDev.Tests.csproj

# Run debugger tests
dotnet test src/NodeDev.Tests/NodeDev.Tests.csproj --filter "DebuggerCoreTests"

The tests demonstrate:

  1. Finding dbgshim from the NuGet package
  2. Loading the dbgshim library
  3. Creating a NodeDev project with nodes
  4. Building the project
  5. Launching the process in suspended mode
  6. Registering for CLR runtime startup
  7. Enumerating CLRs in the target process
  8. Attaching to the process and obtaining ICorDebug interface

Documentation

Detailed topic-specific documentation is maintained in the docs/ folder:

  • docs/e2e-testing.md - End-to-end testing patterns, node interaction, connection testing, and screenshot validation
  • docs/node-types-and-connections.md - Comprehensive guide to node types, connection system, port identification, and testing strategies
  • docs/script-runner.md - ScriptRunner architecture, usage, and ICorDebug debugging infrastructure

Debugging Infrastructure

Hard Debugging (ICorDebug)

NodeDev now supports "Hard Debugging" via the ICorDebug API (.NET's unmanaged debugging interface). This provides low-level debugging capabilities including:

  • Process attachment and management
  • Debug event callbacks (process creation, module loading, thread creation, etc.)
  • Future support for breakpoints and step-through execution

Running with Debug: The UI provides two run modes:

  1. Run - Normal execution without debugger attachment
  2. Run with Debug - Executes with ICorDebug debugger attached

Important: "Run with Debug" requires successful debugger attachment. If attachment fails for any reason (DbgShim not found, CLR enumeration fails, etc.), the operation will fail with an error dialog showing the specific issue. There is no fallback to normal execution.

Debug State Management:

  • Project.IsHardDebugging - Boolean property indicating active debug session
  • Project.DebuggedProcessId - Process ID of debugged process (null when not debugging)
  • Project.HardDebugStateChanged - Observable stream for debug state changes (true when attached, false when detached)
  • Project.DebugCallbacks - Observable stream of DebugCallbackEventArgs for all debug events

UI Visual Feedback:

  • "Run with Debug" button changes color (warning) and shows PID when debugging
  • Button is disabled during active debug session
  • DebuggerConsolePanel shows two tabs:
    • "Console Output" - Standard output from the program
    • "Debug Callbacks" - Real-time debug events with timestamps

Implementation Pattern:

// Running with debug in Project.cs
try 
{
    var result = project.RunWithDebug(BuildOptions.Debug);
}
catch (InvalidOperationException ex)
{
    // Handle debug attachment failure
    // Show error dialog to user with ex.Message
    Console.WriteLine($"Debug failed: {ex.Message}");
}

// Subscribing to debug callbacks
project.DebugCallbacks.Subscribe(callback => {
    Console.WriteLine($"{callback.CallbackType}: {callback.Description}");
});

// Subscribing to debug state changes
project.HardDebugStateChanged.Subscribe(isDebugging => {
    if (isDebugging)
        Console.WriteLine("Debugging started");
    else
        Console.WriteLine("Debugging stopped");
});

Debugger Module (NodeDev.Core.Debugger)

The debugging infrastructure is located in src/NodeDev.Core/Debugger/ and provides ICorDebug API access via the ClrDebug NuGet package:

  • DbgShimResolver: Cross-platform resolution for the dbgshim library from NuGet packages or system paths
  • DebugSessionEngine: Main debugging engine with process launch, attach, and callback handling
  • ManagedDebuggerCallbacks: Implementation of ICorDebugManagedCallback interfaces via ClrDebug
  • DebugEngineException: Custom exception type for debugging errors

Dependencies:

  • ClrDebug (v0.3.4): C# wrappers for the unmanaged ICorDebug API
  • Microsoft.Diagnostics.DbgShim (v9.0.652701): Native dbgshim library for all platforms

ScriptRunner

NodeDev includes a separate console application called ScriptRunner that serves as the target process for debugging. This architecture supports "Hard Debugging" via the ICorDebug API.

Architecture:

  • Host Process: The Visual IDE (NodeDev.Blazor.Server or NodeDev.Blazor.MAUI)
  • Target Process: ScriptRunner - a separate console application that executes the user's compiled code

ScriptRunner Features:

  • Accepts a DLL path as command-line argument
  • Optional --wait-for-debugger flag to pause execution until debugger attaches
  • Loads assemblies using Assembly.LoadFrom()
  • Finds and invokes entry points:
    • Static Program.Main method (in any namespace)
    • Types implementing IRunnable interface (future extensibility)
  • Wraps execution in try/catch blocks to print exceptions to console
  • Proper exit code handling for CI/CD integration

Build System:

  • ScriptRunner is automatically built with NodeDev.Core
  • MSBuild targets copy ScriptRunner to the output directory of dependent projects
  • The Project.Run() method automatically locates and launches ScriptRunner
  • The Project.RunWithDebug() method launches ScriptRunner and attaches debugger
  • The Project.GetScriptRunnerPath() method returns the ScriptRunner location for debugging infrastructure