@electric-agent/studio 1.13.1 → 1.14.2

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 (64) hide show
  1. package/dist/bridge/message-parser.d.ts +3 -3
  2. package/dist/bridge/message-parser.d.ts.map +1 -1
  3. package/dist/bridge/message-parser.js +3 -3
  4. package/dist/bridge/message-parser.js.map +1 -1
  5. package/dist/client/assets/{index-IvCtVUfs.css → index-BSGS-yya.css} +1 -1
  6. package/dist/client/assets/{index-BXdgNRgB.js → index-qUqEqKXn.js} +35 -35
  7. package/dist/client/index.html +2 -2
  8. package/dist/room-router.d.ts +13 -0
  9. package/dist/room-router.d.ts.map +1 -1
  10. package/dist/room-router.js +29 -1
  11. package/dist/room-router.js.map +1 -1
  12. package/dist/server.d.ts +2 -4
  13. package/dist/server.d.ts.map +1 -1
  14. package/dist/server.js +60 -68
  15. package/dist/server.js.map +1 -1
  16. package/package.json +7 -2
  17. package/dist/bridge/codex-docker.d.ts +0 -70
  18. package/dist/bridge/codex-docker.d.ts.map +0 -1
  19. package/dist/bridge/codex-docker.js +0 -234
  20. package/dist/bridge/codex-docker.js.map +0 -1
  21. package/dist/bridge/codex-json-parser.d.ts +0 -31
  22. package/dist/bridge/codex-json-parser.d.ts.map +0 -1
  23. package/dist/bridge/codex-json-parser.js +0 -267
  24. package/dist/bridge/codex-json-parser.js.map +0 -1
  25. package/dist/bridge/codex-md-generator.d.ts +0 -14
  26. package/dist/bridge/codex-md-generator.d.ts.map +0 -1
  27. package/dist/bridge/codex-md-generator.js +0 -55
  28. package/dist/bridge/codex-md-generator.js.map +0 -1
  29. package/dist/bridge/codex-sprites.d.ts +0 -64
  30. package/dist/bridge/codex-sprites.d.ts.map +0 -1
  31. package/dist/bridge/codex-sprites.js +0 -227
  32. package/dist/bridge/codex-sprites.js.map +0 -1
  33. package/dist/bridge/daytona.d.ts +0 -35
  34. package/dist/bridge/daytona.d.ts.map +0 -1
  35. package/dist/bridge/daytona.js +0 -141
  36. package/dist/bridge/daytona.js.map +0 -1
  37. package/dist/bridge/docker-stdio.d.ts +0 -30
  38. package/dist/bridge/docker-stdio.d.ts.map +0 -1
  39. package/dist/bridge/docker-stdio.js +0 -135
  40. package/dist/bridge/docker-stdio.js.map +0 -1
  41. package/dist/bridge/sprites.d.ts +0 -32
  42. package/dist/bridge/sprites.d.ts.map +0 -1
  43. package/dist/bridge/sprites.js +0 -133
  44. package/dist/bridge/sprites.js.map +0 -1
  45. package/dist/github-app.test.d.ts +0 -2
  46. package/dist/github-app.test.d.ts.map +0 -1
  47. package/dist/github-app.test.js +0 -62
  48. package/dist/github-app.test.js.map +0 -1
  49. package/dist/sandbox/daytona-push.d.ts +0 -3
  50. package/dist/sandbox/daytona-push.d.ts.map +0 -1
  51. package/dist/sandbox/daytona-push.js +0 -56
  52. package/dist/sandbox/daytona-push.js.map +0 -1
  53. package/dist/sandbox/daytona-registry.d.ts +0 -41
  54. package/dist/sandbox/daytona-registry.d.ts.map +0 -1
  55. package/dist/sandbox/daytona-registry.js +0 -127
  56. package/dist/sandbox/daytona-registry.js.map +0 -1
  57. package/dist/sandbox/daytona.d.ts +0 -41
  58. package/dist/sandbox/daytona.d.ts.map +0 -1
  59. package/dist/sandbox/daytona.js +0 -282
  60. package/dist/sandbox/daytona.js.map +0 -1
  61. package/dist/shared-sessions.d.ts +0 -16
  62. package/dist/shared-sessions.d.ts.map +0 -1
  63. package/dist/shared-sessions.js +0 -52
  64. package/dist/shared-sessions.js.map +0 -1
@@ -1,135 +0,0 @@
1
- /**
2
- * SessionBridge implementation that communicates with a Docker container
3
- * via stdin/stdout NDJSON using `docker exec -i`.
4
- *
5
- * The server bridges between the Durable Stream (for UI events) and
6
- * the container's stdin/stdout (for agent communication).
7
- */
8
- import { spawn } from "node:child_process"
9
- import * as readline from "node:readline"
10
- import { DurableStream } from "@durable-streams/client"
11
- export class DockerStdioBridge {
12
- sessionId
13
- streamUrl
14
- streamHeaders
15
- containerId
16
- writer
17
- agentEventCallbacks = []
18
- completeCallbacks = []
19
- closed = false
20
- proc = null
21
- constructor(sessionId, connection, containerId) {
22
- this.sessionId = sessionId
23
- this.streamUrl = connection.url
24
- this.streamHeaders = connection.headers
25
- this.containerId = containerId
26
- this.writer = new DurableStream({
27
- url: connection.url,
28
- headers: connection.headers,
29
- contentType: "application/json",
30
- })
31
- }
32
- async emit(event) {
33
- if (this.closed) return
34
- const msg = { source: "server", ...event }
35
- await this.writer.append(JSON.stringify(msg))
36
- }
37
- async sendCommand(cmd) {
38
- if (this.closed || !this.proc?.stdin?.writable) return
39
- const line = JSON.stringify({ type: "command", ...cmd })
40
- this.proc.stdin.write(`${line}\n`)
41
- }
42
- async sendGateResponse(gate, value) {
43
- if (this.closed || !this.proc?.stdin?.writable) return
44
- const line = JSON.stringify({ type: "gate_response", gate, ...value })
45
- this.proc.stdin.write(`${line}\n`)
46
- }
47
- onAgentEvent(cb) {
48
- this.agentEventCallbacks.push(cb)
49
- }
50
- onComplete(cb) {
51
- this.completeCallbacks.push(cb)
52
- }
53
- async start() {
54
- if (this.closed) return
55
- // Spawn docker exec with stdin piped
56
- this.proc = spawn("docker", ["exec", "-i", this.containerId, "electric-agent", "headless"], {
57
- stdio: ["pipe", "pipe", "pipe"],
58
- })
59
- console.log(
60
- `[docker-stdio-bridge] Agent started: session=${this.sessionId} container=${this.containerId} pid=${this.proc.pid}`,
61
- )
62
- // Read stdout line by line (NDJSON)
63
- if (this.proc.stdout) {
64
- const rl = readline.createInterface({
65
- input: this.proc.stdout,
66
- terminal: false,
67
- })
68
- rl.on("line", (line) => {
69
- if (this.closed) return
70
- const trimmed = line.trim()
71
- if (!trimmed) return
72
- let event
73
- try {
74
- event = JSON.parse(trimmed)
75
- } catch {
76
- console.log(`[docker-stdio-bridge] Non-JSON stdout: ${trimmed}`)
77
- return
78
- }
79
- // Write to Durable Stream for UI
80
- const msg = { source: "agent", ...event }
81
- this.writer.append(JSON.stringify(msg)).catch(() => {})
82
- // Dispatch to callbacks
83
- for (const cb of this.agentEventCallbacks) {
84
- try {
85
- cb(event)
86
- } catch {
87
- // Swallow callback errors
88
- }
89
- }
90
- // Detect session_end
91
- if (event.type === "session_end" && "success" in event) {
92
- const success = event.success
93
- for (const cb of this.completeCallbacks) {
94
- try {
95
- cb(success)
96
- } catch {
97
- // Swallow callback errors
98
- }
99
- }
100
- }
101
- })
102
- }
103
- // Log stderr
104
- if (this.proc.stderr) {
105
- const stderrRl = readline.createInterface({
106
- input: this.proc.stderr,
107
- terminal: false,
108
- })
109
- stderrRl.on("line", (line) => {
110
- if (!this.closed) {
111
- console.error(`[docker-stdio-bridge:stderr] ${line}`)
112
- }
113
- })
114
- }
115
- // Handle process exit
116
- this.proc.on("exit", (code) => {
117
- console.log(
118
- `[docker-stdio-bridge] Agent process exited: code=${code} session=${this.sessionId}`,
119
- )
120
- })
121
- }
122
- close() {
123
- this.closed = true
124
- if (this.proc) {
125
- try {
126
- this.proc.stdin?.end()
127
- this.proc.kill("SIGTERM")
128
- } catch {
129
- // Process may already be dead
130
- }
131
- this.proc = null
132
- }
133
- }
134
- }
135
- //# sourceMappingURL=docker-stdio.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"docker-stdio.js","sourceRoot":"","sources":["../../src/bridge/docker-stdio.ts"],"names":[],"mappings":"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"}
@@ -1,32 +0,0 @@
1
- /**
2
- * SessionBridge implementation that communicates with a Sprites sandbox
3
- * via the Sprites SDK session API (stdin/stdout NDJSON).
4
- *
5
- * The server bridges between the Durable Stream (for UI events) and
6
- * the Sprites session (for agent communication). The agent inside the
7
- * sprite uses the stdio adapter — the bridge relays events to the stream.
8
- */
9
- import type { EngineEvent } from "@electric-agent/protocol"
10
- import type { Sprite } from "@fly/sprites"
11
- import type { StreamConnectionInfo } from "../streams.js"
12
- import type { SessionBridge } from "./types.js"
13
- export declare class SpritesStdioBridge implements SessionBridge {
14
- readonly sessionId: string
15
- readonly streamUrl: string
16
- readonly streamHeaders: Record<string, string>
17
- private sprite
18
- private writer
19
- private agentEventCallbacks
20
- private completeCallbacks
21
- private closed
22
- private cmd
23
- constructor(sessionId: string, connection: StreamConnectionInfo, sprite: Sprite)
24
- emit(event: EngineEvent): Promise<void>
25
- sendCommand(cmd: Record<string, unknown>): Promise<void>
26
- sendGateResponse(gate: string, value: Record<string, unknown>): Promise<void>
27
- onAgentEvent(cb: (event: EngineEvent) => void): void
28
- onComplete(cb: (success: boolean) => void): void
29
- start(): Promise<void>
30
- close(): void
31
- }
32
- //# sourceMappingURL=sprites.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sprites.d.ts","sourceRoot":"","sources":["../../src/bridge/sprites.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,cAAc,CAAA;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAI9D,qBAAa,kBAAmB,YAAW,aAAa;IACvD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAE9C,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,mBAAmB,CAA0C;IACrE,OAAO,CAAC,iBAAiB,CAAwC;IACjE,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,GAAG,CAA6B;gBAE5B,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM;IAazE,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvC,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxD,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnF,YAAY,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IAIpD,UAAU,CAAC,EAAE,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAI1C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA6E5B,KAAK,IAAI,IAAI;CAWb"}
@@ -1,133 +0,0 @@
1
- /**
2
- * SessionBridge implementation that communicates with a Sprites sandbox
3
- * via the Sprites SDK session API (stdin/stdout NDJSON).
4
- *
5
- * The server bridges between the Durable Stream (for UI events) and
6
- * the Sprites session (for agent communication). The agent inside the
7
- * sprite uses the stdio adapter — the bridge relays events to the stream.
8
- */
9
- import * as readline from "node:readline"
10
- import { DurableStream } from "@durable-streams/client"
11
-
12
- const SPRITES_SESSION_ID = "agent-session"
13
- export class SpritesStdioBridge {
14
- sessionId
15
- streamUrl
16
- streamHeaders
17
- sprite
18
- writer
19
- agentEventCallbacks = []
20
- completeCallbacks = []
21
- closed = false
22
- cmd = null
23
- constructor(sessionId, connection, sprite) {
24
- this.sessionId = sessionId
25
- this.streamUrl = connection.url
26
- this.streamHeaders = connection.headers
27
- this.sprite = sprite
28
- this.writer = new DurableStream({
29
- url: connection.url,
30
- headers: connection.headers,
31
- contentType: "application/json",
32
- })
33
- }
34
- async emit(event) {
35
- if (this.closed) return
36
- const msg = { source: "server", ...event }
37
- await this.writer.append(JSON.stringify(msg))
38
- }
39
- async sendCommand(cmd) {
40
- if (this.closed || !this.cmd) return
41
- const line = JSON.stringify({ type: "command", ...cmd })
42
- this.cmd.stdin.write(`${line}\n`)
43
- }
44
- async sendGateResponse(gate, value) {
45
- if (this.closed || !this.cmd) return
46
- const line = JSON.stringify({ type: "gate_response", gate, ...value })
47
- this.cmd.stdin.write(`${line}\n`)
48
- }
49
- onAgentEvent(cb) {
50
- this.agentEventCallbacks.push(cb)
51
- }
52
- onComplete(cb) {
53
- this.completeCallbacks.push(cb)
54
- }
55
- async start() {
56
- if (this.closed) return
57
- // Create a persistent session in the sprite so we can reconnect if needed
58
- this.cmd = this.sprite.createSession(
59
- "bash",
60
- [
61
- "-c",
62
- "source /etc/profile.d/npm-global.sh 2>/dev/null; source /etc/profile.d/electric-agent.sh && electric-agent headless",
63
- ],
64
- { detachable: true, sessionId: SPRITES_SESSION_ID },
65
- )
66
- console.log(`[sprites-bridge] Agent started: session=${this.sessionId}`)
67
- // Read stdout line by line (NDJSON)
68
- const rl = readline.createInterface({
69
- input: this.cmd.stdout,
70
- terminal: false,
71
- })
72
- rl.on("line", (line) => {
73
- if (this.closed) return
74
- const trimmed = line.trim()
75
- if (!trimmed) return
76
- let event
77
- try {
78
- event = JSON.parse(trimmed)
79
- } catch {
80
- console.log(`[sprites-bridge] Non-JSON stdout: ${trimmed}`)
81
- return
82
- }
83
- // Write to Durable Stream for UI
84
- const msg = { source: "agent", ...event }
85
- this.writer.append(JSON.stringify(msg)).catch(() => {})
86
- // Dispatch to callbacks
87
- for (const cb of this.agentEventCallbacks) {
88
- try {
89
- cb(event)
90
- } catch {
91
- // Swallow callback errors
92
- }
93
- }
94
- // Detect session_end
95
- if (event.type === "session_end" && "success" in event) {
96
- const success = event.success
97
- for (const cb of this.completeCallbacks) {
98
- try {
99
- cb(success)
100
- } catch {
101
- // Swallow callback errors
102
- }
103
- }
104
- }
105
- })
106
- // Log stderr
107
- const stderrRl = readline.createInterface({
108
- input: this.cmd.stderr,
109
- terminal: false,
110
- })
111
- stderrRl.on("line", (line) => {
112
- if (!this.closed) {
113
- console.error(`[sprites-bridge:stderr] ${line}`)
114
- }
115
- })
116
- // Handle process exit
117
- this.cmd.on("exit", (code) => {
118
- console.log(`[sprites-bridge] Agent process exited: code=${code} session=${this.sessionId}`)
119
- })
120
- }
121
- close() {
122
- this.closed = true
123
- if (this.cmd) {
124
- try {
125
- this.cmd.kill()
126
- } catch {
127
- // Process may already be dead
128
- }
129
- this.cmd = null
130
- }
131
- }
132
- }
133
- //# sourceMappingURL=sprites.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sprites.js","sourceRoot":"","sources":["../../src/bridge/sprites.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=github-app.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"github-app.test.d.ts","sourceRoot":"","sources":["../src/github-app.test.ts"],"names":[],"mappings":""}
@@ -1,62 +0,0 @@
1
- import { describe, it, expect, vi } from "vitest";
2
- import crypto from "node:crypto";
3
- const { privateKey } = crypto.generateKeyPairSync("rsa", {
4
- modulusLength: 2048,
5
- privateKeyEncoding: { type: "pkcs8", format: "pem" },
6
- publicKeyEncoding: { type: "spki", format: "pem" },
7
- });
8
- describe("github-app", () => {
9
- describe("createGitHubAppJWT", () => {
10
- it("creates a valid JWT with correct claims", async () => {
11
- const { createGitHubAppJWT } = await import("./github-app.js");
12
- const jwt = createGitHubAppJWT("12345", privateKey);
13
- const parts = jwt.split(".");
14
- expect(parts).toHaveLength(3);
15
- const header = JSON.parse(Buffer.from(parts[0], "base64url").toString());
16
- expect(header).toEqual({ alg: "RS256", typ: "JWT" });
17
- const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
18
- expect(payload.iss).toBe("12345");
19
- expect(payload.exp).toBeGreaterThan(payload.iat);
20
- expect(payload.exp - payload.iat).toBe(660); // 600s expiry + 60s clock drift offset
21
- });
22
- });
23
- describe("getInstallationToken", () => {
24
- it("exchanges JWT for installation token", async () => {
25
- const mockFetch = vi.fn().mockResolvedValue({
26
- ok: true,
27
- json: () => Promise.resolve({
28
- token: "ghs_test123",
29
- expires_at: "2026-03-12T12:00:00Z",
30
- }),
31
- });
32
- vi.stubGlobal("fetch", mockFetch);
33
- const { getInstallationToken } = await import("./github-app.js");
34
- const result = await getInstallationToken("12345", "67890", privateKey);
35
- expect(result.token).toBe("ghs_test123");
36
- expect(result.expires_at).toBe("2026-03-12T12:00:00Z");
37
- const [url, opts] = mockFetch.mock.calls[0];
38
- expect(url).toBe("https://api.github.com/app/installations/67890/access_tokens");
39
- expect(opts.method).toBe("POST");
40
- expect(opts.headers.Accept).toBe("application/vnd.github+json");
41
- expect(opts.headers.Authorization).toMatch(/^Bearer ey/);
42
- const body = JSON.parse(opts.body);
43
- expect(body.permissions).toEqual({
44
- contents: "write",
45
- administration: "write",
46
- });
47
- vi.unstubAllGlobals();
48
- });
49
- it("throws on GitHub API error", async () => {
50
- const mockFetch = vi.fn().mockResolvedValue({
51
- ok: false,
52
- status: 401,
53
- text: () => Promise.resolve("Bad credentials"),
54
- });
55
- vi.stubGlobal("fetch", mockFetch);
56
- const { getInstallationToken } = await import("./github-app.js");
57
- await expect(getInstallationToken("12345", "67890", privateKey)).rejects.toThrow("GitHub API error 401");
58
- vi.unstubAllGlobals();
59
- });
60
- });
61
- });
62
- //# sourceMappingURL=github-app.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"github-app.test.js","sourceRoot":"","sources":["../src/github-app.test.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env tsx
2
- import "dotenv/config";
3
- //# sourceMappingURL=daytona-push.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"daytona-push.d.ts","sourceRoot":"","sources":["../../src/sandbox/daytona-push.ts"],"names":[],"mappings":";AAiBA,OAAO,eAAe,CAAA"}
@@ -1,56 +0,0 @@
1
- #!/usr/bin/env tsx
2
- /**
3
- * CLI script to build a linux/amd64 sandbox image, push it to Daytona's
4
- * transient registry, and create a snapshot.
5
- *
6
- * Required env vars:
7
- * DAYTONA_API_KEY — Daytona API key
8
- *
9
- * Optional:
10
- * DAYTONA_API_URL — Daytona API URL (default: https://app.daytona.io/api)
11
- * DAYTONA_TARGET — Daytona target region (default: eu)
12
- * SANDBOX_IMAGE — Local image name (default: electric-agent-sandbox)
13
- *
14
- * Usage:
15
- * npm run push:sandbox:daytona
16
- */
17
- import { execSync } from "node:child_process";
18
- import "dotenv/config";
19
- import { Daytona } from "@daytonaio/sdk";
20
- import { ensureSnapshot } from "./daytona-registry.js";
21
- async function main() {
22
- const apiKey = process.env.DAYTONA_API_KEY;
23
- if (!apiKey) {
24
- console.error("Error: DAYTONA_API_KEY environment variable is required.");
25
- process.exit(1);
26
- }
27
- const apiUrl = process.env.DAYTONA_API_URL ?? "https://app.daytona.io/api";
28
- const target = process.env.DAYTONA_TARGET ?? "eu";
29
- const localImage = process.env.SANDBOX_IMAGE || "electric-agent-sandbox";
30
- // Build linux/amd64 image (Daytona requires x86)
31
- console.log(`Building ${localImage} for linux/amd64...`);
32
- execSync(`docker build --platform linux/amd64 -f Dockerfile.sandbox -t ${localImage} .`, {
33
- stdio: "inherit",
34
- timeout: 600_000,
35
- });
36
- console.log();
37
- console.log(`Pushing sandbox image "${localImage}" to Daytona...`);
38
- console.log(` API URL: ${apiUrl}`);
39
- console.log(` Target: ${target}`);
40
- console.log();
41
- const daytona = new Daytona({ apiKey, apiUrl, target });
42
- const snapshotName = await ensureSnapshot(daytona, {
43
- apiKey,
44
- apiUrl,
45
- localImage,
46
- });
47
- console.log();
48
- console.log(`Snapshot ready: "${snapshotName}"`);
49
- console.log("Sandboxes will now use this snapshot automatically.");
50
- process.exit(0);
51
- }
52
- main().catch((err) => {
53
- console.error("Failed to push sandbox image:", err);
54
- process.exit(1);
55
- });
56
- //# sourceMappingURL=daytona-push.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"daytona-push.js","sourceRoot":"","sources":["../../src/sandbox/daytona-push.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,eAAe,CAAA;AACtB,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEtD,KAAK,UAAU,IAAI;IAClB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAA;IAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAA;QACzE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAChB,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,4BAA4B,CAAA;IAC1E,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,CAAA;IACjD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,wBAAwB,CAAA;IAExE,iDAAiD;IACjD,OAAO,CAAC,GAAG,CAAC,YAAY,UAAU,qBAAqB,CAAC,CAAA;IACxD,QAAQ,CAAC,gEAAgE,UAAU,IAAI,EAAE;QACxF,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,OAAO;KAChB,CAAC,CAAA;IACF,OAAO,CAAC,GAAG,EAAE,CAAA;IAEb,OAAO,CAAC,GAAG,CAAC,0BAA0B,UAAU,iBAAiB,CAAC,CAAA;IAClE,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,EAAE,CAAC,CAAA;IACnC,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,EAAE,CAAC,CAAA;IACnC,OAAO,CAAC,GAAG,EAAE,CAAA;IAEb,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAEvD,MAAM,YAAY,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE;QAClD,MAAM;QACN,MAAM;QACN,UAAU;KACV,CAAC,CAAA;IAEF,OAAO,CAAC,GAAG,EAAE,CAAA;IACb,OAAO,CAAC,GAAG,CAAC,oBAAoB,YAAY,GAAG,CAAC,CAAA;IAChD,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAA;IAElE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAChB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACpB,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAA;IACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAChB,CAAC,CAAC,CAAA"}
@@ -1,41 +0,0 @@
1
- import type { Daytona } from "@daytonaio/sdk";
2
- export interface PushImageOpts {
3
- apiKey: string;
4
- apiUrl?: string;
5
- localImage?: string;
6
- }
7
- export interface PushImageResult {
8
- remoteImage: string;
9
- registryUrl: string;
10
- project: string;
11
- }
12
- /**
13
- * Push a local Docker image to Daytona's transient registry.
14
- *
15
- * 1. Gets temporary push credentials via `DockerRegistryApi.getTransientPushAccess()`
16
- * 2. Tags the local image with the remote registry path
17
- * 3. Logs in, pushes, and logs out
18
- */
19
- export declare function pushImageToDaytona(opts: PushImageOpts): Promise<PushImageResult>;
20
- export interface EnsureSnapshotOpts {
21
- apiKey: string;
22
- apiUrl?: string;
23
- localImage?: string;
24
- /** Callback for snapshot creation logs */
25
- onLogs?: (chunk: string) => void;
26
- }
27
- /**
28
- * Ensure a Daytona snapshot exists for the sandbox image.
29
- *
30
- * - If a snapshot with the expected name already exists and is active, returns its name.
31
- * - Otherwise, pushes the local image to the transient registry and creates a snapshot.
32
- */
33
- export declare function ensureSnapshot(daytona: Daytona, opts: EnsureSnapshotOpts): Promise<string>;
34
- /**
35
- * Check if a snapshot exists and is active (non-throwing).
36
- */
37
- export declare function getSnapshotStatus(daytona: Daytona, snapshotName?: string): Promise<{
38
- exists: boolean;
39
- state?: string;
40
- }>;
41
- //# sourceMappingURL=daytona-registry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"daytona-registry.d.ts","sourceRoot":"","sources":["../../src/sandbox/daytona-registry.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAoB7C,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,eAAe;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAgDtF;AAED,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2ChG;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACtC,OAAO,EAAE,OAAO,EAChB,YAAY,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAQ9C"}
@@ -1,127 +0,0 @@
1
- import { execSync } from "node:child_process";
2
- import { readFileSync } from "node:fs";
3
- import { dirname, resolve } from "node:path";
4
- import { fileURLToPath } from "node:url";
5
- import { Configuration, DockerRegistryApi } from "@daytonaio/api-client";
6
- // ---------------------------------------------------------------------------
7
- // Daytona Transient Registry — push local images + create snapshots
8
- // ---------------------------------------------------------------------------
9
- const SANDBOX_IMAGE = process.env.SANDBOX_IMAGE || "electric-agent-sandbox";
10
- function getPackageVersion() {
11
- try {
12
- const __filename = fileURLToPath(import.meta.url);
13
- const __dirname = dirname(__filename);
14
- const pkgPath = resolve(__dirname, "../../../package.json");
15
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
16
- return pkg.version || "0.1.0";
17
- }
18
- catch {
19
- return "0.1.0";
20
- }
21
- }
22
- /**
23
- * Push a local Docker image to Daytona's transient registry.
24
- *
25
- * 1. Gets temporary push credentials via `DockerRegistryApi.getTransientPushAccess()`
26
- * 2. Tags the local image with the remote registry path
27
- * 3. Logs in, pushes, and logs out
28
- */
29
- export async function pushImageToDaytona(opts) {
30
- const localImage = opts.localImage ?? SANDBOX_IMAGE;
31
- const apiUrl = opts.apiUrl ?? "https://app.daytona.io/api";
32
- const version = getPackageVersion();
33
- // Get transient push access credentials
34
- // DockerRegistryApi uses Bearer auth (accessToken), not apiKey header
35
- const config = new Configuration({
36
- accessToken: opts.apiKey,
37
- basePath: apiUrl,
38
- });
39
- const registryApi = new DockerRegistryApi(config);
40
- const response = await registryApi.getTransientPushAccess();
41
- const access = response.data;
42
- const remoteImage = `${access.registryUrl}/${access.project}/${localImage}:${version}`;
43
- console.log(`[daytona-registry] Pushing ${localImage} → ${remoteImage}`);
44
- console.log(`[daytona-registry] Registry: ${access.registryUrl} (expires: ${access.expiresAt})`);
45
- try {
46
- // Tag the local image
47
- execSync(`docker tag ${localImage} ${remoteImage}`, { stdio: "pipe" });
48
- // Login to the transient registry
49
- execSync(`docker login ${access.registryUrl} -u ${access.username} --password-stdin`, {
50
- input: access.secret,
51
- stdio: ["pipe", "pipe", "pipe"],
52
- });
53
- // Push the image
54
- console.log("[daytona-registry] Pushing image (this may take a while)...");
55
- execSync(`docker push ${remoteImage}`, { stdio: "inherit", timeout: 600_000 });
56
- console.log("[daytona-registry] Push complete");
57
- }
58
- finally {
59
- try {
60
- execSync(`docker logout ${access.registryUrl}`, { stdio: "pipe" });
61
- }
62
- catch {
63
- // Ignore logout errors
64
- }
65
- }
66
- return {
67
- remoteImage,
68
- registryUrl: access.registryUrl,
69
- project: access.project,
70
- };
71
- }
72
- /**
73
- * Ensure a Daytona snapshot exists for the sandbox image.
74
- *
75
- * - If a snapshot with the expected name already exists and is active, returns its name.
76
- * - Otherwise, pushes the local image to the transient registry and creates a snapshot.
77
- */
78
- export async function ensureSnapshot(daytona, opts) {
79
- const localImage = opts.localImage ?? SANDBOX_IMAGE;
80
- const snapshotName = localImage;
81
- // Check if snapshot already exists
82
- try {
83
- const existing = await daytona.snapshot.get(snapshotName);
84
- if (existing.state === "active") {
85
- console.log(`[daytona-registry] Snapshot "${snapshotName}" already exists and is active`);
86
- return snapshotName;
87
- }
88
- console.log(`[daytona-registry] Snapshot "${snapshotName}" exists but state=${existing.state}, deleting before recreate...`);
89
- await daytona.snapshot.delete(existing);
90
- console.log(`[daytona-registry] Old snapshot deleted`);
91
- }
92
- catch {
93
- console.log(`[daytona-registry] Snapshot "${snapshotName}" not found, creating...`);
94
- }
95
- // Push the local image to Daytona's transient registry
96
- const { remoteImage } = await pushImageToDaytona({
97
- apiKey: opts.apiKey,
98
- apiUrl: opts.apiUrl,
99
- localImage,
100
- });
101
- // Create the snapshot from the pushed image
102
- console.log(`[daytona-registry] Creating snapshot "${snapshotName}" from ${remoteImage}...`);
103
- await daytona.snapshot.create({
104
- name: snapshotName,
105
- image: remoteImage,
106
- entrypoint: ["/bin/sh", "-c", "sleep infinity"],
107
- }, {
108
- onLogs: opts.onLogs ?? ((chunk) => process.stdout.write(chunk)),
109
- timeout: 600,
110
- });
111
- console.log(`[daytona-registry] Snapshot "${snapshotName}" created successfully`);
112
- return snapshotName;
113
- }
114
- /**
115
- * Check if a snapshot exists and is active (non-throwing).
116
- */
117
- export async function getSnapshotStatus(daytona, snapshotName) {
118
- const name = snapshotName ?? SANDBOX_IMAGE;
119
- try {
120
- const snapshot = await daytona.snapshot.get(name);
121
- return { exists: true, state: snapshot.state };
122
- }
123
- catch {
124
- return { exists: false };
125
- }
126
- }
127
- //# sourceMappingURL=daytona-registry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"daytona-registry.js","sourceRoot":"","sources":["../../src/sandbox/daytona-registry.ts"],"names":[],"mappings":"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"}