@axiom-lattice/microsandbox-service 0.0.50 → 0.0.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @axiom-lattice/microsandbox-service
2
2
 
3
+ ## 0.0.52
4
+
5
+ ### Patch Changes
6
+
7
+ - 18749ee: fix sandbox issue
8
+
9
+ ## 0.0.51
10
+
11
+ ### Patch Changes
12
+
13
+ - 2954442: fix issue
14
+
3
15
  ## 0.0.50
4
16
 
5
17
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildApp
3
- } from "./chunk-3O2XVS6Q.mjs";
3
+ } from "./chunk-I6F4WE2G.mjs";
4
4
 
5
5
  // src/lib/server-cli.ts
6
6
  function parsePort(raw, source) {
@@ -97,4 +97,4 @@ async function startServer({
97
97
  export {
98
98
  startServer
99
99
  };
100
- //# sourceMappingURL=chunk-2MMX4ESI.mjs.map
100
+ //# sourceMappingURL=chunk-CT7REZXC.mjs.map
@@ -4,7 +4,11 @@ import { readdirSync, readFileSync, unlinkSync } from "fs";
4
4
  import { join } from "path";
5
5
  var DEFAULT_IMAGE = process.env.MICROSANDBOX_IMAGE ?? "daytonaio/sandbox:0.6.0";
6
6
  var DEFAULT_IDLE_TIMEOUT_MS = Number(process.env.MICROSANDBOX_IDLE_TIMEOUT_MS) || 6e5;
7
+ var DEFAULT_REMOVE_AFTER_PAUSED_MS = 7 * 24 * 60 * 60 * 1e3;
7
8
  var SWEEP_INTERVAL_MS = 3e4;
9
+ var SWEEP_STOP_TIMEOUT_MS = 6e4;
10
+ var HEALTH_CHECK_TIMEOUT_MS = 2e3;
11
+ var HEALTH_CHECK_INTERVAL_MS = 3e4;
8
12
  var SANDBOX_AGENT_SOCKET_DIR = "/root/.microsandbox/run/agent";
9
13
  function extractConfig(configJson) {
10
14
  try {
@@ -36,6 +40,7 @@ var SandboxRegistry = class {
36
40
  constructor(idleTimeoutMs) {
37
41
  this.handles = /* @__PURE__ */ new Map();
38
42
  this.creating = /* @__PURE__ */ new Map();
43
+ this.stopping = /* @__PURE__ */ new Set();
39
44
  this.idleTimeoutMs = idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
40
45
  this.cleanupOrphanedSockets();
41
46
  if (this.idleTimeoutMs > 0) {
@@ -47,12 +52,29 @@ var SandboxRegistry = class {
47
52
  const now = Date.now();
48
53
  for (const [name, entry] of this.handles) {
49
54
  if (entry.native && now - entry.lastAccessedAt > this.idleTimeoutMs) {
55
+ if (this.stopping.has(name)) {
56
+ continue;
57
+ }
50
58
  console.log(`[SandboxRegistry] sweeper pausing idle sandbox name=${name} idleMs=${now - entry.lastAccessedAt}`);
51
- void entry.native.stop().then(() => {
52
- entry.native = null;
59
+ this.stopping.add(name);
60
+ void Promise.race([
61
+ entry.native.stop(),
62
+ new Promise((_, reject) => setTimeout(() => reject(new Error("stop timed out")), SWEEP_STOP_TIMEOUT_MS))
63
+ ]).then(() => {
53
64
  console.log(`[SandboxRegistry] sweeper paused name=${name}`);
54
65
  }).catch((err) => {
55
66
  console.log(`[SandboxRegistry] sweeper pause failed name=${name} err=${err.message}`);
67
+ }).finally(() => {
68
+ entry.native = null;
69
+ entry.pausedAt = Date.now();
70
+ this.stopping.delete(name);
71
+ });
72
+ } else if (!entry.native && entry.pausedAt && now - entry.pausedAt > DEFAULT_REMOVE_AFTER_PAUSED_MS) {
73
+ console.log(`[SandboxRegistry] sweeper removing paused sandbox name=${name} pausedMs=${now - entry.pausedAt}`);
74
+ void this.removeAndDelete(name).then(() => {
75
+ console.log(`[SandboxRegistry] sweeper removed name=${name}`);
76
+ }).catch((err) => {
77
+ console.log(`[SandboxRegistry] sweeper remove failed name=${name} err=${err.message}`);
56
78
  });
57
79
  }
58
80
  }
@@ -94,15 +116,30 @@ var SandboxRegistry = class {
94
116
  }
95
117
  }
96
118
  async removeAndDelete(name) {
97
- const handle = await Sandbox.get(name);
98
- if (handle.status === "running") {
99
- try {
100
- const native = await handle.connect();
101
- await native.stop();
102
- } catch {
119
+ try {
120
+ const handle = await Promise.race([
121
+ Sandbox.get(name),
122
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Sandbox.get timed out")), SWEEP_STOP_TIMEOUT_MS))
123
+ ]);
124
+ if (handle.status === "running") {
125
+ try {
126
+ const native = await Promise.race([
127
+ handle.connect(),
128
+ new Promise((_, reject) => setTimeout(() => reject(new Error("handle.connect timed out")), SWEEP_STOP_TIMEOUT_MS))
129
+ ]);
130
+ await Promise.race([
131
+ native.stop(),
132
+ new Promise((_, reject) => setTimeout(() => reject(new Error("stop timed out")), SWEEP_STOP_TIMEOUT_MS))
133
+ ]);
134
+ } catch {
135
+ }
103
136
  }
137
+ await Promise.race([
138
+ Sandbox.remove(name),
139
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Sandbox.remove timed out")), SWEEP_STOP_TIMEOUT_MS))
140
+ ]);
141
+ } catch {
104
142
  }
105
- await Sandbox.remove(name);
106
143
  this.remove(name);
107
144
  this.cleanupOrphanedSockets();
108
145
  }
@@ -117,16 +154,32 @@ var SandboxRegistry = class {
117
154
  if (handle.status === "running") {
118
155
  try {
119
156
  await entry.native.stop();
120
- entry.native = null;
121
157
  } catch {
122
158
  }
123
159
  }
160
+ entry.native = null;
161
+ entry.pausedAt = Date.now();
162
+ }
163
+ async healthCheck(native) {
164
+ const fs2 = native.fs();
165
+ try {
166
+ await Promise.race([
167
+ fs2.list("/"),
168
+ new Promise((_, reject) => setTimeout(() => reject(new Error("health check timed out")), HEALTH_CHECK_TIMEOUT_MS))
169
+ ]);
170
+ return true;
171
+ } catch {
172
+ return false;
173
+ }
124
174
  }
125
175
  async waitForFs(native, maxRetries = 10) {
126
176
  const fs2 = native.fs();
127
177
  for (let i = 0; i < maxRetries; i++) {
128
178
  try {
129
- await fs2.list("/");
179
+ await Promise.race([
180
+ fs2.list("/"),
181
+ new Promise((_, reject) => setTimeout(() => reject(new Error("FS check timed out")), 5e3))
182
+ ]);
130
183
  return;
131
184
  } catch {
132
185
  await new Promise((r) => setTimeout(r, 200));
@@ -158,12 +211,32 @@ var SandboxRegistry = class {
158
211
  async ensure(name, createOptions) {
159
212
  const tStart = Date.now();
160
213
  const cached = this.handles.get(name);
161
- if (cached?.native) {
162
- cached.lastAccessedAt = Date.now();
163
- console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms`);
164
- return cached.native;
214
+ if (cached?.native && !this.stopping.has(name)) {
215
+ const now = Date.now();
216
+ if (!cached.lastCheckedAt || now - cached.lastCheckedAt > HEALTH_CHECK_INTERVAL_MS) {
217
+ const tCheck = Date.now();
218
+ const ok2 = await this.healthCheck(cached.native);
219
+ cached.lastCheckedAt = now;
220
+ if (ok2) {
221
+ cached.lastAccessedAt = now;
222
+ console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms health_ok elapsed=${Date.now() - tCheck}ms`);
223
+ return cached.native;
224
+ }
225
+ console.log(`[SandboxRegistry] ensure name=${name} HEALTH_FAIL will_recreate elapsed=${Date.now() - tStart}ms`);
226
+ cached.native = null;
227
+ cached.broken = true;
228
+ } else {
229
+ cached.lastAccessedAt = now;
230
+ console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms`);
231
+ return cached.native;
232
+ }
233
+ }
234
+ if (cached?.native && this.stopping.has(name)) {
235
+ console.log(`[SandboxRegistry] ensure name=${name} STALE_NATIVE (being stopped), forcing revive`);
236
+ cached.native = null;
165
237
  }
166
238
  if (cached && !cached.native) {
239
+ cached.pausedAt = void 0;
167
240
  console.log(`[SandboxRegistry] ensure name=${name} REVIVE idled=${Date.now() - cached.lastAccessedAt}ms`);
168
241
  }
169
242
  const inflight = this.creating.get(name);
@@ -179,44 +252,62 @@ var SandboxRegistry = class {
179
252
  const memoryMib = createOptions?.memoryMib ?? 512;
180
253
  const env = createOptions?.env ?? void 0;
181
254
  let originalConfig;
182
- try {
183
- const tGet = Date.now();
184
- const handle = await Sandbox.get(name);
185
- console.log(`[SandboxRegistry] Sandbox.get name=${name} status=${handle.status} elapsed=${Date.now() - tGet}ms`);
186
- originalConfig = extractConfig(handle.configJson);
187
- if (handle.status === "running" || handle.status === "stopped") {
188
- const isNewConnection = !cached;
189
- if (isNewConnection && createOptions && this.hasConfigMismatch(originalConfig, createOptions)) {
190
- await this.removeAndDelete(name);
191
- native = void 0;
192
- } else if (handle.status === "running") {
193
- const tConnect = Date.now();
194
- native = await handle.connect();
195
- console.log(`[SandboxRegistry] handle.connect name=${name} elapsed=${Date.now() - tConnect}ms`);
196
- const tFs = Date.now();
197
- await this.waitForFs(native);
198
- console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);
199
- } else {
200
- try {
201
- const tStart2 = Date.now();
202
- native = await Sandbox.startDetached(name);
203
- console.log(`[SandboxRegistry] startDetached name=${name} elapsed=${Date.now() - tStart2}ms`);
255
+ const existing = this.handles.get(name);
256
+ if (existing?.broken) {
257
+ console.log(`[SandboxRegistry] ensure name=${name} BROKEN removing before recreate`);
258
+ await this.removeAndDelete(name);
259
+ this.handles.set(name, { native: null, lastAccessedAt: Date.now(), createOptions: existing.createOptions ?? cached?.createOptions });
260
+ } else {
261
+ try {
262
+ const tGet = Date.now();
263
+ const handle = await Sandbox.get(name);
264
+ console.log(`[SandboxRegistry] Sandbox.get name=${name} status=${handle.status} elapsed=${Date.now() - tGet}ms`);
265
+ originalConfig = extractConfig(handle.configJson);
266
+ if (handle.status === "running" || handle.status === "stopped") {
267
+ const isNewConnection = !cached;
268
+ if (isNewConnection && createOptions && this.hasConfigMismatch(originalConfig, createOptions)) {
269
+ await this.removeAndDelete(name);
270
+ native = void 0;
271
+ } else if (handle.status === "running") {
272
+ const tConnect = Date.now();
273
+ native = await Promise.race([
274
+ handle.connect(),
275
+ new Promise(
276
+ (_, reject) => setTimeout(() => reject(new Error("handle.connect timed out")), SWEEP_STOP_TIMEOUT_MS)
277
+ )
278
+ ]);
279
+ console.log(`[SandboxRegistry] handle.connect name=${name} elapsed=${Date.now() - tConnect}ms`);
204
280
  const tFs = Date.now();
205
281
  await this.waitForFs(native);
206
282
  console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);
207
- } catch {
208
- if (!native) {
209
- await this.removeAndDelete(name);
283
+ } else {
284
+ try {
285
+ const tStart2 = Date.now();
286
+ native = await Promise.race([
287
+ Sandbox.startDetached(name),
288
+ new Promise(
289
+ (_, reject) => setTimeout(() => reject(new Error("startDetached timed out")), SWEEP_STOP_TIMEOUT_MS)
290
+ )
291
+ ]);
292
+ console.log(`[SandboxRegistry] startDetached name=${name} elapsed=${Date.now() - tStart2}ms`);
293
+ const tFs = Date.now();
294
+ await this.waitForFs(native);
295
+ console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);
296
+ } catch {
297
+ if (!native) {
298
+ await this.removeAndDelete(name);
299
+ }
210
300
  }
211
301
  }
302
+ } else if (handle.status === "crashed" || handle.status === "draining") {
303
+ await this.removeAndDelete(name);
304
+ } else {
305
+ await this.removeAndDelete(name);
212
306
  }
213
- } else if (handle.status === "crashed" || handle.status === "draining") {
214
- await this.removeAndDelete(name);
215
- } else {
216
- await this.removeAndDelete(name);
307
+ } catch (err) {
308
+ console.log(`[SandboxRegistry] ensure name=${name} existing_check failed err=${err.message}`);
309
+ native = void 0;
217
310
  }
218
- } catch {
219
- native = void 0;
220
311
  }
221
312
  console.log(`[SandboxRegistry] phase=existing_check name=${name} hasNative=${!!native} elapsed=${Date.now() - tCreate}ms`);
222
313
  if (!native) {
@@ -282,7 +373,12 @@ var SandboxRegistry = class {
282
373
  }
283
374
  applyVolumes(builder);
284
375
  const tCreateInner = Date.now();
285
- const result = await builder.create();
376
+ const result = await Promise.race([
377
+ builder.create(),
378
+ new Promise(
379
+ (_, reject) => setTimeout(() => reject(new Error("builder.create timed out")), SWEEP_STOP_TIMEOUT_MS)
380
+ )
381
+ ]);
286
382
  console.log(
287
383
  `[SandboxRegistry] builder.create name=${name} image=${resolvedImage} elapsed=${Date.now() - tCreateInner}ms envKeys=${resolvedEnv ? Object.keys(resolvedEnv).join(",") : "none"} volumes=${volumeDefs ? Object.keys(volumeDefs).join(",") : "none"}`
288
384
  );
@@ -304,7 +400,13 @@ var SandboxRegistry = class {
304
400
  console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);
305
401
  }
306
402
  const totalElapsed = Date.now() - tStart;
307
- this.handles.set(name, { native, lastAccessedAt: Date.now(), createOptions: createOptions ?? cached?.createOptions });
403
+ const entry = {
404
+ native,
405
+ lastAccessedAt: Date.now(),
406
+ lastCheckedAt: Date.now(),
407
+ createOptions: createOptions ?? cached?.createOptions
408
+ };
409
+ this.handles.set(name, entry);
308
410
  console.log(`[SandboxRegistry] ensure DONE name=${name} total=${totalElapsed}ms idleTimeout=${Math.round(this.idleTimeoutMs / 1e3)}s`);
309
411
  return native;
310
412
  })();
@@ -1319,4 +1421,4 @@ export {
1319
1421
  MicrosandboxRuntimeService,
1320
1422
  buildApp
1321
1423
  };
1322
- //# sourceMappingURL=chunk-3O2XVS6Q.mjs.map
1424
+ //# sourceMappingURL=chunk-I6F4WE2G.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/SandboxRegistry.ts","../src/services/MicrosandboxRuntimeService.ts","../src/lib/errors.ts","../src/lib/msb.ts","../src/app.ts","../src/lib/http.ts","../src/routes/health.ts","../src/controllers/images.ts","../src/schemas/images.ts","../src/routes/images.ts","../src/schemas/sandbox.ts","../src/controllers/sandbox.ts","../src/routes/sandbox.ts","../src/controllers/volume-fs.ts","../src/schemas/volume-fs.ts","../src/routes/volume-fs.ts","../src/services/ImageService.ts","../src/swagger.ts"],"sourcesContent":["import { Sandbox, MountBuilder } from \"microsandbox\";\nimport type { SandboxHandle } from \"microsandbox\";\nimport { readdirSync, readFileSync, unlinkSync } from \"fs\";\nimport { join } from \"path\";\n\nconst DEFAULT_IMAGE = process.env.MICROSANDBOX_IMAGE ?? \"daytonaio/sandbox:0.6.0\";\nconst DEFAULT_IDLE_TIMEOUT_MS = Number(process.env.MICROSANDBOX_IDLE_TIMEOUT_MS) || 600_000;\nconst DEFAULT_REMOVE_AFTER_PAUSED_MS = 7 * 24 * 60 * 60 * 1000;\nconst SWEEP_INTERVAL_MS = 30_000;\nconst SWEEP_STOP_TIMEOUT_MS = 60_000;\nconst HEALTH_CHECK_TIMEOUT_MS = 2_000;\nconst HEALTH_CHECK_INTERVAL_MS = 30_000;\nconst SANDBOX_AGENT_SOCKET_DIR = \"/root/.microsandbox/run/agent\";\n\ntype CacheEntry = {\n native: unknown | null;\n lastAccessedAt: number;\n pausedAt?: number;\n lastCheckedAt?: number;\n broken?: boolean;\n createOptions?: Record<string, unknown>;\n};\n\nfunction extractConfig(configJson: string): {\n image: string;\n cpus: number;\n memoryMib: number;\n env: Record<string, string>;\n mounts: Array<{ guest: string; type: string; source?: string; name?: string; size_mib?: number; readonly?: boolean }>;\n} | undefined {\n try {\n const raw = JSON.parse(configJson);\n const image = typeof raw.image === \"string\" ? raw.image\n : raw.image?.Oci?.reference ?? \"\";\n const env: Record<string, string> = {};\n const rawEnv = raw.env;\n if (Array.isArray(rawEnv)) {\n for (const entry of rawEnv) {\n if (Array.isArray(entry) && entry.length >= 2) {\n env[String(entry[0])] = String(entry[1]);\n }\n }\n } else if (rawEnv && typeof rawEnv === \"object\") {\n Object.assign(env, rawEnv);\n }\n return {\n image,\n cpus: raw.cpus ?? 1,\n memoryMib: raw.memory_mib ?? raw.memoryMib ?? 512,\n env,\n mounts: Array.isArray(raw.mounts) ? raw.mounts : [],\n };\n } catch {\n return undefined;\n }\n}\n\nexport class SandboxRegistry {\n private handles = new Map<string, CacheEntry>();\n private creating = new Map<string, Promise<unknown>>();\n private stopping = new Set<string>();\n private readonly idleTimeoutMs: number;\n private sweepTimer?: ReturnType<typeof setInterval>;\n\n constructor(idleTimeoutMs?: number) {\n this.idleTimeoutMs = idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;\n this.cleanupOrphanedSockets();\n if (this.idleTimeoutMs > 0) {\n this.startSweeper();\n }\n }\n\n private startSweeper(): void {\n this.sweepTimer = setInterval(() => {\n const now = Date.now();\n for (const [name, entry] of this.handles) {\n if (entry.native && now - entry.lastAccessedAt > this.idleTimeoutMs) {\n if (this.stopping.has(name)) {\n continue;\n }\n console.log(`[SandboxRegistry] sweeper pausing idle sandbox name=${name} idleMs=${now - entry.lastAccessedAt}`);\n this.stopping.add(name);\n void Promise.race([\n (entry.native as { stop(): Promise<void> }).stop(),\n new Promise<void>((_, reject) => setTimeout(() => reject(new Error(\"stop timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]).then(() => {\n console.log(`[SandboxRegistry] sweeper paused name=${name}`);\n }).catch((err: Error) => {\n console.log(`[SandboxRegistry] sweeper pause failed name=${name} err=${err.message}`);\n }).finally(() => {\n entry.native = null;\n entry.pausedAt = Date.now();\n this.stopping.delete(name);\n });\n } else if (!entry.native && entry.pausedAt && now - entry.pausedAt > DEFAULT_REMOVE_AFTER_PAUSED_MS) {\n console.log(`[SandboxRegistry] sweeper removing paused sandbox name=${name} pausedMs=${now - entry.pausedAt}`);\n void this.removeAndDelete(name).then(() => {\n console.log(`[SandboxRegistry] sweeper removed name=${name}`);\n }).catch((err: Error) => {\n console.log(`[SandboxRegistry] sweeper remove failed name=${name} err=${err.message}`);\n });\n }\n }\n }, SWEEP_INTERVAL_MS);\n }\n\n destroy(): void {\n if (this.sweepTimer) {\n clearInterval(this.sweepTimer);\n this.sweepTimer = undefined;\n }\n this.handles.clear();\n this.creating.clear();\n }\n\n remove(name: string): void {\n this.handles.delete(name);\n this.creating.delete(name);\n }\n\n cleanupOrphanedSockets(): void {\n try {\n const activeSockets = new Set<string>();\n const unixSockets = readFileSync(\"/proc/net/unix\", \"utf-8\");\n for (const line of unixSockets.split(\"\\n\")) {\n const path = line.trim().split(\" \").pop();\n if (path && path.startsWith(SANDBOX_AGENT_SOCKET_DIR)) {\n activeSockets.add(path);\n }\n }\n for (const entry of readdirSync(SANDBOX_AGENT_SOCKET_DIR)) {\n const fullPath = join(SANDBOX_AGENT_SOCKET_DIR, entry);\n if (!activeSockets.has(fullPath)) {\n unlinkSync(fullPath);\n console.log(`[SandboxRegistry] removed orphaned socket: ${entry}`);\n }\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n console.log(`[SandboxRegistry] socket cleanup skipped: ${(err as Error).message}`);\n }\n }\n }\n\n async removeAndDelete(name: string): Promise<void> {\n try {\n const handle = await Promise.race([\n Sandbox.get(name),\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"Sandbox.get timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]);\n if (handle.status === \"running\") {\n try {\n const native = await Promise.race([\n handle.connect(),\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"handle.connect timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]);\n await Promise.race([\n (native as { stop(): Promise<void> }).stop(),\n new Promise<void>((_, reject) => setTimeout(() => reject(new Error(\"stop timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]);\n } catch { /* ignore */ }\n }\n await Promise.race([\n Sandbox.remove(name),\n new Promise<void>((_, reject) => setTimeout(() => reject(new Error(\"Sandbox.remove timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]);\n } catch { /* best effort, always clean cache */ }\n this.remove(name);\n this.cleanupOrphanedSockets();\n }\n\n async pause(name: string): Promise<void> {\n const entry = this.handles.get(name);\n if (!entry) {\n await Sandbox.get(name);\n return;\n }\n if (!entry.native) return;\n const handle = await Sandbox.get(name);\n if (handle.status === \"running\") {\n try {\n await (entry.native as { stop(): Promise<void> }).stop();\n } catch { /* ignore */ }\n }\n entry.native = null;\n entry.pausedAt = Date.now();\n }\n\n private async healthCheck(native: unknown): Promise<boolean> {\n const fs = (native as { fs(): { list(path: string): Promise<unknown> } }).fs();\n try {\n await Promise.race([\n fs.list(\"/\"),\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"health check timed out\")), HEALTH_CHECK_TIMEOUT_MS)),\n ]);\n return true;\n } catch {\n return false;\n }\n }\n\n private async waitForFs(native: unknown, maxRetries = 10): Promise<void> {\n const fs = (native as { fs(): { list(path: string): Promise<unknown> } }).fs();\n for (let i = 0; i < maxRetries; i++) {\n try {\n await Promise.race([\n fs.list(\"/\"),\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"FS check timed out\")), 5000)),\n ]);\n return;\n } catch {\n await new Promise((r) => setTimeout(r, 200));\n }\n }\n throw new Error(\"FS not ready after start\");\n }\n\n private hasConfigMismatch(\n originalConfig: ReturnType<typeof extractConfig>,\n createOptions: Record<string, unknown>\n ): boolean {\n const volumeDefs = createOptions.volumes as Record<string, { type: string }> | undefined;\n const requestEnv = createOptions.env as Record<string, string> | undefined;\n\n if (volumeDefs && Object.keys(volumeDefs).length > 0) {\n const existingGuests = new Set((originalConfig?.mounts ?? []).map((m: { guest: string }) => m.guest));\n const requestedGuests = new Set(Object.keys(volumeDefs));\n if (existingGuests.size !== requestedGuests.size ||\n ![...requestedGuests].every(g => existingGuests.has(g))) {\n console.log(`[SandboxRegistry] volumes mismatch, recreating...`);\n return true;\n }\n }\n\n if (requestEnv && originalConfig?.env) {\n for (const [key, value] of Object.entries(requestEnv)) {\n if (originalConfig.env[key] !== value) {\n console.log(`[SandboxRegistry] env mismatch (key=${key}), recreating...`);\n return true;\n }\n }\n }\n\n return false;\n }\n\n async ensure(name: string, createOptions?: Record<string, unknown>): Promise<unknown> {\n const tStart = Date.now();\n\n const cached = this.handles.get(name);\n\n if (cached?.native && !this.stopping.has(name)) {\n const now = Date.now();\n if (!cached.lastCheckedAt || now - cached.lastCheckedAt > HEALTH_CHECK_INTERVAL_MS) {\n const tCheck = Date.now();\n const ok = await this.healthCheck(cached.native);\n cached.lastCheckedAt = now;\n if (ok) {\n cached.lastAccessedAt = now;\n console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms health_ok elapsed=${Date.now() - tCheck}ms`);\n return cached.native;\n }\n console.log(`[SandboxRegistry] ensure name=${name} HEALTH_FAIL will_recreate elapsed=${Date.now() - tStart}ms`);\n cached.native = null;\n cached.broken = true;\n } else {\n cached.lastAccessedAt = now;\n console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms`);\n return cached.native;\n }\n }\n\n if (cached?.native && this.stopping.has(name)) {\n console.log(`[SandboxRegistry] ensure name=${name} STALE_NATIVE (being stopped), forcing revive`);\n cached.native = null;\n }\n\n if (cached && !cached.native) {\n cached.pausedAt = undefined;\n console.log(`[SandboxRegistry] ensure name=${name} REVIVE idled=${Date.now() - cached.lastAccessedAt}ms`);\n }\n\n const inflight = this.creating.get(name);\n if (inflight) {\n console.log(`[SandboxRegistry] ensure name=${name} AWAITING_INFLIGHT`);\n return inflight;\n }\n\n const creation = (async () => {\n const tCreate = Date.now();\n let native: unknown;\n const image = (createOptions?.image as string) ?? DEFAULT_IMAGE;\n const cpus = (createOptions?.cpus as number) ?? 1;\n const memoryMib = (createOptions?.memoryMib as number) ?? 512;\n const env = (createOptions?.env as Record<string, string>) ?? undefined;\n\n let originalConfig: ReturnType<typeof extractConfig>;\n\n const existing = this.handles.get(name);\n if (existing?.broken) {\n console.log(`[SandboxRegistry] ensure name=${name} BROKEN removing before recreate`);\n await this.removeAndDelete(name);\n this.handles.set(name, { native: null, lastAccessedAt: Date.now(), createOptions: existing.createOptions ?? cached?.createOptions });\n } else {\n try {\n const tGet = Date.now();\n const handle: SandboxHandle = await Sandbox.get(name);\n console.log(`[SandboxRegistry] Sandbox.get name=${name} status=${handle.status} elapsed=${Date.now() - tGet}ms`);\n\n originalConfig = extractConfig(handle.configJson);\n\n if (handle.status === \"running\" || handle.status === \"stopped\") {\n const isNewConnection = !cached;\n if (isNewConnection && createOptions && this.hasConfigMismatch(originalConfig, createOptions)) {\n await this.removeAndDelete(name);\n native = undefined;\n } else if (handle.status === \"running\") {\n const tConnect = Date.now();\n native = await Promise.race([\n handle.connect(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(\"handle.connect timed out\")), SWEEP_STOP_TIMEOUT_MS)\n ),\n ]);\n console.log(`[SandboxRegistry] handle.connect name=${name} elapsed=${Date.now() - tConnect}ms`);\n const tFs = Date.now();\n await this.waitForFs(native);\n console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);\n } else {\n try {\n const tStart2 = Date.now();\n native = await Promise.race([\n Sandbox.startDetached(name),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(\"startDetached timed out\")), SWEEP_STOP_TIMEOUT_MS)\n ),\n ]);\n console.log(`[SandboxRegistry] startDetached name=${name} elapsed=${Date.now() - tStart2}ms`);\n const tFs = Date.now();\n await this.waitForFs(native);\n console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);\n } catch {\n if (!native) {\n await this.removeAndDelete(name);\n }\n }\n }\n } else if (handle.status === \"crashed\" || handle.status === \"draining\") {\n await this.removeAndDelete(name);\n } else {\n await this.removeAndDelete(name);\n }\n } catch (err) {\n console.log(`[SandboxRegistry] ensure name=${name} existing_check failed err=${(err as Error).message}`);\n native = undefined;\n }\n }\n console.log(`[SandboxRegistry] phase=existing_check name=${name} hasNative=${!!native} elapsed=${Date.now() - tCreate}ms`);\n\n if (!native) {\n const effectiveOptions = createOptions ?? cached?.createOptions;\n if (!effectiveOptions) {\n console.log(`[SandboxRegistry] ensure name=${name} NOT_FOUND elapsed=${Date.now() - tStart}ms`);\n throw new Error(`Sandbox ${name} not found`);\n }\n if (!createOptions && cached?.createOptions) {\n console.log(`[SandboxRegistry] ensure name=${name} RECOVER_OPTIONS elapsed=${Date.now() - tStart}ms`);\n }\n const tBuild = Date.now();\n const volumeDefs = effectiveOptions?.volumes as Record<string, { type: string; source?: string; name?: string; sizeMib?: number; readonly?: boolean }> | undefined;\n const resolvedImage = (effectiveOptions?.image as string) ?? originalConfig?.image ?? image;\n console.log(\n `[SandboxRegistry] create sandbox=${name} image=${resolvedImage} ` +\n `from=${(effectiveOptions?.image as string) ? \"request\" : originalConfig?.image ? \"originalConfig\" : \"default\"}`\n );\n const resolvedCpus = (effectiveOptions?.cpus as number) ?? originalConfig?.cpus ?? cpus;\n const resolvedMemoryMib = (effectiveOptions?.memoryMib as number) ?? originalConfig?.memoryMib ?? memoryMib;\n const resolvedEnv = (effectiveOptions?.env as Record<string, string>) ?? originalConfig?.env ?? env;\n const resolvedMounts = originalConfig?.mounts ?? [];\n\n const applyVolumes = (b: ReturnType<typeof Sandbox.builder>): void => {\n if (volumeDefs) {\n for (const [guestPath, def] of Object.entries(volumeDefs)) {\n const mb = new MountBuilder(guestPath);\n if (def.type === \"bind\" && def.source) {\n mb.bind(def.source);\n } else if (def.type === \"named\" && def.name) {\n mb.named(def.name);\n } else if (def.type === \"tmpfs\") {\n mb.tmpfs();\n if (def.sizeMib) {\n mb.size(def.sizeMib);\n }\n }\n if (def.readonly) {\n mb.readonly();\n }\n b.volume(guestPath, () => mb);\n }\n } else {\n for (const mount of resolvedMounts) {\n const mb = new MountBuilder(mount.guest);\n if (mount.type === \"Bind\" || mount.type === \"bind\") {\n if (mount.source) mb.bind(mount.source);\n } else if (mount.type === \"Named\" || mount.type === \"named\") {\n if (mount.name) mb.named(mount.name);\n } else if (mount.type === \"Tmpfs\" || mount.type === \"tmpfs\") {\n mb.tmpfs();\n if (mount.size_mib) mb.size(mount.size_mib);\n }\n if (mount.readonly) {\n mb.readonly();\n }\n b.volume(mount.guest, () => mb);\n }\n }\n };\n\n const tryCreate = async () => {\n const builder = Sandbox.builder(name)\n .detached(true)\n .image(resolvedImage)\n .cpus(resolvedCpus)\n .memory(resolvedMemoryMib);\n if (resolvedEnv) {\n builder.envs(resolvedEnv);\n }\n applyVolumes(builder);\n const tCreateInner = Date.now();\n const result = await Promise.race([\n builder.create(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(\"builder.create timed out\")), SWEEP_STOP_TIMEOUT_MS)\n ),\n ]);\n console.log(\n `[SandboxRegistry] builder.create name=${name} image=${resolvedImage} ` +\n `elapsed=${Date.now() - tCreateInner}ms ` +\n `envKeys=${resolvedEnv ? Object.keys(resolvedEnv).join(\",\") : \"none\"} ` +\n `volumes=${volumeDefs ? Object.keys(volumeDefs).join(\",\") : \"none\"}`\n );\n return result;\n };\n try {\n native = await tryCreate();\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"already exists\")) {\n await this.removeAndDelete(name);\n native = await tryCreate();\n } else {\n throw err;\n }\n }\n console.log(`[SandboxRegistry] phase=create_sandbox name=${name} elapsed=${Date.now() - tBuild}ms`);\n const tFs = Date.now();\n await this.waitForFs(native);\n console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);\n }\n\n const totalElapsed = Date.now() - tStart;\n const entry: CacheEntry = {\n native,\n lastAccessedAt: Date.now(),\n lastCheckedAt: Date.now(),\n createOptions: createOptions ?? cached?.createOptions,\n };\n this.handles.set(name, entry);\n console.log(`[SandboxRegistry] ensure DONE name=${name} total=${totalElapsed}ms idleTimeout=${Math.round(this.idleTimeoutMs / 1000)}s`);\n return native;\n })();\n\n this.creating.set(name, creation);\n creation.catch(() => {});\n void creation.finally(() => this.creating.delete(name));\n\n return creation;\n }\n}\n","import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { Sandbox, Volume } from \"microsandbox\";\nimport type { SandboxHandle } from \"microsandbox\";\nimport type { LogReadSource } from \"microsandbox\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport type { SandboxLogsInput } from \"../schemas/sandbox\";\nimport type { SandboxRuntimeMetrics } from \"../types/runtime-service\";\nimport { HttpError } from \"../lib/errors\";\nimport { getMsbPath } from \"../lib/msb\";\nimport { SandboxRegistry } from \"./SandboxRegistry\";\n\nconst execAsync = promisify(exec);\n\ntype VolumeConfig = NonNullable<EnsureSandboxInput[\"volumes\"]>[string];\n\ntype RuntimeNative = {\n fs(): {\n readString(path: string): Promise<string>;\n readToString(path: string): Promise<string>;\n write(path: string, data: Buffer): Promise<void>;\n list(path: string): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;\n read(path: string): Promise<Buffer | Uint8Array | string>;\n mkdir(path: string): Promise<void>;\n };\n exec(cmd: string, args?: string[]): Promise<{\n stdout(): string;\n stderr(): string;\n get code(): number;\n }>;\n shell(script: string): Promise<{\n stdout(): string;\n stderr(): string;\n get code(): number;\n }>;\n stop(): Promise<void>;\n kill(): Promise<void>;\n};\n\ntype SandboxConfig = {\n name: string;\n image: unknown;\n memoryMib?: number;\n cpus?: number;\n env?: unknown;\n volumes?: Record<string, unknown>;\n};\n\nfunction parseConfigJson(configJson: string): SandboxConfig {\n try {\n const raw = JSON.parse(configJson);\n const rawVolumes = raw.volumes ?? raw.mounts;\n const volumes: Record<string, unknown> = {};\n if (Array.isArray(rawVolumes)) {\n for (const mount of rawVolumes) {\n if (mount && typeof mount === \"object\" && \"guest\" in mount) {\n volumes[String(mount.guest)] = mount;\n }\n }\n } else if (rawVolumes && typeof rawVolumes === \"object\") {\n Object.assign(volumes, rawVolumes);\n }\n return {\n name: raw.name ?? \"\",\n image: raw.image ?? \"\",\n memoryMib: raw.memoryMib ?? raw.memory_mib,\n cpus: raw.cpus,\n env: raw.env ?? {},\n volumes,\n };\n } catch {\n return { name: \"\", image: \"\" };\n }\n}\n\nfunction msToIsoString(ms: number | Date | null | undefined): string {\n if (ms == null) return \"\";\n if (ms instanceof Date) return ms.toISOString();\n return new Date(ms).toISOString();\n}\n\ntype MsbInspectEnvVolumes = {\n env: unknown;\n volumes: Record<string, unknown>;\n};\n\nfunction parseMsbInspectEnvVolumes(stdout: string): MsbInspectEnvVolumes {\n const data = JSON.parse(stdout);\n const env = data?.config?.env ?? {};\n\n const volumes: Record<string, unknown> = {};\n const rawMounts = data?.config?.mounts;\n if (Array.isArray(rawMounts)) {\n for (const mount of rawMounts) {\n if (mount && typeof mount === \"object\" && \"guest\" in mount) {\n volumes[String(mount.guest)] = mount;\n }\n }\n }\n\n return { env, volumes };\n}\n\nexport class MicrosandboxRuntimeService {\n constructor(private deps: { registry?: SandboxRegistry } = {}) {}\n\n private get registry(): SandboxRegistry {\n return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());\n }\n\n private resolvePath(path: string): string {\n if (path === \"~\" || path === \"~/\") {\n return \"/\";\n }\n if (path.startsWith(\"~/\")) {\n return `/${path.slice(2)}`;\n }\n return path;\n }\n\n private toListItem(info: {\n name: string;\n status: string;\n configJson: string;\n createdAt?: number | Date | null;\n updatedAt?: number | Date | null;\n }): {\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n } {\n const config = parseConfigJson(info.configJson);\n const env = config.env ? (Array.isArray(config.env) ? config.env : config.env) : [];\n const envCount = Array.isArray(env) ? env.length : Object.keys(env as Record<string, unknown>).length;\n const volumes = config.volumes ?? {};\n\n return {\n name: info.name,\n status: info.status,\n image: config.image,\n cpus: config.cpus,\n memoryMib: config.memoryMib,\n envCount,\n volumeCount: Object.keys(volumes).length,\n createdAt: msToIsoString(info.createdAt),\n updatedAt: msToIsoString(info.updatedAt),\n };\n }\n\n private async readMsbInspect(name: string): Promise<MsbInspectEnvVolumes | undefined> {\n try {\n const { stdout } = await execAsync(\n `${getMsbPath()} inspect ${name} --format json`,\n { timeout: 5000 }\n );\n return parseMsbInspectEnvVolumes(stdout);\n } catch {\n return undefined;\n }\n }\n\n private async ensureNamedVolumes(volumes?: EnsureSandboxInput[\"volumes\"]): Promise<void> {\n if (!volumes) {\n return;\n }\n\n const defaultQuotaMib = Number(process.env.MICROSANDBOX_VOLUME_QUOTA_MIB ?? \"2048\");\n\n const namedVolumes = Object.values(volumes).filter(\n (v): v is Extract<VolumeConfig, { type: \"named\" }> => v.type === \"named\"\n );\n\n await Promise.all(\n namedVolumes.map(async (definition) => {\n try {\n await Volume.get(definition.name);\n } catch {\n await Volume.builder(definition.name).quota(defaultQuotaMib).create();\n }\n })\n );\n }\n\n private async getOrEnsureNative(name: string): Promise<RuntimeNative> {\n return (await this.registry.ensure(name)) as RuntimeNative;\n }\n\n async ensureSandbox(\n name: string,\n input: EnsureSandboxInput\n ): Promise<{\n name: string;\n status: string;\n }> {\n const image = input.image ?? process.env.MICROSANDBOX_IMAGE ?? \"python:3.11-slim\";\n const cpus = input.cpus ?? Number(process.env.MICROSANDBOX_CPUS ?? \"1\");\n const memoryMib = input.memoryMib ?? Number(process.env.MICROSANDBOX_MEMORY ?? \"512\");\n\n await this.ensureNamedVolumes(input.volumes);\n\n await this.registry.ensure(name, {\n image,\n cpus,\n memoryMib,\n env: input.env,\n volumes: input.volumes,\n });\n\n return {\n name,\n status: \"running\",\n };\n }\n\n async startSandbox(name: string): Promise<{ name: string; status: string }> {\n await this.registry.ensure(name);\n return { name, status: \"running\" };\n }\n\n async stopSandbox(name: string): Promise<{ name: string; status: string }> {\n try {\n await this.registry.pause(name);\n return { name, status: \"stopped\" };\n } catch {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n }\n\n async killSandbox(name: string): Promise<{ name: string; status: string }> {\n let handle;\n try {\n handle = await Sandbox.get(name);\n } catch {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n try {\n if (handle.status === \"running\") {\n const native = await handle.connect();\n await native.kill();\n }\n return { name, status: \"unknown\" };\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"write to relay\")) {\n return { name, status: \"unknown\" };\n }\n throw error;\n } finally {\n this.registry.remove(name);\n }\n }\n\n async deleteSandbox(name: string): Promise<{ name: string; status: string }> {\n try {\n await this.registry.removeAndDelete(name);\n return { name, status: \"unknown\" };\n } catch (error) {\n if (error instanceof HttpError) throw error;\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n }\n\n async listSandboxes(_query: ListSandboxesQuery): Promise<{\n items: Array<{\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n }>;\n total: number;\n }> {\n const all: SandboxHandle[] = await Sandbox.list();\n\n const items = all\n .map((info) =>\n this.toListItem({\n name: info.name,\n status: info.status,\n configJson: info.configJson,\n createdAt: info.createdAt,\n updatedAt: info.updatedAt,\n })\n )\n .filter((item) => {\n if (_query.status && item.status !== _query.status) {\n return false;\n }\n\n if (_query.image && item.image !== _query.image) {\n return false;\n }\n\n if (_query.search) {\n const haystack = [item.name, item.image]\n .filter((value): value is string => Boolean(value))\n .join(\" \")\n .toLowerCase();\n\n if (!haystack.includes(_query.search.toLowerCase())) {\n return false;\n }\n }\n\n return true;\n });\n\n return { items, total: items.length };\n }\n\n async getSandbox(\n name: string\n ): Promise<{\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n env: unknown;\n volumes: Record<string, unknown>;\n metrics?: SandboxRuntimeMetrics;\n createdAt: string;\n updatedAt: string;\n } | undefined> {\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n const config = parseConfigJson(handle.configJson);\n\n const msbData = await this.readMsbInspect(name);\n const env = msbData?.env ?? config.env ?? {};\n const volumes = msbData?.volumes ?? config.volumes ?? {};\n\n let metrics: SandboxRuntimeMetrics | undefined;\n\n try {\n const m = await handle.metrics();\n metrics = {\n cpuPercent: m.cpuPercent,\n memoryBytes: m.memoryBytes,\n memoryLimitBytes: m.memoryLimitBytes,\n diskReadBytes: m.diskReadBytes,\n diskWriteBytes: m.diskWriteBytes,\n netRxBytes: m.netRxBytes,\n netTxBytes: m.netTxBytes,\n uptimeMs: m.uptimeMs,\n timestampMs: m.timestamp.getTime(),\n };\n } catch {\n metrics = undefined;\n }\n\n return {\n name: handle.name,\n status: handle.status,\n image: config.image,\n cpus: config.cpus,\n memoryMib: config.memoryMib,\n env,\n volumes,\n metrics,\n createdAt: msToIsoString(handle.createdAt),\n updatedAt: msToIsoString(handle.updatedAt),\n };\n } catch {\n return undefined;\n }\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n return { name, status: handle.status };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const fs = native.fs();\n const content = typeof fs.readToString === \"function\"\n ? await fs.readToString(resolvedPath)\n : await fs.readString(resolvedPath);\n return { path: resolvedPath, content };\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const parts = resolvedPath.split(\"/\").filter(Boolean);\n for (let i = 1; i < parts.length; i++) {\n const dir = \"/\" + parts.slice(0, i).join(\"/\");\n try {\n await native.fs().mkdir(dir);\n } catch {\n // directory may already exist or parent missing, continue\n }\n }\n await native.fs().write(resolvedPath, Buffer.from(content));\n return { path: resolvedPath };\n }\n\n async listPath(\n sandboxName: string,\n path: string,\n recursive?: boolean\n ): Promise<{ entries: Array<{ path: string; type: string }> }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const entries = await native.fs().list(resolvedPath);\n return {\n entries: entries.map((entry) => ({\n path: entry.path,\n type: entry.kind,\n })),\n };\n }\n\n async findFiles(sandboxName: string, path: string, pattern: string): Promise<{ files: string[] }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const matchFlag = pattern.includes(\"/\") ? \"-path\" : \"-name\";\n const output = await native.exec(\"find\", [resolvedPath, matchFlag, pattern, \"-type\", \"f\"]);\n return { files: output.stdout().split(\"\\n\").filter(Boolean) };\n }\n\n async searchInFile(\n sandboxName: string,\n path: string,\n query: string\n ): Promise<{ matches: Array<{ line: number; content: string }> }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n let stdout: string;\n\n try {\n const output = await native.exec(\"grep\", [\"-n\", \"-E\", query, resolvedPath]);\n stdout = output.stdout();\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === 1) {\n return { matches: [] };\n }\n\n throw error;\n }\n\n return {\n matches: stdout\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => {\n const separator = line.indexOf(\":\");\n return {\n line: Number(line.slice(0, separator)),\n content: line.slice(separator + 1),\n };\n }),\n };\n }\n\n async replaceInFile(\n sandboxName: string,\n input: { path: string; search: string; replace: string }\n ): Promise<{ replaced: number }> {\n const resolvedPath = this.resolvePath(input.path);\n const native = await this.getOrEnsureNative(sandboxName);\n const fs = native.fs();\n const original = typeof fs.readToString === \"function\"\n ? await fs.readToString(resolvedPath)\n : await fs.readString(resolvedPath);\n\n if (!input.search) {\n return { replaced: 0 };\n }\n\n const occurrences = original.split(input.search).length - 1;\n if (occurrences === 0) {\n return { replaced: 0 };\n }\n\n const updated = original.split(input.search).join(input.replace);\n await fs.write(resolvedPath, Buffer.from(updated));\n\n return { replaced: occurrences };\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n await native.fs().write(resolvedPath, Buffer.from(contentBase64, \"base64\"));\n return { path: resolvedPath };\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const data = await native.fs().read(resolvedPath);\n const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);\n return { path: resolvedPath, contentBase64: buffer.toString(\"base64\") };\n }\n\n async execCommand(input: ShellExecInput): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const native = await this.getOrEnsureNative(input.sandboxName);\n const output = await native.shell(input.command);\n\n return {\n stdout: output.stdout(),\n stderr: output.stderr(),\n exitCode: output.code ?? 0,\n };\n }\n\n async getSandboxLogs(\n name: string,\n opts: SandboxLogsInput\n ): Promise<{\n entries: Array<{\n timestamp: string;\n source: string;\n sessionId: number | null;\n text: string;\n }>;\n }> {\n const handle: SandboxHandle = await Sandbox.get(name);\n\n const logOpts: { tail?: number; since?: Date; until?: Date; sources?: readonly LogReadSource[] } = {};\n\n if (opts.tail !== undefined) {\n logOpts.tail = opts.tail;\n }\n\n if (opts.since) {\n logOpts.since = new Date(opts.since);\n }\n\n if (opts.until) {\n logOpts.until = new Date(opts.until);\n }\n\n if (opts.sources && opts.sources.length > 0) {\n logOpts.sources = opts.sources as LogReadSource[];\n } else {\n logOpts.sources = [\"all\" as LogReadSource];\n }\n\n const entries = await handle.logs(logOpts);\n\n return {\n entries: entries.map((entry) => ({\n timestamp: entry.timestamp.toISOString(),\n source: entry.source,\n sessionId: entry.sessionId,\n text: entry.text(),\n })),\n };\n }\n}\n","export class HttpError extends Error {\n constructor(\n public statusCode: number,\n public code: string,\n message: string\n ) {\n super(message);\n }\n}\n\nexport function toErrorResponse(error: unknown): {\n statusCode: number;\n body: {\n success: false;\n error: {\n code: string;\n message: string;\n };\n };\n} {\n if (error instanceof HttpError) {\n return {\n statusCode: error.statusCode,\n body: {\n success: false,\n error: {\n code: error.code,\n message: error.message,\n },\n },\n };\n }\n\n return {\n statusCode: 500,\n body: {\n success: false,\n error: {\n code: \"INTERNAL_ERROR\",\n message: error instanceof Error ? error.message : String(error),\n },\n },\n };\n}\n","export function getMsbPath(): string {\n return process.env.MICROSANDBOX_CLI_PATH ?? `${process.env.HOME ?? \"/root\"}/.microsandbox/bin/msb`;\n}\n","import cors from \"@fastify/cors\";\nimport multipart from \"@fastify/multipart\";\nimport sensible from \"@fastify/sensible\";\nimport fastify, { type FastifyInstance } from \"fastify\";\nimport { toErrorResponse } from \"./lib/errors\";\nimport { registerHealthRoutes } from \"./routes/health\";\nimport { registerImageRoutes } from \"./routes/images\";\nimport { registerSandboxRoutes } from \"./routes/sandbox\";\nimport { registerVolumeFsRoutes } from \"./routes/volume-fs\";\nimport { ImageService } from \"./services/ImageService\";\nimport { MicrosandboxRuntimeService } from \"./services/MicrosandboxRuntimeService\";\nimport { configureSwagger } from \"./swagger\";\nimport type { RuntimeService } from \"./types/runtime-service\";\n\nexport async function buildApp({\n runtimeService = new MicrosandboxRuntimeService(),\n imageService = new ImageService(),\n apiKey,\n}: {\n runtimeService?: RuntimeService;\n imageService?: ImageService;\n apiKey?: string;\n} = {}): Promise<FastifyInstance> {\n const app = fastify({\n logger: false,\n bodyLimit: Number(process.env.BODY_LIMIT) || 100 * 1024 * 1024,\n });\n\n app.register(cors, {\n delegator: (request, callback) => {\n callback(null, {\n origin: true,\n methods: request.headers[\"access-control-request-method\"] ?? \"*\",\n allowedHeaders: request.headers[\"access-control-request-headers\"],\n });\n },\n });\n app.register(sensible);\n app.register(multipart);\n\n if (apiKey) {\n app.addHook(\"onRequest\", async (request, reply) => {\n if (request.method === \"OPTIONS\" || !request.url.startsWith(\"/api/\")) {\n return;\n }\n\n if (request.headers.authorization !== `Bearer ${apiKey}`) {\n await reply.code(401).send({\n success: false,\n error: {\n code: \"UNAUTHORIZED\",\n message: \"Unauthorized\",\n },\n });\n }\n });\n }\n\n registerHealthRoutes(app);\n registerSandboxRoutes(app, runtimeService);\n registerImageRoutes(app, imageService);\n registerVolumeFsRoutes(app);\n\n app.setErrorHandler((error, _request, reply) => {\n const { statusCode, body } = toErrorResponse(error);\n reply.status(statusCode).send(body);\n });\n\n await configureSwagger(app);\n\n return app;\n}\n","export type SuccessResponse<T> = {\n success: true;\n data: T;\n};\n\nexport function ok<T>(data: T): SuccessResponse<T> {\n return {\n success: true,\n data,\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { ok } from \"../lib/http\";\n\nexport function registerHealthRoutes(app: FastifyInstance): void {\n app.get(\"/health\", async () => ok({ status: \"ok\" }));\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport { ZodError } from \"zod\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport { ImageService } from \"../services/ImageService\";\nimport { imageRefQuerySchema, pullImageSchema } from \"../schemas/images\";\n\nfunction parseOrThrow<T>(parse: () => T): T {\n try {\n return parse();\n } catch (error) {\n if (error instanceof ZodError) {\n throw new HttpError(400, \"INVALID_REQUEST\", error.issues[0]?.message ?? \"Invalid request\");\n }\n\n throw error;\n }\n}\n\nexport function createImageController(imageService: ImageService) {\n return {\n listImages: async (_request: FastifyRequest, reply: FastifyReply) => {\n return reply.send(ok(await imageService.listImages()));\n },\n pullImage: async (request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply) => {\n const body = parseOrThrow(() => pullImageSchema.parse(request.body ?? {}));\n return reply.send(ok(await imageService.pullImage(body)));\n },\n getImage: async (request: FastifyRequest<{ Querystring: unknown }>, reply: FastifyReply) => {\n const query = parseOrThrow(() => imageRefQuerySchema.parse(request.query ?? {}));\n return reply.send(ok(await imageService.getImage(query.ref)));\n },\n deleteImage: async (request: FastifyRequest<{ Querystring: unknown }>, reply: FastifyReply) => {\n const query = parseOrThrow(() => imageRefQuerySchema.parse(request.query ?? {}));\n return reply.send(ok(await imageService.deleteImage(query.ref)));\n },\n };\n}\n","import z from \"zod\";\n\nexport const imageRefQuerySchema = z.object({\n ref: z.string().min(1),\n});\n\nexport const pullImageSchema = z.object({\n ref: z.string().min(1),\n});\n\nexport type ImageRefQuery = z.infer<typeof imageRefQuerySchema>;\nexport type PullImageInput = z.infer<typeof pullImageSchema>;\n","import type { FastifyInstance } from \"fastify\";\nimport { createImageController } from \"../controllers/images\";\nimport { ImageService } from \"../services/ImageService\";\n\nexport function registerImageRoutes(app: FastifyInstance, imageService: ImageService): void {\n const controller = createImageController(imageService);\n\n app.get(\"/api/images\", controller.listImages);\n app.post(\"/api/images/pull\", controller.pullImage);\n app.get(\"/api/images/detail\", controller.getImage);\n app.delete(\"/api/images/detail\", controller.deleteImage);\n}\n","import z from \"zod\";\n\nconst bindMountSchema = z.object({\n type: z.literal(\"bind\"),\n source: z.string().min(1),\n readonly: z.boolean().optional(),\n});\n\nconst namedMountSchema = z.object({\n type: z.literal(\"named\"),\n name: z.string().min(1),\n readonly: z.boolean().optional(),\n});\n\nconst tmpfsMountSchema = z.object({\n type: z.literal(\"tmpfs\"),\n sizeMib: z.number().int().positive().optional(),\n});\n\nexport const volumeSchema = z.union([\n bindMountSchema,\n namedMountSchema,\n tmpfsMountSchema,\n]);\n\nexport const ensureSandboxSchema = z.object({\n image: z.string().optional(),\n cpus: z.number().int().positive().optional(),\n memoryMib: z.number().int().positive().optional(),\n env: z.record(z.string()).optional(),\n volumes: z.record(volumeSchema).optional(),\n});\n\nexport const sandboxNameParamsSchema = z.object({\n name: z.string().min(1),\n});\n\nexport const listSandboxesQuerySchema = z.object({\n status: z.enum([\"running\", \"stopped\", \"crashed\", \"unknown\"]).optional(),\n image: z.string().min(1).optional(),\n search: z.string().min(1).optional(),\n});\n\nconst sandboxAndPathSchema = z.object({\n sandboxName: z.string().min(1),\n path: z.string().min(1),\n});\n\nexport const readFileSchema = sandboxAndPathSchema;\n\nexport const writeFileSchema = sandboxAndPathSchema.extend({\n content: z.string(),\n});\n\nexport const listPathSchema = sandboxAndPathSchema.extend({\n recursive: z.boolean().optional(),\n});\n\nexport const findFilesSchema = sandboxAndPathSchema.extend({\n pattern: z.string().min(1),\n});\n\nexport const searchInFileSchema = sandboxAndPathSchema.extend({\n query: z.string().min(1),\n});\n\nexport const replaceInFileSchema = sandboxAndPathSchema.extend({\n search: z.string(),\n replace: z.string(),\n});\n\nexport const uploadFileSchema = sandboxAndPathSchema.and(\n z.union([\n z.object({ contentBase64: z.string() }),\n z.object({ content: z.string().transform((content) => Buffer.from(content).toString(\"base64\")) }),\n ])\n);\n\nexport const downloadFileSchema = sandboxAndPathSchema;\n\nexport const shellExecSchema = z.object({\n sandboxName: z.string().min(1),\n command: z.string().min(1),\n exec_dir: z.string().optional(),\n timeout: z.number().int().positive().optional(),\n});\n\nexport const sandboxLogsSchema = z.object({\n tail: z.number().int().positive().optional(),\n since: z.string().optional(),\n until: z.string().optional(),\n sources: z.array(z.string()).optional(),\n});\n\nexport type EnsureSandboxInput = z.infer<typeof ensureSandboxSchema>;\nexport type ListSandboxesQuery = z.infer<typeof listSandboxesQuerySchema>;\nexport type ShellExecInput = z.infer<typeof shellExecSchema>;\nexport type SandboxLogsInput = z.infer<typeof sandboxLogsSchema>;\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport {\n downloadFileSchema,\n ensureSandboxSchema,\n findFilesSchema,\n listSandboxesQuerySchema,\n listPathSchema,\n readFileSchema,\n replaceInFileSchema,\n sandboxLogsSchema,\n sandboxNameParamsSchema,\n searchInFileSchema,\n shellExecSchema,\n uploadFileSchema,\n writeFileSchema,\n} from \"../schemas/sandbox\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport type { RuntimeService } from \"../types/runtime-service\";\n\nexport function createSandboxController(runtimeService: RuntimeService): {\n ensureSandbox(\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n startSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n stopSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n killSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n deleteSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n listSandboxes(\n request: FastifyRequest<{ Querystring: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getStatus(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getSandboxLogs(\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n readFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n writeFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n listPath(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n findFiles(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n searchInFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n replaceInFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n uploadFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n downloadFile(\n request: FastifyRequest<{ Querystring: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n execCommand(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n} {\n return {\n ensureSandbox: async (\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ) => {\n const body = ensureSandboxSchema.parse(request.body ?? {});\n const result = await runtimeService.ensureSandbox(request.params.name, body);\n return reply.send(ok(result));\n },\n\n startSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.startSandbox(request.params.name)));\n },\n\n stopSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.stopSandbox(request.params.name)));\n },\n\n killSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.killSandbox(request.params.name)));\n },\n\n deleteSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.deleteSandbox(request.params.name)));\n },\n\n listSandboxes: async (request, reply) => {\n const query = listSandboxesQuerySchema.parse(request.query ?? {});\n return reply.send(ok(await runtimeService.listSandboxes(query)));\n },\n\n getSandbox: async (request, reply) => {\n const params = sandboxNameParamsSchema.parse(request.params ?? {});\n const sandbox = await runtimeService.getSandbox(params.name);\n\n if (!sandbox) {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${params.name}' not found`);\n }\n\n return reply.send(ok(sandbox));\n },\n\n getStatus: async (request, reply) => {\n return reply.send(ok(await runtimeService.getStatus(request.params.name)));\n },\n\n getSandboxLogs: async (request, reply) => {\n const body = sandboxLogsSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.getSandboxLogs(request.params.name, body)));\n },\n\n readFile: async (request, reply) => {\n const body = readFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.readFile(body.sandboxName, body.path)));\n },\n\n writeFile: async (request, reply) => {\n const body = writeFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.writeFile(body.sandboxName, body.path, body.content)));\n },\n\n listPath: async (request, reply) => {\n const body = listPathSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.listPath(body.sandboxName, body.path, body.recursive)));\n },\n\n findFiles: async (request, reply) => {\n const body = findFilesSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.findFiles(body.sandboxName, body.path, body.pattern)));\n },\n\n searchInFile: async (request, reply) => {\n const body = searchInFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.searchInFile(body.sandboxName, body.path, body.query)));\n },\n\n replaceInFile: async (request, reply) => {\n const body = replaceInFileSchema.parse(request.body ?? {});\n return reply.send(\n ok(\n await runtimeService.replaceInFile(body.sandboxName, {\n path: body.path,\n search: body.search,\n replace: body.replace,\n })\n )\n );\n },\n\n uploadFile: async (request, reply) => {\n const body = uploadFileSchema.parse(request.body ?? {});\n const contentBase64 = \"contentBase64\" in body ? body.contentBase64 : Buffer.from(body.content).toString(\"base64\");\n return reply.send(ok(await runtimeService.uploadFile(body.sandboxName, body.path, contentBase64)));\n },\n\n downloadFile: async (request, reply) => {\n const query = downloadFileSchema.parse(request.query ?? {});\n return reply.send(ok(await runtimeService.downloadFile(query.sandboxName, query.path)));\n },\n\n execCommand: async (request, reply) => {\n const body = shellExecSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.execCommand(body)));\n },\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { createSandboxController } from \"../controllers/sandbox\";\nimport type { RuntimeService } from \"../types/runtime-service\";\n\nexport function registerSandboxRoutes(\n app: FastifyInstance,\n runtimeService: RuntimeService\n): void {\n const controller = createSandboxController(runtimeService);\n\n app.get(\"/api/sandboxes\", controller.listSandboxes);\n app.get(\"/api/sandboxes/:name\", controller.getSandbox);\n app.put(\"/api/sandboxes/:name\", controller.ensureSandbox);\n app.post(\"/api/sandboxes/:name/start\", controller.startSandbox);\n app.post(\"/api/sandboxes/:name/stop\", controller.stopSandbox);\n app.post(\"/api/sandboxes/:name/kill\", controller.killSandbox);\n app.delete(\"/api/sandboxes/:name\", controller.deleteSandbox);\n app.get(\"/api/sandboxes/:name/status\", controller.getStatus);\n app.post(\"/api/sandboxes/:name/logs\", controller.getSandboxLogs);\n\n app.post(\"/api/files/read\", controller.readFile);\n app.post(\"/api/files/write\", controller.writeFile);\n app.post(\"/api/files/list\", controller.listPath);\n app.post(\"/api/files/find\", controller.findFiles);\n app.post(\"/api/files/search\", controller.searchInFile);\n app.post(\"/api/files/replace\", controller.replaceInFile);\n app.post(\"/api/files/upload\", controller.uploadFile);\n app.get(\"/api/files/download\", controller.downloadFile);\n\n app.post(\"/api/shell/exec\", controller.execCommand);\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport fs from \"fs/promises\";\nimport os from \"os\";\nimport path from \"path\";\nimport { Volume } from \"microsandbox\";\nimport z from \"zod\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport {\n volumeFsReadSchema,\n volumeFsWriteSchema,\n volumeFsListSchema,\n volumeFsUploadSchema,\n volumeFsDownloadSchema,\n} from \"../schemas/volume-fs\";\n\ninterface VolumeFsParams {\n name: string;\n}\n\nconst MSB_DATA_DIR = path.join(os.homedir(), \".microsandbox\");\n\nasync function resolveVolumeHostPath(name: string): Promise<string> {\n try {\n const handle = await Volume.get(name);\n const vol = await Volume.builder(handle.name).create();\n return vol.path;\n } catch {\n try {\n const vol = await Volume.builder(name).create();\n return vol.path;\n } catch {\n return path.join(MSB_DATA_DIR, \"volumes\", name);\n }\n }\n}\n\nfunction resolveGuestPath(hostRoot: string, guestPath: string): string {\n const normalized = guestPath === \"~\" ? \"\" : guestPath.replace(/^~\\//, \"\");\n const resolved = path.join(hostRoot, path.normalize(normalized).replace(/^(\\.\\.(\\/|\\\\|$))+/, \"\"));\n if (!resolved.startsWith(hostRoot + path.sep) && resolved !== hostRoot) {\n throw new HttpError(403, \"PATH_TRAVERSAL\", \"Path traversal detected\");\n }\n return resolved;\n}\n\nexport function createVolumeFsController(): {\n readFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n writeFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string; content: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n listPath(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n downloadFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Querystring: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n uploadFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string; contentBase64: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n} {\n return {\n readFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsReadSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const content = await fs.readFile(fullPath, \"utf-8\");\n return reply.send(ok({ path: guestPath, content }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_READ_ERROR\", `Failed to read from volume '${name}': ${String(err)}`);\n }\n },\n\n writeFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath, content } = volumeFsWriteSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, content, \"utf-8\");\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_WRITE_ERROR\", `Failed to write to volume '${name}': ${String(err)}`);\n }\n },\n\n listPath: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsListSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const dirents = await fs.readdir(fullPath, { withFileTypes: true });\n const entries = dirents.map((d) => ({\n path: guestPath ? `${guestPath}/${d.name}` : d.name,\n kind: d.isDirectory() ? \"directory\" : d.isSymbolicLink() ? \"symlink\" : \"file\",\n size: 0,\n mode: 0,\n }));\n return reply.send(ok({ entries }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_LIST_ERROR\", `Failed to list volume '${name}': ${String(err)}`);\n }\n },\n\n downloadFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsDownloadSchema.parse(request.query ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const buf = await fs.readFile(fullPath);\n const contentBase64 = buf.toString(\"base64\");\n return reply.send(ok({ path: guestPath, contentBase64 }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_DOWNLOAD_ERROR\", `Failed to download from volume '${name}': ${String(err)}`);\n }\n },\n\n uploadFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath, contentBase64 } = volumeFsUploadSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n const data = Buffer.from(contentBase64, \"base64\");\n await fs.writeFile(fullPath, data);\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_UPLOAD_ERROR\", `Failed to upload to volume '${name}': ${String(err)}`);\n }\n },\n };\n}\n","import z from \"zod\";\n\nexport const volumeFsReadSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsWriteSchema = z.object({\n path: z.string(),\n content: z.string(),\n});\n\nexport const volumeFsListSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsUploadSchema = z.object({\n path: z.string(),\n contentBase64: z.string().min(1),\n});\n\nexport const volumeFsDownloadSchema = z.object({\n path: z.string(),\n});\n","import type { FastifyInstance } from \"fastify\";\nimport { createVolumeFsController } from \"../controllers/volume-fs\";\n\nexport function registerVolumeFsRoutes(app: FastifyInstance): void {\n const controller = createVolumeFsController();\n\n app.post(\"/api/volumes/:name/fs/read\", controller.readFile);\n app.post(\"/api/volumes/:name/fs/write\", controller.writeFile);\n app.post(\"/api/volumes/:name/fs/list\", controller.listPath);\n app.get(\"/api/volumes/:name/fs/download\", controller.downloadFile);\n app.post(\"/api/volumes/:name/fs/upload\", controller.uploadFile);\n}\n","import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { PullImageInput } from \"../schemas/images\";\nimport { getMsbPath } from \"../lib/msb\";\n\nconst execAsync = promisify(exec);\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\ntype ImageBindings = {\n list(): Promise<ImageRecord[]>;\n pull(ref: string): Promise<ImageRecord>;\n inspect(ref: string): Promise<ImageRecord>;\n remove(ref: string): Promise<void>;\n};\n\ntype CliImageInfo = {\n architecture: string;\n created_at: string;\n digest: string;\n layer_count: number;\n os: string;\n reference: string;\n size_bytes: number;\n};\n\nclass MicrosandboxImageBindings implements ImageBindings {\n private get msb(): string {\n return getMsbPath();\n }\n\n async list(): Promise<ImageRecord[]> {\n const { stdout } = await execAsync(`${this.msb} image ls --format json`);\n const images: CliImageInfo[] = JSON.parse(stdout);\n return images.map((img) => ({\n ref: img.reference,\n sourceType: \"oci\",\n cached: true,\n size: img.size_bytes,\n createdAt: img.created_at,\n }));\n }\n\n async pull(ref: string): Promise<ImageRecord> {\n await execAsync(`${this.msb} image pull ${ref}`);\n return this.inspect(ref);\n }\n\n async inspect(ref: string): Promise<ImageRecord> {\n const { stdout } = await execAsync(`${this.msb} image inspect ${ref} --format json`);\n const img: CliImageInfo = JSON.parse(stdout);\n return {\n ref: img.reference,\n sourceType: \"oci\",\n cached: true,\n size: img.size_bytes,\n createdAt: img.created_at,\n };\n }\n\n async remove(ref: string): Promise<void> {\n await execAsync(`${this.msb} image rm ${ref}`);\n }\n}\n\nexport class ImageService {\n constructor(\n private readonly deps: {\n bindings?: ImageBindings;\n } = {}\n ) {}\n\n private get bindings(): ImageBindings {\n return this.deps.bindings ?? new MicrosandboxImageBindings();\n }\n\n async listImages(): Promise<{ items: ImageRecord[]; total: number }> {\n const items = await this.bindings.list();\n return { items, total: items.length };\n }\n\n async pullImage(input: PullImageInput): Promise<ImageRecord> {\n return await this.bindings.pull(input.ref);\n }\n\n async getImage(ref: string): Promise<ImageRecord> {\n return await this.bindings.inspect(ref);\n }\n\n async deleteImage(ref: string): Promise<{ ref: string }> {\n await this.bindings.remove(ref);\n return { ref };\n }\n}\n","import type { FastifyInstance } from \"fastify\";\nimport swagger from \"@fastify/swagger\";\nimport swaggerUi from \"@fastify/swagger-ui\";\n\nexport const defaultSwaggerConfig = {\n openapi: {\n openapi: \"3.0.0\",\n info: {\n title: \"Microsandbox Service API\",\n description:\n \"Sandbox lifecycle management, file operations, shell execution, and image registry\",\n version: \"1.0.0\",\n },\n servers: [\n {\n url: \"http://localhost:4002\",\n description: \"Local development\",\n },\n ],\n components: {\n securitySchemes: {\n bearerAuth: {\n type: \"http\" as const,\n scheme: \"bearer\" as const,\n bearerFormat: \"API Key\",\n },\n },\n },\n tags: [\n { name: \"Sandboxes\", description: \"Sandbox lifecycle (CRUD, start, stop, kill)\" },\n { name: \"Files\", description: \"Read, write, list, search, upload, download files inside sandboxes\" },\n { name: \"Shell\", description: \"Execute commands inside sandboxes\" },\n { name: \"Images\", description: \"OCI image management (list, pull, inspect, delete)\" },\n { name: \"Volumes\", description: \"Named volume filesystem operations\" },\n { name: \"Health\", description: \"Service health check\" },\n ],\n },\n};\n\nexport const defaultSwaggerUiConfig = {\n routePrefix: \"/api-docs\",\n uiConfig: {\n docExpansion: \"list\" as const,\n deepLinking: true,\n },\n staticCSP: true,\n transformStaticCSP: (header: string) => header,\n};\n\nexport async function configureSwagger(\n app: FastifyInstance,\n customSwaggerConfig?: Partial<typeof defaultSwaggerConfig>,\n customSwaggerUiConfig?: Partial<typeof defaultSwaggerUiConfig>\n) {\n const swaggerConfig = { ...defaultSwaggerConfig, ...customSwaggerConfig };\n const swaggerUiConfig = {\n ...defaultSwaggerUiConfig,\n ...customSwaggerUiConfig,\n };\n\n await app.register(swagger, swaggerConfig);\n await app.register(swaggerUi, swaggerUiConfig);\n}\n"],"mappings":"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","names":["path","fs","ok","Sandbox","path","Sandbox","fs","z","Volume","z","z","Volume","z","exec","promisify","execAsync","promisify","exec"]}
package/dist/cli.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startServer
4
- } from "./chunk-2MMX4ESI.mjs";
5
- import "./chunk-3O2XVS6Q.mjs";
4
+ } from "./chunk-CT7REZXC.mjs";
5
+ import "./chunk-I6F4WE2G.mjs";
6
6
 
7
7
  // src/cli.ts
8
8
  void startServer().catch((error) => {
package/dist/index.d.mts CHANGED
@@ -292,6 +292,7 @@ declare function buildApp({ runtimeService, imageService, apiKey, }?: {
292
292
  declare class SandboxRegistry {
293
293
  private handles;
294
294
  private creating;
295
+ private stopping;
295
296
  private readonly idleTimeoutMs;
296
297
  private sweepTimer?;
297
298
  constructor(idleTimeoutMs?: number);
@@ -301,6 +302,7 @@ declare class SandboxRegistry {
301
302
  cleanupOrphanedSockets(): void;
302
303
  removeAndDelete(name: string): Promise<void>;
303
304
  pause(name: string): Promise<void>;
305
+ private healthCheck;
304
306
  private waitForFs;
305
307
  private hasConfigMismatch;
306
308
  ensure(name: string, createOptions?: Record<string, unknown>): Promise<unknown>;
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  MicrosandboxRuntimeService,
3
3
  SandboxRegistry,
4
4
  buildApp
5
- } from "./chunk-3O2XVS6Q.mjs";
5
+ } from "./chunk-I6F4WE2G.mjs";
6
6
  export {
7
7
  MicrosandboxRuntimeService,
8
8
  SandboxRegistry,
package/dist/server.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  startServer
3
- } from "./chunk-2MMX4ESI.mjs";
4
- import "./chunk-3O2XVS6Q.mjs";
3
+ } from "./chunk-CT7REZXC.mjs";
4
+ import "./chunk-I6F4WE2G.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.50",
3
+ "version": "0.0.52",
4
4
  "main": "dist/index.mjs",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -5,10 +5,21 @@ import { join } from "path";
5
5
 
6
6
  const DEFAULT_IMAGE = process.env.MICROSANDBOX_IMAGE ?? "daytonaio/sandbox:0.6.0";
7
7
  const DEFAULT_IDLE_TIMEOUT_MS = Number(process.env.MICROSANDBOX_IDLE_TIMEOUT_MS) || 600_000;
8
+ const DEFAULT_REMOVE_AFTER_PAUSED_MS = 7 * 24 * 60 * 60 * 1000;
8
9
  const SWEEP_INTERVAL_MS = 30_000;
10
+ const SWEEP_STOP_TIMEOUT_MS = 60_000;
11
+ const HEALTH_CHECK_TIMEOUT_MS = 2_000;
12
+ const HEALTH_CHECK_INTERVAL_MS = 30_000;
9
13
  const SANDBOX_AGENT_SOCKET_DIR = "/root/.microsandbox/run/agent";
10
14
 
11
- type CacheEntry = { native: unknown | null; lastAccessedAt: number; createOptions?: Record<string, unknown> };
15
+ type CacheEntry = {
16
+ native: unknown | null;
17
+ lastAccessedAt: number;
18
+ pausedAt?: number;
19
+ lastCheckedAt?: number;
20
+ broken?: boolean;
21
+ createOptions?: Record<string, unknown>;
22
+ };
12
23
 
13
24
  function extractConfig(configJson: string): {
14
25
  image: string;
@@ -47,6 +58,7 @@ function extractConfig(configJson: string): {
47
58
  export class SandboxRegistry {
48
59
  private handles = new Map<string, CacheEntry>();
49
60
  private creating = new Map<string, Promise<unknown>>();
61
+ private stopping = new Set<string>();
50
62
  private readonly idleTimeoutMs: number;
51
63
  private sweepTimer?: ReturnType<typeof setInterval>;
52
64
 
@@ -63,12 +75,29 @@ export class SandboxRegistry {
63
75
  const now = Date.now();
64
76
  for (const [name, entry] of this.handles) {
65
77
  if (entry.native && now - entry.lastAccessedAt > this.idleTimeoutMs) {
78
+ if (this.stopping.has(name)) {
79
+ continue;
80
+ }
66
81
  console.log(`[SandboxRegistry] sweeper pausing idle sandbox name=${name} idleMs=${now - entry.lastAccessedAt}`);
67
- void (entry.native as { stop(): Promise<void> }).stop().then(() => {
68
- entry.native = null;
82
+ this.stopping.add(name);
83
+ void Promise.race([
84
+ (entry.native as { stop(): Promise<void> }).stop(),
85
+ new Promise<void>((_, reject) => setTimeout(() => reject(new Error("stop timed out")), SWEEP_STOP_TIMEOUT_MS)),
86
+ ]).then(() => {
69
87
  console.log(`[SandboxRegistry] sweeper paused name=${name}`);
70
88
  }).catch((err: Error) => {
71
89
  console.log(`[SandboxRegistry] sweeper pause failed name=${name} err=${err.message}`);
90
+ }).finally(() => {
91
+ entry.native = null;
92
+ entry.pausedAt = Date.now();
93
+ this.stopping.delete(name);
94
+ });
95
+ } else if (!entry.native && entry.pausedAt && now - entry.pausedAt > DEFAULT_REMOVE_AFTER_PAUSED_MS) {
96
+ console.log(`[SandboxRegistry] sweeper removing paused sandbox name=${name} pausedMs=${now - entry.pausedAt}`);
97
+ void this.removeAndDelete(name).then(() => {
98
+ console.log(`[SandboxRegistry] sweeper removed name=${name}`);
99
+ }).catch((err: Error) => {
100
+ console.log(`[SandboxRegistry] sweeper remove failed name=${name} err=${err.message}`);
72
101
  });
73
102
  }
74
103
  }
@@ -114,14 +143,28 @@ export class SandboxRegistry {
114
143
  }
115
144
 
116
145
  async removeAndDelete(name: string): Promise<void> {
117
- const handle = await Sandbox.get(name);
118
- if (handle.status === "running") {
119
- try {
120
- const native = await handle.connect();
121
- await (native as { stop(): Promise<void> }).stop();
122
- } catch { /* ignore */ }
123
- }
124
- await Sandbox.remove(name);
146
+ try {
147
+ const handle = await Promise.race([
148
+ Sandbox.get(name),
149
+ new Promise<never>((_, reject) => setTimeout(() => reject(new Error("Sandbox.get timed out")), SWEEP_STOP_TIMEOUT_MS)),
150
+ ]);
151
+ if (handle.status === "running") {
152
+ try {
153
+ const native = await Promise.race([
154
+ handle.connect(),
155
+ new Promise<never>((_, reject) => setTimeout(() => reject(new Error("handle.connect timed out")), SWEEP_STOP_TIMEOUT_MS)),
156
+ ]);
157
+ await Promise.race([
158
+ (native as { stop(): Promise<void> }).stop(),
159
+ new Promise<void>((_, reject) => setTimeout(() => reject(new Error("stop timed out")), SWEEP_STOP_TIMEOUT_MS)),
160
+ ]);
161
+ } catch { /* ignore */ }
162
+ }
163
+ await Promise.race([
164
+ Sandbox.remove(name),
165
+ new Promise<void>((_, reject) => setTimeout(() => reject(new Error("Sandbox.remove timed out")), SWEEP_STOP_TIMEOUT_MS)),
166
+ ]);
167
+ } catch { /* best effort, always clean cache */ }
125
168
  this.remove(name);
126
169
  this.cleanupOrphanedSockets();
127
170
  }
@@ -137,16 +180,33 @@ export class SandboxRegistry {
137
180
  if (handle.status === "running") {
138
181
  try {
139
182
  await (entry.native as { stop(): Promise<void> }).stop();
140
- entry.native = null;
141
183
  } catch { /* ignore */ }
142
184
  }
185
+ entry.native = null;
186
+ entry.pausedAt = Date.now();
187
+ }
188
+
189
+ private async healthCheck(native: unknown): Promise<boolean> {
190
+ const fs = (native as { fs(): { list(path: string): Promise<unknown> } }).fs();
191
+ try {
192
+ await Promise.race([
193
+ fs.list("/"),
194
+ new Promise<never>((_, reject) => setTimeout(() => reject(new Error("health check timed out")), HEALTH_CHECK_TIMEOUT_MS)),
195
+ ]);
196
+ return true;
197
+ } catch {
198
+ return false;
199
+ }
143
200
  }
144
201
 
145
202
  private async waitForFs(native: unknown, maxRetries = 10): Promise<void> {
146
203
  const fs = (native as { fs(): { list(path: string): Promise<unknown> } }).fs();
147
204
  for (let i = 0; i < maxRetries; i++) {
148
205
  try {
149
- await fs.list("/");
206
+ await Promise.race([
207
+ fs.list("/"),
208
+ new Promise<never>((_, reject) => setTimeout(() => reject(new Error("FS check timed out")), 5000)),
209
+ ]);
150
210
  return;
151
211
  } catch {
152
212
  await new Promise((r) => setTimeout(r, 200));
@@ -188,13 +248,35 @@ export class SandboxRegistry {
188
248
  const tStart = Date.now();
189
249
 
190
250
  const cached = this.handles.get(name);
191
- if (cached?.native) {
192
- cached.lastAccessedAt = Date.now();
193
- console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms`);
194
- return cached.native;
251
+
252
+ if (cached?.native && !this.stopping.has(name)) {
253
+ const now = Date.now();
254
+ if (!cached.lastCheckedAt || now - cached.lastCheckedAt > HEALTH_CHECK_INTERVAL_MS) {
255
+ const tCheck = Date.now();
256
+ const ok = await this.healthCheck(cached.native);
257
+ cached.lastCheckedAt = now;
258
+ if (ok) {
259
+ cached.lastAccessedAt = now;
260
+ console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms health_ok elapsed=${Date.now() - tCheck}ms`);
261
+ return cached.native;
262
+ }
263
+ console.log(`[SandboxRegistry] ensure name=${name} HEALTH_FAIL will_recreate elapsed=${Date.now() - tStart}ms`);
264
+ cached.native = null;
265
+ cached.broken = true;
266
+ } else {
267
+ cached.lastAccessedAt = now;
268
+ console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms`);
269
+ return cached.native;
270
+ }
271
+ }
272
+
273
+ if (cached?.native && this.stopping.has(name)) {
274
+ console.log(`[SandboxRegistry] ensure name=${name} STALE_NATIVE (being stopped), forcing revive`);
275
+ cached.native = null;
195
276
  }
196
277
 
197
278
  if (cached && !cached.native) {
279
+ cached.pausedAt = undefined;
198
280
  console.log(`[SandboxRegistry] ensure name=${name} REVIVE idled=${Date.now() - cached.lastAccessedAt}ms`);
199
281
  }
200
282
 
@@ -214,7 +296,13 @@ export class SandboxRegistry {
214
296
 
215
297
  let originalConfig: ReturnType<typeof extractConfig>;
216
298
 
217
- try {
299
+ const existing = this.handles.get(name);
300
+ if (existing?.broken) {
301
+ console.log(`[SandboxRegistry] ensure name=${name} BROKEN removing before recreate`);
302
+ await this.removeAndDelete(name);
303
+ this.handles.set(name, { native: null, lastAccessedAt: Date.now(), createOptions: existing.createOptions ?? cached?.createOptions });
304
+ } else {
305
+ try {
218
306
  const tGet = Date.now();
219
307
  const handle: SandboxHandle = await Sandbox.get(name);
220
308
  console.log(`[SandboxRegistry] Sandbox.get name=${name} status=${handle.status} elapsed=${Date.now() - tGet}ms`);
@@ -228,7 +316,12 @@ export class SandboxRegistry {
228
316
  native = undefined;
229
317
  } else if (handle.status === "running") {
230
318
  const tConnect = Date.now();
231
- native = await handle.connect();
319
+ native = await Promise.race([
320
+ handle.connect(),
321
+ new Promise<never>((_, reject) =>
322
+ setTimeout(() => reject(new Error("handle.connect timed out")), SWEEP_STOP_TIMEOUT_MS)
323
+ ),
324
+ ]);
232
325
  console.log(`[SandboxRegistry] handle.connect name=${name} elapsed=${Date.now() - tConnect}ms`);
233
326
  const tFs = Date.now();
234
327
  await this.waitForFs(native);
@@ -236,7 +329,12 @@ export class SandboxRegistry {
236
329
  } else {
237
330
  try {
238
331
  const tStart2 = Date.now();
239
- native = await Sandbox.startDetached(name);
332
+ native = await Promise.race([
333
+ Sandbox.startDetached(name),
334
+ new Promise<never>((_, reject) =>
335
+ setTimeout(() => reject(new Error("startDetached timed out")), SWEEP_STOP_TIMEOUT_MS)
336
+ ),
337
+ ]);
240
338
  console.log(`[SandboxRegistry] startDetached name=${name} elapsed=${Date.now() - tStart2}ms`);
241
339
  const tFs = Date.now();
242
340
  await this.waitForFs(native);
@@ -252,9 +350,11 @@ export class SandboxRegistry {
252
350
  } else {
253
351
  await this.removeAndDelete(name);
254
352
  }
255
- } catch {
353
+ } catch (err) {
354
+ console.log(`[SandboxRegistry] ensure name=${name} existing_check failed err=${(err as Error).message}`);
256
355
  native = undefined;
257
356
  }
357
+ }
258
358
  console.log(`[SandboxRegistry] phase=existing_check name=${name} hasNative=${!!native} elapsed=${Date.now() - tCreate}ms`);
259
359
 
260
360
  if (!native) {
@@ -327,7 +427,12 @@ export class SandboxRegistry {
327
427
  }
328
428
  applyVolumes(builder);
329
429
  const tCreateInner = Date.now();
330
- const result = await builder.create();
430
+ const result = await Promise.race([
431
+ builder.create(),
432
+ new Promise<never>((_, reject) =>
433
+ setTimeout(() => reject(new Error("builder.create timed out")), SWEEP_STOP_TIMEOUT_MS)
434
+ ),
435
+ ]);
331
436
  console.log(
332
437
  `[SandboxRegistry] builder.create name=${name} image=${resolvedImage} ` +
333
438
  `elapsed=${Date.now() - tCreateInner}ms ` +
@@ -353,7 +458,13 @@ export class SandboxRegistry {
353
458
  }
354
459
 
355
460
  const totalElapsed = Date.now() - tStart;
356
- this.handles.set(name, { native, lastAccessedAt: Date.now(), createOptions: createOptions ?? cached?.createOptions });
461
+ const entry: CacheEntry = {
462
+ native,
463
+ lastAccessedAt: Date.now(),
464
+ lastCheckedAt: Date.now(),
465
+ createOptions: createOptions ?? cached?.createOptions,
466
+ };
467
+ this.handles.set(name, entry);
357
468
  console.log(`[SandboxRegistry] ensure DONE name=${name} total=${totalElapsed}ms idleTimeout=${Math.round(this.idleTimeoutMs / 1000)}s`);
358
469
  return native;
359
470
  })();
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/services/SandboxRegistry.ts","../src/services/MicrosandboxRuntimeService.ts","../src/lib/errors.ts","../src/lib/msb.ts","../src/app.ts","../src/lib/http.ts","../src/routes/health.ts","../src/controllers/images.ts","../src/schemas/images.ts","../src/routes/images.ts","../src/schemas/sandbox.ts","../src/controllers/sandbox.ts","../src/routes/sandbox.ts","../src/controllers/volume-fs.ts","../src/schemas/volume-fs.ts","../src/routes/volume-fs.ts","../src/services/ImageService.ts","../src/swagger.ts"],"sourcesContent":["import { Sandbox, MountBuilder } from \"microsandbox\";\nimport type { SandboxHandle } from \"microsandbox\";\nimport { readdirSync, readFileSync, unlinkSync } from \"fs\";\nimport { join } from \"path\";\n\nconst DEFAULT_IMAGE = process.env.MICROSANDBOX_IMAGE ?? \"daytonaio/sandbox:0.6.0\";\nconst DEFAULT_IDLE_TIMEOUT_MS = Number(process.env.MICROSANDBOX_IDLE_TIMEOUT_MS) || 600_000;\nconst SWEEP_INTERVAL_MS = 30_000;\nconst SANDBOX_AGENT_SOCKET_DIR = \"/root/.microsandbox/run/agent\";\n\ntype CacheEntry = { native: unknown | null; lastAccessedAt: number; createOptions?: Record<string, unknown> };\n\nfunction extractConfig(configJson: string): {\n image: string;\n cpus: number;\n memoryMib: number;\n env: Record<string, string>;\n mounts: Array<{ guest: string; type: string; source?: string; name?: string; size_mib?: number; readonly?: boolean }>;\n} | undefined {\n try {\n const raw = JSON.parse(configJson);\n const image = typeof raw.image === \"string\" ? raw.image\n : raw.image?.Oci?.reference ?? \"\";\n const env: Record<string, string> = {};\n const rawEnv = raw.env;\n if (Array.isArray(rawEnv)) {\n for (const entry of rawEnv) {\n if (Array.isArray(entry) && entry.length >= 2) {\n env[String(entry[0])] = String(entry[1]);\n }\n }\n } else if (rawEnv && typeof rawEnv === \"object\") {\n Object.assign(env, rawEnv);\n }\n return {\n image,\n cpus: raw.cpus ?? 1,\n memoryMib: raw.memory_mib ?? raw.memoryMib ?? 512,\n env,\n mounts: Array.isArray(raw.mounts) ? raw.mounts : [],\n };\n } catch {\n return undefined;\n }\n}\n\nexport class SandboxRegistry {\n private handles = new Map<string, CacheEntry>();\n private creating = new Map<string, Promise<unknown>>();\n private readonly idleTimeoutMs: number;\n private sweepTimer?: ReturnType<typeof setInterval>;\n\n constructor(idleTimeoutMs?: number) {\n this.idleTimeoutMs = idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;\n this.cleanupOrphanedSockets();\n if (this.idleTimeoutMs > 0) {\n this.startSweeper();\n }\n }\n\n private startSweeper(): void {\n this.sweepTimer = setInterval(() => {\n const now = Date.now();\n for (const [name, entry] of this.handles) {\n if (entry.native && now - entry.lastAccessedAt > this.idleTimeoutMs) {\n console.log(`[SandboxRegistry] sweeper pausing idle sandbox name=${name} idleMs=${now - entry.lastAccessedAt}`);\n void (entry.native as { stop(): Promise<void> }).stop().then(() => {\n entry.native = null;\n console.log(`[SandboxRegistry] sweeper paused name=${name}`);\n }).catch((err: Error) => {\n console.log(`[SandboxRegistry] sweeper pause failed name=${name} err=${err.message}`);\n });\n }\n }\n }, SWEEP_INTERVAL_MS);\n }\n\n destroy(): void {\n if (this.sweepTimer) {\n clearInterval(this.sweepTimer);\n this.sweepTimer = undefined;\n }\n this.handles.clear();\n this.creating.clear();\n }\n\n remove(name: string): void {\n this.handles.delete(name);\n this.creating.delete(name);\n }\n\n cleanupOrphanedSockets(): void {\n try {\n const activeSockets = new Set<string>();\n const unixSockets = readFileSync(\"/proc/net/unix\", \"utf-8\");\n for (const line of unixSockets.split(\"\\n\")) {\n const path = line.trim().split(\" \").pop();\n if (path && path.startsWith(SANDBOX_AGENT_SOCKET_DIR)) {\n activeSockets.add(path);\n }\n }\n for (const entry of readdirSync(SANDBOX_AGENT_SOCKET_DIR)) {\n const fullPath = join(SANDBOX_AGENT_SOCKET_DIR, entry);\n if (!activeSockets.has(fullPath)) {\n unlinkSync(fullPath);\n console.log(`[SandboxRegistry] removed orphaned socket: ${entry}`);\n }\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n console.log(`[SandboxRegistry] socket cleanup skipped: ${(err as Error).message}`);\n }\n }\n }\n\n async removeAndDelete(name: string): Promise<void> {\n const handle = await Sandbox.get(name);\n if (handle.status === \"running\") {\n try {\n const native = await handle.connect();\n await (native as { stop(): Promise<void> }).stop();\n } catch { /* ignore */ }\n }\n await Sandbox.remove(name);\n this.remove(name);\n this.cleanupOrphanedSockets();\n }\n\n async pause(name: string): Promise<void> {\n const entry = this.handles.get(name);\n if (!entry) {\n await Sandbox.get(name);\n return;\n }\n if (!entry.native) return;\n const handle = await Sandbox.get(name);\n if (handle.status === \"running\") {\n try {\n await (entry.native as { stop(): Promise<void> }).stop();\n entry.native = null;\n } catch { /* ignore */ }\n }\n }\n\n private async waitForFs(native: unknown, maxRetries = 10): Promise<void> {\n const fs = (native as { fs(): { list(path: string): Promise<unknown> } }).fs();\n for (let i = 0; i < maxRetries; i++) {\n try {\n await fs.list(\"/\");\n return;\n } catch {\n await new Promise((r) => setTimeout(r, 200));\n }\n }\n throw new Error(\"FS not ready after start\");\n }\n\n private hasConfigMismatch(\n originalConfig: ReturnType<typeof extractConfig>,\n createOptions: Record<string, unknown>\n ): boolean {\n const volumeDefs = createOptions.volumes as Record<string, { type: string }> | undefined;\n const requestEnv = createOptions.env as Record<string, string> | undefined;\n\n if (volumeDefs && Object.keys(volumeDefs).length > 0) {\n const existingGuests = new Set((originalConfig?.mounts ?? []).map((m: { guest: string }) => m.guest));\n const requestedGuests = new Set(Object.keys(volumeDefs));\n if (existingGuests.size !== requestedGuests.size ||\n ![...requestedGuests].every(g => existingGuests.has(g))) {\n console.log(`[SandboxRegistry] volumes mismatch, recreating...`);\n return true;\n }\n }\n\n if (requestEnv && originalConfig?.env) {\n for (const [key, value] of Object.entries(requestEnv)) {\n if (originalConfig.env[key] !== value) {\n console.log(`[SandboxRegistry] env mismatch (key=${key}), recreating...`);\n return true;\n }\n }\n }\n\n return false;\n }\n\n async ensure(name: string, createOptions?: Record<string, unknown>): Promise<unknown> {\n const tStart = Date.now();\n\n const cached = this.handles.get(name);\n if (cached?.native) {\n cached.lastAccessedAt = Date.now();\n console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms`);\n return cached.native;\n }\n\n if (cached && !cached.native) {\n console.log(`[SandboxRegistry] ensure name=${name} REVIVE idled=${Date.now() - cached.lastAccessedAt}ms`);\n }\n\n const inflight = this.creating.get(name);\n if (inflight) {\n console.log(`[SandboxRegistry] ensure name=${name} AWAITING_INFLIGHT`);\n return inflight;\n }\n\n const creation = (async () => {\n const tCreate = Date.now();\n let native: unknown;\n const image = (createOptions?.image as string) ?? DEFAULT_IMAGE;\n const cpus = (createOptions?.cpus as number) ?? 1;\n const memoryMib = (createOptions?.memoryMib as number) ?? 512;\n const env = (createOptions?.env as Record<string, string>) ?? undefined;\n\n let originalConfig: ReturnType<typeof extractConfig>;\n\n try {\n const tGet = Date.now();\n const handle: SandboxHandle = await Sandbox.get(name);\n console.log(`[SandboxRegistry] Sandbox.get name=${name} status=${handle.status} elapsed=${Date.now() - tGet}ms`);\n\n originalConfig = extractConfig(handle.configJson);\n\n if (handle.status === \"running\" || handle.status === \"stopped\") {\n const isNewConnection = !cached;\n if (isNewConnection && createOptions && this.hasConfigMismatch(originalConfig, createOptions)) {\n await this.removeAndDelete(name);\n native = undefined;\n } else if (handle.status === \"running\") {\n const tConnect = Date.now();\n native = await handle.connect();\n console.log(`[SandboxRegistry] handle.connect name=${name} elapsed=${Date.now() - tConnect}ms`);\n const tFs = Date.now();\n await this.waitForFs(native);\n console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);\n } else {\n try {\n const tStart2 = Date.now();\n native = await Sandbox.startDetached(name);\n console.log(`[SandboxRegistry] startDetached name=${name} elapsed=${Date.now() - tStart2}ms`);\n const tFs = Date.now();\n await this.waitForFs(native);\n console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);\n } catch {\n if (!native) {\n await this.removeAndDelete(name);\n }\n }\n }\n } else if (handle.status === \"crashed\" || handle.status === \"draining\") {\n await this.removeAndDelete(name);\n } else {\n await this.removeAndDelete(name);\n }\n } catch {\n native = undefined;\n }\n console.log(`[SandboxRegistry] phase=existing_check name=${name} hasNative=${!!native} elapsed=${Date.now() - tCreate}ms`);\n\n if (!native) {\n const effectiveOptions = createOptions ?? cached?.createOptions;\n if (!effectiveOptions) {\n console.log(`[SandboxRegistry] ensure name=${name} NOT_FOUND elapsed=${Date.now() - tStart}ms`);\n throw new Error(`Sandbox ${name} not found`);\n }\n if (!createOptions && cached?.createOptions) {\n console.log(`[SandboxRegistry] ensure name=${name} RECOVER_OPTIONS elapsed=${Date.now() - tStart}ms`);\n }\n const tBuild = Date.now();\n const volumeDefs = effectiveOptions?.volumes as Record<string, { type: string; source?: string; name?: string; sizeMib?: number; readonly?: boolean }> | undefined;\n const resolvedImage = (effectiveOptions?.image as string) ?? originalConfig?.image ?? image;\n console.log(\n `[SandboxRegistry] create sandbox=${name} image=${resolvedImage} ` +\n `from=${(effectiveOptions?.image as string) ? \"request\" : originalConfig?.image ? \"originalConfig\" : \"default\"}`\n );\n const resolvedCpus = (effectiveOptions?.cpus as number) ?? originalConfig?.cpus ?? cpus;\n const resolvedMemoryMib = (effectiveOptions?.memoryMib as number) ?? originalConfig?.memoryMib ?? memoryMib;\n const resolvedEnv = (effectiveOptions?.env as Record<string, string>) ?? originalConfig?.env ?? env;\n const resolvedMounts = originalConfig?.mounts ?? [];\n\n const applyVolumes = (b: ReturnType<typeof Sandbox.builder>): void => {\n if (volumeDefs) {\n for (const [guestPath, def] of Object.entries(volumeDefs)) {\n const mb = new MountBuilder(guestPath);\n if (def.type === \"bind\" && def.source) {\n mb.bind(def.source);\n } else if (def.type === \"named\" && def.name) {\n mb.named(def.name);\n } else if (def.type === \"tmpfs\") {\n mb.tmpfs();\n if (def.sizeMib) {\n mb.size(def.sizeMib);\n }\n }\n if (def.readonly) {\n mb.readonly();\n }\n b.volume(guestPath, () => mb);\n }\n } else {\n for (const mount of resolvedMounts) {\n const mb = new MountBuilder(mount.guest);\n if (mount.type === \"Bind\" || mount.type === \"bind\") {\n if (mount.source) mb.bind(mount.source);\n } else if (mount.type === \"Named\" || mount.type === \"named\") {\n if (mount.name) mb.named(mount.name);\n } else if (mount.type === \"Tmpfs\" || mount.type === \"tmpfs\") {\n mb.tmpfs();\n if (mount.size_mib) mb.size(mount.size_mib);\n }\n if (mount.readonly) {\n mb.readonly();\n }\n b.volume(mount.guest, () => mb);\n }\n }\n };\n\n const tryCreate = async () => {\n const builder = Sandbox.builder(name)\n .detached(true)\n .image(resolvedImage)\n .cpus(resolvedCpus)\n .memory(resolvedMemoryMib);\n if (resolvedEnv) {\n builder.envs(resolvedEnv);\n }\n applyVolumes(builder);\n const tCreateInner = Date.now();\n const result = await builder.create();\n console.log(\n `[SandboxRegistry] builder.create name=${name} image=${resolvedImage} ` +\n `elapsed=${Date.now() - tCreateInner}ms ` +\n `envKeys=${resolvedEnv ? Object.keys(resolvedEnv).join(\",\") : \"none\"} ` +\n `volumes=${volumeDefs ? Object.keys(volumeDefs).join(\",\") : \"none\"}`\n );\n return result;\n };\n try {\n native = await tryCreate();\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"already exists\")) {\n await this.removeAndDelete(name);\n native = await tryCreate();\n } else {\n throw err;\n }\n }\n console.log(`[SandboxRegistry] phase=create_sandbox name=${name} elapsed=${Date.now() - tBuild}ms`);\n const tFs = Date.now();\n await this.waitForFs(native);\n console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);\n }\n\n const totalElapsed = Date.now() - tStart;\n this.handles.set(name, { native, lastAccessedAt: Date.now(), createOptions: createOptions ?? cached?.createOptions });\n console.log(`[SandboxRegistry] ensure DONE name=${name} total=${totalElapsed}ms idleTimeout=${Math.round(this.idleTimeoutMs / 1000)}s`);\n return native;\n })();\n\n this.creating.set(name, creation);\n creation.catch(() => {});\n void creation.finally(() => this.creating.delete(name));\n\n return creation;\n }\n}\n","import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { Sandbox, Volume } from \"microsandbox\";\nimport type { SandboxHandle } from \"microsandbox\";\nimport type { LogReadSource } from \"microsandbox\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport type { SandboxLogsInput } from \"../schemas/sandbox\";\nimport type { SandboxRuntimeMetrics } from \"../types/runtime-service\";\nimport { HttpError } from \"../lib/errors\";\nimport { getMsbPath } from \"../lib/msb\";\nimport { SandboxRegistry } from \"./SandboxRegistry\";\n\nconst execAsync = promisify(exec);\n\ntype VolumeConfig = NonNullable<EnsureSandboxInput[\"volumes\"]>[string];\n\ntype RuntimeNative = {\n fs(): {\n readString(path: string): Promise<string>;\n readToString(path: string): Promise<string>;\n write(path: string, data: Buffer): Promise<void>;\n list(path: string): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;\n read(path: string): Promise<Buffer | Uint8Array | string>;\n mkdir(path: string): Promise<void>;\n };\n exec(cmd: string, args?: string[]): Promise<{\n stdout(): string;\n stderr(): string;\n get code(): number;\n }>;\n shell(script: string): Promise<{\n stdout(): string;\n stderr(): string;\n get code(): number;\n }>;\n stop(): Promise<void>;\n kill(): Promise<void>;\n};\n\ntype SandboxConfig = {\n name: string;\n image: unknown;\n memoryMib?: number;\n cpus?: number;\n env?: unknown;\n volumes?: Record<string, unknown>;\n};\n\nfunction parseConfigJson(configJson: string): SandboxConfig {\n try {\n const raw = JSON.parse(configJson);\n const rawVolumes = raw.volumes ?? raw.mounts;\n const volumes: Record<string, unknown> = {};\n if (Array.isArray(rawVolumes)) {\n for (const mount of rawVolumes) {\n if (mount && typeof mount === \"object\" && \"guest\" in mount) {\n volumes[String(mount.guest)] = mount;\n }\n }\n } else if (rawVolumes && typeof rawVolumes === \"object\") {\n Object.assign(volumes, rawVolumes);\n }\n return {\n name: raw.name ?? \"\",\n image: raw.image ?? \"\",\n memoryMib: raw.memoryMib ?? raw.memory_mib,\n cpus: raw.cpus,\n env: raw.env ?? {},\n volumes,\n };\n } catch {\n return { name: \"\", image: \"\" };\n }\n}\n\nfunction msToIsoString(ms: number | Date | null | undefined): string {\n if (ms == null) return \"\";\n if (ms instanceof Date) return ms.toISOString();\n return new Date(ms).toISOString();\n}\n\ntype MsbInspectEnvVolumes = {\n env: unknown;\n volumes: Record<string, unknown>;\n};\n\nfunction parseMsbInspectEnvVolumes(stdout: string): MsbInspectEnvVolumes {\n const data = JSON.parse(stdout);\n const env = data?.config?.env ?? {};\n\n const volumes: Record<string, unknown> = {};\n const rawMounts = data?.config?.mounts;\n if (Array.isArray(rawMounts)) {\n for (const mount of rawMounts) {\n if (mount && typeof mount === \"object\" && \"guest\" in mount) {\n volumes[String(mount.guest)] = mount;\n }\n }\n }\n\n return { env, volumes };\n}\n\nexport class MicrosandboxRuntimeService {\n constructor(private deps: { registry?: SandboxRegistry } = {}) {}\n\n private get registry(): SandboxRegistry {\n return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());\n }\n\n private resolvePath(path: string): string {\n if (path === \"~\" || path === \"~/\") {\n return \"/\";\n }\n if (path.startsWith(\"~/\")) {\n return `/${path.slice(2)}`;\n }\n return path;\n }\n\n private toListItem(info: {\n name: string;\n status: string;\n configJson: string;\n createdAt?: number | Date | null;\n updatedAt?: number | Date | null;\n }): {\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n } {\n const config = parseConfigJson(info.configJson);\n const env = config.env ? (Array.isArray(config.env) ? config.env : config.env) : [];\n const envCount = Array.isArray(env) ? env.length : Object.keys(env as Record<string, unknown>).length;\n const volumes = config.volumes ?? {};\n\n return {\n name: info.name,\n status: info.status,\n image: config.image,\n cpus: config.cpus,\n memoryMib: config.memoryMib,\n envCount,\n volumeCount: Object.keys(volumes).length,\n createdAt: msToIsoString(info.createdAt),\n updatedAt: msToIsoString(info.updatedAt),\n };\n }\n\n private async readMsbInspect(name: string): Promise<MsbInspectEnvVolumes | undefined> {\n try {\n const { stdout } = await execAsync(\n `${getMsbPath()} inspect ${name} --format json`,\n { timeout: 5000 }\n );\n return parseMsbInspectEnvVolumes(stdout);\n } catch {\n return undefined;\n }\n }\n\n private async ensureNamedVolumes(volumes?: EnsureSandboxInput[\"volumes\"]): Promise<void> {\n if (!volumes) {\n return;\n }\n\n const defaultQuotaMib = Number(process.env.MICROSANDBOX_VOLUME_QUOTA_MIB ?? \"2048\");\n\n const namedVolumes = Object.values(volumes).filter(\n (v): v is Extract<VolumeConfig, { type: \"named\" }> => v.type === \"named\"\n );\n\n await Promise.all(\n namedVolumes.map(async (definition) => {\n try {\n await Volume.get(definition.name);\n } catch {\n await Volume.builder(definition.name).quota(defaultQuotaMib).create();\n }\n })\n );\n }\n\n private async getOrEnsureNative(name: string): Promise<RuntimeNative> {\n return (await this.registry.ensure(name)) as RuntimeNative;\n }\n\n async ensureSandbox(\n name: string,\n input: EnsureSandboxInput\n ): Promise<{\n name: string;\n status: string;\n }> {\n const image = input.image ?? process.env.MICROSANDBOX_IMAGE ?? \"python:3.11-slim\";\n const cpus = input.cpus ?? Number(process.env.MICROSANDBOX_CPUS ?? \"1\");\n const memoryMib = input.memoryMib ?? Number(process.env.MICROSANDBOX_MEMORY ?? \"512\");\n\n await this.ensureNamedVolumes(input.volumes);\n\n await this.registry.ensure(name, {\n image,\n cpus,\n memoryMib,\n env: input.env,\n volumes: input.volumes,\n });\n\n return {\n name,\n status: \"running\",\n };\n }\n\n async startSandbox(name: string): Promise<{ name: string; status: string }> {\n await this.registry.ensure(name);\n return { name, status: \"running\" };\n }\n\n async stopSandbox(name: string): Promise<{ name: string; status: string }> {\n try {\n await this.registry.pause(name);\n return { name, status: \"stopped\" };\n } catch {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n }\n\n async killSandbox(name: string): Promise<{ name: string; status: string }> {\n let handle;\n try {\n handle = await Sandbox.get(name);\n } catch {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n try {\n if (handle.status === \"running\") {\n const native = await handle.connect();\n await native.kill();\n }\n return { name, status: \"unknown\" };\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"write to relay\")) {\n return { name, status: \"unknown\" };\n }\n throw error;\n } finally {\n this.registry.remove(name);\n }\n }\n\n async deleteSandbox(name: string): Promise<{ name: string; status: string }> {\n try {\n await this.registry.removeAndDelete(name);\n return { name, status: \"unknown\" };\n } catch (error) {\n if (error instanceof HttpError) throw error;\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n }\n\n async listSandboxes(_query: ListSandboxesQuery): Promise<{\n items: Array<{\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n }>;\n total: number;\n }> {\n const all: SandboxHandle[] = await Sandbox.list();\n\n const items = all\n .map((info) =>\n this.toListItem({\n name: info.name,\n status: info.status,\n configJson: info.configJson,\n createdAt: info.createdAt,\n updatedAt: info.updatedAt,\n })\n )\n .filter((item) => {\n if (_query.status && item.status !== _query.status) {\n return false;\n }\n\n if (_query.image && item.image !== _query.image) {\n return false;\n }\n\n if (_query.search) {\n const haystack = [item.name, item.image]\n .filter((value): value is string => Boolean(value))\n .join(\" \")\n .toLowerCase();\n\n if (!haystack.includes(_query.search.toLowerCase())) {\n return false;\n }\n }\n\n return true;\n });\n\n return { items, total: items.length };\n }\n\n async getSandbox(\n name: string\n ): Promise<{\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n env: unknown;\n volumes: Record<string, unknown>;\n metrics?: SandboxRuntimeMetrics;\n createdAt: string;\n updatedAt: string;\n } | undefined> {\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n const config = parseConfigJson(handle.configJson);\n\n const msbData = await this.readMsbInspect(name);\n const env = msbData?.env ?? config.env ?? {};\n const volumes = msbData?.volumes ?? config.volumes ?? {};\n\n let metrics: SandboxRuntimeMetrics | undefined;\n\n try {\n const m = await handle.metrics();\n metrics = {\n cpuPercent: m.cpuPercent,\n memoryBytes: m.memoryBytes,\n memoryLimitBytes: m.memoryLimitBytes,\n diskReadBytes: m.diskReadBytes,\n diskWriteBytes: m.diskWriteBytes,\n netRxBytes: m.netRxBytes,\n netTxBytes: m.netTxBytes,\n uptimeMs: m.uptimeMs,\n timestampMs: m.timestamp.getTime(),\n };\n } catch {\n metrics = undefined;\n }\n\n return {\n name: handle.name,\n status: handle.status,\n image: config.image,\n cpus: config.cpus,\n memoryMib: config.memoryMib,\n env,\n volumes,\n metrics,\n createdAt: msToIsoString(handle.createdAt),\n updatedAt: msToIsoString(handle.updatedAt),\n };\n } catch {\n return undefined;\n }\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n return { name, status: handle.status };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const fs = native.fs();\n const content = typeof fs.readToString === \"function\"\n ? await fs.readToString(resolvedPath)\n : await fs.readString(resolvedPath);\n return { path: resolvedPath, content };\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const parts = resolvedPath.split(\"/\").filter(Boolean);\n for (let i = 1; i < parts.length; i++) {\n const dir = \"/\" + parts.slice(0, i).join(\"/\");\n try {\n await native.fs().mkdir(dir);\n } catch {\n // directory may already exist or parent missing, continue\n }\n }\n await native.fs().write(resolvedPath, Buffer.from(content));\n return { path: resolvedPath };\n }\n\n async listPath(\n sandboxName: string,\n path: string,\n recursive?: boolean\n ): Promise<{ entries: Array<{ path: string; type: string }> }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const entries = await native.fs().list(resolvedPath);\n return {\n entries: entries.map((entry) => ({\n path: entry.path,\n type: entry.kind,\n })),\n };\n }\n\n async findFiles(sandboxName: string, path: string, pattern: string): Promise<{ files: string[] }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const matchFlag = pattern.includes(\"/\") ? \"-path\" : \"-name\";\n const output = await native.exec(\"find\", [resolvedPath, matchFlag, pattern, \"-type\", \"f\"]);\n return { files: output.stdout().split(\"\\n\").filter(Boolean) };\n }\n\n async searchInFile(\n sandboxName: string,\n path: string,\n query: string\n ): Promise<{ matches: Array<{ line: number; content: string }> }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n let stdout: string;\n\n try {\n const output = await native.exec(\"grep\", [\"-n\", \"-E\", query, resolvedPath]);\n stdout = output.stdout();\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === 1) {\n return { matches: [] };\n }\n\n throw error;\n }\n\n return {\n matches: stdout\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => {\n const separator = line.indexOf(\":\");\n return {\n line: Number(line.slice(0, separator)),\n content: line.slice(separator + 1),\n };\n }),\n };\n }\n\n async replaceInFile(\n sandboxName: string,\n input: { path: string; search: string; replace: string }\n ): Promise<{ replaced: number }> {\n const resolvedPath = this.resolvePath(input.path);\n const native = await this.getOrEnsureNative(sandboxName);\n const fs = native.fs();\n const original = typeof fs.readToString === \"function\"\n ? await fs.readToString(resolvedPath)\n : await fs.readString(resolvedPath);\n\n if (!input.search) {\n return { replaced: 0 };\n }\n\n const occurrences = original.split(input.search).length - 1;\n if (occurrences === 0) {\n return { replaced: 0 };\n }\n\n const updated = original.split(input.search).join(input.replace);\n await fs.write(resolvedPath, Buffer.from(updated));\n\n return { replaced: occurrences };\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n await native.fs().write(resolvedPath, Buffer.from(contentBase64, \"base64\"));\n return { path: resolvedPath };\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const data = await native.fs().read(resolvedPath);\n const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);\n return { path: resolvedPath, contentBase64: buffer.toString(\"base64\") };\n }\n\n async execCommand(input: ShellExecInput): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const native = await this.getOrEnsureNative(input.sandboxName);\n const output = await native.shell(input.command);\n\n return {\n stdout: output.stdout(),\n stderr: output.stderr(),\n exitCode: output.code ?? 0,\n };\n }\n\n async getSandboxLogs(\n name: string,\n opts: SandboxLogsInput\n ): Promise<{\n entries: Array<{\n timestamp: string;\n source: string;\n sessionId: number | null;\n text: string;\n }>;\n }> {\n const handle: SandboxHandle = await Sandbox.get(name);\n\n const logOpts: { tail?: number; since?: Date; until?: Date; sources?: readonly LogReadSource[] } = {};\n\n if (opts.tail !== undefined) {\n logOpts.tail = opts.tail;\n }\n\n if (opts.since) {\n logOpts.since = new Date(opts.since);\n }\n\n if (opts.until) {\n logOpts.until = new Date(opts.until);\n }\n\n if (opts.sources && opts.sources.length > 0) {\n logOpts.sources = opts.sources as LogReadSource[];\n } else {\n logOpts.sources = [\"all\" as LogReadSource];\n }\n\n const entries = await handle.logs(logOpts);\n\n return {\n entries: entries.map((entry) => ({\n timestamp: entry.timestamp.toISOString(),\n source: entry.source,\n sessionId: entry.sessionId,\n text: entry.text(),\n })),\n };\n }\n}\n","export class HttpError extends Error {\n constructor(\n public statusCode: number,\n public code: string,\n message: string\n ) {\n super(message);\n }\n}\n\nexport function toErrorResponse(error: unknown): {\n statusCode: number;\n body: {\n success: false;\n error: {\n code: string;\n message: string;\n };\n };\n} {\n if (error instanceof HttpError) {\n return {\n statusCode: error.statusCode,\n body: {\n success: false,\n error: {\n code: error.code,\n message: error.message,\n },\n },\n };\n }\n\n return {\n statusCode: 500,\n body: {\n success: false,\n error: {\n code: \"INTERNAL_ERROR\",\n message: error instanceof Error ? error.message : String(error),\n },\n },\n };\n}\n","export function getMsbPath(): string {\n return process.env.MICROSANDBOX_CLI_PATH ?? `${process.env.HOME ?? \"/root\"}/.microsandbox/bin/msb`;\n}\n","import cors from \"@fastify/cors\";\nimport multipart from \"@fastify/multipart\";\nimport sensible from \"@fastify/sensible\";\nimport fastify, { type FastifyInstance } from \"fastify\";\nimport { toErrorResponse } from \"./lib/errors\";\nimport { registerHealthRoutes } from \"./routes/health\";\nimport { registerImageRoutes } from \"./routes/images\";\nimport { registerSandboxRoutes } from \"./routes/sandbox\";\nimport { registerVolumeFsRoutes } from \"./routes/volume-fs\";\nimport { ImageService } from \"./services/ImageService\";\nimport { MicrosandboxRuntimeService } from \"./services/MicrosandboxRuntimeService\";\nimport { configureSwagger } from \"./swagger\";\nimport type { RuntimeService } from \"./types/runtime-service\";\n\nexport async function buildApp({\n runtimeService = new MicrosandboxRuntimeService(),\n imageService = new ImageService(),\n apiKey,\n}: {\n runtimeService?: RuntimeService;\n imageService?: ImageService;\n apiKey?: string;\n} = {}): Promise<FastifyInstance> {\n const app = fastify({\n logger: false,\n bodyLimit: Number(process.env.BODY_LIMIT) || 100 * 1024 * 1024,\n });\n\n app.register(cors, {\n delegator: (request, callback) => {\n callback(null, {\n origin: true,\n methods: request.headers[\"access-control-request-method\"] ?? \"*\",\n allowedHeaders: request.headers[\"access-control-request-headers\"],\n });\n },\n });\n app.register(sensible);\n app.register(multipart);\n\n if (apiKey) {\n app.addHook(\"onRequest\", async (request, reply) => {\n if (request.method === \"OPTIONS\" || !request.url.startsWith(\"/api/\")) {\n return;\n }\n\n if (request.headers.authorization !== `Bearer ${apiKey}`) {\n await reply.code(401).send({\n success: false,\n error: {\n code: \"UNAUTHORIZED\",\n message: \"Unauthorized\",\n },\n });\n }\n });\n }\n\n registerHealthRoutes(app);\n registerSandboxRoutes(app, runtimeService);\n registerImageRoutes(app, imageService);\n registerVolumeFsRoutes(app);\n\n app.setErrorHandler((error, _request, reply) => {\n const { statusCode, body } = toErrorResponse(error);\n reply.status(statusCode).send(body);\n });\n\n await configureSwagger(app);\n\n return app;\n}\n","export type SuccessResponse<T> = {\n success: true;\n data: T;\n};\n\nexport function ok<T>(data: T): SuccessResponse<T> {\n return {\n success: true,\n data,\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { ok } from \"../lib/http\";\n\nexport function registerHealthRoutes(app: FastifyInstance): void {\n app.get(\"/health\", async () => ok({ status: \"ok\" }));\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport { ZodError } from \"zod\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport { ImageService } from \"../services/ImageService\";\nimport { imageRefQuerySchema, pullImageSchema } from \"../schemas/images\";\n\nfunction parseOrThrow<T>(parse: () => T): T {\n try {\n return parse();\n } catch (error) {\n if (error instanceof ZodError) {\n throw new HttpError(400, \"INVALID_REQUEST\", error.issues[0]?.message ?? \"Invalid request\");\n }\n\n throw error;\n }\n}\n\nexport function createImageController(imageService: ImageService) {\n return {\n listImages: async (_request: FastifyRequest, reply: FastifyReply) => {\n return reply.send(ok(await imageService.listImages()));\n },\n pullImage: async (request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply) => {\n const body = parseOrThrow(() => pullImageSchema.parse(request.body ?? {}));\n return reply.send(ok(await imageService.pullImage(body)));\n },\n getImage: async (request: FastifyRequest<{ Querystring: unknown }>, reply: FastifyReply) => {\n const query = parseOrThrow(() => imageRefQuerySchema.parse(request.query ?? {}));\n return reply.send(ok(await imageService.getImage(query.ref)));\n },\n deleteImage: async (request: FastifyRequest<{ Querystring: unknown }>, reply: FastifyReply) => {\n const query = parseOrThrow(() => imageRefQuerySchema.parse(request.query ?? {}));\n return reply.send(ok(await imageService.deleteImage(query.ref)));\n },\n };\n}\n","import z from \"zod\";\n\nexport const imageRefQuerySchema = z.object({\n ref: z.string().min(1),\n});\n\nexport const pullImageSchema = z.object({\n ref: z.string().min(1),\n});\n\nexport type ImageRefQuery = z.infer<typeof imageRefQuerySchema>;\nexport type PullImageInput = z.infer<typeof pullImageSchema>;\n","import type { FastifyInstance } from \"fastify\";\nimport { createImageController } from \"../controllers/images\";\nimport { ImageService } from \"../services/ImageService\";\n\nexport function registerImageRoutes(app: FastifyInstance, imageService: ImageService): void {\n const controller = createImageController(imageService);\n\n app.get(\"/api/images\", controller.listImages);\n app.post(\"/api/images/pull\", controller.pullImage);\n app.get(\"/api/images/detail\", controller.getImage);\n app.delete(\"/api/images/detail\", controller.deleteImage);\n}\n","import z from \"zod\";\n\nconst bindMountSchema = z.object({\n type: z.literal(\"bind\"),\n source: z.string().min(1),\n readonly: z.boolean().optional(),\n});\n\nconst namedMountSchema = z.object({\n type: z.literal(\"named\"),\n name: z.string().min(1),\n readonly: z.boolean().optional(),\n});\n\nconst tmpfsMountSchema = z.object({\n type: z.literal(\"tmpfs\"),\n sizeMib: z.number().int().positive().optional(),\n});\n\nexport const volumeSchema = z.union([\n bindMountSchema,\n namedMountSchema,\n tmpfsMountSchema,\n]);\n\nexport const ensureSandboxSchema = z.object({\n image: z.string().optional(),\n cpus: z.number().int().positive().optional(),\n memoryMib: z.number().int().positive().optional(),\n env: z.record(z.string()).optional(),\n volumes: z.record(volumeSchema).optional(),\n});\n\nexport const sandboxNameParamsSchema = z.object({\n name: z.string().min(1),\n});\n\nexport const listSandboxesQuerySchema = z.object({\n status: z.enum([\"running\", \"stopped\", \"crashed\", \"unknown\"]).optional(),\n image: z.string().min(1).optional(),\n search: z.string().min(1).optional(),\n});\n\nconst sandboxAndPathSchema = z.object({\n sandboxName: z.string().min(1),\n path: z.string().min(1),\n});\n\nexport const readFileSchema = sandboxAndPathSchema;\n\nexport const writeFileSchema = sandboxAndPathSchema.extend({\n content: z.string(),\n});\n\nexport const listPathSchema = sandboxAndPathSchema.extend({\n recursive: z.boolean().optional(),\n});\n\nexport const findFilesSchema = sandboxAndPathSchema.extend({\n pattern: z.string().min(1),\n});\n\nexport const searchInFileSchema = sandboxAndPathSchema.extend({\n query: z.string().min(1),\n});\n\nexport const replaceInFileSchema = sandboxAndPathSchema.extend({\n search: z.string(),\n replace: z.string(),\n});\n\nexport const uploadFileSchema = sandboxAndPathSchema.and(\n z.union([\n z.object({ contentBase64: z.string() }),\n z.object({ content: z.string().transform((content) => Buffer.from(content).toString(\"base64\")) }),\n ])\n);\n\nexport const downloadFileSchema = sandboxAndPathSchema;\n\nexport const shellExecSchema = z.object({\n sandboxName: z.string().min(1),\n command: z.string().min(1),\n exec_dir: z.string().optional(),\n timeout: z.number().int().positive().optional(),\n});\n\nexport const sandboxLogsSchema = z.object({\n tail: z.number().int().positive().optional(),\n since: z.string().optional(),\n until: z.string().optional(),\n sources: z.array(z.string()).optional(),\n});\n\nexport type EnsureSandboxInput = z.infer<typeof ensureSandboxSchema>;\nexport type ListSandboxesQuery = z.infer<typeof listSandboxesQuerySchema>;\nexport type ShellExecInput = z.infer<typeof shellExecSchema>;\nexport type SandboxLogsInput = z.infer<typeof sandboxLogsSchema>;\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport {\n downloadFileSchema,\n ensureSandboxSchema,\n findFilesSchema,\n listSandboxesQuerySchema,\n listPathSchema,\n readFileSchema,\n replaceInFileSchema,\n sandboxLogsSchema,\n sandboxNameParamsSchema,\n searchInFileSchema,\n shellExecSchema,\n uploadFileSchema,\n writeFileSchema,\n} from \"../schemas/sandbox\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport type { RuntimeService } from \"../types/runtime-service\";\n\nexport function createSandboxController(runtimeService: RuntimeService): {\n ensureSandbox(\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n startSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n stopSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n killSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n deleteSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n listSandboxes(\n request: FastifyRequest<{ Querystring: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getStatus(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getSandboxLogs(\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n readFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n writeFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n listPath(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n findFiles(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n searchInFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n replaceInFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n uploadFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n downloadFile(\n request: FastifyRequest<{ Querystring: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n execCommand(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n} {\n return {\n ensureSandbox: async (\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ) => {\n const body = ensureSandboxSchema.parse(request.body ?? {});\n const result = await runtimeService.ensureSandbox(request.params.name, body);\n return reply.send(ok(result));\n },\n\n startSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.startSandbox(request.params.name)));\n },\n\n stopSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.stopSandbox(request.params.name)));\n },\n\n killSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.killSandbox(request.params.name)));\n },\n\n deleteSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.deleteSandbox(request.params.name)));\n },\n\n listSandboxes: async (request, reply) => {\n const query = listSandboxesQuerySchema.parse(request.query ?? {});\n return reply.send(ok(await runtimeService.listSandboxes(query)));\n },\n\n getSandbox: async (request, reply) => {\n const params = sandboxNameParamsSchema.parse(request.params ?? {});\n const sandbox = await runtimeService.getSandbox(params.name);\n\n if (!sandbox) {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${params.name}' not found`);\n }\n\n return reply.send(ok(sandbox));\n },\n\n getStatus: async (request, reply) => {\n return reply.send(ok(await runtimeService.getStatus(request.params.name)));\n },\n\n getSandboxLogs: async (request, reply) => {\n const body = sandboxLogsSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.getSandboxLogs(request.params.name, body)));\n },\n\n readFile: async (request, reply) => {\n const body = readFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.readFile(body.sandboxName, body.path)));\n },\n\n writeFile: async (request, reply) => {\n const body = writeFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.writeFile(body.sandboxName, body.path, body.content)));\n },\n\n listPath: async (request, reply) => {\n const body = listPathSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.listPath(body.sandboxName, body.path, body.recursive)));\n },\n\n findFiles: async (request, reply) => {\n const body = findFilesSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.findFiles(body.sandboxName, body.path, body.pattern)));\n },\n\n searchInFile: async (request, reply) => {\n const body = searchInFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.searchInFile(body.sandboxName, body.path, body.query)));\n },\n\n replaceInFile: async (request, reply) => {\n const body = replaceInFileSchema.parse(request.body ?? {});\n return reply.send(\n ok(\n await runtimeService.replaceInFile(body.sandboxName, {\n path: body.path,\n search: body.search,\n replace: body.replace,\n })\n )\n );\n },\n\n uploadFile: async (request, reply) => {\n const body = uploadFileSchema.parse(request.body ?? {});\n const contentBase64 = \"contentBase64\" in body ? body.contentBase64 : Buffer.from(body.content).toString(\"base64\");\n return reply.send(ok(await runtimeService.uploadFile(body.sandboxName, body.path, contentBase64)));\n },\n\n downloadFile: async (request, reply) => {\n const query = downloadFileSchema.parse(request.query ?? {});\n return reply.send(ok(await runtimeService.downloadFile(query.sandboxName, query.path)));\n },\n\n execCommand: async (request, reply) => {\n const body = shellExecSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.execCommand(body)));\n },\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { createSandboxController } from \"../controllers/sandbox\";\nimport type { RuntimeService } from \"../types/runtime-service\";\n\nexport function registerSandboxRoutes(\n app: FastifyInstance,\n runtimeService: RuntimeService\n): void {\n const controller = createSandboxController(runtimeService);\n\n app.get(\"/api/sandboxes\", controller.listSandboxes);\n app.get(\"/api/sandboxes/:name\", controller.getSandbox);\n app.put(\"/api/sandboxes/:name\", controller.ensureSandbox);\n app.post(\"/api/sandboxes/:name/start\", controller.startSandbox);\n app.post(\"/api/sandboxes/:name/stop\", controller.stopSandbox);\n app.post(\"/api/sandboxes/:name/kill\", controller.killSandbox);\n app.delete(\"/api/sandboxes/:name\", controller.deleteSandbox);\n app.get(\"/api/sandboxes/:name/status\", controller.getStatus);\n app.post(\"/api/sandboxes/:name/logs\", controller.getSandboxLogs);\n\n app.post(\"/api/files/read\", controller.readFile);\n app.post(\"/api/files/write\", controller.writeFile);\n app.post(\"/api/files/list\", controller.listPath);\n app.post(\"/api/files/find\", controller.findFiles);\n app.post(\"/api/files/search\", controller.searchInFile);\n app.post(\"/api/files/replace\", controller.replaceInFile);\n app.post(\"/api/files/upload\", controller.uploadFile);\n app.get(\"/api/files/download\", controller.downloadFile);\n\n app.post(\"/api/shell/exec\", controller.execCommand);\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport fs from \"fs/promises\";\nimport os from \"os\";\nimport path from \"path\";\nimport { Volume } from \"microsandbox\";\nimport z from \"zod\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport {\n volumeFsReadSchema,\n volumeFsWriteSchema,\n volumeFsListSchema,\n volumeFsUploadSchema,\n volumeFsDownloadSchema,\n} from \"../schemas/volume-fs\";\n\ninterface VolumeFsParams {\n name: string;\n}\n\nconst MSB_DATA_DIR = path.join(os.homedir(), \".microsandbox\");\n\nasync function resolveVolumeHostPath(name: string): Promise<string> {\n try {\n const handle = await Volume.get(name);\n const vol = await Volume.builder(handle.name).create();\n return vol.path;\n } catch {\n try {\n const vol = await Volume.builder(name).create();\n return vol.path;\n } catch {\n return path.join(MSB_DATA_DIR, \"volumes\", name);\n }\n }\n}\n\nfunction resolveGuestPath(hostRoot: string, guestPath: string): string {\n const normalized = guestPath === \"~\" ? \"\" : guestPath.replace(/^~\\//, \"\");\n const resolved = path.join(hostRoot, path.normalize(normalized).replace(/^(\\.\\.(\\/|\\\\|$))+/, \"\"));\n if (!resolved.startsWith(hostRoot + path.sep) && resolved !== hostRoot) {\n throw new HttpError(403, \"PATH_TRAVERSAL\", \"Path traversal detected\");\n }\n return resolved;\n}\n\nexport function createVolumeFsController(): {\n readFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n writeFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string; content: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n listPath(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n downloadFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Querystring: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n uploadFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string; contentBase64: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n} {\n return {\n readFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsReadSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const content = await fs.readFile(fullPath, \"utf-8\");\n return reply.send(ok({ path: guestPath, content }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_READ_ERROR\", `Failed to read from volume '${name}': ${String(err)}`);\n }\n },\n\n writeFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath, content } = volumeFsWriteSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, content, \"utf-8\");\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_WRITE_ERROR\", `Failed to write to volume '${name}': ${String(err)}`);\n }\n },\n\n listPath: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsListSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const dirents = await fs.readdir(fullPath, { withFileTypes: true });\n const entries = dirents.map((d) => ({\n path: guestPath ? `${guestPath}/${d.name}` : d.name,\n kind: d.isDirectory() ? \"directory\" : d.isSymbolicLink() ? \"symlink\" : \"file\",\n size: 0,\n mode: 0,\n }));\n return reply.send(ok({ entries }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_LIST_ERROR\", `Failed to list volume '${name}': ${String(err)}`);\n }\n },\n\n downloadFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsDownloadSchema.parse(request.query ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const buf = await fs.readFile(fullPath);\n const contentBase64 = buf.toString(\"base64\");\n return reply.send(ok({ path: guestPath, contentBase64 }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_DOWNLOAD_ERROR\", `Failed to download from volume '${name}': ${String(err)}`);\n }\n },\n\n uploadFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath, contentBase64 } = volumeFsUploadSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n const data = Buffer.from(contentBase64, \"base64\");\n await fs.writeFile(fullPath, data);\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_UPLOAD_ERROR\", `Failed to upload to volume '${name}': ${String(err)}`);\n }\n },\n };\n}\n","import z from \"zod\";\n\nexport const volumeFsReadSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsWriteSchema = z.object({\n path: z.string(),\n content: z.string(),\n});\n\nexport const volumeFsListSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsUploadSchema = z.object({\n path: z.string(),\n contentBase64: z.string().min(1),\n});\n\nexport const volumeFsDownloadSchema = z.object({\n path: z.string(),\n});\n","import type { FastifyInstance } from \"fastify\";\nimport { createVolumeFsController } from \"../controllers/volume-fs\";\n\nexport function registerVolumeFsRoutes(app: FastifyInstance): void {\n const controller = createVolumeFsController();\n\n app.post(\"/api/volumes/:name/fs/read\", controller.readFile);\n app.post(\"/api/volumes/:name/fs/write\", controller.writeFile);\n app.post(\"/api/volumes/:name/fs/list\", controller.listPath);\n app.get(\"/api/volumes/:name/fs/download\", controller.downloadFile);\n app.post(\"/api/volumes/:name/fs/upload\", controller.uploadFile);\n}\n","import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { PullImageInput } from \"../schemas/images\";\nimport { getMsbPath } from \"../lib/msb\";\n\nconst execAsync = promisify(exec);\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\ntype ImageBindings = {\n list(): Promise<ImageRecord[]>;\n pull(ref: string): Promise<ImageRecord>;\n inspect(ref: string): Promise<ImageRecord>;\n remove(ref: string): Promise<void>;\n};\n\ntype CliImageInfo = {\n architecture: string;\n created_at: string;\n digest: string;\n layer_count: number;\n os: string;\n reference: string;\n size_bytes: number;\n};\n\nclass MicrosandboxImageBindings implements ImageBindings {\n private get msb(): string {\n return getMsbPath();\n }\n\n async list(): Promise<ImageRecord[]> {\n const { stdout } = await execAsync(`${this.msb} image ls --format json`);\n const images: CliImageInfo[] = JSON.parse(stdout);\n return images.map((img) => ({\n ref: img.reference,\n sourceType: \"oci\",\n cached: true,\n size: img.size_bytes,\n createdAt: img.created_at,\n }));\n }\n\n async pull(ref: string): Promise<ImageRecord> {\n await execAsync(`${this.msb} image pull ${ref}`);\n return this.inspect(ref);\n }\n\n async inspect(ref: string): Promise<ImageRecord> {\n const { stdout } = await execAsync(`${this.msb} image inspect ${ref} --format json`);\n const img: CliImageInfo = JSON.parse(stdout);\n return {\n ref: img.reference,\n sourceType: \"oci\",\n cached: true,\n size: img.size_bytes,\n createdAt: img.created_at,\n };\n }\n\n async remove(ref: string): Promise<void> {\n await execAsync(`${this.msb} image rm ${ref}`);\n }\n}\n\nexport class ImageService {\n constructor(\n private readonly deps: {\n bindings?: ImageBindings;\n } = {}\n ) {}\n\n private get bindings(): ImageBindings {\n return this.deps.bindings ?? new MicrosandboxImageBindings();\n }\n\n async listImages(): Promise<{ items: ImageRecord[]; total: number }> {\n const items = await this.bindings.list();\n return { items, total: items.length };\n }\n\n async pullImage(input: PullImageInput): Promise<ImageRecord> {\n return await this.bindings.pull(input.ref);\n }\n\n async getImage(ref: string): Promise<ImageRecord> {\n return await this.bindings.inspect(ref);\n }\n\n async deleteImage(ref: string): Promise<{ ref: string }> {\n await this.bindings.remove(ref);\n return { ref };\n }\n}\n","import type { FastifyInstance } from \"fastify\";\nimport swagger from \"@fastify/swagger\";\nimport swaggerUi from \"@fastify/swagger-ui\";\n\nexport const defaultSwaggerConfig = {\n openapi: {\n openapi: \"3.0.0\",\n info: {\n title: \"Microsandbox Service API\",\n description:\n \"Sandbox lifecycle management, file operations, shell execution, and image registry\",\n version: \"1.0.0\",\n },\n servers: [\n {\n url: \"http://localhost:4002\",\n description: \"Local development\",\n },\n ],\n components: {\n securitySchemes: {\n bearerAuth: {\n type: \"http\" as const,\n scheme: \"bearer\" as const,\n bearerFormat: \"API Key\",\n },\n },\n },\n tags: [\n { name: \"Sandboxes\", description: \"Sandbox lifecycle (CRUD, start, stop, kill)\" },\n { name: \"Files\", description: \"Read, write, list, search, upload, download files inside sandboxes\" },\n { name: \"Shell\", description: \"Execute commands inside sandboxes\" },\n { name: \"Images\", description: \"OCI image management (list, pull, inspect, delete)\" },\n { name: \"Volumes\", description: \"Named volume filesystem operations\" },\n { name: \"Health\", description: \"Service health check\" },\n ],\n },\n};\n\nexport const defaultSwaggerUiConfig = {\n routePrefix: \"/api-docs\",\n uiConfig: {\n docExpansion: \"list\" as const,\n deepLinking: true,\n },\n staticCSP: true,\n transformStaticCSP: (header: string) => header,\n};\n\nexport async function configureSwagger(\n app: FastifyInstance,\n customSwaggerConfig?: Partial<typeof defaultSwaggerConfig>,\n customSwaggerUiConfig?: Partial<typeof defaultSwaggerUiConfig>\n) {\n const swaggerConfig = { ...defaultSwaggerConfig, ...customSwaggerConfig };\n const swaggerUiConfig = {\n ...defaultSwaggerUiConfig,\n ...customSwaggerUiConfig,\n };\n\n await app.register(swagger, swaggerConfig);\n await app.register(swaggerUi, swaggerUiConfig);\n}\n"],"mappings":"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","names":["path","fs","Sandbox","path","Sandbox","fs","z","Volume","z","z","Volume","z","exec","promisify","execAsync","promisify","exec"]}