Skip to content

Commit 64f80d3

Browse files
authored
feat: eliminate deps/hyperlight-js git clone (#13)
Replace the manual git clone of hyperlight-js with Cargo's built-in git dependency resolution. The runtime's Cargo.toml now uses a git dep on hyperlight-js-runtime, and the NAPI addon (js-host-api) is built from Cargo's checkout at ~/.cargo/git/checkouts/ with a symlink at deps/js-host-api for npm file: dependency resolution. Changes: - Cargo git dep for hyperlight-js-runtime (was path dep to clone) - HYPERLIGHT_CFLAGS resolved via cargo metadata + Node.js one-liner - Justfile: resolve-hyperlight-dir discovers checkout, builds NAPI addon, creates symlink (no more fetch-hyperlight/git clone) - package.json: file:deps/js-host-api (was file:deps/hyperlight-js/...) - Scripts/tests: all paths updated to deps/js-host-api - extract-hyperlight-builtins.ts: uses cargo metadata to find source - Removed: jq dependency, build-with-runtime alias, dead PWD variable - Docs: all clone references removed, setup descriptions updated - Docker/CI: COPY path and comments updated for symlink pattern Signed-off-by: Simon Davies <simongdavies@users.noreply.github.com>
1 parent 50e738c commit 64f80d3

File tree

17 files changed

+462
-186
lines changed

17 files changed

+462
-186
lines changed

.claude/CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Use `just` commands for development (preferred) or npm scripts:
3636

3737
```bash
3838
# ── Development ──
39-
just setup # First-time setup: clone deps, build native addons, npm install
39+
just setup # First-time setup: build native addons, npm install
4040
just build # Rebuild native addons and install deps
4141
just start # Run agent (tsx src/agent/index.ts)
4242

.dockerignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ tests/
1313
.claude/
1414

1515
# Rust build artifacts (huge - 9GB+)
16-
deps/hyperlight-js/target/
17-
src/hyperlight-analysis-guest/target/
1816
**/target/
1917

2018
# KEEP dist/lib/node_modules (bundled @github/copilot SDK)

.github/copilot-instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Key config files at root: `package.json`, `tsconfig.json`, `vitest.config.ts`, `
2929
Always use these commands in this order for a clean build:
3030

3131
```bash
32-
just setup # First-time only: clone deps, build native addons, npm install
32+
just setup # First-time only: build native addons, npm install
3333
just build # Rebuild native addons and install deps (run after Rust changes)
3434
```
3535

.github/workflows/pr-validate.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ jobs:
146146
path: dist/
147147
retention-days: 7
148148

149-
# Build Docker image (just setup clones deps so Dockerfile COPY works)
149+
# Build Docker image (just setup builds deps + creates symlinks for Dockerfile COPY)
150150
build-docker:
151151
name: Build Docker Image
152152
needs: [docs-pr]
@@ -168,6 +168,14 @@ jobs:
168168
- name: Setup
169169
run: just setup
170170

171+
- name: Resolve symlinks for Docker context
172+
run: |
173+
if [ -L deps/js-host-api ]; then
174+
target=$(readlink -f deps/js-host-api)
175+
rm deps/js-host-api
176+
cp -r "$target" deps/js-host-api
177+
fi
178+
171179
- name: Set up Docker Buildx
172180
uses: docker/setup-buildx-action@v3
173181

.github/workflows/publish.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ jobs:
118118
- name: Setup
119119
run: just setup
120120

121+
- name: Resolve symlinks for Docker context
122+
run: |
123+
if [ -L deps/js-host-api ]; then
124+
target=$(readlink -f deps/js-host-api)
125+
rm deps/js-host-api
126+
cp -r "$target" deps/js-host-api
127+
fi
128+
121129
- name: Set up Docker Buildx
122130
uses: docker/setup-buildx-action@v3
123131

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Use `just` commands for development (preferred) or npm scripts:
3636

3737
```bash
3838
# ── Development ──
39-
just setup # First-time setup: clone deps, build native addons, npm install
39+
just setup # First-time setup: build native addons, npm install
4040
just build # Rebuild native addons and install deps
4141
just start # Run agent (tsx src/agent/index.ts)
4242

Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ WORKDIR /build
2727
# Copy package files first for layer caching
2828
COPY package*.json ./
2929

30-
# Copy the hyperlight deps (for file: dependency)
31-
COPY deps/hyperlight-js/src/js-host-api/ ./deps/hyperlight-js/src/js-host-api/
30+
# Copy the NAPI addon (must be a real directory, not a symlink —
31+
# use `just docker-build` or resolve symlinks before `docker build`)
32+
COPY deps/js-host-api/ ./deps/js-host-api/
3233
COPY src/code-validator/guest/ ./src/code-validator/guest/
3334

3435
# Install dependencies

Justfile

Lines changed: 69 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,22 @@
99
# - KVM support (for running the Hyperlight micro-VM)
1010
#
1111
# First-time setup:
12-
# just setup # clones + builds hyperlight-js, installs npm deps
12+
# just setup # builds native addons, installs npm deps
1313
#
1414
# ─────────────────────────────────────────────────────────────────────
1515

16-
# Windows: use PowerShell, replace backslashes for clang compatibility
16+
# Windows: use PowerShell
1717
set windows-shell := ["pwsh.exe", "-NoLogo", "-Command"]
1818

19-
# In windows we need to replace the backslashes with forward slashes
20-
# otherwise clang will misinterpret the paths
21-
PWD := replace(justfile_dir(), "\\", "/")
22-
2319
# On Windows, use Ninja generator for CMake to avoid aws-lc-sys build issues
2420
export CMAKE_GENERATOR := if os() == "windows" { "Ninja" } else { "" }
2521

26-
# The hyperlight-js repo URL and ref to build against.
27-
# Currently using Simon's fork with in-flight PRs (binary types, call stats).
28-
# TODO: Switch to hyperlight-dev/hyperlight-js main once PRs land upstream.
29-
hyperlight-repo := "https://github.com/simongdavies/hyperlight-js.git"
30-
hyperlight-ref := "hyperagent"
31-
hyperlight-dir := justfile_dir() / "deps" / "hyperlight-js"
22+
# The hyperlight-js workspace root, discovered from Cargo's git checkout.
23+
# The runtime's Cargo.toml uses a git dep on hyperlight-js-runtime, so Cargo
24+
# already clones the full workspace — we reuse that checkout to build the
25+
# NAPI addon (js-host-api) without a separate git clone.
26+
# Resolved lazily by the resolve-hyperlight-dir recipe.
27+
hyperlight-link := justfile_dir() / "deps" / "js-host-api"
3228

3329
# Hyperlight analysis guest (secure code validation in micro-VM)
3430
analysis-guest-dir := justfile_dir() / "src" / "code-validator" / "guest"
@@ -37,10 +33,11 @@ analysis-guest-dir := justfile_dir() / "src" / "code-validator" / "guest"
3733
runtime-dir := justfile_dir() / "src" / "sandbox" / "runtime"
3834

3935
# HYPERLIGHT_CFLAGS needed for building guests that link rquickjs/QuickJS:
40-
# -I include/ provides stubs for the hyperlight target (no libc)
41-
# -D__wasi__=1 disables pthread support in QuickJS
42-
# Uses forward slashes (PWD) so clang works on Windows
43-
runtime-cflags := "-I" + PWD + "/deps/hyperlight-js/src/hyperlight-js-runtime/include -D__wasi__=1"
36+
# The hyperlight target has no libc, so QuickJS needs stub headers plus
37+
# -D__wasi__=1 to disable pthreads. Uses cargo metadata to find the
38+
# include/ dir from the hyperlight-js-runtime dependency.
39+
# Fails loudly if resolution fails — empty CFLAGS causes cryptic build errors.
40+
runtime-cflags := `node -e "var m=JSON.parse(require('child_process').execSync('cargo +1.89 metadata --format-version 1 --manifest-path src/sandbox/runtime/Cargo.toml',{encoding:'utf8',stdio:['pipe','pipe','inherit'],maxBuffer:20*1024*1024}));var p=m.packages.find(function(p){return p.name==='hyperlight-js-runtime'});if(!p){process.stderr.write('ERROR: hyperlight-js-runtime not found in cargo metadata\n');process.exit(1)}console.log('-I'+require('path').join(require('path').dirname(p.manifest_path),'include')+' -D__wasi__=1')"`
4441

4542
# Export HYPERLIGHT_CFLAGS so cargo-hyperlight picks them up when building runtimes
4643
export HYPERLIGHT_CFLAGS := runtime-cflags
@@ -50,12 +47,29 @@ export HYPERLIGHT_CFLAGS := runtime-cflags
5047
# Without this, the default runtime (no ha:ziplib) would be embedded.
5148
export HYPERLIGHT_JS_RUNTIME_PATH := runtime-dir / "target" / "x86_64-hyperlight-none" / "release" / "hyperagent-runtime"
5249

53-
# Clone (or update) the hyperlight-js dependency at the pinned ref.
54-
# Cross-platform: - prefix ignores clone failure (dir already exists).
50+
# Resolve the hyperlight-js workspace root from Cargo's git checkout.
51+
# Uses cargo metadata to find where hyperlight-js-runtime lives, then
52+
# derives the workspace src/ dir (js-host-api is a sibling crate).
53+
# Outputs the workspace root path (parent of src/).
5554
[private]
56-
fetch-hyperlight:
57-
-git clone --branch "{{hyperlight-ref}}" --single-branch --depth 1 "{{hyperlight-repo}}" "{{hyperlight-dir}}"
58-
cd "{{hyperlight-dir}}" && git fetch origin "{{hyperlight-ref}}" --depth 1 && git checkout FETCH_HEAD
55+
[unix]
56+
resolve-hyperlight-dir:
57+
#!/usr/bin/env bash
58+
set -euo pipefail
59+
dir=$(node -e "\
60+
var m=JSON.parse(require('child_process').execSync(\
61+
'cargo +1.89 metadata --format-version 1 --manifest-path src/sandbox/runtime/Cargo.toml',\
62+
{encoding:'utf8',stdio:['pipe','pipe','pipe'],maxBuffer:20*1024*1024}));\
63+
var p=m.packages.find(function(p){return p.name==='hyperlight-js-runtime'});\
64+
if(p)console.log(require('path').resolve(require('path').dirname(p.manifest_path),'..','..'));\
65+
else{process.stderr.write('hyperlight-js-runtime not found in cargo metadata');process.exit(1)}")
66+
js_host_api="${dir}/src/js-host-api"
67+
if [ ! -d "$js_host_api" ]; then
68+
echo "❌ js-host-api not found at ${js_host_api}"
69+
echo " Run: cargo +1.89 fetch --manifest-path src/sandbox/runtime/Cargo.toml"
70+
exit 1
71+
fi
72+
echo "$dir"
5973

6074
# Install required Rust toolchains and cargo subcommands.
6175
# Cross-platform (Linux/macOS/Windows) — no bash required.
@@ -65,19 +79,27 @@ ensure-tools:
6579
rustup toolchain install 1.89 --no-self-update
6680
rustup toolchain install nightly --no-self-update
6781

68-
# Build the native hyperlight-js NAPI addon (debug — default)
69-
# Depends on build-runtime-release so the custom runtime with native modules
70-
# is always embedded. cargo clean -p prevents stale cached builds.
71-
[private]
72-
build-hyperlight: fetch-hyperlight (build-runtime-release)
73-
-cd "{{hyperlight-dir}}/src/hyperlight-js" && cargo clean -p hyperlight-js
74-
cd "{{hyperlight-dir}}" && just build
75-
76-
# Build the native hyperlight-js NAPI addon (release — optimised)
82+
# Build the native hyperlight-js NAPI addon.
83+
# 1. Builds the custom runtime (Cargo git dep fetches hyperlight-js automatically)
84+
# 2. Discovers the hyperlight-js workspace from Cargo's checkout
85+
# 3. Builds the NAPI addon with our custom runtime embedded
86+
# 4. Symlinks deps/js-host-api → checkout/src/js-host-api for npm file: dep
87+
# NOTE: [unix] only — Windows support is disabled pending upstream fix (issue #1).
88+
# When Windows lands, add [windows] variants using mklink /J for junctions.
7789
[private]
78-
build-hyperlight-release: fetch-hyperlight (build-runtime-release)
79-
-cd "{{hyperlight-dir}}/src/hyperlight-js" && cargo clean -p hyperlight-js
80-
cd "{{hyperlight-dir}}" && just build release
90+
[unix]
91+
build-hyperlight target="debug": (build-runtime-release)
92+
#!/usr/bin/env bash
93+
set -euo pipefail
94+
hl_dir=$(just resolve-hyperlight-dir)
95+
# Clean stale hyperlight-js builds so build.rs re-embeds the runtime
96+
cd "${hl_dir}/src/hyperlight-js" && cargo clean -p hyperlight-js 2>/dev/null || true
97+
# Build the NAPI addon (inherits HYPERLIGHT_JS_RUNTIME_PATH from env)
98+
cd "${hl_dir}" && just build {{ if target == "debug" { "" } else { target } }}
99+
# Symlink for npm file: dependency resolution
100+
mkdir -p "{{justfile_dir()}}/deps"
101+
ln -sfn "${hl_dir}/src/js-host-api" "{{hyperlight-link}}"
102+
echo "🔗 deps/js-host-api → ${hl_dir}/src/js-host-api"
81103

82104
# Build the hyperlight-analysis-guest NAPI addon (debug)
83105
[private]
@@ -89,19 +111,19 @@ build-analysis-guest:
89111
build-analysis-guest-release:
90112
cd "{{analysis-guest-dir}}" && just build release && just build-napi release
91113

92-
# Install npm deps (links hyperlight-js and analysis-guest from local dirs)
114+
# Install npm deps (builds native addons, symlinks js-host-api)
93115
[private]
94-
install: build-hyperlight build-analysis-guest
116+
install: (build-hyperlight) build-analysis-guest
95117
npm install
96118

97119
# Install npm deps with release-built native addons
98120
[private]
99-
install-release: build-hyperlight-release build-analysis-guest-release
121+
install-release: (build-hyperlight "release") build-analysis-guest-release
100122
npm install
101123

102124
# ── First-time setup ─────────────────────────────────────────────────
103125

104-
# Clone hyperlight-js, build native addon, install npm deps
126+
# First-time setup: build native addons, install npm deps
105127
setup: ensure-tools install
106128
@echo "✅ Setup complete — run 'just start' to launch the agent"
107129

@@ -187,18 +209,13 @@ test-analysis-guest:
187209
# ── HyperAgent Runtime (native modules) ──────────────────────────────
188210

189211
# Build the custom runtime for the hyperlight target (debug)
190-
build-runtime: fetch-hyperlight
212+
build-runtime:
191213
cd "{{runtime-dir}}" && cargo +1.89 hyperlight build --target-dir target
192214

193215
# Build the custom runtime for the hyperlight target (release)
194-
build-runtime-release: fetch-hyperlight
216+
build-runtime-release:
195217
cd "{{runtime-dir}}" && cargo +1.89 hyperlight build --target-dir target --release
196218

197-
# Legacy alias — the standard build now always uses the custom runtime.
198-
# Kept for backwards compatibility with existing scripts/docs.
199-
build-with-runtime: build
200-
@echo "✅ (build-with-runtime is now a no-op — 'just build' always uses the custom runtime)"
201-
202219
# Lint Rust code in the custom runtime
203220
lint-runtime:
204221
cd "{{runtime-dir}}" && cargo +1.89 clippy --workspace -- -D warnings
@@ -238,7 +255,7 @@ check: lint-all test-all
238255
clean:
239256
rm -rf dist node_modules
240257

241-
# Clean everything including the hyperlight-js clone
258+
# Clean everything including deps/ symlinks
242259
clean-all: clean
243260
rm -rf deps
244261

@@ -271,6 +288,13 @@ docker-build:
271288
version="0.0.0-dev"
272289
fi
273290
echo "📦 Docker build version: ${version}"
291+
# Dereference symlinks — Docker COPY can't follow symlinks outside the build context
292+
if [ -L deps/js-host-api ]; then
293+
target=$(readlink -f deps/js-host-api)
294+
rm deps/js-host-api
295+
cp -r "$target" deps/js-host-api
296+
trap 'rm -rf deps/js-host-api && ln -sfn "'"$target"'" deps/js-host-api' EXIT
297+
fi
274298
docker build -t hyperagent --build-arg VERSION="${version}" .
275299

276300
# Run hyperagent in Docker (requires /dev/kvm or /dev/mshv)

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ Requires Node.js 22+, Rust toolchain, and [just](https://github.com/casey/just)
125125
git clone https://github.com/hyperlight-dev/hyperagent.git
126126
cd hyperagent
127127

128-
# First-time setup — clones deps, builds native Rust addons, installs npm packages
128+
# First-time setup — builds native Rust addons, installs npm packages
129129
just setup
130130

131131
# Run the agent (tsx transpiles on the fly — no build step needed)
@@ -140,7 +140,7 @@ Key `just` commands:
140140

141141
| Command | What it does |
142142
|---------|-------------|
143-
| `just setup` | First-time setup (clone deps, build native addons, npm install) |
143+
| `just setup` | First-time setup (build native addons, npm install) |
144144
| `just build` | Rebuild native addons after Rust changes |
145145
| `just start` | Run agent with tsx (fast iteration) |
146146
| `just binary-release` | Build optimised standalone binary to `dist/bin/hyperagent` |

docs/DEVELOPMENT.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,17 @@ For contribution guidelines (issues, PRs, DCO), see [CONTRIBUTING.md](../CONTRIB
1212
- **just** command runner (`cargo install just`)
1313
- **GitHub CLI** (`gh`) authenticated
1414

15-
## Clone and Build
15+
## Build
1616

1717
```bash
1818
git clone https://github.com/hyperlight-dev/hyperagent
1919
cd hyperagent
2020

21-
# Install Node dependencies
22-
npm install
23-
24-
# Build native Hyperlight components
25-
just build
21+
# First-time setup — builds native addons, installs npm deps
22+
just setup
2623

2724
# Verify setup
28-
npm test
25+
just test
2926
```
3027

3128
## Running from Source

0 commit comments

Comments
 (0)