Sitelet https://github.com/NodeOps-app/createos-sandbox-sdk/commit/18cd476e0cdb2ecde1f518364f86e9c674f1acd7
Skip to content

Commit 18cd476

Browse files
committed
feat(examples): add 13-20, 36-37, CI, docs + deps
1 parent 37a8e76 commit 18cd476

116 files changed

Lines changed: 5090 additions & 293 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/examples.yml‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: examples
2+
3+
# Runs every example end-to-end against the live fc-spawn control plane.
4+
# Each example is a one-shot `bun index.ts` that creates a sandbox, verifies
5+
# it, and destroys it in a `finally` block — so a green job means the example
6+
# worked against production.
7+
#
8+
# Cost note: every run spawns real microVMs and makes paid LLM API calls.
9+
# Triggers are kept deliberate: nightly, manual, and on SDK source changes.
10+
11+
on:
12+
workflow_dispatch:
13+
schedule:
14+
- cron: "17 3 * * *" # nightly 03:17 UTC
15+
push:
16+
branches: [main]
17+
paths:
18+
- "src/**"
19+
- ".github/workflows/examples.yml"
20+
pull_request:
21+
paths:
22+
- "src/**"
23+
- ".github/workflows/examples.yml"
24+
25+
concurrency:
26+
group: examples-${{ github.ref }}
27+
cancel-in-progress: true
28+
29+
permissions:
30+
contents: read # checkout only; no write scope needed
31+
32+
jobs:
33+
# Build the example matrix from the examples/ directory so new examples are
34+
# picked up automatically — no edits to this file when one is added.
35+
discover:
36+
runs-on: arc-runner-set
37+
outputs:
38+
examples: ${{ steps.list.outputs.examples }}
39+
steps:
40+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
41+
- id: list
42+
run: |
43+
json=$(cd examples && for d in [0-9]*/; do printf '%s\n' "${d%/}"; done \
44+
| grep . | sed 's/.*/"&"/' | paste -sd, -)
45+
echo "examples=[$json]" >> "$GITHUB_OUTPUT"
46+
47+
run:
48+
needs: discover
49+
runs-on: arc-runner-set
50+
timeout-minutes: 20
51+
strategy:
52+
# No max-parallel: GitHub runs as many matrix jobs in parallel as the
53+
# runner pool allows (unlimited by request). The fc-spawn control plane
54+
# is the backstop that queues sandbox creation under load.
55+
fail-fast: false # one failing example must not cancel the others
56+
matrix:
57+
example: ${{ fromJson(needs.discover.outputs.examples) }}
58+
name: ${{ matrix.example }}
59+
steps:
60+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
61+
62+
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
63+
with:
64+
bun-version: latest
65+
66+
# The SDK is consumed by examples via `file:../`, whose `main` points at
67+
# dist/. Build it before installing/running any example.
68+
- name: Build SDK
69+
run: |
70+
bun install --frozen-lockfile
71+
bun run build
72+
73+
- name: Install example dependencies
74+
working-directory: examples
75+
run: bun install --frozen-lockfile
76+
77+
- name: Run ${{ matrix.example }}
78+
working-directory: examples/${{ matrix.example }}
79+
env:
80+
# --- fc-spawn control plane (read by the SDK + most examples) ---
81+
FC_API_KEY: ${{ secrets.FC_API_KEY }}
82+
FC_BASE_URL: ${{ secrets.FC_BASE_URL }}
83+
# --- OpenAI / OpenAI-compatible ---
84+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
85+
OPENAI_API_URL: ${{ secrets.OPENAI_API_URL }}
86+
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
87+
OPENAI_MODEL: ${{ secrets.OPENAI_MODEL }}
88+
# OPENAI_USE_CHAT_COMPLETIONS: ${{ secrets.OPENAI_USE_CHAT_COMPLETIONS }}
89+
# OPENAI_AGENTS_DISABLE_TRACING: ${{ secrets.OPENAI_AGENTS_DISABLE_TRACING }}
90+
LLM_MODEL: ${{ secrets.LLM_MODEL }}
91+
# --- Anthropic ---
92+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
93+
ANTHROPIC_AUTH_TOKEN: ${{ secrets.ANTHROPIC_AUTH_TOKEN }}
94+
ANTHROPIC_BASE_URL: ${{ secrets.ANTHROPIC_BASE_URL }}
95+
ANTHROPIC_MODEL: ${{ secrets.ANTHROPIC_MODEL }}
96+
# --- third-party integrations (per-example) ---
97+
# BROWSERBASE_API_KEY: ${{ secrets.BROWSERBASE_API_KEY }}
98+
# BROWSERBASE_PROJECT_ID: ${{ secrets.BROWSERBASE_PROJECT_ID }}
99+
# FIRECRAWL_API_KEY: ${{ secrets.FIRECRAWL_API_KEY }}
100+
# FIRECRAWL_API_URL: ${{ secrets.FIRECRAWL_API_URL }}
101+
# OPENCLAW_GATEWAY_TOKEN: ${{ secrets.OPENCLAW_GATEWAY_TOKEN }}
102+
# SCRAPE_URL: ${{ secrets.SCRAPE_URL }}
103+
run: bun index.ts

‎.gitignore‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,7 @@ pnpm-debug.log*
3131

3232
# Local tooling/cache
3333
.firecrawl/
34+
__pycache__
35+
36+
# Claude Code internal state
37+
.claude/worktrees/

‎examples/01-hello-world/README.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ production control plane and only needs to be set to override.
2222

2323
## FC primitives exercised
2424

25-
| primitive | SDK call |
26-
| --- | --- |
25+
| primitive | SDK call |
26+
| ----------------- | ------------------------------------------- |
2727
| Sandbox lifecycle | `Sandbox.create()` (blocks until `running`) |
28-
| Buffered exec | `sandbox.runCommand()` |
29-
| Tear down | `sandbox.destroy()` |
28+
| Buffered exec | `sandbox.runCommand()` |
29+
| Tear down | `sandbox.destroy()` |
3030

3131
## Versions captured at build time
3232

‎examples/02-code-interpreter/README.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ production control plane and only needs to be set to override.
2828

2929
## FC primitives exercised
3030

31-
| primitive | SDK call |
32-
| --- | --- |
33-
| File upload | `sandbox.files.upload()` |
34-
| Buffered exec | `sandbox.runCommand()` |
31+
| primitive | SDK call |
32+
| ------------------------ | --------------------------------- |
33+
| File upload | `sandbox.files.upload()` |
34+
| Buffered exec | `sandbox.runCommand()` |
3535
| Streaming exec (blocked) | `sandbox.streamCommand()` — fc#40 |
36-
| Tear down | `sandbox.destroy()` |
36+
| Tear down | `sandbox.destroy()` |
3737

3838
## Versions captured at build time
3939

‎examples/03-dev-server-preview-url/README.md‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ production control plane and only needs to be set to override.
3434

3535
## FC primitives exercised
3636

37-
| primitive | SDK call |
38-
| --- | --- |
39-
| Public ingress | `ingress_enabled: true` on `Sandbox.create()` |
40-
| URL derivation | `http://<ulid>-<port>.<region>.<domain>/` |
41-
| Background process in VM | `nohup setsid … &` (devbox:1 has no systemd) |
42-
| Port readiness | `sandbox.waitForPortReady()` |
43-
| Loopback gotcha | bind `0.0.0.0`, not `127.0.0.1` — ingress is via eth0 |
44-
| Tear down | `sandbox.destroy()` |
37+
| primitive | SDK call |
38+
| ------------------------ | ----------------------------------------------------- |
39+
| Public ingress | `ingress_enabled: true` on `Sandbox.create()` |
40+
| URL derivation | `http://<ulid>-<port>.<region>.<domain>/` |
41+
| Background process in VM | `nohup setsid … &` (devbox:1 has no systemd) |
42+
| Port readiness | `sandbox.waitForPortReady()` |
43+
| Loopback gotcha | bind `0.0.0.0`, not `127.0.0.1` — ingress is via eth0 |
44+
| Tear down | `sandbox.destroy()` |
4545

4646
## Versions captured at build time
4747

‎examples/05-filesystem-snapshots/README.md‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ production control plane and only needs to be set to override.
3030

3131
## FC primitives exercised
3232

33-
| primitive | SDK call |
34-
| --- | --- |
35-
| Snapshot a running sandbox to storage | `sandbox.pause()` + `waitUntilPaused()` |
36-
| Clone a paused sandbox into a new independent VM | `sandbox.fork()` |
37-
| Restore a paused sandbox in place | `sandbox.resume()` + `waitUntilRunning()` |
38-
| Push a file into a sandbox | `sandbox.files.upload()` |
39-
| Run a buffered command | `sandbox.runCommand()` |
40-
| Tear down | `sandbox.destroy()` |
33+
| primitive | SDK call |
34+
| ------------------------------------------------ | ----------------------------------------- |
35+
| Snapshot a running sandbox to storage | `sandbox.pause()` + `waitUntilPaused()` |
36+
| Clone a paused sandbox into a new independent VM | `sandbox.fork()` |
37+
| Restore a paused sandbox in place | `sandbox.resume()` + `waitUntilRunning()` |
38+
| Push a file into a sandbox | `sandbox.files.upload()` |
39+
| Run a buffered command | `sandbox.runCommand()` |
40+
| Tear down | `sandbox.destroy()` |
4141

4242
## Versions captured at build time
4343

‎examples/06-openai-agents-fc-tools/README.md‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ still runs end-to-end.
3333

3434
## FC primitives exercised
3535

36-
| primitive | SDK call |
37-
| --- | --- |
38-
| Create an isolated microVM workspace | `client.createSandbox()` |
39-
| Push files into the workspace | `sandbox.files.upload()` |
40-
| Run buffered commands for agent tools | `sandbox.runCommand()` |
41-
| Tear down | `sandbox.destroy()` |
36+
| primitive | SDK call |
37+
| ------------------------------------- | ------------------------ |
38+
| Create an isolated microVM workspace | `client.createSandbox()` |
39+
| Push files into the workspace | `sandbox.files.upload()` |
40+
| Run buffered commands for agent tools | `sandbox.runCommand()` |
41+
| Tear down | `sandbox.destroy()` |
4242

4343
## Versions captured at build time
4444

‎examples/07-docker-custom-template/README.md‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ tokens) are documented in `.env.example`.
2727

2828
## FC primitives exercised
2929

30-
| primitive | SDK call |
31-
| --- | --- |
32-
| Build a custom rootfs from a Dockerfile | `fc.templates.create()` |
33-
| Stream live build logs | `fc.templates.followLogs()` |
34-
| Launch sandbox from custom template | `fc.createSandbox({ rootfs: template.id })` |
35-
| Run a buffered command | `sandbox.runCommand()` |
36-
| Tear down sandbox | `sandbox.destroy()` |
37-
| Delete a template | `fc.templates.delete()` |
30+
| primitive | SDK call |
31+
| --------------------------------------- | ------------------------------------------- |
32+
| Build a custom rootfs from a Dockerfile | `fc.templates.create()` |
33+
| Stream live build logs | `fc.templates.followLogs()` |
34+
| Launch sandbox from custom template | `fc.createSandbox({ rootfs: template.id })` |
35+
| Run a buffered command | `sandbox.runCommand()` |
36+
| Tear down sandbox | `sandbox.destroy()` |
37+
| Delete a template | `fc.templates.delete()` |
3838

3939
## Versions captured at build time
4040

‎examples/08-dev-server-git-preview/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ inside an FC sandbox, expose it via HTTP ingress, and print the live preview URL
77

88
1. Creates a sandbox with `ingress_enabled: true` (1 vCPU / 1 GB).
99
2. Sparse-clones the `hello-world` example from the Next.js repo (`--depth=1
10-
--filter=blob:none --sparse`) — under 2 MB download.
10+
--filter=blob:none --sparse`) — under 2 MB download.
1111
3. Runs `npm install` inside the clone.
1212
4. Daemonises `npx next dev -p 3000` via `nohup setsid` (no systemd in FC).
1313
5. Polls the ingress URL until Next.js responds (up to 90 s — cold compile takes

0 commit comments

Comments
 (0)