@electric-agent/studio 1.1.1 → 1.3.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.
- package/dist/bridge/claude-code-docker.d.ts +11 -0
- package/dist/bridge/claude-code-docker.d.ts.map +1 -1
- package/dist/bridge/claude-code-docker.js +103 -22
- package/dist/bridge/claude-code-docker.js.map +1 -1
- package/dist/bridge/claude-code-sprites.d.ts +10 -1
- package/dist/bridge/claude-code-sprites.d.ts.map +1 -1
- package/dist/bridge/claude-code-sprites.js +120 -44
- package/dist/bridge/claude-code-sprites.js.map +1 -1
- package/dist/bridge/claude-md-generator.d.ts +1 -0
- package/dist/bridge/claude-md-generator.d.ts.map +1 -1
- package/dist/bridge/claude-md-generator.js +64 -11
- package/dist/bridge/claude-md-generator.js.map +1 -1
- package/dist/bridge/codex-docker.d.ts +65 -0
- package/dist/bridge/codex-docker.d.ts.map +1 -0
- package/dist/bridge/codex-docker.js +242 -0
- package/dist/bridge/codex-docker.js.map +1 -0
- package/dist/bridge/codex-json-parser.d.ts +31 -0
- package/dist/bridge/codex-json-parser.d.ts.map +1 -0
- package/dist/bridge/codex-json-parser.js +274 -0
- package/dist/bridge/codex-json-parser.js.map +1 -0
- package/dist/bridge/codex-md-generator.d.ts +14 -0
- package/dist/bridge/codex-md-generator.d.ts.map +1 -0
- package/dist/bridge/codex-md-generator.js +45 -0
- package/dist/bridge/codex-md-generator.js.map +1 -0
- package/dist/bridge/codex-sprites.d.ts +59 -0
- package/dist/bridge/codex-sprites.d.ts.map +1 -0
- package/dist/bridge/codex-sprites.js +237 -0
- package/dist/bridge/codex-sprites.js.map +1 -0
- package/dist/bridge/create-app-skill.d.ts +11 -0
- package/dist/bridge/create-app-skill.d.ts.map +1 -0
- package/dist/bridge/create-app-skill.js +39 -0
- package/dist/bridge/create-app-skill.js.map +1 -0
- package/dist/bridge/index.d.ts +0 -3
- package/dist/bridge/index.d.ts.map +1 -1
- package/dist/bridge/index.js +0 -3
- package/dist/bridge/index.js.map +1 -1
- package/dist/bridge/stream-json-parser.d.ts +0 -2
- package/dist/bridge/stream-json-parser.d.ts.map +1 -1
- package/dist/bridge/stream-json-parser.js +0 -18
- package/dist/bridge/stream-json-parser.js.map +1 -1
- package/dist/client/assets/index-Bq9zwhHj.css +1 -0
- package/dist/client/assets/index-Dgpqg5fv.js +234 -0
- package/dist/client/index.html +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/sandbox/daytona.js +4 -4
- package/dist/sandbox/daytona.js.map +1 -1
- package/dist/sandbox/docker.d.ts +0 -1
- package/dist/sandbox/docker.d.ts.map +1 -1
- package/dist/sandbox/docker.js +10 -42
- package/dist/sandbox/docker.js.map +1 -1
- package/dist/sandbox/sprites.d.ts +0 -6
- package/dist/sandbox/sprites.d.ts.map +1 -1
- package/dist/sandbox/sprites.js +4 -36
- package/dist/sandbox/sprites.js.map +1 -1
- package/dist/sandbox/types.d.ts +0 -8
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/server.d.ts +2 -5
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +187 -161
- package/dist/server.js.map +1 -1
- package/dist/session-auth.d.ts +3 -0
- package/dist/session-auth.d.ts.map +1 -0
- package/dist/session-auth.js +11 -0
- package/dist/session-auth.js.map +1 -0
- package/dist/sessions.d.ts +0 -2
- package/dist/sessions.d.ts.map +1 -1
- package/dist/sessions.js.map +1 -1
- package/package.json +2 -2
- package/dist/client/assets/index-BeZ6CTGd.css +0 -1
- 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,6 +136,35 @@ 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
|
|
@@ -134,7 +173,7 @@ function devServerInstructions(runtime) {
|
|
|
134
173
|
- \`pnpm dev:stop\` — stop the dev server
|
|
135
174
|
- \`pnpm dev:restart\` — stop then start
|
|
136
175
|
|
|
137
|
-
The app
|
|
176
|
+
The app listens on port 8080 (set via VITE_PORT) — this is the only port the Sprite proxy exposes.
|
|
138
177
|
The database and Electric sync service are remote (cloud-hosted) — there is no local Postgres or Docker.
|
|
139
178
|
|
|
140
179
|
### Migrations (CRITICAL)
|
|
@@ -144,13 +183,6 @@ pnpm drizzle-kit generate # generate SQL from schema changes
|
|
|
144
183
|
pnpm drizzle-kit migrate # apply migration to the database
|
|
145
184
|
\`\`\`
|
|
146
185
|
|
|
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
186
|
### Workflow
|
|
155
187
|
After finishing ALL code generation: run migrations, then \`pnpm dev:start\` so the user can preview the app.`;
|
|
156
188
|
}
|
|
@@ -180,6 +212,22 @@ This is needed because useLiveQuery uses useSyncExternalStore without getServerS
|
|
|
180
212
|
// ---------------------------------------------------------------------------
|
|
181
213
|
// Claude Code–only sections
|
|
182
214
|
// ---------------------------------------------------------------------------
|
|
215
|
+
const SKILL_AUTO_TRIGGER = `## App Generation Pipeline (CRITICAL)
|
|
216
|
+
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.
|
|
217
|
+
|
|
218
|
+
Invoke it with: /create-app <description>
|
|
219
|
+
|
|
220
|
+
The skill enforces the correct phase order:
|
|
221
|
+
1. Clarification (if description is vague)
|
|
222
|
+
2. Plan generation (PLAN.md with data model + tasks)
|
|
223
|
+
3. Data model validation (schema + zod-schemas + tests — STOP if tests fail)
|
|
224
|
+
4. Collections & API routes
|
|
225
|
+
5. UI components
|
|
226
|
+
6. Build & lint
|
|
227
|
+
7. Final tests
|
|
228
|
+
8. Architecture reference (ARCHITECTURE.md)
|
|
229
|
+
|
|
230
|
+
Do NOT skip phases or code ad-hoc. Always follow the skill's structured pipeline.`;
|
|
183
231
|
const PLAYBOOK_INSTRUCTIONS = `## Playbooks (Domain Knowledge — MUST READ)
|
|
184
232
|
Playbook SKILL.md files contain critical API usage patterns. Read them BEFORE writing code for each phase.
|
|
185
233
|
|
|
@@ -296,6 +344,11 @@ You have git and gh CLI available via Bash. Use them when needed:
|
|
|
296
344
|
- \`gh repo create "org/name" --private --source . --remote origin --push\` — create repo
|
|
297
345
|
- \`gh pr create --title "..." --body "..."\` — create PR
|
|
298
346
|
Commit types: feat, fix, refactor, style, chore, docs, test`;
|
|
347
|
+
// ---------------------------------------------------------------------------
|
|
348
|
+
// Create-app skill content — exported so the server can write it to sandboxes
|
|
349
|
+
// where the npm-installed electric-agent may not include it yet.
|
|
350
|
+
// ---------------------------------------------------------------------------
|
|
351
|
+
export { createAppSkillContent } from "./create-app-skill.js";
|
|
299
352
|
const ERROR_HANDLING = `## Error Handling
|
|
300
353
|
Before fixing any error, check _agent/errors.md for previous attempts at the same fix.
|
|
301
354
|
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":"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
|
|
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":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAqB,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAEvD,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAA;AAE7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAc9D,MAAM,OAAO,iBAAiB;IACpB,SAAS,CAAQ;IACjB,SAAS,CAAQ;IACjB,aAAa,CAAwB;IAEtC,WAAW,CAAQ;IACnB,MAAM,CAAmB;IACzB,MAAM,CAAe;IACrB,MAAM,GAAG,qBAAqB,EAAE,CAAA;IAChC,mBAAmB,GAAwC,EAAE,CAAA;IAC7D,iBAAiB,GAAsC,EAAE,CAAA;IACzD,MAAM,GAAG,KAAK,CAAA;IACd,IAAI,GAAwB,IAAI,CAAA;IAExC,qEAAqE;IAC7D,aAAa,GAAkB,IAAI,CAAA;IAC3C,mDAAmD;IAC3C,OAAO,GAAG,KAAK,CAAA;IACvB,uDAAuD;IAC/C,cAAc,GAAG,KAAK,CAAA;IAE9B,YACC,SAAiB,EACjB,UAAgC,EAChC,WAAmB,EACnB,MAAyB;QAEzB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAC1B,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,GAAG,CAAA;QAC/B,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,OAAO,CAAA;QACvC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAA;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QAEpB,IAAI,CAAC,MAAM,GAAG,IAAI,aAAa,CAAC;YAC/B,GAAG,EAAE,UAAU,CAAC,GAAG;YACnB,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,WAAW,EAAE,kBAAkB;SAC/B,CAAC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAkB;QAC5B,IAAI,IAAI,CAAC,MAAM;YAAE,OAAM;QACvB,MAAM,GAAG,GAAkB,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,CAAA;QACzD,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;IAC9C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,GAA4B;QAC7C,IAAI,IAAI,CAAC,MAAM;YAAE,OAAM;QAEvB,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAClE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAC5B,OAAM;QACP,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,gDAAgD,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;IAC3E,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CAAC,KAAa,EAAE,MAA+B;QACpE,gEAAgE;IACjE,CAAC;IAED,YAAY,CAAC,EAAgC;QAC5C,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAClC,CAAC;IAED,UAAU,CAAC,EAA8B;QACxC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChC,CAAC;IAED,KAAK,CAAC,KAAK;QACV,IAAI,IAAI,CAAC,MAAM;YAAE,OAAM;QACvB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACpC,CAAC;IAED,KAAK;QACJ,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,IAAI,CAAC;gBACJ,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAA;gBACtB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACR,8BAA8B;YAC/B,CAAC;YACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QACjB,CAAC;IACF,CAAC;IAED,0EAA0E;IAC1E,kBAAkB;IAClB,0EAA0E;IAE1E;;;OAGG;IACK,UAAU,CAAC,MAAc;QAChC,4BAA4B;QAC5B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,IAAI,CAAC;gBACJ,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAA;gBACtB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACR,eAAe;YAChB,CAAC;YACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QACjB,CAAC;QAED,yCAAyC;QACzC,IAAI,CAAC,MAAM,GAAG,qBAAqB,EAAE,CAAA;QACrC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAA;QAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QAEnB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS,CAAA;QAE5C,8BAA8B;QAC9B,MAAM,SAAS,GAAG;YACjB,MAAM;YACN,QAAQ;YACR,aAAa;YACb,SAAS;YACT,KAAK;YACL,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;YACjC,IAAI;YACJ,MAAM;SACN,CAAA;QAED,kBAAkB;QAClB,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACnF,MAAM,GAAG,GAAG,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,cAAc,WAAW,EAAE,CAAA;QAE7D,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE;YAC1E,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAC/B,CAAC,CAAA;QAEF,OAAO,CAAC,GAAG,CACV,mCAAmC,IAAI,CAAC,SAAS,cAAc,IAAI,CAAC,WAAW,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CACtG,CAAA;QACD,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,EAAE,CAAC,CAAA;QAEzC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAA;QAE7B,gDAAgD;QAChD,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;YACxB,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;gBACnC,KAAK,EAAE,WAAW,CAAC,MAAM;gBACzB,QAAQ,EAAE,KAAK;aACf,CAAC,CAAA;YAEF,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBACtB,IAAI,IAAI,CAAC,MAAM;oBAAE,OAAM;gBACvB,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAA;gBAC7D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;YACtB,CAAC,CAAC,CAAA;QACH,CAAC;QAED,aAAa;QACb,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,QAAQ,CAAC,eAAe,CAAC;gBACzC,KAAK,EAAE,WAAW,CAAC,MAAM;gBACzB,QAAQ,EAAE,KAAK;aACf,CAAC,CAAA;YACF,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBAC5B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;oBAClB,OAAO,CAAC,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAA;gBAC/C,CAAC;YACF,CAAC,CAAC,CAAA;QACH,CAAC;QAED,yEAAyE;QACzE,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAC/B,OAAO,CAAC,GAAG,CAAC,uCAAuC,IAAI,YAAY,IAAI,CAAC,SAAS,EAAE,CAAC,CAAA;YACpF,UAAU,CAAC,GAAG,EAAE;gBACf,iEAAiE;gBACjE,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;oBAChC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAA;gBAChD,CAAC;gBACD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;gBAEpB,gDAAgD;gBAChD,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;oBAC1C,MAAM,QAAQ,GAAgB;wBAC7B,IAAI,EAAE,aAAa;wBACnB,OAAO,EAAE,IAAI,KAAK,CAAC;wBACnB,EAAE,EAAE,EAAE,EAAE;qBACR,CAAA;oBACD,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;gBAC7B,CAAC;YACF,CAAC,EAAE,GAAG,CAAC,CAAA;QACR,CAAC,CAAC,CAAA;IACH,CAAC;IAEO,UAAU,CAAC,IAAY;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;QAC3B,IAAI,CAAC,OAAO;YAAE,OAAM;QAEpB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACzC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;QAC1B,CAAC;IACF,CAAC;IAEO,aAAa,CAAC,KAAkB;QACvC,iCAAiC;QACjC,MAAM,GAAG,GAAkB,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAA;QACxD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAEvD,0CAA0C;QAC1C,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;QAC3B,CAAC;QAED,wEAAwE;QACxE,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;YACjE,MAAM,GAAG,GAAI,KAAK,CAAC,UAAsC,EAAE,OAAO,CAAA;YAClE,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1D,MAAM,QAAQ,GAAgB,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAA;gBAC7D,MAAM,WAAW,GAAkB,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAA;gBACnE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;gBAC/D,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;oBAC3C,IAAI,CAAC;wBACJ,EAAE,CAAC,QAAQ,CAAC,CAAA;oBACb,CAAC;oBAAC,MAAM,CAAC;wBACR,UAAU;oBACX,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;QAED,wBAAwB;QACxB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC3C,IAAI,CAAC;gBACJ,EAAE,CAAC,KAAK,CAAC,CAAA;YACV,CAAC;YAAC,MAAM,CAAC;gBACR,0BAA0B;YAC3B,CAAC;QACF,CAAC;QAED,qBAAqB;QACrB,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;YACxD,MAAM,OAAO,GAAI,KAA4C,CAAC,OAAO,CAAA;YACrE,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBACzC,IAAI,CAAC;oBACJ,EAAE,CAAC,OAAO,CAAC,CAAA;gBACZ,CAAC;gBAAC,MAAM,CAAC;oBACR,0BAA0B;gBAC3B,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;CACD"}
|
|
@@ -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"}
|