@electric-agent/studio 1.13.1 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/active-sessions.d.ts +4 -13
  2. package/dist/active-sessions.d.ts.map +1 -1
  3. package/dist/active-sessions.js +5 -39
  4. package/dist/active-sessions.js.map +1 -1
  5. package/dist/bridge/claude-code-base.d.ts +0 -2
  6. package/dist/bridge/claude-code-base.d.ts.map +1 -1
  7. package/dist/bridge/claude-code-base.js +0 -2
  8. package/dist/bridge/claude-code-base.js.map +1 -1
  9. package/dist/bridge/claude-md-generator.d.ts +2 -12
  10. package/dist/bridge/claude-md-generator.d.ts.map +1 -1
  11. package/dist/bridge/claude-md-generator.js +94 -72
  12. package/dist/bridge/claude-md-generator.js.map +1 -1
  13. package/dist/bridge/role-skills.d.ts.map +1 -1
  14. package/dist/bridge/role-skills.js +0 -8
  15. package/dist/bridge/role-skills.js.map +1 -1
  16. package/dist/client/assets/index-BfvQSMwH.css +1 -0
  17. package/dist/client/assets/index-BtX82X61.js +234 -0
  18. package/dist/client/index.html +2 -2
  19. package/dist/room-router.d.ts.map +1 -1
  20. package/dist/room-router.js +5 -20
  21. package/dist/room-router.js.map +1 -1
  22. package/dist/sandbox/docker.d.ts +0 -10
  23. package/dist/sandbox/docker.d.ts.map +1 -1
  24. package/dist/sandbox/docker.js +1 -115
  25. package/dist/sandbox/docker.js.map +1 -1
  26. package/dist/sandbox/sprites.d.ts +0 -1
  27. package/dist/sandbox/sprites.d.ts.map +1 -1
  28. package/dist/sandbox/sprites.js +0 -51
  29. package/dist/sandbox/sprites.js.map +1 -1
  30. package/dist/sandbox/types.d.ts +0 -5
  31. package/dist/sandbox/types.d.ts.map +1 -1
  32. package/dist/server.d.ts +0 -12
  33. package/dist/server.d.ts.map +1 -1
  34. package/dist/server.js +187 -1097
  35. package/dist/server.js.map +1 -1
  36. package/dist/session-auth.d.ts +0 -3
  37. package/dist/session-auth.d.ts.map +1 -1
  38. package/dist/session-auth.js +0 -10
  39. package/dist/session-auth.js.map +1 -1
  40. package/dist/sessions.d.ts +0 -2
  41. package/dist/sessions.d.ts.map +1 -1
  42. package/dist/sessions.js.map +1 -1
  43. package/package.json +2 -2
  44. package/dist/api-schemas.d.ts +0 -244
  45. package/dist/api-schemas.d.ts.map +0 -1
  46. package/dist/api-schemas.js +0 -103
  47. package/dist/api-schemas.js.map +0 -1
  48. package/dist/bridge/codex-docker.d.ts +0 -70
  49. package/dist/bridge/codex-docker.d.ts.map +0 -1
  50. package/dist/bridge/codex-docker.js +0 -234
  51. package/dist/bridge/codex-docker.js.map +0 -1
  52. package/dist/bridge/codex-json-parser.d.ts +0 -31
  53. package/dist/bridge/codex-json-parser.d.ts.map +0 -1
  54. package/dist/bridge/codex-json-parser.js +0 -267
  55. package/dist/bridge/codex-json-parser.js.map +0 -1
  56. package/dist/bridge/codex-md-generator.d.ts +0 -14
  57. package/dist/bridge/codex-md-generator.d.ts.map +0 -1
  58. package/dist/bridge/codex-md-generator.js +0 -55
  59. package/dist/bridge/codex-md-generator.js.map +0 -1
  60. package/dist/bridge/codex-sprites.d.ts +0 -64
  61. package/dist/bridge/codex-sprites.d.ts.map +0 -1
  62. package/dist/bridge/codex-sprites.js +0 -227
  63. package/dist/bridge/codex-sprites.js.map +0 -1
  64. package/dist/bridge/daytona.d.ts +0 -35
  65. package/dist/bridge/daytona.d.ts.map +0 -1
  66. package/dist/bridge/daytona.js +0 -141
  67. package/dist/bridge/daytona.js.map +0 -1
  68. package/dist/bridge/docker-stdio.d.ts +0 -30
  69. package/dist/bridge/docker-stdio.d.ts.map +0 -1
  70. package/dist/bridge/docker-stdio.js +0 -135
  71. package/dist/bridge/docker-stdio.js.map +0 -1
  72. package/dist/bridge/sprites.d.ts +0 -32
  73. package/dist/bridge/sprites.d.ts.map +0 -1
  74. package/dist/bridge/sprites.js +0 -133
  75. package/dist/bridge/sprites.js.map +0 -1
  76. package/dist/client/assets/index-BXdgNRgB.js +0 -235
  77. package/dist/client/assets/index-IvCtVUfs.css +0 -1
  78. package/dist/github-app.d.ts +0 -14
  79. package/dist/github-app.d.ts.map +0 -1
  80. package/dist/github-app.js +0 -62
  81. package/dist/github-app.js.map +0 -1
  82. package/dist/github-app.test.d.ts +0 -2
  83. package/dist/github-app.test.d.ts.map +0 -1
  84. package/dist/github-app.test.js +0 -62
  85. package/dist/github-app.test.js.map +0 -1
  86. package/dist/validate.d.ts +0 -10
  87. package/dist/validate.d.ts.map +0 -1
  88. package/dist/validate.js +0 -24
  89. package/dist/validate.js.map +0 -1
@@ -1,31 +0,0 @@
1
- /**
2
- * Translates Codex CLI `codex exec --json` NDJSON messages
3
- * into EngineEvent arrays compatible with the existing bridge/UI pipeline.
4
- *
5
- * Codex exec --json emits lines like:
6
- * {"type":"thread.started","thread_id":"..."}
7
- * {"type":"item.started","item":{"type":"command_execution","id":"...","command":"..."}}
8
- * {"type":"item.completed","item":{"type":"agent_message","id":"...","content":"..."}}
9
- * {"type":"turn.completed","usage":{"input_tokens":100,"output_tokens":50}}
10
- * {"type":"turn.failed","error":"..."}
11
- *
12
- * This parser converts each line into zero or more EngineEvent objects.
13
- */
14
- import type { EngineEvent } from "@electric-agent/protocol"
15
- export interface CodexJsonParserState {
16
- /** Map item ID → tool name for correlating started/completed events */
17
- toolNames: Map<string, string>
18
- /** Accumulated cost from turn.completed messages */
19
- totalCost: number
20
- /** Codex thread ID from thread.started */
21
- threadId: string | null
22
- }
23
- /**
24
- * Create a new stateful parser. The returned `parse` function converts
25
- * a single raw JSON line from Codex into zero or more EngineEvents.
26
- */
27
- export declare function createCodexJsonParser(): {
28
- state: CodexJsonParserState
29
- parse(line: string): EngineEvent[]
30
- }
31
- //# sourceMappingURL=codex-json-parser.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"codex-json-parser.d.ts","sourceRoot":"","sources":["../../src/bridge/codex-json-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AA+F3D,MAAM,WAAW,oBAAoB;IACpC,uEAAuE;IACvE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAA;IACjB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB;;gBASvB,MAAM,GAAG,WAAW,EAAE;EAInC"}
@@ -1,267 +0,0 @@
1
- /**
2
- * Translates Codex CLI `codex exec --json` NDJSON messages
3
- * into EngineEvent arrays compatible with the existing bridge/UI pipeline.
4
- *
5
- * Codex exec --json emits lines like:
6
- * {"type":"thread.started","thread_id":"..."}
7
- * {"type":"item.started","item":{"type":"command_execution","id":"...","command":"..."}}
8
- * {"type":"item.completed","item":{"type":"agent_message","id":"...","content":"..."}}
9
- * {"type":"turn.completed","usage":{"input_tokens":100,"output_tokens":50}}
10
- * {"type":"turn.failed","error":"..."}
11
- *
12
- * This parser converts each line into zero or more EngineEvent objects.
13
- */
14
- import { ts } from "@electric-agent/protocol"
15
- /**
16
- * Create a new stateful parser. The returned `parse` function converts
17
- * a single raw JSON line from Codex into zero or more EngineEvents.
18
- */
19
- export function createCodexJsonParser() {
20
- const state = {
21
- toolNames: new Map(),
22
- totalCost: 0,
23
- threadId: null,
24
- }
25
- return {
26
- state,
27
- parse(line) {
28
- return parseLine(line, state)
29
- },
30
- }
31
- }
32
- function parseLine(line, state) {
33
- const trimmed = line.trim()
34
- if (!trimmed) return []
35
- let msg
36
- try {
37
- msg = JSON.parse(trimmed)
38
- } catch {
39
- return []
40
- }
41
- if (!msg.type) return []
42
- switch (msg.type) {
43
- case "thread.started":
44
- return handleThreadStarted(msg, state)
45
- case "item.started":
46
- return handleItemStarted(msg, state)
47
- case "item.completed":
48
- return handleItemCompleted(msg, state)
49
- case "turn.completed":
50
- return handleTurnCompleted(msg, state)
51
- case "turn.failed":
52
- return handleTurnFailed(msg)
53
- default:
54
- return []
55
- }
56
- }
57
- function handleThreadStarted(msg, state) {
58
- state.threadId = msg.thread_id ?? null
59
- return [
60
- {
61
- type: "session_start",
62
- session_id: msg.thread_id ?? "",
63
- ts: ts(),
64
- },
65
- ]
66
- }
67
- function handleItemStarted(msg, state) {
68
- const item = msg.item
69
- if (!item?.type) return []
70
- switch (item.type) {
71
- case "command_execution": {
72
- const ce = item
73
- const toolUseId = ce.id ?? `codex_${Date.now()}`
74
- state.toolNames.set(toolUseId, "Bash")
75
- return [
76
- {
77
- type: "pre_tool_use",
78
- tool_name: "Bash",
79
- tool_use_id: toolUseId,
80
- tool_input: { command: ce.command ?? "" },
81
- ts: ts(),
82
- },
83
- ]
84
- }
85
- case "file_change": {
86
- const fc = item
87
- const toolUseId = fc.id ?? `codex_${Date.now()}`
88
- const toolName = fc.action === "delete" ? "Delete" : "Write"
89
- state.toolNames.set(toolUseId, toolName)
90
- return [
91
- {
92
- type: "pre_tool_use",
93
- tool_name: toolName,
94
- tool_use_id: toolUseId,
95
- tool_input: { file_path: fc.file_path ?? "", action: fc.action ?? "write" },
96
- ts: ts(),
97
- },
98
- ]
99
- }
100
- case "mcp_tool_call": {
101
- const mc = item
102
- const toolUseId = mc.id ?? `codex_${Date.now()}`
103
- const toolName = mc.tool_name
104
- ? mc.server_name
105
- ? `mcp__${mc.server_name}__${mc.tool_name}`
106
- : mc.tool_name
107
- : "mcp_tool"
108
- state.toolNames.set(toolUseId, toolName)
109
- return [
110
- {
111
- type: "pre_tool_use",
112
- tool_name: toolName,
113
- tool_use_id: toolUseId,
114
- tool_input: mc.arguments ?? {},
115
- ts: ts(),
116
- },
117
- ]
118
- }
119
- case "reasoning": {
120
- const r = item
121
- if (r.content) {
122
- return [
123
- {
124
- type: "assistant_thinking",
125
- text: r.content,
126
- ts: ts(),
127
- },
128
- ]
129
- }
130
- return []
131
- }
132
- default:
133
- return []
134
- }
135
- }
136
- function handleItemCompleted(msg, state) {
137
- const item = msg.item
138
- if (!item?.type) return []
139
- switch (item.type) {
140
- case "agent_message": {
141
- const am = item
142
- const text = extractMessageText(am.content)
143
- if (text) {
144
- return [
145
- {
146
- type: "assistant_message",
147
- text,
148
- ts: ts(),
149
- },
150
- ]
151
- }
152
- return []
153
- }
154
- case "command_execution": {
155
- const ce = item
156
- const toolUseId = ce.id ?? ""
157
- const toolName = state.toolNames.get(toolUseId) ?? "Bash"
158
- const isError = ce.exit_code != null && ce.exit_code !== 0
159
- const response = ce.output ?? ""
160
- if (isError) {
161
- return [
162
- {
163
- type: "post_tool_use",
164
- tool_use_id: toolUseId,
165
- tool_name: toolName,
166
- tool_response: response,
167
- error: response || `Exit code: ${ce.exit_code}`,
168
- ts: ts(),
169
- },
170
- ]
171
- }
172
- return [
173
- {
174
- type: "post_tool_use",
175
- tool_use_id: toolUseId,
176
- tool_name: toolName,
177
- tool_response: response,
178
- ts: ts(),
179
- },
180
- ]
181
- }
182
- case "file_change": {
183
- const fc = item
184
- const toolUseId = fc.id ?? ""
185
- const toolName = state.toolNames.get(toolUseId) ?? "Write"
186
- return [
187
- {
188
- type: "post_tool_use",
189
- tool_use_id: toolUseId,
190
- tool_name: toolName,
191
- tool_response:
192
- fc.diff ?? fc.content ?? `File ${fc.action ?? "changed"}: ${fc.file_path ?? ""}`,
193
- ts: ts(),
194
- },
195
- ]
196
- }
197
- case "mcp_tool_call": {
198
- const mc = item
199
- const toolUseId = mc.id ?? ""
200
- const toolName = state.toolNames.get(toolUseId) ?? "mcp_tool"
201
- return [
202
- {
203
- type: "post_tool_use",
204
- tool_use_id: toolUseId,
205
- tool_name: toolName,
206
- tool_response: mc.result ?? "",
207
- ts: ts(),
208
- },
209
- ]
210
- }
211
- case "reasoning": {
212
- const r = item
213
- if (r.content) {
214
- return [
215
- {
216
- type: "assistant_thinking",
217
- text: r.content,
218
- ts: ts(),
219
- },
220
- ]
221
- }
222
- return []
223
- }
224
- default:
225
- return []
226
- }
227
- }
228
- function handleTurnCompleted(msg, state) {
229
- const events = []
230
- if (msg.cost_usd != null) {
231
- state.totalCost += msg.cost_usd
232
- events.push({
233
- type: "cost_update",
234
- totalCostUsd: state.totalCost,
235
- ts: ts(),
236
- })
237
- }
238
- return events
239
- }
240
- function handleTurnFailed(msg) {
241
- return [
242
- {
243
- type: "log",
244
- level: "error",
245
- message: msg.error ?? "Turn failed",
246
- ts: ts(),
247
- },
248
- ]
249
- }
250
- // ---------------------------------------------------------------------------
251
- // Helpers
252
- // ---------------------------------------------------------------------------
253
- function extractMessageText(content) {
254
- if (content == null) return ""
255
- if (typeof content === "string") return content
256
- if (Array.isArray(content)) {
257
- return content
258
- .map((block) => {
259
- if (block.type === "text" && typeof block.text === "string") return block.text
260
- return ""
261
- })
262
- .filter(Boolean)
263
- .join("\n")
264
- }
265
- return String(content)
266
- }
267
- //# sourceMappingURL=codex-json-parser.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"codex-json-parser.js","sourceRoot":"","sources":["../../src/bridge/codex-json-parser.ts"],"names":[],"mappings":"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"}
@@ -1,14 +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 type { ClaudeMdOptions } from "./claude-md-generator.js"
9
- /**
10
- * Generate an AGENTS.md file for Codex CLI mode.
11
- * Uses the same stack-specific content as Claude Code mode.
12
- */
13
- export declare function generateCodexMd(opts: ClaudeMdOptions): string
14
- //# sourceMappingURL=codex-md-generator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"codex-md-generator.d.ts","sourceRoot":"","sources":["../../src/bridge/codex-md-generator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAa/D;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAoC7D"}
@@ -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