@electric-agent/studio 1.1.1 → 1.3.4

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 (79) hide show
  1. package/dist/bridge/claude-code-docker.d.ts +14 -0
  2. package/dist/bridge/claude-code-docker.d.ts.map +1 -1
  3. package/dist/bridge/claude-code-docker.js +121 -22
  4. package/dist/bridge/claude-code-docker.js.map +1 -1
  5. package/dist/bridge/claude-code-sprites.d.ts +13 -1
  6. package/dist/bridge/claude-code-sprites.d.ts.map +1 -1
  7. package/dist/bridge/claude-code-sprites.js +122 -26
  8. package/dist/bridge/claude-code-sprites.js.map +1 -1
  9. package/dist/bridge/claude-md-generator.d.ts +1 -0
  10. package/dist/bridge/claude-md-generator.d.ts.map +1 -1
  11. package/dist/bridge/claude-md-generator.js +67 -12
  12. package/dist/bridge/claude-md-generator.js.map +1 -1
  13. package/dist/bridge/codex-docker.d.ts +65 -0
  14. package/dist/bridge/codex-docker.d.ts.map +1 -0
  15. package/dist/bridge/codex-docker.js +242 -0
  16. package/dist/bridge/codex-docker.js.map +1 -0
  17. package/dist/bridge/codex-json-parser.d.ts +31 -0
  18. package/dist/bridge/codex-json-parser.d.ts.map +1 -0
  19. package/dist/bridge/codex-json-parser.js +274 -0
  20. package/dist/bridge/codex-json-parser.js.map +1 -0
  21. package/dist/bridge/codex-md-generator.d.ts +14 -0
  22. package/dist/bridge/codex-md-generator.d.ts.map +1 -0
  23. package/dist/bridge/codex-md-generator.js +45 -0
  24. package/dist/bridge/codex-md-generator.js.map +1 -0
  25. package/dist/bridge/codex-sprites.d.ts +59 -0
  26. package/dist/bridge/codex-sprites.d.ts.map +1 -0
  27. package/dist/bridge/codex-sprites.js +237 -0
  28. package/dist/bridge/codex-sprites.js.map +1 -0
  29. package/dist/bridge/create-app-skill.d.ts +11 -0
  30. package/dist/bridge/create-app-skill.d.ts.map +1 -0
  31. package/dist/bridge/create-app-skill.js +39 -0
  32. package/dist/bridge/create-app-skill.js.map +1 -0
  33. package/dist/bridge/hosted.d.ts +1 -0
  34. package/dist/bridge/hosted.d.ts.map +1 -1
  35. package/dist/bridge/hosted.js +4 -0
  36. package/dist/bridge/hosted.js.map +1 -1
  37. package/dist/bridge/index.d.ts +0 -3
  38. package/dist/bridge/index.d.ts.map +1 -1
  39. package/dist/bridge/index.js +0 -3
  40. package/dist/bridge/index.js.map +1 -1
  41. package/dist/bridge/stream-json-parser.d.ts +0 -2
  42. package/dist/bridge/stream-json-parser.d.ts.map +1 -1
  43. package/dist/bridge/stream-json-parser.js +0 -18
  44. package/dist/bridge/stream-json-parser.js.map +1 -1
  45. package/dist/bridge/types.d.ts +6 -0
  46. package/dist/bridge/types.d.ts.map +1 -1
  47. package/dist/client/assets/index-B6arNdVE.css +1 -0
  48. package/dist/client/assets/index-CxBu-PUg.js +234 -0
  49. package/dist/client/index.html +2 -2
  50. package/dist/index.d.ts +1 -0
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +1 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/sandbox/daytona.js +4 -4
  55. package/dist/sandbox/daytona.js.map +1 -1
  56. package/dist/sandbox/docker.d.ts +0 -1
  57. package/dist/sandbox/docker.d.ts.map +1 -1
  58. package/dist/sandbox/docker.js +10 -42
  59. package/dist/sandbox/docker.js.map +1 -1
  60. package/dist/sandbox/sprites.d.ts +0 -6
  61. package/dist/sandbox/sprites.d.ts.map +1 -1
  62. package/dist/sandbox/sprites.js +4 -36
  63. package/dist/sandbox/sprites.js.map +1 -1
  64. package/dist/sandbox/types.d.ts +0 -8
  65. package/dist/sandbox/types.d.ts.map +1 -1
  66. package/dist/server.d.ts +2 -5
  67. package/dist/server.d.ts.map +1 -1
  68. package/dist/server.js +212 -161
  69. package/dist/server.js.map +1 -1
  70. package/dist/session-auth.d.ts +3 -0
  71. package/dist/session-auth.d.ts.map +1 -0
  72. package/dist/session-auth.js +11 -0
  73. package/dist/session-auth.js.map +1 -0
  74. package/dist/sessions.d.ts +0 -2
  75. package/dist/sessions.d.ts.map +1 -1
  76. package/dist/sessions.js.map +1 -1
  77. package/package.json +2 -2
  78. package/dist/client/assets/index-BeZ6CTGd.css +0 -1
  79. package/dist/client/assets/index-DRLXdDNp.js +0 -241
@@ -14,10 +14,17 @@ export function generateClaudeMd(opts) {
14
14
  sections.push("");
15
15
  sections.push(PROJECT_CONTEXT);
16
16
  sections.push("");
17
+ const sandbox = sandboxEnvironment(opts.runtime);
18
+ if (sandbox) {
19
+ sections.push(sandbox);
20
+ sections.push("");
21
+ }
17
22
  if (!opts.isIteration) {
18
23
  sections.push("## Current Task");
19
24
  sections.push(opts.description);
20
25
  sections.push("");
26
+ sections.push(SKILL_AUTO_TRIGGER);
27
+ sections.push("");
21
28
  }
22
29
  sections.push(SCAFFOLD_STRUCTURE);
23
30
  sections.push("");
@@ -44,6 +51,11 @@ export function generateElectricAgentClaudeMd(opts) {
44
51
  sections.push("");
45
52
  sections.push(PROJECT_CONTEXT);
46
53
  sections.push("");
54
+ const sandbox = sandboxEnvironment(opts.runtime);
55
+ if (sandbox) {
56
+ sections.push(sandbox);
57
+ sections.push("");
58
+ }
47
59
  if (!opts.isIteration) {
48
60
  sections.push("## Current Task");
49
61
  sections.push(opts.description);
@@ -98,6 +110,7 @@ const GUARDRAILS = `## Guardrails (MUST FOLLOW)
98
110
 
99
111
  ### Protected Files — DO NOT MODIFY
100
112
  - docker-compose.yml
113
+ - vite.config.ts (pre-configured with port, host, allowedHosts, and proxy — modifying it WILL break the preview)
101
114
  - tsconfig.json
102
115
  - biome.json
103
116
  - pnpm-lock.yaml
@@ -111,9 +124,6 @@ const GUARDRAILS = `## Guardrails (MUST FOLLOW)
111
124
  - Use "@radix-ui/themes" for Radix components (NOT @radix-ui/react-*)
112
125
  - Use "react-router" for routing (NOT react-router-dom)
113
126
 
114
- ### Vite Config Rules
115
- - When modifying vite.config.ts, ALWAYS preserve \`server: { allowedHosts: true }\` — without it, Vite rejects connections from the proxy URL
116
-
117
127
  ### Dependency Rules
118
128
  - NEVER remove existing dependencies from package.json
119
129
  - Only add new dependencies
@@ -126,15 +136,46 @@ const GUARDRAILS = `## Guardrails (MUST FOLLOW)
126
136
  - timestamp({ withTimezone: true }) for all dates
127
137
  - snake_case for SQL table/column names
128
138
  - Foreign keys with onDelete: "cascade" where appropriate`;
139
+ function sandboxEnvironment(runtime) {
140
+ if (runtime === "sprites" || runtime === "daytona") {
141
+ return `## Sandbox Environment (IMPORTANT — READ FIRST)
142
+ You are running inside a cloud micro-VM (Fly.io Sprite). This is NOT a local machine.
143
+
144
+ ### Networking & Port Exposure
145
+ - The Sprite HTTP proxy routes all external traffic to **port 8080** inside the VM
146
+ - Your app MUST listen on port 8080 to be accessible via the preview URL — this is pre-configured via the \`VITE_PORT\` environment variable
147
+ - The app MUST bind to \`0.0.0.0\` (not localhost) — pre-configured via \`host: true\` in vite.config.ts
148
+ - The preview URL follows the pattern: \`https://<sprite-name>.sprites.app\`
149
+ - There is NO way to expose other ports — only port 8080 is proxied
150
+
151
+ ### What's Available
152
+ - Node.js (via nvm at \`/.sprite/languages/node/nvm/\`)
153
+ - pnpm, git, gh CLI
154
+ - Outbound internet access (npm install, API calls, etc.)
155
+ - \`DATABASE_URL\` — remote Postgres (Neon), no local database
156
+
157
+ ### What's NOT Available
158
+ - Docker, docker-compose, or any container runtime
159
+ - Local Postgres or any local database
160
+ - Ports other than 8080 for external HTTP access
161
+
162
+ ### PATH
163
+ - npm global binaries are NOT in PATH by default
164
+ - If you need a globally installed tool, source the profile first: \`source /etc/profile.d/npm-global.sh\``;
165
+ }
166
+ return "";
167
+ }
129
168
  function devServerInstructions(runtime) {
130
169
  if (runtime === "sprites" || runtime === "daytona") {
131
170
  return `## Dev Server & Migrations
132
- ### Dev Server
171
+ ### Dev Server (CRITICAL — use pnpm scripts ONLY)
133
172
  - \`pnpm dev:start\` — start the Vite dev server in the background
134
173
  - \`pnpm dev:stop\` — stop the dev server
135
174
  - \`pnpm dev:restart\` — stop then start
136
175
 
137
- The app is exposed on the VITE_PORT environment variable (default: 5173).
176
+ **IMPORTANT**: Always use \`pnpm dev:start\` from the project directory. Do NOT use \`sprite-env services create\` or launch Vite manually — the project's vite.config.ts contains required settings (allowedHosts, port, proxy) that will not be applied if Vite is started from a different directory or with different arguments.
177
+
178
+ The app listens on port 8080 (set via VITE_PORT) — this is the only port the Sprite proxy exposes.
138
179
  The database and Electric sync service are remote (cloud-hosted) — there is no local Postgres or Docker.
139
180
 
140
181
  ### Migrations (CRITICAL)
@@ -144,13 +185,6 @@ pnpm drizzle-kit generate # generate SQL from schema changes
144
185
  pnpm drizzle-kit migrate # apply migration to the database
145
186
  \`\`\`
146
187
 
147
- ### Sprites Environment Gotchas
148
- - npm global binaries are NOT in PATH by default. If you need to run a globally installed tool, source the profile first: \`source /etc/profile.d/npm-global.sh\`
149
- - Node.js is managed via nvm at \`/.sprite/languages/node/nvm/\`
150
- - The sandbox is a cloud micro-VM — there is no Docker, no docker-compose, no local Postgres
151
- - The database connection string is in DATABASE_URL (remote Neon Postgres)
152
- - **CRITICAL**: vite.config.ts MUST have \`server: { allowedHosts: true }\` — without it, Vite rejects connections from the proxy URL and the preview will not work
153
-
154
188
  ### Workflow
155
189
  After finishing ALL code generation: run migrations, then \`pnpm dev:start\` so the user can preview the app.`;
156
190
  }
@@ -180,6 +214,22 @@ This is needed because useLiveQuery uses useSyncExternalStore without getServerS
180
214
  // ---------------------------------------------------------------------------
181
215
  // Claude Code–only sections
182
216
  // ---------------------------------------------------------------------------
217
+ const SKILL_AUTO_TRIGGER = `## App Generation Pipeline (CRITICAL)
218
+ When building a new app, you MUST use the /create-app skill. This skill is available at .claude/skills/create-app/SKILL.md and provides the structured phased pipeline for generating Electric SQL apps.
219
+
220
+ Invoke it with: /create-app <description>
221
+
222
+ The skill enforces the correct phase order:
223
+ 1. Clarification (if description is vague)
224
+ 2. Plan generation (PLAN.md with data model + tasks)
225
+ 3. Data model validation (schema + zod-schemas + tests — STOP if tests fail)
226
+ 4. Collections & API routes
227
+ 5. UI components
228
+ 6. Build & lint
229
+ 7. Final tests
230
+ 8. Architecture reference (ARCHITECTURE.md)
231
+
232
+ Do NOT skip phases or code ad-hoc. Always follow the skill's structured pipeline.`;
183
233
  const PLAYBOOK_INSTRUCTIONS = `## Playbooks (Domain Knowledge — MUST READ)
184
234
  Playbook SKILL.md files contain critical API usage patterns. Read them BEFORE writing code for each phase.
185
235
 
@@ -296,6 +346,11 @@ You have git and gh CLI available via Bash. Use them when needed:
296
346
  - \`gh repo create "org/name" --private --source . --remote origin --push\` — create repo
297
347
  - \`gh pr create --title "..." --body "..."\` — create PR
298
348
  Commit types: feat, fix, refactor, style, chore, docs, test`;
349
+ // ---------------------------------------------------------------------------
350
+ // Create-app skill content — exported so the server can write it to sandboxes
351
+ // where the npm-installed electric-agent may not include it yet.
352
+ // ---------------------------------------------------------------------------
353
+ export { createAppSkillContent } from "./create-app-skill.js";
299
354
  const ERROR_HANDLING = `## Error Handling
300
355
  Before fixing any error, check _agent/errors.md for previous attempts at the same fix.
301
356
  If you see the same error has failed before, try a different approach.
@@ -1 +1 @@
1
- {"version":3,"file":"claude-md-generator.js","sourceRoot":"","sources":["../../src/bridge/claude-md-generator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiBH,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E,MAAM,UAAU,gBAAgB,CAAC,IAAqB;IACrD,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,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;AAED,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E,MAAM,UAAU,6BAA6B,CAAC,IAAqB;IAClE,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,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,2BAA2B,CAAC,CAAA;IAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjB,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;IACjC,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,sBAAsB,CAAC,CAAA;IACrC,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,SAAS,CAAC,CAAA;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjB,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEjB,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC3B,CAAC;AAED,8EAA8E;AAC9E,0CAA0C;AAC1C,8EAA8E;AAE9E,MAAM,eAAe,GACpB,qIAAqI,CAAA;AAEtI,MAAM,kBAAkB,GAAG;;;;;;;;;;;kHAWuF,CAAA;AAElH,MAAM,gBAAgB,GAAG;;;;;;wBAMD,CAAA;AAExB,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0DA+BuC,CAAA;AAE1D,SAAS,qBAAqB,CAAC,OAAgB;IAC9C,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACpD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;8GAwBqG,CAAA;IAC7G,CAAC;IAED,OAAO;;;;;;;;;;;;;;;;;8GAiBsG,CAAA;AAC9G,CAAC;AAED,MAAM,SAAS,GAAG;;;yFAGuE,CAAA;AAEzF,8EAA8E;AAC9E,4BAA4B;AAC5B,8EAA8E;AAE9E,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qEA+BuC,CAAA;AAErE,MAAM,cAAc,GAAG;;;;;;;;;;;mIAW4G,CAAA;AAEnI,8EAA8E;AAC9E,+BAA+B;AAC/B,8EAA8E;AAE9E,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;qEAkBiC,CAAA;AAErE,MAAM,kBAAkB,GAAG;;;;;;;mDAOwB,CAAA;AAEnD,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0HAiC2F,CAAA;AAE1H,MAAM,gBAAgB,GAAG;;;;;;;4DAOmC,CAAA;AAE5D,MAAM,cAAc,GAAG;;;wCAGiB,CAAA"}
1
+ {"version":3,"file":"claude-md-generator.js","sourceRoot":"","sources":["../../src/bridge/claude-md-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * SessionBridge implementation that runs Codex CLI inside a Docker
3
+ * container via `docker exec -i`, 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 { StreamConnectionInfo } from "../streams.js";
13
+ import type { SessionBridge } from "./types.js";
14
+ export interface CodexDockerConfig {
15
+ /** Initial prompt (the user's app description or task) */
16
+ prompt: string;
17
+ /** Working directory inside the container */
18
+ cwd: string;
19
+ /** Model to use (default: o4-mini) */
20
+ model?: string;
21
+ /** Additional CLI flags */
22
+ extraFlags?: string[];
23
+ }
24
+ export declare class CodexDockerBridge implements SessionBridge {
25
+ readonly sessionId: string;
26
+ readonly streamUrl: string;
27
+ readonly streamHeaders: Record<string, string>;
28
+ private containerId;
29
+ private config;
30
+ private writer;
31
+ private parser;
32
+ private agentEventCallbacks;
33
+ private completeCallbacks;
34
+ private closed;
35
+ private proc;
36
+ /** Codex thread ID captured from thread.started — used for resume */
37
+ private codexThreadId;
38
+ /** Whether a Codex process is currently running */
39
+ private running;
40
+ /** Whether the parser already emitted a session_end */
41
+ private resultReceived;
42
+ constructor(sessionId: string, connection: StreamConnectionInfo, containerId: string, config: CodexDockerConfig);
43
+ emit(event: EngineEvent): Promise<void>;
44
+ /**
45
+ * Send a follow-up user message to Codex by respawning with a new prompt.
46
+ */
47
+ sendCommand(cmd: Record<string, unknown>): Promise<void>;
48
+ /**
49
+ * Send a gate response. Codex exec mode doesn't support stdin interaction,
50
+ * so gate responses are limited.
51
+ */
52
+ sendGateResponse(_gate: string, _value: Record<string, unknown>): Promise<void>;
53
+ onAgentEvent(cb: (event: EngineEvent) => void): void;
54
+ onComplete(cb: (success: boolean) => void): void;
55
+ start(): Promise<void>;
56
+ close(): void;
57
+ /**
58
+ * Spawn a new Codex process. Called for both the initial prompt
59
+ * and follow-up iterate messages.
60
+ */
61
+ private spawnCodex;
62
+ private handleLine;
63
+ private dispatchEvent;
64
+ }
65
+ //# sourceMappingURL=codex-docker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-docker.d.ts","sourceRoot":"","sources":["../../src/bridge/codex-docker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAE3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAEzD,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAE9D,MAAM,WAAW,iBAAiB;IACjC,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAA;IACX,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,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,CAAmB;IACjC,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,IAAI,CAA4B;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,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,iBAAiB;IAepB,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7C;;OAEG;IACG,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAW9D;;;OAGG;IACG,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;IAiBb;;;OAGG;IACH,OAAO,CAAC,UAAU;IAgGlB,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,aAAa;CAgDrB"}
@@ -0,0 +1,242 @@
1
+ /**
2
+ * SessionBridge implementation that runs Codex CLI inside a Docker
3
+ * container via `docker exec -i`, 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 { spawn } from "node:child_process";
12
+ import * as readline from "node:readline";
13
+ import { DurableStream } from "@durable-streams/client";
14
+ import { ts } from "@electric-agent/protocol";
15
+ import { createCodexJsonParser } from "./codex-json-parser.js";
16
+ export class CodexDockerBridge {
17
+ sessionId;
18
+ streamUrl;
19
+ streamHeaders;
20
+ containerId;
21
+ config;
22
+ writer;
23
+ parser = createCodexJsonParser();
24
+ agentEventCallbacks = [];
25
+ completeCallbacks = [];
26
+ closed = false;
27
+ proc = 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, containerId, config) {
35
+ this.sessionId = sessionId;
36
+ this.streamUrl = connection.url;
37
+ this.streamHeaders = connection.headers;
38
+ this.containerId = containerId;
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)
48
+ return;
49
+ const msg = { source: "server", ...event };
50
+ await this.writer.append(JSON.stringify(msg));
51
+ }
52
+ /**
53
+ * Send a follow-up user message to Codex by respawning with a new prompt.
54
+ */
55
+ async sendCommand(cmd) {
56
+ if (this.closed)
57
+ return;
58
+ if (cmd.command === "iterate" && typeof cmd.request === "string") {
59
+ this.spawnCodex(cmd.request);
60
+ return;
61
+ }
62
+ console.log(`[codex-docker] Ignoring unsupported command: ${cmd.command}`);
63
+ }
64
+ /**
65
+ * Send a gate response. Codex exec mode doesn't support stdin interaction,
66
+ * so gate responses are limited.
67
+ */
68
+ async sendGateResponse(_gate, _value) {
69
+ // Codex exec --json doesn't support stdin user messages mid-run
70
+ }
71
+ onAgentEvent(cb) {
72
+ this.agentEventCallbacks.push(cb);
73
+ }
74
+ onComplete(cb) {
75
+ this.completeCallbacks.push(cb);
76
+ }
77
+ async start() {
78
+ if (this.closed)
79
+ return;
80
+ this.spawnCodex(this.config.prompt);
81
+ }
82
+ close() {
83
+ this.closed = true;
84
+ if (this.proc) {
85
+ try {
86
+ this.proc.stdin?.end();
87
+ this.proc.kill("SIGTERM");
88
+ }
89
+ catch {
90
+ // Process may already be dead
91
+ }
92
+ this.proc = null;
93
+ }
94
+ }
95
+ // -----------------------------------------------------------------------
96
+ // Private helpers
97
+ // -----------------------------------------------------------------------
98
+ /**
99
+ * Spawn a new Codex process. Called for both the initial prompt
100
+ * and follow-up iterate messages.
101
+ */
102
+ spawnCodex(prompt) {
103
+ // Kill any existing process
104
+ if (this.proc) {
105
+ try {
106
+ this.proc.stdin?.end();
107
+ this.proc.kill("SIGTERM");
108
+ }
109
+ catch {
110
+ // Already dead
111
+ }
112
+ this.proc = null;
113
+ }
114
+ // Reset parser state for the new process
115
+ this.parser = createCodexJsonParser();
116
+ this.resultReceived = false;
117
+ this.running = true;
118
+ const model = this.config.model ?? "o4-mini";
119
+ // Build the codex CLI command
120
+ const codexArgs = [
121
+ "exec",
122
+ "--json",
123
+ "--full-auto",
124
+ "--model",
125
+ model,
126
+ ...(this.config.extraFlags ?? []),
127
+ "-q",
128
+ prompt,
129
+ ];
130
+ // Escape for bash
131
+ const escapedArgs = codexArgs.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ");
132
+ const cmd = `cd '${this.config.cwd}' && codex ${escapedArgs}`;
133
+ this.proc = spawn("docker", ["exec", this.containerId, "bash", "-c", cmd], {
134
+ stdio: ["pipe", "pipe", "pipe"],
135
+ });
136
+ console.log(`[codex-docker] Started: session=${this.sessionId} container=${this.containerId} pid=${this.proc.pid}`);
137
+ console.log(`[codex-docker] cmd: ${cmd}`);
138
+ const currentProc = this.proc;
139
+ // Read stdout line by line (exec --json NDJSON)
140
+ if (currentProc.stdout) {
141
+ const rl = readline.createInterface({
142
+ input: currentProc.stdout,
143
+ terminal: false,
144
+ });
145
+ rl.on("line", (line) => {
146
+ if (this.closed)
147
+ return;
148
+ console.log(`[codex-docker:stdout] ${line.slice(0, 120)}...`);
149
+ this.handleLine(line);
150
+ });
151
+ }
152
+ // Log stderr
153
+ if (currentProc.stderr) {
154
+ const stderrRl = readline.createInterface({
155
+ input: currentProc.stderr,
156
+ terminal: false,
157
+ });
158
+ stderrRl.on("line", (line) => {
159
+ if (!this.closed) {
160
+ console.error(`[codex-docker:stderr] ${line}`);
161
+ }
162
+ });
163
+ }
164
+ // Handle process exit — defer to let pending readline events flush first
165
+ currentProc.on("exit", (code) => {
166
+ console.log(`[codex-docker] Process exited: code=${code} session=${this.sessionId}`);
167
+ setTimeout(() => {
168
+ // Capture thread ID from parser state before marking not running
169
+ if (this.parser.state.threadId) {
170
+ this.codexThreadId = this.parser.state.threadId;
171
+ }
172
+ this.running = false;
173
+ // Emit session_end if the parser didn't already
174
+ if (!this.closed && !this.resultReceived) {
175
+ const endEvent = {
176
+ type: "session_end",
177
+ success: code === 0,
178
+ ts: ts(),
179
+ };
180
+ this.dispatchEvent(endEvent);
181
+ }
182
+ }, 100);
183
+ });
184
+ }
185
+ handleLine(line) {
186
+ const trimmed = line.trim();
187
+ if (!trimmed)
188
+ return;
189
+ const events = this.parser.parse(trimmed);
190
+ for (const event of events) {
191
+ this.dispatchEvent(event);
192
+ }
193
+ }
194
+ dispatchEvent(event) {
195
+ // Write to Durable Stream for UI
196
+ const msg = { source: "agent", ...event };
197
+ this.writer.append(JSON.stringify(msg)).catch(() => { });
198
+ // Track session_end to prevent duplicates
199
+ if (event.type === "session_end") {
200
+ this.resultReceived = true;
201
+ }
202
+ // Detect dev:start in Bash tool_use → emit app_ready for the UI preview
203
+ if (event.type === "pre_tool_use" && event.tool_name === "Bash") {
204
+ const cmd = event.tool_input?.command;
205
+ if (typeof cmd === "string" && /\bdev:start\b/.test(cmd)) {
206
+ const appReady = { type: "app_ready", ts: ts() };
207
+ const appReadyMsg = { source: "agent", ...appReady };
208
+ this.writer.append(JSON.stringify(appReadyMsg)).catch(() => { });
209
+ for (const cb of this.agentEventCallbacks) {
210
+ try {
211
+ cb(appReady);
212
+ }
213
+ catch {
214
+ // Swallow
215
+ }
216
+ }
217
+ }
218
+ }
219
+ // Dispatch to callbacks
220
+ for (const cb of this.agentEventCallbacks) {
221
+ try {
222
+ cb(event);
223
+ }
224
+ catch {
225
+ // Swallow callback errors
226
+ }
227
+ }
228
+ // Detect session_end
229
+ if (event.type === "session_end" && "success" in event) {
230
+ const success = event.success;
231
+ for (const cb of this.completeCallbacks) {
232
+ try {
233
+ cb(success);
234
+ }
235
+ catch {
236
+ // Swallow callback errors
237
+ }
238
+ }
239
+ }
240
+ }
241
+ }
242
+ //# sourceMappingURL=codex-docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-docker.js","sourceRoot":"","sources":["../../src/bridge/codex-docker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
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
@@ -0,0 +1 @@
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"}