@axiom-lattice/microsandbox-service 0.0.51 → 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 +6 -0
- package/dist/{chunk-OUK4PEG5.mjs → chunk-CT7REZXC.mjs} +2 -2
- package/dist/{chunk-IKWYDXRG.mjs → chunk-I6F4WE2G.mjs} +137 -47
- package/dist/chunk-I6F4WE2G.mjs.map +1 -0
- package/dist/cli.mjs +2 -2
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +1 -1
- package/dist/server.mjs +2 -2
- package/package.json +1 -1
- package/src/services/SandboxRegistry.ts +120 -21
- package/dist/chunk-IKWYDXRG.mjs.map +0 -1
- /package/dist/{chunk-OUK4PEG5.mjs.map → chunk-CT7REZXC.mjs.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildApp
|
|
3
|
-
} from "./chunk-
|
|
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-
|
|
100
|
+
//# sourceMappingURL=chunk-CT7REZXC.mjs.map
|
|
@@ -6,6 +6,9 @@ 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
7
|
var DEFAULT_REMOVE_AFTER_PAUSED_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
8
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;
|
|
9
12
|
var SANDBOX_AGENT_SOCKET_DIR = "/root/.microsandbox/run/agent";
|
|
10
13
|
function extractConfig(configJson) {
|
|
11
14
|
try {
|
|
@@ -37,6 +40,7 @@ var SandboxRegistry = class {
|
|
|
37
40
|
constructor(idleTimeoutMs) {
|
|
38
41
|
this.handles = /* @__PURE__ */ new Map();
|
|
39
42
|
this.creating = /* @__PURE__ */ new Map();
|
|
43
|
+
this.stopping = /* @__PURE__ */ new Set();
|
|
40
44
|
this.idleTimeoutMs = idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
41
45
|
this.cleanupOrphanedSockets();
|
|
42
46
|
if (this.idleTimeoutMs > 0) {
|
|
@@ -48,14 +52,22 @@ var SandboxRegistry = class {
|
|
|
48
52
|
const now = Date.now();
|
|
49
53
|
for (const [name, entry] of this.handles) {
|
|
50
54
|
if (entry.native && now - entry.lastAccessedAt > this.idleTimeoutMs) {
|
|
55
|
+
if (this.stopping.has(name)) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
51
58
|
console.log(`[SandboxRegistry] sweeper pausing idle sandbox name=${name} idleMs=${now - entry.lastAccessedAt}`);
|
|
52
|
-
|
|
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}`);
|
|
56
67
|
}).finally(() => {
|
|
57
68
|
entry.native = null;
|
|
58
69
|
entry.pausedAt = Date.now();
|
|
70
|
+
this.stopping.delete(name);
|
|
59
71
|
});
|
|
60
72
|
} else if (!entry.native && entry.pausedAt && now - entry.pausedAt > DEFAULT_REMOVE_AFTER_PAUSED_MS) {
|
|
61
73
|
console.log(`[SandboxRegistry] sweeper removing paused sandbox name=${name} pausedMs=${now - entry.pausedAt}`);
|
|
@@ -104,15 +116,30 @@ var SandboxRegistry = class {
|
|
|
104
116
|
}
|
|
105
117
|
}
|
|
106
118
|
async removeAndDelete(name) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
+
}
|
|
113
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 {
|
|
114
142
|
}
|
|
115
|
-
await Sandbox.remove(name);
|
|
116
143
|
this.remove(name);
|
|
117
144
|
this.cleanupOrphanedSockets();
|
|
118
145
|
}
|
|
@@ -133,11 +160,26 @@ var SandboxRegistry = class {
|
|
|
133
160
|
entry.native = null;
|
|
134
161
|
entry.pausedAt = Date.now();
|
|
135
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
|
+
}
|
|
174
|
+
}
|
|
136
175
|
async waitForFs(native, maxRetries = 10) {
|
|
137
176
|
const fs2 = native.fs();
|
|
138
177
|
for (let i = 0; i < maxRetries; i++) {
|
|
139
178
|
try {
|
|
140
|
-
await
|
|
179
|
+
await Promise.race([
|
|
180
|
+
fs2.list("/"),
|
|
181
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("FS check timed out")), 5e3))
|
|
182
|
+
]);
|
|
141
183
|
return;
|
|
142
184
|
} catch {
|
|
143
185
|
await new Promise((r) => setTimeout(r, 200));
|
|
@@ -169,10 +211,29 @@ var SandboxRegistry = class {
|
|
|
169
211
|
async ensure(name, createOptions) {
|
|
170
212
|
const tStart = Date.now();
|
|
171
213
|
const cached = this.handles.get(name);
|
|
172
|
-
if (cached?.native) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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;
|
|
176
237
|
}
|
|
177
238
|
if (cached && !cached.native) {
|
|
178
239
|
cached.pausedAt = void 0;
|
|
@@ -191,44 +252,62 @@ var SandboxRegistry = class {
|
|
|
191
252
|
const memoryMib = createOptions?.memoryMib ?? 512;
|
|
192
253
|
const env = createOptions?.env ?? void 0;
|
|
193
254
|
let originalConfig;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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`);
|
|
216
280
|
const tFs = Date.now();
|
|
217
281
|
await this.waitForFs(native);
|
|
218
282
|
console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
|
|
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
|
+
}
|
|
222
300
|
}
|
|
223
301
|
}
|
|
302
|
+
} else if (handle.status === "crashed" || handle.status === "draining") {
|
|
303
|
+
await this.removeAndDelete(name);
|
|
304
|
+
} else {
|
|
305
|
+
await this.removeAndDelete(name);
|
|
224
306
|
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
await this.removeAndDelete(name);
|
|
307
|
+
} catch (err) {
|
|
308
|
+
console.log(`[SandboxRegistry] ensure name=${name} existing_check failed err=${err.message}`);
|
|
309
|
+
native = void 0;
|
|
229
310
|
}
|
|
230
|
-
} catch {
|
|
231
|
-
native = void 0;
|
|
232
311
|
}
|
|
233
312
|
console.log(`[SandboxRegistry] phase=existing_check name=${name} hasNative=${!!native} elapsed=${Date.now() - tCreate}ms`);
|
|
234
313
|
if (!native) {
|
|
@@ -294,7 +373,12 @@ var SandboxRegistry = class {
|
|
|
294
373
|
}
|
|
295
374
|
applyVolumes(builder);
|
|
296
375
|
const tCreateInner = Date.now();
|
|
297
|
-
const result = await
|
|
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
|
+
]);
|
|
298
382
|
console.log(
|
|
299
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"}`
|
|
300
384
|
);
|
|
@@ -316,7 +400,13 @@ var SandboxRegistry = class {
|
|
|
316
400
|
console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);
|
|
317
401
|
}
|
|
318
402
|
const totalElapsed = Date.now() - tStart;
|
|
319
|
-
|
|
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);
|
|
320
410
|
console.log(`[SandboxRegistry] ensure DONE name=${name} total=${totalElapsed}ms idleTimeout=${Math.round(this.idleTimeoutMs / 1e3)}s`);
|
|
321
411
|
return native;
|
|
322
412
|
})();
|
|
@@ -1331,4 +1421,4 @@ export {
|
|
|
1331
1421
|
MicrosandboxRuntimeService,
|
|
1332
1422
|
buildApp
|
|
1333
1423
|
};
|
|
1334
|
-
//# sourceMappingURL=chunk-
|
|
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
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
package/dist/server.mjs
CHANGED
package/package.json
CHANGED
|
@@ -7,9 +7,19 @@ 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
8
|
const DEFAULT_REMOVE_AFTER_PAUSED_MS = 7 * 24 * 60 * 60 * 1000;
|
|
9
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;
|
|
10
13
|
const SANDBOX_AGENT_SOCKET_DIR = "/root/.microsandbox/run/agent";
|
|
11
14
|
|
|
12
|
-
type CacheEntry = {
|
|
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
|
+
};
|
|
13
23
|
|
|
14
24
|
function extractConfig(configJson: string): {
|
|
15
25
|
image: string;
|
|
@@ -48,6 +58,7 @@ function extractConfig(configJson: string): {
|
|
|
48
58
|
export class SandboxRegistry {
|
|
49
59
|
private handles = new Map<string, CacheEntry>();
|
|
50
60
|
private creating = new Map<string, Promise<unknown>>();
|
|
61
|
+
private stopping = new Set<string>();
|
|
51
62
|
private readonly idleTimeoutMs: number;
|
|
52
63
|
private sweepTimer?: ReturnType<typeof setInterval>;
|
|
53
64
|
|
|
@@ -64,14 +75,22 @@ export class SandboxRegistry {
|
|
|
64
75
|
const now = Date.now();
|
|
65
76
|
for (const [name, entry] of this.handles) {
|
|
66
77
|
if (entry.native && now - entry.lastAccessedAt > this.idleTimeoutMs) {
|
|
78
|
+
if (this.stopping.has(name)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
67
81
|
console.log(`[SandboxRegistry] sweeper pausing idle sandbox name=${name} idleMs=${now - entry.lastAccessedAt}`);
|
|
68
|
-
|
|
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}`);
|
|
72
90
|
}).finally(() => {
|
|
73
91
|
entry.native = null;
|
|
74
92
|
entry.pausedAt = Date.now();
|
|
93
|
+
this.stopping.delete(name);
|
|
75
94
|
});
|
|
76
95
|
} else if (!entry.native && entry.pausedAt && now - entry.pausedAt > DEFAULT_REMOVE_AFTER_PAUSED_MS) {
|
|
77
96
|
console.log(`[SandboxRegistry] sweeper removing paused sandbox name=${name} pausedMs=${now - entry.pausedAt}`);
|
|
@@ -124,14 +143,28 @@ export class SandboxRegistry {
|
|
|
124
143
|
}
|
|
125
144
|
|
|
126
145
|
async removeAndDelete(name: string): Promise<void> {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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 */ }
|
|
135
168
|
this.remove(name);
|
|
136
169
|
this.cleanupOrphanedSockets();
|
|
137
170
|
}
|
|
@@ -153,11 +186,27 @@ export class SandboxRegistry {
|
|
|
153
186
|
entry.pausedAt = Date.now();
|
|
154
187
|
}
|
|
155
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
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
156
202
|
private async waitForFs(native: unknown, maxRetries = 10): Promise<void> {
|
|
157
203
|
const fs = (native as { fs(): { list(path: string): Promise<unknown> } }).fs();
|
|
158
204
|
for (let i = 0; i < maxRetries; i++) {
|
|
159
205
|
try {
|
|
160
|
-
await
|
|
206
|
+
await Promise.race([
|
|
207
|
+
fs.list("/"),
|
|
208
|
+
new Promise<never>((_, reject) => setTimeout(() => reject(new Error("FS check timed out")), 5000)),
|
|
209
|
+
]);
|
|
161
210
|
return;
|
|
162
211
|
} catch {
|
|
163
212
|
await new Promise((r) => setTimeout(r, 200));
|
|
@@ -199,10 +248,31 @@ export class SandboxRegistry {
|
|
|
199
248
|
const tStart = Date.now();
|
|
200
249
|
|
|
201
250
|
const cached = this.handles.get(name);
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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;
|
|
206
276
|
}
|
|
207
277
|
|
|
208
278
|
if (cached && !cached.native) {
|
|
@@ -226,7 +296,13 @@ export class SandboxRegistry {
|
|
|
226
296
|
|
|
227
297
|
let originalConfig: ReturnType<typeof extractConfig>;
|
|
228
298
|
|
|
229
|
-
|
|
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 {
|
|
230
306
|
const tGet = Date.now();
|
|
231
307
|
const handle: SandboxHandle = await Sandbox.get(name);
|
|
232
308
|
console.log(`[SandboxRegistry] Sandbox.get name=${name} status=${handle.status} elapsed=${Date.now() - tGet}ms`);
|
|
@@ -240,7 +316,12 @@ export class SandboxRegistry {
|
|
|
240
316
|
native = undefined;
|
|
241
317
|
} else if (handle.status === "running") {
|
|
242
318
|
const tConnect = Date.now();
|
|
243
|
-
native = await
|
|
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
|
+
]);
|
|
244
325
|
console.log(`[SandboxRegistry] handle.connect name=${name} elapsed=${Date.now() - tConnect}ms`);
|
|
245
326
|
const tFs = Date.now();
|
|
246
327
|
await this.waitForFs(native);
|
|
@@ -248,7 +329,12 @@ export class SandboxRegistry {
|
|
|
248
329
|
} else {
|
|
249
330
|
try {
|
|
250
331
|
const tStart2 = Date.now();
|
|
251
|
-
native = await
|
|
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
|
+
]);
|
|
252
338
|
console.log(`[SandboxRegistry] startDetached name=${name} elapsed=${Date.now() - tStart2}ms`);
|
|
253
339
|
const tFs = Date.now();
|
|
254
340
|
await this.waitForFs(native);
|
|
@@ -264,9 +350,11 @@ export class SandboxRegistry {
|
|
|
264
350
|
} else {
|
|
265
351
|
await this.removeAndDelete(name);
|
|
266
352
|
}
|
|
267
|
-
} catch {
|
|
353
|
+
} catch (err) {
|
|
354
|
+
console.log(`[SandboxRegistry] ensure name=${name} existing_check failed err=${(err as Error).message}`);
|
|
268
355
|
native = undefined;
|
|
269
356
|
}
|
|
357
|
+
}
|
|
270
358
|
console.log(`[SandboxRegistry] phase=existing_check name=${name} hasNative=${!!native} elapsed=${Date.now() - tCreate}ms`);
|
|
271
359
|
|
|
272
360
|
if (!native) {
|
|
@@ -339,7 +427,12 @@ export class SandboxRegistry {
|
|
|
339
427
|
}
|
|
340
428
|
applyVolumes(builder);
|
|
341
429
|
const tCreateInner = Date.now();
|
|
342
|
-
const result = await
|
|
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
|
+
]);
|
|
343
436
|
console.log(
|
|
344
437
|
`[SandboxRegistry] builder.create name=${name} image=${resolvedImage} ` +
|
|
345
438
|
`elapsed=${Date.now() - tCreateInner}ms ` +
|
|
@@ -365,7 +458,13 @@ export class SandboxRegistry {
|
|
|
365
458
|
}
|
|
366
459
|
|
|
367
460
|
const totalElapsed = Date.now() - tStart;
|
|
368
|
-
|
|
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);
|
|
369
468
|
console.log(`[SandboxRegistry] ensure DONE name=${name} total=${totalElapsed}ms idleTimeout=${Math.round(this.idleTimeoutMs / 1000)}s`);
|
|
370
469
|
return native;
|
|
371
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 DEFAULT_REMOVE_AFTER_PAUSED_MS = 7 * 24 * 60 * 60 * 1000;\nconst SWEEP_INTERVAL_MS = 30_000;\nconst SANDBOX_AGENT_SOCKET_DIR = \"/root/.microsandbox/run/agent\";\n\ntype CacheEntry = { native: unknown | null; lastAccessedAt: number; pausedAt?: 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 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 });\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 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 } catch { /* ignore */ }\n }\n entry.native = null;\n entry.pausedAt = Date.now();\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 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 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"]}
|
|
File without changes
|