@hotcell/daemon 0.1.0

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.
Files changed (142) hide show
  1. package/dist/agent-check.d.ts +1 -0
  2. package/dist/agent-check.js +105 -0
  3. package/dist/agent-check.js.map +1 -0
  4. package/dist/api/server.d.ts +64 -0
  5. package/dist/api/server.js +1368 -0
  6. package/dist/api/server.js.map +1 -0
  7. package/dist/api/ws.d.ts +14 -0
  8. package/dist/api/ws.js +214 -0
  9. package/dist/api/ws.js.map +1 -0
  10. package/dist/applevz-check.d.ts +1 -0
  11. package/dist/applevz-check.js +280 -0
  12. package/dist/applevz-check.js.map +1 -0
  13. package/dist/backups.d.ts +29 -0
  14. package/dist/backups.js +76 -0
  15. package/dist/backups.js.map +1 -0
  16. package/dist/capacity.d.ts +63 -0
  17. package/dist/capacity.js +95 -0
  18. package/dist/capacity.js.map +1 -0
  19. package/dist/config.d.ts +241 -0
  20. package/dist/config.js +152 -0
  21. package/dist/config.js.map +1 -0
  22. package/dist/cost.d.ts +9 -0
  23. package/dist/cost.js +19 -0
  24. package/dist/cost.js.map +1 -0
  25. package/dist/density-bench.d.ts +1 -0
  26. package/dist/density-bench.js +97 -0
  27. package/dist/density-bench.js.map +1 -0
  28. package/dist/driver/agent-driver.d.ts +67 -0
  29. package/dist/driver/agent-driver.js +197 -0
  30. package/dist/driver/agent-driver.js.map +1 -0
  31. package/dist/driver/agent.d.ts +94 -0
  32. package/dist/driver/agent.js +319 -0
  33. package/dist/driver/agent.js.map +1 -0
  34. package/dist/driver/applevz.d.ts +95 -0
  35. package/dist/driver/applevz.js +527 -0
  36. package/dist/driver/applevz.js.map +1 -0
  37. package/dist/driver/container.d.ts +99 -0
  38. package/dist/driver/container.js +733 -0
  39. package/dist/driver/container.js.map +1 -0
  40. package/dist/driver/fc-api.d.ts +85 -0
  41. package/dist/driver/fc-api.js +173 -0
  42. package/dist/driver/fc-api.js.map +1 -0
  43. package/dist/driver/firecracker.d.ts +126 -0
  44. package/dist/driver/firecracker.js +560 -0
  45. package/dist/driver/firecracker.js.map +1 -0
  46. package/dist/driver/index.d.ts +17 -0
  47. package/dist/driver/index.js +61 -0
  48. package/dist/driver/index.js.map +1 -0
  49. package/dist/driver/router.d.ts +82 -0
  50. package/dist/driver/router.js +159 -0
  51. package/dist/driver/router.js.map +1 -0
  52. package/dist/driver/types.d.ts +234 -0
  53. package/dist/driver/types.js +2 -0
  54. package/dist/driver/types.js.map +1 -0
  55. package/dist/driver/unsupported.d.ts +50 -0
  56. package/dist/driver/unsupported.js +81 -0
  57. package/dist/driver/unsupported.js.map +1 -0
  58. package/dist/driver/vz-image.d.ts +35 -0
  59. package/dist/driver/vz-image.js +75 -0
  60. package/dist/driver/vz-image.js.map +1 -0
  61. package/dist/e2e-harness.d.ts +1 -0
  62. package/dist/e2e-harness.js +99 -0
  63. package/dist/e2e-harness.js.map +1 -0
  64. package/dist/egress-check.d.ts +8 -0
  65. package/dist/egress-check.js +317 -0
  66. package/dist/egress-check.js.map +1 -0
  67. package/dist/fc-check.d.ts +1 -0
  68. package/dist/fc-check.js +113 -0
  69. package/dist/fc-check.js.map +1 -0
  70. package/dist/index.d.ts +2 -0
  71. package/dist/index.js +114 -0
  72. package/dist/index.js.map +1 -0
  73. package/dist/kernels.d.ts +22 -0
  74. package/dist/kernels.js +134 -0
  75. package/dist/kernels.js.map +1 -0
  76. package/dist/lifecycle.d.ts +49 -0
  77. package/dist/lifecycle.js +111 -0
  78. package/dist/lifecycle.js.map +1 -0
  79. package/dist/logger.d.ts +16 -0
  80. package/dist/logger.js +67 -0
  81. package/dist/logger.js.map +1 -0
  82. package/dist/metrics.d.ts +46 -0
  83. package/dist/metrics.js +92 -0
  84. package/dist/metrics.js.map +1 -0
  85. package/dist/net/firewall.d.ts +4 -0
  86. package/dist/net/firewall.js +80 -0
  87. package/dist/net/firewall.js.map +1 -0
  88. package/dist/pricing.d.ts +36 -0
  89. package/dist/pricing.js +81 -0
  90. package/dist/pricing.js.map +1 -0
  91. package/dist/proxy/allowlist-default.d.ts +23 -0
  92. package/dist/proxy/allowlist-default.js +53 -0
  93. package/dist/proxy/allowlist-default.js.map +1 -0
  94. package/dist/proxy/allowlist.d.ts +43 -0
  95. package/dist/proxy/allowlist.js +87 -0
  96. package/dist/proxy/allowlist.js.map +1 -0
  97. package/dist/proxy/egress.d.ts +49 -0
  98. package/dist/proxy/egress.js +599 -0
  99. package/dist/proxy/egress.js.map +1 -0
  100. package/dist/proxy/ratelimit.d.ts +49 -0
  101. package/dist/proxy/ratelimit.js +74 -0
  102. package/dist/proxy/ratelimit.js.map +1 -0
  103. package/dist/proxy/server.d.ts +26 -0
  104. package/dist/proxy/server.js +202 -0
  105. package/dist/proxy/server.js.map +1 -0
  106. package/dist/router-check.d.ts +1 -0
  107. package/dist/router-check.js +97 -0
  108. package/dist/router-check.js.map +1 -0
  109. package/dist/smoke-fc.d.ts +1 -0
  110. package/dist/smoke-fc.js +183 -0
  111. package/dist/smoke-fc.js.map +1 -0
  112. package/dist/smoke-microvm.d.ts +1 -0
  113. package/dist/smoke-microvm.js +187 -0
  114. package/dist/smoke-microvm.js.map +1 -0
  115. package/dist/smoke-remote.d.ts +20 -0
  116. package/dist/smoke-remote.js +155 -0
  117. package/dist/smoke-remote.js.map +1 -0
  118. package/dist/smoke-vz.d.ts +1 -0
  119. package/dist/smoke-vz.js +161 -0
  120. package/dist/smoke-vz.js.map +1 -0
  121. package/dist/smoke.d.ts +7 -0
  122. package/dist/smoke.js +962 -0
  123. package/dist/smoke.js.map +1 -0
  124. package/dist/store.d.ts +124 -0
  125. package/dist/store.js +578 -0
  126. package/dist/store.js.map +1 -0
  127. package/dist/tracing.d.ts +45 -0
  128. package/dist/tracing.js +144 -0
  129. package/dist/tracing.js.map +1 -0
  130. package/dist/types.d.ts +274 -0
  131. package/dist/types.js +3 -0
  132. package/dist/types.js.map +1 -0
  133. package/dist/util.d.ts +27 -0
  134. package/dist/util.js +63 -0
  135. package/dist/util.js.map +1 -0
  136. package/dist/warmpool-check.d.ts +1 -0
  137. package/dist/warmpool-check.js +83 -0
  138. package/dist/warmpool-check.js.map +1 -0
  139. package/dist/web/dashboard.d.ts +1 -0
  140. package/dist/web/dashboard.js +456 -0
  141. package/dist/web/dashboard.js.map +1 -0
  142. package/package.json +53 -0
@@ -0,0 +1,144 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { log } from "./logger.js";
3
+ let cfg = { serviceName: "sbd", otlpEndpoint: "", ringSize: 200 };
4
+ const ring = [];
5
+ let exportQueue = [];
6
+ let flushTimer;
7
+ export function configureTracing(opts) {
8
+ cfg = { ...cfg, ...opts };
9
+ if (cfg.otlpEndpoint && !flushTimer) {
10
+ flushTimer = setInterval(() => void flush(), 5000);
11
+ flushTimer.unref?.();
12
+ }
13
+ }
14
+ /** Stop the background OTLP flusher (call on daemon shutdown). */
15
+ export function stopTracing() {
16
+ if (flushTimer) {
17
+ clearInterval(flushTimer);
18
+ flushTimer = undefined;
19
+ }
20
+ }
21
+ /** Recent finished spans, newest first. */
22
+ export function recentSpans() {
23
+ return [...ring].reverse();
24
+ }
25
+ class ActiveSpan {
26
+ traceId;
27
+ spanId;
28
+ parentId;
29
+ name;
30
+ startWallMs;
31
+ startHr;
32
+ attributes;
33
+ status = "unset";
34
+ ended = false;
35
+ constructor(name, attributes, parent) {
36
+ this.name = name;
37
+ this.attributes = attributes;
38
+ this.traceId = parent?.traceId ?? randomBytes(16).toString("hex");
39
+ this.spanId = randomBytes(8).toString("hex");
40
+ this.parentId = parent?.spanId;
41
+ this.startWallMs = Date.now();
42
+ this.startHr = process.hrtime.bigint();
43
+ }
44
+ setAttribute(key, value) {
45
+ this.attributes[key] = value;
46
+ return this;
47
+ }
48
+ setStatus(status) {
49
+ this.status = status;
50
+ return this;
51
+ }
52
+ end() {
53
+ if (this.ended)
54
+ return;
55
+ this.ended = true;
56
+ const elapsedNs = process.hrtime.bigint() - this.startHr;
57
+ const startUnixNano = BigInt(this.startWallMs) * 1000000n;
58
+ const endUnixNano = startUnixNano + elapsedNs;
59
+ const data = {
60
+ traceId: this.traceId,
61
+ spanId: this.spanId,
62
+ parentId: this.parentId,
63
+ name: this.name,
64
+ startUnixNano: startUnixNano.toString(),
65
+ endUnixNano: endUnixNano.toString(),
66
+ durationMs: Number(elapsedNs) / 1e6,
67
+ attributes: this.attributes,
68
+ status: this.status === "unset" ? "ok" : this.status,
69
+ };
70
+ push(data);
71
+ }
72
+ }
73
+ /** Begin a span. Pass `parent` to nest it within an existing trace. */
74
+ export function startSpan(name, attributes = {}, parent) {
75
+ return new ActiveSpan(name, attributes, parent);
76
+ }
77
+ function push(data) {
78
+ ring.push(data);
79
+ while (ring.length > cfg.ringSize)
80
+ ring.shift();
81
+ if (cfg.otlpEndpoint)
82
+ exportQueue.push(data);
83
+ }
84
+ async function flush() {
85
+ if (exportQueue.length === 0 || !cfg.otlpEndpoint)
86
+ return;
87
+ const batch = exportQueue;
88
+ exportQueue = [];
89
+ try {
90
+ const res = await fetch(`${cfg.otlpEndpoint}/v1/traces`, {
91
+ method: "POST",
92
+ headers: { "content-type": "application/json" },
93
+ body: JSON.stringify(toOtlp(batch, cfg.serviceName)),
94
+ });
95
+ if (!res.ok)
96
+ throw new Error(`status ${res.status}`);
97
+ }
98
+ catch (err) {
99
+ // Best-effort: drop this batch but keep the daemon healthy.
100
+ log.warn("otlp export failed", { error: String(err), spans: batch.length });
101
+ }
102
+ }
103
+ /** Build an OTLP/JSON ExportTraceServiceRequest from a batch of spans. */
104
+ function toOtlp(spans, serviceName) {
105
+ return {
106
+ resourceSpans: [
107
+ {
108
+ resource: {
109
+ attributes: [
110
+ { key: "service.name", value: { stringValue: serviceName } },
111
+ ],
112
+ },
113
+ scopeSpans: [
114
+ {
115
+ scope: { name: "hotcell", version: "0.1.0" },
116
+ spans: spans.map((s) => ({
117
+ traceId: s.traceId,
118
+ spanId: s.spanId,
119
+ parentSpanId: s.parentId,
120
+ name: s.name,
121
+ kind: 2, // SERVER
122
+ startTimeUnixNano: s.startUnixNano,
123
+ endTimeUnixNano: s.endUnixNano,
124
+ attributes: Object.entries(s.attributes).map(([key, value]) => ({
125
+ key,
126
+ value: otlpValue(value),
127
+ })),
128
+ status: { code: s.status === "error" ? 2 : 1 },
129
+ })),
130
+ },
131
+ ],
132
+ },
133
+ ],
134
+ };
135
+ }
136
+ function otlpValue(value) {
137
+ if (typeof value === "boolean")
138
+ return { boolValue: value };
139
+ if (typeof value === "number") {
140
+ return Number.isInteger(value) ? { intValue: value } : { doubleValue: value };
141
+ }
142
+ return { stringValue: value };
143
+ }
144
+ //# sourceMappingURL=tracing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracing.js","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,274 @@
1
+ /**
2
+ * Lifecycle states. `running` and `stopped` are explicit (user-driven via
3
+ * start/stop); `paused` is auto-entered by the idle reaper after `sleepAfterMs`
4
+ * of inactivity and auto-resumes on the next operation. A `stopped` sandbox is
5
+ * left alone by the reaper and does *not* auto-resume — the user must `start` it.
6
+ */
7
+ export type SandboxStatus = "running" | "paused" | "stopped";
8
+ /**
9
+ * Hard per-sandbox resource caps, enforced by the driver (cgroups via Docker).
10
+ * Each field `0`/undefined means "unlimited" (omitted from the container config).
11
+ * Units stay ergonomic for callers; the driver translates to its backend.
12
+ */
13
+ export interface ResourceLimits {
14
+ /** Memory cap in MiB. */
15
+ memoryMb?: number;
16
+ /** CPU cap in fractional cores (e.g. 0.5 = half a core, 2 = two cores). */
17
+ cpus?: number;
18
+ /** Max number of processes/threads (fork-bomb guard). */
19
+ pidsLimit?: number;
20
+ }
21
+ export interface SandboxRecord {
22
+ id: string;
23
+ image: string;
24
+ status: SandboxStatus;
25
+ createdAt: string;
26
+ /**
27
+ * Runtime driver backing this sandbox (`container` | `applevz` | `firecracker`).
28
+ * Set at create time (per-sandbox isolation selection); the daemon routes every
29
+ * op to this driver. Empty/undefined falls back to the daemon default driver.
30
+ */
31
+ driver?: string;
32
+ labels: Record<string, string>;
33
+ /**
34
+ * Sandbox-level environment variables, merged into every `exec`/`startProcess`
35
+ * in this sandbox. Seeded from the create call's `env` and mutated by
36
+ * `setEnvVars`. Request- and session-level env take precedence over these.
37
+ */
38
+ env: Record<string, string>;
39
+ /**
40
+ * Whether `/workspace` is backed by a named volume that survives `stop`/`start`
41
+ * and container recreation. Set at create time; defaults to true.
42
+ */
43
+ persist: boolean;
44
+ /**
45
+ * ISO timestamp of the last operation that ran work in the sandbox (exec, file
46
+ * op, run-code, proxy traffic, …). Drives idle detection. Refreshed by the
47
+ * store's `touch`.
48
+ */
49
+ lastActivityAt: string;
50
+ /**
51
+ * Auto-pause the sandbox after this many milliseconds of inactivity (the idle
52
+ * reaper transitions `running → paused`, freeing compute while the workspace
53
+ * volume persists). `0` disables auto-pause. Set at create time.
54
+ */
55
+ sleepAfterMs: number;
56
+ /** Resolved hard resource caps (per-create override merged over daemon defaults). */
57
+ limits: ResourceLimits;
58
+ /**
59
+ * Hard ceiling (USD) on this sandbox's cumulative LLM-provider cost across ALL
60
+ * its egress tokens — the gateway returns 402 once `usage.providerCost` reaches
61
+ * it, regardless of per-token caps. `0`/undefined = unlimited. A blast-radius
62
+ * backstop: even an abused, not-yet-revoked token can't exceed it.
63
+ */
64
+ egressSpendCapUsd?: number;
65
+ /** Cumulative resource usage, integrated by the metrics sampler. */
66
+ usage: SandboxUsage;
67
+ }
68
+ /**
69
+ * Cumulative, time-integrated resource usage for a sandbox — the basis of the
70
+ * cost meter. Accumulated by the metrics sampler and persisted, so totals carry
71
+ * across daemon restarts. The two `last*` fields are sampler bookkeeping.
72
+ */
73
+ export interface SandboxUsage {
74
+ /** Total vCPU-seconds consumed (Σ of cumulative-CPU-ns deltas / 1e9). */
75
+ cpuSeconds: number;
76
+ /** Total memory byte-seconds (Σ of memBytes × seconds-since-last-sample). */
77
+ memByteSeconds: number;
78
+ /** Total bytes the sandbox has sent out through the preview proxy. */
79
+ egressBytes: number;
80
+ /** Number of LLM-provider calls made through the egress credential proxy. */
81
+ providerCalls: number;
82
+ /** Total bytes exchanged with providers through the egress proxy (both ways). */
83
+ providerBytes: number;
84
+ /** Prompt/input tokens billed across provider calls (parsed from responses). */
85
+ providerTokensIn: number;
86
+ /** Completion/output tokens billed across provider calls. */
87
+ providerTokensOut: number;
88
+ /** Provider-reported LLM cost in USD (e.g. OpenRouter's `usage.cost`), summed across calls. */
89
+ providerCost: number;
90
+ /** Last observed cumulative CPU ns, to compute the next delta (reset-safe). */
91
+ lastCpuTotalNs: number;
92
+ /** ISO timestamp of the last sample, to integrate memory over wall-clock. */
93
+ lastSampledAt: string;
94
+ }
95
+ /**
96
+ * Per-token egress policy. Every field is optional; an empty policy (`{}`) means
97
+ * "unlimited" — the original, pre-policy behaviour. Enforced by the egress
98
+ * gateway on the LLM hot path (see `proxy/egress.ts`).
99
+ */
100
+ export interface EgressPolicy {
101
+ /** ISO timestamp after which the token is rejected with 403. Omit = never expires. */
102
+ expiresAt?: string;
103
+ /** Cumulative USD this token may spend across provider calls; 402 once reached. */
104
+ spendCapUsd?: number;
105
+ /** Sliding-window rate limit (per token). Omit = unlimited. */
106
+ rateLimit?: {
107
+ /** Max provider calls per window. */
108
+ calls?: number;
109
+ /** Max billed tokens (in+out) per window. */
110
+ tokens?: number;
111
+ /** Window length in milliseconds. */
112
+ windowMs: number;
113
+ };
114
+ /** Allowed model ids/prefix-globs (matched against the request's `model`). Omit = all. */
115
+ models?: string[];
116
+ /** Allowed provider names (e.g. `openai`). Omit = every configured provider. */
117
+ providers?: string[];
118
+ }
119
+ /**
120
+ * A minted egress token bound to a sandbox, with its policy and running spend.
121
+ * The store keeps these in an O(1) `Map<token, EgressTokenRecord>` so the gateway
122
+ * resolves token → sandbox + policy in one lookup on every provider call.
123
+ */
124
+ export interface EgressTokenRecord {
125
+ token: string;
126
+ sandboxId: string;
127
+ policy: EgressPolicy;
128
+ createdAt: string;
129
+ /** Cumulative USD spent through this token (drives the spend cap). */
130
+ spendUsd: number;
131
+ }
132
+ /** Per-resource cost breakdown in the configured currency. */
133
+ export interface CostBreakdown {
134
+ cpu: number;
135
+ mem: number;
136
+ egress: number;
137
+ /** LLM cost (provider-reported, e.g. OpenRouter `usage.cost`). */
138
+ provider: number;
139
+ total: number;
140
+ }
141
+ /**
142
+ * A persistent execution context inside a sandbox. Holds a working directory
143
+ * (which follows `cd` across commands) and its own environment overlay, so a
144
+ * sequence of `exec`s behaves like one shell session. Built on top of the
145
+ * driver's stateless `exec`/`readFile` — no driver support required.
146
+ */
147
+ export interface SessionInfo {
148
+ sessionId: string;
149
+ /** Working directory for the next command; updated after each exec. */
150
+ cwd: string;
151
+ /** Session-level env, layered over the sandbox env. */
152
+ env: Record<string, string>;
153
+ createdAt: string;
154
+ }
155
+ export interface ExecOptions {
156
+ cwd?: string;
157
+ env?: Record<string, string>;
158
+ }
159
+ /** A single event in a streaming command execution. */
160
+ export type ExecEvent = {
161
+ type: "stdout";
162
+ data: string;
163
+ } | {
164
+ type: "stderr";
165
+ data: string;
166
+ } | {
167
+ type: "exit";
168
+ exitCode: number;
169
+ };
170
+ /** Metadata returned for a file or directory entry. */
171
+ export interface FileInfo {
172
+ path: string;
173
+ name: string;
174
+ isDirectory: boolean;
175
+ size: number;
176
+ modifiedAt: string;
177
+ }
178
+ /** Options for writing a file inside a sandbox. */
179
+ export interface WriteFileOptions {
180
+ path: string;
181
+ content: string;
182
+ mode?: string;
183
+ }
184
+ /** Options for reading a file from a sandbox. */
185
+ export interface ReadFileOptions {
186
+ path: string;
187
+ }
188
+ /** Options for creating a directory inside a sandbox. */
189
+ export interface MkdirOptions {
190
+ path: string;
191
+ parents?: boolean;
192
+ }
193
+ /** Options for listing files inside a sandbox. */
194
+ export interface ListFilesOptions {
195
+ path: string;
196
+ }
197
+ /** Options for launching a long-running background process. */
198
+ export interface StartProcessOptions {
199
+ cwd?: string;
200
+ env?: Record<string, string>;
201
+ }
202
+ /** A long-running background process tracked by the daemon. */
203
+ export interface ProcessInfo {
204
+ /** Daemon-assigned handle (stable across PID reuse). */
205
+ procId: string;
206
+ /** In-container PID of the detached process. */
207
+ pid: number;
208
+ command: string;
209
+ status: "running" | "exited";
210
+ exitCode: number | null;
211
+ startedAt: string;
212
+ /** Path of the process logfile inside the sandbox. */
213
+ logPath: string;
214
+ }
215
+ /**
216
+ * A persistent code-interpreter context. Backed by a long-lived kernel process
217
+ * inside the sandbox that keeps a namespace across `runCode` calls (variables
218
+ * and imports persist, Jupyter-style).
219
+ */
220
+ export interface CodeContextInfo {
221
+ contextId: string;
222
+ language: "python" | "javascript";
223
+ /** Context directory inside the sandbox (holds the kernel + its fifos). */
224
+ dir: string;
225
+ /** procId of the kernel background process (so it can be killed on cleanup). */
226
+ procId: string;
227
+ /** In-container PID of the kernel (target for the kill on cleanup). */
228
+ pid: number;
229
+ /** Monotonic cell counter, incremented per `runCode`. */
230
+ seq: number;
231
+ createdAt: string;
232
+ }
233
+ /** A single rich output from a code cell. */
234
+ export interface CodeOutput {
235
+ type: "text";
236
+ text: string;
237
+ }
238
+ /** The result of running a code cell. */
239
+ export interface CodeResult {
240
+ stdout: string;
241
+ stderr: string;
242
+ /** Rich outputs (e.g. the value of a trailing expression). */
243
+ results: CodeOutput[];
244
+ /** Formatted traceback/stack if the cell raised, else null. */
245
+ error: string | null;
246
+ }
247
+ /** A filesystem change observed by `watch`. */
248
+ export interface FileChangeEvent {
249
+ type: "created" | "modified" | "deleted";
250
+ path: string;
251
+ }
252
+ /** Options for watching a path for changes. */
253
+ export interface WatchOptions {
254
+ /** Poll interval in milliseconds (default 1000). */
255
+ intervalMs?: number;
256
+ }
257
+ /** Options for waiting until a TCP port is listening inside a sandbox. */
258
+ export interface WaitForPortOptions {
259
+ timeoutMs?: number;
260
+ intervalMs?: number;
261
+ host?: string;
262
+ }
263
+ /** A port exposed through the daemon's preview-URL reverse proxy. */
264
+ export interface ExposedPort {
265
+ /** In-container port the app listens on. */
266
+ port: number;
267
+ /** Routing label / subdomain (`<sandboxId>-<port>`). */
268
+ exposeId: string;
269
+ /** Optional per-port bearer token; null means open on loopback. */
270
+ token: string | null;
271
+ createdAt: string;
272
+ /** Computed preview URL. */
273
+ url: string;
274
+ }
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ // Shared daemon types.
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,uBAAuB"}
package/dist/util.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ import type { ServerResponse } from "node:http";
2
+ /** Normalize any thrown value to a message string. */
3
+ export declare function errorMessage(err: unknown): string;
4
+ /** Single-quote a value for safe interpolation into a shell command. */
5
+ export declare function shellEscape(value: string): string;
6
+ /** Thrown when a request body exceeds the configured cap (→ HTTP 413). */
7
+ export declare class BodyTooLargeError extends Error {
8
+ constructor();
9
+ }
10
+ /**
11
+ * Read a request body fully into a Buffer, aborting with `BodyTooLargeError`
12
+ * once it would exceed `maxBytes`. Shared by the REST API and egress gateway so
13
+ * neither can be made to buffer unbounded memory from one request.
14
+ */
15
+ export declare function readBodyCapped(req: {
16
+ [Symbol.asyncIterator](): AsyncIterator<unknown>;
17
+ }, maxBytes: number): Promise<Buffer>;
18
+ /**
19
+ * Constant-time string equality for secrets (API keys, preview tokens). Avoids
20
+ * the early-exit timing leak of `===`. The length comparison is intentional and
21
+ * standard — `timingSafeEqual` requires equal-length buffers.
22
+ */
23
+ export declare function safeEqual(a: string, b: string): boolean;
24
+ /** Send a JSON response with the correct Content-Length. */
25
+ export declare function sendJson(res: ServerResponse, status: number, body: unknown): void;
26
+ /** Send a `text/plain` response (one trailing newline) with Content-Length. */
27
+ export declare function sendText(res: ServerResponse, status: number, message: string): void;
package/dist/util.js ADDED
@@ -0,0 +1,63 @@
1
+ import { timingSafeEqual } from "node:crypto";
2
+ /** Normalize any thrown value to a message string. */
3
+ export function errorMessage(err) {
4
+ return err instanceof Error ? err.message : String(err);
5
+ }
6
+ /** Single-quote a value for safe interpolation into a shell command. */
7
+ export function shellEscape(value) {
8
+ return `'${value.replace(/'/g, "'\"'\"'")}'`;
9
+ }
10
+ /** Thrown when a request body exceeds the configured cap (→ HTTP 413). */
11
+ export class BodyTooLargeError extends Error {
12
+ constructor() {
13
+ super("request body too large");
14
+ this.name = "BodyTooLargeError";
15
+ }
16
+ }
17
+ /**
18
+ * Read a request body fully into a Buffer, aborting with `BodyTooLargeError`
19
+ * once it would exceed `maxBytes`. Shared by the REST API and egress gateway so
20
+ * neither can be made to buffer unbounded memory from one request.
21
+ */
22
+ export async function readBodyCapped(req, maxBytes) {
23
+ const chunks = [];
24
+ let total = 0;
25
+ for await (const chunk of req) {
26
+ total += chunk.length;
27
+ if (total > maxBytes)
28
+ throw new BodyTooLargeError();
29
+ chunks.push(chunk);
30
+ }
31
+ return Buffer.concat(chunks);
32
+ }
33
+ /**
34
+ * Constant-time string equality for secrets (API keys, preview tokens). Avoids
35
+ * the early-exit timing leak of `===`. The length comparison is intentional and
36
+ * standard — `timingSafeEqual` requires equal-length buffers.
37
+ */
38
+ export function safeEqual(a, b) {
39
+ const ab = Buffer.from(a, "utf8");
40
+ const bb = Buffer.from(b, "utf8");
41
+ if (ab.length !== bb.length)
42
+ return false;
43
+ return timingSafeEqual(ab, bb);
44
+ }
45
+ /** Send a JSON response with the correct Content-Length. */
46
+ export function sendJson(res, status, body) {
47
+ const payload = JSON.stringify(body);
48
+ res.writeHead(status, {
49
+ "Content-Type": "application/json",
50
+ "Content-Length": Buffer.byteLength(payload),
51
+ });
52
+ res.end(payload);
53
+ }
54
+ /** Send a `text/plain` response (one trailing newline) with Content-Length. */
55
+ export function sendText(res, status, message) {
56
+ const body = message + "\n";
57
+ res.writeHead(status, {
58
+ "Content-Type": "text/plain; charset=utf-8",
59
+ "Content-Length": Buffer.byteLength(body),
60
+ });
61
+ res.end(body);
62
+ }
63
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,sDAAsD;AACtD,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC;AAC/C,CAAC;AAED,0EAA0E;AAC1E,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C;QACE,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAyD,EACzD,QAAgB;IAEhB,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAA4B,EAAE,CAAC;QACvD,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC;QACtB,IAAI,KAAK,GAAG,QAAQ;YAAE,MAAM,IAAI,iBAAiB,EAAE,CAAC;QACpD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,CAAS,EAAE,CAAS;IAC5C,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,CAAC,MAAM,KAAK,EAAE,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1C,OAAO,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,QAAQ,CAAC,GAAmB,EAAE,MAAc,EAAE,IAAa;IACzE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACrC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE;QACpB,cAAc,EAAE,kBAAkB;QAClC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;KAC7C,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,QAAQ,CAAC,GAAmB,EAAE,MAAc,EAAE,OAAe;IAC3E,MAAM,IAAI,GAAG,OAAO,GAAG,IAAI,CAAC;IAC5B,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE;QACpB,cAAc,EAAE,2BAA2B;QAC3C,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;KAC1C,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Apple VZ warm-pool (M7b) check. Proves a pre-booted spare microVM is adopted
3
+ * on create — an instant acquire — versus a full cold boot, and that the adopted
4
+ * sandbox is fully functional with an isolated workspace that survives stop/start.
5
+ * Run on a Mac with the VZ artifacts built: `npm run check:warmpool`.
6
+ */
7
+ import assert from "node:assert/strict";
8
+ import { mkdtempSync, rmSync } from "node:fs";
9
+ import { homedir, tmpdir } from "node:os";
10
+ import { join } from "node:path";
11
+ import { setTimeout as sleep } from "node:timers/promises";
12
+ import { AppleVzDriver } from "./driver/applevz.js";
13
+ async function main() {
14
+ const stateDir = mkdtempSync(join(tmpdir(), "hotcell-warmpool-"));
15
+ const driver = new AppleVzDriver({
16
+ helperPath: "helpers/hotcell-vz/dist/hotcell-vz",
17
+ kernel: "helpers/hotcell-vz/guest/vmlinux-vz",
18
+ rootfs: "helpers/hotcell-vz/guest/rootfs.img",
19
+ stateDir,
20
+ diskGb: 2,
21
+ imageCacheDir: join(homedir(), ".sbx", "vz", "images"),
22
+ warmPool: 1, // keep one spare base guest pre-booted
23
+ });
24
+ let passed = 0;
25
+ const ok = (l) => {
26
+ passed++;
27
+ console.log(` ✓ ${l}`);
28
+ };
29
+ try {
30
+ // Wait for the background filler to pre-boot the spare.
31
+ const deadline = Date.now() + 40_000;
32
+ while (driver.poolSize() < 1 && Date.now() < deadline)
33
+ await sleep(200);
34
+ assert.ok(driver.poolSize() >= 1, "warm pool failed to pre-boot a spare");
35
+ ok(`warm pool pre-booted ${driver.poolSize()} spare guest`);
36
+ // Warm acquire: create a base sandbox — should adopt the spare (instant).
37
+ const warmId = "warm01";
38
+ const t0 = Date.now();
39
+ await driver.create({ id: warmId, image: "base", persist: true });
40
+ const warmMs = Date.now() - t0;
41
+ ok(`warm create adopted a spare in ${warmMs}ms`);
42
+ // The adopted sandbox is a real, working VM with its own workspace.
43
+ let out = "";
44
+ await driver.exec(warmId, "uname -s && echo WARM_OK", {}, (e) => {
45
+ if (e.type === "stdout")
46
+ out += e.data;
47
+ });
48
+ assert.match(out, /Linux/, "adopted guest runs Linux");
49
+ assert.match(out, /WARM_OK/, "adopted guest execs");
50
+ await driver.writeFile(warmId, { path: "/workspace/w.txt", content: "warm-data" });
51
+ assert.equal(await driver.readFile(warmId, { path: "/workspace/w.txt" }), "warm-data");
52
+ ok("adopted guest execs + has a writable workspace");
53
+ // Workspace survives stop/start (canonical path adopted from the slot).
54
+ await driver.stop(warmId);
55
+ await driver.start({ id: warmId, image: "base", persist: true });
56
+ assert.equal(await driver.readFile(warmId, { path: "/workspace/w.txt" }), "warm-data", "adopted workspace persists across stop/start");
57
+ ok("adopted workspace persists across stop/start");
58
+ // Cold baseline: drain the pool, then create — a full boot for comparison.
59
+ await driver.drainPool();
60
+ const coldId = "cold01";
61
+ const t1 = Date.now();
62
+ await driver.create({ id: coldId, image: "base", persist: true });
63
+ const coldMs = Date.now() - t1;
64
+ ok(`cold create (pool drained) booted in ${coldMs}ms`);
65
+ assert.ok(warmMs < coldMs, `warm acquire (${warmMs}ms) should beat cold boot (${coldMs}ms)`);
66
+ ok(`★ warm acquire ${warmMs}ms ≪ cold boot ${coldMs}ms (${Math.round(coldMs / Math.max(1, warmMs))}× faster)`);
67
+ await driver.destroy(warmId);
68
+ await driver.destroy(coldId);
69
+ ok("destroy both");
70
+ console.log(`\nwarmpool-check: ${passed} checks passed`);
71
+ }
72
+ finally {
73
+ await driver.drainPool().catch(() => { });
74
+ await driver.stop("warm01").catch(() => { });
75
+ await driver.stop("cold01").catch(() => { });
76
+ rmSync(stateDir, { recursive: true, force: true });
77
+ }
78
+ }
79
+ main().then(() => process.exit(0), (err) => {
80
+ console.error("warmpool-check FAILED:", err);
81
+ process.exit(1);
82
+ });
83
+ //# sourceMappingURL=warmpool-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warmpool-check.js","sourceRoot":"","sources":["../src/warmpool-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const DASHBOARD_HTML: string;