@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.
- package/dist/bridge/message-parser.d.ts +3 -3
- package/dist/bridge/message-parser.d.ts.map +1 -1
- package/dist/bridge/message-parser.js +3 -3
- package/dist/bridge/message-parser.js.map +1 -1
- package/dist/client/assets/{index-IvCtVUfs.css → index-BSGS-yya.css} +1 -1
- package/dist/client/assets/{index-BXdgNRgB.js → index-qUqEqKXn.js} +35 -35
- package/dist/client/index.html +2 -2
- package/dist/room-router.d.ts +13 -0
- package/dist/room-router.d.ts.map +1 -1
- package/dist/room-router.js +29 -1
- package/dist/room-router.js.map +1 -1
- package/dist/server.d.ts +2 -4
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +60 -68
- package/dist/server.js.map +1 -1
- package/package.json +7 -2
- package/dist/bridge/codex-docker.d.ts +0 -70
- package/dist/bridge/codex-docker.d.ts.map +0 -1
- package/dist/bridge/codex-docker.js +0 -234
- package/dist/bridge/codex-docker.js.map +0 -1
- package/dist/bridge/codex-json-parser.d.ts +0 -31
- package/dist/bridge/codex-json-parser.d.ts.map +0 -1
- package/dist/bridge/codex-json-parser.js +0 -267
- package/dist/bridge/codex-json-parser.js.map +0 -1
- package/dist/bridge/codex-md-generator.d.ts +0 -14
- package/dist/bridge/codex-md-generator.d.ts.map +0 -1
- package/dist/bridge/codex-md-generator.js +0 -55
- package/dist/bridge/codex-md-generator.js.map +0 -1
- package/dist/bridge/codex-sprites.d.ts +0 -64
- package/dist/bridge/codex-sprites.d.ts.map +0 -1
- package/dist/bridge/codex-sprites.js +0 -227
- package/dist/bridge/codex-sprites.js.map +0 -1
- package/dist/bridge/daytona.d.ts +0 -35
- package/dist/bridge/daytona.d.ts.map +0 -1
- package/dist/bridge/daytona.js +0 -141
- package/dist/bridge/daytona.js.map +0 -1
- package/dist/bridge/docker-stdio.d.ts +0 -30
- package/dist/bridge/docker-stdio.d.ts.map +0 -1
- package/dist/bridge/docker-stdio.js +0 -135
- package/dist/bridge/docker-stdio.js.map +0 -1
- package/dist/bridge/sprites.d.ts +0 -32
- package/dist/bridge/sprites.d.ts.map +0 -1
- package/dist/bridge/sprites.js +0 -133
- package/dist/bridge/sprites.js.map +0 -1
- package/dist/github-app.test.d.ts +0 -2
- package/dist/github-app.test.d.ts.map +0 -1
- package/dist/github-app.test.js +0 -62
- package/dist/github-app.test.js.map +0 -1
- package/dist/sandbox/daytona-push.d.ts +0 -3
- package/dist/sandbox/daytona-push.d.ts.map +0 -1
- package/dist/sandbox/daytona-push.js +0 -56
- package/dist/sandbox/daytona-push.js.map +0 -1
- package/dist/sandbox/daytona-registry.d.ts +0 -41
- package/dist/sandbox/daytona-registry.d.ts.map +0 -1
- package/dist/sandbox/daytona-registry.js +0 -127
- package/dist/sandbox/daytona-registry.js.map +0 -1
- package/dist/sandbox/daytona.d.ts +0 -41
- package/dist/sandbox/daytona.d.ts.map +0 -1
- package/dist/sandbox/daytona.js +0 -282
- package/dist/sandbox/daytona.js.map +0 -1
- package/dist/shared-sessions.d.ts +0 -16
- package/dist/shared-sessions.d.ts.map +0 -1
- package/dist/shared-sessions.js +0 -52
- 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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"}
|
package/dist/bridge/sprites.d.ts
DELETED
|
@@ -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"}
|
package/dist/bridge/sprites.js
DELETED
|
@@ -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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"github-app.test.d.ts","sourceRoot":"","sources":["../src/github-app.test.ts"],"names":[],"mappings":""}
|
package/dist/github-app.test.js
DELETED
|
@@ -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 +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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"}
|