@electric-agent/studio 1.0.0 → 1.1.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.
Files changed (68) hide show
  1. package/dist/active-sessions.d.ts +28 -0
  2. package/dist/active-sessions.d.ts.map +1 -0
  3. package/dist/active-sessions.js +50 -0
  4. package/dist/active-sessions.js.map +1 -0
  5. package/dist/bridge/claude-code-docker.d.ts +74 -0
  6. package/dist/bridge/claude-code-docker.d.ts.map +1 -0
  7. package/dist/bridge/claude-code-docker.js +305 -0
  8. package/dist/bridge/claude-code-docker.js.map +1 -0
  9. package/dist/bridge/claude-code-sprites.d.ts +64 -0
  10. package/dist/bridge/claude-code-sprites.d.ts.map +1 -0
  11. package/dist/bridge/claude-code-sprites.js +293 -0
  12. package/dist/bridge/claude-code-sprites.js.map +1 -0
  13. package/dist/bridge/claude-md-generator.d.ts +24 -0
  14. package/dist/bridge/claude-md-generator.d.ts.map +1 -0
  15. package/dist/bridge/claude-md-generator.js +303 -0
  16. package/dist/bridge/claude-md-generator.js.map +1 -0
  17. package/dist/bridge/index.d.ts +3 -0
  18. package/dist/bridge/index.d.ts.map +1 -1
  19. package/dist/bridge/index.js +3 -0
  20. package/dist/bridge/index.js.map +1 -1
  21. package/dist/bridge/stream-json-parser.d.ts +30 -0
  22. package/dist/bridge/stream-json-parser.d.ts.map +1 -0
  23. package/dist/bridge/stream-json-parser.js +207 -0
  24. package/dist/bridge/stream-json-parser.js.map +1 -0
  25. package/dist/client/assets/index-BeZ6CTGd.css +1 -0
  26. package/dist/client/assets/index-DRLXdDNp.js +241 -0
  27. package/dist/client/index.html +2 -2
  28. package/dist/index.d.ts +5 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +4 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/project-utils.d.ts +2 -1
  33. package/dist/project-utils.d.ts.map +1 -1
  34. package/dist/project-utils.js +2 -6
  35. package/dist/project-utils.js.map +1 -1
  36. package/dist/registry.d.ts +52 -0
  37. package/dist/registry.d.ts.map +1 -0
  38. package/dist/registry.js +204 -0
  39. package/dist/registry.js.map +1 -0
  40. package/dist/room-registry.d.ts +40 -0
  41. package/dist/room-registry.d.ts.map +1 -0
  42. package/dist/room-registry.js +112 -0
  43. package/dist/room-registry.js.map +1 -0
  44. package/dist/sandbox/sprites-bootstrap.d.ts.map +1 -1
  45. package/dist/sandbox/sprites-bootstrap.js +7 -1
  46. package/dist/sandbox/sprites-bootstrap.js.map +1 -1
  47. package/dist/sandbox/sprites.d.ts +5 -0
  48. package/dist/sandbox/sprites.d.ts.map +1 -1
  49. package/dist/sandbox/sprites.js +22 -2
  50. package/dist/sandbox/sprites.js.map +1 -1
  51. package/dist/server.d.ts +9 -2
  52. package/dist/server.d.ts.map +1 -1
  53. package/dist/server.js +625 -58
  54. package/dist/server.js.map +1 -1
  55. package/dist/sessions.d.ts +2 -0
  56. package/dist/sessions.d.ts.map +1 -1
  57. package/dist/sessions.js.map +1 -1
  58. package/dist/shared-sessions.d.ts +16 -0
  59. package/dist/shared-sessions.d.ts.map +1 -0
  60. package/dist/shared-sessions.js +52 -0
  61. package/dist/shared-sessions.js.map +1 -0
  62. package/dist/streams.d.ts +8 -0
  63. package/dist/streams.d.ts.map +1 -1
  64. package/dist/streams.js +22 -0
  65. package/dist/streams.js.map +1 -1
  66. package/package.json +15 -2
  67. package/dist/client/assets/index-CK__1-6e.css +0 -1
  68. package/dist/client/assets/index-DKL-jl7t.js +0 -241
@@ -0,0 +1,293 @@
1
+ /**
2
+ * SessionBridge implementation that runs Claude Code CLI inside a Sprites
3
+ * sandbox via the Sprites SDK session API, communicating via stream-json NDJSON.
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.
12
+ */
13
+ import * as readline from "node:readline";
14
+ import { DurableStream } from "@durable-streams/client";
15
+ import { ts } from "@electric-agent/protocol";
16
+ import { SpriteCommand } from "@fly/sprites";
17
+ import { createStreamJsonParser } from "./stream-json-parser.js";
18
+ const SPRITES_SESSION_ID = "claude-code-session";
19
+ const DEFAULT_ALLOWED_TOOLS = [
20
+ "Read",
21
+ "Write",
22
+ "Edit",
23
+ "Bash",
24
+ "Glob",
25
+ "Grep",
26
+ "WebSearch",
27
+ "TodoWrite",
28
+ "AskUserQuestion",
29
+ ];
30
+ export class ClaudeCodeSpritesBridge {
31
+ sessionId;
32
+ streamUrl;
33
+ streamHeaders;
34
+ sprite;
35
+ config;
36
+ writer;
37
+ parser = createStreamJsonParser();
38
+ agentEventCallbacks = [];
39
+ completeCallbacks = [];
40
+ closed = false;
41
+ cmd = null;
42
+ /** Claude Code session ID captured from stream-json system.init — used for --resume */
43
+ claudeSessionId = null;
44
+ /** Whether a Claude Code process is currently running */
45
+ running = false;
46
+ /** Whether the parser already emitted a session_end (from a "result" message) */
47
+ resultReceived = false;
48
+ constructor(sessionId, connection, sprite, config) {
49
+ this.sessionId = sessionId;
50
+ this.streamUrl = connection.url;
51
+ this.streamHeaders = connection.headers;
52
+ this.sprite = sprite;
53
+ this.config = config;
54
+ this.writer = new DurableStream({
55
+ url: connection.url,
56
+ headers: connection.headers,
57
+ contentType: "application/json",
58
+ });
59
+ }
60
+ async emit(event) {
61
+ if (this.closed)
62
+ return;
63
+ const msg = { source: "server", ...event };
64
+ await this.writer.append(JSON.stringify(msg));
65
+ }
66
+ async sendCommand(cmd) {
67
+ if (this.closed)
68
+ return;
69
+ if (cmd.command === "iterate" && typeof cmd.request === "string") {
70
+ // Respawn Claude Code with --resume for follow-up messages
71
+ this.spawnClaude(cmd.request, this.claudeSessionId ?? undefined);
72
+ return;
73
+ }
74
+ console.log(`[claude-code-sprites] Ignoring unsupported command: ${cmd.command}`);
75
+ }
76
+ async sendGateResponse(gate, value) {
77
+ if (this.closed || !this.cmd)
78
+ return;
79
+ if (gate === "ask_user_question" || gate.startsWith("ask_user_question:")) {
80
+ const answer = value.answer || "";
81
+ this.writeUserMessage(answer);
82
+ return;
83
+ }
84
+ if (gate === "clarification") {
85
+ const answers = value.answers;
86
+ if (answers?.length) {
87
+ this.writeUserMessage(answers.join("\n"));
88
+ }
89
+ return;
90
+ }
91
+ if (gate === "approval") {
92
+ const decision = value.decision || "approve";
93
+ this.writeUserMessage(decision);
94
+ return;
95
+ }
96
+ if (gate === "continue") {
97
+ const proceed = value.proceed;
98
+ this.writeUserMessage(proceed ? "continue" : "stop");
99
+ return;
100
+ }
101
+ this.writeUserMessage(JSON.stringify(value));
102
+ }
103
+ onAgentEvent(cb) {
104
+ this.agentEventCallbacks.push(cb);
105
+ }
106
+ onComplete(cb) {
107
+ this.completeCallbacks.push(cb);
108
+ }
109
+ async start() {
110
+ if (this.closed)
111
+ return;
112
+ this.spawnClaude(this.config.prompt);
113
+ }
114
+ close() {
115
+ this.closed = true;
116
+ if (this.cmd) {
117
+ try {
118
+ this.cmd.kill();
119
+ }
120
+ catch {
121
+ // Process may already be dead
122
+ }
123
+ this.cmd = null;
124
+ }
125
+ }
126
+ // -----------------------------------------------------------------------
127
+ // Private helpers
128
+ // -----------------------------------------------------------------------
129
+ /**
130
+ * Spawn a new Claude Code process. Called for both the initial prompt
131
+ * and follow-up iterate messages (with --resume).
132
+ */
133
+ spawnClaude(prompt, resumeSessionId) {
134
+ // Kill any existing process
135
+ if (this.cmd) {
136
+ try {
137
+ this.cmd.kill();
138
+ }
139
+ catch {
140
+ // Already dead
141
+ }
142
+ this.cmd = null;
143
+ }
144
+ // Reset parser state for the new process
145
+ this.parser = createStreamJsonParser();
146
+ this.resultReceived = false;
147
+ this.running = true;
148
+ const allowedTools = this.config.allowedTools ?? DEFAULT_ALLOWED_TOOLS;
149
+ const model = this.config.model ?? "claude-sonnet-4-6";
150
+ // Build the claude CLI command
151
+ const claudeArgs = [
152
+ "-p",
153
+ prompt,
154
+ "--output-format",
155
+ "stream-json",
156
+ "--verbose",
157
+ "--model",
158
+ model,
159
+ "--dangerously-skip-permissions",
160
+ "--allowedTools",
161
+ allowedTools.join(","),
162
+ ...(this.config.extraFlags ?? []),
163
+ ];
164
+ // Add --resume if we have a previous session ID
165
+ if (resumeSessionId) {
166
+ claudeArgs.push("--resume", resumeSessionId);
167
+ }
168
+ // Escape for bash — use bash -c with properly escaped args
169
+ const escapedArgs = claudeArgs.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ");
170
+ 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}`;
171
+ // Use SpriteCommand with tty:true (for streaming) but NOT detachable
172
+ // (detachable creates a tmux session which causes immediate exit)
173
+ this.cmd = new SpriteCommand(this.sprite, "bash", ["-c", fullCmd], {
174
+ tty: true,
175
+ });
176
+ this.cmd.start();
177
+ console.log(`[claude-code-sprites] Started: session=${this.sessionId} resume=${resumeSessionId ?? "none"}`);
178
+ const currentCmd = this.cmd;
179
+ // Read stdout line by line (stream-json NDJSON)
180
+ const rl = readline.createInterface({
181
+ input: currentCmd.stdout,
182
+ terminal: false,
183
+ });
184
+ rl.on("line", (line) => {
185
+ if (this.closed)
186
+ return;
187
+ this.handleLine(line);
188
+ });
189
+ // Log stderr
190
+ const stderrRl = readline.createInterface({
191
+ input: currentCmd.stderr,
192
+ terminal: false,
193
+ });
194
+ stderrRl.on("line", (line) => {
195
+ if (!this.closed) {
196
+ console.error(`[claude-code-sprites:stderr] ${line}`);
197
+ }
198
+ });
199
+ // Handle process exit
200
+ currentCmd.on("exit", (code) => {
201
+ console.log(`[claude-code-sprites] Process exited: code=${code} session=${this.sessionId}`);
202
+ // Capture session ID from parser state before marking not running
203
+ if (this.parser.state.sessionId) {
204
+ this.claudeSessionId = this.parser.state.sessionId;
205
+ }
206
+ this.running = false;
207
+ // Only emit session_end from exit handler if the parser didn't already
208
+ // emit one (via a "result" message). This prevents double session_end.
209
+ if (!this.closed && !this.resultReceived) {
210
+ const endEvent = {
211
+ type: "session_end",
212
+ success: code === 0,
213
+ ts: ts(),
214
+ };
215
+ this.dispatchEvent(endEvent);
216
+ }
217
+ });
218
+ }
219
+ handleLine(line) {
220
+ // Strip ANSI escape sequences and terminal control chars added by tty mode
221
+ const cleaned = stripAnsi(line).trim();
222
+ if (!cleaned)
223
+ return;
224
+ const events = this.parser.parse(cleaned);
225
+ for (const event of events) {
226
+ this.dispatchEvent(event);
227
+ }
228
+ }
229
+ dispatchEvent(event) {
230
+ const msg = { source: "agent", ...event };
231
+ this.writer.append(JSON.stringify(msg)).catch(() => { });
232
+ // Track session_end from result messages to prevent duplicates
233
+ if (event.type === "session_end") {
234
+ this.resultReceived = true;
235
+ }
236
+ // Detect dev:start in Bash tool_use → emit app_ready for the UI preview
237
+ if (event.type === "pre_tool_use" && event.tool_name === "Bash") {
238
+ const cmd = event.tool_input?.command;
239
+ if (typeof cmd === "string" && /\bdev:start\b/.test(cmd)) {
240
+ const appReady = { type: "app_ready", ts: ts() };
241
+ const appReadyMsg = { source: "agent", ...appReady };
242
+ this.writer.append(JSON.stringify(appReadyMsg)).catch(() => { });
243
+ for (const cb of this.agentEventCallbacks) {
244
+ try {
245
+ cb(appReady);
246
+ }
247
+ catch {
248
+ // Swallow
249
+ }
250
+ }
251
+ }
252
+ }
253
+ for (const cb of this.agentEventCallbacks) {
254
+ try {
255
+ cb(event);
256
+ }
257
+ catch {
258
+ // Swallow callback errors
259
+ }
260
+ }
261
+ if (event.type === "session_end" && "success" in event) {
262
+ const success = event.success;
263
+ for (const cb of this.completeCallbacks) {
264
+ try {
265
+ cb(success);
266
+ }
267
+ catch {
268
+ // Swallow callback errors
269
+ }
270
+ }
271
+ }
272
+ }
273
+ writeUserMessage(content) {
274
+ if (!this.cmd)
275
+ return;
276
+ const msg = JSON.stringify({
277
+ type: "user",
278
+ message: { role: "user", content },
279
+ });
280
+ this.cmd.stdin.write(`${msg}\n`);
281
+ }
282
+ }
283
+ /** Strip ANSI escape sequences and control characters from tty output */
284
+ function stripAnsi(str) {
285
+ const ESC = "\x1b";
286
+ const csi = new RegExp(`${ESC}\\[[0-9;]*[a-zA-Z]`, "g");
287
+ const osc1 = new RegExp(`${ESC}\\][^\\x07]*\\x07`, "g");
288
+ const osc2 = new RegExp(`${ESC}\\][^${ESC}]*${ESC}\\\\`, "g");
289
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: strip C0 control chars except \n \r
290
+ const ctrl = /[\x00-\x09\x0b\x0c\x0e-\x1f\x7f]/g;
291
+ return str.replace(csi, "").replace(osc1, "").replace(osc2, "").replace(ctrl, "");
292
+ }
293
+ //# sourceMappingURL=claude-code-sprites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code-sprites.js","sourceRoot":"","sources":["../../src/bridge/claude-code-sprites.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Generates CLAUDE.md files for project workspaces.
3
+ *
4
+ * Two variants:
5
+ * - `generateClaudeMd()` — for Claude Code mode (streamlined, no redundant instructions)
6
+ * - `generateElectricAgentClaudeMd()` — for electric-agent mode (full instructions for the SDK agent)
7
+ */
8
+ export interface ClaudeMdOptions {
9
+ /** The user's app description */
10
+ description: string;
11
+ /** Project name (kebab-case) */
12
+ projectName: string;
13
+ /** Absolute path to the project inside the sandbox */
14
+ projectDir: string;
15
+ /** Whether this is an iteration (vs initial generation) */
16
+ isIteration?: boolean;
17
+ /** Iteration request text (if isIteration) */
18
+ iterationRequest?: string;
19
+ /** Sandbox runtime — affects environment-specific instructions */
20
+ runtime?: "docker" | "sprites" | "daytona";
21
+ }
22
+ export declare function generateClaudeMd(opts: ClaudeMdOptions): string;
23
+ export declare function generateElectricAgentClaudeMd(opts: ClaudeMdOptions): string;
24
+ //# sourceMappingURL=claude-md-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-md-generator.d.ts","sourceRoot":"","sources":["../../src/bridge/claude-md-generator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,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,GAAG,SAAS,CAAA;CAC1C;AAMD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CA8B9D;AAMD,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAoC3E"}
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Generates CLAUDE.md files for project workspaces.
3
+ *
4
+ * Two variants:
5
+ * - `generateClaudeMd()` — for Claude Code mode (streamlined, no redundant instructions)
6
+ * - `generateElectricAgentClaudeMd()` — for electric-agent mode (full instructions for the SDK agent)
7
+ */
8
+ // ---------------------------------------------------------------------------
9
+ // Claude Code variant
10
+ // ---------------------------------------------------------------------------
11
+ export function generateClaudeMd(opts) {
12
+ const sections = [];
13
+ sections.push(`# ${opts.projectName}`);
14
+ sections.push("");
15
+ sections.push(PROJECT_CONTEXT);
16
+ sections.push("");
17
+ if (!opts.isIteration) {
18
+ sections.push("## Current Task");
19
+ sections.push(opts.description);
20
+ sections.push("");
21
+ }
22
+ sections.push(SCAFFOLD_STRUCTURE);
23
+ sections.push("");
24
+ sections.push(DRIZZLE_WORKFLOW);
25
+ sections.push("");
26
+ sections.push(GUARDRAILS);
27
+ sections.push("");
28
+ sections.push(PLAYBOOK_INSTRUCTIONS);
29
+ sections.push("");
30
+ sections.push(INFRASTRUCTURE);
31
+ sections.push("");
32
+ sections.push(devServerInstructions(opts.runtime));
33
+ sections.push("");
34
+ sections.push(SSR_RULES);
35
+ sections.push("");
36
+ return sections.join("\n");
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // Electric Agent variant
40
+ // ---------------------------------------------------------------------------
41
+ export function generateElectricAgentClaudeMd(opts) {
42
+ const sections = [];
43
+ sections.push(`# ${opts.projectName}`);
44
+ sections.push("");
45
+ sections.push(PROJECT_CONTEXT);
46
+ sections.push("");
47
+ if (!opts.isIteration) {
48
+ sections.push("## Current Task");
49
+ sections.push(opts.description);
50
+ sections.push("");
51
+ }
52
+ sections.push(SCAFFOLD_STRUCTURE);
53
+ sections.push("");
54
+ sections.push(DRIZZLE_WORKFLOW);
55
+ sections.push("");
56
+ sections.push(GUARDRAILS);
57
+ sections.push("");
58
+ sections.push(PLAYBOOK_INSTRUCTIONS_AGENT);
59
+ sections.push("");
60
+ sections.push(BUILD_INSTRUCTIONS);
61
+ sections.push("");
62
+ sections.push(devServerInstructions(opts.runtime));
63
+ sections.push("");
64
+ sections.push(ARCHITECTURE_REFERENCE);
65
+ sections.push("");
66
+ sections.push(GIT_INSTRUCTIONS);
67
+ sections.push("");
68
+ sections.push(SSR_RULES);
69
+ sections.push("");
70
+ sections.push(ERROR_HANDLING);
71
+ sections.push("");
72
+ return sections.join("\n");
73
+ }
74
+ // ---------------------------------------------------------------------------
75
+ // Shared sections (used by both variants)
76
+ // ---------------------------------------------------------------------------
77
+ const PROJECT_CONTEXT = "## Project Context\nThis is a reactive, real-time application built with Electric SQL + TanStack DB + Drizzle ORM + TanStack Start.";
78
+ const SCAFFOLD_STRUCTURE = `## Scaffold Structure (DO NOT EXPLORE)
79
+ The project is scaffolded from a known template. DO NOT read or explore scaffold files before coding. You already know the structure:
80
+ - src/db/schema.ts — placeholder Drizzle schema (you will overwrite)
81
+ - src/db/zod-schemas.ts — placeholder Zod derivation (you will overwrite)
82
+ - src/db/index.ts — Drizzle client setup (do not modify)
83
+ - src/db/utils.ts — parseDates + generateTxId helpers (do not modify)
84
+ - src/lib/electric-proxy.ts — Electric shape proxy helper (do not modify)
85
+ - src/components/ClientOnly.tsx — SSR wrapper (do not modify, just import when needed)
86
+ - src/routes/__root.tsx — root layout with SSR (do not add ssr:false here)
87
+ - tests/helpers/schema-test-utils.ts — generateValidRow/generateRowWithout (do not modify)
88
+
89
+ DO NOT use Bash/ls/find to explore the project. DO NOT read files you aren't about to modify. Start writing code.`;
90
+ const DRIZZLE_WORKFLOW = `## Drizzle Workflow (CRITICAL)
91
+ Always follow this order:
92
+ 1. Edit src/db/schema.ts (Drizzle pgTable definitions)
93
+ 2. Edit src/db/zod-schemas.ts (derive Zod schemas via createSelectSchema/createInsertSchema from drizzle-zod — NEVER hand-write Zod schemas — ALWAYS import z from "zod/v4" and override ALL timestamp columns with z.union([z.date(), z.string()]).default(() => new Date()) — the .default() is required so collection.insert() works without timestamps)
94
+ 3. Create collection files in src/db/collections/ (import from ../zod-schemas)
95
+ 4. Create API routes (proxy + mutation)
96
+ 5. Create UI components`;
97
+ const GUARDRAILS = `## Guardrails (MUST FOLLOW)
98
+
99
+ ### Protected Files — DO NOT MODIFY
100
+ - docker-compose.yml
101
+ - tsconfig.json
102
+ - biome.json
103
+ - pnpm-lock.yaml
104
+ - postgres.conf
105
+ - vitest.config.ts
106
+ - Caddyfile
107
+
108
+ ### Import Rules
109
+ - Use "zod/v4" (NOT "zod") for all Zod imports
110
+ - Use "lucide-react" for icons (NOT @radix-ui/react-icons)
111
+ - Use "@radix-ui/themes" for Radix components (NOT @radix-ui/react-*)
112
+ - Use "react-router" for routing (NOT react-router-dom)
113
+
114
+ ### Vite Config Rules
115
+ - When modifying vite.config.ts, ALWAYS preserve \`server: { allowedHosts: true }\` — without it, Vite rejects connections from the proxy URL
116
+
117
+ ### Dependency Rules
118
+ - NEVER remove existing dependencies from package.json
119
+ - Only add new dependencies
120
+
121
+ ### Schema Rules
122
+ - ALL timestamp columns MUST use: z.union([z.date(), z.string()]).default(() => new Date())
123
+ - NEVER use z.coerce.date() — it breaks TanStack DB
124
+ - ALL tables MUST have REPLICA IDENTITY FULL (auto-applied by migration hook)
125
+ - UUID primary keys with defaultRandom()
126
+ - timestamp({ withTimezone: true }) for all dates
127
+ - snake_case for SQL table/column names
128
+ - Foreign keys with onDelete: "cascade" where appropriate`;
129
+ function devServerInstructions(runtime) {
130
+ if (runtime === "sprites" || runtime === "daytona") {
131
+ return `## Dev Server & Migrations
132
+ ### Dev Server
133
+ - \`pnpm dev:start\` — start the Vite dev server in the background
134
+ - \`pnpm dev:stop\` — stop the dev server
135
+ - \`pnpm dev:restart\` — stop then start
136
+
137
+ The app is exposed on the VITE_PORT environment variable (default: 5173).
138
+ The database and Electric sync service are remote (cloud-hosted) — there is no local Postgres or Docker.
139
+
140
+ ### Migrations (CRITICAL)
141
+ After modifying src/db/schema.ts, ALWAYS run migrations:
142
+ \`\`\`bash
143
+ pnpm drizzle-kit generate # generate SQL from schema changes
144
+ pnpm drizzle-kit migrate # apply migration to the database
145
+ \`\`\`
146
+
147
+ ### Sprites Environment Gotchas
148
+ - npm global binaries are NOT in PATH by default. If you need to run a globally installed tool, source the profile first: \`source /etc/profile.d/npm-global.sh\`
149
+ - Node.js is managed via nvm at \`/.sprite/languages/node/nvm/\`
150
+ - The sandbox is a cloud micro-VM — there is no Docker, no docker-compose, no local Postgres
151
+ - The database connection string is in DATABASE_URL (remote Neon Postgres)
152
+ - **CRITICAL**: vite.config.ts MUST have \`server: { allowedHosts: true }\` — without it, Vite rejects connections from the proxy URL and the preview will not work
153
+
154
+ ### Workflow
155
+ After finishing ALL code generation: run migrations, then \`pnpm dev:start\` so the user can preview the app.`;
156
+ }
157
+ return `## Dev Server & Migrations
158
+ ### Dev Server
159
+ - \`pnpm dev:start\` — start Vite + Postgres + Electric in the background
160
+ - \`pnpm dev:stop\` — stop all background services
161
+ - \`pnpm dev:restart\` — stop then start
162
+
163
+ The app is exposed on the VITE_PORT environment variable (default: 5173).
164
+
165
+ ### Migrations (CRITICAL)
166
+ After modifying src/db/schema.ts, ALWAYS run migrations:
167
+ \`\`\`bash
168
+ pnpm dev:start # start Postgres (needed for migrate)
169
+ pnpm drizzle-kit generate # generate SQL from schema changes
170
+ pnpm drizzle-kit migrate # apply migration to the database
171
+ \`\`\`
172
+
173
+ ### Workflow
174
+ After finishing ALL code generation: run migrations, then \`pnpm dev:start\` so the user can preview the app.`;
175
+ }
176
+ const SSR_RULES = `## SSR Configuration (CRITICAL)
177
+ NEVER add ssr: false to __root.tsx — it renders the HTML shell and must always SSR.
178
+ Instead, add ssr: false to each LEAF route that uses useLiveQuery or collections.
179
+ This is needed because useLiveQuery uses useSyncExternalStore without getServerSnapshot.`;
180
+ // ---------------------------------------------------------------------------
181
+ // Claude Code–only sections
182
+ // ---------------------------------------------------------------------------
183
+ const PLAYBOOK_INSTRUCTIONS = `## Playbooks (Domain Knowledge — MUST READ)
184
+ Playbook SKILL.md files contain critical API usage patterns. Read them BEFORE writing code for each phase.
185
+
186
+ ### Available Skills
187
+ Read with the Read tool at these exact paths:
188
+
189
+ **Electric SQL** (\`node_modules/@electric-sql/playbook/skills/\`):
190
+ - \`electric/SKILL.md\` — core Electric concepts and shape API
191
+ - \`electric-tanstack-integration/SKILL.md\` — how Electric + TanStack DB work together (READ FIRST)
192
+ - \`electric-quickstart/SKILL.md\` — quickstart patterns
193
+ - \`electric-security-check/SKILL.md\` — security best practices
194
+ - \`tanstack-start-quickstart/SKILL.md\` — TanStack Start framework patterns
195
+ - \`deploying-electric/SKILL.md\` — deployment configuration
196
+ - \`electric-go-live/SKILL.md\` — production checklist
197
+
198
+ **TanStack DB** (\`node_modules/@tanstack/db-playbook/skills/\`):
199
+ - \`tanstack-db/SKILL.md\` — collections, useLiveQuery, mutations (CRITICAL — read before writing any UI)
200
+
201
+ **Durable Streams** (\`node_modules/@durable-streams/playbook/skills/\`):
202
+ - \`durable-streams/SKILL.md\` — event streaming patterns
203
+ - \`durable-state/SKILL.md\` — state management
204
+ - \`durable-streams-dev-setup/SKILL.md\` — development setup
205
+
206
+ ### Reading Order
207
+ 1. \`electric-tanstack-integration/SKILL.md\` — integration rules and guardrails
208
+ 2. \`tanstack-db/SKILL.md\` — collections, queries, mutations API
209
+ 3. \`electric/SKILL.md\` — shape API for proxy routes
210
+ 4. Other skills as needed for your current phase
211
+
212
+ ### Important
213
+ - ONLY read playbooks relevant to your current phase
214
+ - Do NOT use include_references — the SKILL.md content is sufficient`;
215
+ const INFRASTRUCTURE = `## Infrastructure (Pre-configured — DO NOT MODIFY)
216
+ The database (Postgres) and Electric sync service are already provisioned and configured via environment variables:
217
+ - \`DATABASE_URL\` — Postgres connection string
218
+ - \`ELECTRIC_URL\` — Electric sync service URL
219
+ - \`ELECTRIC_SOURCE_ID\` / \`ELECTRIC_SECRET\` — Electric Cloud auth (if using cloud mode)
220
+
221
+ These are read by:
222
+ - \`src/db/index.ts\` — Drizzle client (DO NOT MODIFY)
223
+ - \`drizzle.config.ts\` — Drizzle Kit migrations (DO NOT MODIFY)
224
+ - \`src/lib/electric-proxy.ts\` — Electric shape proxy for API routes (DO NOT MODIFY)
225
+
226
+ You do NOT need to set up database connections or configure Electric. Just define your schema, run migrations, and write your app.`;
227
+ // ---------------------------------------------------------------------------
228
+ // Electric Agent–only sections
229
+ // ---------------------------------------------------------------------------
230
+ const PLAYBOOK_INSTRUCTIONS_AGENT = `## Playbooks (Domain Knowledge)
231
+ Playbook skill files are available in node_modules. Read them before implementing each phase:
232
+
233
+ ### How to Read Playbooks
234
+ Use the Read tool to read playbook SKILL.md files:
235
+ - \`node_modules/@electric-sql/playbook/skills/<name>/SKILL.md\`
236
+ - \`node_modules/@tanstack/db-playbook/skills/<name>/SKILL.md\`
237
+ - \`node_modules/@durable-streams/playbook/skills/<name>/SKILL.md\`
238
+
239
+ ### Required Reading Order
240
+ 1. Read the electric-app-guardrails playbook FIRST (critical integration rules)
241
+ 2. Read "schemas" before writing Drizzle schemas
242
+ 3. Read "collections" before creating collection files
243
+ 4. Read "mutations" before creating mutation routes
244
+ 5. Read "live-queries" before creating UI with useLiveQuery
245
+
246
+ ### Important
247
+ - ONLY read playbooks relevant to your current phase
248
+ - Do NOT use include_references — the SKILL.md content is sufficient`;
249
+ const BUILD_INSTRUCTIONS = `## Build & Test
250
+ Run these commands to verify your work:
251
+ - \`pnpm run build\` — TypeScript compilation
252
+ - \`pnpm run check\` — Biome lint + format check
253
+ - \`pnpm test\` — Run tests (if tests/ directory exists)
254
+
255
+ Build only twice during initial generation: once after finishing all code, once after tests.
256
+ During iterations, build after completing changes.`;
257
+ const ARCHITECTURE_REFERENCE = `## Architecture Reference
258
+
259
+ ### Writing ARCHITECTURE.md (Initial Generation)
260
+ After ALL tasks are complete and the build passes, write ARCHITECTURE.md in the project root as your FINAL action. This is a concise navigation index — not documentation. Keep it under 1500 tokens.
261
+
262
+ Format:
263
+ \`\`\`
264
+ # [App Name] — Architecture Reference
265
+ _Last updated: [ISO date]_
266
+
267
+ ## App Description
268
+ [1-2 sentences]
269
+
270
+ ## Data Model
271
+ ### [EntityName] (\`table_name\`)
272
+ - **Columns**: id (uuid PK), title (text), created_at (timestamptz)
273
+ - **Relations**: [none | field → table.id cascade]
274
+ - **Collection**: src/db/collections/[entity].ts
275
+
276
+ ## API Routes
277
+ | Method | Path | File | Purpose |
278
+
279
+ ## UI Routes & Components
280
+ | Route | File | Description |
281
+
282
+ ### Key Components
283
+ - src/components/X.tsx — [one line: what it renders]
284
+
285
+ ## Styling
286
+ - CSS files: [file: purpose]
287
+ \`\`\`
288
+
289
+ ### Using ARCHITECTURE.md (Iteration Mode)
290
+ On iterations, read ARCHITECTURE.md to understand the app structure. Use it to locate files — do NOT scan the filesystem.`;
291
+ const GIT_INSTRUCTIONS = `## Git & GitHub CLI
292
+ You have git and gh CLI available via Bash. Use them when needed:
293
+ - \`git status\` / \`git diff --stat\` — check current state
294
+ - \`git add -A && git commit -m "type(scope): description"\` — commit changes
295
+ - \`git push -u origin main\` — push to remote
296
+ - \`gh repo create "org/name" --private --source . --remote origin --push\` — create repo
297
+ - \`gh pr create --title "..." --body "..."\` — create PR
298
+ Commit types: feat, fix, refactor, style, chore, docs, test`;
299
+ const ERROR_HANDLING = `## Error Handling
300
+ Before fixing any error, check _agent/errors.md for previous attempts at the same fix.
301
+ If you see the same error has failed before, try a different approach.
302
+ After fixing an error, log the outcome.`;
303
+ //# sourceMappingURL=claude-md-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-md-generator.js","sourceRoot":"","sources":["../../src/bridge/claude-md-generator.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,9 @@
1
+ export { ClaudeCodeDockerBridge, type ClaudeCodeDockerConfig } from "./claude-code-docker.js";
2
+ export { ClaudeCodeSpritesBridge, type ClaudeCodeSpritesConfig } from "./claude-code-sprites.js";
1
3
  export { DaytonaSessionBridge } from "./daytona.js";
2
4
  export { DockerStdioBridge } from "./docker-stdio.js";
3
5
  export { HostedStreamBridge } from "./hosted.js";
4
6
  export { SpritesStdioBridge } from "./sprites.js";
7
+ export { createStreamJsonParser } from "./stream-json-parser.js";
5
8
  export type { AgentEvent, ServerCommand, ServerGateResponse, SessionBridge, StreamMessage, } from "./types.js";
6
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACjD,YAAY,EACX,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,aAAa,GACb,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,KAAK,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAC7F,OAAO,EAAE,uBAAuB,EAAE,KAAK,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAChG,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAChE,YAAY,EACX,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,aAAa,GACb,MAAM,YAAY,CAAA"}