@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.
- package/dist/api-schemas.d.ts +225 -0
- package/dist/api-schemas.d.ts.map +1 -0
- package/dist/api-schemas.js +95 -0
- package/dist/api-schemas.js.map +1 -0
- package/dist/bridge/claude-code-base.d.ts +121 -0
- package/dist/bridge/claude-code-base.d.ts.map +1 -0
- package/dist/bridge/claude-code-base.js +263 -0
- package/dist/bridge/claude-code-base.js.map +1 -0
- package/dist/bridge/claude-code-docker.d.ts +13 -73
- package/dist/bridge/claude-code-docker.d.ts.map +1 -1
- package/dist/bridge/claude-code-docker.js +91 -302
- package/dist/bridge/claude-code-docker.js.map +1 -1
- package/dist/bridge/claude-code-sprites.d.ts +12 -59
- package/dist/bridge/claude-code-sprites.d.ts.map +1 -1
- package/dist/bridge/claude-code-sprites.js +88 -281
- package/dist/bridge/claude-code-sprites.js.map +1 -1
- package/dist/bridge/claude-md-generator.d.ts +22 -5
- package/dist/bridge/claude-md-generator.d.ts.map +1 -1
- package/dist/bridge/claude-md-generator.js +81 -213
- package/dist/bridge/claude-md-generator.js.map +1 -1
- package/dist/bridge/codex-docker.d.ts +56 -51
- package/dist/bridge/codex-docker.js +222 -230
- package/dist/bridge/codex-json-parser.d.ts +11 -11
- package/dist/bridge/codex-json-parser.js +231 -238
- package/dist/bridge/codex-md-generator.d.ts +3 -3
- package/dist/bridge/codex-md-generator.js +42 -32
- package/dist/bridge/codex-sprites.d.ts +50 -45
- package/dist/bridge/codex-sprites.js +212 -222
- package/dist/bridge/daytona.d.ts +25 -25
- package/dist/bridge/daytona.js +131 -136
- package/dist/bridge/docker-stdio.d.ts +21 -21
- package/dist/bridge/docker-stdio.js +126 -132
- package/dist/bridge/hosted.d.ts +3 -2
- package/dist/bridge/hosted.d.ts.map +1 -1
- package/dist/bridge/hosted.js +4 -0
- package/dist/bridge/hosted.js.map +1 -1
- package/dist/bridge/message-parser.d.ts +24 -0
- package/dist/bridge/message-parser.d.ts.map +1 -0
- package/dist/bridge/message-parser.js +39 -0
- package/dist/bridge/message-parser.js.map +1 -0
- package/dist/bridge/role-skills.d.ts +25 -0
- package/dist/bridge/role-skills.d.ts.map +1 -0
- package/dist/bridge/role-skills.js +120 -0
- package/dist/bridge/role-skills.js.map +1 -0
- package/dist/bridge/room-messaging-skill.d.ts +11 -0
- package/dist/bridge/room-messaging-skill.d.ts.map +1 -0
- package/dist/bridge/room-messaging-skill.js +41 -0
- package/dist/bridge/room-messaging-skill.js.map +1 -0
- package/dist/bridge/sprites.d.ts +22 -22
- package/dist/bridge/sprites.js +123 -128
- package/dist/bridge/stream-json-parser.js +12 -5
- package/dist/bridge/stream-json-parser.js.map +1 -1
- package/dist/bridge/types.d.ts +4 -10
- package/dist/bridge/types.d.ts.map +1 -1
- package/dist/client/assets/index-BfvQSMwH.css +1 -0
- package/dist/client/assets/index-CiwD5LkP.js +235 -0
- package/dist/client/index.html +2 -2
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/invite-code.d.ts +5 -0
- package/dist/invite-code.d.ts.map +1 -0
- package/dist/invite-code.js +14 -0
- package/dist/invite-code.js.map +1 -0
- package/dist/project-utils.d.ts.map +1 -1
- package/dist/project-utils.js.map +1 -1
- package/dist/registry.d.ts +11 -4
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +1 -1
- package/dist/registry.js.map +1 -1
- package/dist/room-router.d.ts +73 -0
- package/dist/room-router.d.ts.map +1 -0
- package/dist/room-router.js +345 -0
- package/dist/room-router.js.map +1 -0
- package/dist/sandbox/docker.d.ts.map +1 -1
- package/dist/sandbox/docker.js +5 -6
- package/dist/sandbox/docker.js.map +1 -1
- package/dist/sandbox/index.d.ts +0 -1
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +0 -1
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/sprites.d.ts.map +1 -1
- package/dist/sandbox/sprites.js +40 -10
- package/dist/sandbox/sprites.js.map +1 -1
- package/dist/sandbox/types.d.ts +4 -2
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/server.d.ts +12 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +824 -309
- package/dist/server.js.map +1 -1
- package/dist/session-auth.d.ts +9 -0
- package/dist/session-auth.d.ts.map +1 -1
- package/dist/session-auth.js +30 -0
- package/dist/session-auth.js.map +1 -1
- package/dist/sessions.d.ts +7 -1
- package/dist/sessions.d.ts.map +1 -1
- package/dist/sessions.js.map +1 -1
- package/dist/streams.d.ts +2 -6
- package/dist/streams.d.ts.map +1 -1
- package/dist/streams.js +6 -17
- package/dist/streams.js.map +1 -1
- package/dist/validate.d.ts +10 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +24 -0
- package/dist/validate.js.map +1 -0
- package/package.json +6 -9
- package/dist/client/assets/index-DDzmxYub.js +0 -234
- package/dist/client/assets/index-DcP7prsZ.css +0 -1
|
@@ -1,240 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SessionBridge implementation that runs Claude Code CLI inside a Docker
|
|
3
|
-
* container via `docker exec
|
|
3
|
+
* container via `docker exec`, communicating via stream-json NDJSON.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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
8
|
import { execFileSync, spawn } from "node:child_process";
|
|
14
9
|
import * as readline from "node:readline";
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
import { createStreamJsonParser } from "./stream-json-parser.js";
|
|
19
|
-
const DEFAULT_ALLOWED_TOOLS = [
|
|
20
|
-
"Read",
|
|
21
|
-
"Write",
|
|
22
|
-
"Edit",
|
|
23
|
-
"Bash",
|
|
24
|
-
"Glob",
|
|
25
|
-
"Grep",
|
|
26
|
-
"WebSearch",
|
|
27
|
-
"TodoWrite",
|
|
28
|
-
"AskUserQuestion",
|
|
29
|
-
"Skill",
|
|
30
|
-
];
|
|
31
|
-
export class ClaudeCodeDockerBridge {
|
|
32
|
-
sessionId;
|
|
33
|
-
streamUrl;
|
|
34
|
-
streamHeaders;
|
|
10
|
+
import { ClaudeCodeBaseBridge, DEFAULT_ALLOWED_TOOLS, } from "./claude-code-base.js";
|
|
11
|
+
export class ClaudeCodeDockerBridge extends ClaudeCodeBaseBridge {
|
|
12
|
+
logPrefix = "claude-code-docker";
|
|
35
13
|
containerId;
|
|
36
14
|
config;
|
|
37
|
-
writer;
|
|
38
|
-
parser = createStreamJsonParser();
|
|
39
|
-
agentEventCallbacks = [];
|
|
40
|
-
completeCallbacks = [];
|
|
41
|
-
closed = false;
|
|
42
15
|
proc = null;
|
|
43
|
-
/** Claude Code session ID captured from stream-json system.init — used for --resume */
|
|
44
|
-
claudeSessionId = null;
|
|
45
|
-
/** Whether a Claude Code process is currently running */
|
|
46
|
-
running = false;
|
|
47
|
-
/** Whether the parser already emitted a session_end (from a "result" message) */
|
|
48
|
-
resultReceived = false;
|
|
49
|
-
/** Whether the process was intentionally interrupted (suppress exit handler session_end) */
|
|
50
|
-
interrupted = false;
|
|
51
|
-
/** Whether hooks have been installed in the container */
|
|
52
|
-
hooksInstalled = false;
|
|
53
16
|
constructor(sessionId, connection, containerId, config) {
|
|
54
|
-
|
|
55
|
-
this.streamUrl = connection.url;
|
|
56
|
-
this.streamHeaders = connection.headers;
|
|
17
|
+
super(sessionId, connection);
|
|
57
18
|
this.containerId = containerId;
|
|
58
19
|
this.config = config;
|
|
59
|
-
this.writer = new DurableStream({
|
|
60
|
-
url: connection.url,
|
|
61
|
-
headers: connection.headers,
|
|
62
|
-
contentType: "application/json",
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
async emit(event) {
|
|
66
|
-
if (this.closed)
|
|
67
|
-
return;
|
|
68
|
-
const msg = { source: "server", ...event };
|
|
69
|
-
await this.writer.append(JSON.stringify(msg));
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Send a follow-up user message to Claude Code by respawning with --resume.
|
|
73
|
-
* Used for iteration requests (the user types a new message in the UI).
|
|
74
|
-
*/
|
|
75
|
-
async sendCommand(cmd) {
|
|
76
|
-
if (this.closed)
|
|
77
|
-
return;
|
|
78
|
-
// For iteration: respawn Claude Code with --resume
|
|
79
|
-
if (cmd.command === "iterate" && typeof cmd.request === "string") {
|
|
80
|
-
this.spawnClaude(cmd.request, this.claudeSessionId ?? undefined);
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
// For initial "new" command: this is handled in start() via the prompt
|
|
84
|
-
// Other commands are ignored — Claude Code doesn't understand them
|
|
85
|
-
console.log(`[claude-code-docker] Ignoring unsupported command: ${cmd.command}`);
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Send a gate response back to Claude Code as a user message.
|
|
89
|
-
* For ask_user_question gates, the user's answer becomes a follow-up message.
|
|
90
|
-
*/
|
|
91
|
-
async sendGateResponse(gate, value) {
|
|
92
|
-
if (this.closed || !this.proc?.stdin?.writable)
|
|
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
20
|
}
|
|
105
21
|
async start() {
|
|
106
22
|
if (this.closed)
|
|
107
23
|
return;
|
|
108
|
-
this.
|
|
109
|
-
}
|
|
110
|
-
interrupt() {
|
|
111
|
-
this.interrupted = true;
|
|
112
|
-
if (this.proc) {
|
|
113
|
-
try {
|
|
114
|
-
this.proc.stdin?.end();
|
|
115
|
-
this.proc.kill("SIGTERM");
|
|
116
|
-
}
|
|
117
|
-
catch {
|
|
118
|
-
// Process may already be dead
|
|
119
|
-
}
|
|
120
|
-
this.proc = null;
|
|
121
|
-
}
|
|
122
|
-
this.running = false;
|
|
123
|
-
}
|
|
124
|
-
close() {
|
|
125
|
-
this.closed = true;
|
|
126
|
-
if (this.proc) {
|
|
127
|
-
try {
|
|
128
|
-
this.proc.stdin?.end();
|
|
129
|
-
this.proc.kill("SIGTERM");
|
|
130
|
-
}
|
|
131
|
-
catch {
|
|
132
|
-
// Process may already be dead
|
|
133
|
-
}
|
|
134
|
-
this.proc = null;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
// -----------------------------------------------------------------------
|
|
138
|
-
// Private helpers
|
|
139
|
-
// -----------------------------------------------------------------------
|
|
140
|
-
/**
|
|
141
|
-
* Install Claude Code hooks inside the container so that AskUserQuestion
|
|
142
|
-
* blocks until the user answers in the studio UI.
|
|
143
|
-
* The hook script forwards the PreToolUse event to the studio server via HTTP,
|
|
144
|
-
* which blocks the response until the gate is resolved.
|
|
145
|
-
*/
|
|
146
|
-
installHooks() {
|
|
147
|
-
const port = this.config.studioPort;
|
|
148
|
-
if (!port)
|
|
149
|
-
return;
|
|
150
|
-
const hookDir = `${this.config.cwd}/.claude/hooks`;
|
|
151
|
-
const settingsFile = `${this.config.cwd}/.claude/settings.local.json`;
|
|
152
|
-
// Studio server is on the host — use host.docker.internal to reach it
|
|
153
|
-
const studioUrl = `http://host.docker.internal:${port}`;
|
|
154
|
-
const forwardScript = `#!/bin/bash
|
|
155
|
-
# Forward AskUserQuestion hook events to Electric Agent studio.
|
|
156
|
-
# Blocks until the user answers in the web UI.
|
|
157
|
-
BODY="$(cat)"
|
|
158
|
-
RESPONSE=$(curl -s -X POST "${studioUrl}/api/sessions/${this.sessionId}/hook-event" \\
|
|
159
|
-
-H "Content-Type: application/json" \\
|
|
160
|
-
-d "\${BODY}" \\
|
|
161
|
-
--max-time 360 \\
|
|
162
|
-
--connect-timeout 5 \\
|
|
163
|
-
2>/dev/null)
|
|
164
|
-
if echo "\${RESPONSE}" | grep -q '"hookSpecificOutput"'; then
|
|
165
|
-
echo "\${RESPONSE}"
|
|
166
|
-
fi
|
|
167
|
-
exit 0`;
|
|
168
|
-
// Configure hooks in settings.local.json.
|
|
169
|
-
// Tool permissions come from --allowedTools CLI flag instead.
|
|
170
|
-
// Hook format: each event has matcher groups, each with a `hooks` array.
|
|
171
|
-
const settings = JSON.stringify({
|
|
172
|
-
hooks: {
|
|
173
|
-
PreToolUse: [
|
|
174
|
-
{
|
|
175
|
-
matcher: "AskUserQuestion",
|
|
176
|
-
hooks: [
|
|
177
|
-
{
|
|
178
|
-
type: "command",
|
|
179
|
-
command: `${hookDir}/forward.sh`,
|
|
180
|
-
},
|
|
181
|
-
],
|
|
182
|
-
},
|
|
183
|
-
],
|
|
184
|
-
},
|
|
185
|
-
});
|
|
186
|
-
try {
|
|
187
|
-
// Use base64 encoding to avoid heredoc delimiter issues in docker exec
|
|
188
|
-
const forwardB64 = Buffer.from(forwardScript).toString("base64");
|
|
189
|
-
const settingsB64 = Buffer.from(settings).toString("base64");
|
|
190
|
-
const setupCmd = [
|
|
191
|
-
`mkdir -p '${hookDir}'`,
|
|
192
|
-
`echo '${forwardB64}' | base64 -d > '${hookDir}/forward.sh'`,
|
|
193
|
-
`chmod +x '${hookDir}/forward.sh'`,
|
|
194
|
-
`echo '${settingsB64}' | base64 -d > '${settingsFile}'`,
|
|
195
|
-
].join(" && ");
|
|
196
|
-
execFileSync("docker", ["exec", this.containerId, "bash", "-c", setupCmd], {
|
|
197
|
-
timeout: 10_000,
|
|
198
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
199
|
-
});
|
|
200
|
-
console.log(`[claude-code-docker] Installed AskUserQuestion hooks in container`);
|
|
201
|
-
}
|
|
202
|
-
catch (err) {
|
|
203
|
-
console.error(`[claude-code-docker] Failed to install hooks:`, err);
|
|
204
|
-
}
|
|
24
|
+
this.spawnProcess(this.config.prompt);
|
|
205
25
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
spawnClaude(prompt, resumeSessionId) {
|
|
26
|
+
// -------------------------------------------------------------------
|
|
27
|
+
// Abstract method implementations
|
|
28
|
+
// -------------------------------------------------------------------
|
|
29
|
+
spawnProcess(prompt, resumeSessionId) {
|
|
211
30
|
// Kill any existing process
|
|
212
|
-
|
|
213
|
-
try {
|
|
214
|
-
this.proc.stdin?.end();
|
|
215
|
-
this.proc.kill("SIGTERM");
|
|
216
|
-
}
|
|
217
|
-
catch {
|
|
218
|
-
// Already dead
|
|
219
|
-
}
|
|
220
|
-
this.proc = null;
|
|
221
|
-
}
|
|
31
|
+
this.killProcess();
|
|
222
32
|
// Install hooks on first spawn (they persist for resume spawns)
|
|
223
33
|
if (!this.hooksInstalled) {
|
|
224
|
-
this.
|
|
34
|
+
this.installHooksImpl();
|
|
225
35
|
this.hooksInstalled = true;
|
|
226
36
|
}
|
|
227
37
|
// Reset parser state for the new process
|
|
228
|
-
this.
|
|
229
|
-
this.resultReceived = false;
|
|
230
|
-
this.interrupted = false;
|
|
231
|
-
this.running = true;
|
|
38
|
+
this.resetParserState();
|
|
232
39
|
const model = this.config.model ?? "claude-sonnet-4-6";
|
|
233
|
-
// Build the claude CLI command.
|
|
234
|
-
// Use --allowedTools to grant permissions (keeps hooks firing, unlike
|
|
235
|
-
// --dangerously-skip-permissions which bypasses hooks entirely).
|
|
236
|
-
// Use --settings to pass hook configuration directly (more reliable
|
|
237
|
-
// than settings.local.json which may not be loaded by all versions).
|
|
238
40
|
const allowedTools = this.config.allowedTools ?? DEFAULT_ALLOWED_TOOLS;
|
|
239
41
|
const claudeArgs = [
|
|
240
42
|
"-p",
|
|
@@ -249,22 +51,17 @@ exit 0`;
|
|
|
249
51
|
: ["--dangerously-skip-permissions"]),
|
|
250
52
|
...(this.config.extraFlags ?? []),
|
|
251
53
|
];
|
|
252
|
-
// Add --resume if we have a previous session ID
|
|
253
54
|
if (resumeSessionId) {
|
|
254
55
|
claudeArgs.push("--resume", resumeSessionId);
|
|
255
56
|
}
|
|
256
|
-
// Escape for bash
|
|
257
57
|
const escapedArgs = claudeArgs.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ");
|
|
258
58
|
const cmd = `cd '${this.config.cwd}' && claude ${escapedArgs}`;
|
|
259
|
-
// Note: do NOT use -i flag — Claude Code detects interactive stdin and blocks
|
|
260
|
-
// waiting for input even when -p is provided. Without -i, stdout flows normally.
|
|
261
59
|
this.proc = spawn("docker", ["exec", this.containerId, "bash", "-c", cmd], {
|
|
262
60
|
stdio: ["pipe", "pipe", "pipe"],
|
|
263
61
|
});
|
|
264
62
|
console.log(`[claude-code-docker] Started: session=${this.sessionId} container=${this.containerId} pid=${this.proc.pid} resume=${resumeSessionId ?? "none"}`);
|
|
265
63
|
console.log(`[claude-code-docker] cmd: ${cmd}`);
|
|
266
64
|
const currentProc = this.proc;
|
|
267
|
-
// Read stdout line by line (stream-json NDJSON)
|
|
268
65
|
if (currentProc.stdout) {
|
|
269
66
|
const rl = readline.createInterface({
|
|
270
67
|
input: currentProc.stdout,
|
|
@@ -277,7 +74,6 @@ exit 0`;
|
|
|
277
74
|
this.handleLine(line);
|
|
278
75
|
});
|
|
279
76
|
}
|
|
280
|
-
// Log stderr
|
|
281
77
|
if (currentProc.stderr) {
|
|
282
78
|
const stderrRl = readline.createInterface({
|
|
283
79
|
input: currentProc.stderr,
|
|
@@ -289,101 +85,94 @@ exit 0`;
|
|
|
289
85
|
}
|
|
290
86
|
});
|
|
291
87
|
}
|
|
292
|
-
// Handle process exit — defer to let pending readline events flush first,
|
|
293
|
-
// which prevents duplicate session_end (the parser emits one from "result").
|
|
294
88
|
currentProc.on("exit", (code) => {
|
|
295
|
-
|
|
296
|
-
setTimeout(() => {
|
|
297
|
-
// Capture session ID from parser state before marking not running
|
|
298
|
-
if (this.parser.state.sessionId) {
|
|
299
|
-
this.claudeSessionId = this.parser.state.sessionId;
|
|
300
|
-
}
|
|
301
|
-
this.running = false;
|
|
302
|
-
// Only emit session_end from exit handler if the parser didn't already
|
|
303
|
-
// emit one (via a "result" message) and the process wasn't intentionally
|
|
304
|
-
// interrupted. This prevents double session_end.
|
|
305
|
-
if (!this.closed && !this.resultReceived && !this.interrupted) {
|
|
306
|
-
const endEvent = {
|
|
307
|
-
type: "session_end",
|
|
308
|
-
success: code === 0,
|
|
309
|
-
ts: ts(),
|
|
310
|
-
};
|
|
311
|
-
this.dispatchEvent(endEvent);
|
|
312
|
-
}
|
|
313
|
-
}, 100);
|
|
89
|
+
this.handleProcessExit(code);
|
|
314
90
|
});
|
|
315
91
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
if (!trimmed)
|
|
319
|
-
return;
|
|
320
|
-
const events = this.parser.parse(trimmed);
|
|
321
|
-
for (const event of events) {
|
|
322
|
-
this.dispatchEvent(event);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
dispatchEvent(event) {
|
|
326
|
-
// Write to Durable Stream for UI
|
|
327
|
-
const msg = { source: "agent", ...event };
|
|
328
|
-
this.writer.append(JSON.stringify(msg)).catch(() => { });
|
|
329
|
-
// Track session_end from result messages to prevent duplicates
|
|
330
|
-
if (event.type === "session_end") {
|
|
331
|
-
this.resultReceived = true;
|
|
332
|
-
}
|
|
333
|
-
// Detect dev:start in Bash tool_use → emit app_status for the UI preview
|
|
334
|
-
if (event.type === "pre_tool_use" && event.tool_name === "Bash") {
|
|
335
|
-
const cmd = event.tool_input?.command;
|
|
336
|
-
if (typeof cmd === "string" && /\bdev:start\b/.test(cmd)) {
|
|
337
|
-
const appStatus = {
|
|
338
|
-
type: "app_status",
|
|
339
|
-
status: "running",
|
|
340
|
-
ts: ts(),
|
|
341
|
-
};
|
|
342
|
-
const appStatusMsg = { source: "agent", ...appStatus };
|
|
343
|
-
this.writer.append(JSON.stringify(appStatusMsg)).catch(() => { });
|
|
344
|
-
for (const cb of this.agentEventCallbacks) {
|
|
345
|
-
try {
|
|
346
|
-
cb(appStatus);
|
|
347
|
-
}
|
|
348
|
-
catch {
|
|
349
|
-
// Swallow
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
// Dispatch to callbacks
|
|
355
|
-
for (const cb of this.agentEventCallbacks) {
|
|
92
|
+
killProcess() {
|
|
93
|
+
if (this.proc) {
|
|
356
94
|
try {
|
|
357
|
-
|
|
95
|
+
this.proc.stdin?.end();
|
|
96
|
+
this.proc.kill("SIGTERM");
|
|
358
97
|
}
|
|
359
98
|
catch {
|
|
360
|
-
//
|
|
99
|
+
// Process may already be dead
|
|
361
100
|
}
|
|
101
|
+
this.proc = null;
|
|
362
102
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
catch {
|
|
371
|
-
// Swallow callback errors
|
|
372
|
-
}
|
|
373
|
-
}
|
|
103
|
+
}
|
|
104
|
+
hasProcess() {
|
|
105
|
+
return this.proc != null;
|
|
106
|
+
}
|
|
107
|
+
writeToStdin(content) {
|
|
108
|
+
if (this.proc?.stdin?.writable) {
|
|
109
|
+
this.proc.stdin.write(content);
|
|
374
110
|
}
|
|
375
111
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
112
|
+
getAgentName() {
|
|
113
|
+
return this.config.agentName;
|
|
114
|
+
}
|
|
115
|
+
// -------------------------------------------------------------------
|
|
116
|
+
// Docker-specific hook installation
|
|
117
|
+
// -------------------------------------------------------------------
|
|
118
|
+
installHooksImpl() {
|
|
119
|
+
const port = this.config.studioPort;
|
|
120
|
+
if (!port)
|
|
381
121
|
return;
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
122
|
+
const hookDir = `${this.config.cwd}/.claude/hooks`;
|
|
123
|
+
const settingsFile = `${this.config.cwd}/.claude/settings.local.json`;
|
|
124
|
+
const studioUrl = `http://host.docker.internal:${port}`;
|
|
125
|
+
const hookToken = this.config.hookToken ?? "";
|
|
126
|
+
const forwardScript = `#!/bin/bash
|
|
127
|
+
# Forward AskUserQuestion hook events to Electric Agent studio.
|
|
128
|
+
# Blocks until the user answers in the web UI.
|
|
129
|
+
BODY="$(cat)"
|
|
130
|
+
RESPONSE=$(curl -s -X POST "${studioUrl}/api/sessions/${this.sessionId}/hook-event" \\
|
|
131
|
+
-H "Content-Type: application/json" \\
|
|
132
|
+
-H "Authorization: Bearer ${hookToken}" \\
|
|
133
|
+
-d "\${BODY}" \\
|
|
134
|
+
--max-time 360 \\
|
|
135
|
+
--connect-timeout 5 \\
|
|
136
|
+
2>/dev/null)
|
|
137
|
+
if echo "\${RESPONSE}" | grep -q '"hookSpecificOutput"'; then
|
|
138
|
+
echo "\${RESPONSE}"
|
|
139
|
+
fi
|
|
140
|
+
exit 0`;
|
|
141
|
+
const settings = JSON.stringify({
|
|
142
|
+
hooks: {
|
|
143
|
+
PreToolUse: [
|
|
144
|
+
{
|
|
145
|
+
matcher: "AskUserQuestion",
|
|
146
|
+
hooks: [
|
|
147
|
+
{
|
|
148
|
+
type: "command",
|
|
149
|
+
command: `${hookDir}/forward.sh`,
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
},
|
|
385
155
|
});
|
|
386
|
-
|
|
156
|
+
try {
|
|
157
|
+
const forwardB64 = Buffer.from(forwardScript).toString("base64");
|
|
158
|
+
const settingsB64 = Buffer.from(settings).toString("base64");
|
|
159
|
+
execFileSync("docker", [
|
|
160
|
+
"exec",
|
|
161
|
+
this.containerId,
|
|
162
|
+
"bash",
|
|
163
|
+
"-c",
|
|
164
|
+
[
|
|
165
|
+
`mkdir -p '${hookDir}'`,
|
|
166
|
+
`echo '${forwardB64}' | base64 -d > '${hookDir}/forward.sh'`,
|
|
167
|
+
`chmod +x '${hookDir}/forward.sh'`,
|
|
168
|
+
`echo '${settingsB64}' | base64 -d > '${settingsFile}'`,
|
|
169
|
+
].join(" && "),
|
|
170
|
+
]);
|
|
171
|
+
console.log(`[claude-code-docker] Installed AskUserQuestion hooks in container`);
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
console.error(`[claude-code-docker] Failed to install hooks:`, err);
|
|
175
|
+
}
|
|
387
176
|
}
|
|
388
177
|
}
|
|
389
178
|
//# sourceMappingURL=claude-code-docker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code-docker.js","sourceRoot":"","sources":["../../src/bridge/claude-code-docker.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"claude-code-docker.js","sourceRoot":"","sources":["../../src/bridge/claude-code-docker.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,75 +2,28 @@
|
|
|
2
2
|
* SessionBridge implementation that runs Claude Code CLI inside a Sprites
|
|
3
3
|
* sandbox via the Sprites SDK session API, communicating via stream-json NDJSON.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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 Sprites-specific process management
|
|
6
|
+
* (SpriteCommand lifecycle, TTY mode, ANSI stripping, Sprites hook installation).
|
|
12
7
|
*/
|
|
13
|
-
import type { EngineEvent } from "@electric-agent/protocol";
|
|
14
8
|
import type { Sprite } from "@fly/sprites";
|
|
15
9
|
import type { StreamConnectionInfo } from "../streams.js";
|
|
16
|
-
import type
|
|
17
|
-
export interface ClaudeCodeSpritesConfig {
|
|
18
|
-
/** Initial prompt (the user's app description or task) */
|
|
19
|
-
prompt: string;
|
|
20
|
-
/** Working directory inside the sprite */
|
|
21
|
-
cwd: string;
|
|
22
|
-
/** Model to use (default: claude-sonnet-4-6) */
|
|
23
|
-
model?: string;
|
|
24
|
-
/** Allowed tools (default: all standard tools) */
|
|
25
|
-
allowedTools?: string[];
|
|
26
|
-
/** Additional CLI flags */
|
|
27
|
-
extraFlags?: string[];
|
|
10
|
+
import { ClaudeCodeBaseBridge, type ClaudeCodeBaseConfig } from "./claude-code-base.js";
|
|
11
|
+
export interface ClaudeCodeSpritesConfig extends ClaudeCodeBaseConfig {
|
|
28
12
|
/** Studio server URL — used to set up AskUserQuestion hooks inside the sprite */
|
|
29
13
|
studioUrl?: string;
|
|
30
14
|
}
|
|
31
|
-
export declare class ClaudeCodeSpritesBridge
|
|
32
|
-
readonly
|
|
33
|
-
readonly streamUrl: string;
|
|
34
|
-
readonly streamHeaders: Record<string, string>;
|
|
15
|
+
export declare class ClaudeCodeSpritesBridge extends ClaudeCodeBaseBridge {
|
|
16
|
+
protected readonly logPrefix = "claude-code-sprites";
|
|
35
17
|
private sprite;
|
|
36
18
|
private config;
|
|
37
|
-
private writer;
|
|
38
|
-
private parser;
|
|
39
|
-
private agentEventCallbacks;
|
|
40
|
-
private completeCallbacks;
|
|
41
|
-
private closed;
|
|
42
19
|
private cmd;
|
|
43
|
-
/** Claude Code session ID captured from stream-json system.init — used for --resume */
|
|
44
|
-
private claudeSessionId;
|
|
45
|
-
/** Whether a Claude Code process is currently running */
|
|
46
|
-
private running;
|
|
47
|
-
/** Whether the parser already emitted a session_end (from a "result" message) */
|
|
48
|
-
private resultReceived;
|
|
49
|
-
/** Whether the process was intentionally interrupted (suppress exit handler session_end) */
|
|
50
|
-
private interrupted;
|
|
51
|
-
/** Whether hooks have been installed in the sprite */
|
|
52
|
-
private hooksInstalled;
|
|
53
20
|
constructor(sessionId: string, connection: StreamConnectionInfo, sprite: Sprite, config: ClaudeCodeSpritesConfig);
|
|
54
|
-
emit(event: EngineEvent): Promise<void>;
|
|
55
|
-
sendCommand(cmd: Record<string, unknown>): Promise<void>;
|
|
56
|
-
sendGateResponse(gate: string, value: Record<string, unknown>): Promise<void>;
|
|
57
|
-
onAgentEvent(cb: (event: EngineEvent) => void): void;
|
|
58
|
-
onComplete(cb: (success: boolean) => void): void;
|
|
59
21
|
start(): Promise<void>;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
private installHooks;
|
|
67
|
-
/**
|
|
68
|
-
* Spawn a new Claude Code process. Called for both the initial prompt
|
|
69
|
-
* and follow-up iterate messages (with --resume).
|
|
70
|
-
*/
|
|
71
|
-
private spawnClaudeAsync;
|
|
72
|
-
private handleLine;
|
|
73
|
-
private dispatchEvent;
|
|
74
|
-
private writeUserMessage;
|
|
22
|
+
protected spawnProcess(prompt: string, resumeSessionId?: string): Promise<void>;
|
|
23
|
+
protected killProcess(): void;
|
|
24
|
+
protected hasProcess(): boolean;
|
|
25
|
+
protected writeToStdin(content: string): void;
|
|
26
|
+
protected getAgentName(): string | undefined;
|
|
27
|
+
protected installHooksImpl(): Promise<void>;
|
|
75
28
|
}
|
|
76
29
|
//# sourceMappingURL=claude-code-sprites.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code-sprites.d.ts","sourceRoot":"","sources":["../../src/bridge/claude-code-sprites.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"claude-code-sprites.d.ts","sourceRoot":"","sources":["../../src/bridge/claude-code-sprites.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,EACN,oBAAoB,EACpB,KAAK,oBAAoB,EAEzB,MAAM,uBAAuB,CAAA;AAE9B,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACpE,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,qBAAa,uBAAwB,SAAQ,oBAAoB;IAChE,SAAS,CAAC,QAAQ,CAAC,SAAS,yBAAwB;IAEpD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,GAAG,CAA6B;gBAGvC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,uBAAuB;IAO1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;cASZ,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4ErF,SAAS,CAAC,WAAW,IAAI,IAAI;IAW7B,SAAS,CAAC,UAAU,IAAI,OAAO;IAI/B,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM7C,SAAS,CAAC,YAAY,IAAI,MAAM,GAAG,SAAS;cAQ5B,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;CAuDjD"}
|