@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,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generates AGENTS.md files for Codex CLI project workspaces.
|
|
3
|
-
*
|
|
4
|
-
* Reuses the same stack-specific content constants from claude-md-generator.ts
|
|
5
|
-
* since the instructions are framework-specific (Electric SQL + TanStack DB),
|
|
6
|
-
* not agent-specific.
|
|
7
|
-
*/
|
|
8
|
-
import {
|
|
9
|
-
DRIZZLE_WORKFLOW,
|
|
10
|
-
devServerInstructions,
|
|
11
|
-
GUARDRAILS,
|
|
12
|
-
INFRASTRUCTURE,
|
|
13
|
-
PLAYBOOK_INSTRUCTIONS,
|
|
14
|
-
PROJECT_CONTEXT,
|
|
15
|
-
SCAFFOLD_STRUCTURE,
|
|
16
|
-
SSR_RULES,
|
|
17
|
-
sandboxEnvironment,
|
|
18
|
-
} from "./claude-md-generator.js"
|
|
19
|
-
/**
|
|
20
|
-
* Generate an AGENTS.md file for Codex CLI mode.
|
|
21
|
-
* Uses the same stack-specific content as Claude Code mode.
|
|
22
|
-
*/
|
|
23
|
-
export function generateCodexMd(opts) {
|
|
24
|
-
const sections = []
|
|
25
|
-
sections.push(`# ${opts.projectName}`)
|
|
26
|
-
sections.push("")
|
|
27
|
-
sections.push(PROJECT_CONTEXT)
|
|
28
|
-
sections.push("")
|
|
29
|
-
const sandbox = sandboxEnvironment(opts.runtime)
|
|
30
|
-
if (sandbox) {
|
|
31
|
-
sections.push(sandbox)
|
|
32
|
-
sections.push("")
|
|
33
|
-
}
|
|
34
|
-
if (!opts.isIteration) {
|
|
35
|
-
sections.push("## Current Task")
|
|
36
|
-
sections.push(opts.description)
|
|
37
|
-
sections.push("")
|
|
38
|
-
}
|
|
39
|
-
sections.push(SCAFFOLD_STRUCTURE)
|
|
40
|
-
sections.push("")
|
|
41
|
-
sections.push(DRIZZLE_WORKFLOW)
|
|
42
|
-
sections.push("")
|
|
43
|
-
sections.push(GUARDRAILS)
|
|
44
|
-
sections.push("")
|
|
45
|
-
sections.push(PLAYBOOK_INSTRUCTIONS)
|
|
46
|
-
sections.push("")
|
|
47
|
-
sections.push(INFRASTRUCTURE)
|
|
48
|
-
sections.push("")
|
|
49
|
-
sections.push(devServerInstructions(opts.runtime))
|
|
50
|
-
sections.push("")
|
|
51
|
-
sections.push(SSR_RULES)
|
|
52
|
-
sections.push("")
|
|
53
|
-
return sections.join("\n")
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=codex-md-generator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codex-md-generator.js","sourceRoot":"","sources":["../../src/bridge/codex-md-generator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACN,gBAAgB,EAChB,qBAAqB,EACrB,UAAU,EACV,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,SAAS,EACT,kBAAkB,GAClB,MAAM,0BAA0B,CAAA;AAEjC;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,IAAqB;IACpD,MAAM,QAAQ,GAAa,EAAE,CAAA;IAE7B,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;IACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjB,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEjB,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAChD,IAAI,OAAO,EAAE,CAAC;QACb,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAClB,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QAChC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAClB,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjB,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjB,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjB,QAAQ,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjB,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjB,QAAQ,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;IAClD,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjB,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEjB,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC3B,CAAC"}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SessionBridge implementation that runs Codex CLI inside a Sprites
|
|
3
|
-
* sandbox via the Sprites SDK session API, communicating via exec --json NDJSON.
|
|
4
|
-
*
|
|
5
|
-
* The bridge translates Codex's exec --json output into EngineEvents
|
|
6
|
-
* and writes them to the Durable Stream for the UI.
|
|
7
|
-
*
|
|
8
|
-
* Codex runs in one-shot mode (`codex exec --json`) and exits after completing.
|
|
9
|
-
* On iterate (follow-up message), the bridge respawns Codex with the new prompt.
|
|
10
|
-
*/
|
|
11
|
-
import type { EngineEvent } from "@electric-agent/protocol"
|
|
12
|
-
import type { Sprite } from "@fly/sprites"
|
|
13
|
-
import type { StreamConnectionInfo } from "../streams.js"
|
|
14
|
-
import type { SessionBridge } from "./types.js"
|
|
15
|
-
export interface CodexSpritesConfig {
|
|
16
|
-
/** Initial prompt (the user's app description or task) */
|
|
17
|
-
prompt: string
|
|
18
|
-
/** Working directory inside the sprite */
|
|
19
|
-
cwd: string
|
|
20
|
-
/** Model to use (default: o4-mini) */
|
|
21
|
-
model?: string
|
|
22
|
-
/** Additional CLI flags */
|
|
23
|
-
extraFlags?: string[]
|
|
24
|
-
}
|
|
25
|
-
export declare class CodexSpritesBridge implements SessionBridge {
|
|
26
|
-
readonly sessionId: string
|
|
27
|
-
readonly streamUrl: string
|
|
28
|
-
readonly streamHeaders: Record<string, string>
|
|
29
|
-
private sprite
|
|
30
|
-
private config
|
|
31
|
-
private writer
|
|
32
|
-
private parser
|
|
33
|
-
private agentEventCallbacks
|
|
34
|
-
private completeCallbacks
|
|
35
|
-
private closed
|
|
36
|
-
private cmd
|
|
37
|
-
/** Codex thread ID captured from thread.started — used for resume */
|
|
38
|
-
private codexThreadId
|
|
39
|
-
/** Whether a Codex process is currently running */
|
|
40
|
-
private running
|
|
41
|
-
/** Whether the parser already emitted a session_end */
|
|
42
|
-
private resultReceived
|
|
43
|
-
constructor(
|
|
44
|
-
sessionId: string,
|
|
45
|
-
connection: StreamConnectionInfo,
|
|
46
|
-
sprite: Sprite,
|
|
47
|
-
config: CodexSpritesConfig,
|
|
48
|
-
)
|
|
49
|
-
emit(event: EngineEvent): Promise<void>
|
|
50
|
-
sendCommand(cmd: Record<string, unknown>): Promise<void>
|
|
51
|
-
sendGateResponse(_gate: string, _value: Record<string, unknown>): Promise<void>
|
|
52
|
-
onAgentEvent(cb: (event: EngineEvent) => void): void
|
|
53
|
-
onComplete(cb: (success: boolean) => void): void
|
|
54
|
-
start(): Promise<void>
|
|
55
|
-
close(): void
|
|
56
|
-
/**
|
|
57
|
-
* Spawn a new Codex process. Called for both the initial prompt
|
|
58
|
-
* and follow-up iterate messages.
|
|
59
|
-
*/
|
|
60
|
-
private spawnCodex
|
|
61
|
-
private handleLine
|
|
62
|
-
private dispatchEvent
|
|
63
|
-
}
|
|
64
|
-
//# sourceMappingURL=codex-sprites.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codex-sprites.d.ts","sourceRoot":"","sources":["../../src/bridge/codex-sprites.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAE3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAEzD,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAE9D,MAAM,WAAW,kBAAkB;IAClC,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAA;IACd,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAA;IACX,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,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,CAAoB;IAClC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,mBAAmB,CAA0C;IACrE,OAAO,CAAC,iBAAiB,CAAwC;IACjE,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,GAAG,CAA6B;IAExC,qEAAqE;IACrE,OAAO,CAAC,aAAa,CAAsB;IAC3C,mDAAmD;IACnD,OAAO,CAAC,OAAO,CAAQ;IACvB,uDAAuD;IACvD,OAAO,CAAC,cAAc,CAAQ;gBAG7B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,kBAAkB;IAerB,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;IAWxD,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrF,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;IAK5B,KAAK,IAAI,IAAI;IAgBb;;;OAGG;IACH,OAAO,CAAC,UAAU;IAyFlB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,aAAa;CA6CrB"}
|
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SessionBridge implementation that runs Codex CLI inside a Sprites
|
|
3
|
-
* sandbox via the Sprites SDK session API, communicating via exec --json NDJSON.
|
|
4
|
-
*
|
|
5
|
-
* The bridge translates Codex's exec --json output into EngineEvents
|
|
6
|
-
* and writes them to the Durable Stream for the UI.
|
|
7
|
-
*
|
|
8
|
-
* Codex runs in one-shot mode (`codex exec --json`) and exits after completing.
|
|
9
|
-
* On iterate (follow-up message), the bridge respawns Codex with the new prompt.
|
|
10
|
-
*/
|
|
11
|
-
import * as readline from "node:readline"
|
|
12
|
-
import { DurableStream } from "@durable-streams/client"
|
|
13
|
-
import { ts } from "@electric-agent/protocol"
|
|
14
|
-
import { SpriteCommand } from "@fly/sprites"
|
|
15
|
-
import { createCodexJsonParser } from "./codex-json-parser.js"
|
|
16
|
-
export class CodexSpritesBridge {
|
|
17
|
-
sessionId
|
|
18
|
-
streamUrl
|
|
19
|
-
streamHeaders
|
|
20
|
-
sprite
|
|
21
|
-
config
|
|
22
|
-
writer
|
|
23
|
-
parser = createCodexJsonParser()
|
|
24
|
-
agentEventCallbacks = []
|
|
25
|
-
completeCallbacks = []
|
|
26
|
-
closed = false
|
|
27
|
-
cmd = null
|
|
28
|
-
/** Codex thread ID captured from thread.started — used for resume */
|
|
29
|
-
codexThreadId = null
|
|
30
|
-
/** Whether a Codex process is currently running */
|
|
31
|
-
running = false
|
|
32
|
-
/** Whether the parser already emitted a session_end */
|
|
33
|
-
resultReceived = false
|
|
34
|
-
constructor(sessionId, connection, sprite, config) {
|
|
35
|
-
this.sessionId = sessionId
|
|
36
|
-
this.streamUrl = connection.url
|
|
37
|
-
this.streamHeaders = connection.headers
|
|
38
|
-
this.sprite = sprite
|
|
39
|
-
this.config = config
|
|
40
|
-
this.writer = new DurableStream({
|
|
41
|
-
url: connection.url,
|
|
42
|
-
headers: connection.headers,
|
|
43
|
-
contentType: "application/json",
|
|
44
|
-
})
|
|
45
|
-
}
|
|
46
|
-
async emit(event) {
|
|
47
|
-
if (this.closed) return
|
|
48
|
-
const msg = { source: "server", ...event }
|
|
49
|
-
await this.writer.append(JSON.stringify(msg))
|
|
50
|
-
}
|
|
51
|
-
async sendCommand(cmd) {
|
|
52
|
-
if (this.closed) return
|
|
53
|
-
if (cmd.command === "iterate" && typeof cmd.request === "string") {
|
|
54
|
-
this.spawnCodex(cmd.request)
|
|
55
|
-
return
|
|
56
|
-
}
|
|
57
|
-
console.log(`[codex-sprites] Ignoring unsupported command: ${cmd.command}`)
|
|
58
|
-
}
|
|
59
|
-
async sendGateResponse(_gate, _value) {
|
|
60
|
-
// Codex exec --json doesn't support stdin user messages mid-run
|
|
61
|
-
}
|
|
62
|
-
onAgentEvent(cb) {
|
|
63
|
-
this.agentEventCallbacks.push(cb)
|
|
64
|
-
}
|
|
65
|
-
onComplete(cb) {
|
|
66
|
-
this.completeCallbacks.push(cb)
|
|
67
|
-
}
|
|
68
|
-
async start() {
|
|
69
|
-
if (this.closed) return
|
|
70
|
-
this.spawnCodex(this.config.prompt)
|
|
71
|
-
}
|
|
72
|
-
close() {
|
|
73
|
-
this.closed = true
|
|
74
|
-
if (this.cmd) {
|
|
75
|
-
try {
|
|
76
|
-
this.cmd.kill()
|
|
77
|
-
} catch {
|
|
78
|
-
// Process may already be dead
|
|
79
|
-
}
|
|
80
|
-
this.cmd = null
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
// -----------------------------------------------------------------------
|
|
84
|
-
// Private helpers
|
|
85
|
-
// -----------------------------------------------------------------------
|
|
86
|
-
/**
|
|
87
|
-
* Spawn a new Codex process. Called for both the initial prompt
|
|
88
|
-
* and follow-up iterate messages.
|
|
89
|
-
*/
|
|
90
|
-
spawnCodex(prompt) {
|
|
91
|
-
// Kill any existing process
|
|
92
|
-
if (this.cmd) {
|
|
93
|
-
try {
|
|
94
|
-
this.cmd.kill()
|
|
95
|
-
} catch {
|
|
96
|
-
// Already dead
|
|
97
|
-
}
|
|
98
|
-
this.cmd = null
|
|
99
|
-
}
|
|
100
|
-
// Reset parser state for the new process
|
|
101
|
-
this.parser = createCodexJsonParser()
|
|
102
|
-
this.resultReceived = false
|
|
103
|
-
this.running = true
|
|
104
|
-
const model = this.config.model ?? "o4-mini"
|
|
105
|
-
// Build the codex CLI command
|
|
106
|
-
const codexArgs = [
|
|
107
|
-
"exec",
|
|
108
|
-
"--json",
|
|
109
|
-
"--full-auto",
|
|
110
|
-
"--model",
|
|
111
|
-
model,
|
|
112
|
-
...(this.config.extraFlags ?? []),
|
|
113
|
-
"-q",
|
|
114
|
-
prompt,
|
|
115
|
-
]
|
|
116
|
-
// Escape for bash — use bash -c with properly escaped args
|
|
117
|
-
const escapedArgs = codexArgs.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ")
|
|
118
|
-
const fullCmd = `source /etc/profile.d/npm-global.sh 2>/dev/null; source /etc/profile.d/electric-agent.sh 2>/dev/null; cd '${this.config.cwd}' && codex ${escapedArgs}`
|
|
119
|
-
// Use SpriteCommand with tty:true (for streaming)
|
|
120
|
-
this.cmd = new SpriteCommand(this.sprite, "bash", ["-c", fullCmd], {
|
|
121
|
-
tty: true,
|
|
122
|
-
})
|
|
123
|
-
this.cmd.start()
|
|
124
|
-
console.log(`[codex-sprites] Started: session=${this.sessionId}`)
|
|
125
|
-
const currentCmd = this.cmd
|
|
126
|
-
// Read stdout line by line (exec --json NDJSON)
|
|
127
|
-
const rl = readline.createInterface({
|
|
128
|
-
input: currentCmd.stdout,
|
|
129
|
-
terminal: false,
|
|
130
|
-
})
|
|
131
|
-
rl.on("line", (line) => {
|
|
132
|
-
if (this.closed) return
|
|
133
|
-
this.handleLine(line)
|
|
134
|
-
})
|
|
135
|
-
// Log stderr
|
|
136
|
-
const stderrRl = readline.createInterface({
|
|
137
|
-
input: currentCmd.stderr,
|
|
138
|
-
terminal: false,
|
|
139
|
-
})
|
|
140
|
-
stderrRl.on("line", (line) => {
|
|
141
|
-
if (!this.closed) {
|
|
142
|
-
console.error(`[codex-sprites:stderr] ${line}`)
|
|
143
|
-
}
|
|
144
|
-
})
|
|
145
|
-
// Handle process exit — defer to let pending readline events flush first
|
|
146
|
-
currentCmd.on("exit", (code) => {
|
|
147
|
-
console.log(`[codex-sprites] Process exited: code=${code} session=${this.sessionId}`)
|
|
148
|
-
setTimeout(() => {
|
|
149
|
-
// Capture thread ID from parser state before marking not running
|
|
150
|
-
if (this.parser.state.threadId) {
|
|
151
|
-
this.codexThreadId = this.parser.state.threadId
|
|
152
|
-
}
|
|
153
|
-
this.running = false
|
|
154
|
-
// Emit session_end if the parser didn't already
|
|
155
|
-
if (!this.closed && !this.resultReceived) {
|
|
156
|
-
const endEvent = {
|
|
157
|
-
type: "session_end",
|
|
158
|
-
success: code === 0,
|
|
159
|
-
ts: ts(),
|
|
160
|
-
}
|
|
161
|
-
this.dispatchEvent(endEvent)
|
|
162
|
-
}
|
|
163
|
-
}, 100)
|
|
164
|
-
})
|
|
165
|
-
}
|
|
166
|
-
handleLine(line) {
|
|
167
|
-
// Strip ANSI escape sequences and terminal control chars added by tty mode
|
|
168
|
-
const cleaned = stripAnsi(line).trim()
|
|
169
|
-
if (!cleaned) return
|
|
170
|
-
const events = this.parser.parse(cleaned)
|
|
171
|
-
for (const event of events) {
|
|
172
|
-
this.dispatchEvent(event)
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
dispatchEvent(event) {
|
|
176
|
-
const msg = { source: "agent", ...event }
|
|
177
|
-
this.writer.append(JSON.stringify(msg)).catch(() => {})
|
|
178
|
-
// Track session_end to prevent duplicates
|
|
179
|
-
if (event.type === "session_end") {
|
|
180
|
-
this.resultReceived = true
|
|
181
|
-
}
|
|
182
|
-
// Detect dev:start in Bash tool_use → emit app_ready for the UI preview
|
|
183
|
-
if (event.type === "pre_tool_use" && event.tool_name === "Bash") {
|
|
184
|
-
const cmd = event.tool_input?.command
|
|
185
|
-
if (typeof cmd === "string" && /\bdev:start\b/.test(cmd)) {
|
|
186
|
-
const appReady = { type: "app_ready", ts: ts() }
|
|
187
|
-
const appReadyMsg = { source: "agent", ...appReady }
|
|
188
|
-
this.writer.append(JSON.stringify(appReadyMsg)).catch(() => {})
|
|
189
|
-
for (const cb of this.agentEventCallbacks) {
|
|
190
|
-
try {
|
|
191
|
-
cb(appReady)
|
|
192
|
-
} catch {
|
|
193
|
-
// Swallow
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
for (const cb of this.agentEventCallbacks) {
|
|
199
|
-
try {
|
|
200
|
-
cb(event)
|
|
201
|
-
} catch {
|
|
202
|
-
// Swallow callback errors
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
if (event.type === "session_end" && "success" in event) {
|
|
206
|
-
const success = event.success
|
|
207
|
-
for (const cb of this.completeCallbacks) {
|
|
208
|
-
try {
|
|
209
|
-
cb(success)
|
|
210
|
-
} catch {
|
|
211
|
-
// Swallow callback errors
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
/** Strip ANSI escape sequences and control characters from tty output */
|
|
218
|
-
function stripAnsi(str) {
|
|
219
|
-
const ESC = "\x1b"
|
|
220
|
-
const csi = new RegExp(`${ESC}\\[[0-9;]*[a-zA-Z]`, "g")
|
|
221
|
-
const osc1 = new RegExp(`${ESC}\\][^\\x07]*\\x07`, "g")
|
|
222
|
-
const osc2 = new RegExp(`${ESC}\\][^${ESC}]*${ESC}\\\\`, "g")
|
|
223
|
-
// biome-ignore lint/suspicious/noControlCharactersInRegex: strip C0 control chars except \n \r
|
|
224
|
-
const ctrl = /[\x00-\x09\x0b\x0c\x0e-\x1f\x7f]/g
|
|
225
|
-
return str.replace(csi, "").replace(osc1, "").replace(osc2, "").replace(ctrl, "")
|
|
226
|
-
}
|
|
227
|
-
//# sourceMappingURL=codex-sprites.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codex-sprites.js","sourceRoot":"","sources":["../../src/bridge/codex-sprites.ts"],"names":[],"mappings":"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"}
|
package/dist/bridge/daytona.d.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SessionBridge implementation that communicates with a Daytona sandbox
|
|
3
|
-
* via the Daytona SDK session API (stdin/stdout NDJSON).
|
|
4
|
-
*
|
|
5
|
-
* The server bridges between the Durable Stream (for UI events) and
|
|
6
|
-
* the Daytona session (for agent communication). The agent inside the
|
|
7
|
-
* sandbox uses the stdio adapter — no outbound internet required.
|
|
8
|
-
*/
|
|
9
|
-
import type { Sandbox } from "@daytonaio/sdk"
|
|
10
|
-
import type { EngineEvent } from "@electric-agent/protocol"
|
|
11
|
-
import type { StreamConnectionInfo } from "../streams.js"
|
|
12
|
-
import type { SessionBridge } from "./types.js"
|
|
13
|
-
export declare class DaytonaSessionBridge implements SessionBridge {
|
|
14
|
-
readonly sessionId: string
|
|
15
|
-
readonly streamUrl: string
|
|
16
|
-
readonly streamHeaders: Record<string, string>
|
|
17
|
-
private sandbox
|
|
18
|
-
private writer
|
|
19
|
-
private agentEventCallbacks
|
|
20
|
-
private completeCallbacks
|
|
21
|
-
private closed
|
|
22
|
-
private cmdId
|
|
23
|
-
private stdoutBuffer
|
|
24
|
-
constructor(sessionId: string, connection: StreamConnectionInfo, sandbox: Sandbox)
|
|
25
|
-
emit(event: EngineEvent): Promise<void>
|
|
26
|
-
sendCommand(cmd: Record<string, unknown>): Promise<void>
|
|
27
|
-
sendGateResponse(gate: string, value: Record<string, unknown>): Promise<void>
|
|
28
|
-
onAgentEvent(cb: (event: EngineEvent) => void): void
|
|
29
|
-
onComplete(cb: (success: boolean) => void): void
|
|
30
|
-
start(): Promise<void>
|
|
31
|
-
private pollLogs
|
|
32
|
-
private handleStdout
|
|
33
|
-
close(): void
|
|
34
|
-
}
|
|
35
|
-
//# sourceMappingURL=daytona.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"daytona.d.ts","sourceRoot":"","sources":["../../src/bridge/daytona.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAE7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAI9D,qBAAa,oBAAqB,YAAW,aAAa;IACzD,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,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,mBAAmB,CAA0C;IACrE,OAAO,CAAC,iBAAiB,CAAwC;IACjE,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,YAAY,CAAK;gBAEb,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,oBAAoB,EAAE,OAAO,EAAE,OAAO;IAa3E,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;YA2Bd,QAAQ;IAqBtB,OAAO,CAAC,YAAY;IAiDpB,KAAK,IAAI,IAAI;CAGb"}
|
package/dist/bridge/daytona.js
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SessionBridge implementation that communicates with a Daytona sandbox
|
|
3
|
-
* via the Daytona SDK session API (stdin/stdout NDJSON).
|
|
4
|
-
*
|
|
5
|
-
* The server bridges between the Durable Stream (for UI events) and
|
|
6
|
-
* the Daytona session (for agent communication). The agent inside the
|
|
7
|
-
* sandbox uses the stdio adapter — no outbound internet required.
|
|
8
|
-
*/
|
|
9
|
-
import { DurableStream } from "@durable-streams/client"
|
|
10
|
-
|
|
11
|
-
const DAYTONA_SESSION_ID = "agent-session"
|
|
12
|
-
export class DaytonaSessionBridge {
|
|
13
|
-
sessionId
|
|
14
|
-
streamUrl
|
|
15
|
-
streamHeaders
|
|
16
|
-
sandbox
|
|
17
|
-
writer
|
|
18
|
-
agentEventCallbacks = []
|
|
19
|
-
completeCallbacks = []
|
|
20
|
-
closed = false
|
|
21
|
-
cmdId = null
|
|
22
|
-
stdoutBuffer = ""
|
|
23
|
-
constructor(sessionId, connection, sandbox) {
|
|
24
|
-
this.sessionId = sessionId
|
|
25
|
-
this.streamUrl = connection.url
|
|
26
|
-
this.streamHeaders = connection.headers
|
|
27
|
-
this.sandbox = sandbox
|
|
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.cmdId) return
|
|
41
|
-
const line = JSON.stringify({ type: "command", ...cmd })
|
|
42
|
-
await this.sandbox.process.sendSessionCommandInput(DAYTONA_SESSION_ID, this.cmdId, `${line}\n`)
|
|
43
|
-
}
|
|
44
|
-
async sendGateResponse(gate, value) {
|
|
45
|
-
if (this.closed || !this.cmdId) return
|
|
46
|
-
const line = JSON.stringify({ type: "gate_response", gate, ...value })
|
|
47
|
-
await this.sandbox.process.sendSessionCommandInput(DAYTONA_SESSION_ID, this.cmdId, `${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 sandbox
|
|
58
|
-
await this.sandbox.process.createSession(DAYTONA_SESSION_ID)
|
|
59
|
-
// Start the headless agent asynchronously
|
|
60
|
-
const response = await this.sandbox.process.executeSessionCommand(DAYTONA_SESSION_ID, {
|
|
61
|
-
command: "electric-agent headless",
|
|
62
|
-
runAsync: true,
|
|
63
|
-
})
|
|
64
|
-
this.cmdId = response.cmdId ?? null
|
|
65
|
-
if (!this.cmdId) {
|
|
66
|
-
throw new Error("Failed to get command ID from Daytona session")
|
|
67
|
-
}
|
|
68
|
-
console.log(`[daytona-bridge] Agent started: session=${this.sessionId} cmdId=${this.cmdId}`)
|
|
69
|
-
// Stream stdout output via log polling
|
|
70
|
-
this.pollLogs().catch((err) => {
|
|
71
|
-
if (!this.closed) {
|
|
72
|
-
console.error(`[daytona-bridge] Log streaming error:`, err)
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
}
|
|
76
|
-
async pollLogs() {
|
|
77
|
-
if (!this.cmdId) return
|
|
78
|
-
try {
|
|
79
|
-
await this.sandbox.process.getSessionCommandLogs(
|
|
80
|
-
DAYTONA_SESSION_ID,
|
|
81
|
-
this.cmdId,
|
|
82
|
-
(chunk) => this.handleStdout(chunk),
|
|
83
|
-
(chunk) => {
|
|
84
|
-
if (!this.closed) {
|
|
85
|
-
process.stderr.write(`[daytona-bridge:stderr] ${chunk}`)
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
)
|
|
89
|
-
} catch (err) {
|
|
90
|
-
if (!this.closed) {
|
|
91
|
-
console.error(`[daytona-bridge] getSessionCommandLogs error:`, err)
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
handleStdout(chunk) {
|
|
96
|
-
if (this.closed) return
|
|
97
|
-
// Buffer partial lines
|
|
98
|
-
this.stdoutBuffer += chunk
|
|
99
|
-
const lines = this.stdoutBuffer.split("\n")
|
|
100
|
-
// Keep the last (possibly incomplete) line in the buffer
|
|
101
|
-
this.stdoutBuffer = lines.pop() ?? ""
|
|
102
|
-
for (const line of lines) {
|
|
103
|
-
const trimmed = line.trim()
|
|
104
|
-
if (!trimmed) continue
|
|
105
|
-
let event
|
|
106
|
-
try {
|
|
107
|
-
event = JSON.parse(trimmed)
|
|
108
|
-
} catch {
|
|
109
|
-
// Not valid JSON — log as diagnostic
|
|
110
|
-
console.log(`[daytona-bridge] Non-JSON stdout: ${trimmed}`)
|
|
111
|
-
continue
|
|
112
|
-
}
|
|
113
|
-
// Write to Durable Stream for UI
|
|
114
|
-
const msg = { source: "agent", ...event }
|
|
115
|
-
this.writer.append(JSON.stringify(msg)).catch(() => {})
|
|
116
|
-
// Dispatch to callbacks
|
|
117
|
-
for (const cb of this.agentEventCallbacks) {
|
|
118
|
-
try {
|
|
119
|
-
cb(event)
|
|
120
|
-
} catch {
|
|
121
|
-
// Swallow callback errors
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
// Detect session_end
|
|
125
|
-
if (event.type === "session_end" && "success" in event) {
|
|
126
|
-
const success = event.success
|
|
127
|
-
for (const cb of this.completeCallbacks) {
|
|
128
|
-
try {
|
|
129
|
-
cb(success)
|
|
130
|
-
} catch {
|
|
131
|
-
// Swallow callback errors
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
close() {
|
|
138
|
-
this.closed = true
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
//# sourceMappingURL=daytona.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"daytona.js","sourceRoot":"","sources":["../../src/bridge/daytona.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,30 +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 type { EngineEvent } from "@electric-agent/protocol"
|
|
9
|
-
import type { StreamConnectionInfo } from "../streams.js"
|
|
10
|
-
import type { SessionBridge } from "./types.js"
|
|
11
|
-
export declare class DockerStdioBridge implements SessionBridge {
|
|
12
|
-
readonly sessionId: string
|
|
13
|
-
readonly streamUrl: string
|
|
14
|
-
readonly streamHeaders: Record<string, string>
|
|
15
|
-
private containerId
|
|
16
|
-
private writer
|
|
17
|
-
private agentEventCallbacks
|
|
18
|
-
private completeCallbacks
|
|
19
|
-
private closed
|
|
20
|
-
private proc
|
|
21
|
-
constructor(sessionId: string, connection: StreamConnectionInfo, containerId: string)
|
|
22
|
-
emit(event: EngineEvent): Promise<void>
|
|
23
|
-
sendCommand(cmd: Record<string, unknown>): Promise<void>
|
|
24
|
-
sendGateResponse(gate: string, value: Record<string, unknown>): Promise<void>
|
|
25
|
-
onAgentEvent(cb: (event: EngineEvent) => void): void
|
|
26
|
-
onComplete(cb: (success: boolean) => void): void
|
|
27
|
-
start(): Promise<void>
|
|
28
|
-
close(): void
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=docker-stdio.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"docker-stdio.d.ts","sourceRoot":"","sources":["../../src/bridge/docker-stdio.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAE9D,qBAAa,iBAAkB,YAAW,aAAa;IACtD,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,WAAW,CAAQ;IAC3B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,mBAAmB,CAA0C;IACrE,OAAO,CAAC,iBAAiB,CAAwC;IACjE,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,IAAI,CAA4B;gBAE5B,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM;IAa9E,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;IAgF5B,KAAK,IAAI,IAAI;CAYb"}
|