@axiom-lattice/microsandbox-service 0.0.2 → 0.0.3

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @axiom-lattice/microsandbox-service@0.0.2 build /home/runner/work/agentic/agentic/packages/microsandbox-service
2
+ > @axiom-lattice/microsandbox-service@0.0.3 build /home/runner/work/agentic/agentic/packages/microsandbox-service
3
3
  > tsup src/index.ts src/server.ts src/cli.ts --format cjs,esm --dts --clean --sourcemap
4
4
 
5
5
  CLI Building entry: src/cli.ts, src/index.ts, src/server.ts
@@ -9,26 +9,26 @@
9
9
  CLI Cleaning output folder
10
10
  CJS Build start
11
11
  ESM Build start
12
+ CJS dist/cli.js 25.40 KB
13
+ CJS dist/index.js 24.26 KB
14
+ CJS dist/server.js 25.71 KB
15
+ CJS dist/cli.js.map 53.23 KB
16
+ CJS dist/index.js.map 49.47 KB
17
+ CJS dist/server.js.map 52.95 KB
18
+ CJS ⚡️ Build success in 174ms
12
19
  ESM dist/cli.mjs 277.00 B
13
20
  ESM dist/index.mjs 206.00 B
14
21
  ESM dist/server.mjs 146.00 B
15
- ESM dist/chunk-CSOLG3XA.mjs 1.89 KB
16
- ESM dist/chunk-D5L33FAA.mjs 21.70 KB
17
- ESM dist/index.mjs.map 71.00 B
22
+ ESM dist/chunk-KRXZP6OH.mjs 1.71 KB
23
+ ESM dist/chunk-VM3OJT5V.mjs 21.33 KB
18
24
  ESM dist/cli.mjs.map 389.00 B
25
+ ESM dist/index.mjs.map 71.00 B
19
26
  ESM dist/server.mjs.map 71.00 B
20
- ESM dist/chunk-CSOLG3XA.mjs.map 4.06 KB
21
- ESM dist/chunk-D5L33FAA.mjs.map 48.91 KB
22
- ESM ⚡️ Build success in 152ms
23
- CJS dist/cli.js 25.56 KB
24
- CJS dist/index.js 24.26 KB
25
- CJS dist/server.js 25.88 KB
26
- CJS dist/cli.js.map 53.53 KB
27
- CJS dist/index.js.map 49.47 KB
28
- CJS dist/server.js.map 53.25 KB
29
- CJS ⚡️ Build success in 163ms
27
+ ESM dist/chunk-KRXZP6OH.mjs.map 3.76 KB
28
+ ESM dist/chunk-VM3OJT5V.mjs.map 48.91 KB
29
+ ESM ⚡️ Build success in 177ms
30
30
  DTS Build start
31
- DTS ⚡️ Build success in 18685ms
31
+ DTS ⚡️ Build success in 21471ms
32
32
  DTS dist/cli.d.ts 20.00 B
33
33
  DTS dist/server.d.ts 281.00 B
34
34
  DTS dist/index.d.ts 10.21 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @axiom-lattice/microsandbox-service
2
2
 
3
+ ## 0.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - fb974b7: fix sandbox service
8
+
3
9
  ## 0.0.2
4
10
 
5
11
  ### Patch Changes
@@ -1,7 +1,6 @@
1
1
  import {
2
- __require,
3
2
  buildApp
4
- } from "./chunk-D5L33FAA.mjs";
3
+ } from "./chunk-VM3OJT5V.mjs";
5
4
 
6
5
  // src/lib/server-cli.ts
7
6
  function parsePort(raw, source) {
@@ -70,14 +69,8 @@ async function startServer({
70
69
  await app.listen({ port: config.port, host: config.host });
71
70
  return app;
72
71
  }
73
- if (__require.main === module) {
74
- void startServer().catch((error) => {
75
- console.error("Failed to start microsandbox-service", error);
76
- process.exit(1);
77
- });
78
- }
79
72
 
80
73
  export {
81
74
  startServer
82
75
  };
83
- //# sourceMappingURL=chunk-CSOLG3XA.mjs.map
76
+ //# sourceMappingURL=chunk-KRXZP6OH.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/server-cli.ts","../src/server.ts"],"sourcesContent":["export interface ParsedServerArgs {\n host?: string;\n port?: number;\n}\n\nexport interface ResolvedServerConfig {\n host: string;\n port: number;\n}\n\nfunction parsePort(raw: string, source: string): number {\n const value = Number(raw);\n if (!Number.isInteger(value) || value <= 0) {\n throw new Error(`Invalid value for ${source}: ${raw}`);\n }\n return value;\n}\n\nexport function parseServerArgs(argv: string[]): ParsedServerArgs {\n const parsed: ParsedServerArgs = {};\n\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index];\n\n if (token === \"--port\") {\n const raw = argv[index + 1];\n if (!raw) {\n throw new Error(\"Missing value for --port\");\n }\n parsed.port = parsePort(raw, \"--port\");\n index += 1;\n continue;\n }\n\n if (token === \"--host\") {\n const raw = argv[index + 1];\n if (!raw) {\n throw new Error(\"Missing value for --host\");\n }\n parsed.host = raw;\n index += 1;\n }\n }\n\n return parsed;\n}\n\nexport function resolveServerConfig({\n args,\n env,\n}: {\n args: ParsedServerArgs;\n env: NodeJS.ProcessEnv;\n}): ResolvedServerConfig {\n return {\n host: args.host ?? env.HOST ?? \"0.0.0.0\",\n port: args.port ?? (env.PORT ? parsePort(env.PORT, \"PORT\") : 4002),\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { buildApp } from \"./app\";\nimport { parseServerArgs, resolveServerConfig } from \"./lib/server-cli\";\n\nexport async function startServer({\n argv = process.argv.slice(2),\n env = process.env,\n app = buildApp(),\n}: {\n argv?: string[];\n env?: NodeJS.ProcessEnv;\n app?: Pick<FastifyInstance, \"listen\" | \"close\">;\n} = {}): Promise<Pick<FastifyInstance, \"listen\" | \"close\">> {\n const config = resolveServerConfig({ args: parseServerArgs(argv), env });\n\n const shutdown = async (code: number): Promise<void> => {\n try {\n await app.close();\n process.exit(code);\n } catch (error) {\n console.error(\"Failed to shutdown microsandbox-service cleanly\", error);\n process.exit(1);\n }\n };\n\n process.once(\"SIGINT\", () => {\n void shutdown(0);\n });\n\n process.once(\"SIGTERM\", () => {\n void shutdown(0);\n });\n\n await app.listen({ port: config.port, host: config.host });\n return app;\n}\n\nif (require.main === module) {\n void startServer().catch((error) => {\n console.error(\"Failed to start microsandbox-service\", error);\n process.exit(1);\n });\n}\n"],"mappings":";;;;;;AAUA,SAAS,UAAU,KAAa,QAAwB;AACtD,QAAM,QAAQ,OAAO,GAAG;AACxB,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,SAAS,GAAG;AAC1C,UAAM,IAAI,MAAM,qBAAqB,MAAM,KAAK,GAAG,EAAE;AAAA,EACvD;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,MAAkC;AAChE,QAAM,SAA2B,CAAC;AAElC,WAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;AACnD,UAAM,QAAQ,KAAK,KAAK;AAExB,QAAI,UAAU,UAAU;AACtB,YAAM,MAAM,KAAK,QAAQ,CAAC;AAC1B,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC5C;AACA,aAAO,OAAO,UAAU,KAAK,QAAQ;AACrC,eAAS;AACT;AAAA,IACF;AAEA,QAAI,UAAU,UAAU;AACtB,YAAM,MAAM,KAAK,QAAQ,CAAC;AAC1B,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC5C;AACA,aAAO,OAAO;AACd,eAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AACF,GAGyB;AACvB,SAAO;AAAA,IACL,MAAM,KAAK,QAAQ,IAAI,QAAQ;AAAA,IAC/B,MAAM,KAAK,SAAS,IAAI,OAAO,UAAU,IAAI,MAAM,MAAM,IAAI;AAAA,EAC/D;AACF;;;ACtDA,eAAsB,YAAY;AAAA,EAChC,OAAO,QAAQ,KAAK,MAAM,CAAC;AAAA,EAC3B,MAAM,QAAQ;AAAA,EACd,MAAM,SAAS;AACjB,IAII,CAAC,GAAuD;AAC1D,QAAM,SAAS,oBAAoB,EAAE,MAAM,gBAAgB,IAAI,GAAG,IAAI,CAAC;AAEvE,QAAM,WAAW,OAAO,SAAgC;AACtD,QAAI;AACF,YAAM,IAAI,MAAM;AAChB,cAAQ,KAAK,IAAI;AAAA,IACnB,SAAS,OAAO;AACd,cAAQ,MAAM,mDAAmD,KAAK;AACtE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,UAAQ,KAAK,UAAU,MAAM;AAC3B,SAAK,SAAS,CAAC;AAAA,EACjB,CAAC;AAED,UAAQ,KAAK,WAAW,MAAM;AAC5B,SAAK,SAAS,CAAC;AAAA,EACjB,CAAC;AAED,QAAM,IAAI,OAAO,EAAE,MAAM,OAAO,MAAM,MAAM,OAAO,KAAK,CAAC;AACzD,SAAO;AACT;AAEA,IAAI,UAAQ,SAAS,QAAQ;AAC3B,OAAK,YAAY,EAAE,MAAM,CAAC,UAAU;AAClC,YAAQ,MAAM,wCAAwC,KAAK;AAC3D,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;","names":[]}
1
+ {"version":3,"sources":["../src/lib/server-cli.ts","../src/server.ts"],"sourcesContent":["export interface ParsedServerArgs {\n host?: string;\n port?: number;\n}\n\nexport interface ResolvedServerConfig {\n host: string;\n port: number;\n}\n\nfunction parsePort(raw: string, source: string): number {\n const value = Number(raw);\n if (!Number.isInteger(value) || value <= 0) {\n throw new Error(`Invalid value for ${source}: ${raw}`);\n }\n return value;\n}\n\nexport function parseServerArgs(argv: string[]): ParsedServerArgs {\n const parsed: ParsedServerArgs = {};\n\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index];\n\n if (token === \"--port\") {\n const raw = argv[index + 1];\n if (!raw) {\n throw new Error(\"Missing value for --port\");\n }\n parsed.port = parsePort(raw, \"--port\");\n index += 1;\n continue;\n }\n\n if (token === \"--host\") {\n const raw = argv[index + 1];\n if (!raw) {\n throw new Error(\"Missing value for --host\");\n }\n parsed.host = raw;\n index += 1;\n }\n }\n\n return parsed;\n}\n\nexport function resolveServerConfig({\n args,\n env,\n}: {\n args: ParsedServerArgs;\n env: NodeJS.ProcessEnv;\n}): ResolvedServerConfig {\n return {\n host: args.host ?? env.HOST ?? \"0.0.0.0\",\n port: args.port ?? (env.PORT ? parsePort(env.PORT, \"PORT\") : 4002),\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { buildApp } from \"./app\";\nimport { parseServerArgs, resolveServerConfig } from \"./lib/server-cli\";\n\nexport async function startServer({\n argv = process.argv.slice(2),\n env = process.env,\n app = buildApp(),\n}: {\n argv?: string[];\n env?: NodeJS.ProcessEnv;\n app?: Pick<FastifyInstance, \"listen\" | \"close\">;\n} = {}): Promise<Pick<FastifyInstance, \"listen\" | \"close\">> {\n const config = resolveServerConfig({ args: parseServerArgs(argv), env });\n\n const shutdown = async (code: number): Promise<void> => {\n try {\n await app.close();\n process.exit(code);\n } catch (error) {\n console.error(\"Failed to shutdown microsandbox-service cleanly\", error);\n process.exit(1);\n }\n };\n\n process.once(\"SIGINT\", () => {\n void shutdown(0);\n });\n\n process.once(\"SIGTERM\", () => {\n void shutdown(0);\n });\n\n await app.listen({ port: config.port, host: config.host });\n return app;\n}\n"],"mappings":";;;;;AAUA,SAAS,UAAU,KAAa,QAAwB;AACtD,QAAM,QAAQ,OAAO,GAAG;AACxB,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,SAAS,GAAG;AAC1C,UAAM,IAAI,MAAM,qBAAqB,MAAM,KAAK,GAAG,EAAE;AAAA,EACvD;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,MAAkC;AAChE,QAAM,SAA2B,CAAC;AAElC,WAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;AACnD,UAAM,QAAQ,KAAK,KAAK;AAExB,QAAI,UAAU,UAAU;AACtB,YAAM,MAAM,KAAK,QAAQ,CAAC;AAC1B,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC5C;AACA,aAAO,OAAO,UAAU,KAAK,QAAQ;AACrC,eAAS;AACT;AAAA,IACF;AAEA,QAAI,UAAU,UAAU;AACtB,YAAM,MAAM,KAAK,QAAQ,CAAC;AAC1B,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC5C;AACA,aAAO,OAAO;AACd,eAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AACF,GAGyB;AACvB,SAAO;AAAA,IACL,MAAM,KAAK,QAAQ,IAAI,QAAQ;AAAA,IAC/B,MAAM,KAAK,SAAS,IAAI,OAAO,UAAU,IAAI,MAAM,MAAM,IAAI;AAAA,EAC/D;AACF;;;ACtDA,eAAsB,YAAY;AAAA,EAChC,OAAO,QAAQ,KAAK,MAAM,CAAC;AAAA,EAC3B,MAAM,QAAQ;AAAA,EACd,MAAM,SAAS;AACjB,IAII,CAAC,GAAuD;AAC1D,QAAM,SAAS,oBAAoB,EAAE,MAAM,gBAAgB,IAAI,GAAG,IAAI,CAAC;AAEvE,QAAM,WAAW,OAAO,SAAgC;AACtD,QAAI;AACF,YAAM,IAAI,MAAM;AAChB,cAAQ,KAAK,IAAI;AAAA,IACnB,SAAS,OAAO;AACd,cAAQ,MAAM,mDAAmD,KAAK;AACtE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,UAAQ,KAAK,UAAU,MAAM;AAC3B,SAAK,SAAS,CAAC;AAAA,EACjB,CAAC;AAED,UAAQ,KAAK,WAAW,MAAM;AAC5B,SAAK,SAAS,CAAC;AAAA,EACjB,CAAC;AAED,QAAM,IAAI,OAAO,EAAE,MAAM,OAAO,MAAM,MAAM,OAAO,KAAK,CAAC;AACzD,SAAO;AACT;","names":[]}
@@ -1,10 +1,3 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
1
  // src/services/SandboxRegistry.ts
9
2
  import { Sandbox } from "microsandbox";
10
3
  var DEFAULT_IMAGE = process.env.MICROSANDBOX_IMAGE ?? "daytonaio/sandbox:0.6.0";
@@ -680,9 +673,8 @@ function buildApp({
680
673
  }
681
674
 
682
675
  export {
683
- __require,
684
676
  SandboxRegistry,
685
677
  MicrosandboxRuntimeService,
686
678
  buildApp
687
679
  };
688
- //# sourceMappingURL=chunk-D5L33FAA.mjs.map
680
+ //# sourceMappingURL=chunk-VM3OJT5V.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/services/SandboxRegistry.ts","../src/services/MicrosandboxRuntimeService.ts","../src/services/SandboxMetadataStore.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/services/ImageService.ts"],"sourcesContent":["import { Sandbox } 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 createConfig = {\n name,\n image: DEFAULT_IMAGE,\n ...(createOptions ?? {}),\n };\n\n try {\n const handle = 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 }\n } catch {\n native = undefined;\n }\n\n if (!native) {\n native = await Sandbox.createDetached(createConfig);\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 { Mount, Sandbox } from \"microsandbox\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport { SandboxRegistry } from \"./SandboxRegistry\";\nimport {\n SandboxMetadataStore,\n type SandboxMetadataRecord,\n type SandboxMetadataStoreLike,\n} from \"./SandboxMetadataStore\";\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(\n path: string,\n options?: { recursive?: boolean }\n ): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;\n read(path: string): Promise<Buffer | Uint8Array | string>;\n };\n execWithConfig(config: {\n cmd: string;\n args?: string[];\n cwd?: string;\n timeoutMs?: number;\n }): Promise<{\n stdout(): string;\n stderr?(): string;\n code?: number;\n }>;\n stop(): Promise<void>;\n kill(): Promise<void>;\n};\n\nexport class MicrosandboxRuntimeService {\n constructor(private deps: { registry?: SandboxRegistry; metadataStore?: SandboxMetadataStoreLike } = {}) {}\n\n private get registry(): SandboxRegistry {\n return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());\n }\n\n private get metadataStore(): SandboxMetadataStoreLike {\n return this.deps.metadataStore ?? (this.deps.metadataStore = new SandboxMetadataStore());\n }\n\n private toListItem(record: SandboxMetadataRecord): {\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 return {\n name: record.name,\n status: record.status,\n image: record.image,\n cpus: record.cpus,\n memoryMib: record.memoryMib,\n envCount: Object.keys(record.env).length,\n volumeCount: Object.keys(record.volumes).length,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n };\n }\n\n private buildVolumes(volumes?: EnsureSandboxInput[\"volumes\"]): Record<string, unknown> | undefined {\n if (!volumes) {\n return undefined;\n }\n\n return Object.fromEntries(\n Object.entries(volumes).map(([mountPath, definition]) => [mountPath, this.buildVolume(definition)])\n );\n }\n\n private buildVolume(definition: VolumeConfig): unknown {\n if (definition.type === \"bind\") {\n return Mount.bind(definition.source, { readonly: definition.readonly ?? false });\n }\n\n if (definition.type === \"named\") {\n return Mount.named(definition.name, { readonly: definition.readonly ?? false });\n }\n\n return Mount.tmpfs({ sizeMib: definition.sizeMib });\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(name: string, input: EnsureSandboxInput): 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.registry.ensure(name, {\n image,\n cpus,\n memoryMib,\n env: input.env,\n volumes: this.buildVolumes(input.volumes),\n });\n\n const existing = await this.metadataStore.get(name);\n const now = new Date().toISOString();\n\n await this.metadataStore.upsert({\n name,\n status: \"running\",\n image,\n cpus,\n memoryMib,\n env: input.env ?? {},\n volumes: input.volumes ?? {},\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\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 await this.metadataStore.patchStatus(name, \"running\");\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 await this.metadataStore.patchStatus(name, \"stopped\");\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 await this.metadataStore.patchStatus(name, \"unknown\");\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 await this.metadataStore.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 items = (await this.metadataStore.list())\n .filter((record) => {\n if (_query.status && record.status !== _query.status) {\n return false;\n }\n\n if (_query.image && record.image !== _query.image) {\n return false;\n }\n\n if (_query.search) {\n const haystack = [record.name, record.image, ...Object.keys(record.env)]\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 .map((record) => this.toListItem(record));\n\n return { items, total: items.length };\n }\n\n async getSandbox(name: string): Promise<SandboxMetadataRecord | undefined> {\n return await this.metadataStore.get(name);\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n try {\n this.getNative(name);\n return { name, status: \"running\" };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const content = await this.getNative(sandboxName).fs().readString(path);\n return { path, content };\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n await this.getNative(sandboxName).fs().write(path, Buffer.from(content));\n return { path };\n }\n\n async listPath(\n sandboxName: string,\n path: string,\n recursive?: boolean\n ): Promise<{ entries: Array<{ path: string; type: string }> }> {\n const entries = await this.getNative(sandboxName).fs().list(path, { recursive });\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 output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"find\",\n args: [path, \"-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 let stdout: string;\n\n try {\n const output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"grep\",\n args: [\"-n\", \"-E\", query, path],\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 fs = this.getNative(sandboxName).fs();\n const original = await fs.readString(input.path);\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(input.path, Buffer.from(updated));\n\n return { replaced: occurrences };\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n await this.getNative(sandboxName).fs().write(path, Buffer.from(contentBase64, \"base64\"));\n return { path };\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const data = await this.getNative(sandboxName).fs().read(path);\n const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);\n return { path, 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 ? output.stderr() : \"\",\n exitCode: output.code ?? 0,\n };\n }\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { EnsureSandboxInput } from \"../schemas/sandbox\";\n\nexport type SandboxStatus = \"running\" | \"stopped\" | \"unknown\";\n\nexport type SandboxMetadataRecord = {\n name: string;\n status: SandboxStatus;\n image?: string;\n cpus?: number;\n memoryMib?: number;\n env: Record<string, string>;\n volumes: NonNullable<EnsureSandboxInput[\"volumes\"]>;\n createdAt: string;\n updatedAt: string;\n};\n\ntype SandboxMetadataFile = {\n sandboxes: SandboxMetadataRecord[];\n};\n\nfunction isSandboxMetadataFile(value: unknown): value is SandboxMetadataFile {\n return typeof value === \"object\" && value !== null && \"sandboxes\" in value && Array.isArray(value.sandboxes);\n}\n\nexport interface SandboxMetadataStoreLike {\n list(): Promise<SandboxMetadataRecord[]>;\n get(name: string): Promise<SandboxMetadataRecord | undefined>;\n upsert(record: SandboxMetadataRecord): Promise<SandboxMetadataRecord>;\n patchStatus(name: string, status: SandboxStatus): Promise<void>;\n remove(name: string): Promise<void>;\n}\n\nexport class SandboxMetadataStore implements SandboxMetadataStoreLike {\n constructor(private readonly options: { filePath?: string } = {}) {}\n\n private get filePath(): string {\n return this.options.filePath ?? process.env.MICROSANDBOX_METADATA_FILE ?? \".microsandbox/metadata.json\";\n }\n\n private async readAll(): Promise<SandboxMetadataFile> {\n try {\n const content = await readFile(this.filePath, \"utf8\");\n const parsed: unknown = JSON.parse(content);\n\n if (!isSandboxMetadataFile(parsed)) {\n throw new Error(\"Invalid sandbox metadata file\");\n }\n\n return parsed;\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") {\n return { sandboxes: [] };\n }\n\n throw error;\n }\n }\n\n private async writeAll(file: SandboxMetadataFile): Promise<void> {\n await mkdir(dirname(this.filePath), { recursive: true });\n await writeFile(this.filePath, JSON.stringify(file, null, 2));\n }\n\n async list(): Promise<SandboxMetadataRecord[]> {\n const file = await this.readAll();\n return file.sandboxes.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n }\n\n async get(name: string): Promise<SandboxMetadataRecord | undefined> {\n const file = await this.readAll();\n return file.sandboxes.find((entry) => entry.name === name);\n }\n\n async upsert(record: SandboxMetadataRecord): Promise<SandboxMetadataRecord> {\n const file = await this.readAll();\n const next = file.sandboxes.filter((entry) => entry.name !== record.name);\n next.push(record);\n await this.writeAll({ sandboxes: next });\n return record;\n }\n\n async patchStatus(name: string, status: SandboxStatus): Promise<void> {\n const current = await this.get(name);\n if (!current) {\n return;\n }\n\n await this.upsert({ ...current, status, updatedAt: new Date().toISOString() });\n }\n\n async remove(name: string): Promise<void> {\n const file = await this.readAll();\n await this.writeAll({ sandboxes: file.sandboxes.filter((entry) => entry.name !== name) });\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 { 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}: {\n runtimeService?: RuntimeService;\n imageService?: ImageService;\n} = {}): FastifyInstance {\n const app = fastify({ logger: false });\n\n app.register(cors, { origin: true });\n app.register(sensible);\n app.register(multipart);\n\n registerHealthRoutes(app);\n registerSandboxRoutes(app, runtimeService);\n registerImageRoutes(app, imageService);\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\", \"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 return reply.send(ok(await runtimeService.uploadFile(body.sandboxName, body.path, body.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 { PullImageInput } from \"../schemas/images\";\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\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\nexport class ImageService {\n constructor(\n private readonly deps: {\n bindings?: ImageBindings;\n } = {}\n ) {}\n\n private get bindings(): ImageBindings {\n return (\n this.deps.bindings ?? {\n list: async () => [],\n pull: async (ref: string) => ({ ref, sourceType: \"oci\", cached: true }),\n inspect: async (ref: string) => ({ ref, sourceType: \"oci\", cached: true }),\n remove: async () => undefined,\n }\n );\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","Sandbox","z"]}
1
+ {"version":3,"sources":["../src/services/SandboxRegistry.ts","../src/services/MicrosandboxRuntimeService.ts","../src/services/SandboxMetadataStore.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/services/ImageService.ts"],"sourcesContent":["import { Sandbox } 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 createConfig = {\n name,\n image: DEFAULT_IMAGE,\n ...(createOptions ?? {}),\n };\n\n try {\n const handle = 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 }\n } catch {\n native = undefined;\n }\n\n if (!native) {\n native = await Sandbox.createDetached(createConfig);\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 { Mount, Sandbox } from \"microsandbox\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport { SandboxRegistry } from \"./SandboxRegistry\";\nimport {\n SandboxMetadataStore,\n type SandboxMetadataRecord,\n type SandboxMetadataStoreLike,\n} from \"./SandboxMetadataStore\";\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(\n path: string,\n options?: { recursive?: boolean }\n ): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;\n read(path: string): Promise<Buffer | Uint8Array | string>;\n };\n execWithConfig(config: {\n cmd: string;\n args?: string[];\n cwd?: string;\n timeoutMs?: number;\n }): Promise<{\n stdout(): string;\n stderr?(): string;\n code?: number;\n }>;\n stop(): Promise<void>;\n kill(): Promise<void>;\n};\n\nexport class MicrosandboxRuntimeService {\n constructor(private deps: { registry?: SandboxRegistry; metadataStore?: SandboxMetadataStoreLike } = {}) {}\n\n private get registry(): SandboxRegistry {\n return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());\n }\n\n private get metadataStore(): SandboxMetadataStoreLike {\n return this.deps.metadataStore ?? (this.deps.metadataStore = new SandboxMetadataStore());\n }\n\n private toListItem(record: SandboxMetadataRecord): {\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 return {\n name: record.name,\n status: record.status,\n image: record.image,\n cpus: record.cpus,\n memoryMib: record.memoryMib,\n envCount: Object.keys(record.env).length,\n volumeCount: Object.keys(record.volumes).length,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n };\n }\n\n private buildVolumes(volumes?: EnsureSandboxInput[\"volumes\"]): Record<string, unknown> | undefined {\n if (!volumes) {\n return undefined;\n }\n\n return Object.fromEntries(\n Object.entries(volumes).map(([mountPath, definition]) => [mountPath, this.buildVolume(definition)])\n );\n }\n\n private buildVolume(definition: VolumeConfig): unknown {\n if (definition.type === \"bind\") {\n return Mount.bind(definition.source, { readonly: definition.readonly ?? false });\n }\n\n if (definition.type === \"named\") {\n return Mount.named(definition.name, { readonly: definition.readonly ?? false });\n }\n\n return Mount.tmpfs({ sizeMib: definition.sizeMib });\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(name: string, input: EnsureSandboxInput): 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.registry.ensure(name, {\n image,\n cpus,\n memoryMib,\n env: input.env,\n volumes: this.buildVolumes(input.volumes),\n });\n\n const existing = await this.metadataStore.get(name);\n const now = new Date().toISOString();\n\n await this.metadataStore.upsert({\n name,\n status: \"running\",\n image,\n cpus,\n memoryMib,\n env: input.env ?? {},\n volumes: input.volumes ?? {},\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\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 await this.metadataStore.patchStatus(name, \"running\");\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 await this.metadataStore.patchStatus(name, \"stopped\");\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 await this.metadataStore.patchStatus(name, \"unknown\");\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 await this.metadataStore.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 items = (await this.metadataStore.list())\n .filter((record) => {\n if (_query.status && record.status !== _query.status) {\n return false;\n }\n\n if (_query.image && record.image !== _query.image) {\n return false;\n }\n\n if (_query.search) {\n const haystack = [record.name, record.image, ...Object.keys(record.env)]\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 .map((record) => this.toListItem(record));\n\n return { items, total: items.length };\n }\n\n async getSandbox(name: string): Promise<SandboxMetadataRecord | undefined> {\n return await this.metadataStore.get(name);\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n try {\n this.getNative(name);\n return { name, status: \"running\" };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const content = await this.getNative(sandboxName).fs().readString(path);\n return { path, content };\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n await this.getNative(sandboxName).fs().write(path, Buffer.from(content));\n return { path };\n }\n\n async listPath(\n sandboxName: string,\n path: string,\n recursive?: boolean\n ): Promise<{ entries: Array<{ path: string; type: string }> }> {\n const entries = await this.getNative(sandboxName).fs().list(path, { recursive });\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 output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"find\",\n args: [path, \"-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 let stdout: string;\n\n try {\n const output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"grep\",\n args: [\"-n\", \"-E\", query, path],\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 fs = this.getNative(sandboxName).fs();\n const original = await fs.readString(input.path);\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(input.path, Buffer.from(updated));\n\n return { replaced: occurrences };\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n await this.getNative(sandboxName).fs().write(path, Buffer.from(contentBase64, \"base64\"));\n return { path };\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const data = await this.getNative(sandboxName).fs().read(path);\n const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);\n return { path, 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 ? output.stderr() : \"\",\n exitCode: output.code ?? 0,\n };\n }\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { EnsureSandboxInput } from \"../schemas/sandbox\";\n\nexport type SandboxStatus = \"running\" | \"stopped\" | \"unknown\";\n\nexport type SandboxMetadataRecord = {\n name: string;\n status: SandboxStatus;\n image?: string;\n cpus?: number;\n memoryMib?: number;\n env: Record<string, string>;\n volumes: NonNullable<EnsureSandboxInput[\"volumes\"]>;\n createdAt: string;\n updatedAt: string;\n};\n\ntype SandboxMetadataFile = {\n sandboxes: SandboxMetadataRecord[];\n};\n\nfunction isSandboxMetadataFile(value: unknown): value is SandboxMetadataFile {\n return typeof value === \"object\" && value !== null && \"sandboxes\" in value && Array.isArray(value.sandboxes);\n}\n\nexport interface SandboxMetadataStoreLike {\n list(): Promise<SandboxMetadataRecord[]>;\n get(name: string): Promise<SandboxMetadataRecord | undefined>;\n upsert(record: SandboxMetadataRecord): Promise<SandboxMetadataRecord>;\n patchStatus(name: string, status: SandboxStatus): Promise<void>;\n remove(name: string): Promise<void>;\n}\n\nexport class SandboxMetadataStore implements SandboxMetadataStoreLike {\n constructor(private readonly options: { filePath?: string } = {}) {}\n\n private get filePath(): string {\n return this.options.filePath ?? process.env.MICROSANDBOX_METADATA_FILE ?? \".microsandbox/metadata.json\";\n }\n\n private async readAll(): Promise<SandboxMetadataFile> {\n try {\n const content = await readFile(this.filePath, \"utf8\");\n const parsed: unknown = JSON.parse(content);\n\n if (!isSandboxMetadataFile(parsed)) {\n throw new Error(\"Invalid sandbox metadata file\");\n }\n\n return parsed;\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") {\n return { sandboxes: [] };\n }\n\n throw error;\n }\n }\n\n private async writeAll(file: SandboxMetadataFile): Promise<void> {\n await mkdir(dirname(this.filePath), { recursive: true });\n await writeFile(this.filePath, JSON.stringify(file, null, 2));\n }\n\n async list(): Promise<SandboxMetadataRecord[]> {\n const file = await this.readAll();\n return file.sandboxes.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n }\n\n async get(name: string): Promise<SandboxMetadataRecord | undefined> {\n const file = await this.readAll();\n return file.sandboxes.find((entry) => entry.name === name);\n }\n\n async upsert(record: SandboxMetadataRecord): Promise<SandboxMetadataRecord> {\n const file = await this.readAll();\n const next = file.sandboxes.filter((entry) => entry.name !== record.name);\n next.push(record);\n await this.writeAll({ sandboxes: next });\n return record;\n }\n\n async patchStatus(name: string, status: SandboxStatus): Promise<void> {\n const current = await this.get(name);\n if (!current) {\n return;\n }\n\n await this.upsert({ ...current, status, updatedAt: new Date().toISOString() });\n }\n\n async remove(name: string): Promise<void> {\n const file = await this.readAll();\n await this.writeAll({ sandboxes: file.sandboxes.filter((entry) => entry.name !== name) });\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 { 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}: {\n runtimeService?: RuntimeService;\n imageService?: ImageService;\n} = {}): FastifyInstance {\n const app = fastify({ logger: false });\n\n app.register(cors, { origin: true });\n app.register(sensible);\n app.register(multipart);\n\n registerHealthRoutes(app);\n registerSandboxRoutes(app, runtimeService);\n registerImageRoutes(app, imageService);\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\", \"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 return reply.send(ok(await runtimeService.uploadFile(body.sandboxName, body.path, body.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 { PullImageInput } from \"../schemas/images\";\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\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\nexport class ImageService {\n constructor(\n private readonly deps: {\n bindings?: ImageBindings;\n } = {}\n ) {}\n\n private get bindings(): ImageBindings {\n return (\n this.deps.bindings ?? {\n list: async () => [],\n pull: async (ref: string) => ({ ref, sourceType: \"oci\", cached: true }),\n inspect: async (ref: string) => ({ ref, sourceType: \"oci\", cached: true }),\n remove: async () => undefined,\n }\n );\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","Sandbox","z"]}
package/dist/cli.js CHANGED
@@ -764,12 +764,6 @@ async function startServer({
764
764
  await app.listen({ port: config.port, host: config.host });
765
765
  return app;
766
766
  }
767
- if (require.main === module) {
768
- void startServer().catch((error) => {
769
- console.error("Failed to start microsandbox-service", error);
770
- process.exit(1);
771
- });
772
- }
773
767
 
774
768
  // src/cli.ts
775
769
  void startServer().catch((error) => {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../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/services/ImageService.ts","../src/services/MicrosandboxRuntimeService.ts","../src/services/SandboxRegistry.ts","../src/services/SandboxMetadataStore.ts","../src/lib/server-cli.ts","../src/server.ts","../src/cli.ts"],"sourcesContent":["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 { 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}: {\n runtimeService?: RuntimeService;\n imageService?: ImageService;\n} = {}): FastifyInstance {\n const app = fastify({ logger: false });\n\n app.register(cors, { origin: true });\n app.register(sensible);\n app.register(multipart);\n\n registerHealthRoutes(app);\n registerSandboxRoutes(app, runtimeService);\n registerImageRoutes(app, imageService);\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\", \"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 return reply.send(ok(await runtimeService.uploadFile(body.sandboxName, body.path, body.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 { PullImageInput } from \"../schemas/images\";\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\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\nexport class ImageService {\n constructor(\n private readonly deps: {\n bindings?: ImageBindings;\n } = {}\n ) {}\n\n private get bindings(): ImageBindings {\n return (\n this.deps.bindings ?? {\n list: async () => [],\n pull: async (ref: string) => ({ ref, sourceType: \"oci\", cached: true }),\n inspect: async (ref: string) => ({ ref, sourceType: \"oci\", cached: true }),\n remove: async () => undefined,\n }\n );\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","import { Mount, Sandbox } from \"microsandbox\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport { SandboxRegistry } from \"./SandboxRegistry\";\nimport {\n SandboxMetadataStore,\n type SandboxMetadataRecord,\n type SandboxMetadataStoreLike,\n} from \"./SandboxMetadataStore\";\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(\n path: string,\n options?: { recursive?: boolean }\n ): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;\n read(path: string): Promise<Buffer | Uint8Array | string>;\n };\n execWithConfig(config: {\n cmd: string;\n args?: string[];\n cwd?: string;\n timeoutMs?: number;\n }): Promise<{\n stdout(): string;\n stderr?(): string;\n code?: number;\n }>;\n stop(): Promise<void>;\n kill(): Promise<void>;\n};\n\nexport class MicrosandboxRuntimeService {\n constructor(private deps: { registry?: SandboxRegistry; metadataStore?: SandboxMetadataStoreLike } = {}) {}\n\n private get registry(): SandboxRegistry {\n return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());\n }\n\n private get metadataStore(): SandboxMetadataStoreLike {\n return this.deps.metadataStore ?? (this.deps.metadataStore = new SandboxMetadataStore());\n }\n\n private toListItem(record: SandboxMetadataRecord): {\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 return {\n name: record.name,\n status: record.status,\n image: record.image,\n cpus: record.cpus,\n memoryMib: record.memoryMib,\n envCount: Object.keys(record.env).length,\n volumeCount: Object.keys(record.volumes).length,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n };\n }\n\n private buildVolumes(volumes?: EnsureSandboxInput[\"volumes\"]): Record<string, unknown> | undefined {\n if (!volumes) {\n return undefined;\n }\n\n return Object.fromEntries(\n Object.entries(volumes).map(([mountPath, definition]) => [mountPath, this.buildVolume(definition)])\n );\n }\n\n private buildVolume(definition: VolumeConfig): unknown {\n if (definition.type === \"bind\") {\n return Mount.bind(definition.source, { readonly: definition.readonly ?? false });\n }\n\n if (definition.type === \"named\") {\n return Mount.named(definition.name, { readonly: definition.readonly ?? false });\n }\n\n return Mount.tmpfs({ sizeMib: definition.sizeMib });\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(name: string, input: EnsureSandboxInput): 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.registry.ensure(name, {\n image,\n cpus,\n memoryMib,\n env: input.env,\n volumes: this.buildVolumes(input.volumes),\n });\n\n const existing = await this.metadataStore.get(name);\n const now = new Date().toISOString();\n\n await this.metadataStore.upsert({\n name,\n status: \"running\",\n image,\n cpus,\n memoryMib,\n env: input.env ?? {},\n volumes: input.volumes ?? {},\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\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 await this.metadataStore.patchStatus(name, \"running\");\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 await this.metadataStore.patchStatus(name, \"stopped\");\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 await this.metadataStore.patchStatus(name, \"unknown\");\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 await this.metadataStore.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 items = (await this.metadataStore.list())\n .filter((record) => {\n if (_query.status && record.status !== _query.status) {\n return false;\n }\n\n if (_query.image && record.image !== _query.image) {\n return false;\n }\n\n if (_query.search) {\n const haystack = [record.name, record.image, ...Object.keys(record.env)]\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 .map((record) => this.toListItem(record));\n\n return { items, total: items.length };\n }\n\n async getSandbox(name: string): Promise<SandboxMetadataRecord | undefined> {\n return await this.metadataStore.get(name);\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n try {\n this.getNative(name);\n return { name, status: \"running\" };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const content = await this.getNative(sandboxName).fs().readString(path);\n return { path, content };\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n await this.getNative(sandboxName).fs().write(path, Buffer.from(content));\n return { path };\n }\n\n async listPath(\n sandboxName: string,\n path: string,\n recursive?: boolean\n ): Promise<{ entries: Array<{ path: string; type: string }> }> {\n const entries = await this.getNative(sandboxName).fs().list(path, { recursive });\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 output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"find\",\n args: [path, \"-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 let stdout: string;\n\n try {\n const output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"grep\",\n args: [\"-n\", \"-E\", query, path],\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 fs = this.getNative(sandboxName).fs();\n const original = await fs.readString(input.path);\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(input.path, Buffer.from(updated));\n\n return { replaced: occurrences };\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n await this.getNative(sandboxName).fs().write(path, Buffer.from(contentBase64, \"base64\"));\n return { path };\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const data = await this.getNative(sandboxName).fs().read(path);\n const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);\n return { path, 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 ? output.stderr() : \"\",\n exitCode: output.code ?? 0,\n };\n }\n}\n","import { Sandbox } 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 createConfig = {\n name,\n image: DEFAULT_IMAGE,\n ...(createOptions ?? {}),\n };\n\n try {\n const handle = 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 }\n } catch {\n native = undefined;\n }\n\n if (!native) {\n native = await Sandbox.createDetached(createConfig);\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 { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { EnsureSandboxInput } from \"../schemas/sandbox\";\n\nexport type SandboxStatus = \"running\" | \"stopped\" | \"unknown\";\n\nexport type SandboxMetadataRecord = {\n name: string;\n status: SandboxStatus;\n image?: string;\n cpus?: number;\n memoryMib?: number;\n env: Record<string, string>;\n volumes: NonNullable<EnsureSandboxInput[\"volumes\"]>;\n createdAt: string;\n updatedAt: string;\n};\n\ntype SandboxMetadataFile = {\n sandboxes: SandboxMetadataRecord[];\n};\n\nfunction isSandboxMetadataFile(value: unknown): value is SandboxMetadataFile {\n return typeof value === \"object\" && value !== null && \"sandboxes\" in value && Array.isArray(value.sandboxes);\n}\n\nexport interface SandboxMetadataStoreLike {\n list(): Promise<SandboxMetadataRecord[]>;\n get(name: string): Promise<SandboxMetadataRecord | undefined>;\n upsert(record: SandboxMetadataRecord): Promise<SandboxMetadataRecord>;\n patchStatus(name: string, status: SandboxStatus): Promise<void>;\n remove(name: string): Promise<void>;\n}\n\nexport class SandboxMetadataStore implements SandboxMetadataStoreLike {\n constructor(private readonly options: { filePath?: string } = {}) {}\n\n private get filePath(): string {\n return this.options.filePath ?? process.env.MICROSANDBOX_METADATA_FILE ?? \".microsandbox/metadata.json\";\n }\n\n private async readAll(): Promise<SandboxMetadataFile> {\n try {\n const content = await readFile(this.filePath, \"utf8\");\n const parsed: unknown = JSON.parse(content);\n\n if (!isSandboxMetadataFile(parsed)) {\n throw new Error(\"Invalid sandbox metadata file\");\n }\n\n return parsed;\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") {\n return { sandboxes: [] };\n }\n\n throw error;\n }\n }\n\n private async writeAll(file: SandboxMetadataFile): Promise<void> {\n await mkdir(dirname(this.filePath), { recursive: true });\n await writeFile(this.filePath, JSON.stringify(file, null, 2));\n }\n\n async list(): Promise<SandboxMetadataRecord[]> {\n const file = await this.readAll();\n return file.sandboxes.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n }\n\n async get(name: string): Promise<SandboxMetadataRecord | undefined> {\n const file = await this.readAll();\n return file.sandboxes.find((entry) => entry.name === name);\n }\n\n async upsert(record: SandboxMetadataRecord): Promise<SandboxMetadataRecord> {\n const file = await this.readAll();\n const next = file.sandboxes.filter((entry) => entry.name !== record.name);\n next.push(record);\n await this.writeAll({ sandboxes: next });\n return record;\n }\n\n async patchStatus(name: string, status: SandboxStatus): Promise<void> {\n const current = await this.get(name);\n if (!current) {\n return;\n }\n\n await this.upsert({ ...current, status, updatedAt: new Date().toISOString() });\n }\n\n async remove(name: string): Promise<void> {\n const file = await this.readAll();\n await this.writeAll({ sandboxes: file.sandboxes.filter((entry) => entry.name !== name) });\n }\n}\n","export interface ParsedServerArgs {\n host?: string;\n port?: number;\n}\n\nexport interface ResolvedServerConfig {\n host: string;\n port: number;\n}\n\nfunction parsePort(raw: string, source: string): number {\n const value = Number(raw);\n if (!Number.isInteger(value) || value <= 0) {\n throw new Error(`Invalid value for ${source}: ${raw}`);\n }\n return value;\n}\n\nexport function parseServerArgs(argv: string[]): ParsedServerArgs {\n const parsed: ParsedServerArgs = {};\n\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index];\n\n if (token === \"--port\") {\n const raw = argv[index + 1];\n if (!raw) {\n throw new Error(\"Missing value for --port\");\n }\n parsed.port = parsePort(raw, \"--port\");\n index += 1;\n continue;\n }\n\n if (token === \"--host\") {\n const raw = argv[index + 1];\n if (!raw) {\n throw new Error(\"Missing value for --host\");\n }\n parsed.host = raw;\n index += 1;\n }\n }\n\n return parsed;\n}\n\nexport function resolveServerConfig({\n args,\n env,\n}: {\n args: ParsedServerArgs;\n env: NodeJS.ProcessEnv;\n}): ResolvedServerConfig {\n return {\n host: args.host ?? env.HOST ?? \"0.0.0.0\",\n port: args.port ?? (env.PORT ? parsePort(env.PORT, \"PORT\") : 4002),\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { buildApp } from \"./app\";\nimport { parseServerArgs, resolveServerConfig } from \"./lib/server-cli\";\n\nexport async function startServer({\n argv = process.argv.slice(2),\n env = process.env,\n app = buildApp(),\n}: {\n argv?: string[];\n env?: NodeJS.ProcessEnv;\n app?: Pick<FastifyInstance, \"listen\" | \"close\">;\n} = {}): Promise<Pick<FastifyInstance, \"listen\" | \"close\">> {\n const config = resolveServerConfig({ args: parseServerArgs(argv), env });\n\n const shutdown = async (code: number): Promise<void> => {\n try {\n await app.close();\n process.exit(code);\n } catch (error) {\n console.error(\"Failed to shutdown microsandbox-service cleanly\", error);\n process.exit(1);\n }\n };\n\n process.once(\"SIGINT\", () => {\n void shutdown(0);\n });\n\n process.once(\"SIGTERM\", () => {\n void shutdown(0);\n });\n\n await app.listen({ port: config.port, host: config.host });\n return app;\n}\n\nif (require.main === module) {\n void startServer().catch((error) => {\n console.error(\"Failed to start microsandbox-service\", error);\n process.exit(1);\n });\n}\n","#!/usr/bin/env node\n\nimport { startServer } from \"./server\";\n\nvoid startServer().catch((error) => {\n console.error(\"Failed to start microsandbox-service\", error);\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kBAAiB;AACjB,uBAAsB;AACtB,sBAAqB;AACrB,qBAA8C;;;ACHvC,IAAM,YAAN,cAAwB,MAAM;AAAA,EACnC,YACS,YACA,MACP,SACA;AACA,UAAM,OAAO;AAJN;AACA;AAAA,EAIT;AACF;AAEO,SAAS,gBAAgB,OAS9B;AACA,MAAI,iBAAiB,WAAW;AAC9B,WAAO;AAAA,MACL,YAAY,MAAM;AAAA,MAClB,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,OAAO;AAAA,UACL,MAAM,MAAM;AAAA,UACZ,SAAS,MAAM;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAChE;AAAA,IACF;AAAA,EACF;AACF;;;ACtCO,SAAS,GAAM,MAA6B;AACjD,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,EACF;AACF;;;ACPO,SAAS,qBAAqB,KAA4B;AAC/D,MAAI,IAAI,WAAW,YAAY,GAAG,EAAE,QAAQ,KAAK,CAAC,CAAC;AACrD;;;ACJA,IAAAA,cAAyB;;;ACDzB,iBAAc;AAEP,IAAM,sBAAsB,WAAAC,QAAE,OAAO;AAAA,EAC1C,KAAK,WAAAA,QAAE,OAAO,EAAE,IAAI,CAAC;AACvB,CAAC;AAEM,IAAM,kBAAkB,WAAAA,QAAE,OAAO;AAAA,EACtC,KAAK,WAAAA,QAAE,OAAO,EAAE,IAAI,CAAC;AACvB,CAAC;;;ADDD,SAAS,aAAgB,OAAmB;AAC1C,MAAI;AACF,WAAO,MAAM;AAAA,EACf,SAAS,OAAO;AACd,QAAI,iBAAiB,sBAAU;AAC7B,YAAM,IAAI,UAAU,KAAK,mBAAmB,MAAM,OAAO,CAAC,GAAG,WAAW,iBAAiB;AAAA,IAC3F;AAEA,UAAM;AAAA,EACR;AACF;AAEO,SAAS,sBAAsB,cAA4B;AAChE,SAAO;AAAA,IACL,YAAY,OAAO,UAA0B,UAAwB;AACnE,aAAO,MAAM,KAAK,GAAG,MAAM,aAAa,WAAW,CAAC,CAAC;AAAA,IACvD;AAAA,IACA,WAAW,OAAO,SAA4C,UAAwB;AACpF,YAAM,OAAO,aAAa,MAAM,gBAAgB,MAAM,QAAQ,QAAQ,CAAC,CAAC,CAAC;AACzE,aAAO,MAAM,KAAK,GAAG,MAAM,aAAa,UAAU,IAAI,CAAC,CAAC;AAAA,IAC1D;AAAA,IACA,UAAU,OAAO,SAAmD,UAAwB;AAC1F,YAAM,QAAQ,aAAa,MAAM,oBAAoB,MAAM,QAAQ,SAAS,CAAC,CAAC,CAAC;AAC/E,aAAO,MAAM,KAAK,GAAG,MAAM,aAAa,SAAS,MAAM,GAAG,CAAC,CAAC;AAAA,IAC9D;AAAA,IACA,aAAa,OAAO,SAAmD,UAAwB;AAC7F,YAAM,QAAQ,aAAa,MAAM,oBAAoB,MAAM,QAAQ,SAAS,CAAC,CAAC,CAAC;AAC/E,aAAO,MAAM,KAAK,GAAG,MAAM,aAAa,YAAY,MAAM,GAAG,CAAC,CAAC;AAAA,IACjE;AAAA,EACF;AACF;;;AEjCO,SAAS,oBAAoB,KAAsB,cAAkC;AAC1F,QAAM,aAAa,sBAAsB,YAAY;AAErD,MAAI,IAAI,eAAe,WAAW,UAAU;AAC5C,MAAI,KAAK,oBAAoB,WAAW,SAAS;AACjD,MAAI,IAAI,sBAAsB,WAAW,QAAQ;AACjD,MAAI,OAAO,sBAAsB,WAAW,WAAW;AACzD;;;ACXA,IAAAC,cAAc;AAEd,IAAM,kBAAkB,YAAAC,QAAE,OAAO;AAAA,EAC/B,MAAM,YAAAA,QAAE,QAAQ,MAAM;AAAA,EACtB,QAAQ,YAAAA,QAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACxB,UAAU,YAAAA,QAAE,QAAQ,EAAE,SAAS;AACjC,CAAC;AAED,IAAM,mBAAmB,YAAAA,QAAE,OAAO;AAAA,EAChC,MAAM,YAAAA,QAAE,QAAQ,OAAO;AAAA,EACvB,MAAM,YAAAA,QAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,UAAU,YAAAA,QAAE,QAAQ,EAAE,SAAS;AACjC,CAAC;AAED,IAAM,mBAAmB,YAAAA,QAAE,OAAO;AAAA,EAChC,MAAM,YAAAA,QAAE,QAAQ,OAAO;AAAA,EACvB,SAAS,YAAAA,QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAChD,CAAC;AAEM,IAAM,eAAe,YAAAA,QAAE,MAAM;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,sBAAsB,YAAAA,QAAE,OAAO;AAAA,EAC1C,OAAO,YAAAA,QAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,MAAM,YAAAA,QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,EAC3C,WAAW,YAAAA,QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,EAChD,KAAK,YAAAA,QAAE,OAAO,YAAAA,QAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACnC,SAAS,YAAAA,QAAE,OAAO,YAAY,EAAE,SAAS;AAC3C,CAAC;AAEM,IAAM,0BAA0B,YAAAA,QAAE,OAAO;AAAA,EAC9C,MAAM,YAAAA,QAAE,OAAO,EAAE,IAAI,CAAC;AACxB,CAAC;AAEM,IAAM,2BAA2B,YAAAA,QAAE,OAAO;AAAA,EAC/C,QAAQ,YAAAA,QAAE,KAAK,CAAC,WAAW,WAAW,SAAS,CAAC,EAAE,SAAS;AAAA,EAC3D,OAAO,YAAAA,QAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAClC,QAAQ,YAAAA,QAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AACrC,CAAC;AAED,IAAM,uBAAuB,YAAAA,QAAE,OAAO;AAAA,EACpC,aAAa,YAAAA,QAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC7B,MAAM,YAAAA,QAAE,OAAO,EAAE,IAAI,CAAC;AACxB,CAAC;AAEM,IAAM,iBAAiB;AAEvB,IAAM,kBAAkB,qBAAqB,OAAO;AAAA,EACzD,SAAS,YAAAA,QAAE,OAAO;AACpB,CAAC;AAEM,IAAM,iBAAiB,qBAAqB,OAAO;AAAA,EACxD,WAAW,YAAAA,QAAE,QAAQ,EAAE,SAAS;AAClC,CAAC;AAEM,IAAM,kBAAkB,qBAAqB,OAAO;AAAA,EACzD,SAAS,YAAAA,QAAE,OAAO,EAAE,IAAI,CAAC;AAC3B,CAAC;AAEM,IAAM,qBAAqB,qBAAqB,OAAO;AAAA,EAC5D,OAAO,YAAAA,QAAE,OAAO,EAAE,IAAI,CAAC;AACzB,CAAC;AAEM,IAAM,sBAAsB,qBAAqB,OAAO;AAAA,EAC7D,QAAQ,YAAAA,QAAE,OAAO;AAAA,EACjB,SAAS,YAAAA,QAAE,OAAO;AACpB,CAAC;AAEM,IAAM,mBAAmB,qBAAqB;AAAA,EACnD,YAAAA,QAAE,MAAM;AAAA,IACN,YAAAA,QAAE,OAAO,EAAE,eAAe,YAAAA,QAAE,OAAO,EAAE,CAAC;AAAA,IACtC,YAAAA,QAAE,OAAO,EAAE,SAAS,YAAAA,QAAE,OAAO,EAAE,UAAU,CAAC,YAAY,OAAO,KAAK,OAAO,EAAE,SAAS,QAAQ,CAAC,EAAE,CAAC;AAAA,EAClG,CAAC;AACH;AAEO,IAAM,qBAAqB;AAE3B,IAAM,kBAAkB,YAAAA,QAAE,OAAO;AAAA,EACtC,aAAa,YAAAA,QAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC7B,SAAS,YAAAA,QAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACzB,UAAU,YAAAA,QAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,SAAS,YAAAA,QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAChD,CAAC;;;AClEM,SAAS,wBAAwB,gBA6CtC;AACA,SAAO;AAAA,IACL,eAAe,OACb,SACA,UACG;AACH,YAAM,OAAO,oBAAoB,MAAM,QAAQ,QAAQ,CAAC,CAAC;AACzD,YAAM,SAAS,MAAM,eAAe,cAAc,QAAQ,OAAO,MAAM,IAAI;AAC3E,aAAO,MAAM,KAAK,GAAG,MAAM,CAAC;AAAA,IAC9B;AAAA,IAEA,cAAc,OAAO,SAAS,UAAU;AACtC,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,aAAa,QAAQ,OAAO,IAAI,CAAC,CAAC;AAAA,IAC9E;AAAA,IAEA,aAAa,OAAO,SAAS,UAAU;AACrC,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,YAAY,QAAQ,OAAO,IAAI,CAAC,CAAC;AAAA,IAC7E;AAAA,IAEA,aAAa,OAAO,SAAS,UAAU;AACrC,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,YAAY,QAAQ,OAAO,IAAI,CAAC,CAAC;AAAA,IAC7E;AAAA,IAEA,eAAe,OAAO,SAAS,UAAU;AACvC,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,cAAc,QAAQ,OAAO,IAAI,CAAC,CAAC;AAAA,IAC/E;AAAA,IAEA,eAAe,OAAO,SAAS,UAAU;AACvC,YAAM,QAAQ,yBAAyB,MAAM,QAAQ,SAAS,CAAC,CAAC;AAChE,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,cAAc,KAAK,CAAC,CAAC;AAAA,IACjE;AAAA,IAEA,YAAY,OAAO,SAAS,UAAU;AACpC,YAAM,SAAS,wBAAwB,MAAM,QAAQ,UAAU,CAAC,CAAC;AACjE,YAAM,UAAU,MAAM,eAAe,WAAW,OAAO,IAAI;AAE3D,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,UAAU,KAAK,qBAAqB,YAAY,OAAO,IAAI,aAAa;AAAA,MACpF;AAEA,aAAO,MAAM,KAAK,GAAG,OAAO,CAAC;AAAA,IAC/B;AAAA,IAEA,WAAW,OAAO,SAAS,UAAU;AACnC,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,UAAU,QAAQ,OAAO,IAAI,CAAC,CAAC;AAAA,IAC3E;AAAA,IAEA,UAAU,OAAO,SAAS,UAAU;AAClC,YAAM,OAAO,eAAe,MAAM,QAAQ,QAAQ,CAAC,CAAC;AACpD,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,SAAS,KAAK,aAAa,KAAK,IAAI,CAAC,CAAC;AAAA,IAClF;AAAA,IAEA,WAAW,OAAO,SAAS,UAAU;AACnC,YAAM,OAAO,gBAAgB,MAAM,QAAQ,QAAQ,CAAC,CAAC;AACrD,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,UAAU,KAAK,aAAa,KAAK,MAAM,KAAK,OAAO,CAAC,CAAC;AAAA,IACjG;AAAA,IAEA,UAAU,OAAO,SAAS,UAAU;AAClC,YAAM,OAAO,eAAe,MAAM,QAAQ,QAAQ,CAAC,CAAC;AACpD,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,SAAS,KAAK,aAAa,KAAK,MAAM,KAAK,SAAS,CAAC,CAAC;AAAA,IAClG;AAAA,IAEA,WAAW,OAAO,SAAS,UAAU;AACnC,YAAM,OAAO,gBAAgB,MAAM,QAAQ,QAAQ,CAAC,CAAC;AACrD,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,UAAU,KAAK,aAAa,KAAK,MAAM,KAAK,OAAO,CAAC,CAAC;AAAA,IACjG;AAAA,IAEA,cAAc,OAAO,SAAS,UAAU;AACtC,YAAM,OAAO,mBAAmB,MAAM,QAAQ,QAAQ,CAAC,CAAC;AACxD,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,aAAa,KAAK,aAAa,KAAK,MAAM,KAAK,KAAK,CAAC,CAAC;AAAA,IAClG;AAAA,IAEA,eAAe,OAAO,SAAS,UAAU;AACvC,YAAM,OAAO,oBAAoB,MAAM,QAAQ,QAAQ,CAAC,CAAC;AACzD,aAAO,MAAM;AAAA,QACX;AAAA,UACE,MAAM,eAAe,cAAc,KAAK,aAAa;AAAA,YACnD,MAAM,KAAK;AAAA,YACX,QAAQ,KAAK;AAAA,YACb,SAAS,KAAK;AAAA,UAChB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,IAEA,YAAY,OAAO,SAAS,UAAU;AACpC,YAAM,OAAO,iBAAiB,MAAM,QAAQ,QAAQ,CAAC,CAAC;AACtD,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,WAAW,KAAK,aAAa,KAAK,MAAM,KAAK,aAAa,CAAC,CAAC;AAAA,IACxG;AAAA,IAEA,cAAc,OAAO,SAAS,UAAU;AACtC,YAAM,QAAQ,mBAAmB,MAAM,QAAQ,SAAS,CAAC,CAAC;AAC1D,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,aAAa,MAAM,aAAa,MAAM,IAAI,CAAC,CAAC;AAAA,IACxF;AAAA,IAEA,aAAa,OAAO,SAAS,UAAU;AACrC,YAAM,OAAO,gBAAgB,MAAM,QAAQ,QAAQ,CAAC,CAAC;AACrD,aAAO,MAAM,KAAK,GAAG,MAAM,eAAe,YAAY,IAAI,CAAC,CAAC;AAAA,IAC9D;AAAA,EACF;AACF;;;AChKO,SAAS,sBACd,KACA,gBACM;AACN,QAAM,aAAa,wBAAwB,cAAc;AAEzD,MAAI,IAAI,kBAAkB,WAAW,aAAa;AAClD,MAAI,IAAI,wBAAwB,WAAW,UAAU;AACrD,MAAI,IAAI,wBAAwB,WAAW,aAAa;AACxD,MAAI,KAAK,8BAA8B,WAAW,YAAY;AAC9D,MAAI,KAAK,6BAA6B,WAAW,WAAW;AAC5D,MAAI,KAAK,6BAA6B,WAAW,WAAW;AAC5D,MAAI,OAAO,wBAAwB,WAAW,aAAa;AAC3D,MAAI,IAAI,+BAA+B,WAAW,SAAS;AAE3D,MAAI,KAAK,mBAAmB,WAAW,QAAQ;AAC/C,MAAI,KAAK,oBAAoB,WAAW,SAAS;AACjD,MAAI,KAAK,mBAAmB,WAAW,QAAQ;AAC/C,MAAI,KAAK,mBAAmB,WAAW,SAAS;AAChD,MAAI,KAAK,qBAAqB,WAAW,YAAY;AACrD,MAAI,KAAK,sBAAsB,WAAW,aAAa;AACvD,MAAI,KAAK,qBAAqB,WAAW,UAAU;AACnD,MAAI,IAAI,uBAAuB,WAAW,YAAY;AAEtD,MAAI,KAAK,mBAAmB,WAAW,WAAW;AACpD;;;ACXO,IAAM,eAAN,MAAmB;AAAA,EACxB,YACmB,OAEb,CAAC,GACL;AAHiB;AAAA,EAGhB;AAAA,EAEH,IAAY,WAA0B;AACpC,WACE,KAAK,KAAK,YAAY;AAAA,MACpB,MAAM,YAAY,CAAC;AAAA,MACnB,MAAM,OAAO,SAAiB,EAAE,KAAK,YAAY,OAAO,QAAQ,KAAK;AAAA,MACrE,SAAS,OAAO,SAAiB,EAAE,KAAK,YAAY,OAAO,QAAQ,KAAK;AAAA,MACxE,QAAQ,YAAY;AAAA,IACtB;AAAA,EAEJ;AAAA,EAEA,MAAM,aAA+D;AACnE,UAAM,QAAQ,MAAM,KAAK,SAAS,KAAK;AACvC,WAAO,EAAE,OAAO,OAAO,MAAM,OAAO;AAAA,EACtC;AAAA,EAEA,MAAM,UAAU,OAA6C;AAC3D,WAAO,MAAM,KAAK,SAAS,KAAK,MAAM,GAAG;AAAA,EAC3C;AAAA,EAEA,MAAM,SAAS,KAAmC;AAChD,WAAO,MAAM,KAAK,SAAS,QAAQ,GAAG;AAAA,EACxC;AAAA,EAEA,MAAM,YAAY,KAAuC;AACvD,UAAM,KAAK,SAAS,OAAO,GAAG;AAC9B,WAAO,EAAE,IAAI;AAAA,EACf;AACF;;;ACrDA,IAAAC,uBAA+B;;;ACA/B,0BAAwB;AAExB,IAAM,gBAAgB,QAAQ,IAAI,sBAAsB;AAEjD,IAAM,kBAAN,MAAsB;AAAA,EAAtB;AACL,SAAQ,UAAU,oBAAI,IAAqB;AAC3C,SAAQ,WAAW,oBAAI,IAA8B;AAAA;AAAA,EAErD,MAAM,OAAO,MAAc,eAA2D;AACpF,UAAM,SAAS,KAAK,QAAQ,IAAI,IAAI;AACpC,QAAI,QAAQ;AACV,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,KAAK,SAAS,IAAI,IAAI;AACvC,QAAI,UAAU;AACZ,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,YAAY;AAC5B,UAAI;AACJ,YAAM,eAAe;AAAA,QACnB;AAAA,QACA,OAAO;AAAA,QACP,GAAI,iBAAiB,CAAC;AAAA,MACxB;AAEA,UAAI;AACF,cAAM,SAAS,MAAM,4BAAQ,IAAI,IAAI;AAErC,YAAI,OAAO,WAAW,WAAW;AAC/B,mBAAS,MAAM,OAAO,QAAQ;AAAA,QAChC,WAAW,OAAO,WAAW,WAAW;AACtC,mBAAS,MAAM,4BAAQ,MAAM,IAAI;AAAA,QACnC,WAAW,OAAO,WAAW,aAAa,OAAO,WAAW,YAAY;AACtE,gBAAM,4BAAQ,OAAO,IAAI;AAAA,QAC3B;AAAA,MACF,QAAQ;AACN,iBAAS;AAAA,MACX;AAEA,UAAI,CAAC,QAAQ;AACX,iBAAS,MAAM,4BAAQ,eAAe,YAAY;AAAA,MACpD;AAEA,WAAK,QAAQ,IAAI,MAAM,MAAM;AAC7B,aAAO;AAAA,IACT,GAAG;AAEH,SAAK,SAAS,IAAI,MAAM,QAAQ;AAChC,SAAK,SAAS,QAAQ,MAAM,KAAK,SAAS,OAAO,IAAI,CAAC;AAEtD,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,MAAuB;AACzB,UAAM,SAAS,KAAK,QAAQ,IAAI,IAAI;AAEpC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,WAAW,IAAI,YAAY;AAAA,IAC7C;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,MAAoB;AACzB,SAAK,QAAQ,OAAO,IAAI;AAAA,EAC1B;AACF;;;ACpEA,sBAA2C;AAC3C,uBAAwB;AAqBxB,SAAS,sBAAsB,OAA8C;AAC3E,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,eAAe,SAAS,MAAM,QAAQ,MAAM,SAAS;AAC7G;AAUO,IAAM,uBAAN,MAA+D;AAAA,EACpE,YAA6B,UAAiC,CAAC,GAAG;AAArC;AAAA,EAAsC;AAAA,EAEnE,IAAY,WAAmB;AAC7B,WAAO,KAAK,QAAQ,YAAY,QAAQ,IAAI,8BAA8B;AAAA,EAC5E;AAAA,EAEA,MAAc,UAAwC;AACpD,QAAI;AACF,YAAM,UAAU,UAAM,0BAAS,KAAK,UAAU,MAAM;AACpD,YAAM,SAAkB,KAAK,MAAM,OAAO;AAE1C,UAAI,CAAC,sBAAsB,MAAM,GAAG;AAClC,cAAM,IAAI,MAAM,+BAA+B;AAAA,MACjD;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,SAAS,MAAM,SAAS,UAAU;AAC7F,eAAO,EAAE,WAAW,CAAC,EAAE;AAAA,MACzB;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,SAAS,MAA0C;AAC/D,cAAM,2BAAM,0BAAQ,KAAK,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AACvD,cAAM,2BAAU,KAAK,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,EAC9D;AAAA,EAEA,MAAM,OAAyC;AAC7C,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,WAAO,KAAK,UAAU,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,cAAc,EAAE,SAAS,CAAC;AAAA,EAC7E;AAAA,EAEA,MAAM,IAAI,MAA0D;AAClE,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,WAAO,KAAK,UAAU,KAAK,CAAC,UAAU,MAAM,SAAS,IAAI;AAAA,EAC3D;AAAA,EAEA,MAAM,OAAO,QAA+D;AAC1E,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,UAAM,OAAO,KAAK,UAAU,OAAO,CAAC,UAAU,MAAM,SAAS,OAAO,IAAI;AACxE,SAAK,KAAK,MAAM;AAChB,UAAM,KAAK,SAAS,EAAE,WAAW,KAAK,CAAC;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,YAAY,MAAc,QAAsC;AACpE,UAAM,UAAU,MAAM,KAAK,IAAI,IAAI;AACnC,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,UAAM,KAAK,OAAO,EAAE,GAAG,SAAS,QAAQ,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AAAA,EAC/E;AAAA,EAEA,MAAM,OAAO,MAA6B;AACxC,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,UAAM,KAAK,SAAS,EAAE,WAAW,KAAK,UAAU,OAAO,CAAC,UAAU,MAAM,SAAS,IAAI,EAAE,CAAC;AAAA,EAC1F;AACF;;;AF7DO,IAAM,6BAAN,MAAiC;AAAA,EACtC,YAAoB,OAAiF,CAAC,GAAG;AAArF;AAAA,EAAsF;AAAA,EAE1G,IAAY,WAA4B;AACtC,WAAO,KAAK,KAAK,aAAa,KAAK,KAAK,WAAW,IAAI,gBAAgB;AAAA,EACzE;AAAA,EAEA,IAAY,gBAA0C;AACpD,WAAO,KAAK,KAAK,kBAAkB,KAAK,KAAK,gBAAgB,IAAI,qBAAqB;AAAA,EACxF;AAAA,EAEQ,WAAW,QAUjB;AACA,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,MACb,QAAQ,OAAO;AAAA,MACf,OAAO,OAAO;AAAA,MACd,MAAM,OAAO;AAAA,MACb,WAAW,OAAO;AAAA,MAClB,UAAU,OAAO,KAAK,OAAO,GAAG,EAAE;AAAA,MAClC,aAAa,OAAO,KAAK,OAAO,OAAO,EAAE;AAAA,MACzC,WAAW,OAAO;AAAA,MAClB,WAAW,OAAO;AAAA,IACpB;AAAA,EACF;AAAA,EAEQ,aAAa,SAA8E;AACjG,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,IACT;AAEA,WAAO,OAAO;AAAA,MACZ,OAAO,QAAQ,OAAO,EAAE,IAAI,CAAC,CAAC,WAAW,UAAU,MAAM,CAAC,WAAW,KAAK,YAAY,UAAU,CAAC,CAAC;AAAA,IACpG;AAAA,EACF;AAAA,EAEQ,YAAY,YAAmC;AACrD,QAAI,WAAW,SAAS,QAAQ;AAC9B,aAAO,2BAAM,KAAK,WAAW,QAAQ,EAAE,UAAU,WAAW,YAAY,MAAM,CAAC;AAAA,IACjF;AAEA,QAAI,WAAW,SAAS,SAAS;AAC/B,aAAO,2BAAM,MAAM,WAAW,MAAM,EAAE,UAAU,WAAW,YAAY,MAAM,CAAC;AAAA,IAChF;AAEA,WAAO,2BAAM,MAAM,EAAE,SAAS,WAAW,QAAQ,CAAC;AAAA,EACpD;AAAA,EAEQ,UAAU,MAA6B;AAC7C,WAAO,KAAK,SAAS,IAAI,IAAI;AAAA,EAC/B;AAAA,EAEA,MAAc,kBAAkB,MAAsC;AACpE,QAAI;AACF,aAAO,KAAK,UAAU,IAAI;AAAA,IAC5B,QAAQ;AACN,aAAQ,MAAM,KAAK,SAAS,OAAO,IAAI;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,MAAc,OAG/B;AACD,UAAM,QAAQ,MAAM,SAAS,QAAQ,IAAI,sBAAsB;AAC/D,UAAM,OAAO,MAAM,QAAQ,OAAO,QAAQ,IAAI,qBAAqB,GAAG;AACtE,UAAM,YAAY,MAAM,aAAa,OAAO,QAAQ,IAAI,uBAAuB,KAAK;AAEpF,UAAM,KAAK,SAAS,OAAO,MAAM;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,MAAM;AAAA,MACX,SAAS,KAAK,aAAa,MAAM,OAAO;AAAA,IAC1C,CAAC;AAED,UAAM,WAAW,MAAM,KAAK,cAAc,IAAI,IAAI;AAClD,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AAEnC,UAAM,KAAK,cAAc,OAAO;AAAA,MAC9B;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,MAAM,OAAO,CAAC;AAAA,MACnB,SAAS,MAAM,WAAW,CAAC;AAAA,MAC3B,WAAW,UAAU,aAAa;AAAA,MAClC,WAAW;AAAA,IACb,CAAC;AAED,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,MAAyD;AAC1E,UAAM,6BAAQ,MAAM,IAAI;AACxB,SAAK,SAAS,OAAO,IAAI;AACzB,UAAM,KAAK,SAAS,OAAO,IAAI;AAC/B,UAAM,KAAK,cAAc,YAAY,MAAM,SAAS;AACpD,WAAO,EAAE,MAAM,QAAQ,UAAU;AAAA,EACnC;AAAA,EAEA,MAAM,YAAY,MAAyD;AACzE,UAAM,SAAS,MAAM,KAAK,kBAAkB,IAAI;AAChD,UAAM,OAAO,KAAK;AAClB,SAAK,SAAS,OAAO,IAAI;AACzB,UAAM,KAAK,cAAc,YAAY,MAAM,SAAS;AACpD,WAAO,EAAE,MAAM,QAAQ,UAAU;AAAA,EACnC;AAAA,EAEA,MAAM,YAAY,MAAyD;AACzE,UAAM,SAAS,MAAM,KAAK,kBAAkB,IAAI;AAChD,UAAM,OAAO,KAAK;AAClB,SAAK,SAAS,OAAO,IAAI;AACzB,UAAM,KAAK,cAAc,YAAY,MAAM,SAAS;AACpD,WAAO,EAAE,MAAM,QAAQ,UAAU;AAAA,EACnC;AAAA,EAEA,MAAM,cAAc,MAAyD;AAC3E,QAAI;AACF,YAAM,KAAK,UAAU,IAAI,EAAE,KAAK;AAAA,IAClC,QAAQ;AAAA,IAER;AAEA,UAAM,6BAAQ,OAAO,IAAI;AACzB,SAAK,SAAS,OAAO,IAAI;AACzB,UAAM,KAAK,cAAc,OAAO,IAAI;AAEpC,WAAO,EAAE,MAAM,QAAQ,UAAU;AAAA,EACnC;AAAA,EAEA,MAAM,cAAc,QAajB;AACD,UAAM,SAAS,MAAM,KAAK,cAAc,KAAK,GAC1C,OAAO,CAAC,WAAW;AAClB,UAAI,OAAO,UAAU,OAAO,WAAW,OAAO,QAAQ;AACpD,eAAO;AAAA,MACT;AAEA,UAAI,OAAO,SAAS,OAAO,UAAU,OAAO,OAAO;AACjD,eAAO;AAAA,MACT;AAEA,UAAI,OAAO,QAAQ;AACjB,cAAM,WAAW,CAAC,OAAO,MAAM,OAAO,OAAO,GAAG,OAAO,KAAK,OAAO,GAAG,CAAC,EACpE,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC,EACjD,KAAK,GAAG,EACR,YAAY;AAEf,YAAI,CAAC,SAAS,SAAS,OAAO,OAAO,YAAY,CAAC,GAAG;AACnD,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,aAAO;AAAA,IACT,CAAC,EACA,IAAI,CAAC,WAAW,KAAK,WAAW,MAAM,CAAC;AAE1C,WAAO,EAAE,OAAO,OAAO,MAAM,OAAO;AAAA,EACtC;AAAA,EAEA,MAAM,WAAW,MAA0D;AACzE,WAAO,MAAM,KAAK,cAAc,IAAI,IAAI;AAAA,EAC1C;AAAA,EAEA,MAAM,UAAU,MAAyD;AACvE,QAAI;AACF,WAAK,UAAU,IAAI;AACnB,aAAO,EAAE,MAAM,QAAQ,UAAU;AAAA,IACnC,QAAQ;AACN,aAAO,EAAE,MAAM,QAAQ,UAAU;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,aAAqB,MAA0D;AAC5F,UAAM,UAAU,MAAM,KAAK,UAAU,WAAW,EAAE,GAAG,EAAE,WAAW,IAAI;AACtE,WAAO,EAAE,MAAM,QAAQ;AAAA,EACzB;AAAA,EAEA,MAAM,UAAU,aAAqB,MAAc,SAA4C;AAC7F,UAAM,KAAK,UAAU,WAAW,EAAE,GAAG,EAAE,MAAM,MAAM,OAAO,KAAK,OAAO,CAAC;AACvE,WAAO,EAAE,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,SACJ,aACA,MACA,WAC6D;AAC7D,UAAM,UAAU,MAAM,KAAK,UAAU,WAAW,EAAE,GAAG,EAAE,KAAK,MAAM,EAAE,UAAU,CAAC;AAC/E,WAAO;AAAA,MACL,SAAS,QAAQ,IAAI,CAAC,WAAW;AAAA,QAC/B,MAAM,MAAM;AAAA,QACZ,MAAM,MAAM;AAAA,MACd,EAAE;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,aAAqB,MAAc,SAA+C;AAChG,UAAM,SAAS,MAAM,KAAK,UAAU,WAAW,EAAE,eAAe;AAAA,MAC9D,KAAK;AAAA,MACL,MAAM,CAAC,MAAM,SAAS,SAAS,SAAS,GAAG;AAAA,IAC7C,CAAC;AACD,WAAO,EAAE,OAAO,OAAO,OAAO,EAAE,MAAM,IAAI,EAAE,OAAO,OAAO,EAAE;AAAA,EAC9D;AAAA,EAEA,MAAM,aACJ,aACA,MACA,OACgE;AAChE,QAAI;AAEJ,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,UAAU,WAAW,EAAE,eAAe;AAAA,QAC9D,KAAK;AAAA,QACL,MAAM,CAAC,MAAM,MAAM,OAAO,IAAI;AAAA,MAChC,CAAC;AACD,eAAS,OAAO,OAAO;AAAA,IACzB,SAAS,OAAO;AACd,UAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,SAAS,MAAM,SAAS,GAAG;AACtF,eAAO,EAAE,SAAS,CAAC,EAAE;AAAA,MACvB;AAEA,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,MACL,SAAS,OACN,MAAM,IAAI,EACV,OAAO,OAAO,EACd,IAAI,CAAC,SAAS;AACb,cAAM,YAAY,KAAK,QAAQ,GAAG;AAClC,eAAO;AAAA,UACL,MAAM,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;AAAA,UACrC,SAAS,KAAK,MAAM,YAAY,CAAC;AAAA,QACnC;AAAA,MACF,CAAC;AAAA,IACL;AAAA,EACF;AAAA,EAEA,MAAM,cACJ,aACA,OAC+B;AAC/B,UAAM,KAAK,KAAK,UAAU,WAAW,EAAE,GAAG;AAC1C,UAAM,WAAW,MAAM,GAAG,WAAW,MAAM,IAAI;AAE/C,QAAI,CAAC,MAAM,QAAQ;AACjB,aAAO,EAAE,UAAU,EAAE;AAAA,IACvB;AAEA,UAAM,cAAc,SAAS,MAAM,MAAM,MAAM,EAAE,SAAS;AAC1D,QAAI,gBAAgB,GAAG;AACrB,aAAO,EAAE,UAAU,EAAE;AAAA,IACvB;AAEA,UAAM,UAAU,SAAS,MAAM,MAAM,MAAM,EAAE,KAAK,MAAM,OAAO;AAC/D,UAAM,GAAG,MAAM,MAAM,MAAM,OAAO,KAAK,OAAO,CAAC;AAE/C,WAAO,EAAE,UAAU,YAAY;AAAA,EACjC;AAAA,EAEA,MAAM,WAAW,aAAqB,MAAc,eAAkD;AACpG,UAAM,KAAK,UAAU,WAAW,EAAE,GAAG,EAAE,MAAM,MAAM,OAAO,KAAK,eAAe,QAAQ,CAAC;AACvF,WAAO,EAAE,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,aAAa,aAAqB,MAAgE;AACtG,UAAM,OAAO,MAAM,KAAK,UAAU,WAAW,EAAE,GAAG,EAAE,KAAK,IAAI;AAC7D,UAAM,SAAS,OAAO,SAAS,IAAI,IAAI,OAAO,OAAO,KAAK,IAAI;AAC9D,WAAO,EAAE,MAAM,eAAe,OAAO,SAAS,QAAQ,EAAE;AAAA,EAC1D;AAAA,EAEA,MAAM,YAAY,OAAsF;AACtG,UAAM,SAAS,MAAM,KAAK,UAAU,MAAM,WAAW,EAAE,eAAe;AAAA,MACpE,KAAK;AAAA,MACL,MAAM,CAAC,MAAM,MAAM,OAAO;AAAA,MAC1B,KAAK,MAAM;AAAA,MACX,WAAW,MAAM,UAAU,MAAM,UAAU,MAAO;AAAA,IACpD,CAAC;AAED,WAAO;AAAA,MACL,QAAQ,OAAO,OAAO;AAAA,MACtB,QAAQ,OAAO,SAAS,OAAO,OAAO,IAAI;AAAA,MAC1C,UAAU,OAAO,QAAQ;AAAA,IAC3B;AAAA,EACF;AACF;;;AXhVO,SAAS,SAAS;AAAA,EACvB,iBAAiB,IAAI,2BAA2B;AAAA,EAChD,eAAe,IAAI,aAAa;AAClC,IAGI,CAAC,GAAoB;AACvB,QAAM,UAAM,eAAAC,SAAQ,EAAE,QAAQ,MAAM,CAAC;AAErC,MAAI,SAAS,YAAAC,SAAM,EAAE,QAAQ,KAAK,CAAC;AACnC,MAAI,SAAS,gBAAAC,OAAQ;AACrB,MAAI,SAAS,iBAAAC,OAAS;AAEtB,uBAAqB,GAAG;AACxB,wBAAsB,KAAK,cAAc;AACzC,sBAAoB,KAAK,YAAY;AAErC,MAAI,gBAAgB,CAAC,OAAO,UAAU,UAAU;AAC9C,UAAM,EAAE,YAAY,KAAK,IAAI,gBAAgB,KAAK;AAClD,UAAM,OAAO,UAAU,EAAE,KAAK,IAAI;AAAA,EACpC,CAAC;AAED,SAAO;AACT;;;AczBA,SAAS,UAAU,KAAa,QAAwB;AACtD,QAAM,QAAQ,OAAO,GAAG;AACxB,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,SAAS,GAAG;AAC1C,UAAM,IAAI,MAAM,qBAAqB,MAAM,KAAK,GAAG,EAAE;AAAA,EACvD;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,MAAkC;AAChE,QAAM,SAA2B,CAAC;AAElC,WAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;AACnD,UAAM,QAAQ,KAAK,KAAK;AAExB,QAAI,UAAU,UAAU;AACtB,YAAM,MAAM,KAAK,QAAQ,CAAC;AAC1B,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC5C;AACA,aAAO,OAAO,UAAU,KAAK,QAAQ;AACrC,eAAS;AACT;AAAA,IACF;AAEA,QAAI,UAAU,UAAU;AACtB,YAAM,MAAM,KAAK,QAAQ,CAAC;AAC1B,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC5C;AACA,aAAO,OAAO;AACd,eAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AACF,GAGyB;AACvB,SAAO;AAAA,IACL,MAAM,KAAK,QAAQ,IAAI,QAAQ;AAAA,IAC/B,MAAM,KAAK,SAAS,IAAI,OAAO,UAAU,IAAI,MAAM,MAAM,IAAI;AAAA,EAC/D;AACF;;;ACtDA,eAAsB,YAAY;AAAA,EAChC,OAAO,QAAQ,KAAK,MAAM,CAAC;AAAA,EAC3B,MAAM,QAAQ;AAAA,EACd,MAAM,SAAS;AACjB,IAII,CAAC,GAAuD;AAC1D,QAAM,SAAS,oBAAoB,EAAE,MAAM,gBAAgB,IAAI,GAAG,IAAI,CAAC;AAEvE,QAAM,WAAW,OAAO,SAAgC;AACtD,QAAI;AACF,YAAM,IAAI,MAAM;AAChB,cAAQ,KAAK,IAAI;AAAA,IACnB,SAAS,OAAO;AACd,cAAQ,MAAM,mDAAmD,KAAK;AACtE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,UAAQ,KAAK,UAAU,MAAM;AAC3B,SAAK,SAAS,CAAC;AAAA,EACjB,CAAC;AAED,UAAQ,KAAK,WAAW,MAAM;AAC5B,SAAK,SAAS,CAAC;AAAA,EACjB,CAAC;AAED,QAAM,IAAI,OAAO,EAAE,MAAM,OAAO,MAAM,MAAM,OAAO,KAAK,CAAC;AACzD,SAAO;AACT;AAEA,IAAI,QAAQ,SAAS,QAAQ;AAC3B,OAAK,YAAY,EAAE,MAAM,CAAC,UAAU;AAClC,YAAQ,MAAM,wCAAwC,KAAK;AAC3D,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;;;ACtCA,KAAK,YAAY,EAAE,MAAM,CAAC,UAAU;AAClC,UAAQ,MAAM,wCAAwC,KAAK;AAC3D,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["import_zod","z","import_zod","z","import_microsandbox","fastify","cors","sensible","multipart"]}
1
+ {"version":3,"sources":["../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/services/ImageService.ts","../src/services/MicrosandboxRuntimeService.ts","../src/services/SandboxRegistry.ts","../src/services/SandboxMetadataStore.ts","../src/lib/server-cli.ts","../src/server.ts","../src/cli.ts"],"sourcesContent":["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 { 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}: {\n runtimeService?: RuntimeService;\n imageService?: ImageService;\n} = {}): FastifyInstance {\n const app = fastify({ logger: false });\n\n app.register(cors, { origin: true });\n app.register(sensible);\n app.register(multipart);\n\n registerHealthRoutes(app);\n registerSandboxRoutes(app, runtimeService);\n registerImageRoutes(app, imageService);\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\", \"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 return reply.send(ok(await runtimeService.uploadFile(body.sandboxName, body.path, body.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 { PullImageInput } from \"../schemas/images\";\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\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\nexport class ImageService {\n constructor(\n private readonly deps: {\n bindings?: ImageBindings;\n } = {}\n ) {}\n\n private get bindings(): ImageBindings {\n return (\n this.deps.bindings ?? {\n list: async () => [],\n pull: async (ref: string) => ({ ref, sourceType: \"oci\", cached: true }),\n inspect: async (ref: string) => ({ ref, sourceType: \"oci\", cached: true }),\n remove: async () => undefined,\n }\n );\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","import { Mount, Sandbox } from \"microsandbox\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport { SandboxRegistry } from \"./SandboxRegistry\";\nimport {\n SandboxMetadataStore,\n type SandboxMetadataRecord,\n type SandboxMetadataStoreLike,\n} from \"./SandboxMetadataStore\";\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(\n path: string,\n options?: { recursive?: boolean }\n ): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;\n read(path: string): Promise<Buffer | Uint8Array | string>;\n };\n execWithConfig(config: {\n cmd: string;\n args?: string[];\n cwd?: string;\n timeoutMs?: number;\n }): Promise<{\n stdout(): string;\n stderr?(): string;\n code?: number;\n }>;\n stop(): Promise<void>;\n kill(): Promise<void>;\n};\n\nexport class MicrosandboxRuntimeService {\n constructor(private deps: { registry?: SandboxRegistry; metadataStore?: SandboxMetadataStoreLike } = {}) {}\n\n private get registry(): SandboxRegistry {\n return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());\n }\n\n private get metadataStore(): SandboxMetadataStoreLike {\n return this.deps.metadataStore ?? (this.deps.metadataStore = new SandboxMetadataStore());\n }\n\n private toListItem(record: SandboxMetadataRecord): {\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 return {\n name: record.name,\n status: record.status,\n image: record.image,\n cpus: record.cpus,\n memoryMib: record.memoryMib,\n envCount: Object.keys(record.env).length,\n volumeCount: Object.keys(record.volumes).length,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n };\n }\n\n private buildVolumes(volumes?: EnsureSandboxInput[\"volumes\"]): Record<string, unknown> | undefined {\n if (!volumes) {\n return undefined;\n }\n\n return Object.fromEntries(\n Object.entries(volumes).map(([mountPath, definition]) => [mountPath, this.buildVolume(definition)])\n );\n }\n\n private buildVolume(definition: VolumeConfig): unknown {\n if (definition.type === \"bind\") {\n return Mount.bind(definition.source, { readonly: definition.readonly ?? false });\n }\n\n if (definition.type === \"named\") {\n return Mount.named(definition.name, { readonly: definition.readonly ?? false });\n }\n\n return Mount.tmpfs({ sizeMib: definition.sizeMib });\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(name: string, input: EnsureSandboxInput): 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.registry.ensure(name, {\n image,\n cpus,\n memoryMib,\n env: input.env,\n volumes: this.buildVolumes(input.volumes),\n });\n\n const existing = await this.metadataStore.get(name);\n const now = new Date().toISOString();\n\n await this.metadataStore.upsert({\n name,\n status: \"running\",\n image,\n cpus,\n memoryMib,\n env: input.env ?? {},\n volumes: input.volumes ?? {},\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\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 await this.metadataStore.patchStatus(name, \"running\");\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 await this.metadataStore.patchStatus(name, \"stopped\");\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 await this.metadataStore.patchStatus(name, \"unknown\");\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 await this.metadataStore.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 items = (await this.metadataStore.list())\n .filter((record) => {\n if (_query.status && record.status !== _query.status) {\n return false;\n }\n\n if (_query.image && record.image !== _query.image) {\n return false;\n }\n\n if (_query.search) {\n const haystack = [record.name, record.image, ...Object.keys(record.env)]\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 .map((record) => this.toListItem(record));\n\n return { items, total: items.length };\n }\n\n async getSandbox(name: string): Promise<SandboxMetadataRecord | undefined> {\n return await this.metadataStore.get(name);\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n try {\n this.getNative(name);\n return { name, status: \"running\" };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const content = await this.getNative(sandboxName).fs().readString(path);\n return { path, content };\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n await this.getNative(sandboxName).fs().write(path, Buffer.from(content));\n return { path };\n }\n\n async listPath(\n sandboxName: string,\n path: string,\n recursive?: boolean\n ): Promise<{ entries: Array<{ path: string; type: string }> }> {\n const entries = await this.getNative(sandboxName).fs().list(path, { recursive });\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 output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"find\",\n args: [path, \"-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 let stdout: string;\n\n try {\n const output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"grep\",\n args: [\"-n\", \"-E\", query, path],\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 fs = this.getNative(sandboxName).fs();\n const original = await fs.readString(input.path);\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(input.path, Buffer.from(updated));\n\n return { replaced: occurrences };\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n await this.getNative(sandboxName).fs().write(path, Buffer.from(contentBase64, \"base64\"));\n return { path };\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const data = await this.getNative(sandboxName).fs().read(path);\n const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);\n return { path, 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 ? output.stderr() : \"\",\n exitCode: output.code ?? 0,\n };\n }\n}\n","import { Sandbox } 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 createConfig = {\n name,\n image: DEFAULT_IMAGE,\n ...(createOptions ?? {}),\n };\n\n try {\n const handle = 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 }\n } catch {\n native = undefined;\n }\n\n if (!native) {\n native = await Sandbox.createDetached(createConfig);\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 { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { EnsureSandboxInput } from \"../schemas/sandbox\";\n\nexport type SandboxStatus = \"running\" | \"stopped\" | \"unknown\";\n\nexport type SandboxMetadataRecord = {\n name: string;\n status: SandboxStatus;\n image?: string;\n cpus?: number;\n memoryMib?: number;\n env: Record<string, string>;\n volumes: NonNullable<EnsureSandboxInput[\"volumes\"]>;\n createdAt: string;\n updatedAt: string;\n};\n\ntype SandboxMetadataFile = {\n sandboxes: SandboxMetadataRecord[];\n};\n\nfunction isSandboxMetadataFile(value: unknown): value is SandboxMetadataFile {\n return typeof value === \"object\" && value !== null && \"sandboxes\" in value && Array.isArray(value.sandboxes);\n}\n\nexport interface SandboxMetadataStoreLike {\n list(): Promise<SandboxMetadataRecord[]>;\n get(name: string): Promise<SandboxMetadataRecord | undefined>;\n upsert(record: SandboxMetadataRecord): Promise<SandboxMetadataRecord>;\n patchStatus(name: string, status: SandboxStatus): Promise<void>;\n remove(name: string): Promise<void>;\n}\n\nexport class SandboxMetadataStore implements SandboxMetadataStoreLike {\n constructor(private readonly options: { filePath?: string } = {}) {}\n\n private get filePath(): string {\n return this.options.filePath ?? process.env.MICROSANDBOX_METADATA_FILE ?? \".microsandbox/metadata.json\";\n }\n\n private async readAll(): Promise<SandboxMetadataFile> {\n try {\n const content = await readFile(this.filePath, \"utf8\");\n const parsed: unknown = JSON.parse(content);\n\n if (!isSandboxMetadataFile(parsed)) {\n throw new Error(\"Invalid sandbox metadata file\");\n }\n\n return parsed;\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") {\n return { sandboxes: [] };\n }\n\n throw error;\n }\n }\n\n private async writeAll(file: SandboxMetadataFile): Promise<void> {\n await mkdir(dirname(this.filePath), { recursive: true });\n await writeFile(this.filePath, JSON.stringify(file, null, 2));\n }\n\n async list(): Promise<SandboxMetadataRecord[]> {\n const file = await this.readAll();\n return file.sandboxes.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n }\n\n async get(name: string): Promise<SandboxMetadataRecord | undefined> {\n const file = await this.readAll();\n return file.sandboxes.find((entry) => entry.name === name);\n }\n\n async upsert(record: SandboxMetadataRecord): Promise<SandboxMetadataRecord> {\n const file = await this.readAll();\n const next = file.sandboxes.filter((entry) => entry.name !== record.name);\n next.push(record);\n await this.writeAll({ sandboxes: next });\n return record;\n }\n\n async patchStatus(name: string, status: SandboxStatus): Promise<void> {\n const current = await this.get(name);\n if (!current) {\n return;\n }\n\n await this.upsert({ ...current, status, updatedAt: new Date().toISOString() });\n }\n\n async remove(name: string): Promise<void> {\n const file = await this.readAll();\n await this.writeAll({ sandboxes: file.sandboxes.filter((entry) => entry.name !== name) });\n }\n}\n","export interface ParsedServerArgs {\n host?: string;\n port?: number;\n}\n\nexport interface ResolvedServerConfig {\n host: string;\n port: number;\n}\n\nfunction parsePort(raw: string, source: string): number {\n const value = Number(raw);\n if (!Number.isInteger(value) || value <= 0) {\n throw new Error(`Invalid value for ${source}: ${raw}`);\n }\n return value;\n}\n\nexport function parseServerArgs(argv: string[]): ParsedServerArgs {\n const parsed: ParsedServerArgs = {};\n\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index];\n\n if (token === \"--port\") {\n const raw = argv[index + 1];\n if (!raw) {\n throw new Error(\"Missing value for --port\");\n }\n parsed.port = parsePort(raw, \"--port\");\n index += 1;\n continue;\n }\n\n if (token === \"--host\") {\n const raw = argv[index + 1];\n if (!raw) {\n throw new Error(\"Missing value for --host\");\n }\n parsed.host = raw;\n index += 1;\n }\n }\n\n return parsed;\n}\n\nexport function resolveServerConfig({\n args,\n env,\n}: {\n args: ParsedServerArgs;\n env: NodeJS.ProcessEnv;\n}): ResolvedServerConfig {\n return {\n host: args.host ?? env.HOST ?? \"0.0.0.0\",\n port: args.port ?? (env.PORT ? parsePort(env.PORT, \"PORT\") : 4002),\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { buildApp } from \"./app\";\nimport { parseServerArgs, resolveServerConfig } from \"./lib/server-cli\";\n\nexport async function startServer({\n argv = process.argv.slice(2),\n env = process.env,\n app = buildApp(),\n}: {\n argv?: string[];\n env?: NodeJS.ProcessEnv;\n app?: Pick<FastifyInstance, \"listen\" | \"close\">;\n} = {}): Promise<Pick<FastifyInstance, \"listen\" | \"close\">> {\n const config = resolveServerConfig({ args: parseServerArgs(argv), env });\n\n const shutdown = async (code: number): Promise<void> => {\n try {\n await app.close();\n process.exit(code);\n } catch (error) {\n console.error(\"Failed to shutdown microsandbox-service cleanly\", error);\n process.exit(1);\n }\n };\n\n process.once(\"SIGINT\", () => {\n void shutdown(0);\n });\n\n process.once(\"SIGTERM\", () => {\n void shutdown(0);\n });\n\n await app.listen({ port: config.port, host: config.host });\n return app;\n}\n","#!/usr/bin/env node\n\nimport { startServer } from \"./server\";\n\nvoid startServer().catch((error) => {\n console.error(\"Failed to start microsandbox-service\", error);\n process.exit(1);\n});\n"],"mappings":"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","names":["import_zod","z","import_zod","z","import_microsandbox","fastify","cors","sensible","multipart"]}
package/dist/cli.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startServer
4
- } from "./chunk-CSOLG3XA.mjs";
5
- import "./chunk-D5L33FAA.mjs";
4
+ } from "./chunk-KRXZP6OH.mjs";
5
+ import "./chunk-VM3OJT5V.mjs";
6
6
 
7
7
  // src/cli.ts
8
8
  void startServer().catch((error) => {
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  MicrosandboxRuntimeService,
3
3
  SandboxRegistry,
4
4
  buildApp
5
- } from "./chunk-D5L33FAA.mjs";
5
+ } from "./chunk-VM3OJT5V.mjs";
6
6
  export {
7
7
  MicrosandboxRuntimeService,
8
8
  SandboxRegistry,
package/dist/server.js CHANGED
@@ -775,12 +775,6 @@ async function startServer({
775
775
  await app.listen({ port: config.port, host: config.host });
776
776
  return app;
777
777
  }
778
- if (require.main === module) {
779
- void startServer().catch((error) => {
780
- console.error("Failed to start microsandbox-service", error);
781
- process.exit(1);
782
- });
783
- }
784
778
  // Annotate the CommonJS export names for ESM import in node:
785
779
  0 && (module.exports = {
786
780
  startServer
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.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/services/ImageService.ts","../src/services/MicrosandboxRuntimeService.ts","../src/services/SandboxRegistry.ts","../src/services/SandboxMetadataStore.ts","../src/lib/server-cli.ts"],"sourcesContent":["import type { FastifyInstance } from \"fastify\";\nimport { buildApp } from \"./app\";\nimport { parseServerArgs, resolveServerConfig } from \"./lib/server-cli\";\n\nexport async function startServer({\n argv = process.argv.slice(2),\n env = process.env,\n app = buildApp(),\n}: {\n argv?: string[];\n env?: NodeJS.ProcessEnv;\n app?: Pick<FastifyInstance, \"listen\" | \"close\">;\n} = {}): Promise<Pick<FastifyInstance, \"listen\" | \"close\">> {\n const config = resolveServerConfig({ args: parseServerArgs(argv), env });\n\n const shutdown = async (code: number): Promise<void> => {\n try {\n await app.close();\n process.exit(code);\n } catch (error) {\n console.error(\"Failed to shutdown microsandbox-service cleanly\", error);\n process.exit(1);\n }\n };\n\n process.once(\"SIGINT\", () => {\n void shutdown(0);\n });\n\n process.once(\"SIGTERM\", () => {\n void shutdown(0);\n });\n\n await app.listen({ port: config.port, host: config.host });\n return app;\n}\n\nif (require.main === module) {\n void startServer().catch((error) => {\n console.error(\"Failed to start microsandbox-service\", error);\n process.exit(1);\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 { 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}: {\n runtimeService?: RuntimeService;\n imageService?: ImageService;\n} = {}): FastifyInstance {\n const app = fastify({ logger: false });\n\n app.register(cors, { origin: true });\n app.register(sensible);\n app.register(multipart);\n\n registerHealthRoutes(app);\n registerSandboxRoutes(app, runtimeService);\n registerImageRoutes(app, imageService);\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\", \"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 return reply.send(ok(await runtimeService.uploadFile(body.sandboxName, body.path, body.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 { PullImageInput } from \"../schemas/images\";\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\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\nexport class ImageService {\n constructor(\n private readonly deps: {\n bindings?: ImageBindings;\n } = {}\n ) {}\n\n private get bindings(): ImageBindings {\n return (\n this.deps.bindings ?? {\n list: async () => [],\n pull: async (ref: string) => ({ ref, sourceType: \"oci\", cached: true }),\n inspect: async (ref: string) => ({ ref, sourceType: \"oci\", cached: true }),\n remove: async () => undefined,\n }\n );\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","import { Mount, Sandbox } from \"microsandbox\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport { SandboxRegistry } from \"./SandboxRegistry\";\nimport {\n SandboxMetadataStore,\n type SandboxMetadataRecord,\n type SandboxMetadataStoreLike,\n} from \"./SandboxMetadataStore\";\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(\n path: string,\n options?: { recursive?: boolean }\n ): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;\n read(path: string): Promise<Buffer | Uint8Array | string>;\n };\n execWithConfig(config: {\n cmd: string;\n args?: string[];\n cwd?: string;\n timeoutMs?: number;\n }): Promise<{\n stdout(): string;\n stderr?(): string;\n code?: number;\n }>;\n stop(): Promise<void>;\n kill(): Promise<void>;\n};\n\nexport class MicrosandboxRuntimeService {\n constructor(private deps: { registry?: SandboxRegistry; metadataStore?: SandboxMetadataStoreLike } = {}) {}\n\n private get registry(): SandboxRegistry {\n return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());\n }\n\n private get metadataStore(): SandboxMetadataStoreLike {\n return this.deps.metadataStore ?? (this.deps.metadataStore = new SandboxMetadataStore());\n }\n\n private toListItem(record: SandboxMetadataRecord): {\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 return {\n name: record.name,\n status: record.status,\n image: record.image,\n cpus: record.cpus,\n memoryMib: record.memoryMib,\n envCount: Object.keys(record.env).length,\n volumeCount: Object.keys(record.volumes).length,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n };\n }\n\n private buildVolumes(volumes?: EnsureSandboxInput[\"volumes\"]): Record<string, unknown> | undefined {\n if (!volumes) {\n return undefined;\n }\n\n return Object.fromEntries(\n Object.entries(volumes).map(([mountPath, definition]) => [mountPath, this.buildVolume(definition)])\n );\n }\n\n private buildVolume(definition: VolumeConfig): unknown {\n if (definition.type === \"bind\") {\n return Mount.bind(definition.source, { readonly: definition.readonly ?? false });\n }\n\n if (definition.type === \"named\") {\n return Mount.named(definition.name, { readonly: definition.readonly ?? false });\n }\n\n return Mount.tmpfs({ sizeMib: definition.sizeMib });\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(name: string, input: EnsureSandboxInput): 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.registry.ensure(name, {\n image,\n cpus,\n memoryMib,\n env: input.env,\n volumes: this.buildVolumes(input.volumes),\n });\n\n const existing = await this.metadataStore.get(name);\n const now = new Date().toISOString();\n\n await this.metadataStore.upsert({\n name,\n status: \"running\",\n image,\n cpus,\n memoryMib,\n env: input.env ?? {},\n volumes: input.volumes ?? {},\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\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 await this.metadataStore.patchStatus(name, \"running\");\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 await this.metadataStore.patchStatus(name, \"stopped\");\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 await this.metadataStore.patchStatus(name, \"unknown\");\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 await this.metadataStore.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 items = (await this.metadataStore.list())\n .filter((record) => {\n if (_query.status && record.status !== _query.status) {\n return false;\n }\n\n if (_query.image && record.image !== _query.image) {\n return false;\n }\n\n if (_query.search) {\n const haystack = [record.name, record.image, ...Object.keys(record.env)]\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 .map((record) => this.toListItem(record));\n\n return { items, total: items.length };\n }\n\n async getSandbox(name: string): Promise<SandboxMetadataRecord | undefined> {\n return await this.metadataStore.get(name);\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n try {\n this.getNative(name);\n return { name, status: \"running\" };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const content = await this.getNative(sandboxName).fs().readString(path);\n return { path, content };\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n await this.getNative(sandboxName).fs().write(path, Buffer.from(content));\n return { path };\n }\n\n async listPath(\n sandboxName: string,\n path: string,\n recursive?: boolean\n ): Promise<{ entries: Array<{ path: string; type: string }> }> {\n const entries = await this.getNative(sandboxName).fs().list(path, { recursive });\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 output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"find\",\n args: [path, \"-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 let stdout: string;\n\n try {\n const output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"grep\",\n args: [\"-n\", \"-E\", query, path],\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 fs = this.getNative(sandboxName).fs();\n const original = await fs.readString(input.path);\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(input.path, Buffer.from(updated));\n\n return { replaced: occurrences };\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n await this.getNative(sandboxName).fs().write(path, Buffer.from(contentBase64, \"base64\"));\n return { path };\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const data = await this.getNative(sandboxName).fs().read(path);\n const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);\n return { path, 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 ? output.stderr() : \"\",\n exitCode: output.code ?? 0,\n };\n }\n}\n","import { Sandbox } 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 createConfig = {\n name,\n image: DEFAULT_IMAGE,\n ...(createOptions ?? {}),\n };\n\n try {\n const handle = 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 }\n } catch {\n native = undefined;\n }\n\n if (!native) {\n native = await Sandbox.createDetached(createConfig);\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 { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { EnsureSandboxInput } from \"../schemas/sandbox\";\n\nexport type SandboxStatus = \"running\" | \"stopped\" | \"unknown\";\n\nexport type SandboxMetadataRecord = {\n name: string;\n status: SandboxStatus;\n image?: string;\n cpus?: number;\n memoryMib?: number;\n env: Record<string, string>;\n volumes: NonNullable<EnsureSandboxInput[\"volumes\"]>;\n createdAt: string;\n updatedAt: string;\n};\n\ntype SandboxMetadataFile = {\n sandboxes: SandboxMetadataRecord[];\n};\n\nfunction isSandboxMetadataFile(value: unknown): value is SandboxMetadataFile {\n return typeof value === \"object\" && value !== null && \"sandboxes\" in value && Array.isArray(value.sandboxes);\n}\n\nexport interface SandboxMetadataStoreLike {\n list(): Promise<SandboxMetadataRecord[]>;\n get(name: string): Promise<SandboxMetadataRecord | undefined>;\n upsert(record: SandboxMetadataRecord): Promise<SandboxMetadataRecord>;\n patchStatus(name: string, status: SandboxStatus): Promise<void>;\n remove(name: string): Promise<void>;\n}\n\nexport class SandboxMetadataStore implements SandboxMetadataStoreLike {\n constructor(private readonly options: { filePath?: string } = {}) {}\n\n private get filePath(): string {\n return this.options.filePath ?? process.env.MICROSANDBOX_METADATA_FILE ?? \".microsandbox/metadata.json\";\n }\n\n private async readAll(): Promise<SandboxMetadataFile> {\n try {\n const content = await readFile(this.filePath, \"utf8\");\n const parsed: unknown = JSON.parse(content);\n\n if (!isSandboxMetadataFile(parsed)) {\n throw new Error(\"Invalid sandbox metadata file\");\n }\n\n return parsed;\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") {\n return { sandboxes: [] };\n }\n\n throw error;\n }\n }\n\n private async writeAll(file: SandboxMetadataFile): Promise<void> {\n await mkdir(dirname(this.filePath), { recursive: true });\n await writeFile(this.filePath, JSON.stringify(file, null, 2));\n }\n\n async list(): Promise<SandboxMetadataRecord[]> {\n const file = await this.readAll();\n return file.sandboxes.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n }\n\n async get(name: string): Promise<SandboxMetadataRecord | undefined> {\n const file = await this.readAll();\n return file.sandboxes.find((entry) => entry.name === name);\n }\n\n async upsert(record: SandboxMetadataRecord): Promise<SandboxMetadataRecord> {\n const file = await this.readAll();\n const next = file.sandboxes.filter((entry) => entry.name !== record.name);\n next.push(record);\n await this.writeAll({ sandboxes: next });\n return record;\n }\n\n async patchStatus(name: string, status: SandboxStatus): Promise<void> {\n const current = await this.get(name);\n if (!current) {\n return;\n }\n\n await this.upsert({ ...current, status, updatedAt: new Date().toISOString() });\n }\n\n async remove(name: string): Promise<void> {\n const file = await this.readAll();\n await this.writeAll({ sandboxes: file.sandboxes.filter((entry) => entry.name !== name) });\n }\n}\n","export interface ParsedServerArgs {\n host?: string;\n port?: number;\n}\n\nexport interface ResolvedServerConfig {\n host: string;\n port: number;\n}\n\nfunction parsePort(raw: string, source: string): number {\n const value = Number(raw);\n if (!Number.isInteger(value) || value <= 0) {\n throw new Error(`Invalid value for ${source}: ${raw}`);\n }\n return value;\n}\n\nexport function parseServerArgs(argv: string[]): ParsedServerArgs {\n const parsed: ParsedServerArgs = {};\n\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index];\n\n if (token === \"--port\") {\n const raw = argv[index + 1];\n if (!raw) {\n throw new Error(\"Missing value for --port\");\n }\n parsed.port = parsePort(raw, \"--port\");\n index += 1;\n continue;\n }\n\n if (token === \"--host\") {\n const raw = argv[index + 1];\n if (!raw) {\n throw new Error(\"Missing value for --host\");\n }\n parsed.host = raw;\n index += 1;\n }\n }\n\n return parsed;\n}\n\nexport function resolveServerConfig({\n args,\n env,\n}: {\n args: ParsedServerArgs;\n env: NodeJS.ProcessEnv;\n}): ResolvedServerConfig {\n return {\n host: args.host ?? env.HOST ?? \"0.0.0.0\",\n port: args.port ?? (env.PORT ? parsePort(env.PORT, \"PORT\") : 4002),\n };\n}\n"],"mappings":"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","names":["import_zod","z","import_zod","z","import_microsandbox","fastify","cors","sensible","multipart"]}
1
+ {"version":3,"sources":["../src/server.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/services/ImageService.ts","../src/services/MicrosandboxRuntimeService.ts","../src/services/SandboxRegistry.ts","../src/services/SandboxMetadataStore.ts","../src/lib/server-cli.ts"],"sourcesContent":["import type { FastifyInstance } from \"fastify\";\nimport { buildApp } from \"./app\";\nimport { parseServerArgs, resolveServerConfig } from \"./lib/server-cli\";\n\nexport async function startServer({\n argv = process.argv.slice(2),\n env = process.env,\n app = buildApp(),\n}: {\n argv?: string[];\n env?: NodeJS.ProcessEnv;\n app?: Pick<FastifyInstance, \"listen\" | \"close\">;\n} = {}): Promise<Pick<FastifyInstance, \"listen\" | \"close\">> {\n const config = resolveServerConfig({ args: parseServerArgs(argv), env });\n\n const shutdown = async (code: number): Promise<void> => {\n try {\n await app.close();\n process.exit(code);\n } catch (error) {\n console.error(\"Failed to shutdown microsandbox-service cleanly\", error);\n process.exit(1);\n }\n };\n\n process.once(\"SIGINT\", () => {\n void shutdown(0);\n });\n\n process.once(\"SIGTERM\", () => {\n void shutdown(0);\n });\n\n await app.listen({ port: config.port, host: config.host });\n return app;\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 { 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}: {\n runtimeService?: RuntimeService;\n imageService?: ImageService;\n} = {}): FastifyInstance {\n const app = fastify({ logger: false });\n\n app.register(cors, { origin: true });\n app.register(sensible);\n app.register(multipart);\n\n registerHealthRoutes(app);\n registerSandboxRoutes(app, runtimeService);\n registerImageRoutes(app, imageService);\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\", \"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 return reply.send(ok(await runtimeService.uploadFile(body.sandboxName, body.path, body.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 { PullImageInput } from \"../schemas/images\";\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\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\nexport class ImageService {\n constructor(\n private readonly deps: {\n bindings?: ImageBindings;\n } = {}\n ) {}\n\n private get bindings(): ImageBindings {\n return (\n this.deps.bindings ?? {\n list: async () => [],\n pull: async (ref: string) => ({ ref, sourceType: \"oci\", cached: true }),\n inspect: async (ref: string) => ({ ref, sourceType: \"oci\", cached: true }),\n remove: async () => undefined,\n }\n );\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","import { Mount, Sandbox } from \"microsandbox\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport { SandboxRegistry } from \"./SandboxRegistry\";\nimport {\n SandboxMetadataStore,\n type SandboxMetadataRecord,\n type SandboxMetadataStoreLike,\n} from \"./SandboxMetadataStore\";\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(\n path: string,\n options?: { recursive?: boolean }\n ): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;\n read(path: string): Promise<Buffer | Uint8Array | string>;\n };\n execWithConfig(config: {\n cmd: string;\n args?: string[];\n cwd?: string;\n timeoutMs?: number;\n }): Promise<{\n stdout(): string;\n stderr?(): string;\n code?: number;\n }>;\n stop(): Promise<void>;\n kill(): Promise<void>;\n};\n\nexport class MicrosandboxRuntimeService {\n constructor(private deps: { registry?: SandboxRegistry; metadataStore?: SandboxMetadataStoreLike } = {}) {}\n\n private get registry(): SandboxRegistry {\n return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());\n }\n\n private get metadataStore(): SandboxMetadataStoreLike {\n return this.deps.metadataStore ?? (this.deps.metadataStore = new SandboxMetadataStore());\n }\n\n private toListItem(record: SandboxMetadataRecord): {\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 return {\n name: record.name,\n status: record.status,\n image: record.image,\n cpus: record.cpus,\n memoryMib: record.memoryMib,\n envCount: Object.keys(record.env).length,\n volumeCount: Object.keys(record.volumes).length,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n };\n }\n\n private buildVolumes(volumes?: EnsureSandboxInput[\"volumes\"]): Record<string, unknown> | undefined {\n if (!volumes) {\n return undefined;\n }\n\n return Object.fromEntries(\n Object.entries(volumes).map(([mountPath, definition]) => [mountPath, this.buildVolume(definition)])\n );\n }\n\n private buildVolume(definition: VolumeConfig): unknown {\n if (definition.type === \"bind\") {\n return Mount.bind(definition.source, { readonly: definition.readonly ?? false });\n }\n\n if (definition.type === \"named\") {\n return Mount.named(definition.name, { readonly: definition.readonly ?? false });\n }\n\n return Mount.tmpfs({ sizeMib: definition.sizeMib });\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(name: string, input: EnsureSandboxInput): 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.registry.ensure(name, {\n image,\n cpus,\n memoryMib,\n env: input.env,\n volumes: this.buildVolumes(input.volumes),\n });\n\n const existing = await this.metadataStore.get(name);\n const now = new Date().toISOString();\n\n await this.metadataStore.upsert({\n name,\n status: \"running\",\n image,\n cpus,\n memoryMib,\n env: input.env ?? {},\n volumes: input.volumes ?? {},\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\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 await this.metadataStore.patchStatus(name, \"running\");\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 await this.metadataStore.patchStatus(name, \"stopped\");\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 await this.metadataStore.patchStatus(name, \"unknown\");\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 await this.metadataStore.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 items = (await this.metadataStore.list())\n .filter((record) => {\n if (_query.status && record.status !== _query.status) {\n return false;\n }\n\n if (_query.image && record.image !== _query.image) {\n return false;\n }\n\n if (_query.search) {\n const haystack = [record.name, record.image, ...Object.keys(record.env)]\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 .map((record) => this.toListItem(record));\n\n return { items, total: items.length };\n }\n\n async getSandbox(name: string): Promise<SandboxMetadataRecord | undefined> {\n return await this.metadataStore.get(name);\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n try {\n this.getNative(name);\n return { name, status: \"running\" };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const content = await this.getNative(sandboxName).fs().readString(path);\n return { path, content };\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n await this.getNative(sandboxName).fs().write(path, Buffer.from(content));\n return { path };\n }\n\n async listPath(\n sandboxName: string,\n path: string,\n recursive?: boolean\n ): Promise<{ entries: Array<{ path: string; type: string }> }> {\n const entries = await this.getNative(sandboxName).fs().list(path, { recursive });\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 output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"find\",\n args: [path, \"-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 let stdout: string;\n\n try {\n const output = await this.getNative(sandboxName).execWithConfig({\n cmd: \"grep\",\n args: [\"-n\", \"-E\", query, path],\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 fs = this.getNative(sandboxName).fs();\n const original = await fs.readString(input.path);\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(input.path, Buffer.from(updated));\n\n return { replaced: occurrences };\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n await this.getNative(sandboxName).fs().write(path, Buffer.from(contentBase64, \"base64\"));\n return { path };\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const data = await this.getNative(sandboxName).fs().read(path);\n const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);\n return { path, 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 ? output.stderr() : \"\",\n exitCode: output.code ?? 0,\n };\n }\n}\n","import { Sandbox } 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 createConfig = {\n name,\n image: DEFAULT_IMAGE,\n ...(createOptions ?? {}),\n };\n\n try {\n const handle = 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 }\n } catch {\n native = undefined;\n }\n\n if (!native) {\n native = await Sandbox.createDetached(createConfig);\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 { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { EnsureSandboxInput } from \"../schemas/sandbox\";\n\nexport type SandboxStatus = \"running\" | \"stopped\" | \"unknown\";\n\nexport type SandboxMetadataRecord = {\n name: string;\n status: SandboxStatus;\n image?: string;\n cpus?: number;\n memoryMib?: number;\n env: Record<string, string>;\n volumes: NonNullable<EnsureSandboxInput[\"volumes\"]>;\n createdAt: string;\n updatedAt: string;\n};\n\ntype SandboxMetadataFile = {\n sandboxes: SandboxMetadataRecord[];\n};\n\nfunction isSandboxMetadataFile(value: unknown): value is SandboxMetadataFile {\n return typeof value === \"object\" && value !== null && \"sandboxes\" in value && Array.isArray(value.sandboxes);\n}\n\nexport interface SandboxMetadataStoreLike {\n list(): Promise<SandboxMetadataRecord[]>;\n get(name: string): Promise<SandboxMetadataRecord | undefined>;\n upsert(record: SandboxMetadataRecord): Promise<SandboxMetadataRecord>;\n patchStatus(name: string, status: SandboxStatus): Promise<void>;\n remove(name: string): Promise<void>;\n}\n\nexport class SandboxMetadataStore implements SandboxMetadataStoreLike {\n constructor(private readonly options: { filePath?: string } = {}) {}\n\n private get filePath(): string {\n return this.options.filePath ?? process.env.MICROSANDBOX_METADATA_FILE ?? \".microsandbox/metadata.json\";\n }\n\n private async readAll(): Promise<SandboxMetadataFile> {\n try {\n const content = await readFile(this.filePath, \"utf8\");\n const parsed: unknown = JSON.parse(content);\n\n if (!isSandboxMetadataFile(parsed)) {\n throw new Error(\"Invalid sandbox metadata file\");\n }\n\n return parsed;\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") {\n return { sandboxes: [] };\n }\n\n throw error;\n }\n }\n\n private async writeAll(file: SandboxMetadataFile): Promise<void> {\n await mkdir(dirname(this.filePath), { recursive: true });\n await writeFile(this.filePath, JSON.stringify(file, null, 2));\n }\n\n async list(): Promise<SandboxMetadataRecord[]> {\n const file = await this.readAll();\n return file.sandboxes.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n }\n\n async get(name: string): Promise<SandboxMetadataRecord | undefined> {\n const file = await this.readAll();\n return file.sandboxes.find((entry) => entry.name === name);\n }\n\n async upsert(record: SandboxMetadataRecord): Promise<SandboxMetadataRecord> {\n const file = await this.readAll();\n const next = file.sandboxes.filter((entry) => entry.name !== record.name);\n next.push(record);\n await this.writeAll({ sandboxes: next });\n return record;\n }\n\n async patchStatus(name: string, status: SandboxStatus): Promise<void> {\n const current = await this.get(name);\n if (!current) {\n return;\n }\n\n await this.upsert({ ...current, status, updatedAt: new Date().toISOString() });\n }\n\n async remove(name: string): Promise<void> {\n const file = await this.readAll();\n await this.writeAll({ sandboxes: file.sandboxes.filter((entry) => entry.name !== name) });\n }\n}\n","export interface ParsedServerArgs {\n host?: string;\n port?: number;\n}\n\nexport interface ResolvedServerConfig {\n host: string;\n port: number;\n}\n\nfunction parsePort(raw: string, source: string): number {\n const value = Number(raw);\n if (!Number.isInteger(value) || value <= 0) {\n throw new Error(`Invalid value for ${source}: ${raw}`);\n }\n return value;\n}\n\nexport function parseServerArgs(argv: string[]): ParsedServerArgs {\n const parsed: ParsedServerArgs = {};\n\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index];\n\n if (token === \"--port\") {\n const raw = argv[index + 1];\n if (!raw) {\n throw new Error(\"Missing value for --port\");\n }\n parsed.port = parsePort(raw, \"--port\");\n index += 1;\n continue;\n }\n\n if (token === \"--host\") {\n const raw = argv[index + 1];\n if (!raw) {\n throw new Error(\"Missing value for --host\");\n }\n parsed.host = raw;\n index += 1;\n }\n }\n\n return parsed;\n}\n\nexport function resolveServerConfig({\n args,\n env,\n}: {\n args: ParsedServerArgs;\n env: NodeJS.ProcessEnv;\n}): ResolvedServerConfig {\n return {\n host: args.host ?? env.HOST ?? \"0.0.0.0\",\n port: args.port ?? (env.PORT ? parsePort(env.PORT, \"PORT\") : 4002),\n };\n}\n"],"mappings":"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","names":["import_zod","z","import_zod","z","import_microsandbox","fastify","cors","sensible","multipart"]}
package/dist/server.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  startServer
3
- } from "./chunk-CSOLG3XA.mjs";
4
- import "./chunk-D5L33FAA.mjs";
3
+ } from "./chunk-KRXZP6OH.mjs";
4
+ import "./chunk-VM3OJT5V.mjs";
5
5
  export {
6
6
  startServer
7
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axiom-lattice/microsandbox-service",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -42,8 +42,8 @@
42
42
  },
43
43
  "scripts": {
44
44
  "build": "tsup src/index.ts src/server.ts src/cli.ts --format cjs,esm --dts --clean --sourcemap",
45
- "start": "node dist/server.js",
46
- "dev": "tsup src/index.ts src/server.ts src/cli.ts --format cjs,esm --dts --watch --sourcemap --onSuccess \"node dist/server.js\"",
45
+ "start": "node dist/cli.js",
46
+ "dev": "tsup src/index.ts src/server.ts src/cli.ts --format cjs,esm --dts --watch --sourcemap --onSuccess \"node dist/cli.js\"",
47
47
  "lint": "tsc --noEmit",
48
48
  "test": "jest",
49
49
  "test:watch": "jest --watch"
@@ -27,7 +27,8 @@ describe("package metadata", () => {
27
27
  });
28
28
  });
29
29
 
30
- it("uses watch-and-run dev mode", () => {
31
- expect(packageJson.scripts.dev).toContain('--onSuccess "node dist/server.js"');
30
+ it("uses explicit CLI-driven start scripts", () => {
31
+ expect(packageJson.scripts.start).toBe("node dist/cli.js");
32
+ expect(packageJson.scripts.dev).toContain('--onSuccess "node dist/cli.js"');
32
33
  });
33
34
  });
@@ -1,4 +1,9 @@
1
+ import fs from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import path from "node:path";
4
+ import vm from "node:vm";
1
5
  import packageJson from "../../package.json";
6
+ import ts from "typescript";
2
7
  import { parseServerArgs, resolveServerConfig } from "../lib/server-cli";
3
8
 
4
9
  describe("server CLI parsing", () => {
@@ -28,4 +33,55 @@ describe("server CLI parsing", () => {
28
33
  it("rejects invalid port values", () => {
29
34
  expect(() => parseServerArgs(["--port", "abc"])).toThrow("Invalid value for --port: abc");
30
35
  });
36
+
37
+ it("does not start listening when server.ts is executed directly", async () => {
38
+ const buildApp = jest.fn();
39
+ const listen = jest.fn();
40
+ const close = jest.fn();
41
+ const serverPath = path.resolve(__dirname, "../server.ts");
42
+ const serverRequire = createRequire(serverPath);
43
+ const serverSource = fs.readFileSync(serverPath, "utf8");
44
+ const transpiled = ts.transpileModule(serverSource, {
45
+ compilerOptions: {
46
+ module: ts.ModuleKind.CommonJS,
47
+ target: ts.ScriptTarget.ES2020,
48
+ },
49
+ fileName: serverPath,
50
+ });
51
+ const module = { exports: {}, filename: serverPath };
52
+ const processMock = {
53
+ argv: ["node", serverPath],
54
+ env: {},
55
+ exit: jest.fn(),
56
+ once: jest.fn(),
57
+ };
58
+
59
+ buildApp.mockReturnValue({ listen, close });
60
+
61
+ const customRequire = Object.assign(
62
+ (specifier: string) => {
63
+ if (specifier === "./app") {
64
+ return { buildApp };
65
+ }
66
+
67
+ return serverRequire(specifier);
68
+ },
69
+ { main: module }
70
+ );
71
+
72
+ vm.runInNewContext(transpiled.outputText, {
73
+ module,
74
+ exports: module.exports,
75
+ require: customRequire,
76
+ __dirname: path.dirname(serverPath),
77
+ __filename: serverPath,
78
+ process: processMock,
79
+ console,
80
+ });
81
+
82
+ await Promise.resolve();
83
+
84
+ expect(buildApp).not.toHaveBeenCalled();
85
+ expect(listen).not.toHaveBeenCalled();
86
+ });
31
87
  });
package/src/server.ts CHANGED
@@ -34,10 +34,3 @@ export async function startServer({
34
34
  await app.listen({ port: config.port, host: config.host });
35
35
  return app;
36
36
  }
37
-
38
- if (require.main === module) {
39
- void startServer().catch((error) => {
40
- console.error("Failed to start microsandbox-service", error);
41
- process.exit(1);
42
- });
43
- }