@ekairos/sandbox 1.22.4-beta.feature-core-thread-registry-sync.0 → 1.22.5-beta.development.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.
package/README.md CHANGED
@@ -1,492 +1,57 @@
1
1
  # @ekairos/sandbox
2
2
 
3
- Provider-agnostic helpers to provision and manage external sandboxes with durable IDs stored in InstantDB.
4
- This package is **independent** (no workflow runtime dependency). Other packages (e.g. `@ekairos/dataset`, `@ekairos/structure`)
5
- may depend on it, but `@ekairos/sandbox` does not depend on any workflow framework.
3
+ Provider-agnostic sandbox service with durable sandbox ids stored in InstantDB.
6
4
 
7
- ---
5
+ ## What it does
8
6
 
9
- ## Why this package exists
7
+ - creates sandboxes and persists them in `sandbox_sandboxes`
8
+ - reconnects by durable `sandboxId`
9
+ - runs commands
10
+ - reads and writes files
11
+ - supports multiple providers behind one API
10
12
 
11
- We need a stable, provider-agnostic interface to:
12
- - Create and reconnect sandboxes by a durable `sandboxId`.
13
- - Run commands and read/write files in a consistent way.
14
- - Persist sandbox metadata in InstantDB for continuity across runs.
15
- - Support multiple providers (Vercel, Daytona, etc.) without changing callers.
13
+ ## Main APIs
16
14
 
17
- ---
15
+ - `sandboxDomain`
16
+ - `SandboxService`
17
+ - `createVercelSandbox(...)`
18
+ - `runCommandInSandbox(...)`
18
19
 
19
- ## Installation (pnpm)
20
-
21
- ```bash
22
- pnpm add @ekairos/sandbox
23
- ```
24
-
25
- ---
26
-
27
- ## Environment variables
28
-
29
- ### InstantDB (admin)
30
- You must provide an InstantDB **admin** database client so sandbox actions can persist and query sandbox records.
31
-
32
- ### Provider selection
33
-
34
- By default, provider is `sprites` unless overridden.
35
-
36
- You can set:
37
- - `SANDBOX_PROVIDER=sprites` or `SANDBOX_PROVIDER=daytona` or `SANDBOX_PROVIDER=vercel`
38
- - or pass `provider` in `SandboxConfig`
39
-
40
- ### Sprites.dev
41
-
42
- - `SPRITES_API_TOKEN` (or `SPRITE_TOKEN`) - required
43
- - Optional:
44
- - `SPRITES_API_BASE_URL` / `SPRITES_API_URL` (default: `https://api.sprites.dev`)
45
-
46
- ### Daytona (current)
47
-
48
- `@daytonaio/sdk` supports these env vars:
49
-
50
- - `DAYTONA_API_URL` (required) - Daytona API base URL
51
- - `DAYTONA_API_KEY` (required if not using JWT)
52
- - `DAYTONA_JWT_TOKEN` + `DAYTONA_ORGANIZATION_ID` (optional auth mode)
53
- - `DAYTONA_TARGET` (optional)
54
- - `SANDBOX_DAYTONA_EPHEMERAL` (optional) - default ephemeral for Daytona sandboxes (true unless set to 0/false)
55
-
56
- ### Vercel
57
-
58
- - `SANDBOX_VERCEL_TEAM_ID`
59
- - `SANDBOX_VERCEL_PROJECT_ID`
60
- - `SANDBOX_VERCEL_TOKEN`
61
-
62
- ---
63
-
64
- ## Data model (InstantDB)
65
-
66
- ### `sandboxDomain`
67
- Defines a single entity:
68
-
69
- - `sandbox_sandboxes`
70
-
71
- Fields (high-level):
72
- - `externalSandboxId` (string, indexed): provider sandbox id (Vercel `sandbox.sandboxId`, Daytona `sandbox.id`)
73
- - `provider` (string, indexed): e.g. `"vercel"`, `"daytona"`
74
- - `sandboxUrl` (string, optional): optional URL metadata
75
- - `status` (string, indexed): `"creating" | "active" | "shutdown" | "error" | ...`
76
- - `timeout` (number, optional): milliseconds
77
- - `runtime` (string, optional): `"node22" | "python3" | ...`
78
- - `vcpus` (number, optional)
79
- - `ports` (json, optional): array of ports
80
- - `purpose` (string, optional, indexed)
81
- - `params` (json, optional)
82
- - timestamps: `createdAt`, `updatedAt`, `shutdownAt`
83
-
84
- ---
85
-
86
- ## ID semantics (important)
87
-
88
- There are two ids involved:
89
-
90
- ### 1) `sandboxId` (internal, durable handle)
91
- - The **InstantDB record id**: `sandbox_sandboxes[sandboxId]`
92
- - This is the id you store in durable state and pass around.
93
- - All sandbox actions and helpers take this `sandboxId`.
94
-
95
- ### 2) `externalSandboxId` (provider id)
96
- - The id returned by the provider SDK (Vercel `sandbox.sandboxId`, Daytona `sandbox.id`)
97
- - Stored on the record as `externalSandboxId`
98
- - Used internally to reconnect via the provider SDK
99
-
100
- ---
101
-
102
- ## Schema integration
103
-
104
- In your app schema, include `sandboxDomain` along with other domains, then initialize Instant with the composed schema.
105
-
106
- ```ts
107
- import { domain } from "@ekairos/domain";
108
- import { sandboxDomain } from "@ekairos/sandbox";
109
- // import { storyDomain } from "@ekairos/story" (if you use stories)
110
- // import { datasetDomain } from "@ekairos/dataset" (if you use dataset)
111
-
112
- export const appDomain = domain("app")
113
- .includes(sandboxDomain)
114
- // .includes(storyDomain)
115
- // .includes(datasetDomain)
116
- .schema({
117
- entities: {},
118
- links: {},
119
- rooms: {},
120
- });
121
-
122
- export const schema = appDomain.toInstantSchema();
123
- ```
124
-
125
- ---
126
-
127
- ## Exports
20
+ ## Providers
128
21
 
129
- - `sandboxDomain` (schema domain + actions factory)
130
- - `SandboxService` (high-level service)
131
- - `runCommandInSandbox` (low-level helper for Vercel)
132
- - Types: `SandboxConfig`, `SandboxRecord`, `ServiceResult<T>`, `CommandResult`
22
+ - `vercel`
23
+ - `daytona`
24
+ - `sprites`
133
25
 
134
- ---
26
+ Provider selection:
135
27
 
136
- ## Quickstart
28
+ 1. `config.provider`
29
+ 2. `SANDBOX_PROVIDER`
30
+ 3. default provider
137
31
 
138
- ### 1) Instantiate the service
32
+ ## Quick example
139
33
 
140
34
  ```ts
141
- import { init } from "@instantdb/admin";
142
- import { sandboxDomain } from "@ekairos/sandbox";
143
-
144
- const db = init({
145
- appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID,
146
- adminToken: process.env.INSTANT_APP_ADMIN_TOKEN,
147
- schema: {}, // your composed schema that includes sandboxDomain
148
- });
35
+ const service = new SandboxService(db);
149
36
 
150
- const sandboxes = sandboxDomain(db);
151
- ```
152
-
153
- ### 2) Create a persisted sandbox
154
-
155
- ```ts
156
- const created = await sandboxes.createSandbox({
157
- provider: "daytona", // or set SANDBOX_PROVIDER=daytona
37
+ const created = await service.createSandbox({
38
+ provider: "vercel",
158
39
  runtime: "node22",
159
40
  timeoutMs: 10 * 60 * 1000,
160
- resources: { vcpus: 2 },
161
- purpose: "dataset-file-parse",
162
- params: { datasetId: "..." },
163
41
  });
164
42
 
165
43
  if (!created.ok) throw new Error(created.error);
166
- const { sandboxId } = created.data;
167
- ```
168
-
169
- ### 3) Run commands by `sandboxId`
170
-
171
- ```ts
172
- const sandbox = sandboxes.getSandbox(sandboxId);
173
- const res = await sandbox.runCommand("node", ["-e", "console.log('hello')"]);
174
- if (!res.ok) throw new Error(res.error);
175
- console.log(res.data.exitCode, res.data.output);
176
- ```
177
-
178
- ### 4) Reconnect (when you need the runtime object)
179
44
 
180
- ```ts
181
- const sandbox = sandboxes.getSandbox(sandboxId);
182
- const rec = await sandbox.reconnect();
183
- if (!rec.ok) throw new Error(rec.error);
184
-
185
- const { sandbox: providerSandbox } = rec.data;
186
- // Use provider-specific SDK features on providerSandbox
187
- ```
188
-
189
- ### 5) Stop (optional)
190
-
191
- ```ts
192
- const sandbox = sandboxes.getSandbox(sandboxId);
193
- await sandbox.stop();
45
+ const run = await service.runCommand(created.data.sandboxId, "node", ["-v"]);
194
46
  ```
195
47
 
196
- ---
197
-
198
- ## Provider selection rules
199
-
200
- Precedence:
201
- 1) `SandboxConfig.provider`
202
- 2) `SANDBOX_PROVIDER`
203
- 3) default: `sprites`
204
-
205
- ---
206
-
207
- ## Daytona provider details
48
+ ## Important ids
208
49
 
209
- ### Config mapping
50
+ - `sandboxId`: durable InstantDB record id
51
+ - `externalSandboxId`: provider-native sandbox id
210
52
 
211
- `SandboxConfig` accepts Daytona-specific options via `config.daytona`:
212
-
213
- ```ts
214
- {
215
- provider: "daytona",
216
- runtime: "node22", // used to infer language when daytona.language not set
217
- daytona: {
218
- language: "typescript" | "javascript" | "python",
219
- snapshot: "snapshot-id",
220
- image: "debian:12" | "...",
221
- envVars: { KEY: "value" },
222
- labels: { "app": "ekairos" },
223
- public: false,
224
- ephemeral: true,
225
- autoStopIntervalMin: 30,
226
- autoArchiveIntervalMin: 60,
227
- user: "daytona",
228
- volumes: [{ volumeId: "vol-123", mountPath: "/home/daytona/volume" }],
229
- }
230
- }
231
- ```
232
-
233
- ### Command execution
234
-
235
- For Daytona, `runCommand` uses `sandbox.process.executeCommand(...)` and returns:
236
-
237
- - `exitCode`
238
- - `output` (stdout)
239
- - `error` (stderr if available)
240
-
241
- ### File IO
242
-
243
- - `writeFiles` -> `sandbox.fs.uploadFiles(...)`
244
- - `readFile` -> `sandbox.fs.downloadFile(...)`
245
-
246
- ---
247
-
248
- ## Volumes (Daytona)
249
-
250
- Volumes are persistent FUSE mounts that can be attached to multiple sandboxes.
251
- They are ideal for caching datasets or large artifacts across runs.
252
-
253
- ### Create/get a volume
254
-
255
- ```ts
256
- import { Daytona } from "@daytonaio/sdk";
257
-
258
- const daytona = new Daytona();
259
- const volume = await daytona.volume.get("ekairos-ds-123", true);
260
- ```
261
-
262
- ### Mount a volume when creating a sandbox
263
-
264
- ```ts
265
- const created = await sandboxes.createSandbox({
266
- provider: "daytona",
267
- daytona: {
268
- // Either volumeId or volumeName can be provided.
269
- volumes: [{ volumeId: volume.id, mountPath: "/home/daytona/.ekairos" }],
270
- // volumes: [{ volumeName: "ekairos-ds-123", mountPath: "/home/daytona/.ekairos" }],
271
- },
272
- });
273
- ```
274
-
275
- ### Use the volume in the sandbox
276
-
277
- Once mounted, read/write like any other directory.
278
- Files written to a volume persist even after the sandbox is removed.
279
-
280
- ### Limitations
281
-
282
- - Volumes are FUSE-based and **slower** than the local sandbox filesystem.
283
- - Volumes are **not** block storage and are not suitable for databases.
284
- - For heavy processing, consider copying from the volume to local FS first.
285
-
286
- ---
287
-
288
- ## Volumes vs InstantDB files (how they relate)
289
-
290
- InstantDB storage (`$files`) is **durable object storage** (good for canonical datasets,
291
- outputs, and sharing data across services). Daytona volumes are **durable shared file mounts**
292
- optimized for **fast re-use inside sandboxes**.
293
-
294
- Think of it like this:
295
-
296
- - **InstantDB `$files`** is the source of truth and can be accessed by any service.
297
- - **Daytona volumes** are a performance layer to avoid re-downloading the same files into sandboxes.
298
-
299
- ### Recommended pattern
300
-
301
- 1) **Persist canonical files** in InstantDB `$files`.
302
- 2) **On sandbox start**, check a manifest in the volume:
303
- - If present and hashes match, **use volume data**.
304
- - If not, **download from InstantDB** and refresh the volume + manifest.
305
- 3) **Write output back to InstantDB** when you need durable sharing or indexing.
306
-
307
- ### Example manifest layout
308
-
309
- ```
310
- /home/daytona/.ekairos/datasets/{datasetId}/
311
- manifest.json
312
- raw/
313
- normalized/
314
- cache/
315
- ```
316
-
317
- ### Why both are needed
318
-
319
- - InstantDB guarantees durability, queryability, and cross-service access.
320
- - Volumes reduce cold-start and repeated downloads for sandbox workloads.
321
-
322
- ---
323
-
324
- ## Ephemeral sandboxes (Daytona)
325
-
326
- Set `daytona.ephemeral = true` to auto-delete a sandbox after it stops.
327
- Pair this with `autoStopIntervalMin` to avoid quota exhaustion from idle sandboxes.
328
-
329
- ```ts
330
- const created = await sandboxes.createSandbox({
331
- provider: "daytona",
332
- daytona: {
333
- ephemeral: true,
334
- autoStopIntervalMin: 5,
335
- },
336
- });
337
- ```
338
-
339
- ---
340
-
341
- ## Behavioral notes
342
-
343
- ### `createSandbox(config)`
344
- - Creates an InstantDB record `sandbox_sandboxes[sandboxId]` with status `"creating"`.
345
- - Provisions a provider sandbox (provider-specific).
346
- - Updates the record to status `"active"` and stores `externalSandboxId`.
347
-
348
- ### `reconnectToSandbox(sandboxId)`
349
- - Loads the record by internal `sandboxId`.
350
- - Validates:
351
- - record exists
352
- - `externalSandboxId` exists
353
- - Reconnects using the provider SDK/client (provider-specific).
354
- - Returns `ok: false` if sandbox is not found/not running.
355
- - If reconnection fails and the record was `"active"`, it may mark the record as `"shutdown"`.
356
-
357
- ### `runCommand(sandboxId, command, args?)`
358
- - Durable-friendly command execution.
359
- - Attempts to reconnect; if unavailable it may recreate the sandbox from the stored record configuration and retry.
360
- - Returns a capped output payload suitable for storing in logs.
361
-
362
- ### `stopSandbox(sandboxId)`
363
- - Attempts to reconnect and stop the provider sandbox.
364
- - Marks the record as `"shutdown"` regardless (the provider sandbox may already be gone).
365
-
366
- ---
367
-
368
- ## Providers
369
-
370
- ### Daytona (current)
371
-
372
- Environment variables:
373
- - `DAYTONA_API_URL`
374
- - `DAYTONA_API_KEY` or `DAYTONA_JWT_TOKEN + DAYTONA_ORGANIZATION_ID`
375
- - `DAYTONA_TARGET` (optional)
376
-
377
- Behavior notes:
378
- - `externalSandboxId` maps to Daytona `sandbox.id`.
379
- - Reconnect uses `daytona.get(id)` and starts if not running.
380
- - File IO uses `sandbox.fs`.
381
- - Command execution uses `sandbox.process.executeCommand`.
382
-
383
- ### Local Daytona OSS (Docker Desktop / Windows)
384
-
385
- We keep the Daytona OSS repo **outside** this workspace to avoid nested repos.
386
- Use the helper script in `./scripts/daytona-local.ps1` to clone and run the official
387
- Docker Compose stack.
388
-
389
- ```powershell
390
- # clone once (pin a ref for repeatability)
391
- powershell -ExecutionPolicy Bypass -File .\scripts\daytona-local.ps1 init -Ref <tag-or-commit>
392
-
393
- # start / stop
394
- powershell -ExecutionPolicy Bypass -File .\scripts\daytona-local.ps1 up
395
- powershell -ExecutionPolicy Bypass -File .\scripts\daytona-local.ps1 down
396
- ```
397
-
398
- Defaults and overrides:
399
- - Default clone path: `%USERPROFILE%\.ekairos\daytona-oss`
400
- - Override with `DAYTONA_OSS_HOME`
401
- - Pin a specific version with `DAYTONA_OSS_REF`
402
-
403
- Environment variables for local usage:
404
-
405
- ```bash
406
- SANDBOX_PROVIDER=daytona
407
- DAYTONA_API_URL=http://localhost:3000/api
408
- DAYTONA_API_KEY=... # create in the local Daytona dashboard (http://localhost:3000)
409
- ```
410
-
411
- Optional: if you need proxy/preview URLs, Windows needs wildcard DNS for `*.proxy.localhost`.
412
- You can run Daytona's `scripts/setup-proxy-dns.sh` inside WSL or use a local DNS tool.
413
- This is not required for API-only usage.
414
-
415
- ### Vercel
416
-
417
- Environment variables:
418
- - `SANDBOX_VERCEL_TEAM_ID`
419
- - `SANDBOX_VERCEL_PROJECT_ID`
420
- - `SANDBOX_VERCEL_TOKEN`
421
-
422
- Behavior notes:
423
- - `externalSandboxId` maps to Vercel `sandbox.sandboxId`.
424
- - Reconnect is done via `Sandbox.get(...)` using the stored `externalSandboxId`.
425
-
426
- ---
427
-
428
- ## Dev local (Daytona OSS en Docker Desktop)
429
-
430
- ### 1) Levantar Daytona local
431
-
432
- Usa el helper para clonar el repo de Daytona (fuera del workspace) y levantar el stack:
433
-
434
- ```powershell
435
- powershell -ExecutionPolicy Bypass -File .\scripts\daytona-local.ps1 init
436
- powershell -ExecutionPolicy Bypass -File .\scripts\daytona-local.ps1 up
437
- ```
438
-
439
- Dashboard local: `http://localhost:3000`
440
-
441
- Credenciales (dev):
442
- - usuario: `dev@daytona.io`
443
- - password: `password`
444
-
445
- ### 2) Crear API key manualmente
446
-
447
- En el dashboard, ve a **API Keys** y crea una key. Luego configura tu app:
53
+ ## Tests
448
54
 
449
- ```bash
450
- SANDBOX_PROVIDER=daytona
451
- DAYTONA_API_URL=http://localhost:3000/api
452
- DAYTONA_API_KEY=...tu_api_key_local...
453
- ```
454
-
455
- Notas:
456
- - Guarda la key localmente; **no la comitees**.
457
- - Si necesitas proxy/preview en Windows, configura `*.proxy.localhost` (ver README de Daytona OSS).
458
-
459
- ---
460
-
461
- ## Development notes
462
-
463
- - Prefer `runCommand(sandboxId, ...)` for provider-agnostic usage.
464
- - Only `reconnect()` when you need direct provider SDK features.
465
- - Avoid storing secrets in `params`.
466
- - When using volumes, include a manifest/versioning strategy.
467
-
468
- ---
469
-
470
- ## Testing
471
-
472
- A smoke test exists in:
473
- - `packages/sandbox/src/tests/sandbox.temp-app.test.ts`
474
-
475
- It:
476
- - Creates a temporary Instant app via `instant-cli`.
477
- - Pushes a minimal schema with `sandboxDomain`.
478
- - Creates a sandbox (Daytona) and runs a simple command.
479
-
480
- Run:
481
55
  ```bash
482
56
  pnpm --filter @ekairos/sandbox test
483
57
  ```
484
-
485
- ---
486
-
487
- ## Roadmap
488
-
489
- - Snapshot/image presets for faster cold-start.
490
- - Volume GC policy.
491
- - Preview proxy on custom domain.
492
-
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAGjE,eAAO,MAAM,aAAa,EAAE,kBAoB1B,CAAA"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAGjE,eAAO,MAAM,aAAa,EAAE,kBAkC1B,CAAA"}
package/dist/schema.js CHANGED
@@ -5,6 +5,7 @@ export const sandboxDomain = domain("sandbox").schema({
5
5
  entities: {
6
6
  sandbox_sandboxes: i.entity({
7
7
  externalSandboxId: i.string().optional().indexed(),
8
+ sandboxUserId: i.string().optional().indexed(),
8
9
  provider: i.string().indexed(),
9
10
  sandboxUrl: i.string().optional(),
10
11
  status: i.string().indexed(),
@@ -19,7 +20,20 @@ export const sandboxDomain = domain("sandbox").schema({
19
20
  shutdownAt: i.number().optional().indexed(),
20
21
  }),
21
22
  },
22
- links: {},
23
+ links: {
24
+ sandbox_user: {
25
+ forward: {
26
+ on: "sandbox_sandboxes",
27
+ has: "one",
28
+ label: "user",
29
+ },
30
+ reverse: {
31
+ on: "$users",
32
+ has: "many",
33
+ label: "sandboxes",
34
+ },
35
+ },
36
+ },
23
37
  rooms: {},
24
38
  });
25
39
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAA;AACnC,OAAO,EAAE,MAAM,EAA2B,MAAM,iBAAiB,CAAA;AAEjE,0DAA0D;AAC1D,MAAM,CAAC,MAAM,aAAa,GAAuB,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IACxE,QAAQ,EAAE;QACR,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC;YAC1B,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;YAClD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;YAC9B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACjC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;YAC5B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC9B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC5B,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;YAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;YACxC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;YAC3B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;YAC/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;YAC1C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;SAC5C,CAAC;KACH;IACD,KAAK,EAAE,EAAE;IACT,KAAK,EAAE,EAAE;CACV,CAAC,CAAA"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAA;AACnC,OAAO,EAAE,MAAM,EAA2B,MAAM,iBAAiB,CAAA;AAEjE,0DAA0D;AAC1D,MAAM,CAAC,MAAM,aAAa,GAAuB,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IACxE,QAAQ,EAAE;QACR,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC;YAC1B,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;YAClD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;YAC9C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;YAC9B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACjC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;YAC5B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC9B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC5B,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;YAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;YACxC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;YAC3B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;YAC/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;YAC1C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;SAC5C,CAAC;KACH;IACD,KAAK,EAAE;QACL,YAAY,EAAE;YACZ,OAAO,EAAE;gBACP,EAAE,EAAE,mBAAmB;gBACvB,GAAG,EAAE,KAAK;gBACV,KAAK,EAAE,MAAM;aACd;YACD,OAAO,EAAE;gBACP,EAAE,EAAE,QAAQ;gBACZ,GAAG,EAAE,MAAM;gBACX,KAAK,EAAE,WAAW;aACnB;SACF;KACF;IACD,KAAK,EAAE,EAAE;CACV,CAAC,CAAA"}
package/dist/service.d.ts CHANGED
@@ -9,6 +9,7 @@ type SandboxSchemaType = SchemaOf<typeof sandboxDomain>;
9
9
  export interface SandboxRecord {
10
10
  id: string;
11
11
  externalSandboxId?: string;
12
+ sandboxUserId?: string;
12
13
  provider: string;
13
14
  sandboxUrl?: string;
14
15
  status: "creating" | "active" | "shutdown" | "error" | "recreating";
@@ -44,6 +45,23 @@ export declare class SandboxService {
44
45
  private adminDb;
45
46
  constructor(db: InstantAdminDatabase<SandboxSchemaType>);
46
47
  private static getVercelCredentials;
48
+ private static getDomainName;
49
+ private static getDomainContextString;
50
+ private static cloneJson;
51
+ private static buildEkairosNetworkPolicy;
52
+ private static buildEkairosManifest;
53
+ private static buildEkairosRuntimeFiles;
54
+ private static resolveInstantUserIdByRefreshToken;
55
+ private static resolveEkairosBootstrap;
56
+ private static bootstrapEkairosFiles;
57
+ private static safeMkDir;
58
+ private static buildSkillInstallSet;
59
+ private static bootstrapSkills;
60
+ private static resolveVercelWorkingDirectory;
61
+ private static findLinkedVercelProjectFile;
62
+ private static readLinkedVercelProject;
63
+ private static pullVercelOidcToken;
64
+ private static resolveVercelCredentials;
47
65
  private static provisionVercelSandbox;
48
66
  private static getDaytonaConfig;
49
67
  private static normalizeBaseUrl;
@@ -71,7 +89,9 @@ export declare class SandboxService {
71
89
  reconnectToSandbox(sandboxId: string): Promise<ServiceResult<{
72
90
  sandbox: ProviderSandbox;
73
91
  }>>;
92
+ private getSandboxRecord;
74
93
  stopSandbox(sandboxId: string): Promise<ServiceResult<void>>;
94
+ query(sandboxId: string, query: Record<string, any>): Promise<ServiceResult<any>>;
75
95
  runCommand(sandboxId: string, command: string, args?: string[]): Promise<ServiceResult<CommandResult>>;
76
96
  writeFiles(sandboxId: string, files: Array<{
77
97
  path: string;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}