Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ All other workspace member crates inherit the version automatically.

- `src/wasm_sandbox/guests/javascript/package.json`

### .NET (Directory.Build.props)

- `src/sdk/dotnet/Directory.Build.props`

## 2. Verify the Build

```sh
Expand Down
19 changes: 15 additions & 4 deletions src/sdk/dotnet/Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ devnull := if os() == "windows" { "$null" } else { "/dev/null" }
#### BUILD ####

# Build everything (Rust FFI + .NET solution)
build target=default-target: (build-rust target) (build-dotnet target)
build target=default-target: (build-rust target) (build-dotnet target) (build-guests target)

# Build only the Rust FFI crate
build-rust target=default-target:
Expand All @@ -29,6 +29,11 @@ build-rust target=default-target:
build-dotnet target=default-target:
dotnet build {{repo-root}}/src/sdk/dotnet/core/HyperlightSandbox.sln --configuration {{ if target == "release" { "Release" } else { "Debug" } }}

# Build guest modules that are embedded into guest NuGet packages
build-guests target=default-target:
cd {{repo-root}} && just -f src/wasm_sandbox/Justfile guest-build {{target}}
cd {{repo-root}} && just -f src/wasm_sandbox/Justfile js-guest-build

#### FORMAT ####

# Apply all formatting (Rust + .NET)
Expand Down Expand Up @@ -82,8 +87,8 @@ test-dotnet target=default-target: (build target)

#### EXAMPLES ####

# Run the core examples (requires guest module: just wasm guest-build)
examples:
# Run the core examples
examples target=default-target: (build-guests target)
dotnet run --project {{repo-root}}/src/sdk/dotnet/core/Examples/BasicExample/BasicExample.csproj
dotnet run --project {{repo-root}}/src/sdk/dotnet/core/Examples/ToolRegistrationExample/ToolRegistrationExample.csproj
dotnet run --project {{repo-root}}/src/sdk/dotnet/core/Examples/SnapshotExample/SnapshotExample.csproj
Expand All @@ -99,11 +104,13 @@ copilot-sdk-example:
#### DIST / PUBLISH ####

# Build NuGet packages
dist target="release": (build target)
dist target="release": (build-guests target) (build target)
{{mkdirp}} {{repo-root}}/dist/dotnetsdk
dotnet pack {{repo-root}}/src/sdk/dotnet/core/PInvoke/HyperlightSandbox.PInvoke.csproj --configuration {{ if target == "release" { "Release" } else { "Debug" } }} --no-build --output {{repo-root}}/dist/dotnetsdk
dotnet pack {{repo-root}}/src/sdk/dotnet/core/Api/HyperlightSandbox.Api.csproj --configuration {{ if target == "release" { "Release" } else { "Debug" } }} --no-build --output {{repo-root}}/dist/dotnetsdk
dotnet pack {{repo-root}}/src/sdk/dotnet/core/Extensions.AI/HyperlightSandbox.Extensions.AI.csproj --configuration {{ if target == "release" { "Release" } else { "Debug" } }} --no-build --output {{repo-root}}/dist/dotnetsdk
dotnet pack {{repo-root}}/src/sdk/dotnet/core/Guest.Python/HyperlightSandbox.Guest.Python.csproj --configuration {{ if target == "release" { "Release" } else { "Debug" } }} --no-build --output {{repo-root}}/dist/dotnetsdk
dotnet pack {{repo-root}}/src/sdk/dotnet/core/Guest.JavaScript/HyperlightSandbox.Guest.JavaScript.csproj --configuration {{ if target == "release" { "Release" } else { "Debug" } }} --no-build --output {{repo-root}}/dist/dotnetsdk
@echo "✅ NuGet packages created in dist/dotnetsdk/"

# Publish NuGet packages to nuget.org (requires NUGET_API_KEY env var)
Expand Down Expand Up @@ -157,4 +164,8 @@ clean:
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Api/obj
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Extensions.AI/bin
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Extensions.AI/obj
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Guest.Python/bin
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Guest.Python/obj
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Guest.JavaScript/bin
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Guest.JavaScript/obj
-{{rmrf}} {{repo-root}}/dist/dotnetsdk
30 changes: 23 additions & 7 deletions src/sdk/dotnet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ A .NET 8.0 SDK for running code in secure, sandboxed environments using [hyperli

```bash
# Prerequisites
just wasm guest-build # Build the Python guest module
just dotnet build # Build the .NET SDK + Rust FFI
```

### Basic Usage

```csharp
using HyperlightSandbox.Api;
using HyperlightSandbox.Guest.Python;

// Create a sandbox with the Python guest
using var sandbox = new SandboxBuilder()
.WithModulePath("path/to/python-sandbox.aot")
.WithPythonModule()
.Build();

// Execute code
Expand All @@ -50,7 +50,7 @@ Register .NET functions that guest code can call:

```csharp
using var sandbox = new SandboxBuilder()
.WithModulePath("python-sandbox.aot")
.WithPythonModule()
.Build();

// Typed tool — auto-serializes args and result
Expand Down Expand Up @@ -87,13 +87,24 @@ using var sandbox = new SandboxBuilder()
var result = sandbox.Run("console.log('Hello from JS!');");
```

To run JavaScript through the Wasm guest module package instead, reference
`Hyperlight.HyperlightSandbox.Guest.JavaScript` and call:

```csharp
using HyperlightSandbox.Guest.JavaScript;

using var sandbox = new SandboxBuilder()
.WithJavaScriptModule()
.Build();
```

### Snapshot/Restore

Checkpoint sandbox state for fast resets between executions:

```csharp
using var sandbox = new SandboxBuilder()
.WithModulePath("python-sandbox.aot")
.WithPythonModule()
.Build();

// Cold start (~2.5s)
Expand All @@ -114,7 +125,7 @@ sandbox.Run("print(x)"); // NameError: x is not defined

```csharp
using var sandbox = new SandboxBuilder()
.WithModulePath("python-sandbox.aot")
.WithPythonModule()
.WithInputDir("/path/to/input") // Read-only /input in guest
.WithTempOutput() // Writable /output in guest
.Build();
Expand Down Expand Up @@ -149,11 +160,12 @@ Use with GitHub Copilot SDK or Microsoft Agent Framework:
```csharp
using HyperlightSandbox.Api;
using HyperlightSandbox.Extensions.AI;
using HyperlightSandbox.Guest.Python;

// Create a code execution tool with snapshot/restore for clean state
using var codeTool = new CodeExecutionTool(
new SandboxBuilder()
.WithModulePath("python-sandbox.aot")
.WithPythonModule()
.WithTempOutput());

codeTool.RegisterTool<MathArgs, double>("compute",
Expand Down Expand Up @@ -229,6 +241,8 @@ just dotnet copilot-sdk-example # Run Copilot SDK example
| `Hyperlight.HyperlightSandbox.PInvoke` | P/Invoke bindings + native library |
| `Hyperlight.HyperlightSandbox.Api` | High-level API (Sandbox, tools, snapshots) |
| `Hyperlight.HyperlightSandbox.Extensions.AI` | AI agent integration (CodeExecutionTool, AIFunction) |
| `Hyperlight.HyperlightSandbox.Guest.Python` | Bundled Python Wasm/AOT guest module + `WithPythonModule()` |
| `Hyperlight.HyperlightSandbox.Guest.JavaScript` | Bundled JavaScript Wasm/AOT guest module + `WithJavaScriptModule()` |

## API Reference

Expand All @@ -237,6 +251,8 @@ just dotnet copilot-sdk-example # Run Copilot SDK example
| Method | Description |
|--------|-------------|
| `WithModulePath(string)` | Path to `.wasm`/`.aot` guest (required for Wasm) |
| `WithPythonModule()` | Use the bundled Python guest from `Hyperlight.HyperlightSandbox.Guest.Python` |
| `WithJavaScriptModule()` | Use the bundled JavaScript guest from `Hyperlight.HyperlightSandbox.Guest.JavaScript` |
| `WithBackend(SandboxBackend)` | `Wasm` (default) or `JavaScript` |
| `WithHeapSize(string\|ulong)` | Guest heap size (e.g. `"50Mi"`, default: platform-dependent) |
| `WithStackSize(string\|ulong)` | Guest stack size (e.g. `"35Mi"`, default: platform-dependent) |
Expand Down Expand Up @@ -299,7 +315,7 @@ sandbox.Run("...");
- .NET 8.0 SDK or later
- Rust 1.89+ (for building the FFI crate)
- Linux (Windows support coming via hyperlight)
- `just wasm guest-build` for Wasm backend examples
- `just dotnet dist` builds the Python and JavaScript guest modules before packing their NuGet packages

## Contributing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Api\HyperlightSandbox.Api.csproj" />
<ProjectReference Include="..\Common\Common.csproj" />
<ProjectReference Include="..\..\Guest.Python\HyperlightSandbox.Guest.Python.csproj" />
</ItemGroup>
</Project>
10 changes: 3 additions & 7 deletions src/sdk/dotnet/core/Examples/BasicExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@
// Mirrors: src/wasm_sandbox/examples/python_basics.rs
//
// Prerequisites:
// just wasm guest-build # builds python-sandbox.aot
// just dotnet build # builds the .NET SDK + FFI
// just dotnet build # builds the .NET SDK + bundled guest package
Comment thread
jsturtevant marked this conversation as resolved.

using HyperlightSandbox.Api;
using HyperlightSandbox.Examples.Common;

var guestPath = ExampleHelper.RequirePythonGuest();
using HyperlightSandbox.Guest.Python;

Console.WriteLine("=== Hyperlight Sandbox .NET — Basic Example ===\n");
Console.WriteLine($"Guest module: {guestPath}\n");

using var sandbox = new SandboxBuilder()
.WithModulePath(guestPath)
.WithPythonModule()
.Build();

// --- Test 1: Basic code execution ---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Api\HyperlightSandbox.Api.csproj" />
<ProjectReference Include="..\Common\Common.csproj" />
<ProjectReference Include="..\..\Guest.Python\HyperlightSandbox.Guest.Python.csproj" />
</ItemGroup>
</Project>
8 changes: 3 additions & 5 deletions src/sdk/dotnet/core/Examples/FilesystemExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@
// Mirrors: src/wasm_sandbox/examples/python_filesystem_demo.rs

using HyperlightSandbox.Api;
using HyperlightSandbox.Examples.Common;

var guestPath = ExampleHelper.RequirePythonGuest();
using HyperlightSandbox.Guest.Python;

Console.WriteLine("=== Hyperlight Sandbox .NET — Filesystem Example ===\n");

// --- Test 1: Temp output ---
Console.WriteLine("═══ Test 1: Temp output directory ═══");
using (var sandbox = new SandboxBuilder()
.WithModulePath(guestPath)
.WithPythonModule()
.WithTempOutput()
.Build())
{
Expand All @@ -38,7 +36,7 @@ with open("/output/hello.txt", "w") as f:
try
{
using var sandbox = new SandboxBuilder()
.WithModulePath(guestPath)
.WithPythonModule()
.WithInputDir(inputDir)
.WithTempOutput()
.Build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Api\HyperlightSandbox.Api.csproj" />
<ProjectReference Include="..\Common\Common.csproj" />
<ProjectReference Include="..\..\Guest.Python\HyperlightSandbox.Guest.Python.csproj" />
</ItemGroup>
</Project>
8 changes: 3 additions & 5 deletions src/sdk/dotnet/core/Examples/NetworkExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@
// Mirrors: src/wasm_sandbox/examples/python_network_demo.rs

using HyperlightSandbox.Api;
using HyperlightSandbox.Examples.Common;

var guestPath = ExampleHelper.RequirePythonGuest();
using HyperlightSandbox.Guest.Python;

Console.WriteLine("=== Hyperlight Sandbox .NET — Network Example ===\n");

// --- Test 1: Allow a domain with all methods ---
Console.WriteLine("═══ Test 1: HTTP GET with allowlisted domain ═══");
using (var sandbox = new SandboxBuilder()
.WithModulePath(guestPath)
.WithPythonModule()
.Build())
{
sandbox.AllowDomain("https://httpbin.org");
Expand All @@ -30,7 +28,7 @@
// --- Test 2: Method-filtered access ---
Console.WriteLine("\n═══ Test 2: Method-filtered access (GET only) ═══");
using (var sandbox = new SandboxBuilder()
.WithModulePath(guestPath)
.WithPythonModule()
.Build())
{
// Only allow GET requests to httpbin.org.
Expand Down
6 changes: 2 additions & 4 deletions src/sdk/dotnet/core/Examples/SnapshotExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@

using System.Diagnostics;
using HyperlightSandbox.Api;
using HyperlightSandbox.Examples.Common;

var guestPath = ExampleHelper.RequirePythonGuest();
using HyperlightSandbox.Guest.Python;

Console.WriteLine("=== Hyperlight Sandbox .NET — Snapshot Example ===\n");

using var sandbox = new SandboxBuilder()
.WithModulePath(guestPath)
.WithPythonModule()
.WithTempOutput()
.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Api\HyperlightSandbox.Api.csproj" />
<ProjectReference Include="..\Common\Common.csproj" />
<ProjectReference Include="..\..\Guest.Python\HyperlightSandbox.Guest.Python.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@

using System.Text.Json.Serialization;
using HyperlightSandbox.Api;
using HyperlightSandbox.Examples.Common;

var guestPath = ExampleHelper.RequirePythonGuest();
using HyperlightSandbox.Guest.Python;

Console.WriteLine("=== Hyperlight Sandbox .NET — Tool Registration Example ===\n");

using var sandbox = new SandboxBuilder()
.WithModulePath(guestPath)
.WithPythonModule()
.Build();

// --- Register typed tools ---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Api\HyperlightSandbox.Api.csproj" />
<ProjectReference Include="..\Common\Common.csproj" />
<ProjectReference Include="..\..\Guest.Python\HyperlightSandbox.Guest.Python.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AnalysisMode>All</AnalysisMode>
<AnalysisLevel>latest</AnalysisLevel>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<RootNamespace>HyperlightSandbox.Guest.JavaScript</RootNamespace>

<!-- NuGet Package Metadata -->
<PackageId>Hyperlight.HyperlightSandbox.Guest.JavaScript</PackageId>
<Description>JavaScript guest module package for hyperlight-sandbox. Bundles the prebuilt JavaScript AOT guest and provides SandboxBuilder.WithJavaScriptModule().</Description>
<PackageTags>hyperlight;sandbox;javascript;guest;module</PackageTags>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/hyperlight-dev/hyperlight-sandbox</PackageProjectUrl>
<RepositoryUrl>https://github.com/hyperlight-dev/hyperlight-sandbox</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
</PropertyGroup>

<PropertyGroup>
<WorkspaceRoot>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../../../../..'))</WorkspaceRoot>
<JavaScriptGuestDir>$([System.IO.Path]::Combine('$(WorkspaceRoot)', 'src', 'wasm_sandbox', 'guests', 'javascript'))</JavaScriptGuestDir>
</PropertyGroup>
Comment thread
jsturtevant marked this conversation as resolved.

<ItemGroup>
<ProjectReference Include="..\Api\HyperlightSandbox.Api.csproj" />
</ItemGroup>

<!--
Native assets following the NuGet runtimes/{rid}/native/ convention (same as PInvoke).
The .aot file is Hyperlight/Cranelift AOT output: architecture-specific but NOT OS-specific,
so the same binary serves both linux-x64 and win-x64. Include it under both RID folders so
NuGet selects the right entry for each consumer platform from a single package build.
-->
<ItemGroup>
<None Include="$(JavaScriptGuestDir)/js-sandbox.aot"
Condition="Exists('$(JavaScriptGuestDir)/js-sandbox.aot')">
<Pack>true</Pack>
<PackagePath>runtimes/linux-x64/native/</PackagePath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>runtimes/linux-x64/native/js-sandbox.aot</Link>
</None>
<None Include="$(JavaScriptGuestDir)/js-sandbox.aot"
Condition="Exists('$(JavaScriptGuestDir)/js-sandbox.aot')">
<Pack>true</Pack>
<PackagePath>runtimes/win-x64/native/</PackagePath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>runtimes/win-x64/native/js-sandbox.aot</Link>
</None>
</ItemGroup>

<Target Name="ValidateJavaScriptGuestResources" BeforeTargets="Pack">
<Error Condition="!Exists('$(JavaScriptGuestDir)/js-sandbox.aot')"
Text="JavaScript guest AOT binary is missing. Run 'just wasm js-guest-build' before packing Hyperlight.HyperlightSandbox.Guest.JavaScript." />
</Target>

</Project>
Loading
Loading