Skip to content

Commit 3c59041

Browse files
authored
Add wasm packages for .net sdk (#68)
* Add wasm packages for .net sdk Signed-off-by: James Sturtevant <jsturtevant@gmail.com> * Respond to feedback Signed-off-by: James Sturtevant <jsturtevant@gmail.com> --------- Signed-off-by: James Sturtevant <jsturtevant@gmail.com>
1 parent 4b9647a commit 3c59041

21 files changed

Lines changed: 376 additions & 64 deletions

File tree

RELEASE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ All other workspace member crates inherit the version automatically.
2424

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

27+
### .NET (Directory.Build.props)
28+
29+
- `src/sdk/dotnet/Directory.Build.props`
30+
2731
## 2. Verify the Build
2832

2933
```sh

src/sdk/dotnet/Justfile

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ devnull := if os() == "windows" { "$null" } else { "/dev/null" }
1919
#### BUILD ####
2020

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

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

32+
# Build guest modules that are embedded into guest NuGet packages
33+
build-guests target=default-target:
34+
cd {{repo-root}} && just -f src/wasm_sandbox/Justfile guest-build {{target}}
35+
cd {{repo-root}} && just -f src/wasm_sandbox/Justfile js-guest-build
36+
3237
#### FORMAT ####
3338

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

8388
#### EXAMPLES ####
8489

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

101106
# Build NuGet packages
102-
dist target="release": (build target)
107+
dist target="release": (build-guests target) (build target)
103108
{{mkdirp}} {{repo-root}}/dist/dotnetsdk
104109
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
105110
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
106111
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
112+
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
113+
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
107114
@echo "✅ NuGet packages created in dist/dotnetsdk/"
108115

109116
# Publish NuGet packages to nuget.org (requires NUGET_API_KEY env var)
@@ -157,4 +164,8 @@ clean:
157164
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Api/obj
158165
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Extensions.AI/bin
159166
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Extensions.AI/obj
167+
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Guest.Python/bin
168+
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Guest.Python/obj
169+
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Guest.JavaScript/bin
170+
-{{rmrf}} {{repo-root}}/src/sdk/dotnet/core/Guest.JavaScript/obj
160171
-{{rmrf}} {{repo-root}}/dist/dotnetsdk

src/sdk/dotnet/README.md

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ A .NET 8.0 SDK for running code in secure, sandboxed environments using [hyperli
1818

1919
```bash
2020
# Prerequisites
21-
just wasm guest-build # Build the Python guest module
2221
just dotnet build # Build the .NET SDK + Rust FFI
2322
```
2423

2524
### Basic Usage
2625

2726
```csharp
2827
using HyperlightSandbox.Api;
28+
using HyperlightSandbox.Guest.Python;
2929

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

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

5151
```csharp
5252
using var sandbox = new SandboxBuilder()
53-
.WithModulePath("python-sandbox.aot")
53+
.WithPythonModule()
5454
.Build();
5555

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

90+
To run JavaScript through the Wasm guest module package instead, reference
91+
`Hyperlight.HyperlightSandbox.Guest.JavaScript` and call:
92+
93+
```csharp
94+
using HyperlightSandbox.Guest.JavaScript;
95+
96+
using var sandbox = new SandboxBuilder()
97+
.WithJavaScriptModule()
98+
.Build();
99+
```
100+
90101
### Snapshot/Restore
91102

92103
Checkpoint sandbox state for fast resets between executions:
93104

94105
```csharp
95106
using var sandbox = new SandboxBuilder()
96-
.WithModulePath("python-sandbox.aot")
107+
.WithPythonModule()
97108
.Build();
98109

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

115126
```csharp
116127
using var sandbox = new SandboxBuilder()
117-
.WithModulePath("python-sandbox.aot")
128+
.WithPythonModule()
118129
.WithInputDir("/path/to/input") // Read-only /input in guest
119130
.WithTempOutput() // Writable /output in guest
120131
.Build();
@@ -149,11 +160,12 @@ Use with GitHub Copilot SDK or Microsoft Agent Framework:
149160
```csharp
150161
using HyperlightSandbox.Api;
151162
using HyperlightSandbox.Extensions.AI;
163+
using HyperlightSandbox.Guest.Python;
152164

153165
// Create a code execution tool with snapshot/restore for clean state
154166
using var codeTool = new CodeExecutionTool(
155167
new SandboxBuilder()
156-
.WithModulePath("python-sandbox.aot")
168+
.WithPythonModule()
157169
.WithTempOutput());
158170

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

233247
## API Reference
234248

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

304320
## Contributing
305321

src/sdk/dotnet/core/Examples/BasicExample/BasicExample.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
</PropertyGroup>
88
<ItemGroup>
99
<ProjectReference Include="..\..\Api\HyperlightSandbox.Api.csproj" />
10-
<ProjectReference Include="..\Common\Common.csproj" />
10+
<ProjectReference Include="..\..\Guest.Python\HyperlightSandbox.Guest.Python.csproj" />
1111
</ItemGroup>
1212
</Project>

src/sdk/dotnet/core/Examples/BasicExample/Program.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,15 @@
33
// Mirrors: src/wasm_sandbox/examples/python_basics.rs
44
//
55
// Prerequisites:
6-
// just wasm guest-build # builds python-sandbox.aot
7-
// just dotnet build # builds the .NET SDK + FFI
6+
// just dotnet build # builds the .NET SDK + bundled guest package
87

98
using HyperlightSandbox.Api;
10-
using HyperlightSandbox.Examples.Common;
11-
12-
var guestPath = ExampleHelper.RequirePythonGuest();
9+
using HyperlightSandbox.Guest.Python;
1310

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

1713
using var sandbox = new SandboxBuilder()
18-
.WithModulePath(guestPath)
14+
.WithPythonModule()
1915
.Build();
2016

2117
// --- Test 1: Basic code execution ---

src/sdk/dotnet/core/Examples/FilesystemExample/FilesystemExample.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
</PropertyGroup>
88
<ItemGroup>
99
<ProjectReference Include="..\..\Api\HyperlightSandbox.Api.csproj" />
10-
<ProjectReference Include="..\Common\Common.csproj" />
10+
<ProjectReference Include="..\..\Guest.Python\HyperlightSandbox.Guest.Python.csproj" />
1111
</ItemGroup>
1212
</Project>

src/sdk/dotnet/core/Examples/FilesystemExample/Program.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@
33
// Mirrors: src/wasm_sandbox/examples/python_filesystem_demo.rs
44

55
using HyperlightSandbox.Api;
6-
using HyperlightSandbox.Examples.Common;
7-
8-
var guestPath = ExampleHelper.RequirePythonGuest();
6+
using HyperlightSandbox.Guest.Python;
97

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

1210
// --- Test 1: Temp output ---
1311
Console.WriteLine("═══ Test 1: Temp output directory ═══");
1412
using (var sandbox = new SandboxBuilder()
15-
.WithModulePath(guestPath)
13+
.WithPythonModule()
1614
.WithTempOutput()
1715
.Build())
1816
{
@@ -38,7 +36,7 @@ with open("/output/hello.txt", "w") as f:
3836
try
3937
{
4038
using var sandbox = new SandboxBuilder()
41-
.WithModulePath(guestPath)
39+
.WithPythonModule()
4240
.WithInputDir(inputDir)
4341
.WithTempOutput()
4442
.Build();

src/sdk/dotnet/core/Examples/NetworkExample/NetworkExample.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
</PropertyGroup>
88
<ItemGroup>
99
<ProjectReference Include="..\..\Api\HyperlightSandbox.Api.csproj" />
10-
<ProjectReference Include="..\Common\Common.csproj" />
10+
<ProjectReference Include="..\..\Guest.Python\HyperlightSandbox.Guest.Python.csproj" />
1111
</ItemGroup>
1212
</Project>

src/sdk/dotnet/core/Examples/NetworkExample/Program.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@
33
// Mirrors: src/wasm_sandbox/examples/python_network_demo.rs
44

55
using HyperlightSandbox.Api;
6-
using HyperlightSandbox.Examples.Common;
7-
8-
var guestPath = ExampleHelper.RequirePythonGuest();
6+
using HyperlightSandbox.Guest.Python;
97

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

1210
// --- Test 1: Allow a domain with all methods ---
1311
Console.WriteLine("═══ Test 1: HTTP GET with allowlisted domain ═══");
1412
using (var sandbox = new SandboxBuilder()
15-
.WithModulePath(guestPath)
13+
.WithPythonModule()
1614
.Build())
1715
{
1816
sandbox.AllowDomain("https://httpbin.org");
@@ -30,7 +28,7 @@
3028
// --- Test 2: Method-filtered access ---
3129
Console.WriteLine("\n═══ Test 2: Method-filtered access (GET only) ═══");
3230
using (var sandbox = new SandboxBuilder()
33-
.WithModulePath(guestPath)
31+
.WithPythonModule()
3432
.Build())
3533
{
3634
// Only allow GET requests to httpbin.org.

src/sdk/dotnet/core/Examples/SnapshotExample/Program.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@
66

77
using System.Diagnostics;
88
using HyperlightSandbox.Api;
9-
using HyperlightSandbox.Examples.Common;
10-
11-
var guestPath = ExampleHelper.RequirePythonGuest();
9+
using HyperlightSandbox.Guest.Python;
1210

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

1513
using var sandbox = new SandboxBuilder()
16-
.WithModulePath(guestPath)
14+
.WithPythonModule()
1715
.WithTempOutput()
1816
.Build();
1917

0 commit comments

Comments
 (0)