@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
|
@@ -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":"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"}
|
|
@@ -1,88 +1,28 @@
|
|
|
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
|
-
import type { EngineEvent } from "@electric-agent/protocol";
|
|
14
8
|
import type { StreamConnectionInfo } from "../streams.js";
|
|
15
|
-
import type
|
|
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
|
|
31
|
-
readonly
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
|
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"}
|