@axiom-lattice/opensandbox-gateway 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +12 -0
- package/README.md +32 -0
- package/dist/{chunk-R4WOPZ76.mjs → chunk-DXSDNFP5.mjs} +53 -32
- package/dist/chunk-DXSDNFP5.mjs.map +1 -0
- package/dist/cli.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/src/services/OpenSandboxRuntimeService.ts +30 -4
- package/dist/chunk-R4WOPZ76.mjs.map +0 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @axiom-lattice/opensandbox-gateway@0.1.
|
|
2
|
+
> @axiom-lattice/opensandbox-gateway@0.1.5 build /home/runner/work/agentic/agentic/packages/opensandbox-gateway
|
|
3
3
|
> tsup src/index.ts src/cli.ts --format esm --dts --clean --sourcemap
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/cli.ts, src/index.ts
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
[34mESM[39m Build start
|
|
11
11
|
[32mESM[39m [1mdist/cli.mjs [22m[32m245.00 B[39m
|
|
12
12
|
[32mESM[39m [1mdist/index.mjs [22m[32m196.00 B[39m
|
|
13
|
-
[32mESM[39m [1mdist/chunk-
|
|
13
|
+
[32mESM[39m [1mdist/chunk-DXSDNFP5.mjs [22m[32m37.61 KB[39m
|
|
14
14
|
[32mESM[39m [1mdist/cli.mjs.map [22m[32m387.00 B[39m
|
|
15
15
|
[32mESM[39m [1mdist/index.mjs.map [22m[32m71.00 B[39m
|
|
16
|
-
[32mESM[39m [1mdist/chunk-
|
|
17
|
-
[32mESM[39m ⚡️ Build success in
|
|
16
|
+
[32mESM[39m [1mdist/chunk-DXSDNFP5.mjs.map [22m[32m78.82 KB[39m
|
|
17
|
+
[32mESM[39m ⚡️ Build success in 164ms
|
|
18
18
|
[34mDTS[39m Build start
|
|
19
|
-
[32mDTS[39m ⚡️ Build success in
|
|
19
|
+
[32mDTS[39m ⚡️ Build success in 29813ms
|
|
20
20
|
[32mDTS[39m [1mdist/cli.d.mts [22m[32m20.00 B[39m
|
|
21
21
|
[32mDTS[39m [1mdist/index.d.mts [22m[32m10.55 KB[39m
|
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -57,6 +57,10 @@ type = "docker" # "docker" or "kubernetes"
|
|
|
57
57
|
|
|
58
58
|
[runtime.docker]
|
|
59
59
|
network_mode = "host" # "host" or "bridge"
|
|
60
|
+
|
|
61
|
+
# Required for volume mounts (named volumes from Core)
|
|
62
|
+
[storage]
|
|
63
|
+
allowed_host_paths = ["/root/.opensandbox/volumes"]
|
|
60
64
|
```
|
|
61
65
|
|
|
62
66
|
### Verify
|
|
@@ -112,8 +116,27 @@ Runtime configuration is resolved in this order: CLI arguments → environment v
|
|
|
112
116
|
| `HOST` | `0.0.0.0` | Listen address |
|
|
113
117
|
| `PORT` | `4002` | Listen port |
|
|
114
118
|
| `GATEWAY_API_KEY` | — | Bearer token for authenticating to this service |
|
|
119
|
+
| `MICROSANDBOX_API_KEY` | — | Fallback alias for `GATEWAY_API_KEY` (backward compatibility) |
|
|
115
120
|
| `BODY_LIMIT` | `104857600` (100MB) | Max request body size |
|
|
116
121
|
|
|
122
|
+
### Authentication
|
|
123
|
+
|
|
124
|
+
When `GATEWAY_API_KEY` (or `MICROSANDBOX_API_KEY`) is set, all `/api/*` endpoints require a Bearer token:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Without key → 401
|
|
128
|
+
curl http://localhost:4003/api/sandboxes
|
|
129
|
+
# → {"success":false,"error":{"code":"UNAUTHORIZED","message":"Unauthorized"}}
|
|
130
|
+
|
|
131
|
+
# With key → 200
|
|
132
|
+
curl -H "Authorization: Bearer your-key" http://localhost:4003/api/sandboxes
|
|
133
|
+
# → {"success":true,"data":{...}}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The `/health` endpoint and Swagger UI (`/api-docs`) are not authenticated.
|
|
137
|
+
|
|
138
|
+
On the Core side, set `MICROSANDBOX_API_KEY` environment variable to match.
|
|
139
|
+
|
|
117
140
|
### OpenSandbox Connection
|
|
118
141
|
|
|
119
142
|
| Variable | Default | Description |
|
|
@@ -139,6 +162,15 @@ Runtime configuration is resolved in this order: CLI arguments → environment v
|
|
|
139
162
|
|----------|---------|-------------|
|
|
140
163
|
| `VOLUME_BASE_PATH` | `~/.opensandbox/volumes` | Host directory for named volume filesystem operations |
|
|
141
164
|
|
|
165
|
+
Named volumes from Core (e.g. `s<hash>` for skills, `p<hash>` for projects) are mapped to host directories under `$VOLUME_BASE_PATH/<name>/`. The OpenSandbox Server must allow this path via `[storage] allowed_host_paths` in `~/.sandbox.toml`:
|
|
166
|
+
|
|
167
|
+
```toml
|
|
168
|
+
[storage]
|
|
169
|
+
allowed_host_paths = ["/root/.opensandbox/volumes"]
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Without this, volume mounts will fail with "Host path is not under any allowed prefix".
|
|
173
|
+
|
|
142
174
|
## Startup Examples
|
|
143
175
|
|
|
144
176
|
Start with CLI flags:
|
|
@@ -37,6 +37,18 @@ function toErrorResponse(error) {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
// src/services/OpenSandboxRuntimeService.ts
|
|
40
|
+
import path from "path";
|
|
41
|
+
import os from "os";
|
|
42
|
+
var defaultVolumeBasePath = path.join(os.homedir(), ".opensandbox", "volumes");
|
|
43
|
+
function resolveVolumeBasePath() {
|
|
44
|
+
return process.env.VOLUME_BASE_PATH ?? defaultVolumeBasePath;
|
|
45
|
+
}
|
|
46
|
+
function sanitizeVolumeName(mountPath) {
|
|
47
|
+
return mountPath.replace(/^\/+|\/+$/g, "").replace(/[^a-z0-9-]/gi, "-").replace(/--+/g, "-").replace(/^-|-$/g, "") || "volume";
|
|
48
|
+
}
|
|
49
|
+
function resolveNamedVolumeHostPath(name) {
|
|
50
|
+
return path.join(resolveVolumeBasePath(), name);
|
|
51
|
+
}
|
|
40
52
|
var NAME_METADATA_KEY = "axiom-lattice/name";
|
|
41
53
|
function getEnv(key, fallback) {
|
|
42
54
|
return process.env[key] ?? fallback;
|
|
@@ -65,10 +77,10 @@ var OpenSandboxRuntimeService = class {
|
|
|
65
77
|
if (!volumes) return [];
|
|
66
78
|
return Object.entries(volumes).map(([mountPath, def]) => {
|
|
67
79
|
if (def.type === "bind" && def.source) {
|
|
68
|
-
return { name: mountPath, host: { path: def.source }, mountPath, readOnly: def.readonly };
|
|
80
|
+
return { name: sanitizeVolumeName(mountPath), host: { path: def.source }, mountPath, readOnly: def.readonly };
|
|
69
81
|
}
|
|
70
82
|
if (def.type === "named" && def.name) {
|
|
71
|
-
return { name: mountPath,
|
|
83
|
+
return { name: sanitizeVolumeName(mountPath), host: { path: resolveNamedVolumeHostPath(def.name) }, mountPath, readOnly: def.readonly };
|
|
72
84
|
}
|
|
73
85
|
if (def.type === "tmpfs") {
|
|
74
86
|
throw new HttpError(400, "INVALID_REQUEST", "tmpfs volumes are not supported by OpenSandbox");
|
|
@@ -87,6 +99,7 @@ var OpenSandboxRuntimeService = class {
|
|
|
87
99
|
try {
|
|
88
100
|
const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });
|
|
89
101
|
const result = await manager.listSandboxInfos({
|
|
102
|
+
states: ["Running", "Paused"],
|
|
90
103
|
metadata: { [NAME_METADATA_KEY]: name },
|
|
91
104
|
pageSize: 1
|
|
92
105
|
});
|
|
@@ -244,6 +257,7 @@ var OpenSandboxRuntimeService = class {
|
|
|
244
257
|
try {
|
|
245
258
|
const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });
|
|
246
259
|
const result = await manager.listSandboxInfos({
|
|
260
|
+
states: ["Running", "Paused"],
|
|
247
261
|
metadata: { [NAME_METADATA_KEY]: name },
|
|
248
262
|
pageSize: 1
|
|
249
263
|
});
|
|
@@ -254,13 +268,13 @@ var OpenSandboxRuntimeService = class {
|
|
|
254
268
|
}
|
|
255
269
|
return { name, status: "unknown" };
|
|
256
270
|
}
|
|
257
|
-
resolvePath(
|
|
258
|
-
if (
|
|
259
|
-
if (
|
|
260
|
-
return
|
|
271
|
+
resolvePath(path3) {
|
|
272
|
+
if (path3 === "~" || path3 === "~/") return "/";
|
|
273
|
+
if (path3.startsWith("~/")) return `/${path3.slice(2)}`;
|
|
274
|
+
return path3;
|
|
261
275
|
}
|
|
262
|
-
async readFile(sandboxName,
|
|
263
|
-
const resolvedPath = this.resolvePath(
|
|
276
|
+
async readFile(sandboxName, path3) {
|
|
277
|
+
const resolvedPath = this.resolvePath(path3);
|
|
264
278
|
const entry = this.getCached(sandboxName);
|
|
265
279
|
try {
|
|
266
280
|
const content = await entry.sandbox.files.readFile(resolvedPath);
|
|
@@ -269,8 +283,8 @@ var OpenSandboxRuntimeService = class {
|
|
|
269
283
|
throw this.wrapError(err, "INTERNAL_ERROR", `Failed to read file '${resolvedPath}' in sandbox '${sandboxName}'`);
|
|
270
284
|
}
|
|
271
285
|
}
|
|
272
|
-
async writeFile(sandboxName,
|
|
273
|
-
const resolvedPath = this.resolvePath(
|
|
286
|
+
async writeFile(sandboxName, path3, content) {
|
|
287
|
+
const resolvedPath = this.resolvePath(path3);
|
|
274
288
|
const entry = this.getCached(sandboxName);
|
|
275
289
|
try {
|
|
276
290
|
const parentDir = resolvedPath.split("/").slice(0, -1).join("/") || "/";
|
|
@@ -282,8 +296,8 @@ var OpenSandboxRuntimeService = class {
|
|
|
282
296
|
throw this.wrapError(err, "INTERNAL_ERROR", `Failed to write file '${resolvedPath}' in sandbox '${sandboxName}'`);
|
|
283
297
|
}
|
|
284
298
|
}
|
|
285
|
-
async listPath(sandboxName,
|
|
286
|
-
const resolvedPath = this.resolvePath(
|
|
299
|
+
async listPath(sandboxName, path3, recursive) {
|
|
300
|
+
const resolvedPath = this.resolvePath(path3);
|
|
287
301
|
const entry = this.getCached(sandboxName);
|
|
288
302
|
try {
|
|
289
303
|
const files = await entry.sandbox.files.listDirectory({
|
|
@@ -300,8 +314,8 @@ var OpenSandboxRuntimeService = class {
|
|
|
300
314
|
throw this.wrapError(err, "INTERNAL_ERROR", `Failed to list path '${resolvedPath}' in sandbox '${sandboxName}'`);
|
|
301
315
|
}
|
|
302
316
|
}
|
|
303
|
-
async findFiles(sandboxName,
|
|
304
|
-
const resolvedPath = this.resolvePath(
|
|
317
|
+
async findFiles(sandboxName, path3, pattern) {
|
|
318
|
+
const resolvedPath = this.resolvePath(path3);
|
|
305
319
|
const entry = this.getCached(sandboxName);
|
|
306
320
|
try {
|
|
307
321
|
const results = await entry.sandbox.files.search({
|
|
@@ -321,8 +335,8 @@ var OpenSandboxRuntimeService = class {
|
|
|
321
335
|
}
|
|
322
336
|
}
|
|
323
337
|
}
|
|
324
|
-
async searchInFile(sandboxName,
|
|
325
|
-
const resolvedPath = this.resolvePath(
|
|
338
|
+
async searchInFile(sandboxName, path3, query) {
|
|
339
|
+
const resolvedPath = this.resolvePath(path3);
|
|
326
340
|
const entry = this.getCached(sandboxName);
|
|
327
341
|
try {
|
|
328
342
|
const result = await entry.sandbox.commands.run(
|
|
@@ -360,8 +374,8 @@ var OpenSandboxRuntimeService = class {
|
|
|
360
374
|
throw this.wrapError(err, "INTERNAL_ERROR", `Failed to replace in file '${resolvedPath}'`);
|
|
361
375
|
}
|
|
362
376
|
}
|
|
363
|
-
async uploadFile(sandboxName,
|
|
364
|
-
const resolvedPath = this.resolvePath(
|
|
377
|
+
async uploadFile(sandboxName, path3, contentBase64) {
|
|
378
|
+
const resolvedPath = this.resolvePath(path3);
|
|
365
379
|
const entry = this.getCached(sandboxName);
|
|
366
380
|
try {
|
|
367
381
|
const data = Buffer.from(contentBase64, "base64").toString("utf-8");
|
|
@@ -371,8 +385,8 @@ var OpenSandboxRuntimeService = class {
|
|
|
371
385
|
throw this.wrapError(err, "INTERNAL_ERROR", `Failed to upload file '${resolvedPath}'`);
|
|
372
386
|
}
|
|
373
387
|
}
|
|
374
|
-
async downloadFile(sandboxName,
|
|
375
|
-
const resolvedPath = this.resolvePath(
|
|
388
|
+
async downloadFile(sandboxName, path3) {
|
|
389
|
+
const resolvedPath = this.resolvePath(path3);
|
|
376
390
|
const entry = this.getCached(sandboxName);
|
|
377
391
|
try {
|
|
378
392
|
const data = await entry.sandbox.files.readBytes(resolvedPath);
|
|
@@ -387,7 +401,7 @@ var OpenSandboxRuntimeService = class {
|
|
|
387
401
|
try {
|
|
388
402
|
const result = await entry.sandbox.commands.run(input.command, {
|
|
389
403
|
workingDirectory: input.exec_dir,
|
|
390
|
-
timeoutSeconds: input.timeout ? Math.ceil(input.timeout / 1e3) :
|
|
404
|
+
timeoutSeconds: input.timeout ? Math.ceil(input.timeout / 1e3) : 300
|
|
391
405
|
});
|
|
392
406
|
return {
|
|
393
407
|
stdout: result.logs.stdout.map((s) => s.text).join(""),
|
|
@@ -395,7 +409,13 @@ var OpenSandboxRuntimeService = class {
|
|
|
395
409
|
exitCode: result.exitCode ?? 0
|
|
396
410
|
};
|
|
397
411
|
} catch (err) {
|
|
398
|
-
|
|
412
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
413
|
+
console.error(`[execCommand] sandbox=${input.sandboxName} cmd=${input.command.slice(0, 80)} error=${message}`);
|
|
414
|
+
return {
|
|
415
|
+
stdout: "",
|
|
416
|
+
stderr: message,
|
|
417
|
+
exitCode: -1
|
|
418
|
+
};
|
|
399
419
|
}
|
|
400
420
|
}
|
|
401
421
|
async getSandbox(name) {
|
|
@@ -422,6 +442,7 @@ var OpenSandboxRuntimeService = class {
|
|
|
422
442
|
try {
|
|
423
443
|
const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });
|
|
424
444
|
const result = await manager.listSandboxInfos({
|
|
445
|
+
states: ["Running", "Paused"],
|
|
425
446
|
metadata: { [NAME_METADATA_KEY]: name },
|
|
426
447
|
pageSize: 1
|
|
427
448
|
});
|
|
@@ -741,8 +762,8 @@ function registerSandboxRoutes(app, runtimeService) {
|
|
|
741
762
|
|
|
742
763
|
// src/controllers/volume-fs.ts
|
|
743
764
|
import fs from "fs/promises";
|
|
744
|
-
import
|
|
745
|
-
import
|
|
765
|
+
import os2 from "os";
|
|
766
|
+
import path2 from "path";
|
|
746
767
|
import z4 from "zod";
|
|
747
768
|
|
|
748
769
|
// src/schemas/volume-fs.ts
|
|
@@ -767,18 +788,18 @@ var volumeFsDownloadSchema = z3.object({
|
|
|
767
788
|
|
|
768
789
|
// src/controllers/volume-fs.ts
|
|
769
790
|
function getVolumeBasePath() {
|
|
770
|
-
return process.env.VOLUME_BASE_PATH ??
|
|
791
|
+
return process.env.VOLUME_BASE_PATH ?? path2.join(os2.homedir(), ".opensandbox", "volumes");
|
|
771
792
|
}
|
|
772
793
|
function resolveVolumeHostPath(name) {
|
|
773
|
-
return
|
|
794
|
+
return path2.join(getVolumeBasePath(), name);
|
|
774
795
|
}
|
|
775
796
|
function resolveGuestPath(hostRoot, guestPath) {
|
|
776
797
|
const normalized = guestPath === "~" ? "" : guestPath.replace(/^~\//, "");
|
|
777
|
-
const resolved =
|
|
798
|
+
const resolved = path2.join(
|
|
778
799
|
hostRoot,
|
|
779
|
-
|
|
800
|
+
path2.normalize(normalized).replace(/^(\.\.(\/|\\|$))+/, "")
|
|
780
801
|
);
|
|
781
|
-
if (!resolved.startsWith(hostRoot +
|
|
802
|
+
if (!resolved.startsWith(hostRoot + path2.sep) && resolved !== hostRoot) {
|
|
782
803
|
throw new HttpError(403, "PATH_TRAVERSAL", "Path traversal detected");
|
|
783
804
|
}
|
|
784
805
|
return resolved;
|
|
@@ -807,7 +828,7 @@ function createVolumeFsController() {
|
|
|
807
828
|
const { path: guestPath, content } = volumeFsWriteSchema.parse(request.body ?? {});
|
|
808
829
|
const hostRoot = resolveVolumeHostPath(name);
|
|
809
830
|
const fullPath = resolveGuestPath(hostRoot, guestPath);
|
|
810
|
-
await fs.mkdir(
|
|
831
|
+
await fs.mkdir(path2.dirname(fullPath), { recursive: true });
|
|
811
832
|
await fs.writeFile(fullPath, content, "utf-8");
|
|
812
833
|
return reply.send(ok({ path: guestPath }));
|
|
813
834
|
} catch (err) {
|
|
@@ -863,7 +884,7 @@ function createVolumeFsController() {
|
|
|
863
884
|
const { path: guestPath, contentBase64 } = volumeFsUploadSchema.parse(request.body ?? {});
|
|
864
885
|
const hostRoot = resolveVolumeHostPath(name);
|
|
865
886
|
const fullPath = resolveGuestPath(hostRoot, guestPath);
|
|
866
|
-
await fs.mkdir(
|
|
887
|
+
await fs.mkdir(path2.dirname(fullPath), { recursive: true });
|
|
867
888
|
const data = Buffer.from(contentBase64, "base64");
|
|
868
889
|
await fs.writeFile(fullPath, data);
|
|
869
890
|
return reply.send(ok({ path: guestPath }));
|
|
@@ -1085,4 +1106,4 @@ export {
|
|
|
1085
1106
|
buildApp,
|
|
1086
1107
|
startServer
|
|
1087
1108
|
};
|
|
1088
|
-
//# sourceMappingURL=chunk-
|
|
1109
|
+
//# sourceMappingURL=chunk-DXSDNFP5.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/OpenSandboxRuntimeService.ts","../src/lib/errors.ts","../src/app.ts","../src/lib/http.ts","../src/routes/health.ts","../src/controllers/images.ts","../src/schemas/images.ts","../src/routes/images.ts","../src/schemas/sandbox.ts","../src/controllers/sandbox.ts","../src/routes/sandbox.ts","../src/controllers/volume-fs.ts","../src/schemas/volume-fs.ts","../src/routes/volume-fs.ts","../src/services/ImageService.ts","../src/swagger.ts","../src/lib/server-cli.ts","../src/server.ts"],"sourcesContent":["import { ConnectionConfig, Sandbox, type Volume } from \"@alibaba-group/opensandbox\";\nimport { SandboxManager, type SandboxFilter } from \"@alibaba-group/opensandbox\";\nimport { SandboxException } from \"@alibaba-group/opensandbox\";\nimport type { RuntimeService } from \"../types/runtime-service\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport type { SandboxLogsInput } from \"../schemas/sandbox\";\nimport type { SandboxRuntimeMetrics } from \"../types/runtime-service\";\nimport { HttpError } from \"../lib/errors\";\n\ntype CachedEntry = {\n sandbox: Sandbox;\n sandboxId: string;\n createdAt: string;\n lastUsedAt: number;\n};\n\ntype VolumeDefinition = NonNullable<EnsureSandboxInput[\"volumes\"]>[string];\n\nimport path from \"path\";\nimport os from \"os\";\n\nconst defaultVolumeBasePath = path.join(os.homedir(), \".opensandbox\", \"volumes\");\n\nfunction resolveVolumeBasePath(): string {\n return process.env.VOLUME_BASE_PATH ?? defaultVolumeBasePath;\n}\n\nfunction sanitizeVolumeName(mountPath: string): string {\n return mountPath.replace(/^\\/+|\\/+$/g, \"\").replace(/[^a-z0-9-]/gi, \"-\").replace(/--+/g, \"-\").replace(/^-|-$/g, \"\") || \"volume\";\n}\n\nfunction resolveNamedVolumeHostPath(name: string): string {\n return path.join(resolveVolumeBasePath(), name);\n}\n\nconst NAME_METADATA_KEY = \"axiom-lattice/name\";\n\nfunction getEnv(key: string, fallback: string): string {\n return process.env[key] ?? fallback;\n}\n\nfunction getEnvNumber(key: string, fallback: number): number {\n const v = process.env[key];\n return v ? Number(v) : fallback;\n}\n\nexport class OpenSandboxRuntimeService implements RuntimeService {\n private cache = new Map<string, CachedEntry>();\n private pendingCreates = new Map<string, Promise<CachedEntry>>();\n private connectionConfig: ConnectionConfig;\n private defaultImage: string;\n private defaultCpus: number;\n private defaultMemoryMib: number;\n private defaultTimeout: number;\n private idleTimeoutMs: number;\n\n constructor() {\n this.connectionConfig = new ConnectionConfig({\n domain: getEnv(\"OPEN_SANDBOX_DOMAIN\", \"localhost:8080\"),\n protocol: (getEnv(\"OPEN_SANDBOX_PROTOCOL\", \"http\") as \"http\" | \"https\"),\n apiKey: process.env[\"OPEN_SANDBOX_API_KEY\"],\n useServerProxy: getEnv(\"OPEN_SANDBOX_USE_SERVER_PROXY\", \"false\") === \"true\",\n });\n\n this.defaultImage = getEnv(\"OPEN_SANDBOX_DEFAULT_IMAGE\", \"ubuntu:22.04\");\n this.defaultCpus = getEnvNumber(\"OPEN_SANDBOX_DEFAULT_CPUS\", 1);\n this.defaultMemoryMib = getEnvNumber(\"OPEN_SANDBOX_DEFAULT_MEMORY_MIB\", 2048);\n this.defaultTimeout = getEnvNumber(\"OPEN_SANDBOX_DEFAULT_TIMEOUT\", 600);\n this.idleTimeoutMs = getEnvNumber(\"SANDBOX_IDLE_TIMEOUT_MS\", 600_000);\n }\n\n private mapVolumes(volumes?: Record<string, VolumeDefinition>): Volume[] {\n if (!volumes) return [];\n return Object.entries(volumes).map(([mountPath, def]) => {\n if (def.type === \"bind\" && def.source) {\n return { name: sanitizeVolumeName(mountPath), host: { path: def.source }, mountPath, readOnly: def.readonly };\n }\n if (def.type === \"named\" && def.name) {\n return { name: sanitizeVolumeName(mountPath), host: { path: resolveNamedVolumeHostPath(def.name) }, mountPath, readOnly: def.readonly };\n }\n if (def.type === \"tmpfs\") {\n throw new HttpError(400, \"INVALID_REQUEST\", \"tmpfs volumes are not supported by OpenSandbox\");\n }\n throw new HttpError(400, \"INVALID_REQUEST\", `Unsupported volume type at ${mountPath}`);\n });\n }\n\n private getCached(name: string): CachedEntry {\n const entry = this.cache.get(name);\n if (!entry) {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n return entry;\n }\n\n private async findByNameViaMetadata(name: string): Promise<CachedEntry | null> {\n try {\n const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });\n const result = await manager.listSandboxInfos({\n states: [\"Running\", \"Paused\"],\n metadata: { [NAME_METADATA_KEY]: name },\n pageSize: 1,\n });\n\n if (result.items.length === 0) {\n return null;\n }\n\n const info = result.items[0];\n const sandbox = await Sandbox.resume({\n sandboxId: info.id,\n connectionConfig: this.connectionConfig,\n readyTimeoutSeconds: 1800,\n });\n\n const entry: CachedEntry = {\n sandbox,\n sandboxId: info.id,\n createdAt: info.createdAt ? new Date(info.createdAt).toISOString() : new Date().toISOString(),\n lastUsedAt: Date.now(),\n };\n this.cache.set(name, entry);\n return entry;\n } catch (err) {\n if (err instanceof SandboxException && err.error.code === \"NOT_FOUND\") {\n return null;\n }\n console.warn(`[OpenSandboxRuntimeService] metadata lookup for name=${name} failed:`, err);\n return null;\n }\n }\n\n async ensureSandbox(\n name: string,\n input: EnsureSandboxInput\n ): Promise<{ name: string; status: string }> {\n // 1. Check cache\n const cached = this.cache.get(name);\n if (cached) {\n try {\n const info = await cached.sandbox.getInfo();\n if (info.status.state === \"Running\") {\n cached.lastUsedAt = Date.now();\n await cached.sandbox.renew(this.defaultTimeout).catch(() => {\n });\n return { name, status: \"running\" };\n }\n this.cache.delete(name);\n } catch {\n this.cache.delete(name);\n }\n }\n\n // 2. Dedup concurrent creates for same name\n const inflight = this.pendingCreates.get(name);\n if (inflight) {\n await inflight;\n return { name, status: \"running\" };\n }\n\n // 3. Try metadata recovery (crash recovery)\n const recovered = await this.findByNameViaMetadata(name);\n if (recovered) {\n return { name, status: \"running\" };\n }\n\n // 4. Create new sandbox\n const creation = this.doCreateSandbox(name, input);\n this.pendingCreates.set(name, creation);\n try {\n await creation;\n return { name, status: \"running\" };\n } finally {\n this.pendingCreates.delete(name);\n }\n }\n\n private async doCreateSandbox(\n name: string,\n input: EnsureSandboxInput\n ): Promise<CachedEntry> {\n const sandbox = await Sandbox.create({\n connectionConfig: this.connectionConfig,\n image: input.image ?? this.defaultImage,\n timeoutSeconds: this.defaultTimeout,\n readyTimeoutSeconds: 1800,\n resource: {\n cpu: String(input.cpus ?? this.defaultCpus),\n memory: `${input.memoryMib ?? this.defaultMemoryMib}Mi`,\n },\n env: input.env ?? {},\n metadata: { [NAME_METADATA_KEY]: name },\n volumes: this.mapVolumes(input.volumes),\n entrypoint: [\"tail\", \"-f\", \"/dev/null\"],\n });\n\n const info = await sandbox.getInfo();\n\n const entry: CachedEntry = {\n sandbox,\n sandboxId: info.id,\n createdAt: info.createdAt ? new Date(info.createdAt).toISOString() : new Date().toISOString(),\n lastUsedAt: Date.now(),\n };\n this.cache.set(name, entry);\n return entry;\n }\n\n private wrapError(err: unknown, code: string, message: string): never {\n if (err instanceof HttpError) throw err;\n if (err instanceof SandboxException) {\n throw new HttpError(\n err.error.code === \"NOT_FOUND\" ? 404\n : err.error.code === \"FORBIDDEN\" ? 403\n : err.error.code === \"CONFLICT\" ? 409\n : err.error.code === \"INVALID_REQUEST\" ? 400\n : 500,\n err.error.code,\n err.error.message ?? message\n );\n }\n throw new HttpError(500, code, message);\n }\n\n async startSandbox(name: string): Promise<{ name: string; status: string }> {\n const entry = this.getCached(name);\n try {\n const resumed = await Sandbox.resume({\n sandboxId: entry.sandboxId,\n connectionConfig: this.connectionConfig,\n readyTimeoutSeconds: 1800,\n });\n // Update cache with new Sandbox instance (sandboxId may change on K8s)\n const info = await resumed.getInfo();\n entry.sandbox = resumed;\n entry.sandboxId = info.id;\n entry.lastUsedAt = Date.now();\n return { name, status: \"running\" };\n } catch (err) {\n throw this.wrapError(err, \"SANDBOX_NOT_FOUND\", `Failed to start sandbox '${name}'`);\n }\n }\n\n async stopSandbox(name: string): Promise<{ name: string; status: string }> {\n const entry = this.getCached(name);\n try {\n await entry.sandbox.pause();\n return { name, status: \"stopped\" };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to stop sandbox '${name}'`);\n }\n }\n\n async killSandbox(name: string): Promise<{ name: string; status: string }> {\n const entry = this.cache.get(name);\n if (!entry) {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n try {\n await entry.sandbox.kill();\n } catch {\n // kill failure is non-fatal\n }\n try {\n await entry.sandbox.close();\n } catch {\n // close failure is non-fatal\n }\n this.cache.delete(name);\n return { name, status: \"unknown\" };\n }\n\n async deleteSandbox(name: string): Promise<{ name: string; status: string }> {\n return this.killSandbox(name);\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n const entry = this.cache.get(name);\n if (entry) {\n try {\n const info = await entry.sandbox.getInfo();\n const status = info.status.state.toLowerCase();\n return { name, status };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n // Try server-side lookup\n try {\n const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });\n const result = await manager.listSandboxInfos({\n states: [\"Running\", \"Paused\"],\n metadata: { [NAME_METADATA_KEY]: name },\n pageSize: 1,\n });\n if (result.items.length > 0) {\n return { name, status: result.items[0].status.state.toLowerCase() };\n }\n } catch {\n // ignore\n }\n return { name, status: \"unknown\" };\n }\n\n private resolvePath(path: string): string {\n if (path === \"~\" || path === \"~/\") return \"/\";\n if (path.startsWith(\"~/\")) return `/${path.slice(2)}`;\n return path;\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n const content = await entry.sandbox.files.readFile(resolvedPath);\n return { path: resolvedPath, content };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to read file '${resolvedPath}' in sandbox '${sandboxName}'`);\n }\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n // Create parent directories if needed\n const parentDir = resolvedPath.split(\"/\").slice(0, -1).join(\"/\") || \"/\";\n await entry.sandbox.files.createDirectories([{ path: parentDir }]).catch(() => {\n // parent may already exist\n });\n await entry.sandbox.files.writeFiles([{ path: resolvedPath, data: content }]);\n return { path: resolvedPath };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to write file '${resolvedPath}' in sandbox '${sandboxName}'`);\n }\n }\n\n async listPath(\n sandboxName: string,\n path: string,\n recursive?: boolean\n ): Promise<{ entries: Array<{ path: string; type: string }> }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n const files = await entry.sandbox.files.listDirectory({\n path: resolvedPath,\n depth: recursive ? undefined : 1,\n });\n return {\n entries: files.map((f) => ({\n path: f.path,\n type: f.isDir === true ? \"directory\" : f.isSymlink === true ? \"symlink\" : \"file\",\n })),\n };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to list path '${resolvedPath}' in sandbox '${sandboxName}'`);\n }\n }\n\n async findFiles(sandboxName: string, path: string, pattern: string): Promise<{ files: string[] }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n const results = await entry.sandbox.files.search({\n path: resolvedPath,\n pattern: pattern || \"*\",\n });\n return { files: results.map((r) => r.path) };\n } catch (err) {\n // Fallback to shell find command\n try {\n const result = await entry.sandbox.commands.run(\n `find ${resolvedPath} -name '${pattern}' -type f`,\n { timeoutSeconds: 30 }\n );\n return { files: result.logs.stdout.map((s) => s.text).join(\"\").split(\"\\n\").filter(Boolean) };\n } catch {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to find files in '${resolvedPath}'`);\n }\n }\n }\n\n async searchInFile(\n sandboxName: string,\n path: string,\n query: string\n ): Promise<{ matches: Array<{ line: number; content: string }> }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n const result = await entry.sandbox.commands.run(\n `grep -n -E '${query.replace(/'/g, \"'\\\\''\")}' ${resolvedPath}`,\n { timeoutSeconds: 30 }\n );\n const stdout = result.logs.stdout.map((s) => s.text).join(\"\");\n if (!stdout.trim()) return { matches: [] };\n return {\n matches: stdout.split(\"\\n\").filter(Boolean).map((line) => {\n const idx = line.indexOf(\":\");\n return { line: Number(line.slice(0, idx)), content: line.slice(idx + 1) };\n }),\n };\n } catch (err: unknown) {\n // grep returns exit code 1 for no matches — may throw or not\n if (err instanceof SandboxException) return { matches: [] };\n if (typeof err === \"object\" && err !== null && \"code\" in err && (err as { code: number }).code === 1) {\n return { matches: [] };\n }\n return { matches: [] };\n }\n }\n\n async replaceInFile(\n sandboxName: string,\n input: { path: string; search: string; replace: string }\n ): Promise<{ replaced: number }> {\n const resolvedPath = this.resolvePath(input.path);\n const entry = this.getCached(sandboxName);\n try {\n const original = await entry.sandbox.files.readFile(resolvedPath);\n if (!input.search) return { replaced: 0 };\n const occurrences = original.split(input.search).length - 1;\n if (occurrences === 0) return { replaced: 0 };\n const updated = original.split(input.search).join(input.replace);\n await entry.sandbox.files.writeFiles([{ path: resolvedPath, data: updated }]);\n return { replaced: occurrences };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to replace in file '${resolvedPath}'`);\n }\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n const data = Buffer.from(contentBase64, \"base64\").toString(\"utf-8\");\n await entry.sandbox.files.writeFiles([{ path: resolvedPath, data }]);\n return { path: resolvedPath };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to upload file '${resolvedPath}'`);\n }\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n const data = await entry.sandbox.files.readBytes(resolvedPath);\n const b64 = Buffer.from(data).toString(\"base64\");\n return { path: resolvedPath, contentBase64: b64 };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to download file '${resolvedPath}'`);\n }\n }\n\n async execCommand(input: ShellExecInput): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const entry = this.getCached(input.sandboxName);\n try {\n const result = await entry.sandbox.commands.run(input.command, {\n workingDirectory: input.exec_dir,\n timeoutSeconds: input.timeout ? Math.ceil(input.timeout / 1000) : 300,\n });\n return {\n stdout: result.logs.stdout.map((s) => s.text).join(\"\"),\n stderr: result.logs.stderr.map((s) => s.text).join(\"\"),\n exitCode: result.exitCode ?? 0,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`[execCommand] sandbox=${input.sandboxName} cmd=${input.command.slice(0, 80)} error=${message}`);\n return {\n stdout: \"\",\n stderr: message,\n exitCode: -1,\n };\n }\n }\n\n async getSandbox(\n name: string\n ): Promise<{\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n env: unknown;\n volumes: Record<string, unknown>;\n metrics?: SandboxRuntimeMetrics;\n createdAt: string;\n updatedAt: string;\n } | undefined> {\n // Try cache first\n const entry = this.cache.get(name);\n if (entry) {\n try {\n const info = await entry.sandbox.getInfo();\n return {\n name,\n status: info.status.state.toLowerCase(),\n image: info.image?.uri ?? \"unknown\",\n cpus: undefined,\n memoryMib: undefined,\n env: {},\n volumes: {},\n metrics: undefined,\n createdAt: info.createdAt ? new Date(info.createdAt).toISOString() : entry.createdAt,\n updatedAt: info.createdAt ? new Date(info.createdAt).toISOString() : entry.createdAt,\n };\n } catch {\n this.cache.delete(name);\n }\n }\n\n // Try server-side lookup via metadata\n try {\n const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });\n const result = await manager.listSandboxInfos({\n states: [\"Running\", \"Paused\"],\n metadata: { [NAME_METADATA_KEY]: name },\n pageSize: 1,\n });\n if (result.items.length > 0) {\n const info = result.items[0];\n return {\n name,\n status: info.status.state.toLowerCase(),\n image: info.image?.uri ?? \"unknown\",\n cpus: undefined,\n memoryMib: undefined,\n env: {},\n volumes: {},\n metrics: undefined,\n createdAt: info.createdAt ? new Date(info.createdAt).toISOString() : \"\",\n updatedAt: info.createdAt ? new Date(info.createdAt).toISOString() : \"\",\n };\n }\n } catch {\n // ignore\n }\n\n return undefined;\n }\n\n async listSandboxes(_query: ListSandboxesQuery): Promise<{\n items: Array<{\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n }>;\n total: number;\n }> {\n try {\n const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });\n const filter: SandboxFilter = {};\n if (_query.status) filter.states = [_query.status];\n const result = await manager.listSandboxInfos(filter);\n\n const items = result.items\n .filter((info) => {\n if (_query.search) {\n const haystack = [\n info.id,\n info.metadata?.[NAME_METADATA_KEY],\n info.image?.uri,\n ].filter(Boolean).join(\" \").toLowerCase();\n return haystack.includes(_query.search.toLowerCase());\n }\n return true;\n })\n .map((info) => ({\n name: info.metadata?.[NAME_METADATA_KEY] ?? info.id,\n status: info.status.state.toLowerCase(),\n image: info.image?.uri ?? \"unknown\",\n cpus: undefined,\n memoryMib: undefined,\n envCount: 0,\n volumeCount: 0,\n createdAt: info.createdAt ? new Date(info.createdAt).toISOString() : \"\",\n updatedAt: info.createdAt ? new Date(info.createdAt).toISOString() : \"\",\n }));\n\n return { items, total: items.length };\n } catch {\n return { items: [], total: 0 };\n }\n }\n\n async getSandboxLogs(\n _name: string,\n _opts: SandboxLogsInput\n ): Promise<{\n entries: Array<{\n timestamp: string;\n source: string;\n sessionId: number | null;\n text: string;\n }>;\n }> {\n return { entries: [] };\n }\n}\n","export class HttpError extends Error {\n constructor(\n public statusCode: number,\n public code: string,\n message: string\n ) {\n super(message);\n }\n}\n\nexport function toErrorResponse(error: unknown): {\n statusCode: number;\n body: {\n success: false;\n error: {\n code: string;\n message: string;\n };\n };\n} {\n if (error instanceof HttpError) {\n return {\n statusCode: error.statusCode,\n body: {\n success: false,\n error: {\n code: error.code,\n message: error.message,\n },\n },\n };\n }\n\n return {\n statusCode: 500,\n body: {\n success: false,\n error: {\n code: \"INTERNAL_ERROR\",\n message: error instanceof Error ? error.message : String(error),\n },\n },\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport cors from \"@fastify/cors\";\nimport multipart from \"@fastify/multipart\";\nimport sensible from \"@fastify/sensible\";\nimport fastify from \"fastify\";\nimport { toErrorResponse } from \"./lib/errors\";\nimport { registerHealthRoutes } from \"./routes/health\";\nimport { registerImageRoutes } from \"./routes/images\";\nimport { registerSandboxRoutes } from \"./routes/sandbox\";\nimport { registerVolumeFsRoutes } from \"./routes/volume-fs\";\nimport { ImageService } from \"./services/ImageService\";\nimport { OpenSandboxRuntimeService } from \"./services/OpenSandboxRuntimeService\";\nimport { configureSwagger } from \"./swagger\";\n\nexport async function buildApp({\n apiKey,\n}: {\n apiKey?: string;\n} = {}): Promise<FastifyInstance> {\n const runtimeService = new OpenSandboxRuntimeService();\n const imageService = new ImageService();\n\n const app = fastify({\n logger: false,\n bodyLimit: Number(process.env[\"BODY_LIMIT\"]) || 100 * 1024 * 1024,\n });\n\n await app.register(cors, {\n delegator: (request, callback) => {\n callback(null, {\n origin: true,\n methods: request.headers[\"access-control-request-method\"] ?? \"*\",\n allowedHeaders: request.headers[\"access-control-request-headers\"],\n });\n },\n });\n await app.register(sensible);\n await app.register(multipart);\n\n if (apiKey) {\n app.addHook(\"onRequest\", async (request, reply) => {\n if (request.method === \"OPTIONS\" || !request.url.startsWith(\"/api/\")) {\n return;\n }\n if (request.headers.authorization !== `Bearer ${apiKey}`) {\n await reply.code(401).send({\n success: false,\n error: { code: \"UNAUTHORIZED\", message: \"Unauthorized\" },\n });\n }\n });\n }\n\n registerHealthRoutes(app);\n registerSandboxRoutes(app, runtimeService);\n registerImageRoutes(app, imageService);\n registerVolumeFsRoutes(app);\n\n app.setErrorHandler((error, _request, reply) => {\n const { statusCode, body } = toErrorResponse(error);\n reply.status(statusCode).send(body);\n });\n\n await configureSwagger(app);\n\n return app;\n}\n","export type SuccessResponse<T> = {\n success: true;\n data: T;\n};\n\nexport function ok<T>(data: T): SuccessResponse<T> {\n return {\n success: true,\n data,\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { ok } from \"../lib/http\";\n\nexport function registerHealthRoutes(app: FastifyInstance): void {\n app.get(\"/health\", async () => ok({ status: \"ok\" }));\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport { ZodError } from \"zod\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport { ImageService } from \"../services/ImageService\";\nimport { imageRefQuerySchema, pullImageSchema } from \"../schemas/images\";\n\nfunction parseOrThrow<T>(parse: () => T): T {\n try {\n return parse();\n } catch (error) {\n if (error instanceof ZodError) {\n throw new HttpError(400, \"INVALID_REQUEST\", error.issues[0]?.message ?? \"Invalid request\");\n }\n\n throw error;\n }\n}\n\nexport function createImageController(imageService: ImageService) {\n return {\n listImages: async (_request: FastifyRequest, reply: FastifyReply) => {\n return reply.send(ok(await imageService.listImages()));\n },\n pullImage: async (request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply) => {\n const body = parseOrThrow(() => pullImageSchema.parse(request.body ?? {}));\n return reply.send(ok(await imageService.pullImage(body)));\n },\n getImage: async (request: FastifyRequest<{ Querystring: unknown }>, reply: FastifyReply) => {\n const query = parseOrThrow(() => imageRefQuerySchema.parse(request.query ?? {}));\n return reply.send(ok(await imageService.getImage(query.ref)));\n },\n deleteImage: async (request: FastifyRequest<{ Querystring: unknown }>, reply: FastifyReply) => {\n const query = parseOrThrow(() => imageRefQuerySchema.parse(request.query ?? {}));\n return reply.send(ok(await imageService.deleteImage(query.ref)));\n },\n };\n}\n","import z from \"zod\";\n\nexport const imageRefQuerySchema = z.object({\n ref: z.string().min(1),\n});\n\nexport const pullImageSchema = z.object({\n ref: z.string().min(1),\n});\n\nexport type ImageRefQuery = z.infer<typeof imageRefQuerySchema>;\nexport type PullImageInput = z.infer<typeof pullImageSchema>;\n","import type { FastifyInstance } from \"fastify\";\nimport { createImageController } from \"../controllers/images\";\nimport { ImageService } from \"../services/ImageService\";\n\nexport function registerImageRoutes(app: FastifyInstance, imageService: ImageService): void {\n const controller = createImageController(imageService);\n\n app.get(\"/api/images\", controller.listImages);\n app.post(\"/api/images/pull\", controller.pullImage);\n app.get(\"/api/images/detail\", controller.getImage);\n app.delete(\"/api/images/detail\", controller.deleteImage);\n}\n","import z from \"zod\";\n\nconst bindMountSchema = z.object({\n type: z.literal(\"bind\"),\n source: z.string().min(1),\n readonly: z.boolean().optional(),\n});\n\nconst namedMountSchema = z.object({\n type: z.literal(\"named\"),\n name: z.string().min(1),\n readonly: z.boolean().optional(),\n});\n\nconst tmpfsMountSchema = z.object({\n type: z.literal(\"tmpfs\"),\n sizeMib: z.number().int().positive().optional(),\n});\n\nexport const volumeSchema = z.union([\n bindMountSchema,\n namedMountSchema,\n tmpfsMountSchema,\n]);\n\nexport const ensureSandboxSchema = z.object({\n image: z.string().optional(),\n cpus: z.number().int().positive().optional(),\n memoryMib: z.number().int().positive().optional(),\n env: z.record(z.string()).optional(),\n volumes: z.record(volumeSchema).optional(),\n});\n\nexport const sandboxNameParamsSchema = z.object({\n name: z.string().min(1),\n});\n\nexport const listSandboxesQuerySchema = z.object({\n status: z.enum([\"running\", \"stopped\", \"crashed\", \"unknown\"]).optional(),\n image: z.string().min(1).optional(),\n search: z.string().min(1).optional(),\n});\n\nconst sandboxAndPathSchema = z.object({\n sandboxName: z.string().min(1),\n path: z.string().min(1),\n});\n\nexport const readFileSchema = sandboxAndPathSchema;\n\nexport const writeFileSchema = sandboxAndPathSchema.extend({\n content: z.string(),\n});\n\nexport const listPathSchema = sandboxAndPathSchema.extend({\n recursive: z.boolean().optional(),\n});\n\nexport const findFilesSchema = sandboxAndPathSchema.extend({\n pattern: z.string().min(1),\n});\n\nexport const searchInFileSchema = sandboxAndPathSchema.extend({\n query: z.string().min(1),\n});\n\nexport const replaceInFileSchema = sandboxAndPathSchema.extend({\n search: z.string(),\n replace: z.string(),\n});\n\nexport const uploadFileSchema = sandboxAndPathSchema.and(\n z.union([\n z.object({ contentBase64: z.string() }),\n z.object({ content: z.string().transform((content) => Buffer.from(content).toString(\"base64\")) }),\n ])\n);\n\nexport const downloadFileSchema = sandboxAndPathSchema;\n\nexport const shellExecSchema = z.object({\n sandboxName: z.string().min(1),\n command: z.string().min(1),\n exec_dir: z.string().optional(),\n timeout: z.number().int().positive().optional(),\n});\n\nexport const sandboxLogsSchema = z.object({\n tail: z.number().int().positive().optional(),\n since: z.string().optional(),\n until: z.string().optional(),\n sources: z.array(z.string()).optional(),\n});\n\nexport type EnsureSandboxInput = z.infer<typeof ensureSandboxSchema>;\nexport type ListSandboxesQuery = z.infer<typeof listSandboxesQuerySchema>;\nexport type ShellExecInput = z.infer<typeof shellExecSchema>;\nexport type SandboxLogsInput = z.infer<typeof sandboxLogsSchema>;\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport {\n downloadFileSchema,\n ensureSandboxSchema,\n findFilesSchema,\n listSandboxesQuerySchema,\n listPathSchema,\n readFileSchema,\n replaceInFileSchema,\n sandboxLogsSchema,\n sandboxNameParamsSchema,\n searchInFileSchema,\n shellExecSchema,\n uploadFileSchema,\n writeFileSchema,\n} from \"../schemas/sandbox\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport type { RuntimeService } from \"../types/runtime-service\";\n\nexport function createSandboxController(runtimeService: RuntimeService): {\n ensureSandbox(\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n startSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n stopSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n killSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n deleteSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n listSandboxes(\n request: FastifyRequest<{ Querystring: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getStatus(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getSandboxLogs(\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n readFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n writeFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n listPath(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n findFiles(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n searchInFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n replaceInFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n uploadFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n downloadFile(\n request: FastifyRequest<{ Querystring: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n execCommand(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n} {\n return {\n ensureSandbox: async (\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ) => {\n const body = ensureSandboxSchema.parse(request.body ?? {});\n const result = await runtimeService.ensureSandbox(request.params.name, body);\n return reply.send(ok(result));\n },\n\n startSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.startSandbox(request.params.name)));\n },\n\n stopSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.stopSandbox(request.params.name)));\n },\n\n killSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.killSandbox(request.params.name)));\n },\n\n deleteSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.deleteSandbox(request.params.name)));\n },\n\n listSandboxes: async (request, reply) => {\n const query = listSandboxesQuerySchema.parse(request.query ?? {});\n return reply.send(ok(await runtimeService.listSandboxes(query)));\n },\n\n getSandbox: async (request, reply) => {\n const params = sandboxNameParamsSchema.parse(request.params ?? {});\n const sandbox = await runtimeService.getSandbox(params.name);\n\n if (!sandbox) {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${params.name}' not found`);\n }\n\n return reply.send(ok(sandbox));\n },\n\n getStatus: async (request, reply) => {\n return reply.send(ok(await runtimeService.getStatus(request.params.name)));\n },\n\n getSandboxLogs: async (request, reply) => {\n const body = sandboxLogsSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.getSandboxLogs(request.params.name, body)));\n },\n\n readFile: async (request, reply) => {\n const body = readFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.readFile(body.sandboxName, body.path)));\n },\n\n writeFile: async (request, reply) => {\n const body = writeFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.writeFile(body.sandboxName, body.path, body.content)));\n },\n\n listPath: async (request, reply) => {\n const body = listPathSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.listPath(body.sandboxName, body.path, body.recursive)));\n },\n\n findFiles: async (request, reply) => {\n const body = findFilesSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.findFiles(body.sandboxName, body.path, body.pattern)));\n },\n\n searchInFile: async (request, reply) => {\n const body = searchInFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.searchInFile(body.sandboxName, body.path, body.query)));\n },\n\n replaceInFile: async (request, reply) => {\n const body = replaceInFileSchema.parse(request.body ?? {});\n return reply.send(\n ok(\n await runtimeService.replaceInFile(body.sandboxName, {\n path: body.path,\n search: body.search,\n replace: body.replace,\n })\n )\n );\n },\n\n uploadFile: async (request, reply) => {\n const body = uploadFileSchema.parse(request.body ?? {});\n const contentBase64 = \"contentBase64\" in body ? body.contentBase64 : Buffer.from(body.content).toString(\"base64\");\n return reply.send(ok(await runtimeService.uploadFile(body.sandboxName, body.path, contentBase64)));\n },\n\n downloadFile: async (request, reply) => {\n const query = downloadFileSchema.parse(request.query ?? {});\n return reply.send(ok(await runtimeService.downloadFile(query.sandboxName, query.path)));\n },\n\n execCommand: async (request, reply) => {\n const body = shellExecSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.execCommand(body)));\n },\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { createSandboxController } from \"../controllers/sandbox\";\nimport type { RuntimeService } from \"../types/runtime-service\";\n\nexport function registerSandboxRoutes(\n app: FastifyInstance,\n runtimeService: RuntimeService\n): void {\n const controller = createSandboxController(runtimeService);\n\n app.get(\"/api/sandboxes\", controller.listSandboxes);\n app.get(\"/api/sandboxes/:name\", controller.getSandbox);\n app.put(\"/api/sandboxes/:name\", controller.ensureSandbox);\n app.post(\"/api/sandboxes/:name/start\", controller.startSandbox);\n app.post(\"/api/sandboxes/:name/stop\", controller.stopSandbox);\n app.post(\"/api/sandboxes/:name/kill\", controller.killSandbox);\n app.delete(\"/api/sandboxes/:name\", controller.deleteSandbox);\n app.get(\"/api/sandboxes/:name/status\", controller.getStatus);\n app.post(\"/api/sandboxes/:name/logs\", controller.getSandboxLogs);\n\n app.post(\"/api/files/read\", controller.readFile);\n app.post(\"/api/files/write\", controller.writeFile);\n app.post(\"/api/files/list\", controller.listPath);\n app.post(\"/api/files/find\", controller.findFiles);\n app.post(\"/api/files/search\", controller.searchInFile);\n app.post(\"/api/files/replace\", controller.replaceInFile);\n app.post(\"/api/files/upload\", controller.uploadFile);\n app.get(\"/api/files/download\", controller.downloadFile);\n\n app.post(\"/api/shell/exec\", controller.execCommand);\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport fs from \"fs/promises\";\nimport os from \"os\";\nimport path from \"path\";\nimport z from \"zod\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport {\n volumeFsReadSchema,\n volumeFsWriteSchema,\n volumeFsListSchema,\n volumeFsUploadSchema,\n volumeFsDownloadSchema,\n} from \"../schemas/volume-fs\";\n\ninterface VolumeFsParams {\n name: string;\n}\n\nfunction getVolumeBasePath(): string {\n return process.env.VOLUME_BASE_PATH ?? path.join(os.homedir(), \".opensandbox\", \"volumes\");\n}\n\nfunction resolveVolumeHostPath(name: string): string {\n return path.join(getVolumeBasePath(), name);\n}\n\nfunction resolveGuestPath(hostRoot: string, guestPath: string): string {\n const normalized = guestPath === \"~\" ? \"\" : guestPath.replace(/^~\\//, \"\");\n const resolved = path.join(\n hostRoot,\n path.normalize(normalized).replace(/^(\\.\\.(\\/|\\\\|$))+/, \"\")\n );\n if (!resolved.startsWith(hostRoot + path.sep) && resolved !== hostRoot) {\n throw new HttpError(403, \"PATH_TRAVERSAL\", \"Path traversal detected\");\n }\n return resolved;\n}\n\nexport function createVolumeFsController(): {\n readFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n writeFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string; content: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n listPath(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n downloadFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Querystring: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n uploadFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string; contentBase64: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n} {\n return {\n readFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsReadSchema.parse(request.body ?? {});\n const hostRoot = resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const content = await fs.readFile(fullPath, \"utf-8\");\n return reply.send(ok({ path: guestPath, content }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_READ_ERROR\", `Failed to read from volume '${name}': ${String(err)}`);\n }\n },\n\n writeFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath, content } = volumeFsWriteSchema.parse(request.body ?? {});\n const hostRoot = resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, content, \"utf-8\");\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_WRITE_ERROR\", `Failed to write to volume '${name}': ${String(err)}`);\n }\n },\n\n listPath: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsListSchema.parse(request.body ?? {});\n const hostRoot = resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const dirents = await fs.readdir(fullPath, { withFileTypes: true });\n const entries = dirents.map((d) => ({\n path: guestPath ? `${guestPath}/${d.name}` : d.name,\n kind: d.isDirectory() ? \"directory\" : d.isSymbolicLink() ? \"symlink\" : \"file\",\n size: 0,\n mode: 0,\n }));\n return reply.send(ok({ entries }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_LIST_ERROR\", `Failed to list volume '${name}': ${String(err)}`);\n }\n },\n\n downloadFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsDownloadSchema.parse(request.query ?? {});\n const hostRoot = resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const buf = await fs.readFile(fullPath);\n const contentBase64 = buf.toString(\"base64\");\n return reply.send(ok({ path: guestPath, contentBase64 }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_DOWNLOAD_ERROR\", `Failed to download from volume '${name}': ${String(err)}`);\n }\n },\n\n uploadFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath, contentBase64 } = volumeFsUploadSchema.parse(request.body ?? {});\n const hostRoot = resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n const data = Buffer.from(contentBase64, \"base64\");\n await fs.writeFile(fullPath, data);\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_UPLOAD_ERROR\", `Failed to upload to volume '${name}': ${String(err)}`);\n }\n },\n };\n}\n","import z from \"zod\";\n\nexport const volumeFsReadSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsWriteSchema = z.object({\n path: z.string(),\n content: z.string(),\n});\n\nexport const volumeFsListSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsUploadSchema = z.object({\n path: z.string(),\n contentBase64: z.string().min(1),\n});\n\nexport const volumeFsDownloadSchema = z.object({\n path: z.string(),\n});\n","import type { FastifyInstance } from \"fastify\";\nimport { createVolumeFsController } from \"../controllers/volume-fs\";\n\nexport function registerVolumeFsRoutes(app: FastifyInstance): void {\n const controller = createVolumeFsController();\n\n app.post(\"/api/volumes/:name/fs/read\", controller.readFile);\n app.post(\"/api/volumes/:name/fs/write\", controller.writeFile);\n app.post(\"/api/volumes/:name/fs/list\", controller.listPath);\n app.get(\"/api/volumes/:name/fs/download\", controller.downloadFile);\n app.post(\"/api/volumes/:name/fs/upload\", controller.uploadFile);\n}\n","import type { PullImageInput } from \"../schemas/images\";\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\nexport class ImageService {\n async listImages(): Promise<{ items: ImageRecord[]; total: number }> {\n return { items: [], total: 0 };\n }\n\n async pullImage(_input: PullImageInput): Promise<ImageRecord> {\n throw new Error(\"Image pull not supported in OpenSandbox gateway\");\n }\n\n async getImage(ref: string): Promise<ImageRecord> {\n return {\n ref,\n sourceType: \"oci\",\n cached: false,\n };\n }\n\n async deleteImage(ref: string): Promise<{ ref: string }> {\n return { ref };\n }\n}\n","import type { FastifyInstance } from \"fastify\";\nimport swagger from \"@fastify/swagger\";\nimport swaggerUi from \"@fastify/swagger-ui\";\n\nconst swaggerConfig = {\n openapi: {\n openapi: \"3.0.0\",\n info: {\n title: \"OpenSandbox Gateway API\",\n description: \"Sandbox lifecycle management backed by OpenSandbox\",\n version: \"1.0.0\",\n },\n servers: [{ url: \"http://localhost:4002\", description: \"Local development\" }],\n components: {\n securitySchemes: {\n bearerAuth: { type: \"http\" as const, scheme: \"bearer\" as const, bearerFormat: \"API Key\" },\n },\n },\n tags: [\n { name: \"Sandboxes\", description: \"Sandbox lifecycle\" },\n { name: \"Files\", description: \"File operations inside sandboxes\" },\n { name: \"Shell\", description: \"Execute commands inside sandboxes\" },\n { name: \"Images\", description: \"Image management (stub)\" },\n { name: \"Volumes\", description: \"Named volume filesystem operations\" },\n { name: \"Health\", description: \"Service health check\" },\n ],\n },\n};\n\nconst swaggerUiConfig = {\n routePrefix: \"/api-docs\",\n uiConfig: { docExpansion: \"list\" as const, deepLinking: true },\n staticCSP: true,\n transformStaticCSP: (header: string) => header,\n};\n\nexport async function configureSwagger(app: FastifyInstance) {\n await app.register(swagger, swaggerConfig);\n await app.register(swaggerUi, swaggerUiConfig);\n}\n","export interface ParsedServerArgs {\n host?: string;\n port?: number;\n}\n\nexport interface ResolvedServerConfig {\n host: string;\n port: number;\n apiKey?: string;\n}\n\nfunction parsePort(raw: string, source: string): number {\n const value = Number(raw);\n if (!Number.isInteger(value) || value <= 0 || value > 65535) {\n throw new Error(`Invalid value for ${source}: ${raw}`);\n }\n return value;\n}\n\nfunction isMissingOptionValue(raw: string | undefined): raw is undefined {\n return !raw || raw.startsWith(\"--\");\n}\n\nexport function parseServerArgs(argv: string[]): ParsedServerArgs {\n const parsed: ParsedServerArgs = {};\n\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index];\n\n if (token === \"--port\") {\n const raw = argv[index + 1];\n if (isMissingOptionValue(raw)) {\n throw new Error(\"Missing value for --port\");\n }\n parsed.port = parsePort(raw, \"--port\");\n index += 1;\n continue;\n }\n\n if (token === \"--host\") {\n const raw = argv[index + 1];\n if (isMissingOptionValue(raw)) {\n throw new Error(\"Missing value for --host\");\n }\n parsed.host = raw;\n index += 1;\n }\n }\n\n return parsed;\n}\n\nexport function resolveServerConfig({\n args,\n env,\n}: {\n args: ParsedServerArgs;\n env: NodeJS.ProcessEnv;\n}): ResolvedServerConfig {\n return {\n host: args.host ?? env.HOST ?? \"0.0.0.0\",\n port: args.port ?? (env.PORT ? parsePort(env.PORT, \"PORT\") : 4002),\n apiKey: env.GATEWAY_API_KEY ?? env.MICROSANDBOX_API_KEY,\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { buildApp } from \"./app\";\nimport { parseServerArgs, resolveServerConfig } from \"./lib/server-cli\";\n\nexport async function startServer({\n argv = process.argv.slice(2),\n env = process.env,\n app,\n}: {\n argv?: string[];\n env?: NodeJS.ProcessEnv;\n app?: Pick<FastifyInstance, \"listen\" | \"close\">;\n} = {}): Promise<Pick<FastifyInstance, \"listen\" | \"close\">> {\n const config = resolveServerConfig({ args: parseServerArgs(argv), env });\n const resolvedApp = app ?? (await buildApp({ apiKey: config.apiKey }));\n\n const removeSignalHandlers = (): void => {\n process.off(\"SIGINT\", onSigInt);\n process.off(\"SIGTERM\", onSigTerm);\n };\n\n const close = async (): Promise<undefined> => {\n removeSignalHandlers();\n return resolvedApp.close();\n };\n\n const onSigInt = () => { void shutdown(0); };\n const onSigTerm = () => { void shutdown(0); };\n\n const shutdown = async (code: number): Promise<void> => {\n try {\n await close();\n process.exit(code);\n } catch (error) {\n console.error(\"Failed to shutdown opensandbox-gateway cleanly\", error);\n process.exit(1);\n }\n };\n\n process.once(\"SIGINT\", onSigInt);\n process.once(\"SIGTERM\", onSigTerm);\n\n try {\n await resolvedApp.listen({ port: config.port, host: config.host });\n return { listen: resolvedApp.listen.bind(resolvedApp), close: close as FastifyInstance[\"close\"] };\n } catch (error) {\n removeSignalHandlers();\n throw error;\n }\n}\n"],"mappings":"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","names":["path","z","os","path","z","z","path","os","z"]}
|
package/dist/cli.mjs
CHANGED
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -16,6 +16,23 @@ type CachedEntry = {
|
|
|
16
16
|
|
|
17
17
|
type VolumeDefinition = NonNullable<EnsureSandboxInput["volumes"]>[string];
|
|
18
18
|
|
|
19
|
+
import path from "path";
|
|
20
|
+
import os from "os";
|
|
21
|
+
|
|
22
|
+
const defaultVolumeBasePath = path.join(os.homedir(), ".opensandbox", "volumes");
|
|
23
|
+
|
|
24
|
+
function resolveVolumeBasePath(): string {
|
|
25
|
+
return process.env.VOLUME_BASE_PATH ?? defaultVolumeBasePath;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function sanitizeVolumeName(mountPath: string): string {
|
|
29
|
+
return mountPath.replace(/^\/+|\/+$/g, "").replace(/[^a-z0-9-]/gi, "-").replace(/--+/g, "-").replace(/^-|-$/g, "") || "volume";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function resolveNamedVolumeHostPath(name: string): string {
|
|
33
|
+
return path.join(resolveVolumeBasePath(), name);
|
|
34
|
+
}
|
|
35
|
+
|
|
19
36
|
const NAME_METADATA_KEY = "axiom-lattice/name";
|
|
20
37
|
|
|
21
38
|
function getEnv(key: string, fallback: string): string {
|
|
@@ -56,10 +73,10 @@ export class OpenSandboxRuntimeService implements RuntimeService {
|
|
|
56
73
|
if (!volumes) return [];
|
|
57
74
|
return Object.entries(volumes).map(([mountPath, def]) => {
|
|
58
75
|
if (def.type === "bind" && def.source) {
|
|
59
|
-
return { name: mountPath, host: { path: def.source }, mountPath, readOnly: def.readonly };
|
|
76
|
+
return { name: sanitizeVolumeName(mountPath), host: { path: def.source }, mountPath, readOnly: def.readonly };
|
|
60
77
|
}
|
|
61
78
|
if (def.type === "named" && def.name) {
|
|
62
|
-
return { name: mountPath,
|
|
79
|
+
return { name: sanitizeVolumeName(mountPath), host: { path: resolveNamedVolumeHostPath(def.name) }, mountPath, readOnly: def.readonly };
|
|
63
80
|
}
|
|
64
81
|
if (def.type === "tmpfs") {
|
|
65
82
|
throw new HttpError(400, "INVALID_REQUEST", "tmpfs volumes are not supported by OpenSandbox");
|
|
@@ -80,6 +97,7 @@ export class OpenSandboxRuntimeService implements RuntimeService {
|
|
|
80
97
|
try {
|
|
81
98
|
const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });
|
|
82
99
|
const result = await manager.listSandboxInfos({
|
|
100
|
+
states: ["Running", "Paused"],
|
|
83
101
|
metadata: { [NAME_METADATA_KEY]: name },
|
|
84
102
|
pageSize: 1,
|
|
85
103
|
});
|
|
@@ -271,6 +289,7 @@ export class OpenSandboxRuntimeService implements RuntimeService {
|
|
|
271
289
|
try {
|
|
272
290
|
const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });
|
|
273
291
|
const result = await manager.listSandboxInfos({
|
|
292
|
+
states: ["Running", "Paused"],
|
|
274
293
|
metadata: { [NAME_METADATA_KEY]: name },
|
|
275
294
|
pageSize: 1,
|
|
276
295
|
});
|
|
@@ -440,7 +459,7 @@ export class OpenSandboxRuntimeService implements RuntimeService {
|
|
|
440
459
|
try {
|
|
441
460
|
const result = await entry.sandbox.commands.run(input.command, {
|
|
442
461
|
workingDirectory: input.exec_dir,
|
|
443
|
-
timeoutSeconds: input.timeout ? Math.ceil(input.timeout / 1000) :
|
|
462
|
+
timeoutSeconds: input.timeout ? Math.ceil(input.timeout / 1000) : 300,
|
|
444
463
|
});
|
|
445
464
|
return {
|
|
446
465
|
stdout: result.logs.stdout.map((s) => s.text).join(""),
|
|
@@ -448,7 +467,13 @@ export class OpenSandboxRuntimeService implements RuntimeService {
|
|
|
448
467
|
exitCode: result.exitCode ?? 0,
|
|
449
468
|
};
|
|
450
469
|
} catch (err) {
|
|
451
|
-
|
|
470
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
471
|
+
console.error(`[execCommand] sandbox=${input.sandboxName} cmd=${input.command.slice(0, 80)} error=${message}`);
|
|
472
|
+
return {
|
|
473
|
+
stdout: "",
|
|
474
|
+
stderr: message,
|
|
475
|
+
exitCode: -1,
|
|
476
|
+
};
|
|
452
477
|
}
|
|
453
478
|
}
|
|
454
479
|
|
|
@@ -492,6 +517,7 @@ export class OpenSandboxRuntimeService implements RuntimeService {
|
|
|
492
517
|
try {
|
|
493
518
|
const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });
|
|
494
519
|
const result = await manager.listSandboxInfos({
|
|
520
|
+
states: ["Running", "Paused"],
|
|
495
521
|
metadata: { [NAME_METADATA_KEY]: name },
|
|
496
522
|
pageSize: 1,
|
|
497
523
|
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/services/OpenSandboxRuntimeService.ts","../src/lib/errors.ts","../src/app.ts","../src/lib/http.ts","../src/routes/health.ts","../src/controllers/images.ts","../src/schemas/images.ts","../src/routes/images.ts","../src/schemas/sandbox.ts","../src/controllers/sandbox.ts","../src/routes/sandbox.ts","../src/controllers/volume-fs.ts","../src/schemas/volume-fs.ts","../src/routes/volume-fs.ts","../src/services/ImageService.ts","../src/swagger.ts","../src/lib/server-cli.ts","../src/server.ts"],"sourcesContent":["import { ConnectionConfig, Sandbox, type Volume } from \"@alibaba-group/opensandbox\";\nimport { SandboxManager, type SandboxFilter } from \"@alibaba-group/opensandbox\";\nimport { SandboxException } from \"@alibaba-group/opensandbox\";\nimport type { RuntimeService } from \"../types/runtime-service\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport type { SandboxLogsInput } from \"../schemas/sandbox\";\nimport type { SandboxRuntimeMetrics } from \"../types/runtime-service\";\nimport { HttpError } from \"../lib/errors\";\n\ntype CachedEntry = {\n sandbox: Sandbox;\n sandboxId: string;\n createdAt: string;\n lastUsedAt: number;\n};\n\ntype VolumeDefinition = NonNullable<EnsureSandboxInput[\"volumes\"]>[string];\n\nconst NAME_METADATA_KEY = \"axiom-lattice/name\";\n\nfunction getEnv(key: string, fallback: string): string {\n return process.env[key] ?? fallback;\n}\n\nfunction getEnvNumber(key: string, fallback: number): number {\n const v = process.env[key];\n return v ? Number(v) : fallback;\n}\n\nexport class OpenSandboxRuntimeService implements RuntimeService {\n private cache = new Map<string, CachedEntry>();\n private pendingCreates = new Map<string, Promise<CachedEntry>>();\n private connectionConfig: ConnectionConfig;\n private defaultImage: string;\n private defaultCpus: number;\n private defaultMemoryMib: number;\n private defaultTimeout: number;\n private idleTimeoutMs: number;\n\n constructor() {\n this.connectionConfig = new ConnectionConfig({\n domain: getEnv(\"OPEN_SANDBOX_DOMAIN\", \"localhost:8080\"),\n protocol: (getEnv(\"OPEN_SANDBOX_PROTOCOL\", \"http\") as \"http\" | \"https\"),\n apiKey: process.env[\"OPEN_SANDBOX_API_KEY\"],\n useServerProxy: getEnv(\"OPEN_SANDBOX_USE_SERVER_PROXY\", \"false\") === \"true\",\n });\n\n this.defaultImage = getEnv(\"OPEN_SANDBOX_DEFAULT_IMAGE\", \"ubuntu:22.04\");\n this.defaultCpus = getEnvNumber(\"OPEN_SANDBOX_DEFAULT_CPUS\", 1);\n this.defaultMemoryMib = getEnvNumber(\"OPEN_SANDBOX_DEFAULT_MEMORY_MIB\", 2048);\n this.defaultTimeout = getEnvNumber(\"OPEN_SANDBOX_DEFAULT_TIMEOUT\", 600);\n this.idleTimeoutMs = getEnvNumber(\"SANDBOX_IDLE_TIMEOUT_MS\", 600_000);\n }\n\n private mapVolumes(volumes?: Record<string, VolumeDefinition>): Volume[] {\n if (!volumes) return [];\n return Object.entries(volumes).map(([mountPath, def]) => {\n if (def.type === \"bind\" && def.source) {\n return { name: mountPath, host: { path: def.source }, mountPath, readOnly: def.readonly };\n }\n if (def.type === \"named\" && def.name) {\n return { name: mountPath, pvc: { claimName: def.name }, mountPath, readOnly: def.readonly };\n }\n if (def.type === \"tmpfs\") {\n throw new HttpError(400, \"INVALID_REQUEST\", \"tmpfs volumes are not supported by OpenSandbox\");\n }\n throw new HttpError(400, \"INVALID_REQUEST\", `Unsupported volume type at ${mountPath}`);\n });\n }\n\n private getCached(name: string): CachedEntry {\n const entry = this.cache.get(name);\n if (!entry) {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n return entry;\n }\n\n private async findByNameViaMetadata(name: string): Promise<CachedEntry | null> {\n try {\n const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });\n const result = await manager.listSandboxInfos({\n metadata: { [NAME_METADATA_KEY]: name },\n pageSize: 1,\n });\n\n if (result.items.length === 0) {\n return null;\n }\n\n const info = result.items[0];\n const sandbox = await Sandbox.resume({\n sandboxId: info.id,\n connectionConfig: this.connectionConfig,\n readyTimeoutSeconds: 1800,\n });\n\n const entry: CachedEntry = {\n sandbox,\n sandboxId: info.id,\n createdAt: info.createdAt ? new Date(info.createdAt).toISOString() : new Date().toISOString(),\n lastUsedAt: Date.now(),\n };\n this.cache.set(name, entry);\n return entry;\n } catch (err) {\n if (err instanceof SandboxException && err.error.code === \"NOT_FOUND\") {\n return null;\n }\n console.warn(`[OpenSandboxRuntimeService] metadata lookup for name=${name} failed:`, err);\n return null;\n }\n }\n\n async ensureSandbox(\n name: string,\n input: EnsureSandboxInput\n ): Promise<{ name: string; status: string }> {\n // 1. Check cache\n const cached = this.cache.get(name);\n if (cached) {\n try {\n const info = await cached.sandbox.getInfo();\n if (info.status.state === \"Running\") {\n cached.lastUsedAt = Date.now();\n await cached.sandbox.renew(this.defaultTimeout).catch(() => {\n });\n return { name, status: \"running\" };\n }\n this.cache.delete(name);\n } catch {\n this.cache.delete(name);\n }\n }\n\n // 2. Dedup concurrent creates for same name\n const inflight = this.pendingCreates.get(name);\n if (inflight) {\n await inflight;\n return { name, status: \"running\" };\n }\n\n // 3. Try metadata recovery (crash recovery)\n const recovered = await this.findByNameViaMetadata(name);\n if (recovered) {\n return { name, status: \"running\" };\n }\n\n // 4. Create new sandbox\n const creation = this.doCreateSandbox(name, input);\n this.pendingCreates.set(name, creation);\n try {\n await creation;\n return { name, status: \"running\" };\n } finally {\n this.pendingCreates.delete(name);\n }\n }\n\n private async doCreateSandbox(\n name: string,\n input: EnsureSandboxInput\n ): Promise<CachedEntry> {\n const sandbox = await Sandbox.create({\n connectionConfig: this.connectionConfig,\n image: input.image ?? this.defaultImage,\n timeoutSeconds: this.defaultTimeout,\n readyTimeoutSeconds: 1800,\n resource: {\n cpu: String(input.cpus ?? this.defaultCpus),\n memory: `${input.memoryMib ?? this.defaultMemoryMib}Mi`,\n },\n env: input.env ?? {},\n metadata: { [NAME_METADATA_KEY]: name },\n volumes: this.mapVolumes(input.volumes),\n entrypoint: [\"tail\", \"-f\", \"/dev/null\"],\n });\n\n const info = await sandbox.getInfo();\n\n const entry: CachedEntry = {\n sandbox,\n sandboxId: info.id,\n createdAt: info.createdAt ? new Date(info.createdAt).toISOString() : new Date().toISOString(),\n lastUsedAt: Date.now(),\n };\n this.cache.set(name, entry);\n return entry;\n }\n\n private wrapError(err: unknown, code: string, message: string): never {\n if (err instanceof HttpError) throw err;\n if (err instanceof SandboxException) {\n throw new HttpError(\n err.error.code === \"NOT_FOUND\" ? 404\n : err.error.code === \"FORBIDDEN\" ? 403\n : err.error.code === \"CONFLICT\" ? 409\n : err.error.code === \"INVALID_REQUEST\" ? 400\n : 500,\n err.error.code,\n err.error.message ?? message\n );\n }\n throw new HttpError(500, code, message);\n }\n\n async startSandbox(name: string): Promise<{ name: string; status: string }> {\n const entry = this.getCached(name);\n try {\n const resumed = await Sandbox.resume({\n sandboxId: entry.sandboxId,\n connectionConfig: this.connectionConfig,\n readyTimeoutSeconds: 1800,\n });\n // Update cache with new Sandbox instance (sandboxId may change on K8s)\n const info = await resumed.getInfo();\n entry.sandbox = resumed;\n entry.sandboxId = info.id;\n entry.lastUsedAt = Date.now();\n return { name, status: \"running\" };\n } catch (err) {\n throw this.wrapError(err, \"SANDBOX_NOT_FOUND\", `Failed to start sandbox '${name}'`);\n }\n }\n\n async stopSandbox(name: string): Promise<{ name: string; status: string }> {\n const entry = this.getCached(name);\n try {\n await entry.sandbox.pause();\n return { name, status: \"stopped\" };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to stop sandbox '${name}'`);\n }\n }\n\n async killSandbox(name: string): Promise<{ name: string; status: string }> {\n const entry = this.cache.get(name);\n if (!entry) {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n try {\n await entry.sandbox.kill();\n } catch {\n // kill failure is non-fatal\n }\n try {\n await entry.sandbox.close();\n } catch {\n // close failure is non-fatal\n }\n this.cache.delete(name);\n return { name, status: \"unknown\" };\n }\n\n async deleteSandbox(name: string): Promise<{ name: string; status: string }> {\n return this.killSandbox(name);\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n const entry = this.cache.get(name);\n if (entry) {\n try {\n const info = await entry.sandbox.getInfo();\n const status = info.status.state.toLowerCase();\n return { name, status };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n // Try server-side lookup\n try {\n const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });\n const result = await manager.listSandboxInfos({\n metadata: { [NAME_METADATA_KEY]: name },\n pageSize: 1,\n });\n if (result.items.length > 0) {\n return { name, status: result.items[0].status.state.toLowerCase() };\n }\n } catch {\n // ignore\n }\n return { name, status: \"unknown\" };\n }\n\n private resolvePath(path: string): string {\n if (path === \"~\" || path === \"~/\") return \"/\";\n if (path.startsWith(\"~/\")) return `/${path.slice(2)}`;\n return path;\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n const content = await entry.sandbox.files.readFile(resolvedPath);\n return { path: resolvedPath, content };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to read file '${resolvedPath}' in sandbox '${sandboxName}'`);\n }\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n // Create parent directories if needed\n const parentDir = resolvedPath.split(\"/\").slice(0, -1).join(\"/\") || \"/\";\n await entry.sandbox.files.createDirectories([{ path: parentDir }]).catch(() => {\n // parent may already exist\n });\n await entry.sandbox.files.writeFiles([{ path: resolvedPath, data: content }]);\n return { path: resolvedPath };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to write file '${resolvedPath}' in sandbox '${sandboxName}'`);\n }\n }\n\n async listPath(\n sandboxName: string,\n path: string,\n recursive?: boolean\n ): Promise<{ entries: Array<{ path: string; type: string }> }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n const files = await entry.sandbox.files.listDirectory({\n path: resolvedPath,\n depth: recursive ? undefined : 1,\n });\n return {\n entries: files.map((f) => ({\n path: f.path,\n type: f.isDir === true ? \"directory\" : f.isSymlink === true ? \"symlink\" : \"file\",\n })),\n };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to list path '${resolvedPath}' in sandbox '${sandboxName}'`);\n }\n }\n\n async findFiles(sandboxName: string, path: string, pattern: string): Promise<{ files: string[] }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n const results = await entry.sandbox.files.search({\n path: resolvedPath,\n pattern: pattern || \"*\",\n });\n return { files: results.map((r) => r.path) };\n } catch (err) {\n // Fallback to shell find command\n try {\n const result = await entry.sandbox.commands.run(\n `find ${resolvedPath} -name '${pattern}' -type f`,\n { timeoutSeconds: 30 }\n );\n return { files: result.logs.stdout.map((s) => s.text).join(\"\").split(\"\\n\").filter(Boolean) };\n } catch {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to find files in '${resolvedPath}'`);\n }\n }\n }\n\n async searchInFile(\n sandboxName: string,\n path: string,\n query: string\n ): Promise<{ matches: Array<{ line: number; content: string }> }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n const result = await entry.sandbox.commands.run(\n `grep -n -E '${query.replace(/'/g, \"'\\\\''\")}' ${resolvedPath}`,\n { timeoutSeconds: 30 }\n );\n const stdout = result.logs.stdout.map((s) => s.text).join(\"\");\n if (!stdout.trim()) return { matches: [] };\n return {\n matches: stdout.split(\"\\n\").filter(Boolean).map((line) => {\n const idx = line.indexOf(\":\");\n return { line: Number(line.slice(0, idx)), content: line.slice(idx + 1) };\n }),\n };\n } catch (err: unknown) {\n // grep returns exit code 1 for no matches — may throw or not\n if (err instanceof SandboxException) return { matches: [] };\n if (typeof err === \"object\" && err !== null && \"code\" in err && (err as { code: number }).code === 1) {\n return { matches: [] };\n }\n return { matches: [] };\n }\n }\n\n async replaceInFile(\n sandboxName: string,\n input: { path: string; search: string; replace: string }\n ): Promise<{ replaced: number }> {\n const resolvedPath = this.resolvePath(input.path);\n const entry = this.getCached(sandboxName);\n try {\n const original = await entry.sandbox.files.readFile(resolvedPath);\n if (!input.search) return { replaced: 0 };\n const occurrences = original.split(input.search).length - 1;\n if (occurrences === 0) return { replaced: 0 };\n const updated = original.split(input.search).join(input.replace);\n await entry.sandbox.files.writeFiles([{ path: resolvedPath, data: updated }]);\n return { replaced: occurrences };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to replace in file '${resolvedPath}'`);\n }\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n const data = Buffer.from(contentBase64, \"base64\").toString(\"utf-8\");\n await entry.sandbox.files.writeFiles([{ path: resolvedPath, data }]);\n return { path: resolvedPath };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to upload file '${resolvedPath}'`);\n }\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const resolvedPath = this.resolvePath(path);\n const entry = this.getCached(sandboxName);\n try {\n const data = await entry.sandbox.files.readBytes(resolvedPath);\n const b64 = Buffer.from(data).toString(\"base64\");\n return { path: resolvedPath, contentBase64: b64 };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Failed to download file '${resolvedPath}'`);\n }\n }\n\n async execCommand(input: ShellExecInput): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const entry = this.getCached(input.sandboxName);\n try {\n const result = await entry.sandbox.commands.run(input.command, {\n workingDirectory: input.exec_dir,\n timeoutSeconds: input.timeout ? Math.ceil(input.timeout / 1000) : undefined,\n });\n return {\n stdout: result.logs.stdout.map((s) => s.text).join(\"\"),\n stderr: result.logs.stderr.map((s) => s.text).join(\"\"),\n exitCode: result.exitCode ?? 0,\n };\n } catch (err) {\n throw this.wrapError(err, \"INTERNAL_ERROR\", `Command execution failed in sandbox '${input.sandboxName}'`);\n }\n }\n\n async getSandbox(\n name: string\n ): Promise<{\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n env: unknown;\n volumes: Record<string, unknown>;\n metrics?: SandboxRuntimeMetrics;\n createdAt: string;\n updatedAt: string;\n } | undefined> {\n // Try cache first\n const entry = this.cache.get(name);\n if (entry) {\n try {\n const info = await entry.sandbox.getInfo();\n return {\n name,\n status: info.status.state.toLowerCase(),\n image: info.image?.uri ?? \"unknown\",\n cpus: undefined,\n memoryMib: undefined,\n env: {},\n volumes: {},\n metrics: undefined,\n createdAt: info.createdAt ? new Date(info.createdAt).toISOString() : entry.createdAt,\n updatedAt: info.createdAt ? new Date(info.createdAt).toISOString() : entry.createdAt,\n };\n } catch {\n this.cache.delete(name);\n }\n }\n\n // Try server-side lookup via metadata\n try {\n const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });\n const result = await manager.listSandboxInfos({\n metadata: { [NAME_METADATA_KEY]: name },\n pageSize: 1,\n });\n if (result.items.length > 0) {\n const info = result.items[0];\n return {\n name,\n status: info.status.state.toLowerCase(),\n image: info.image?.uri ?? \"unknown\",\n cpus: undefined,\n memoryMib: undefined,\n env: {},\n volumes: {},\n metrics: undefined,\n createdAt: info.createdAt ? new Date(info.createdAt).toISOString() : \"\",\n updatedAt: info.createdAt ? new Date(info.createdAt).toISOString() : \"\",\n };\n }\n } catch {\n // ignore\n }\n\n return undefined;\n }\n\n async listSandboxes(_query: ListSandboxesQuery): Promise<{\n items: Array<{\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n }>;\n total: number;\n }> {\n try {\n const manager = SandboxManager.create({ connectionConfig: this.connectionConfig });\n const filter: SandboxFilter = {};\n if (_query.status) filter.states = [_query.status];\n const result = await manager.listSandboxInfos(filter);\n\n const items = result.items\n .filter((info) => {\n if (_query.search) {\n const haystack = [\n info.id,\n info.metadata?.[NAME_METADATA_KEY],\n info.image?.uri,\n ].filter(Boolean).join(\" \").toLowerCase();\n return haystack.includes(_query.search.toLowerCase());\n }\n return true;\n })\n .map((info) => ({\n name: info.metadata?.[NAME_METADATA_KEY] ?? info.id,\n status: info.status.state.toLowerCase(),\n image: info.image?.uri ?? \"unknown\",\n cpus: undefined,\n memoryMib: undefined,\n envCount: 0,\n volumeCount: 0,\n createdAt: info.createdAt ? new Date(info.createdAt).toISOString() : \"\",\n updatedAt: info.createdAt ? new Date(info.createdAt).toISOString() : \"\",\n }));\n\n return { items, total: items.length };\n } catch {\n return { items: [], total: 0 };\n }\n }\n\n async getSandboxLogs(\n _name: string,\n _opts: SandboxLogsInput\n ): Promise<{\n entries: Array<{\n timestamp: string;\n source: string;\n sessionId: number | null;\n text: string;\n }>;\n }> {\n return { entries: [] };\n }\n}\n","export class HttpError extends Error {\n constructor(\n public statusCode: number,\n public code: string,\n message: string\n ) {\n super(message);\n }\n}\n\nexport function toErrorResponse(error: unknown): {\n statusCode: number;\n body: {\n success: false;\n error: {\n code: string;\n message: string;\n };\n };\n} {\n if (error instanceof HttpError) {\n return {\n statusCode: error.statusCode,\n body: {\n success: false,\n error: {\n code: error.code,\n message: error.message,\n },\n },\n };\n }\n\n return {\n statusCode: 500,\n body: {\n success: false,\n error: {\n code: \"INTERNAL_ERROR\",\n message: error instanceof Error ? error.message : String(error),\n },\n },\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport cors from \"@fastify/cors\";\nimport multipart from \"@fastify/multipart\";\nimport sensible from \"@fastify/sensible\";\nimport fastify from \"fastify\";\nimport { toErrorResponse } from \"./lib/errors\";\nimport { registerHealthRoutes } from \"./routes/health\";\nimport { registerImageRoutes } from \"./routes/images\";\nimport { registerSandboxRoutes } from \"./routes/sandbox\";\nimport { registerVolumeFsRoutes } from \"./routes/volume-fs\";\nimport { ImageService } from \"./services/ImageService\";\nimport { OpenSandboxRuntimeService } from \"./services/OpenSandboxRuntimeService\";\nimport { configureSwagger } from \"./swagger\";\n\nexport async function buildApp({\n apiKey,\n}: {\n apiKey?: string;\n} = {}): Promise<FastifyInstance> {\n const runtimeService = new OpenSandboxRuntimeService();\n const imageService = new ImageService();\n\n const app = fastify({\n logger: false,\n bodyLimit: Number(process.env[\"BODY_LIMIT\"]) || 100 * 1024 * 1024,\n });\n\n await app.register(cors, {\n delegator: (request, callback) => {\n callback(null, {\n origin: true,\n methods: request.headers[\"access-control-request-method\"] ?? \"*\",\n allowedHeaders: request.headers[\"access-control-request-headers\"],\n });\n },\n });\n await app.register(sensible);\n await app.register(multipart);\n\n if (apiKey) {\n app.addHook(\"onRequest\", async (request, reply) => {\n if (request.method === \"OPTIONS\" || !request.url.startsWith(\"/api/\")) {\n return;\n }\n if (request.headers.authorization !== `Bearer ${apiKey}`) {\n await reply.code(401).send({\n success: false,\n error: { code: \"UNAUTHORIZED\", message: \"Unauthorized\" },\n });\n }\n });\n }\n\n registerHealthRoutes(app);\n registerSandboxRoutes(app, runtimeService);\n registerImageRoutes(app, imageService);\n registerVolumeFsRoutes(app);\n\n app.setErrorHandler((error, _request, reply) => {\n const { statusCode, body } = toErrorResponse(error);\n reply.status(statusCode).send(body);\n });\n\n await configureSwagger(app);\n\n return app;\n}\n","export type SuccessResponse<T> = {\n success: true;\n data: T;\n};\n\nexport function ok<T>(data: T): SuccessResponse<T> {\n return {\n success: true,\n data,\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { ok } from \"../lib/http\";\n\nexport function registerHealthRoutes(app: FastifyInstance): void {\n app.get(\"/health\", async () => ok({ status: \"ok\" }));\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport { ZodError } from \"zod\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport { ImageService } from \"../services/ImageService\";\nimport { imageRefQuerySchema, pullImageSchema } from \"../schemas/images\";\n\nfunction parseOrThrow<T>(parse: () => T): T {\n try {\n return parse();\n } catch (error) {\n if (error instanceof ZodError) {\n throw new HttpError(400, \"INVALID_REQUEST\", error.issues[0]?.message ?? \"Invalid request\");\n }\n\n throw error;\n }\n}\n\nexport function createImageController(imageService: ImageService) {\n return {\n listImages: async (_request: FastifyRequest, reply: FastifyReply) => {\n return reply.send(ok(await imageService.listImages()));\n },\n pullImage: async (request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply) => {\n const body = parseOrThrow(() => pullImageSchema.parse(request.body ?? {}));\n return reply.send(ok(await imageService.pullImage(body)));\n },\n getImage: async (request: FastifyRequest<{ Querystring: unknown }>, reply: FastifyReply) => {\n const query = parseOrThrow(() => imageRefQuerySchema.parse(request.query ?? {}));\n return reply.send(ok(await imageService.getImage(query.ref)));\n },\n deleteImage: async (request: FastifyRequest<{ Querystring: unknown }>, reply: FastifyReply) => {\n const query = parseOrThrow(() => imageRefQuerySchema.parse(request.query ?? {}));\n return reply.send(ok(await imageService.deleteImage(query.ref)));\n },\n };\n}\n","import z from \"zod\";\n\nexport const imageRefQuerySchema = z.object({\n ref: z.string().min(1),\n});\n\nexport const pullImageSchema = z.object({\n ref: z.string().min(1),\n});\n\nexport type ImageRefQuery = z.infer<typeof imageRefQuerySchema>;\nexport type PullImageInput = z.infer<typeof pullImageSchema>;\n","import type { FastifyInstance } from \"fastify\";\nimport { createImageController } from \"../controllers/images\";\nimport { ImageService } from \"../services/ImageService\";\n\nexport function registerImageRoutes(app: FastifyInstance, imageService: ImageService): void {\n const controller = createImageController(imageService);\n\n app.get(\"/api/images\", controller.listImages);\n app.post(\"/api/images/pull\", controller.pullImage);\n app.get(\"/api/images/detail\", controller.getImage);\n app.delete(\"/api/images/detail\", controller.deleteImage);\n}\n","import z from \"zod\";\n\nconst bindMountSchema = z.object({\n type: z.literal(\"bind\"),\n source: z.string().min(1),\n readonly: z.boolean().optional(),\n});\n\nconst namedMountSchema = z.object({\n type: z.literal(\"named\"),\n name: z.string().min(1),\n readonly: z.boolean().optional(),\n});\n\nconst tmpfsMountSchema = z.object({\n type: z.literal(\"tmpfs\"),\n sizeMib: z.number().int().positive().optional(),\n});\n\nexport const volumeSchema = z.union([\n bindMountSchema,\n namedMountSchema,\n tmpfsMountSchema,\n]);\n\nexport const ensureSandboxSchema = z.object({\n image: z.string().optional(),\n cpus: z.number().int().positive().optional(),\n memoryMib: z.number().int().positive().optional(),\n env: z.record(z.string()).optional(),\n volumes: z.record(volumeSchema).optional(),\n});\n\nexport const sandboxNameParamsSchema = z.object({\n name: z.string().min(1),\n});\n\nexport const listSandboxesQuerySchema = z.object({\n status: z.enum([\"running\", \"stopped\", \"crashed\", \"unknown\"]).optional(),\n image: z.string().min(1).optional(),\n search: z.string().min(1).optional(),\n});\n\nconst sandboxAndPathSchema = z.object({\n sandboxName: z.string().min(1),\n path: z.string().min(1),\n});\n\nexport const readFileSchema = sandboxAndPathSchema;\n\nexport const writeFileSchema = sandboxAndPathSchema.extend({\n content: z.string(),\n});\n\nexport const listPathSchema = sandboxAndPathSchema.extend({\n recursive: z.boolean().optional(),\n});\n\nexport const findFilesSchema = sandboxAndPathSchema.extend({\n pattern: z.string().min(1),\n});\n\nexport const searchInFileSchema = sandboxAndPathSchema.extend({\n query: z.string().min(1),\n});\n\nexport const replaceInFileSchema = sandboxAndPathSchema.extend({\n search: z.string(),\n replace: z.string(),\n});\n\nexport const uploadFileSchema = sandboxAndPathSchema.and(\n z.union([\n z.object({ contentBase64: z.string() }),\n z.object({ content: z.string().transform((content) => Buffer.from(content).toString(\"base64\")) }),\n ])\n);\n\nexport const downloadFileSchema = sandboxAndPathSchema;\n\nexport const shellExecSchema = z.object({\n sandboxName: z.string().min(1),\n command: z.string().min(1),\n exec_dir: z.string().optional(),\n timeout: z.number().int().positive().optional(),\n});\n\nexport const sandboxLogsSchema = z.object({\n tail: z.number().int().positive().optional(),\n since: z.string().optional(),\n until: z.string().optional(),\n sources: z.array(z.string()).optional(),\n});\n\nexport type EnsureSandboxInput = z.infer<typeof ensureSandboxSchema>;\nexport type ListSandboxesQuery = z.infer<typeof listSandboxesQuerySchema>;\nexport type ShellExecInput = z.infer<typeof shellExecSchema>;\nexport type SandboxLogsInput = z.infer<typeof sandboxLogsSchema>;\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport {\n downloadFileSchema,\n ensureSandboxSchema,\n findFilesSchema,\n listSandboxesQuerySchema,\n listPathSchema,\n readFileSchema,\n replaceInFileSchema,\n sandboxLogsSchema,\n sandboxNameParamsSchema,\n searchInFileSchema,\n shellExecSchema,\n uploadFileSchema,\n writeFileSchema,\n} from \"../schemas/sandbox\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport type { RuntimeService } from \"../types/runtime-service\";\n\nexport function createSandboxController(runtimeService: RuntimeService): {\n ensureSandbox(\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n startSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n stopSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n killSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n deleteSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n listSandboxes(\n request: FastifyRequest<{ Querystring: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getStatus(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getSandboxLogs(\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n readFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n writeFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n listPath(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n findFiles(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n searchInFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n replaceInFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n uploadFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n downloadFile(\n request: FastifyRequest<{ Querystring: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n execCommand(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n} {\n return {\n ensureSandbox: async (\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ) => {\n const body = ensureSandboxSchema.parse(request.body ?? {});\n const result = await runtimeService.ensureSandbox(request.params.name, body);\n return reply.send(ok(result));\n },\n\n startSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.startSandbox(request.params.name)));\n },\n\n stopSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.stopSandbox(request.params.name)));\n },\n\n killSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.killSandbox(request.params.name)));\n },\n\n deleteSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.deleteSandbox(request.params.name)));\n },\n\n listSandboxes: async (request, reply) => {\n const query = listSandboxesQuerySchema.parse(request.query ?? {});\n return reply.send(ok(await runtimeService.listSandboxes(query)));\n },\n\n getSandbox: async (request, reply) => {\n const params = sandboxNameParamsSchema.parse(request.params ?? {});\n const sandbox = await runtimeService.getSandbox(params.name);\n\n if (!sandbox) {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${params.name}' not found`);\n }\n\n return reply.send(ok(sandbox));\n },\n\n getStatus: async (request, reply) => {\n return reply.send(ok(await runtimeService.getStatus(request.params.name)));\n },\n\n getSandboxLogs: async (request, reply) => {\n const body = sandboxLogsSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.getSandboxLogs(request.params.name, body)));\n },\n\n readFile: async (request, reply) => {\n const body = readFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.readFile(body.sandboxName, body.path)));\n },\n\n writeFile: async (request, reply) => {\n const body = writeFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.writeFile(body.sandboxName, body.path, body.content)));\n },\n\n listPath: async (request, reply) => {\n const body = listPathSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.listPath(body.sandboxName, body.path, body.recursive)));\n },\n\n findFiles: async (request, reply) => {\n const body = findFilesSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.findFiles(body.sandboxName, body.path, body.pattern)));\n },\n\n searchInFile: async (request, reply) => {\n const body = searchInFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.searchInFile(body.sandboxName, body.path, body.query)));\n },\n\n replaceInFile: async (request, reply) => {\n const body = replaceInFileSchema.parse(request.body ?? {});\n return reply.send(\n ok(\n await runtimeService.replaceInFile(body.sandboxName, {\n path: body.path,\n search: body.search,\n replace: body.replace,\n })\n )\n );\n },\n\n uploadFile: async (request, reply) => {\n const body = uploadFileSchema.parse(request.body ?? {});\n const contentBase64 = \"contentBase64\" in body ? body.contentBase64 : Buffer.from(body.content).toString(\"base64\");\n return reply.send(ok(await runtimeService.uploadFile(body.sandboxName, body.path, contentBase64)));\n },\n\n downloadFile: async (request, reply) => {\n const query = downloadFileSchema.parse(request.query ?? {});\n return reply.send(ok(await runtimeService.downloadFile(query.sandboxName, query.path)));\n },\n\n execCommand: async (request, reply) => {\n const body = shellExecSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.execCommand(body)));\n },\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { createSandboxController } from \"../controllers/sandbox\";\nimport type { RuntimeService } from \"../types/runtime-service\";\n\nexport function registerSandboxRoutes(\n app: FastifyInstance,\n runtimeService: RuntimeService\n): void {\n const controller = createSandboxController(runtimeService);\n\n app.get(\"/api/sandboxes\", controller.listSandboxes);\n app.get(\"/api/sandboxes/:name\", controller.getSandbox);\n app.put(\"/api/sandboxes/:name\", controller.ensureSandbox);\n app.post(\"/api/sandboxes/:name/start\", controller.startSandbox);\n app.post(\"/api/sandboxes/:name/stop\", controller.stopSandbox);\n app.post(\"/api/sandboxes/:name/kill\", controller.killSandbox);\n app.delete(\"/api/sandboxes/:name\", controller.deleteSandbox);\n app.get(\"/api/sandboxes/:name/status\", controller.getStatus);\n app.post(\"/api/sandboxes/:name/logs\", controller.getSandboxLogs);\n\n app.post(\"/api/files/read\", controller.readFile);\n app.post(\"/api/files/write\", controller.writeFile);\n app.post(\"/api/files/list\", controller.listPath);\n app.post(\"/api/files/find\", controller.findFiles);\n app.post(\"/api/files/search\", controller.searchInFile);\n app.post(\"/api/files/replace\", controller.replaceInFile);\n app.post(\"/api/files/upload\", controller.uploadFile);\n app.get(\"/api/files/download\", controller.downloadFile);\n\n app.post(\"/api/shell/exec\", controller.execCommand);\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport fs from \"fs/promises\";\nimport os from \"os\";\nimport path from \"path\";\nimport z from \"zod\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport {\n volumeFsReadSchema,\n volumeFsWriteSchema,\n volumeFsListSchema,\n volumeFsUploadSchema,\n volumeFsDownloadSchema,\n} from \"../schemas/volume-fs\";\n\ninterface VolumeFsParams {\n name: string;\n}\n\nfunction getVolumeBasePath(): string {\n return process.env.VOLUME_BASE_PATH ?? path.join(os.homedir(), \".opensandbox\", \"volumes\");\n}\n\nfunction resolveVolumeHostPath(name: string): string {\n return path.join(getVolumeBasePath(), name);\n}\n\nfunction resolveGuestPath(hostRoot: string, guestPath: string): string {\n const normalized = guestPath === \"~\" ? \"\" : guestPath.replace(/^~\\//, \"\");\n const resolved = path.join(\n hostRoot,\n path.normalize(normalized).replace(/^(\\.\\.(\\/|\\\\|$))+/, \"\")\n );\n if (!resolved.startsWith(hostRoot + path.sep) && resolved !== hostRoot) {\n throw new HttpError(403, \"PATH_TRAVERSAL\", \"Path traversal detected\");\n }\n return resolved;\n}\n\nexport function createVolumeFsController(): {\n readFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n writeFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string; content: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n listPath(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n downloadFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Querystring: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n uploadFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string; contentBase64: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n} {\n return {\n readFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsReadSchema.parse(request.body ?? {});\n const hostRoot = resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const content = await fs.readFile(fullPath, \"utf-8\");\n return reply.send(ok({ path: guestPath, content }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_READ_ERROR\", `Failed to read from volume '${name}': ${String(err)}`);\n }\n },\n\n writeFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath, content } = volumeFsWriteSchema.parse(request.body ?? {});\n const hostRoot = resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, content, \"utf-8\");\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_WRITE_ERROR\", `Failed to write to volume '${name}': ${String(err)}`);\n }\n },\n\n listPath: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsListSchema.parse(request.body ?? {});\n const hostRoot = resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const dirents = await fs.readdir(fullPath, { withFileTypes: true });\n const entries = dirents.map((d) => ({\n path: guestPath ? `${guestPath}/${d.name}` : d.name,\n kind: d.isDirectory() ? \"directory\" : d.isSymbolicLink() ? \"symlink\" : \"file\",\n size: 0,\n mode: 0,\n }));\n return reply.send(ok({ entries }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_LIST_ERROR\", `Failed to list volume '${name}': ${String(err)}`);\n }\n },\n\n downloadFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsDownloadSchema.parse(request.query ?? {});\n const hostRoot = resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const buf = await fs.readFile(fullPath);\n const contentBase64 = buf.toString(\"base64\");\n return reply.send(ok({ path: guestPath, contentBase64 }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_DOWNLOAD_ERROR\", `Failed to download from volume '${name}': ${String(err)}`);\n }\n },\n\n uploadFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath, contentBase64 } = volumeFsUploadSchema.parse(request.body ?? {});\n const hostRoot = resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n const data = Buffer.from(contentBase64, \"base64\");\n await fs.writeFile(fullPath, data);\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_UPLOAD_ERROR\", `Failed to upload to volume '${name}': ${String(err)}`);\n }\n },\n };\n}\n","import z from \"zod\";\n\nexport const volumeFsReadSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsWriteSchema = z.object({\n path: z.string(),\n content: z.string(),\n});\n\nexport const volumeFsListSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsUploadSchema = z.object({\n path: z.string(),\n contentBase64: z.string().min(1),\n});\n\nexport const volumeFsDownloadSchema = z.object({\n path: z.string(),\n});\n","import type { FastifyInstance } from \"fastify\";\nimport { createVolumeFsController } from \"../controllers/volume-fs\";\n\nexport function registerVolumeFsRoutes(app: FastifyInstance): void {\n const controller = createVolumeFsController();\n\n app.post(\"/api/volumes/:name/fs/read\", controller.readFile);\n app.post(\"/api/volumes/:name/fs/write\", controller.writeFile);\n app.post(\"/api/volumes/:name/fs/list\", controller.listPath);\n app.get(\"/api/volumes/:name/fs/download\", controller.downloadFile);\n app.post(\"/api/volumes/:name/fs/upload\", controller.uploadFile);\n}\n","import type { PullImageInput } from \"../schemas/images\";\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\nexport class ImageService {\n async listImages(): Promise<{ items: ImageRecord[]; total: number }> {\n return { items: [], total: 0 };\n }\n\n async pullImage(_input: PullImageInput): Promise<ImageRecord> {\n throw new Error(\"Image pull not supported in OpenSandbox gateway\");\n }\n\n async getImage(ref: string): Promise<ImageRecord> {\n return {\n ref,\n sourceType: \"oci\",\n cached: false,\n };\n }\n\n async deleteImage(ref: string): Promise<{ ref: string }> {\n return { ref };\n }\n}\n","import type { FastifyInstance } from \"fastify\";\nimport swagger from \"@fastify/swagger\";\nimport swaggerUi from \"@fastify/swagger-ui\";\n\nconst swaggerConfig = {\n openapi: {\n openapi: \"3.0.0\",\n info: {\n title: \"OpenSandbox Gateway API\",\n description: \"Sandbox lifecycle management backed by OpenSandbox\",\n version: \"1.0.0\",\n },\n servers: [{ url: \"http://localhost:4002\", description: \"Local development\" }],\n components: {\n securitySchemes: {\n bearerAuth: { type: \"http\" as const, scheme: \"bearer\" as const, bearerFormat: \"API Key\" },\n },\n },\n tags: [\n { name: \"Sandboxes\", description: \"Sandbox lifecycle\" },\n { name: \"Files\", description: \"File operations inside sandboxes\" },\n { name: \"Shell\", description: \"Execute commands inside sandboxes\" },\n { name: \"Images\", description: \"Image management (stub)\" },\n { name: \"Volumes\", description: \"Named volume filesystem operations\" },\n { name: \"Health\", description: \"Service health check\" },\n ],\n },\n};\n\nconst swaggerUiConfig = {\n routePrefix: \"/api-docs\",\n uiConfig: { docExpansion: \"list\" as const, deepLinking: true },\n staticCSP: true,\n transformStaticCSP: (header: string) => header,\n};\n\nexport async function configureSwagger(app: FastifyInstance) {\n await app.register(swagger, swaggerConfig);\n await app.register(swaggerUi, swaggerUiConfig);\n}\n","export interface ParsedServerArgs {\n host?: string;\n port?: number;\n}\n\nexport interface ResolvedServerConfig {\n host: string;\n port: number;\n apiKey?: string;\n}\n\nfunction parsePort(raw: string, source: string): number {\n const value = Number(raw);\n if (!Number.isInteger(value) || value <= 0 || value > 65535) {\n throw new Error(`Invalid value for ${source}: ${raw}`);\n }\n return value;\n}\n\nfunction isMissingOptionValue(raw: string | undefined): raw is undefined {\n return !raw || raw.startsWith(\"--\");\n}\n\nexport function parseServerArgs(argv: string[]): ParsedServerArgs {\n const parsed: ParsedServerArgs = {};\n\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index];\n\n if (token === \"--port\") {\n const raw = argv[index + 1];\n if (isMissingOptionValue(raw)) {\n throw new Error(\"Missing value for --port\");\n }\n parsed.port = parsePort(raw, \"--port\");\n index += 1;\n continue;\n }\n\n if (token === \"--host\") {\n const raw = argv[index + 1];\n if (isMissingOptionValue(raw)) {\n throw new Error(\"Missing value for --host\");\n }\n parsed.host = raw;\n index += 1;\n }\n }\n\n return parsed;\n}\n\nexport function resolveServerConfig({\n args,\n env,\n}: {\n args: ParsedServerArgs;\n env: NodeJS.ProcessEnv;\n}): ResolvedServerConfig {\n return {\n host: args.host ?? env.HOST ?? \"0.0.0.0\",\n port: args.port ?? (env.PORT ? parsePort(env.PORT, \"PORT\") : 4002),\n apiKey: env.GATEWAY_API_KEY ?? env.MICROSANDBOX_API_KEY,\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { buildApp } from \"./app\";\nimport { parseServerArgs, resolveServerConfig } from \"./lib/server-cli\";\n\nexport async function startServer({\n argv = process.argv.slice(2),\n env = process.env,\n app,\n}: {\n argv?: string[];\n env?: NodeJS.ProcessEnv;\n app?: Pick<FastifyInstance, \"listen\" | \"close\">;\n} = {}): Promise<Pick<FastifyInstance, \"listen\" | \"close\">> {\n const config = resolveServerConfig({ args: parseServerArgs(argv), env });\n const resolvedApp = app ?? (await buildApp({ apiKey: config.apiKey }));\n\n const removeSignalHandlers = (): void => {\n process.off(\"SIGINT\", onSigInt);\n process.off(\"SIGTERM\", onSigTerm);\n };\n\n const close = async (): Promise<undefined> => {\n removeSignalHandlers();\n return resolvedApp.close();\n };\n\n const onSigInt = () => { void shutdown(0); };\n const onSigTerm = () => { void shutdown(0); };\n\n const shutdown = async (code: number): Promise<void> => {\n try {\n await close();\n process.exit(code);\n } catch (error) {\n console.error(\"Failed to shutdown opensandbox-gateway cleanly\", error);\n process.exit(1);\n }\n };\n\n process.once(\"SIGINT\", onSigInt);\n process.once(\"SIGTERM\", onSigTerm);\n\n try {\n await resolvedApp.listen({ port: config.port, host: config.host });\n return { listen: resolvedApp.listen.bind(resolvedApp), close: close as FastifyInstance[\"close\"] };\n } catch (error) {\n removeSignalHandlers();\n throw error;\n }\n}\n"],"mappings":"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","names":["path","z","z","z","z"]}
|