@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
package/dist/store.js ADDED
@@ -0,0 +1,578 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { mkdirSync } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ import { DatabaseSync } from "node:sqlite";
5
+ /** Zero-valued usage accumulator for a fresh sandbox. */
6
+ export function emptyUsage() {
7
+ return {
8
+ cpuSeconds: 0,
9
+ memByteSeconds: 0,
10
+ egressBytes: 0,
11
+ providerCalls: 0,
12
+ providerBytes: 0,
13
+ providerTokensIn: 0,
14
+ providerTokensOut: 0,
15
+ providerCost: 0,
16
+ lastCpuTotalNs: 0,
17
+ lastSampledAt: "",
18
+ };
19
+ }
20
+ /**
21
+ * Durable sandbox registry backed by embedded SQLite (`node:sqlite`, built into
22
+ * Node ≥22 — no external dependency). Alongside the sandbox records it tracks
23
+ * background processes, exposed preview ports, sessions, and code-interpreter
24
+ * contexts so the full control-plane state survives a daemon restart (the
25
+ * lead-in to the lifecycle FSM).
26
+ *
27
+ * The in-memory `Map`s are a hot cache that is the working copy during the
28
+ * daemon's lifetime — they preserve mutate-by-reference semantics for callers
29
+ * that tweak a returned record in place. Every mutating method is write-through
30
+ * to SQLite; on construction the cache is hydrated from the database. Pass
31
+ * `:memory:` (the default) for an ephemeral, in-process store (tests, smoke).
32
+ */
33
+ export class SandboxStore {
34
+ db;
35
+ byId = new Map();
36
+ // sandboxId -> procId -> process
37
+ procs = new Map();
38
+ // sandboxId -> port -> exposed port
39
+ exposed = new Map();
40
+ // exposeId -> route target (O(1) lookup for the proxy)
41
+ routes = new Map();
42
+ // sandboxId -> sessionId -> session
43
+ sessions = new Map();
44
+ // sandboxId -> contextId -> code context
45
+ contexts = new Map();
46
+ // egress token -> record (sandboxId + policy + spend; O(1) lookup for the egress proxy)
47
+ egressTokens = new Map();
48
+ constructor(dbPath = ":memory:") {
49
+ if (dbPath !== ":memory:")
50
+ mkdirSync(dirname(dbPath), { recursive: true });
51
+ this.db = new DatabaseSync(dbPath);
52
+ if (dbPath !== ":memory:")
53
+ this.db.exec("PRAGMA journal_mode = WAL;");
54
+ this.migrate();
55
+ this.hydrate();
56
+ }
57
+ /** Close the underlying database handle (call on daemon shutdown). */
58
+ close() {
59
+ this.db.close();
60
+ }
61
+ migrate() {
62
+ this.db.exec(`
63
+ CREATE TABLE IF NOT EXISTS sandboxes (
64
+ id TEXT PRIMARY KEY,
65
+ image TEXT NOT NULL,
66
+ status TEXT NOT NULL,
67
+ createdAt TEXT NOT NULL,
68
+ driver TEXT NOT NULL DEFAULT '',
69
+ labels TEXT NOT NULL,
70
+ env TEXT NOT NULL,
71
+ persist INTEGER NOT NULL,
72
+ lastActivityAt TEXT NOT NULL DEFAULT '',
73
+ sleepAfterMs INTEGER NOT NULL DEFAULT 0,
74
+ usage TEXT NOT NULL DEFAULT '{}',
75
+ limits TEXT NOT NULL DEFAULT '{}',
76
+ egressSpendCap REAL NOT NULL DEFAULT 0
77
+ );
78
+ CREATE TABLE IF NOT EXISTS processes (
79
+ sandboxId TEXT NOT NULL,
80
+ procId TEXT NOT NULL,
81
+ pid INTEGER NOT NULL,
82
+ command TEXT NOT NULL,
83
+ status TEXT NOT NULL,
84
+ exitCode INTEGER,
85
+ startedAt TEXT NOT NULL,
86
+ logPath TEXT NOT NULL,
87
+ PRIMARY KEY (sandboxId, procId)
88
+ );
89
+ CREATE TABLE IF NOT EXISTS exposed_ports (
90
+ sandboxId TEXT NOT NULL,
91
+ port INTEGER NOT NULL,
92
+ exposeId TEXT NOT NULL,
93
+ token TEXT,
94
+ createdAt TEXT NOT NULL,
95
+ url TEXT NOT NULL,
96
+ PRIMARY KEY (sandboxId, port)
97
+ );
98
+ CREATE TABLE IF NOT EXISTS sessions (
99
+ sandboxId TEXT NOT NULL,
100
+ sessionId TEXT NOT NULL,
101
+ cwd TEXT NOT NULL,
102
+ env TEXT NOT NULL,
103
+ createdAt TEXT NOT NULL,
104
+ PRIMARY KEY (sandboxId, sessionId)
105
+ );
106
+ CREATE TABLE IF NOT EXISTS code_contexts (
107
+ sandboxId TEXT NOT NULL,
108
+ contextId TEXT NOT NULL,
109
+ language TEXT NOT NULL,
110
+ dir TEXT NOT NULL,
111
+ procId TEXT NOT NULL,
112
+ pid INTEGER NOT NULL,
113
+ seq INTEGER NOT NULL,
114
+ createdAt TEXT NOT NULL,
115
+ PRIMARY KEY (sandboxId, contextId)
116
+ );
117
+ CREATE TABLE IF NOT EXISTS egress_tokens (
118
+ token TEXT PRIMARY KEY,
119
+ sandboxId TEXT NOT NULL,
120
+ createdAt TEXT NOT NULL,
121
+ policy TEXT NOT NULL DEFAULT '{}',
122
+ spendUsd REAL NOT NULL DEFAULT 0
123
+ );
124
+ `);
125
+ // Backfill columns added after the first release on databases created by an
126
+ // older daemon (CREATE TABLE IF NOT EXISTS leaves existing tables untouched).
127
+ this.ensureColumn("sandboxes", "lastActivityAt", "TEXT NOT NULL DEFAULT ''");
128
+ this.ensureColumn("sandboxes", "sleepAfterMs", "INTEGER NOT NULL DEFAULT 0");
129
+ this.ensureColumn("sandboxes", "usage", "TEXT NOT NULL DEFAULT '{}'");
130
+ this.ensureColumn("sandboxes", "limits", "TEXT NOT NULL DEFAULT '{}'");
131
+ this.ensureColumn("sandboxes", "egressSpendCap", "REAL NOT NULL DEFAULT 0");
132
+ this.ensureColumn("sandboxes", "driver", "TEXT NOT NULL DEFAULT ''");
133
+ this.ensureColumn("egress_tokens", "policy", "TEXT NOT NULL DEFAULT '{}'");
134
+ this.ensureColumn("egress_tokens", "spendUsd", "REAL NOT NULL DEFAULT 0");
135
+ }
136
+ /** Add a column to a table if it isn't already present (idempotent migration). */
137
+ ensureColumn(table, column, decl) {
138
+ const cols = this.db.prepare(`PRAGMA table_info(${table})`).all();
139
+ if (!cols.some((c) => c.name === column)) {
140
+ this.db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${decl}`);
141
+ }
142
+ }
143
+ /** Load all persisted rows into the in-memory cache on startup. */
144
+ hydrate() {
145
+ for (const row of this.db.prepare("SELECT * FROM sandboxes").all()) {
146
+ this.byId.set(row.id, rowToSandbox(row));
147
+ }
148
+ for (const row of this.db.prepare("SELECT * FROM processes").all()) {
149
+ mapIn(this.procs, row.sandboxId).set(row.procId, rowToProcess(row));
150
+ }
151
+ for (const row of this.db.prepare("SELECT * FROM exposed_ports").all()) {
152
+ const exposed = rowToExposed(row);
153
+ mapIn(this.exposed, row.sandboxId).set(exposed.port, exposed);
154
+ this.routes.set(exposed.exposeId, {
155
+ sandboxId: row.sandboxId,
156
+ port: exposed.port,
157
+ token: exposed.token,
158
+ });
159
+ }
160
+ for (const row of this.db.prepare("SELECT * FROM sessions").all()) {
161
+ mapIn(this.sessions, row.sandboxId).set(row.sessionId, rowToSession(row));
162
+ }
163
+ for (const row of this.db.prepare("SELECT * FROM code_contexts").all()) {
164
+ mapIn(this.contexts, row.sandboxId).set(row.contextId, rowToContext(row));
165
+ }
166
+ for (const row of this.db.prepare("SELECT * FROM egress_tokens").all()) {
167
+ this.egressTokens.set(row.token, rowToEgressToken(row));
168
+ }
169
+ }
170
+ static newId() {
171
+ return randomBytes(6).toString("hex");
172
+ }
173
+ static newContextId() {
174
+ return randomBytes(4).toString("hex");
175
+ }
176
+ static newProcId() {
177
+ return randomBytes(4).toString("hex");
178
+ }
179
+ static newSessionId() {
180
+ return randomBytes(4).toString("hex");
181
+ }
182
+ static newBackupId() {
183
+ return randomBytes(6).toString("hex");
184
+ }
185
+ /** Mint an opaque per-sandbox egress token (used as the gateway's API key). */
186
+ static newEgressToken() {
187
+ return "hc-" + randomBytes(24).toString("hex");
188
+ }
189
+ // --- sandboxes -----------------------------------------------------------
190
+ /** Insert or update a sandbox record (write-through; also use to persist
191
+ * in-place edits to a record returned by `get`). */
192
+ add(record) {
193
+ this.byId.set(record.id, record);
194
+ this.db
195
+ .prepare(`INSERT INTO sandboxes
196
+ (id, image, status, createdAt, driver, labels, env, persist, lastActivityAt, sleepAfterMs, usage, limits, egressSpendCap)
197
+ VALUES
198
+ ($id, $image, $status, $createdAt, $driver, $labels, $env, $persist, $lastActivityAt, $sleepAfterMs, $usage, $limits, $egressSpendCap)
199
+ ON CONFLICT(id) DO UPDATE SET
200
+ image=$image, status=$status, createdAt=$createdAt, driver=$driver,
201
+ labels=$labels, env=$env, persist=$persist,
202
+ lastActivityAt=$lastActivityAt, sleepAfterMs=$sleepAfterMs, usage=$usage, limits=$limits,
203
+ egressSpendCap=$egressSpendCap`)
204
+ .run({
205
+ id: record.id,
206
+ image: record.image,
207
+ status: record.status,
208
+ createdAt: record.createdAt,
209
+ driver: record.driver ?? "",
210
+ labels: JSON.stringify(record.labels),
211
+ env: JSON.stringify(record.env),
212
+ persist: record.persist ? 1 : 0,
213
+ lastActivityAt: record.lastActivityAt,
214
+ sleepAfterMs: record.sleepAfterMs,
215
+ usage: JSON.stringify(record.usage),
216
+ limits: JSON.stringify(record.limits ?? {}),
217
+ egressSpendCap: record.egressSpendCapUsd ?? 0,
218
+ });
219
+ }
220
+ /**
221
+ * Persist updated cumulative usage for a sandbox (write-through). Cheap single
222
+ * column used by the metrics sampler on every tick. No-op for an unknown id.
223
+ */
224
+ setUsage(id, usage) {
225
+ const rec = this.byId.get(id);
226
+ if (!rec)
227
+ return;
228
+ rec.usage = usage;
229
+ this.db
230
+ .prepare("UPDATE sandboxes SET usage = ? WHERE id = ?")
231
+ .run(JSON.stringify(usage), id);
232
+ }
233
+ /**
234
+ * Add to a sandbox's cumulative egress byte counter (write-through). Called by
235
+ * the preview proxy as connections close. No-op for an unknown id.
236
+ */
237
+ addEgress(id, bytes) {
238
+ const rec = this.byId.get(id);
239
+ if (!rec || bytes <= 0)
240
+ return;
241
+ rec.usage.egressBytes += bytes;
242
+ this.db
243
+ .prepare("UPDATE sandboxes SET usage = ? WHERE id = ?")
244
+ .run(JSON.stringify(rec.usage), id);
245
+ }
246
+ /**
247
+ * Record one LLM-provider call's usage (write-through). Called by the egress
248
+ * credential proxy as each provider response completes. No-op for unknown id.
249
+ */
250
+ addProviderUsage(id, delta) {
251
+ const rec = this.byId.get(id);
252
+ if (!rec)
253
+ return;
254
+ rec.usage.providerCalls += 1;
255
+ rec.usage.providerBytes += Math.max(0, delta.bytes);
256
+ rec.usage.providerTokensIn += Math.max(0, delta.tokensIn);
257
+ rec.usage.providerTokensOut += Math.max(0, delta.tokensOut);
258
+ rec.usage.providerCost += Math.max(0, delta.cost);
259
+ this.db
260
+ .prepare("UPDATE sandboxes SET usage = ? WHERE id = ?")
261
+ .run(JSON.stringify(rec.usage), id);
262
+ }
263
+ // --- egress tokens -------------------------------------------------------
264
+ /** Bind an egress token to a sandbox with an optional policy (write-through). */
265
+ addEgressToken(token, sandboxId, policy = {}) {
266
+ const record = {
267
+ token,
268
+ sandboxId,
269
+ policy,
270
+ createdAt: new Date().toISOString(),
271
+ spendUsd: 0,
272
+ };
273
+ this.egressTokens.set(token, record);
274
+ this.db
275
+ .prepare("INSERT OR REPLACE INTO egress_tokens (token, sandboxId, createdAt, policy, spendUsd) VALUES (?, ?, ?, ?, ?)")
276
+ .run(token, sandboxId, record.createdAt, JSON.stringify(policy), 0);
277
+ }
278
+ /** Resolve an egress token to its sandbox id (O(1)). Back-compat shorthand. */
279
+ resolveEgressToken(token) {
280
+ return this.egressTokens.get(token)?.sandboxId;
281
+ }
282
+ /** Resolve an egress token to its full record (sandbox + policy + spend). */
283
+ resolveEgressTokenFull(token) {
284
+ return this.egressTokens.get(token);
285
+ }
286
+ /** Add to a token's cumulative spend (write-through). Drives the spend cap. */
287
+ addEgressTokenSpend(token, usd) {
288
+ const rec = this.egressTokens.get(token);
289
+ if (!rec || !(usd > 0))
290
+ return;
291
+ rec.spendUsd += usd;
292
+ this.db
293
+ .prepare("UPDATE egress_tokens SET spendUsd = ? WHERE token = ?")
294
+ .run(rec.spendUsd, token);
295
+ }
296
+ /** List the egress token records minted for a sandbox. */
297
+ listEgressTokens(sandboxId) {
298
+ return [...this.egressTokens.values()].filter((r) => r.sandboxId === sandboxId);
299
+ }
300
+ /** Revoke a single egress token. Returns whether it existed. */
301
+ removeEgressToken(token) {
302
+ this.db.prepare("DELETE FROM egress_tokens WHERE token = ?").run(token);
303
+ return this.egressTokens.delete(token);
304
+ }
305
+ /**
306
+ * Mark a sandbox as just-active (refresh `lastActivityAt`). Cheap single-column
307
+ * write-through used on every operation that runs work in the sandbox, so the
308
+ * idle reaper sees recent use. No-op for an unknown id.
309
+ */
310
+ touch(id) {
311
+ const rec = this.byId.get(id);
312
+ if (!rec)
313
+ return;
314
+ rec.lastActivityAt = new Date().toISOString();
315
+ this.db
316
+ .prepare("UPDATE sandboxes SET lastActivityAt = ? WHERE id = ?")
317
+ .run(rec.lastActivityAt, id);
318
+ }
319
+ get(id) {
320
+ return this.byId.get(id);
321
+ }
322
+ remove(id) {
323
+ this.db.prepare("DELETE FROM sandboxes WHERE id = ?").run(id);
324
+ return this.byId.delete(id);
325
+ }
326
+ list() {
327
+ return [...this.byId.values()].sort((a, b) => a.createdAt < b.createdAt ? 1 : -1);
328
+ }
329
+ // --- processes -----------------------------------------------------------
330
+ /** Insert or update a background-process record (write-through). */
331
+ addProcess(sandboxId, proc) {
332
+ mapIn(this.procs, sandboxId).set(proc.procId, proc);
333
+ this.db
334
+ .prepare(`INSERT INTO processes (sandboxId, procId, pid, command, status, exitCode, startedAt, logPath)
335
+ VALUES ($sandboxId, $procId, $pid, $command, $status, $exitCode, $startedAt, $logPath)
336
+ ON CONFLICT(sandboxId, procId) DO UPDATE SET
337
+ pid=$pid, command=$command, status=$status, exitCode=$exitCode,
338
+ startedAt=$startedAt, logPath=$logPath`)
339
+ .run({
340
+ sandboxId,
341
+ procId: proc.procId,
342
+ pid: proc.pid,
343
+ command: proc.command,
344
+ status: proc.status,
345
+ exitCode: proc.exitCode,
346
+ startedAt: proc.startedAt,
347
+ logPath: proc.logPath,
348
+ });
349
+ }
350
+ getProcess(sandboxId, procId) {
351
+ return this.procs.get(sandboxId)?.get(procId);
352
+ }
353
+ listProcesses(sandboxId) {
354
+ return [...(this.procs.get(sandboxId)?.values() ?? [])].sort((a, b) => a.startedAt < b.startedAt ? 1 : -1);
355
+ }
356
+ // --- exposed ports -------------------------------------------------------
357
+ addExposed(sandboxId, exposed) {
358
+ mapIn(this.exposed, sandboxId).set(exposed.port, exposed);
359
+ this.routes.set(exposed.exposeId, {
360
+ sandboxId,
361
+ port: exposed.port,
362
+ token: exposed.token,
363
+ });
364
+ this.db
365
+ .prepare(`INSERT INTO exposed_ports (sandboxId, port, exposeId, token, createdAt, url)
366
+ VALUES ($sandboxId, $port, $exposeId, $token, $createdAt, $url)
367
+ ON CONFLICT(sandboxId, port) DO UPDATE SET
368
+ exposeId=$exposeId, token=$token, createdAt=$createdAt, url=$url`)
369
+ .run({
370
+ sandboxId,
371
+ port: exposed.port,
372
+ exposeId: exposed.exposeId,
373
+ token: exposed.token,
374
+ createdAt: exposed.createdAt,
375
+ url: exposed.url,
376
+ });
377
+ }
378
+ removeExposed(sandboxId, port) {
379
+ const map = this.exposed.get(sandboxId);
380
+ const exposed = map?.get(port);
381
+ if (!map || !exposed)
382
+ return false;
383
+ map.delete(port);
384
+ this.routes.delete(exposed.exposeId);
385
+ this.db
386
+ .prepare("DELETE FROM exposed_ports WHERE sandboxId = ? AND port = ?")
387
+ .run(sandboxId, port);
388
+ return true;
389
+ }
390
+ listExposed(sandboxId) {
391
+ return [...(this.exposed.get(sandboxId)?.values() ?? [])].sort((a, b) => a.port - b.port);
392
+ }
393
+ /** Resolve a preview route label (`<sandboxId>-<port>`) to its target. */
394
+ resolveRoute(exposeId) {
395
+ return this.routes.get(exposeId);
396
+ }
397
+ // --- sessions ------------------------------------------------------------
398
+ /** Insert or update a session record (write-through; also use to persist
399
+ * in-place edits to cwd/env on a session returned by `getSession`). */
400
+ addSession(sandboxId, session) {
401
+ mapIn(this.sessions, sandboxId).set(session.sessionId, session);
402
+ this.db
403
+ .prepare(`INSERT INTO sessions (sandboxId, sessionId, cwd, env, createdAt)
404
+ VALUES ($sandboxId, $sessionId, $cwd, $env, $createdAt)
405
+ ON CONFLICT(sandboxId, sessionId) DO UPDATE SET
406
+ cwd=$cwd, env=$env, createdAt=$createdAt`)
407
+ .run({
408
+ sandboxId,
409
+ sessionId: session.sessionId,
410
+ cwd: session.cwd,
411
+ env: JSON.stringify(session.env),
412
+ createdAt: session.createdAt,
413
+ });
414
+ }
415
+ getSession(sandboxId, sessionId) {
416
+ return this.sessions.get(sandboxId)?.get(sessionId);
417
+ }
418
+ listSessions(sandboxId) {
419
+ return [...(this.sessions.get(sandboxId)?.values() ?? [])].sort((a, b) => a.createdAt < b.createdAt ? 1 : -1);
420
+ }
421
+ removeSession(sandboxId, sessionId) {
422
+ this.db
423
+ .prepare("DELETE FROM sessions WHERE sandboxId = ? AND sessionId = ?")
424
+ .run(sandboxId, sessionId);
425
+ return this.sessions.get(sandboxId)?.delete(sessionId) ?? false;
426
+ }
427
+ // --- code contexts -------------------------------------------------------
428
+ /** Insert or update a code-interpreter context record (write-through; also
429
+ * use to persist the bumped `seq` after running a cell). */
430
+ addContext(sandboxId, ctx) {
431
+ mapIn(this.contexts, sandboxId).set(ctx.contextId, ctx);
432
+ this.db
433
+ .prepare(`INSERT INTO code_contexts (sandboxId, contextId, language, dir, procId, pid, seq, createdAt)
434
+ VALUES ($sandboxId, $contextId, $language, $dir, $procId, $pid, $seq, $createdAt)
435
+ ON CONFLICT(sandboxId, contextId) DO UPDATE SET
436
+ language=$language, dir=$dir, procId=$procId, pid=$pid,
437
+ seq=$seq, createdAt=$createdAt`)
438
+ .run({
439
+ sandboxId,
440
+ contextId: ctx.contextId,
441
+ language: ctx.language,
442
+ dir: ctx.dir,
443
+ procId: ctx.procId,
444
+ pid: ctx.pid,
445
+ seq: ctx.seq,
446
+ createdAt: ctx.createdAt,
447
+ });
448
+ }
449
+ getContext(sandboxId, contextId) {
450
+ return this.contexts.get(sandboxId)?.get(contextId);
451
+ }
452
+ listContexts(sandboxId) {
453
+ return [...(this.contexts.get(sandboxId)?.values() ?? [])].sort((a, b) => a.createdAt < b.createdAt ? 1 : -1);
454
+ }
455
+ removeContext(sandboxId, contextId) {
456
+ this.db
457
+ .prepare("DELETE FROM code_contexts WHERE sandboxId = ? AND contextId = ?")
458
+ .run(sandboxId, contextId);
459
+ return this.contexts.get(sandboxId)?.delete(contextId) ?? false;
460
+ }
461
+ /** Drop all process + exposed-port + session + context + egress-token state for a destroyed sandbox. */
462
+ clearSandbox(sandboxId) {
463
+ this.clearRuntimeState(sandboxId);
464
+ this.sessions.delete(sandboxId);
465
+ this.db.prepare("DELETE FROM sessions WHERE sandboxId = ?").run(sandboxId);
466
+ for (const rec of this.listEgressTokens(sandboxId))
467
+ this.egressTokens.delete(rec.token);
468
+ this.db.prepare("DELETE FROM egress_tokens WHERE sandboxId = ?").run(sandboxId);
469
+ }
470
+ /**
471
+ * Drop the state tied to a live container — background processes, exposed
472
+ * ports, and code-interpreter contexts (their kernels die with the
473
+ * container) — when a sandbox is stopped. Sessions (just cwd/env strings) and
474
+ * the sandbox record are kept so `start` resumes with them intact.
475
+ */
476
+ clearRuntimeState(sandboxId) {
477
+ this.procs.delete(sandboxId);
478
+ this.contexts.delete(sandboxId);
479
+ const ports = this.exposed.get(sandboxId);
480
+ if (ports) {
481
+ for (const exposed of ports.values())
482
+ this.routes.delete(exposed.exposeId);
483
+ this.exposed.delete(sandboxId);
484
+ }
485
+ this.db.prepare("DELETE FROM processes WHERE sandboxId = ?").run(sandboxId);
486
+ this.db.prepare("DELETE FROM code_contexts WHERE sandboxId = ?").run(sandboxId);
487
+ this.db.prepare("DELETE FROM exposed_ports WHERE sandboxId = ?").run(sandboxId);
488
+ }
489
+ }
490
+ /** Get-or-create the inner per-sandbox map for a two-level cache. */
491
+ function mapIn(outer, key) {
492
+ let inner = outer.get(key);
493
+ if (!inner) {
494
+ inner = new Map();
495
+ outer.set(key, inner);
496
+ }
497
+ return inner;
498
+ }
499
+ function rowToSandbox(row) {
500
+ return {
501
+ id: row.id,
502
+ image: row.image,
503
+ status: row.status,
504
+ createdAt: row.createdAt,
505
+ driver: row.driver || undefined,
506
+ labels: JSON.parse(row.labels),
507
+ env: JSON.parse(row.env),
508
+ persist: row.persist === 1,
509
+ lastActivityAt: row.lastActivityAt || row.createdAt,
510
+ sleepAfterMs: row.sleepAfterMs ?? 0,
511
+ limits: parseJsonObject(row.limits),
512
+ egressSpendCapUsd: typeof row.egressSpendCap === "number" ? row.egressSpendCap : 0,
513
+ usage: { ...emptyUsage(), ...parseUsage(row.usage) },
514
+ };
515
+ }
516
+ function parseUsage(raw) {
517
+ return parseJsonObject(raw);
518
+ }
519
+ /** Parse a JSON-object column, tolerating null/empty/malformed values. */
520
+ function parseJsonObject(raw) {
521
+ if (typeof raw !== "string" || !raw)
522
+ return {};
523
+ try {
524
+ return JSON.parse(raw);
525
+ }
526
+ catch {
527
+ return {};
528
+ }
529
+ }
530
+ function rowToEgressToken(row) {
531
+ return {
532
+ token: row.token,
533
+ sandboxId: row.sandboxId,
534
+ policy: parseJsonObject(row.policy),
535
+ createdAt: row.createdAt,
536
+ spendUsd: typeof row.spendUsd === "number" ? row.spendUsd : 0,
537
+ };
538
+ }
539
+ function rowToProcess(row) {
540
+ return {
541
+ procId: row.procId,
542
+ pid: row.pid,
543
+ command: row.command,
544
+ status: row.status,
545
+ exitCode: row.exitCode,
546
+ startedAt: row.startedAt,
547
+ logPath: row.logPath,
548
+ };
549
+ }
550
+ function rowToExposed(row) {
551
+ return {
552
+ port: row.port,
553
+ exposeId: row.exposeId,
554
+ token: row.token,
555
+ createdAt: row.createdAt,
556
+ url: row.url,
557
+ };
558
+ }
559
+ function rowToSession(row) {
560
+ return {
561
+ sessionId: row.sessionId,
562
+ cwd: row.cwd,
563
+ env: JSON.parse(row.env),
564
+ createdAt: row.createdAt,
565
+ };
566
+ }
567
+ function rowToContext(row) {
568
+ return {
569
+ contextId: row.contextId,
570
+ language: row.language,
571
+ dir: row.dir,
572
+ procId: row.procId,
573
+ pid: row.pid,
574
+ seq: row.seq,
575
+ createdAt: row.createdAt,
576
+ };
577
+ }
578
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAY3C,yDAAyD;AACzD,MAAM,UAAU,UAAU;IACxB,OAAO;QACL,UAAU,EAAE,CAAC;QACb,cAAc,EAAE,CAAC;QACjB,WAAW,EAAE,CAAC;QACd,aAAa,EAAE,CAAC;QAChB,aAAa,EAAE,CAAC;QAChB,gBAAgB,EAAE,CAAC;QACnB,iBAAiB,EAAE,CAAC;QACpB,YAAY,EAAE,CAAC;QACf,cAAc,EAAE,CAAC;QACjB,aAAa,EAAE,EAAE;KAClB,CAAC;AACJ,CAAC;AAkBD;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,YAAY;IACf,EAAE,CAAe;IAEjB,IAAI,GAAG,IAAI,GAAG,EAAyB,CAAC;IAChD,iCAAiC;IACzB,KAAK,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC5D,oCAAoC;IAC5B,OAAO,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC9D,uDAAuD;IAC/C,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAC;IAChD,oCAAoC;IAC5B,QAAQ,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC/D,yCAAyC;IACjC,QAAQ,GAAG,IAAI,GAAG,EAAwC,CAAC;IACnE,wFAAwF;IAChF,YAAY,GAAG,IAAI,GAAG,EAA6B,CAAC;IAE5D,YAAY,MAAM,GAAG,UAAU;QAC7B,IAAI,MAAM,KAAK,UAAU;YAAE,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3E,IAAI,CAAC,EAAE,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,MAAM,KAAK,UAAU;YAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACtE,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,sEAAsE;IACtE,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;IAEO,OAAO;QACb,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA8DZ,CAAC,CAAC;QACH,4EAA4E;QAC5E,8EAA8E;QAC9E,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,gBAAgB,EAAE,0BAA0B,CAAC,CAAC;QAC7E,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,cAAc,EAAE,4BAA4B,CAAC,CAAC;QAC7E,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,EAAE,4BAA4B,CAAC,CAAC;QACtE,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,QAAQ,EAAE,4BAA4B,CAAC,CAAC;QACvE,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,gBAAgB,EAAE,yBAAyB,CAAC,CAAC;QAC5E,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,QAAQ,EAAE,0BAA0B,CAAC,CAAC;QACrE,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,QAAQ,EAAE,4BAA4B,CAAC,CAAC;QAC3E,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,UAAU,EAAE,yBAAyB,CAAC,CAAC;IAC5E,CAAC;IAED,kFAAkF;IAC1E,YAAY,CAAC,KAAa,EAAE,MAAc,EAAE,IAAY;QAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,qBAAqB,KAAK,GAAG,CAAC,CAAC,GAAG,EAAW,CAAC;QAC3E,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,eAAe,KAAK,eAAe,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,mEAAmE;IAC3D,OAAO;QACb,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,GAAG,EAAW,EAAE,CAAC;YAC5E,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,GAAG,EAAW,EAAE,CAAC;YAC5E,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QACtE,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC,GAAG,EAAW,EAAE,CAAC;YAChF,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC9D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE;gBAChC,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,KAAK,EAAE,OAAO,CAAC,KAAK;aACrB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC,GAAG,EAAW,EAAE,CAAC;YAC3E,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5E,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC,GAAG,EAAW,EAAE,CAAC;YAChF,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5E,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC,GAAG,EAAW,EAAE,CAAC;YAChF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,MAAM,CAAC,KAAK;QACV,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,YAAY;QACjB,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,SAAS;QACd,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,YAAY;QACjB,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,WAAW;QAChB,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,+EAA+E;IAC/E,MAAM,CAAC,cAAc;QACnB,OAAO,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC;IAED,4EAA4E;IAE5E;wDACoD;IACpD,GAAG,CAAC,MAAqB;QACvB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE;aACJ,OAAO,CACN;;;;;;;;0CAQkC,CACnC;aACA,GAAG,CAAC;YACH,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;YAC3B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;YACrC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC;YAC/B,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/B,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC;YACnC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;YAC3C,cAAc,EAAE,MAAM,CAAC,iBAAiB,IAAI,CAAC;SAC9C,CAAC,CAAC;IACP,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,EAAU,EAAE,KAAmB;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC;QAClB,IAAI,CAAC,EAAE;aACJ,OAAO,CAAC,6CAA6C,CAAC;aACtD,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,EAAU,EAAE,KAAa;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;YAAE,OAAO;QAC/B,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC;QAC/B,IAAI,CAAC,EAAE;aACJ,OAAO,CAAC,6CAA6C,CAAC;aACtD,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IACxC,CAAC;IAED;;;OAGG;IACH,gBAAgB,CAAC,EAAU,EAAE,KAAyB;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,GAAG,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;QAC7B,GAAG,CAAC,KAAK,CAAC,aAAa,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACpD,GAAG,CAAC,KAAK,CAAC,gBAAgB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC1D,GAAG,CAAC,KAAK,CAAC,iBAAiB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QAC5D,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,EAAE;aACJ,OAAO,CAAC,6CAA6C,CAAC;aACtD,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,4EAA4E;IAE5E,iFAAiF;IACjF,cAAc,CAAC,KAAa,EAAE,SAAiB,EAAE,SAAuB,EAAE;QACxE,MAAM,MAAM,GAAsB;YAChC,KAAK;YACL,SAAS;YACT,MAAM;YACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,QAAQ,EAAE,CAAC;SACZ,CAAC;QACF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,EAAE;aACJ,OAAO,CACN,6GAA6G,CAC9G;aACA,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,+EAA+E;IAC/E,kBAAkB,CAAC,KAAa;QAC9B,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IACjD,CAAC;IAED,6EAA6E;IAC7E,sBAAsB,CAAC,KAAa;QAClC,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,+EAA+E;IAC/E,mBAAmB,CAAC,KAAa,EAAE,GAAW;QAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;YAAE,OAAO;QAC/B,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC;QACpB,IAAI,CAAC,EAAE;aACJ,OAAO,CAAC,uDAAuD,CAAC;aAChE,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,0DAA0D;IAC1D,gBAAgB,CAAC,SAAiB;QAChC,OAAO,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;IAClF,CAAC;IAED,gEAAgE;IAChE,iBAAiB,CAAC,KAAa;QAC7B,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,EAAU;QACd,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,GAAG,CAAC,cAAc,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC9C,IAAI,CAAC,EAAE;aACJ,OAAO,CAAC,sDAAsD,CAAC;aAC/D,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,EAAU;QACf,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC3C,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACnC,CAAC;IACJ,CAAC;IAED,4EAA4E;IAE5E,oEAAoE;IACpE,UAAU,CAAC,SAAiB,EAAE,IAAiB;QAC7C,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACpD,IAAI,CAAC,EAAE;aACJ,OAAO,CACN;;;;kDAI0C,CAC3C;aACA,GAAG,CAAC;YACH,SAAS;YACT,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;IACP,CAAC;IAED,UAAU,CAAC,SAAiB,EAAE,MAAc;QAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAChD,CAAC;IAED,aAAa,CAAC,SAAiB;QAC7B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACpE,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACnC,CAAC;IACJ,CAAC;IAED,4EAA4E;IAE5E,UAAU,CAAC,SAAiB,EAAE,OAAoB;QAChD,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE;YAChC,SAAS;YACT,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CAAC;QACH,IAAI,CAAC,EAAE;aACJ,OAAO,CACN;;;4EAGoE,CACrE;aACA,GAAG,CAAC;YACH,SAAS;YACT,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;IACP,CAAC;IAED,aAAa,CAAC,SAAiB,EAAE,IAAY;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QACnC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACjB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,CAAC,EAAE;aACJ,OAAO,CAAC,4DAA4D,CAAC;aACrE,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,WAAW,CAAC,SAAiB;QAC3B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAC5D,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAC1B,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,YAAY,CAAC,QAAgB;QAC3B,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,4EAA4E;IAE5E;2EACuE;IACvE,UAAU,CAAC,SAAiB,EAAE,OAAoB;QAChD,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAChE,IAAI,CAAC,EAAE;aACJ,OAAO,CACN;;;oDAG4C,CAC7C;aACA,GAAG,CAAC;YACH,SAAS;YACT,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC;YAChC,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,CAAC,CAAC;IACP,CAAC;IAED,UAAU,CAAC,SAAiB,EAAE,SAAiB;QAC7C,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IACtD,CAAC;IAED,YAAY,CAAC,SAAiB;QAC5B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACvE,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACnC,CAAC;IACJ,CAAC;IAED,aAAa,CAAC,SAAiB,EAAE,SAAiB;QAChD,IAAI,CAAC,EAAE;aACJ,OAAO,CAAC,4DAA4D,CAAC;aACrE,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC;IAClE,CAAC;IAED,4EAA4E;IAE5E;gEAC4D;IAC5D,UAAU,CAAC,SAAiB,EAAE,GAAoB;QAChD,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,EAAE;aACJ,OAAO,CACN;;;;0CAIkC,CACnC;aACA,GAAG,CAAC;YACH,SAAS;YACT,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC,CAAC;IACP,CAAC;IAED,UAAU,CAAC,SAAiB,EAAE,SAAiB;QAC7C,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IACtD,CAAC;IAED,YAAY,CAAC,SAAiB;QAC5B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACvE,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACnC,CAAC;IACJ,CAAC;IAED,aAAa,CAAC,SAAiB,EAAE,SAAiB;QAChD,IAAI,CAAC,EAAE;aACJ,OAAO,CAAC,iEAAiE,CAAC;aAC1E,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC;IAClE,CAAC;IAED,wGAAwG;IACxG,YAAY,CAAC,SAAiB;QAC5B,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAClC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAChC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3E,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC;YAAE,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACxF,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAClF,CAAC;IAED;;;;;OAKG;IACH,iBAAiB,CAAC,SAAiB;QACjC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE;gBAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC3E,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACjC,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC5E,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAChF,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAClF,CAAC;CACF;AAED,qEAAqE;AACrE,SAAS,KAAK,CAAI,KAA+B,EAAE,GAAW;IAC5D,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QAClB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CAAC,GAAQ;IAC5B,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,SAAS;QAC/B,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;QAC9B,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;QACxB,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,CAAC;QAC1B,cAAc,EAAE,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,SAAS;QACnD,YAAY,EAAE,GAAG,CAAC,YAAY,IAAI,CAAC;QACnC,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC;QACnC,iBAAiB,EAAE,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;QAClF,KAAK,EAAE,EAAE,GAAG,UAAU,EAAE,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;KACrD,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,GAAY;IAC9B,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,0EAA0E;AAC1E,SAAS,eAAe,CAAC,GAAY;IACnC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IAC/C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAQ;IAChC,OAAO;QACL,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,MAAM,CAAiB;QACnD,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,QAAQ,EAAE,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;KAC9D,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,GAAQ;IAC5B,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,OAAO,EAAE,GAAG,CAAC,OAAO;KACrB,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,GAAQ;IAC5B,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,GAAG,EAAE,GAAG,CAAC,GAAG;KACb,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,GAAQ;IAC5B,OAAO;QACL,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;QACxB,SAAS,EAAE,GAAG,CAAC,SAAS;KACzB,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,GAAQ;IAC5B,OAAO;QACL,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,SAAS,EAAE,GAAG,CAAC,SAAS;KACzB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Minimal, dependency-free distributed tracing — the Phase 2 "OpenTelemetry
3
+ * traces (create→exec→destroy)" deliverable without pulling in the (large)
4
+ * `@opentelemetry/*` tree.
5
+ *
6
+ * Every finished span is kept in an in-memory ring (served at `GET /traces`) and,
7
+ * when an OTLP/HTTP endpoint is configured, batch-exported as OTLP-JSON to
8
+ * `<endpoint>/v1/traces` so it lands in Jaeger/Tempo/Honeycomb/etc. The wire
9
+ * shape follows the OTLP spec (resourceSpans → scopeSpans → spans) closely
10
+ * enough for standard collectors to ingest.
11
+ */
12
+ export type SpanStatus = "unset" | "ok" | "error";
13
+ export interface SpanData {
14
+ traceId: string;
15
+ spanId: string;
16
+ parentId?: string;
17
+ name: string;
18
+ /** Wall-clock start, unix nanoseconds (string to survive JSON without precision loss). */
19
+ startUnixNano: string;
20
+ endUnixNano: string;
21
+ durationMs: number;
22
+ attributes: Record<string, string | number | boolean>;
23
+ status: SpanStatus;
24
+ }
25
+ export interface Span {
26
+ readonly traceId: string;
27
+ readonly spanId: string;
28
+ setAttribute(key: string, value: string | number | boolean): this;
29
+ setStatus(status: SpanStatus): this;
30
+ /** Finish the span: record duration, push to the ring, queue for export. */
31
+ end(): void;
32
+ }
33
+ interface TracerConfig {
34
+ serviceName: string;
35
+ otlpEndpoint: string;
36
+ ringSize: number;
37
+ }
38
+ export declare function configureTracing(opts: Partial<TracerConfig>): void;
39
+ /** Stop the background OTLP flusher (call on daemon shutdown). */
40
+ export declare function stopTracing(): void;
41
+ /** Recent finished spans, newest first. */
42
+ export declare function recentSpans(): SpanData[];
43
+ /** Begin a span. Pass `parent` to nest it within an existing trace. */
44
+ export declare function startSpan(name: string, attributes?: Record<string, string | number | boolean>, parent?: Span): Span;
45
+ export {};