@electric-agent/studio 1.5.0 → 1.12.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 (109) hide show
  1. package/dist/api-schemas.d.ts +225 -0
  2. package/dist/api-schemas.d.ts.map +1 -0
  3. package/dist/api-schemas.js +95 -0
  4. package/dist/api-schemas.js.map +1 -0
  5. package/dist/bridge/claude-code-base.d.ts +121 -0
  6. package/dist/bridge/claude-code-base.d.ts.map +1 -0
  7. package/dist/bridge/claude-code-base.js +263 -0
  8. package/dist/bridge/claude-code-base.js.map +1 -0
  9. package/dist/bridge/claude-code-docker.d.ts +13 -73
  10. package/dist/bridge/claude-code-docker.d.ts.map +1 -1
  11. package/dist/bridge/claude-code-docker.js +91 -302
  12. package/dist/bridge/claude-code-docker.js.map +1 -1
  13. package/dist/bridge/claude-code-sprites.d.ts +12 -59
  14. package/dist/bridge/claude-code-sprites.d.ts.map +1 -1
  15. package/dist/bridge/claude-code-sprites.js +88 -281
  16. package/dist/bridge/claude-code-sprites.js.map +1 -1
  17. package/dist/bridge/claude-md-generator.d.ts +22 -5
  18. package/dist/bridge/claude-md-generator.d.ts.map +1 -1
  19. package/dist/bridge/claude-md-generator.js +81 -213
  20. package/dist/bridge/claude-md-generator.js.map +1 -1
  21. package/dist/bridge/codex-docker.d.ts +56 -51
  22. package/dist/bridge/codex-docker.js +222 -230
  23. package/dist/bridge/codex-json-parser.d.ts +11 -11
  24. package/dist/bridge/codex-json-parser.js +231 -238
  25. package/dist/bridge/codex-md-generator.d.ts +3 -3
  26. package/dist/bridge/codex-md-generator.js +42 -32
  27. package/dist/bridge/codex-sprites.d.ts +50 -45
  28. package/dist/bridge/codex-sprites.js +212 -222
  29. package/dist/bridge/daytona.d.ts +25 -25
  30. package/dist/bridge/daytona.js +131 -136
  31. package/dist/bridge/docker-stdio.d.ts +21 -21
  32. package/dist/bridge/docker-stdio.js +126 -132
  33. package/dist/bridge/hosted.d.ts +3 -2
  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/message-parser.d.ts +24 -0
  38. package/dist/bridge/message-parser.d.ts.map +1 -0
  39. package/dist/bridge/message-parser.js +39 -0
  40. package/dist/bridge/message-parser.js.map +1 -0
  41. package/dist/bridge/role-skills.d.ts +25 -0
  42. package/dist/bridge/role-skills.d.ts.map +1 -0
  43. package/dist/bridge/role-skills.js +120 -0
  44. package/dist/bridge/role-skills.js.map +1 -0
  45. package/dist/bridge/room-messaging-skill.d.ts +11 -0
  46. package/dist/bridge/room-messaging-skill.d.ts.map +1 -0
  47. package/dist/bridge/room-messaging-skill.js +41 -0
  48. package/dist/bridge/room-messaging-skill.js.map +1 -0
  49. package/dist/bridge/sprites.d.ts +22 -22
  50. package/dist/bridge/sprites.js +123 -128
  51. package/dist/bridge/stream-json-parser.js +12 -5
  52. package/dist/bridge/stream-json-parser.js.map +1 -1
  53. package/dist/bridge/types.d.ts +4 -10
  54. package/dist/bridge/types.d.ts.map +1 -1
  55. package/dist/client/assets/index-BfvQSMwH.css +1 -0
  56. package/dist/client/assets/index-CiwD5LkP.js +235 -0
  57. package/dist/client/index.html +2 -2
  58. package/dist/index.d.ts +4 -3
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +3 -3
  61. package/dist/index.js.map +1 -1
  62. package/dist/invite-code.d.ts +5 -0
  63. package/dist/invite-code.d.ts.map +1 -0
  64. package/dist/invite-code.js +14 -0
  65. package/dist/invite-code.js.map +1 -0
  66. package/dist/project-utils.d.ts.map +1 -1
  67. package/dist/project-utils.js.map +1 -1
  68. package/dist/registry.d.ts +11 -4
  69. package/dist/registry.d.ts.map +1 -1
  70. package/dist/registry.js +1 -1
  71. package/dist/registry.js.map +1 -1
  72. package/dist/room-router.d.ts +73 -0
  73. package/dist/room-router.d.ts.map +1 -0
  74. package/dist/room-router.js +345 -0
  75. package/dist/room-router.js.map +1 -0
  76. package/dist/sandbox/docker.d.ts.map +1 -1
  77. package/dist/sandbox/docker.js +5 -6
  78. package/dist/sandbox/docker.js.map +1 -1
  79. package/dist/sandbox/index.d.ts +0 -1
  80. package/dist/sandbox/index.d.ts.map +1 -1
  81. package/dist/sandbox/index.js +0 -1
  82. package/dist/sandbox/index.js.map +1 -1
  83. package/dist/sandbox/sprites.d.ts.map +1 -1
  84. package/dist/sandbox/sprites.js +40 -10
  85. package/dist/sandbox/sprites.js.map +1 -1
  86. package/dist/sandbox/types.d.ts +4 -2
  87. package/dist/sandbox/types.d.ts.map +1 -1
  88. package/dist/server.d.ts +12 -0
  89. package/dist/server.d.ts.map +1 -1
  90. package/dist/server.js +824 -309
  91. package/dist/server.js.map +1 -1
  92. package/dist/session-auth.d.ts +9 -0
  93. package/dist/session-auth.d.ts.map +1 -1
  94. package/dist/session-auth.js +30 -0
  95. package/dist/session-auth.js.map +1 -1
  96. package/dist/sessions.d.ts +7 -1
  97. package/dist/sessions.d.ts.map +1 -1
  98. package/dist/sessions.js.map +1 -1
  99. package/dist/streams.d.ts +2 -6
  100. package/dist/streams.d.ts.map +1 -1
  101. package/dist/streams.js +6 -17
  102. package/dist/streams.js.map +1 -1
  103. package/dist/validate.d.ts +10 -0
  104. package/dist/validate.d.ts.map +1 -0
  105. package/dist/validate.js +24 -0
  106. package/dist/validate.js.map +1 -0
  107. package/package.json +6 -9
  108. package/dist/client/assets/index-DDzmxYub.js +0 -234
  109. package/dist/client/assets/index-DcP7prsZ.css +0 -1
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Abstract base class for Claude Code bridges (Docker and Sprites).
3
+ *
4
+ * Encapsulates the shared logic for:
5
+ * - Durable Stream writing (emit, dispatchEvent)
6
+ * - Message queueing (sendCommand with queue-if-busy)
7
+ * - Event dispatching (callbacks, app_status detection)
8
+ * - Process lifecycle (exit handling, queue draining, session_end)
9
+ * - Gate responses
10
+ *
11
+ * Subclasses implement the platform-specific process management:
12
+ * - spawnProcess() — start a new Claude Code process
13
+ * - killProcess() — terminate the running process
14
+ * - isProcessAlive() — check if a process is currently running
15
+ * - writeToStdin(content) — write a user message to stdin
16
+ * - installHooksImpl() — install AskUserQuestion hooks
17
+ */
18
+ import { DurableStream } from "@durable-streams/client";
19
+ import { ts } from "@electric-agent/protocol";
20
+ import { formatGateMessage } from "./gate-response.js";
21
+ import { createStreamJsonParser } from "./stream-json-parser.js";
22
+ export const DEFAULT_ALLOWED_TOOLS = [
23
+ "Read",
24
+ "Write",
25
+ "Edit",
26
+ "Bash",
27
+ "Glob",
28
+ "Grep",
29
+ "WebSearch",
30
+ "TodoWrite",
31
+ "AskUserQuestion",
32
+ "Skill",
33
+ ];
34
+ /** Tools allowed in production mode — no WebSearch to prevent abuse */
35
+ export const PRODUCTION_ALLOWED_TOOLS = DEFAULT_ALLOWED_TOOLS.filter((t) => t !== "WebSearch");
36
+ export class ClaudeCodeBaseBridge {
37
+ sessionId;
38
+ writer;
39
+ parser = createStreamJsonParser();
40
+ closed = false;
41
+ running = false;
42
+ hooksInstalled = false;
43
+ /** Claude Code session ID captured from stream-json system.init — used for --resume */
44
+ claudeSessionId = null;
45
+ /** Whether the parser already emitted a session_end (from a "result" message) */
46
+ resultReceived = false;
47
+ /** Whether the process was intentionally interrupted (suppress exit handler session_end) */
48
+ interrupted = false;
49
+ /** Queued messages to deliver after the current process finishes */
50
+ pendingMessages = [];
51
+ agentEventCallbacks = [];
52
+ completeCallbacks = [];
53
+ constructor(sessionId, connection) {
54
+ this.sessionId = sessionId;
55
+ this.writer = new DurableStream({
56
+ url: connection.url,
57
+ headers: connection.headers,
58
+ contentType: "application/json",
59
+ });
60
+ }
61
+ // -------------------------------------------------------------------
62
+ // SessionBridge interface
63
+ // -------------------------------------------------------------------
64
+ async emit(event) {
65
+ if (this.closed)
66
+ return;
67
+ const msg = { source: "server", ...event };
68
+ await this.writer.append(JSON.stringify(msg));
69
+ }
70
+ /**
71
+ * Send a follow-up user message to Claude Code by respawning with --resume.
72
+ *
73
+ * If Claude Code is currently running, the message is queued and delivered
74
+ * after the current process finishes. This prevents killing the agent
75
+ * mid-work and losing in-flight file writes or tool calls.
76
+ */
77
+ async sendCommand(cmd) {
78
+ if (this.closed)
79
+ return;
80
+ if (cmd.command === "iterate" && typeof cmd.request === "string") {
81
+ if (this.running && this.hasProcess()) {
82
+ console.log(`[${this.logPrefix}] Queuing message (agent busy): session=${this.sessionId} queue=${this.pendingMessages.length + 1}`);
83
+ this.pendingMessages.push(cmd.request);
84
+ return;
85
+ }
86
+ await this.spawnProcess(cmd.request, this.claudeSessionId ?? undefined);
87
+ return;
88
+ }
89
+ console.log(`[${this.logPrefix}] Ignoring unsupported command: ${cmd.command}`);
90
+ }
91
+ async sendGateResponse(gate, value) {
92
+ if (this.closed || !this.hasProcess())
93
+ return;
94
+ const message = formatGateMessage(gate, value);
95
+ if (message != null) {
96
+ this.writeUserMessage(message);
97
+ }
98
+ }
99
+ onAgentEvent(cb) {
100
+ this.agentEventCallbacks.push(cb);
101
+ }
102
+ onComplete(cb) {
103
+ this.completeCallbacks.push(cb);
104
+ }
105
+ isRunning() {
106
+ return this.running;
107
+ }
108
+ interrupt() {
109
+ this.interrupted = true;
110
+ this.killProcess();
111
+ this.running = false;
112
+ }
113
+ close() {
114
+ this.closed = true;
115
+ this.killProcess();
116
+ }
117
+ // -------------------------------------------------------------------
118
+ // Shared helpers — used by subclasses
119
+ // -------------------------------------------------------------------
120
+ /**
121
+ * Reset parser state before spawning a new process.
122
+ * Call this at the start of spawnProcess implementations.
123
+ */
124
+ resetParserState() {
125
+ this.parser = createStreamJsonParser();
126
+ this.resultReceived = false;
127
+ this.interrupted = false;
128
+ this.running = true;
129
+ }
130
+ /**
131
+ * Install hooks if not already installed.
132
+ * Call this at the start of spawnProcess implementations.
133
+ */
134
+ async ensureHooksInstalled() {
135
+ if (!this.hooksInstalled) {
136
+ try {
137
+ await this.installHooksImpl();
138
+ this.hooksInstalled = true;
139
+ }
140
+ catch (err) {
141
+ console.error(`[${this.logPrefix}] Hook install error:`, err);
142
+ }
143
+ }
144
+ }
145
+ /**
146
+ * Handle a line of NDJSON output from Claude Code.
147
+ * Call this from stdout readline handlers.
148
+ */
149
+ handleLine(line) {
150
+ const trimmed = line.trim();
151
+ if (!trimmed)
152
+ return;
153
+ const events = this.parser.parse(trimmed);
154
+ for (const event of events) {
155
+ this.dispatchEvent(event);
156
+ }
157
+ }
158
+ /**
159
+ * Handle process exit. Call this from process exit handlers.
160
+ * Defers processing to let pending readline events flush first.
161
+ */
162
+ handleProcessExit(code) {
163
+ console.log(`[${this.logPrefix}] Process exited: code=${code} session=${this.sessionId}`);
164
+ setTimeout(() => {
165
+ if (this.parser.state.sessionId) {
166
+ this.claudeSessionId = this.parser.state.sessionId;
167
+ }
168
+ this.running = false;
169
+ // Drain pending messages — if messages were queued while the agent
170
+ // was busy, combine them and respawn with --resume so the agent
171
+ // continues from where it left off instead of losing context.
172
+ if (!this.closed && this.pendingMessages.length > 0) {
173
+ const combined = this.pendingMessages.join("\n\n---\n\n");
174
+ this.pendingMessages = [];
175
+ console.log(`[${this.logPrefix}] Draining queued messages: session=${this.sessionId}`);
176
+ this.spawnProcess(combined, this.claudeSessionId ?? undefined);
177
+ return;
178
+ }
179
+ // Only emit session_end from exit handler if the parser didn't already
180
+ // emit one (via a "result" message) and the process wasn't intentionally
181
+ // interrupted. This prevents double session_end.
182
+ if (!this.closed && !this.resultReceived && !this.interrupted) {
183
+ const endEvent = {
184
+ type: "session_end",
185
+ success: code === 0,
186
+ ts: ts(),
187
+ };
188
+ this.dispatchEvent(endEvent);
189
+ }
190
+ }, 100);
191
+ }
192
+ /**
193
+ * Dispatch an engine event to the durable stream and all callbacks.
194
+ */
195
+ dispatchEvent(event) {
196
+ // Inject agent name into assistant_message events for display
197
+ const agentName = this.getAgentName();
198
+ if (agentName && event.type === "assistant_message") {
199
+ ;
200
+ event.agent = agentName;
201
+ }
202
+ // Write to Durable Stream for UI
203
+ const msg = { source: "agent", ...event };
204
+ this.writer.append(JSON.stringify(msg)).catch(() => { });
205
+ // Track session_end from result messages to prevent duplicates
206
+ if (event.type === "session_end") {
207
+ this.resultReceived = true;
208
+ }
209
+ // Detect dev:start in Bash tool_use → emit app_status for the UI preview
210
+ if (event.type === "pre_tool_use" && event.tool_name === "Bash") {
211
+ const cmd = event.tool_input?.command;
212
+ if (typeof cmd === "string" && /\bdev:start\b/.test(cmd)) {
213
+ const appStatus = {
214
+ type: "app_status",
215
+ status: "running",
216
+ ts: ts(),
217
+ };
218
+ const appStatusMsg = { source: "agent", ...appStatus };
219
+ this.writer.append(JSON.stringify(appStatusMsg)).catch(() => { });
220
+ for (const cb of this.agentEventCallbacks) {
221
+ try {
222
+ cb(appStatus);
223
+ }
224
+ catch {
225
+ // Swallow
226
+ }
227
+ }
228
+ }
229
+ }
230
+ // Dispatch to callbacks
231
+ for (const cb of this.agentEventCallbacks) {
232
+ try {
233
+ cb(event);
234
+ }
235
+ catch {
236
+ // Swallow callback errors
237
+ }
238
+ }
239
+ // Detect session_end
240
+ if (event.type === "session_end" && "success" in event) {
241
+ const success = event.success;
242
+ for (const cb of this.completeCallbacks) {
243
+ try {
244
+ cb(success);
245
+ }
246
+ catch {
247
+ // Swallow callback errors
248
+ }
249
+ }
250
+ }
251
+ }
252
+ /**
253
+ * Write a user message to Claude Code's stdin in stream-json format.
254
+ */
255
+ writeUserMessage(content) {
256
+ const msg = JSON.stringify({
257
+ type: "user",
258
+ message: { role: "user", content },
259
+ });
260
+ this.writeToStdin(`${msg}\n`);
261
+ }
262
+ }
263
+ //# sourceMappingURL=claude-code-base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code-base.js","sourceRoot":"","sources":["../../src/bridge/claude-code-base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAEvD,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAA;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAuBhE,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACpC,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,WAAW;IACX,WAAW;IACX,iBAAiB;IACjB,OAAO;CACP,CAAA;AAED,uEAAuE;AACvE,MAAM,CAAC,MAAM,wBAAwB,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,WAAW,CAAC,CAAA;AAE9F,MAAM,OAAgB,oBAAoB;IAChC,SAAS,CAAQ;IAEhB,MAAM,CAAe;IACrB,MAAM,GAAqB,sBAAsB,EAAE,CAAA;IACnD,MAAM,GAAG,KAAK,CAAA;IACd,OAAO,GAAG,KAAK,CAAA;IACf,cAAc,GAAG,KAAK,CAAA;IAEhC,uFAAuF;IAC7E,eAAe,GAAkB,IAAI,CAAA;IAC/C,iFAAiF;IACvE,cAAc,GAAG,KAAK,CAAA;IAChC,4FAA4F;IAClF,WAAW,GAAG,KAAK,CAAA;IAC7B,oEAAoE;IAC1D,eAAe,GAAa,EAAE,CAAA;IAEhC,mBAAmB,GAAwC,EAAE,CAAA;IAC7D,iBAAiB,GAAsC,EAAE,CAAA;IAKjE,YAAY,SAAiB,EAAE,UAAgC;QAC9D,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAE1B,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;IAwBD,sEAAsE;IACtE,0BAA0B;IAC1B,sEAAsE;IAEtE,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;;;;;;OAMG;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,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;gBACvC,OAAO,CAAC,GAAG,CACV,IAAI,IAAI,CAAC,SAAS,2CAA2C,IAAI,CAAC,SAAS,UAAU,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CACtH,CAAA;gBACD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;gBACtC,OAAM;YACP,CAAC;YACD,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,IAAI,SAAS,CAAC,CAAA;YACvE,OAAM;QACP,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,mCAAmC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;IAChF,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,IAAY,EAAE,KAA8B;QAClE,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YAAE,OAAM;QAC7C,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAC9C,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACrB,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAA;QAC/B,CAAC;IACF,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;IAID,SAAS;QACR,OAAO,IAAI,CAAC,OAAO,CAAA;IACpB,CAAC;IAED,SAAS;QACR,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;QACvB,IAAI,CAAC,WAAW,EAAE,CAAA;QAClB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IACrB,CAAC;IAED,KAAK;QACJ,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,CAAC,WAAW,EAAE,CAAA;IACnB,CAAC;IAED,sEAAsE;IACtE,sCAAsC;IACtC,sEAAsE;IAEtE;;;OAGG;IACO,gBAAgB;QACzB,IAAI,CAAC,MAAM,GAAG,sBAAsB,EAAE,CAAA;QACtC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAA;QAC3B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAA;QACxB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;IACpB,CAAC;IAED;;;OAGG;IACO,KAAK,CAAC,oBAAoB;QACnC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACJ,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAA;gBAC7B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;YAC3B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,SAAS,uBAAuB,EAAE,GAAG,CAAC,CAAA;YAC9D,CAAC;QACF,CAAC;IACF,CAAC;IAED;;;OAGG;IACO,UAAU,CAAC,IAAY;QAChC,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;IAED;;;OAGG;IACO,iBAAiB,CAAC,IAAmB;QAC9C,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,0BAA0B,IAAI,YAAY,IAAI,CAAC,SAAS,EAAE,CAAC,CAAA;QACzF,UAAU,CAAC,GAAG,EAAE;YACf,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAA;YACnD,CAAC;YACD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;YAEpB,mEAAmE;YACnE,gEAAgE;YAChE,8DAA8D;YAC9D,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;gBACzD,IAAI,CAAC,eAAe,GAAG,EAAE,CAAA;gBACzB,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,uCAAuC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAA;gBACtF,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,eAAe,IAAI,SAAS,CAAC,CAAA;gBAC9D,OAAM;YACP,CAAC;YAED,uEAAuE;YACvE,yEAAyE;YACzE,iDAAiD;YACjD,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC/D,MAAM,QAAQ,GAAgB;oBAC7B,IAAI,EAAE,aAAa;oBACnB,OAAO,EAAE,IAAI,KAAK,CAAC;oBACnB,EAAE,EAAE,EAAE,EAAE;iBACR,CAAA;gBACD,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;YAC7B,CAAC;QACF,CAAC,EAAE,GAAG,CAAC,CAAA;IACR,CAAC;IAED;;OAEG;IACO,aAAa,CAAC,KAAkB;QACzC,8DAA8D;QAC9D,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAA;QACrC,IAAI,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;YACrD,CAAC;YAAC,KAA0C,CAAC,KAAK,GAAG,SAAS,CAAA;QAC/D,CAAC;QAED,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,+DAA+D;QAC/D,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;QAC3B,CAAC;QAED,yEAAyE;QACzE,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,SAAS,GAAgB;oBAC9B,IAAI,EAAE,YAAY;oBAClB,MAAM,EAAE,SAAS;oBACjB,EAAE,EAAE,EAAE,EAAE;iBACR,CAAA;gBACD,MAAM,YAAY,GAAkB,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,CAAA;gBACrE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;gBAChE,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;oBAC3C,IAAI,CAAC;wBACJ,EAAE,CAAC,SAAS,CAAC,CAAA;oBACd,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;IAED;;OAEG;IACK,gBAAgB,CAAC,OAAe;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;SAClC,CAAC,CAAA;QACF,IAAI,CAAC,YAAY,CAAC,GAAG,GAAG,IAAI,CAAC,CAAA;IAC9B,CAAC;CACD"}
@@ -1,88 +1,28 @@
1
1
  /**
2
2
  * SessionBridge implementation that runs Claude Code CLI inside a Docker
3
- * container via `docker exec -i`, communicating via stream-json NDJSON.
3
+ * container via `docker exec`, communicating via stream-json NDJSON.
4
4
  *
5
- * The bridge translates Claude Code's stream-json output into EngineEvents
6
- * and writes them to the Durable Stream for the UI. User messages and
7
- * gate responses are sent to Claude Code's stdin.
8
- *
9
- * Claude Code runs in one-shot mode (`-p`) and exits after completing.
10
- * On iterate (follow-up message), the bridge respawns Claude Code with
11
- * `--resume <sessionId>` so it picks up the previous conversation context.
5
+ * Extends ClaudeCodeBaseBridge with Docker-specific process management
6
+ * (spawn via `docker exec`, ChildProcess lifecycle, Docker hook installation).
12
7
  */
13
- import type { EngineEvent } from "@electric-agent/protocol";
14
8
  import type { StreamConnectionInfo } from "../streams.js";
15
- import type { SessionBridge } from "./types.js";
16
- export interface ClaudeCodeDockerConfig {
17
- /** Initial prompt (the user's app description or task) */
18
- prompt: string;
19
- /** Working directory inside the container */
20
- cwd: string;
21
- /** Model to use (default: claude-sonnet-4-6) */
22
- model?: string;
23
- /** Allowed tools (default: all standard tools) */
24
- allowedTools?: string[];
25
- /** Additional CLI flags */
26
- extraFlags?: string[];
9
+ import { ClaudeCodeBaseBridge, type ClaudeCodeBaseConfig } from "./claude-code-base.js";
10
+ export interface ClaudeCodeDockerConfig extends ClaudeCodeBaseConfig {
27
11
  /** Studio server port — used to set up AskUserQuestion hooks inside the container */
28
12
  studioPort?: number;
29
13
  }
30
- export declare class ClaudeCodeDockerBridge implements SessionBridge {
31
- readonly sessionId: string;
32
- readonly streamUrl: string;
33
- readonly streamHeaders: Record<string, string>;
14
+ export declare class ClaudeCodeDockerBridge extends ClaudeCodeBaseBridge {
15
+ protected readonly logPrefix = "claude-code-docker";
34
16
  private containerId;
35
17
  private config;
36
- private writer;
37
- private parser;
38
- private agentEventCallbacks;
39
- private completeCallbacks;
40
- private closed;
41
18
  private proc;
42
- /** Claude Code session ID captured from stream-json system.init — used for --resume */
43
- private claudeSessionId;
44
- /** Whether a Claude Code process is currently running */
45
- private running;
46
- /** Whether the parser already emitted a session_end (from a "result" message) */
47
- private resultReceived;
48
- /** Whether the process was intentionally interrupted (suppress exit handler session_end) */
49
- private interrupted;
50
- /** Whether hooks have been installed in the container */
51
- private hooksInstalled;
52
19
  constructor(sessionId: string, connection: StreamConnectionInfo, containerId: string, config: ClaudeCodeDockerConfig);
53
- emit(event: EngineEvent): Promise<void>;
54
- /**
55
- * Send a follow-up user message to Claude Code by respawning with --resume.
56
- * Used for iteration requests (the user types a new message in the UI).
57
- */
58
- sendCommand(cmd: Record<string, unknown>): Promise<void>;
59
- /**
60
- * Send a gate response back to Claude Code as a user message.
61
- * For ask_user_question gates, the user's answer becomes a follow-up message.
62
- */
63
- sendGateResponse(gate: string, value: Record<string, unknown>): Promise<void>;
64
- onAgentEvent(cb: (event: EngineEvent) => void): void;
65
- onComplete(cb: (success: boolean) => void): void;
66
20
  start(): Promise<void>;
67
- interrupt(): void;
68
- close(): void;
69
- /**
70
- * Install Claude Code hooks inside the container so that AskUserQuestion
71
- * blocks until the user answers in the studio UI.
72
- * The hook script forwards the PreToolUse event to the studio server via HTTP,
73
- * which blocks the response until the gate is resolved.
74
- */
75
- private installHooks;
76
- /**
77
- * Spawn a new Claude Code process. Called for both the initial prompt
78
- * and follow-up iterate messages (with --resume).
79
- */
80
- private spawnClaude;
81
- private handleLine;
82
- private dispatchEvent;
83
- /**
84
- * Write a user message to Claude Code's stdin in stream-json format.
85
- */
86
- private writeUserMessage;
21
+ protected spawnProcess(prompt: string, resumeSessionId?: string): void;
22
+ protected killProcess(): void;
23
+ protected hasProcess(): boolean;
24
+ protected writeToStdin(content: string): void;
25
+ protected getAgentName(): string | undefined;
26
+ protected installHooksImpl(): void;
87
27
  }
88
28
  //# sourceMappingURL=claude-code-docker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code-docker.d.ts","sourceRoot":"","sources":["../../src/bridge/claude-code-docker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAE3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAGzD,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAE9D,MAAM,WAAW,sBAAsB;IACtC,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAA;IACX,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAeD,qBAAa,sBAAuB,YAAW,aAAa;IAC3D,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,CAAwB;IACtC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,mBAAmB,CAA0C;IACrE,OAAO,CAAC,iBAAiB,CAAwC;IACjE,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,IAAI,CAA4B;IAExC,uFAAuF;IACvF,OAAO,CAAC,eAAe,CAAsB;IAC7C,yDAAyD;IACzD,OAAO,CAAC,OAAO,CAAQ;IACvB,iFAAiF;IACjF,OAAO,CAAC,cAAc,CAAQ;IAC9B,4FAA4F;IAC5F,OAAO,CAAC,WAAW,CAAQ;IAC3B,yDAAyD;IACzD,OAAO,CAAC,cAAc,CAAQ;gBAG7B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,oBAAoB,EAChC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,sBAAsB;IAezB,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7C;;;OAGG;IACG,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAc9D;;;OAGG;IACG,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IASnF,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,SAAS,IAAI,IAAI;IAcjB,KAAK,IAAI,IAAI;IAiBb;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAgEpB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAyHnB,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,aAAa;IAqDrB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAQxB"}
1
+ {"version":3,"file":"claude-code-docker.d.ts","sourceRoot":"","sources":["../../src/bridge/claude-code-docker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,EACN,oBAAoB,EACpB,KAAK,oBAAoB,EAEzB,MAAM,uBAAuB,CAAA;AAE9B,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;IACnE,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,qBAAa,sBAAuB,SAAQ,oBAAoB;IAC/D,SAAS,CAAC,QAAQ,CAAC,SAAS,wBAAuB;IAEnD,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,IAAI,CAA4B;gBAGvC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,oBAAoB,EAChC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,sBAAsB;IAOzB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI;IA4EtE,SAAS,CAAC,WAAW,IAAI,IAAI;IAY7B,SAAS,CAAC,UAAU,IAAI,OAAO;IAI/B,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM7C,SAAS,CAAC,YAAY,IAAI,MAAM,GAAG,SAAS;IAQ5C,SAAS,CAAC,gBAAgB,IAAI,IAAI;CA6DlC"}