@electric-agent/studio 1.7.0 → 1.12.1
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/active-sessions.d.ts +2 -0
- package/dist/active-sessions.d.ts.map +1 -1
- package/dist/active-sessions.js +4 -0
- package/dist/active-sessions.js.map +1 -1
- 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 +15 -3
- package/dist/bridge/claude-md-generator.d.ts.map +1 -1
- package/dist/bridge/claude-md-generator.js +79 -98
- 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/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-CtOOaA2Q.js +235 -0
- package/dist/client/index.html +2 -2
- package/dist/github-app.d.ts +14 -0
- package/dist/github-app.d.ts.map +1 -0
- package/dist/github-app.js +62 -0
- package/dist/github-app.js.map +1 -0
- package/dist/github-app.test.d.ts +2 -0
- package/dist/github-app.test.d.ts.map +1 -0
- package/dist/github-app.test.js +62 -0
- package/dist/github-app.test.js.map +1 -0
- 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 +1 -0
- package/dist/sandbox/docker.d.ts.map +1 -1
- package/dist/sandbox/docker.js +56 -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 +1 -0
- package/dist/sandbox/sprites.d.ts.map +1 -1
- package/dist/sandbox/sprites.js +91 -10
- package/dist/sandbox/sprites.js.map +1 -1
- package/dist/sandbox/types.d.ts +9 -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 +906 -445
- 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 +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-D5-jqAV-.js +0 -234
- package/dist/client/assets/index-YyyiO26y.css +0 -1
|
@@ -2,104 +2,95 @@
|
|
|
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
8
|
import * as readline from "node:readline";
|
|
14
|
-
import { DurableStream } from "@durable-streams/client";
|
|
15
|
-
import { ts } from "@electric-agent/protocol";
|
|
16
9
|
import { SpriteCommand } from "@fly/sprites";
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const DEFAULT_ALLOWED_TOOLS = [
|
|
21
|
-
"Read",
|
|
22
|
-
"Write",
|
|
23
|
-
"Edit",
|
|
24
|
-
"Bash",
|
|
25
|
-
"Glob",
|
|
26
|
-
"Grep",
|
|
27
|
-
"WebSearch",
|
|
28
|
-
"TodoWrite",
|
|
29
|
-
"AskUserQuestion",
|
|
30
|
-
"Skill",
|
|
31
|
-
];
|
|
32
|
-
export class ClaudeCodeSpritesBridge {
|
|
33
|
-
sessionId;
|
|
34
|
-
streamUrl;
|
|
35
|
-
streamHeaders;
|
|
10
|
+
import { ClaudeCodeBaseBridge, DEFAULT_ALLOWED_TOOLS, } from "./claude-code-base.js";
|
|
11
|
+
export class ClaudeCodeSpritesBridge extends ClaudeCodeBaseBridge {
|
|
12
|
+
logPrefix = "claude-code-sprites";
|
|
36
13
|
sprite;
|
|
37
14
|
config;
|
|
38
|
-
writer;
|
|
39
|
-
parser = createStreamJsonParser();
|
|
40
|
-
agentEventCallbacks = [];
|
|
41
|
-
completeCallbacks = [];
|
|
42
|
-
closed = false;
|
|
43
15
|
cmd = null;
|
|
44
|
-
/** Claude Code session ID captured from stream-json system.init — used for --resume */
|
|
45
|
-
claudeSessionId = null;
|
|
46
|
-
/** Whether a Claude Code process is currently running */
|
|
47
|
-
running = false;
|
|
48
|
-
/** Whether the parser already emitted a session_end (from a "result" message) */
|
|
49
|
-
resultReceived = false;
|
|
50
|
-
/** Whether the process was intentionally interrupted (suppress exit handler session_end) */
|
|
51
|
-
interrupted = false;
|
|
52
|
-
/** Whether hooks have been installed in the sprite */
|
|
53
|
-
hooksInstalled = false;
|
|
54
16
|
constructor(sessionId, connection, sprite, config) {
|
|
55
|
-
|
|
56
|
-
this.streamUrl = connection.url;
|
|
57
|
-
this.streamHeaders = connection.headers;
|
|
17
|
+
super(sessionId, connection);
|
|
58
18
|
this.sprite = sprite;
|
|
59
19
|
this.config = config;
|
|
60
|
-
this.writer = new DurableStream({
|
|
61
|
-
url: connection.url,
|
|
62
|
-
headers: connection.headers,
|
|
63
|
-
contentType: "application/json",
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
async emit(event) {
|
|
67
|
-
if (this.closed)
|
|
68
|
-
return;
|
|
69
|
-
const msg = { source: "server", ...event };
|
|
70
|
-
await this.writer.append(JSON.stringify(msg));
|
|
71
20
|
}
|
|
72
|
-
async
|
|
21
|
+
async start() {
|
|
73
22
|
if (this.closed)
|
|
74
23
|
return;
|
|
75
|
-
|
|
76
|
-
// Respawn Claude Code with --resume for follow-up messages
|
|
77
|
-
this.spawnClaudeAsync(cmd.request, this.claudeSessionId ?? undefined);
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
console.log(`[claude-code-sprites] Ignoring unsupported command: ${cmd.command}`);
|
|
24
|
+
await this.spawnProcess(this.config.prompt);
|
|
81
25
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
26
|
+
// -------------------------------------------------------------------
|
|
27
|
+
// Abstract method implementations
|
|
28
|
+
// -------------------------------------------------------------------
|
|
29
|
+
async spawnProcess(prompt, resumeSessionId) {
|
|
30
|
+
// Kill any existing process
|
|
31
|
+
this.killProcess();
|
|
32
|
+
// Install hooks on first spawn — must await for sprites
|
|
33
|
+
await this.ensureHooksInstalled();
|
|
34
|
+
// Reset parser state for the new process
|
|
35
|
+
this.resetParserState();
|
|
36
|
+
const model = this.config.model ?? "claude-sonnet-4-6";
|
|
37
|
+
const allowedTools = this.config.allowedTools ?? DEFAULT_ALLOWED_TOOLS;
|
|
38
|
+
const claudeArgs = [
|
|
39
|
+
"-p",
|
|
40
|
+
prompt,
|
|
41
|
+
"--output-format",
|
|
42
|
+
"stream-json",
|
|
43
|
+
"--verbose",
|
|
44
|
+
"--model",
|
|
45
|
+
model,
|
|
46
|
+
...(this.hooksInstalled
|
|
47
|
+
? ["--allowedTools", allowedTools.join(",")]
|
|
48
|
+
: ["--dangerously-skip-permissions"]),
|
|
49
|
+
...(this.config.extraFlags ?? []),
|
|
50
|
+
];
|
|
51
|
+
if (resumeSessionId) {
|
|
52
|
+
claudeArgs.push("--resume", resumeSessionId);
|
|
88
53
|
}
|
|
54
|
+
const escapedArgs = claudeArgs.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ");
|
|
55
|
+
const fullCmd = `source /etc/profile.d/npm-global.sh 2>/dev/null; source /etc/profile.d/electric-agent.sh 2>/dev/null; cd '${this.config.cwd}' && claude ${escapedArgs}`;
|
|
56
|
+
// Use SpriteCommand with tty:true — Claude Code requires a TTY to produce
|
|
57
|
+
// stream-json output in sprites (non-TTY mode results in zero stdout).
|
|
58
|
+
// Do NOT use detachable (creates a tmux session causing immediate exit).
|
|
59
|
+
this.cmd = new SpriteCommand(this.sprite, "bash", ["-c", fullCmd], {
|
|
60
|
+
tty: true,
|
|
61
|
+
});
|
|
62
|
+
this.cmd.start();
|
|
63
|
+
console.log(`[claude-code-sprites] Started: session=${this.sessionId} resume=${resumeSessionId ?? "none"}`);
|
|
64
|
+
const currentCmd = this.cmd;
|
|
65
|
+
// Read stdout line by line (stream-json NDJSON)
|
|
66
|
+
const rl = readline.createInterface({
|
|
67
|
+
input: currentCmd.stdout,
|
|
68
|
+
terminal: false,
|
|
69
|
+
});
|
|
70
|
+
rl.on("line", (line) => {
|
|
71
|
+
if (this.closed)
|
|
72
|
+
return;
|
|
73
|
+
// Strip ANSI escape sequences added by TTY mode before parsing
|
|
74
|
+
const cleaned = stripAnsi(line).trim();
|
|
75
|
+
if (!cleaned)
|
|
76
|
+
return;
|
|
77
|
+
this.handleLine(cleaned);
|
|
78
|
+
});
|
|
79
|
+
// Log stderr
|
|
80
|
+
const stderrRl = readline.createInterface({
|
|
81
|
+
input: currentCmd.stderr,
|
|
82
|
+
terminal: false,
|
|
83
|
+
});
|
|
84
|
+
stderrRl.on("line", (line) => {
|
|
85
|
+
if (!this.closed) {
|
|
86
|
+
console.error(`[claude-code-sprites:stderr] ${line}`);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
currentCmd.on("exit", (code) => {
|
|
90
|
+
this.handleProcessExit(code);
|
|
91
|
+
});
|
|
89
92
|
}
|
|
90
|
-
|
|
91
|
-
this.agentEventCallbacks.push(cb);
|
|
92
|
-
}
|
|
93
|
-
onComplete(cb) {
|
|
94
|
-
this.completeCallbacks.push(cb);
|
|
95
|
-
}
|
|
96
|
-
async start() {
|
|
97
|
-
if (this.closed)
|
|
98
|
-
return;
|
|
99
|
-
await this.spawnClaudeAsync(this.config.prompt);
|
|
100
|
-
}
|
|
101
|
-
interrupt() {
|
|
102
|
-
this.interrupted = true;
|
|
93
|
+
killProcess() {
|
|
103
94
|
if (this.cmd) {
|
|
104
95
|
try {
|
|
105
96
|
this.cmd.kill();
|
|
@@ -109,37 +100,33 @@ export class ClaudeCodeSpritesBridge {
|
|
|
109
100
|
}
|
|
110
101
|
this.cmd = null;
|
|
111
102
|
}
|
|
112
|
-
this.running = false;
|
|
113
103
|
}
|
|
114
|
-
|
|
115
|
-
this.
|
|
104
|
+
hasProcess() {
|
|
105
|
+
return this.cmd != null;
|
|
106
|
+
}
|
|
107
|
+
writeToStdin(content) {
|
|
116
108
|
if (this.cmd) {
|
|
117
|
-
|
|
118
|
-
this.cmd.kill();
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
// Process may already be dead
|
|
122
|
-
}
|
|
123
|
-
this.cmd = null;
|
|
109
|
+
this.cmd.stdin.write(content);
|
|
124
110
|
}
|
|
125
111
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
async installHooks() {
|
|
112
|
+
getAgentName() {
|
|
113
|
+
return this.config.agentName;
|
|
114
|
+
}
|
|
115
|
+
// -------------------------------------------------------------------
|
|
116
|
+
// Sprites-specific hook installation
|
|
117
|
+
// -------------------------------------------------------------------
|
|
118
|
+
async installHooksImpl() {
|
|
134
119
|
const studioUrl = this.config.studioUrl;
|
|
135
120
|
if (!studioUrl)
|
|
136
121
|
return;
|
|
137
122
|
const hookDir = `${this.config.cwd}/.claude/hooks`;
|
|
138
123
|
const settingsFile = `${this.config.cwd}/.claude/settings.local.json`;
|
|
124
|
+
const hookToken = this.config.hookToken ?? "";
|
|
139
125
|
const forwardScript = `#!/bin/bash
|
|
140
126
|
BODY="$(cat)"
|
|
141
127
|
RESPONSE=$(curl -s -X POST "${studioUrl}/api/sessions/${this.sessionId}/hook-event" \\
|
|
142
128
|
-H "Content-Type: application/json" \\
|
|
129
|
+
-H "Authorization: Bearer ${hookToken}" \\
|
|
143
130
|
-d "\${BODY}" \\
|
|
144
131
|
--max-time 360 \\
|
|
145
132
|
--connect-timeout 5 \\
|
|
@@ -148,9 +135,6 @@ if echo "\${RESPONSE}" | grep -q '"hookSpecificOutput"'; then
|
|
|
148
135
|
echo "\${RESPONSE}"
|
|
149
136
|
fi
|
|
150
137
|
exit 0`;
|
|
151
|
-
// Configure hooks in settings.local.json.
|
|
152
|
-
// Tool permissions come from --allowedTools CLI flag instead.
|
|
153
|
-
// Hook format: each event has matcher groups, each with a `hooks` array.
|
|
154
138
|
const settings = JSON.stringify({
|
|
155
139
|
hooks: {
|
|
156
140
|
PreToolUse: [
|
|
@@ -167,7 +151,6 @@ exit 0`;
|
|
|
167
151
|
},
|
|
168
152
|
});
|
|
169
153
|
try {
|
|
170
|
-
// Use base64 encoding to avoid heredoc delimiter issues
|
|
171
154
|
const forwardB64 = Buffer.from(forwardScript).toString("base64");
|
|
172
155
|
const settingsB64 = Buffer.from(settings).toString("base64");
|
|
173
156
|
await this.sprite.execFile("bash", [
|
|
@@ -185,182 +168,6 @@ exit 0`;
|
|
|
185
168
|
console.error(`[claude-code-sprites] Failed to install hooks:`, err);
|
|
186
169
|
}
|
|
187
170
|
}
|
|
188
|
-
/**
|
|
189
|
-
* Spawn a new Claude Code process. Called for both the initial prompt
|
|
190
|
-
* and follow-up iterate messages (with --resume).
|
|
191
|
-
*/
|
|
192
|
-
async spawnClaudeAsync(prompt, resumeSessionId) {
|
|
193
|
-
// Kill any existing process
|
|
194
|
-
if (this.cmd) {
|
|
195
|
-
try {
|
|
196
|
-
this.cmd.kill();
|
|
197
|
-
}
|
|
198
|
-
catch {
|
|
199
|
-
// Already dead
|
|
200
|
-
}
|
|
201
|
-
this.cmd = null;
|
|
202
|
-
}
|
|
203
|
-
// Install hooks on first spawn (they persist for resume spawns)
|
|
204
|
-
// Must await to ensure hooks are in place before Claude starts.
|
|
205
|
-
if (!this.hooksInstalled) {
|
|
206
|
-
try {
|
|
207
|
-
await this.installHooks();
|
|
208
|
-
this.hooksInstalled = true;
|
|
209
|
-
}
|
|
210
|
-
catch (err) {
|
|
211
|
-
console.error(`[claude-code-sprites] Hook install error:`, err);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
// Reset parser state for the new process
|
|
215
|
-
this.parser = createStreamJsonParser();
|
|
216
|
-
this.resultReceived = false;
|
|
217
|
-
this.interrupted = false;
|
|
218
|
-
this.running = true;
|
|
219
|
-
const model = this.config.model ?? "claude-sonnet-4-6";
|
|
220
|
-
// Build the claude CLI command.
|
|
221
|
-
// Use --allowedTools to grant permissions (keeps hooks firing, unlike
|
|
222
|
-
// --dangerously-skip-permissions which bypasses hooks entirely).
|
|
223
|
-
const allowedTools = this.config.allowedTools ?? DEFAULT_ALLOWED_TOOLS;
|
|
224
|
-
const claudeArgs = [
|
|
225
|
-
"-p",
|
|
226
|
-
prompt,
|
|
227
|
-
"--output-format",
|
|
228
|
-
"stream-json",
|
|
229
|
-
"--verbose",
|
|
230
|
-
"--model",
|
|
231
|
-
model,
|
|
232
|
-
...(this.hooksInstalled
|
|
233
|
-
? ["--allowedTools", allowedTools.join(",")]
|
|
234
|
-
: ["--dangerously-skip-permissions"]),
|
|
235
|
-
...(this.config.extraFlags ?? []),
|
|
236
|
-
];
|
|
237
|
-
// Add --resume if we have a previous session ID
|
|
238
|
-
if (resumeSessionId) {
|
|
239
|
-
claudeArgs.push("--resume", resumeSessionId);
|
|
240
|
-
}
|
|
241
|
-
// Escape for bash — use bash -c with properly escaped args
|
|
242
|
-
const escapedArgs = claudeArgs.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ");
|
|
243
|
-
const fullCmd = `source /etc/profile.d/npm-global.sh 2>/dev/null; source /etc/profile.d/electric-agent.sh 2>/dev/null; cd '${this.config.cwd}' && claude ${escapedArgs}`;
|
|
244
|
-
// Use SpriteCommand with tty:true — Claude Code requires a TTY to produce
|
|
245
|
-
// stream-json output in sprites (non-TTY mode results in zero stdout).
|
|
246
|
-
// Do NOT use detachable (creates a tmux session causing immediate exit).
|
|
247
|
-
this.cmd = new SpriteCommand(this.sprite, "bash", ["-c", fullCmd], {
|
|
248
|
-
tty: true,
|
|
249
|
-
});
|
|
250
|
-
this.cmd.start();
|
|
251
|
-
console.log(`[claude-code-sprites] Started: session=${this.sessionId} resume=${resumeSessionId ?? "none"}`);
|
|
252
|
-
const currentCmd = this.cmd;
|
|
253
|
-
// Read stdout line by line (stream-json NDJSON)
|
|
254
|
-
const rl = readline.createInterface({
|
|
255
|
-
input: currentCmd.stdout,
|
|
256
|
-
terminal: false,
|
|
257
|
-
});
|
|
258
|
-
rl.on("line", (line) => {
|
|
259
|
-
if (this.closed)
|
|
260
|
-
return;
|
|
261
|
-
this.handleLine(line);
|
|
262
|
-
});
|
|
263
|
-
// Log stderr
|
|
264
|
-
const stderrRl = readline.createInterface({
|
|
265
|
-
input: currentCmd.stderr,
|
|
266
|
-
terminal: false,
|
|
267
|
-
});
|
|
268
|
-
stderrRl.on("line", (line) => {
|
|
269
|
-
if (!this.closed) {
|
|
270
|
-
console.error(`[claude-code-sprites:stderr] ${line}`);
|
|
271
|
-
}
|
|
272
|
-
});
|
|
273
|
-
// Handle process exit — defer to let pending readline events flush first,
|
|
274
|
-
// which prevents duplicate session_end (the parser emits one from "result").
|
|
275
|
-
currentCmd.on("exit", (code) => {
|
|
276
|
-
console.log(`[claude-code-sprites] Process exited: code=${code} session=${this.sessionId}`);
|
|
277
|
-
setTimeout(() => {
|
|
278
|
-
// Capture session ID from parser state before marking not running
|
|
279
|
-
if (this.parser.state.sessionId) {
|
|
280
|
-
this.claudeSessionId = this.parser.state.sessionId;
|
|
281
|
-
}
|
|
282
|
-
this.running = false;
|
|
283
|
-
// Only emit session_end from exit handler if the parser didn't already
|
|
284
|
-
// emit one (via a "result" message) and the process wasn't intentionally
|
|
285
|
-
// interrupted. This prevents double session_end.
|
|
286
|
-
if (!this.closed && !this.resultReceived && !this.interrupted) {
|
|
287
|
-
const endEvent = {
|
|
288
|
-
type: "session_end",
|
|
289
|
-
success: code === 0,
|
|
290
|
-
ts: ts(),
|
|
291
|
-
};
|
|
292
|
-
this.dispatchEvent(endEvent);
|
|
293
|
-
}
|
|
294
|
-
}, 100);
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
handleLine(line) {
|
|
298
|
-
// Strip ANSI escape sequences and terminal control chars added by tty mode
|
|
299
|
-
const cleaned = stripAnsi(line).trim();
|
|
300
|
-
if (!cleaned)
|
|
301
|
-
return;
|
|
302
|
-
const events = this.parser.parse(cleaned);
|
|
303
|
-
for (const event of events) {
|
|
304
|
-
this.dispatchEvent(event);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
dispatchEvent(event) {
|
|
308
|
-
const msg = { source: "agent", ...event };
|
|
309
|
-
this.writer.append(JSON.stringify(msg)).catch(() => { });
|
|
310
|
-
// Track session_end from result messages to prevent duplicates
|
|
311
|
-
if (event.type === "session_end") {
|
|
312
|
-
this.resultReceived = true;
|
|
313
|
-
}
|
|
314
|
-
// Detect dev:start in Bash tool_use → emit app_status for the UI preview
|
|
315
|
-
if (event.type === "pre_tool_use" && event.tool_name === "Bash") {
|
|
316
|
-
const cmd = event.tool_input?.command;
|
|
317
|
-
if (typeof cmd === "string" && /\bdev:start\b/.test(cmd)) {
|
|
318
|
-
const appStatus = {
|
|
319
|
-
type: "app_status",
|
|
320
|
-
status: "running",
|
|
321
|
-
ts: ts(),
|
|
322
|
-
};
|
|
323
|
-
const appStatusMsg = { source: "agent", ...appStatus };
|
|
324
|
-
this.writer.append(JSON.stringify(appStatusMsg)).catch(() => { });
|
|
325
|
-
for (const cb of this.agentEventCallbacks) {
|
|
326
|
-
try {
|
|
327
|
-
cb(appStatus);
|
|
328
|
-
}
|
|
329
|
-
catch {
|
|
330
|
-
// Swallow
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
for (const cb of this.agentEventCallbacks) {
|
|
336
|
-
try {
|
|
337
|
-
cb(event);
|
|
338
|
-
}
|
|
339
|
-
catch {
|
|
340
|
-
// Swallow callback errors
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
if (event.type === "session_end" && "success" in event) {
|
|
344
|
-
const success = event.success;
|
|
345
|
-
for (const cb of this.completeCallbacks) {
|
|
346
|
-
try {
|
|
347
|
-
cb(success);
|
|
348
|
-
}
|
|
349
|
-
catch {
|
|
350
|
-
// Swallow callback errors
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
writeUserMessage(content) {
|
|
356
|
-
if (!this.cmd)
|
|
357
|
-
return;
|
|
358
|
-
const msg = JSON.stringify({
|
|
359
|
-
type: "user",
|
|
360
|
-
message: { role: "user", content },
|
|
361
|
-
});
|
|
362
|
-
this.cmd.stdin.write(`${msg}\n`);
|
|
363
|
-
}
|
|
364
171
|
}
|
|
365
172
|
/** Strip ANSI escape sequences and control characters from tty output */
|
|
366
173
|
function stripAnsi(str) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code-sprites.js","sourceRoot":"","sources":["../../src/bridge/claude-code-sprites.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"claude-code-sprites.js","sourceRoot":"","sources":["../../src/bridge/claude-code-sprites.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Generates CLAUDE.md files for project workspaces.
|
|
3
|
+
*
|
|
4
|
+
* CLAUDE.md provides environment context, infrastructure details, and guardrails.
|
|
5
|
+
* Implementation details (phase order, API patterns, code templates) live in the
|
|
6
|
+
* create-app skill (.claude/skills/create-app/SKILL.md) and in playbook skills
|
|
7
|
+
* shipped with npm dependencies (discoverable via `npx @tanstack/intent list`).
|
|
3
8
|
*/
|
|
4
9
|
export interface GitConfig {
|
|
5
|
-
/** "create" — agent should git init + gh repo create after scaffolding */
|
|
10
|
+
/** "create" — agent should git init + gh repo create after scaffolding (dev mode) */
|
|
11
|
+
/** "pre-created" — repo already exists, git remote configured; agent just commits + pushes (prod mode) */
|
|
6
12
|
/** "existing" — repo was cloned; agent should commit + push after changes */
|
|
7
|
-
mode: "create" | "existing";
|
|
13
|
+
mode: "create" | "pre-created" | "existing";
|
|
8
14
|
/** Full repo name, e.g. "owner/repo-name" */
|
|
9
15
|
repoName: string;
|
|
16
|
+
/** Repo HTML URL (only for pre-created mode) */
|
|
17
|
+
repoUrl?: string;
|
|
10
18
|
/** Visibility for new repos (only relevant when mode=create) */
|
|
11
19
|
visibility?: "public" | "private";
|
|
12
20
|
/** Branch name (only relevant when mode=existing) */
|
|
@@ -24,10 +32,14 @@ export interface ClaudeMdOptions {
|
|
|
24
32
|
/** Iteration request text (if isIteration) */
|
|
25
33
|
iterationRequest?: string;
|
|
26
34
|
/** Sandbox runtime — affects environment-specific instructions */
|
|
27
|
-
runtime?: "docker" | "sprites"
|
|
35
|
+
runtime?: "docker" | "sprites";
|
|
28
36
|
/** Git/GitHub configuration — when set, git instructions are injected */
|
|
29
37
|
git?: GitConfig;
|
|
38
|
+
/** When true, inject production guardrails that restrict agent scope */
|
|
39
|
+
production?: boolean;
|
|
30
40
|
}
|
|
31
41
|
export declare function generateClaudeMd(opts: ClaudeMdOptions): string;
|
|
32
42
|
export { createAppSkillContent } from "./create-app-skill.js";
|
|
43
|
+
export { resolveRoleSkill } from "./role-skills.js";
|
|
44
|
+
export { roomMessagingSkillContent } from "./room-messaging-skill.js";
|
|
33
45
|
//# sourceMappingURL=claude-md-generator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-md-generator.d.ts","sourceRoot":"","sources":["../../src/bridge/claude-md-generator.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"claude-md-generator.d.ts","sourceRoot":"","sources":["../../src/bridge/claude-md-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,SAAS;IACzB,qFAAqF;IACrF,0GAA0G;IAC1G,6EAA6E;IAC7E,IAAI,EAAE,QAAQ,GAAG,aAAa,GAAG,UAAU,CAAA;IAC3C,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAA;IAChB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,gEAAgE;IAChE,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAA;IACjC,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,eAAe;IAC/B,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAA;IACnB,gCAAgC;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAA;IAClB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,kEAAkE;IAClE,OAAO,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAA;IAC9B,yEAAyE;IACzE,GAAG,CAAC,EAAE,SAAS,CAAA;IACf,wEAAwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CA6C9D;AAkOD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAA"}
|