@axiom-lattice/microsandbox-service 0.0.12 → 0.0.14
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/CHANGELOG.md +12 -0
- package/dist/{chunk-ARPFW5HA.mjs → chunk-7FG2JFOQ.mjs} +37 -15
- package/dist/chunk-7FG2JFOQ.mjs.map +1 -0
- package/dist/{chunk-H46YDPX5.mjs → chunk-DZXYJERT.mjs} +2 -2
- package/dist/cli.mjs +2 -2
- package/dist/index.mjs +1 -1
- package/dist/server.mjs +2 -2
- package/package.json +1 -1
- package/src/__tests__/MicrosandboxRuntimeService.test.ts +18 -49
- package/src/app.ts +4 -1
- package/src/services/MicrosandboxRuntimeService.ts +33 -13
- package/dist/chunk-ARPFW5HA.mjs.map +0 -1
- /package/dist/{chunk-H46YDPX5.mjs.map → chunk-DZXYJERT.mjs.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -135,9 +135,11 @@ var MicrosandboxRuntimeService = class {
|
|
|
135
135
|
return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());
|
|
136
136
|
}
|
|
137
137
|
resolvePath(path2) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
if (path2 === "~" || path2 === "~/") {
|
|
139
|
+
return "/";
|
|
140
|
+
}
|
|
141
|
+
if (path2.startsWith("~/")) {
|
|
142
|
+
return `/${path2.slice(2)}`;
|
|
141
143
|
}
|
|
142
144
|
return path2;
|
|
143
145
|
}
|
|
@@ -209,24 +211,40 @@ var MicrosandboxRuntimeService = class {
|
|
|
209
211
|
return { name, status: "running" };
|
|
210
212
|
}
|
|
211
213
|
async stopSandbox(name) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
try {
|
|
215
|
+
const native = await this.getOrEnsureNative(name);
|
|
216
|
+
await native.stop();
|
|
217
|
+
this.registry.delete(name);
|
|
218
|
+
return { name, status: "stopped" };
|
|
219
|
+
} catch (error) {
|
|
220
|
+
if (error instanceof Error && error.message.includes("write to relay")) {
|
|
221
|
+
this.registry.delete(name);
|
|
222
|
+
return { name, status: "unknown" };
|
|
223
|
+
}
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
216
226
|
}
|
|
217
227
|
async killSandbox(name) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
228
|
+
try {
|
|
229
|
+
const native = await this.getOrEnsureNative(name);
|
|
230
|
+
await native.kill();
|
|
231
|
+
this.registry.delete(name);
|
|
232
|
+
return { name, status: "unknown" };
|
|
233
|
+
} catch (error) {
|
|
234
|
+
if (error instanceof Error && error.message.includes("write to relay")) {
|
|
235
|
+
this.registry.delete(name);
|
|
236
|
+
return { name, status: "unknown" };
|
|
237
|
+
}
|
|
238
|
+
throw error;
|
|
239
|
+
}
|
|
222
240
|
}
|
|
223
241
|
async deleteSandbox(name) {
|
|
224
242
|
try {
|
|
225
243
|
await this.getNative(name).kill();
|
|
226
244
|
} catch {
|
|
227
245
|
}
|
|
228
|
-
await Sandbox2.remove(name);
|
|
229
246
|
this.registry.delete(name);
|
|
247
|
+
await Sandbox2.remove(name);
|
|
230
248
|
return { name, status: "unknown" };
|
|
231
249
|
}
|
|
232
250
|
async listSandboxes(_query) {
|
|
@@ -323,9 +341,10 @@ var MicrosandboxRuntimeService = class {
|
|
|
323
341
|
}
|
|
324
342
|
async findFiles(sandboxName, path2, pattern) {
|
|
325
343
|
const resolvedPath = this.resolvePath(path2);
|
|
344
|
+
const matchFlag = pattern.includes("/") ? "-path" : "-name";
|
|
326
345
|
const output = await this.getNative(sandboxName).execWithConfig({
|
|
327
346
|
cmd: "find",
|
|
328
|
-
args: [resolvedPath,
|
|
347
|
+
args: [resolvedPath, matchFlag, pattern, "-type", "f"]
|
|
329
348
|
});
|
|
330
349
|
return { files: output.stdout().split("\n").filter(Boolean) };
|
|
331
350
|
}
|
|
@@ -905,7 +924,10 @@ function buildApp({
|
|
|
905
924
|
imageService = new ImageService(),
|
|
906
925
|
apiKey
|
|
907
926
|
} = {}) {
|
|
908
|
-
const app = fastify({
|
|
927
|
+
const app = fastify({
|
|
928
|
+
logger: false,
|
|
929
|
+
bodyLimit: Number(process.env.BODY_LIMIT) || 100 * 1024 * 1024
|
|
930
|
+
});
|
|
909
931
|
app.register(cors, {
|
|
910
932
|
delegator: (request, callback) => {
|
|
911
933
|
callback(null, {
|
|
@@ -949,4 +971,4 @@ export {
|
|
|
949
971
|
MicrosandboxRuntimeService,
|
|
950
972
|
buildApp
|
|
951
973
|
};
|
|
952
|
-
//# sourceMappingURL=chunk-
|
|
974
|
+
//# sourceMappingURL=chunk-7FG2JFOQ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/SandboxRegistry.ts","../src/services/MicrosandboxRuntimeService.ts","../src/app.ts","../src/lib/errors.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"],"sourcesContent":["import { Sandbox, Mount } from \"microsandbox\";\nimport type { SandboxHandle } from \"microsandbox\";\n\nconst DEFAULT_IMAGE = process.env.MICROSANDBOX_IMAGE ?? \"daytonaio/sandbox:0.6.0\";\n\nexport class SandboxRegistry {\n private handles = new Map<string, unknown>();\n private creating = new Map<string, Promise<unknown>>();\n\n async ensure(name: string, createOptions?: Record<string, unknown>): Promise<unknown> {\n const cached = this.handles.get(name);\n if (cached) {\n return cached;\n }\n\n const inflight = this.creating.get(name);\n if (inflight) {\n return inflight;\n }\n\n const creation = (async () => {\n let native: unknown;\n const image = (createOptions?.image as string) ?? DEFAULT_IMAGE;\n const cpus = (createOptions?.cpus as number) ?? 1;\n const memoryMib = (createOptions?.memoryMib as number) ?? 512;\n const env = (createOptions?.env as Record<string, string>) ?? undefined;\n\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n\n if (handle.status === \"running\") {\n native = await handle.connect();\n } else if (handle.status === \"stopped\") {\n native = await Sandbox.start(name);\n } else if (handle.status === \"crashed\" || handle.status === \"draining\") {\n await Sandbox.remove(name);\n } else {\n await Sandbox.remove(name);\n }\n } catch {\n native = undefined;\n }\n\n if (!native) {\n const volumeDefs = createOptions?.volumes as Record<string, { type: string; source?: string; name?: string; sizeMib?: number; readonly?: boolean }> | undefined;\n const volumes: Record<string, ReturnType<typeof Mount.bind>> = {};\n if (volumeDefs) {\n for (const [guestPath, def] of Object.entries(volumeDefs)) {\n const mountOpts = def.readonly ? { readonly: true } : undefined;\n if (def.type === \"bind\" && def.source) {\n volumes[guestPath] = Mount.bind(def.source, mountOpts);\n } else if (def.type === \"named\" && def.name) {\n volumes[guestPath] = Mount.named(def.name, mountOpts);\n } else if (def.type === \"tmpfs\") {\n volumes[guestPath] = Mount.tmpfs(def.sizeMib ? { sizeMib: def.sizeMib, ...mountOpts } : mountOpts);\n }\n }\n }\n try {\n native = await Sandbox.createDetached({\n name,\n image,\n cpus,\n memoryMib,\n env,\n volumes,\n });\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"already exists\")) {\n await Sandbox.remove(name);\n native = await Sandbox.createDetached({\n name,\n image,\n cpus,\n memoryMib,\n env,\n volumes,\n });\n } else {\n throw err;\n }\n }\n }\n\n this.handles.set(name, native);\n return native;\n })();\n\n this.creating.set(name, creation);\n void creation.finally(() => this.creating.delete(name));\n\n return creation;\n }\n\n get(name: string): unknown {\n const handle = this.handles.get(name);\n\n if (!handle) {\n throw new Error(`Sandbox ${name} not found`);\n }\n\n return handle;\n }\n\n delete(name: string): void {\n this.handles.delete(name);\n }\n}\n","import { Sandbox, Volume } from \"microsandbox\";\nimport type { SandboxHandle, SandboxInfo } from \"microsandbox\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport type { SandboxRuntimeMetrics } from \"../types/runtime-service\";\nimport { SandboxRegistry } from \"./SandboxRegistry\";\n\ntype VolumeConfig = NonNullable<EnsureSandboxInput[\"volumes\"]>[string];\n\ntype RuntimeNative = {\n fs(): {\n readString(path: string): Promise<string>;\n write(path: string, data: Buffer): Promise<void>;\n list(path: string): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;\n read(path: string): Promise<Buffer | Uint8Array | string>;\n };\n execWithConfig(config: { cmd: string; args?: string[]; cwd?: string; timeoutMs?: number }): Promise<{\n stdout(): string;\n stderr(): string;\n code?: number;\n }>;\n stop(): Promise<void>;\n kill(): Promise<void>;\n};\n\ntype SandboxConfig = {\n name: string;\n image: string;\n memoryMib?: number;\n cpus?: number;\n env?: Record<string, string>;\n volumes?: Record<string, unknown>;\n};\n\nfunction parseEnvArray(env: unknown): Record<string, string> {\n if (!Array.isArray(env)) return env as Record<string, string>;\n const result: Record<string, string> = {};\n for (const entry of env) {\n if (typeof entry !== \"string\") continue;\n const eq = entry.indexOf(\"=\");\n if (eq < 0) continue;\n result[entry.slice(0, eq)] = entry.slice(eq + 1);\n }\n return result;\n}\n\nfunction parseConfigJson(configJson: string): SandboxConfig {\n try {\n const raw = JSON.parse(configJson);\n return {\n name: raw.name ?? \"\",\n image: raw.image ?? \"\",\n memoryMib: raw.memoryMib ?? raw.memory_mib,\n cpus: raw.cpus,\n env: raw.env != null ? parseEnvArray(raw.env) : undefined,\n volumes: raw.volumes,\n };\n } catch {\n return { name: \"\", image: \"\" };\n }\n}\n\nfunction msToIsoString(ms: number | Date | null | undefined): string {\n if (ms == null) return \"\";\n if (ms instanceof Date) return ms.toISOString();\n return new Date(ms).toISOString();\n}\n\nexport class MicrosandboxRuntimeService {\n constructor(private deps: { registry?: SandboxRegistry } = {}) {}\n\n private get registry(): SandboxRegistry {\n return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());\n }\n\n private resolvePath(path: string): string {\n if (path === \"~\" || path === \"~/\") {\n return \"/\";\n }\n if (path.startsWith(\"~/\")) {\n return `/${path.slice(2)}`;\n }\n return path;\n }\n\n private toListItem(info: {\n name: string;\n status: string;\n configJson: string;\n createdAt?: number | Date | null;\n updatedAt?: number | Date | null;\n }): {\n name: string;\n status: string;\n image?: string;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n } {\n const config = parseConfigJson(info.configJson);\n const env = config.env ?? {};\n const volumes = config.volumes ?? {};\n\n return {\n name: info.name,\n status: info.status,\n image: config.image,\n cpus: config.cpus,\n memoryMib: config.memoryMib,\n envCount: Object.keys(env).length,\n volumeCount: Object.keys(volumes).length,\n createdAt: msToIsoString(info.createdAt),\n updatedAt: msToIsoString(info.updatedAt),\n };\n }\n\n private async ensureNamedVolumes(volumes?: EnsureSandboxInput[\"volumes\"]): Promise<void> {\n if (!volumes) {\n return;\n }\n\n const defaultQuotaMib = Number(process.env.MICROSANDBOX_VOLUME_QUOTA_MIB ?? \"1024\");\n\n const namedVolumes = Object.values(volumes).filter(\n (v): v is Extract<VolumeConfig, { type: \"named\" }> => v.type === \"named\"\n );\n\n await Promise.all(\n namedVolumes.map(async (definition) => {\n try {\n await Volume.get(definition.name);\n } catch {\n await Volume.create({ name: definition.name, quotaMib: defaultQuotaMib });\n }\n })\n );\n }\n\n private getNative(name: string): RuntimeNative {\n return this.registry.get(name) as RuntimeNative;\n }\n\n private async getOrEnsureNative(name: string): Promise<RuntimeNative> {\n try {\n return this.getNative(name);\n } catch {\n return (await this.registry.ensure(name)) as RuntimeNative;\n }\n }\n\n async ensureSandbox(\n name: string,\n input: EnsureSandboxInput\n ): Promise<{\n name: string;\n status: string;\n }> {\n const image = input.image ?? process.env.MICROSANDBOX_IMAGE ?? \"python:3.11-slim\";\n const cpus = input.cpus ?? Number(process.env.MICROSANDBOX_CPUS ?? \"1\");\n const memoryMib = input.memoryMib ?? Number(process.env.MICROSANDBOX_MEMORY ?? \"512\");\n\n await this.ensureNamedVolumes(input.volumes);\n\n await this.registry.ensure(name, {\n image,\n cpus,\n memoryMib,\n env: input.env,\n volumes: input.volumes,\n });\n\n return {\n name,\n status: \"running\",\n };\n }\n\n async startSandbox(name: string): Promise<{ name: string; status: string }> {\n await Sandbox.start(name);\n this.registry.delete(name);\n await this.registry.ensure(name);\n return { name, status: \"running\" };\n }\n\n async stopSandbox(name: string): Promise<{ name: string; status: string }> {\n try {\n const native = await this.getOrEnsureNative(name);\n await native.stop();\n this.registry.delete(name);\n return { name, status: \"stopped\" };\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"write to relay\")) {\n this.registry.delete(name);\n return { name, status: \"unknown\" };\n }\n throw error;\n }\n }\n\n async killSandbox(name: string): Promise<{ name: string; status: string }> {\n try {\n const native = await this.getOrEnsureNative(name);\n await native.kill();\n this.registry.delete(name);\n return { name, status: \"unknown\" };\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"write to relay\")) {\n this.registry.delete(name);\n return { name, status: \"unknown\" };\n }\n throw error;\n }\n }\n\n async deleteSandbox(name: string): Promise<{ name: string; status: string }> {\n try {\n await this.getNative(name).kill();\n } catch {\n // Ignore missing cached native handle before remove.\n }\n\n this.registry.delete(name);\n await Sandbox.remove(name);\n\n return { name, status: \"unknown\" };\n }\n\n async listSandboxes(_query: ListSandboxesQuery): Promise<{\n items: Array<{\n name: string;\n status: string;\n image?: string;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n }>;\n total: number;\n }> {\n const all: SandboxInfo[] = await Sandbox.list();\n\n const items = all\n .map((info) =>\n this.toListItem({\n name: info.name,\n status: info.status,\n configJson: info.configJson,\n createdAt: info.createdAt,\n updatedAt: info.updatedAt,\n })\n )\n .filter((item) => {\n if (_query.status && item.status !== _query.status) {\n return false;\n }\n\n if (_query.image && item.image !== _query.image) {\n return false;\n }\n\n if (_query.search) {\n const haystack = [item.name, item.image]\n .filter((value): value is string => Boolean(value))\n .join(\" \")\n .toLowerCase();\n\n if (!haystack.includes(_query.search.toLowerCase())) {\n return false;\n }\n }\n\n return true;\n });\n\n return { items, total: items.length };\n }\n\n async getSandbox(\n name: string\n ): Promise<{\n name: string;\n status: string;\n image?: string;\n cpus?: number;\n memoryMib?: number;\n env: Record<string, string>;\n volumes: Record<string, unknown>;\n metrics?: SandboxRuntimeMetrics;\n createdAt: string;\n updatedAt: string;\n } | undefined> {\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n const config = parseConfigJson(handle.configJson);\n let metrics: SandboxRuntimeMetrics | undefined;\n\n try {\n const m = await handle.metrics();\n metrics = {\n cpuPercent: m.cpuPercent,\n memoryBytes: m.memoryBytes,\n memoryLimitBytes: m.memoryLimitBytes,\n diskReadBytes: m.diskReadBytes,\n diskWriteBytes: m.diskWriteBytes,\n netRxBytes: m.netRxBytes,\n netTxBytes: m.netTxBytes,\n uptimeMs: m.uptimeMs,\n timestampMs: m.timestampMs,\n };\n } catch {\n metrics = undefined;\n }\n\n return {\n name: handle.name,\n status: handle.status,\n image: config.image,\n cpus: config.cpus,\n memoryMib: config.memoryMib,\n env: config.env ?? {},\n volumes: config.volumes ?? {},\n metrics,\n createdAt: msToIsoString(handle.createdAt),\n updatedAt: msToIsoString(handle.updatedAt),\n };\n } catch {\n return undefined;\n }\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n return { name, status: handle.status };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const resolvedPath = this.resolvePath(path);\n const content = await this.getNative(sandboxName).fs().readString(resolvedPath);\n return { path: resolvedPath, content };\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n await this.getNative(sandboxName).fs().write(resolvedPath, Buffer.from(content));\n return { path: resolvedPath };\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 entries = await this.getNative(sandboxName).fs().list(resolvedPath);\n return {\n entries: entries.map((entry) => ({\n path: entry.path,\n type: entry.kind,\n })),\n };\n }\n\n async findFiles(sandboxName: string, path: string, pattern: string): Promise<{ files: string[] }> {\n const resolvedPath = this.resolvePath(path);\n // Use -path for patterns containing / (e.g., \"**/*.py\"), -name for filename-only patterns (e.g., \"*.py\")\n const matchFlag = pattern.includes(\"/\") ? \"-path\" : \"-name\";\n const output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"find\",\n args: [resolvedPath, matchFlag, pattern, \"-type\", \"f\"],\n });\n return { files: output.stdout().split(\"\\n\").filter(Boolean) };\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 let stdout: string;\n\n try {\n const output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"grep\",\n args: [\"-n\", \"-E\", query, resolvedPath],\n });\n stdout = output.stdout();\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === 1) {\n return { matches: [] };\n }\n\n throw error;\n }\n\n return {\n matches: stdout\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => {\n const separator = line.indexOf(\":\");\n return {\n line: Number(line.slice(0, separator)),\n content: line.slice(separator + 1),\n };\n }),\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 fs = this.getNative(sandboxName).fs();\n const original = await fs.readString(resolvedPath);\n\n if (!input.search) {\n return { replaced: 0 };\n }\n\n const occurrences = original.split(input.search).length - 1;\n if (occurrences === 0) {\n return { replaced: 0 };\n }\n\n const updated = original.split(input.search).join(input.replace);\n await fs.write(resolvedPath, Buffer.from(updated));\n\n return { replaced: occurrences };\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n await this.getNative(sandboxName).fs().write(resolvedPath, Buffer.from(contentBase64, \"base64\"));\n return { path: resolvedPath };\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const resolvedPath = this.resolvePath(path);\n const data = await this.getNative(sandboxName).fs().read(resolvedPath);\n const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);\n return { path: resolvedPath, contentBase64: buffer.toString(\"base64\") };\n }\n\n async execCommand(input: ShellExecInput): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const output = await this.getNative(input.sandboxName).execWithConfig({\n cmd: \"sh\",\n args: [\"-c\", input.command],\n cwd: input.exec_dir,\n timeoutMs: input.timeout ? input.timeout * 1000 : undefined,\n });\n\n return {\n stdout: output.stdout(),\n stderr: output.stderr(),\n exitCode: output.code ?? 0,\n };\n }\n}\n","import cors from \"@fastify/cors\";\nimport multipart from \"@fastify/multipart\";\nimport sensible from \"@fastify/sensible\";\nimport fastify, { type FastifyInstance } 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 { MicrosandboxRuntimeService } from \"./services/MicrosandboxRuntimeService\";\nimport type { RuntimeService } from \"./types/runtime-service\";\n\nexport function buildApp({\n runtimeService = new MicrosandboxRuntimeService(),\n imageService = new ImageService(),\n apiKey,\n}: {\n runtimeService?: RuntimeService;\n imageService?: ImageService;\n apiKey?: string;\n} = {}): FastifyInstance {\n const app = fastify({\n logger: false,\n bodyLimit: Number(process.env.BODY_LIMIT) || 100 * 1024 * 1024,\n });\n\n 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 app.register(sensible);\n 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\n if (request.headers.authorization !== `Bearer ${apiKey}`) {\n await reply.code(401).send({\n success: false,\n error: {\n code: \"UNAUTHORIZED\",\n message: \"Unauthorized\",\n },\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 return app;\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","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 type EnsureSandboxInput = z.infer<typeof ensureSandboxSchema>;\nexport type ListSandboxesQuery = z.infer<typeof listSandboxesQuerySchema>;\nexport type ShellExecInput = z.infer<typeof shellExecSchema>;\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport {\n downloadFileSchema,\n ensureSandboxSchema,\n findFilesSchema,\n listSandboxesQuerySchema,\n listPathSchema,\n readFileSchema,\n replaceInFileSchema,\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 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 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\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 { Volume } from \"microsandbox\";\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\nconst MSB_DATA_DIR = path.join(os.homedir(), \".microsandbox\");\n\nasync function resolveVolumeHostPath(name: string): Promise<string> {\n // Ensure volume exists and get its host path in one shot.\n // Volume.create() returns a live Volume handle with .path; if the volume\n // already exists the call may succeed (idempotent) or throw — in that case\n // fall back to the standard data directory layout.\n try {\n const vol = await Volume.create({ name });\n return vol.path;\n } catch {\n try {\n await Volume.get(name);\n } catch {\n await Volume.create({ name });\n }\n // Retry after ensuring existence\n try {\n const vol = await Volume.create({ name });\n return vol.path;\n } catch {\n return path.join(MSB_DATA_DIR, \"volumes\", name);\n }\n }\n}\n\nfunction resolveGuestPath(hostRoot: string, guestPath: string): string {\n const normalized = guestPath === \"~\" ? \"\" : guestPath.replace(/^~\\//, \"\");\n const resolved = path.join(hostRoot, path.normalize(normalized).replace(/^(\\.\\.(\\/|\\\\|$))+/, \"\"));\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 = await 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 = await 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 = await 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 = await 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 = await 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 { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { PullImageInput } from \"../schemas/images\";\n\nconst execAsync = promisify(exec);\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\ntype ImageBindings = {\n list(): Promise<ImageRecord[]>;\n pull(ref: string): Promise<ImageRecord>;\n inspect(ref: string): Promise<ImageRecord>;\n remove(ref: string): Promise<void>;\n};\n\ntype CliImageInfo = {\n architecture: string;\n created_at: string;\n digest: string;\n layer_count: number;\n os: string;\n reference: string;\n size_bytes: number;\n};\n\nfunction getMsbPath(): string {\n return process.env.MICROSANDBOX_CLI_PATH || `${process.env.HOME}/.microsandbox/bin/msb`;\n}\n\nclass MicrosandboxImageBindings implements ImageBindings {\n private get msb(): string {\n return getMsbPath();\n }\n\n async list(): Promise<ImageRecord[]> {\n const { stdout } = await execAsync(`${this.msb} image ls --format json`);\n const images: CliImageInfo[] = JSON.parse(stdout);\n return images.map((img) => ({\n ref: img.reference,\n sourceType: \"oci\",\n cached: true,\n size: img.size_bytes,\n createdAt: img.created_at,\n }));\n }\n\n async pull(ref: string): Promise<ImageRecord> {\n await execAsync(`${this.msb} image pull ${ref}`);\n return this.inspect(ref);\n }\n\n async inspect(ref: string): Promise<ImageRecord> {\n const { stdout } = await execAsync(`${this.msb} image inspect ${ref} --format json`);\n const img: CliImageInfo = JSON.parse(stdout);\n return {\n ref: img.reference,\n sourceType: \"oci\",\n cached: true,\n size: img.size_bytes,\n createdAt: img.created_at,\n };\n }\n\n async remove(ref: string): Promise<void> {\n await execAsync(`${this.msb} image rm ${ref}`);\n }\n}\n\nexport class ImageService {\n constructor(\n private readonly deps: {\n bindings?: ImageBindings;\n } = {}\n ) {}\n\n private get bindings(): ImageBindings {\n return this.deps.bindings ?? new MicrosandboxImageBindings();\n }\n\n async listImages(): Promise<{ items: ImageRecord[]; total: number }> {\n const items = await this.bindings.list();\n return { items, total: items.length };\n }\n\n async pullImage(input: PullImageInput): Promise<ImageRecord> {\n return await this.bindings.pull(input.ref);\n }\n\n async getImage(ref: string): Promise<ImageRecord> {\n return await this.bindings.inspect(ref);\n }\n\n async deleteImage(ref: string): Promise<{ ref: string }> {\n await this.bindings.remove(ref);\n return { ref };\n }\n}\n"],"mappings":"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","names":["Sandbox","path","Sandbox","fs","z","Volume","z","z","Volume","z"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildApp
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7FG2JFOQ.mjs";
|
|
4
4
|
|
|
5
5
|
// src/lib/server-cli.ts
|
|
6
6
|
function parsePort(raw, source) {
|
|
@@ -97,4 +97,4 @@ async function startServer({
|
|
|
97
97
|
export {
|
|
98
98
|
startServer
|
|
99
99
|
};
|
|
100
|
-
//# sourceMappingURL=chunk-
|
|
100
|
+
//# sourceMappingURL=chunk-DZXYJERT.mjs.map
|
package/dist/cli.mjs
CHANGED
package/dist/index.mjs
CHANGED
package/dist/server.mjs
CHANGED
package/package.json
CHANGED
|
@@ -483,23 +483,11 @@ describe("MicrosandboxRuntimeService", () => {
|
|
|
483
483
|
});
|
|
484
484
|
|
|
485
485
|
describe("resolvePath", () => {
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
beforeEach(() => {
|
|
489
|
-
jest.resetModules();
|
|
490
|
-
process.env = { ...originalEnv };
|
|
491
|
-
delete process.env.MICROSANDBOX_HOME_DIR;
|
|
492
|
-
});
|
|
493
|
-
|
|
494
|
-
afterEach(() => {
|
|
495
|
-
process.env = originalEnv;
|
|
496
|
-
});
|
|
497
|
-
|
|
498
|
-
it("expands ~/ to /home/daytona/ by default", async () => {
|
|
486
|
+
it("normalizes ~/ to / prefix", async () => {
|
|
499
487
|
const fs = {
|
|
500
488
|
readString: jest.fn().mockResolvedValue("hello"),
|
|
501
489
|
write: jest.fn().mockResolvedValue(undefined),
|
|
502
|
-
list: jest.fn().mockResolvedValue([{ path: "/
|
|
490
|
+
list: jest.fn().mockResolvedValue([{ path: "/file.txt", kind: "file" }]),
|
|
503
491
|
read: jest.fn().mockResolvedValue(Buffer.from("data")),
|
|
504
492
|
};
|
|
505
493
|
const registry = {
|
|
@@ -509,50 +497,31 @@ describe("MicrosandboxRuntimeService", () => {
|
|
|
509
497
|
const service = new MicrosandboxRuntimeService({ registry });
|
|
510
498
|
|
|
511
499
|
await expect(service.readFile("tenant-a", "~/test.txt")).resolves.toEqual({
|
|
512
|
-
path: "/
|
|
500
|
+
path: "/test.txt",
|
|
513
501
|
content: "hello",
|
|
514
502
|
});
|
|
515
|
-
expect(fs.readString).toHaveBeenCalledWith("/
|
|
503
|
+
expect(fs.readString).toHaveBeenCalledWith("/test.txt");
|
|
516
504
|
|
|
517
505
|
await expect(service.writeFile("tenant-a", "~/test.txt", "content")).resolves.toEqual({
|
|
518
|
-
path: "/
|
|
506
|
+
path: "/test.txt",
|
|
519
507
|
});
|
|
520
|
-
expect(fs.write).toHaveBeenCalledWith("/
|
|
508
|
+
expect(fs.write).toHaveBeenCalledWith("/test.txt", Buffer.from("content"));
|
|
521
509
|
|
|
522
510
|
await expect(service.listPath("tenant-a", "~")).resolves.toEqual({
|
|
523
|
-
entries: [{ path: "/
|
|
511
|
+
entries: [{ path: "/file.txt", type: "file" }],
|
|
524
512
|
});
|
|
525
|
-
expect(fs.list).toHaveBeenCalledWith("/
|
|
513
|
+
expect(fs.list).toHaveBeenCalledWith("/");
|
|
526
514
|
|
|
527
515
|
await expect(service.uploadFile("tenant-a", "~/blob.bin", Buffer.from("data").toString("base64"))).resolves.toEqual({
|
|
528
|
-
path: "/
|
|
516
|
+
path: "/blob.bin",
|
|
529
517
|
});
|
|
530
|
-
expect(fs.write).toHaveBeenCalledWith("/
|
|
518
|
+
expect(fs.write).toHaveBeenCalledWith("/blob.bin", Buffer.from("data"));
|
|
531
519
|
|
|
532
520
|
await expect(service.downloadFile("tenant-a", "~/blob.bin")).resolves.toEqual({
|
|
533
|
-
path: "/
|
|
521
|
+
path: "/blob.bin",
|
|
534
522
|
contentBase64: Buffer.from("data").toString("base64"),
|
|
535
523
|
});
|
|
536
|
-
expect(fs.read).toHaveBeenCalledWith("/
|
|
537
|
-
});
|
|
538
|
-
|
|
539
|
-
it("respects MICROSANDBOX_HOME_DIR environment variable", async () => {
|
|
540
|
-
process.env.MICROSANDBOX_HOME_DIR = "/custom/home";
|
|
541
|
-
|
|
542
|
-
const fs = {
|
|
543
|
-
readString: jest.fn().mockResolvedValue("hello"),
|
|
544
|
-
};
|
|
545
|
-
const registry = {
|
|
546
|
-
get: jest.fn().mockReturnValue({ fs: () => fs }),
|
|
547
|
-
} as unknown as SandboxRegistry;
|
|
548
|
-
|
|
549
|
-
const service = new MicrosandboxRuntimeService({ registry });
|
|
550
|
-
|
|
551
|
-
await expect(service.readFile("tenant-a", "~/test.txt")).resolves.toEqual({
|
|
552
|
-
path: "/custom/home/test.txt",
|
|
553
|
-
content: "hello",
|
|
554
|
-
});
|
|
555
|
-
expect(fs.readString).toHaveBeenCalledWith("/custom/home/test.txt");
|
|
524
|
+
expect(fs.read).toHaveBeenCalledWith("/blob.bin");
|
|
556
525
|
});
|
|
557
526
|
|
|
558
527
|
it("does not modify paths that do not start with ~/", async () => {
|
|
@@ -572,9 +541,9 @@ describe("MicrosandboxRuntimeService", () => {
|
|
|
572
541
|
expect(fs.readString).toHaveBeenCalledWith("/tmp/test.txt");
|
|
573
542
|
});
|
|
574
543
|
|
|
575
|
-
it("
|
|
544
|
+
it("normalizes ~/ in findFiles, searchInFile, and replaceInFile", async () => {
|
|
576
545
|
const execOutput = {
|
|
577
|
-
stdout: jest.fn().mockReturnValue("/
|
|
546
|
+
stdout: jest.fn().mockReturnValue("/subdir/match.txt"),
|
|
578
547
|
stderr: jest.fn().mockReturnValue(""),
|
|
579
548
|
code: 0,
|
|
580
549
|
};
|
|
@@ -595,18 +564,18 @@ describe("MicrosandboxRuntimeService", () => {
|
|
|
595
564
|
await service.findFiles("tenant-a", "~", "*.txt");
|
|
596
565
|
expect(execWithConfig).toHaveBeenCalledWith({
|
|
597
566
|
cmd: "find",
|
|
598
|
-
args: ["/
|
|
567
|
+
args: ["/", "-name", "*.txt", "-type", "f"],
|
|
599
568
|
});
|
|
600
569
|
|
|
601
570
|
await service.searchInFile("tenant-a", "~/test.txt", "hello");
|
|
602
571
|
expect(execWithConfig).toHaveBeenCalledWith({
|
|
603
572
|
cmd: "grep",
|
|
604
|
-
args: ["-n", "-E", "hello", "/
|
|
573
|
+
args: ["-n", "-E", "hello", "/test.txt"],
|
|
605
574
|
});
|
|
606
575
|
|
|
607
576
|
await service.replaceInFile("tenant-a", { path: "~/test.txt", search: "hello", replace: "hi" });
|
|
608
|
-
expect(fs.readString).toHaveBeenCalledWith("/
|
|
609
|
-
expect(fs.write).toHaveBeenCalledWith("/
|
|
577
|
+
expect(fs.readString).toHaveBeenCalledWith("/test.txt");
|
|
578
|
+
expect(fs.write).toHaveBeenCalledWith("/test.txt", Buffer.from("hi world"));
|
|
610
579
|
});
|
|
611
580
|
});
|
|
612
581
|
});
|
package/src/app.ts
CHANGED
|
@@ -20,7 +20,10 @@ export function buildApp({
|
|
|
20
20
|
imageService?: ImageService;
|
|
21
21
|
apiKey?: string;
|
|
22
22
|
} = {}): FastifyInstance {
|
|
23
|
-
const app = fastify({
|
|
23
|
+
const app = fastify({
|
|
24
|
+
logger: false,
|
|
25
|
+
bodyLimit: Number(process.env.BODY_LIMIT) || 100 * 1024 * 1024,
|
|
26
|
+
});
|
|
24
27
|
|
|
25
28
|
app.register(cors, {
|
|
26
29
|
delegator: (request, callback) => {
|
|
@@ -73,9 +73,11 @@ export class MicrosandboxRuntimeService {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
private resolvePath(path: string): string {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
if (path === "~" || path === "~/") {
|
|
77
|
+
return "/";
|
|
78
|
+
}
|
|
79
|
+
if (path.startsWith("~/")) {
|
|
80
|
+
return `/${path.slice(2)}`;
|
|
79
81
|
}
|
|
80
82
|
return path;
|
|
81
83
|
}
|
|
@@ -183,17 +185,33 @@ export class MicrosandboxRuntimeService {
|
|
|
183
185
|
}
|
|
184
186
|
|
|
185
187
|
async stopSandbox(name: string): Promise<{ name: string; status: string }> {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
188
|
+
try {
|
|
189
|
+
const native = await this.getOrEnsureNative(name);
|
|
190
|
+
await native.stop();
|
|
191
|
+
this.registry.delete(name);
|
|
192
|
+
return { name, status: "stopped" };
|
|
193
|
+
} catch (error) {
|
|
194
|
+
if (error instanceof Error && error.message.includes("write to relay")) {
|
|
195
|
+
this.registry.delete(name);
|
|
196
|
+
return { name, status: "unknown" };
|
|
197
|
+
}
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
190
200
|
}
|
|
191
201
|
|
|
192
202
|
async killSandbox(name: string): Promise<{ name: string; status: string }> {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
203
|
+
try {
|
|
204
|
+
const native = await this.getOrEnsureNative(name);
|
|
205
|
+
await native.kill();
|
|
206
|
+
this.registry.delete(name);
|
|
207
|
+
return { name, status: "unknown" };
|
|
208
|
+
} catch (error) {
|
|
209
|
+
if (error instanceof Error && error.message.includes("write to relay")) {
|
|
210
|
+
this.registry.delete(name);
|
|
211
|
+
return { name, status: "unknown" };
|
|
212
|
+
}
|
|
213
|
+
throw error;
|
|
214
|
+
}
|
|
197
215
|
}
|
|
198
216
|
|
|
199
217
|
async deleteSandbox(name: string): Promise<{ name: string; status: string }> {
|
|
@@ -203,8 +221,8 @@ export class MicrosandboxRuntimeService {
|
|
|
203
221
|
// Ignore missing cached native handle before remove.
|
|
204
222
|
}
|
|
205
223
|
|
|
206
|
-
await Sandbox.remove(name);
|
|
207
224
|
this.registry.delete(name);
|
|
225
|
+
await Sandbox.remove(name);
|
|
208
226
|
|
|
209
227
|
return { name, status: "unknown" };
|
|
210
228
|
}
|
|
@@ -352,9 +370,11 @@ export class MicrosandboxRuntimeService {
|
|
|
352
370
|
|
|
353
371
|
async findFiles(sandboxName: string, path: string, pattern: string): Promise<{ files: string[] }> {
|
|
354
372
|
const resolvedPath = this.resolvePath(path);
|
|
373
|
+
// Use -path for patterns containing / (e.g., "**/*.py"), -name for filename-only patterns (e.g., "*.py")
|
|
374
|
+
const matchFlag = pattern.includes("/") ? "-path" : "-name";
|
|
355
375
|
const output = await this.getNative(sandboxName).execWithConfig({
|
|
356
376
|
cmd: "find",
|
|
357
|
-
args: [resolvedPath,
|
|
377
|
+
args: [resolvedPath, matchFlag, pattern, "-type", "f"],
|
|
358
378
|
});
|
|
359
379
|
return { files: output.stdout().split("\n").filter(Boolean) };
|
|
360
380
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/services/SandboxRegistry.ts","../src/services/MicrosandboxRuntimeService.ts","../src/app.ts","../src/lib/errors.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"],"sourcesContent":["import { Sandbox, Mount } from \"microsandbox\";\nimport type { SandboxHandle } from \"microsandbox\";\n\nconst DEFAULT_IMAGE = process.env.MICROSANDBOX_IMAGE ?? \"daytonaio/sandbox:0.6.0\";\n\nexport class SandboxRegistry {\n private handles = new Map<string, unknown>();\n private creating = new Map<string, Promise<unknown>>();\n\n async ensure(name: string, createOptions?: Record<string, unknown>): Promise<unknown> {\n const cached = this.handles.get(name);\n if (cached) {\n return cached;\n }\n\n const inflight = this.creating.get(name);\n if (inflight) {\n return inflight;\n }\n\n const creation = (async () => {\n let native: unknown;\n const image = (createOptions?.image as string) ?? DEFAULT_IMAGE;\n const cpus = (createOptions?.cpus as number) ?? 1;\n const memoryMib = (createOptions?.memoryMib as number) ?? 512;\n const env = (createOptions?.env as Record<string, string>) ?? undefined;\n\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n\n if (handle.status === \"running\") {\n native = await handle.connect();\n } else if (handle.status === \"stopped\") {\n native = await Sandbox.start(name);\n } else if (handle.status === \"crashed\" || handle.status === \"draining\") {\n await Sandbox.remove(name);\n } else {\n await Sandbox.remove(name);\n }\n } catch {\n native = undefined;\n }\n\n if (!native) {\n const volumeDefs = createOptions?.volumes as Record<string, { type: string; source?: string; name?: string; sizeMib?: number; readonly?: boolean }> | undefined;\n const volumes: Record<string, ReturnType<typeof Mount.bind>> = {};\n if (volumeDefs) {\n for (const [guestPath, def] of Object.entries(volumeDefs)) {\n const mountOpts = def.readonly ? { readonly: true } : undefined;\n if (def.type === \"bind\" && def.source) {\n volumes[guestPath] = Mount.bind(def.source, mountOpts);\n } else if (def.type === \"named\" && def.name) {\n volumes[guestPath] = Mount.named(def.name, mountOpts);\n } else if (def.type === \"tmpfs\") {\n volumes[guestPath] = Mount.tmpfs(def.sizeMib ? { sizeMib: def.sizeMib, ...mountOpts } : mountOpts);\n }\n }\n }\n try {\n native = await Sandbox.createDetached({\n name,\n image,\n cpus,\n memoryMib,\n env,\n volumes,\n });\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"already exists\")) {\n await Sandbox.remove(name);\n native = await Sandbox.createDetached({\n name,\n image,\n cpus,\n memoryMib,\n env,\n volumes,\n });\n } else {\n throw err;\n }\n }\n }\n\n this.handles.set(name, native);\n return native;\n })();\n\n this.creating.set(name, creation);\n void creation.finally(() => this.creating.delete(name));\n\n return creation;\n }\n\n get(name: string): unknown {\n const handle = this.handles.get(name);\n\n if (!handle) {\n throw new Error(`Sandbox ${name} not found`);\n }\n\n return handle;\n }\n\n delete(name: string): void {\n this.handles.delete(name);\n }\n}\n","import { Sandbox, Volume } from \"microsandbox\";\nimport type { SandboxHandle, SandboxInfo } from \"microsandbox\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport type { SandboxRuntimeMetrics } from \"../types/runtime-service\";\nimport { SandboxRegistry } from \"./SandboxRegistry\";\n\ntype VolumeConfig = NonNullable<EnsureSandboxInput[\"volumes\"]>[string];\n\ntype RuntimeNative = {\n fs(): {\n readString(path: string): Promise<string>;\n write(path: string, data: Buffer): Promise<void>;\n list(path: string): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;\n read(path: string): Promise<Buffer | Uint8Array | string>;\n };\n execWithConfig(config: { cmd: string; args?: string[]; cwd?: string; timeoutMs?: number }): Promise<{\n stdout(): string;\n stderr(): string;\n code?: number;\n }>;\n stop(): Promise<void>;\n kill(): Promise<void>;\n};\n\ntype SandboxConfig = {\n name: string;\n image: string;\n memoryMib?: number;\n cpus?: number;\n env?: Record<string, string>;\n volumes?: Record<string, unknown>;\n};\n\nfunction parseEnvArray(env: unknown): Record<string, string> {\n if (!Array.isArray(env)) return env as Record<string, string>;\n const result: Record<string, string> = {};\n for (const entry of env) {\n if (typeof entry !== \"string\") continue;\n const eq = entry.indexOf(\"=\");\n if (eq < 0) continue;\n result[entry.slice(0, eq)] = entry.slice(eq + 1);\n }\n return result;\n}\n\nfunction parseConfigJson(configJson: string): SandboxConfig {\n try {\n const raw = JSON.parse(configJson);\n return {\n name: raw.name ?? \"\",\n image: raw.image ?? \"\",\n memoryMib: raw.memoryMib ?? raw.memory_mib,\n cpus: raw.cpus,\n env: raw.env != null ? parseEnvArray(raw.env) : undefined,\n volumes: raw.volumes,\n };\n } catch {\n return { name: \"\", image: \"\" };\n }\n}\n\nfunction msToIsoString(ms: number | Date | null | undefined): string {\n if (ms == null) return \"\";\n if (ms instanceof Date) return ms.toISOString();\n return new Date(ms).toISOString();\n}\n\nexport class MicrosandboxRuntimeService {\n constructor(private deps: { registry?: SandboxRegistry } = {}) {}\n\n private get registry(): SandboxRegistry {\n return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());\n }\n\n private resolvePath(path: string): string {\n const homeDir = process.env.MICROSANDBOX_HOME_DIR ?? \"/home/daytona\";\n if (path === \"~\" || path.startsWith(\"~/\")) {\n return `${homeDir}${path === \"~\" ? \"\" : \"/\" + path.slice(2)}`;\n }\n return path;\n }\n\n private toListItem(info: {\n name: string;\n status: string;\n configJson: string;\n createdAt?: number | Date | null;\n updatedAt?: number | Date | null;\n }): {\n name: string;\n status: string;\n image?: string;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n } {\n const config = parseConfigJson(info.configJson);\n const env = config.env ?? {};\n const volumes = config.volumes ?? {};\n\n return {\n name: info.name,\n status: info.status,\n image: config.image,\n cpus: config.cpus,\n memoryMib: config.memoryMib,\n envCount: Object.keys(env).length,\n volumeCount: Object.keys(volumes).length,\n createdAt: msToIsoString(info.createdAt),\n updatedAt: msToIsoString(info.updatedAt),\n };\n }\n\n private async ensureNamedVolumes(volumes?: EnsureSandboxInput[\"volumes\"]): Promise<void> {\n if (!volumes) {\n return;\n }\n\n const defaultQuotaMib = Number(process.env.MICROSANDBOX_VOLUME_QUOTA_MIB ?? \"1024\");\n\n const namedVolumes = Object.values(volumes).filter(\n (v): v is Extract<VolumeConfig, { type: \"named\" }> => v.type === \"named\"\n );\n\n await Promise.all(\n namedVolumes.map(async (definition) => {\n try {\n await Volume.get(definition.name);\n } catch {\n await Volume.create({ name: definition.name, quotaMib: defaultQuotaMib });\n }\n })\n );\n }\n\n private getNative(name: string): RuntimeNative {\n return this.registry.get(name) as RuntimeNative;\n }\n\n private async getOrEnsureNative(name: string): Promise<RuntimeNative> {\n try {\n return this.getNative(name);\n } catch {\n return (await this.registry.ensure(name)) as RuntimeNative;\n }\n }\n\n async ensureSandbox(\n name: string,\n input: EnsureSandboxInput\n ): Promise<{\n name: string;\n status: string;\n }> {\n const image = input.image ?? process.env.MICROSANDBOX_IMAGE ?? \"python:3.11-slim\";\n const cpus = input.cpus ?? Number(process.env.MICROSANDBOX_CPUS ?? \"1\");\n const memoryMib = input.memoryMib ?? Number(process.env.MICROSANDBOX_MEMORY ?? \"512\");\n\n await this.ensureNamedVolumes(input.volumes);\n\n await this.registry.ensure(name, {\n image,\n cpus,\n memoryMib,\n env: input.env,\n volumes: input.volumes,\n });\n\n return {\n name,\n status: \"running\",\n };\n }\n\n async startSandbox(name: string): Promise<{ name: string; status: string }> {\n await Sandbox.start(name);\n this.registry.delete(name);\n await this.registry.ensure(name);\n return { name, status: \"running\" };\n }\n\n async stopSandbox(name: string): Promise<{ name: string; status: string }> {\n const native = await this.getOrEnsureNative(name);\n await native.stop();\n this.registry.delete(name);\n return { name, status: \"stopped\" };\n }\n\n async killSandbox(name: string): Promise<{ name: string; status: string }> {\n const native = await this.getOrEnsureNative(name);\n await native.kill();\n this.registry.delete(name);\n return { name, status: \"unknown\" };\n }\n\n async deleteSandbox(name: string): Promise<{ name: string; status: string }> {\n try {\n await this.getNative(name).kill();\n } catch {\n // Ignore missing cached native handle before remove.\n }\n\n await Sandbox.remove(name);\n this.registry.delete(name);\n\n return { name, status: \"unknown\" };\n }\n\n async listSandboxes(_query: ListSandboxesQuery): Promise<{\n items: Array<{\n name: string;\n status: string;\n image?: string;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n }>;\n total: number;\n }> {\n const all: SandboxInfo[] = await Sandbox.list();\n\n const items = all\n .map((info) =>\n this.toListItem({\n name: info.name,\n status: info.status,\n configJson: info.configJson,\n createdAt: info.createdAt,\n updatedAt: info.updatedAt,\n })\n )\n .filter((item) => {\n if (_query.status && item.status !== _query.status) {\n return false;\n }\n\n if (_query.image && item.image !== _query.image) {\n return false;\n }\n\n if (_query.search) {\n const haystack = [item.name, item.image]\n .filter((value): value is string => Boolean(value))\n .join(\" \")\n .toLowerCase();\n\n if (!haystack.includes(_query.search.toLowerCase())) {\n return false;\n }\n }\n\n return true;\n });\n\n return { items, total: items.length };\n }\n\n async getSandbox(\n name: string\n ): Promise<{\n name: string;\n status: string;\n image?: string;\n cpus?: number;\n memoryMib?: number;\n env: Record<string, string>;\n volumes: Record<string, unknown>;\n metrics?: SandboxRuntimeMetrics;\n createdAt: string;\n updatedAt: string;\n } | undefined> {\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n const config = parseConfigJson(handle.configJson);\n let metrics: SandboxRuntimeMetrics | undefined;\n\n try {\n const m = await handle.metrics();\n metrics = {\n cpuPercent: m.cpuPercent,\n memoryBytes: m.memoryBytes,\n memoryLimitBytes: m.memoryLimitBytes,\n diskReadBytes: m.diskReadBytes,\n diskWriteBytes: m.diskWriteBytes,\n netRxBytes: m.netRxBytes,\n netTxBytes: m.netTxBytes,\n uptimeMs: m.uptimeMs,\n timestampMs: m.timestampMs,\n };\n } catch {\n metrics = undefined;\n }\n\n return {\n name: handle.name,\n status: handle.status,\n image: config.image,\n cpus: config.cpus,\n memoryMib: config.memoryMib,\n env: config.env ?? {},\n volumes: config.volumes ?? {},\n metrics,\n createdAt: msToIsoString(handle.createdAt),\n updatedAt: msToIsoString(handle.updatedAt),\n };\n } catch {\n return undefined;\n }\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n return { name, status: handle.status };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const resolvedPath = this.resolvePath(path);\n const content = await this.getNative(sandboxName).fs().readString(resolvedPath);\n return { path: resolvedPath, content };\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n await this.getNative(sandboxName).fs().write(resolvedPath, Buffer.from(content));\n return { path: resolvedPath };\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 entries = await this.getNative(sandboxName).fs().list(resolvedPath);\n return {\n entries: entries.map((entry) => ({\n path: entry.path,\n type: entry.kind,\n })),\n };\n }\n\n async findFiles(sandboxName: string, path: string, pattern: string): Promise<{ files: string[] }> {\n const resolvedPath = this.resolvePath(path);\n const output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"find\",\n args: [resolvedPath, \"-name\", pattern, \"-type\", \"f\"],\n });\n return { files: output.stdout().split(\"\\n\").filter(Boolean) };\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 let stdout: string;\n\n try {\n const output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"grep\",\n args: [\"-n\", \"-E\", query, resolvedPath],\n });\n stdout = output.stdout();\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === 1) {\n return { matches: [] };\n }\n\n throw error;\n }\n\n return {\n matches: stdout\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => {\n const separator = line.indexOf(\":\");\n return {\n line: Number(line.slice(0, separator)),\n content: line.slice(separator + 1),\n };\n }),\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 fs = this.getNative(sandboxName).fs();\n const original = await fs.readString(resolvedPath);\n\n if (!input.search) {\n return { replaced: 0 };\n }\n\n const occurrences = original.split(input.search).length - 1;\n if (occurrences === 0) {\n return { replaced: 0 };\n }\n\n const updated = original.split(input.search).join(input.replace);\n await fs.write(resolvedPath, Buffer.from(updated));\n\n return { replaced: occurrences };\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n await this.getNative(sandboxName).fs().write(resolvedPath, Buffer.from(contentBase64, \"base64\"));\n return { path: resolvedPath };\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const resolvedPath = this.resolvePath(path);\n const data = await this.getNative(sandboxName).fs().read(resolvedPath);\n const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);\n return { path: resolvedPath, contentBase64: buffer.toString(\"base64\") };\n }\n\n async execCommand(input: ShellExecInput): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const output = await this.getNative(input.sandboxName).execWithConfig({\n cmd: \"sh\",\n args: [\"-c\", input.command],\n cwd: input.exec_dir,\n timeoutMs: input.timeout ? input.timeout * 1000 : undefined,\n });\n\n return {\n stdout: output.stdout(),\n stderr: output.stderr(),\n exitCode: output.code ?? 0,\n };\n }\n}\n","import cors from \"@fastify/cors\";\nimport multipart from \"@fastify/multipart\";\nimport sensible from \"@fastify/sensible\";\nimport fastify, { type FastifyInstance } 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 { MicrosandboxRuntimeService } from \"./services/MicrosandboxRuntimeService\";\nimport type { RuntimeService } from \"./types/runtime-service\";\n\nexport function buildApp({\n runtimeService = new MicrosandboxRuntimeService(),\n imageService = new ImageService(),\n apiKey,\n}: {\n runtimeService?: RuntimeService;\n imageService?: ImageService;\n apiKey?: string;\n} = {}): FastifyInstance {\n const app = fastify({ logger: false });\n\n 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 app.register(sensible);\n 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\n if (request.headers.authorization !== `Bearer ${apiKey}`) {\n await reply.code(401).send({\n success: false,\n error: {\n code: \"UNAUTHORIZED\",\n message: \"Unauthorized\",\n },\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 return app;\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","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 type EnsureSandboxInput = z.infer<typeof ensureSandboxSchema>;\nexport type ListSandboxesQuery = z.infer<typeof listSandboxesQuerySchema>;\nexport type ShellExecInput = z.infer<typeof shellExecSchema>;\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport {\n downloadFileSchema,\n ensureSandboxSchema,\n findFilesSchema,\n listSandboxesQuerySchema,\n listPathSchema,\n readFileSchema,\n replaceInFileSchema,\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 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 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\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 { Volume } from \"microsandbox\";\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\nconst MSB_DATA_DIR = path.join(os.homedir(), \".microsandbox\");\n\nasync function resolveVolumeHostPath(name: string): Promise<string> {\n // Ensure volume exists and get its host path in one shot.\n // Volume.create() returns a live Volume handle with .path; if the volume\n // already exists the call may succeed (idempotent) or throw — in that case\n // fall back to the standard data directory layout.\n try {\n const vol = await Volume.create({ name });\n return vol.path;\n } catch {\n try {\n await Volume.get(name);\n } catch {\n await Volume.create({ name });\n }\n // Retry after ensuring existence\n try {\n const vol = await Volume.create({ name });\n return vol.path;\n } catch {\n return path.join(MSB_DATA_DIR, \"volumes\", name);\n }\n }\n}\n\nfunction resolveGuestPath(hostRoot: string, guestPath: string): string {\n const normalized = guestPath === \"~\" ? \"\" : guestPath.replace(/^~\\//, \"\");\n const resolved = path.join(hostRoot, path.normalize(normalized).replace(/^(\\.\\.(\\/|\\\\|$))+/, \"\"));\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 = await 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 = await 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 = await 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 = await 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 = await 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 { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { PullImageInput } from \"../schemas/images\";\n\nconst execAsync = promisify(exec);\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\ntype ImageBindings = {\n list(): Promise<ImageRecord[]>;\n pull(ref: string): Promise<ImageRecord>;\n inspect(ref: string): Promise<ImageRecord>;\n remove(ref: string): Promise<void>;\n};\n\ntype CliImageInfo = {\n architecture: string;\n created_at: string;\n digest: string;\n layer_count: number;\n os: string;\n reference: string;\n size_bytes: number;\n};\n\nfunction getMsbPath(): string {\n return process.env.MICROSANDBOX_CLI_PATH || `${process.env.HOME}/.microsandbox/bin/msb`;\n}\n\nclass MicrosandboxImageBindings implements ImageBindings {\n private get msb(): string {\n return getMsbPath();\n }\n\n async list(): Promise<ImageRecord[]> {\n const { stdout } = await execAsync(`${this.msb} image ls --format json`);\n const images: CliImageInfo[] = JSON.parse(stdout);\n return images.map((img) => ({\n ref: img.reference,\n sourceType: \"oci\",\n cached: true,\n size: img.size_bytes,\n createdAt: img.created_at,\n }));\n }\n\n async pull(ref: string): Promise<ImageRecord> {\n await execAsync(`${this.msb} image pull ${ref}`);\n return this.inspect(ref);\n }\n\n async inspect(ref: string): Promise<ImageRecord> {\n const { stdout } = await execAsync(`${this.msb} image inspect ${ref} --format json`);\n const img: CliImageInfo = JSON.parse(stdout);\n return {\n ref: img.reference,\n sourceType: \"oci\",\n cached: true,\n size: img.size_bytes,\n createdAt: img.created_at,\n };\n }\n\n async remove(ref: string): Promise<void> {\n await execAsync(`${this.msb} image rm ${ref}`);\n }\n}\n\nexport class ImageService {\n constructor(\n private readonly deps: {\n bindings?: ImageBindings;\n } = {}\n ) {}\n\n private get bindings(): ImageBindings {\n return this.deps.bindings ?? new MicrosandboxImageBindings();\n }\n\n async listImages(): Promise<{ items: ImageRecord[]; total: number }> {\n const items = await this.bindings.list();\n return { items, total: items.length };\n }\n\n async pullImage(input: PullImageInput): Promise<ImageRecord> {\n return await this.bindings.pull(input.ref);\n }\n\n async getImage(ref: string): Promise<ImageRecord> {\n return await this.bindings.inspect(ref);\n }\n\n async deleteImage(ref: string): Promise<{ ref: string }> {\n await this.bindings.remove(ref);\n return { ref };\n }\n}\n"],"mappings":"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","names":["Sandbox","path","Sandbox","fs","z","Volume","z","z","Volume","z"]}
|
|
File without changes
|