@fronx/use-claude-code 0.1.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/README.md +273 -0
- package/dist/client/connection.d.ts +101 -0
- package/dist/client/connection.d.ts.map +1 -0
- package/dist/client/connection.js +379 -0
- package/dist/client/connection.js.map +1 -0
- package/dist/client/event-emitter.d.ts +32 -0
- package/dist/client/event-emitter.d.ts.map +1 -0
- package/dist/client/event-emitter.js +72 -0
- package/dist/client/event-emitter.js.map +1 -0
- package/dist/client/index.d.ts +30 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +29 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/state-machine.d.ts +61 -0
- package/dist/client/state-machine.d.ts.map +1 -0
- package/dist/client/state-machine.js +292 -0
- package/dist/client/state-machine.js.map +1 -0
- package/dist/client/stream-processor.d.ts +46 -0
- package/dist/client/stream-processor.d.ts.map +1 -0
- package/dist/client/stream-processor.js +173 -0
- package/dist/client/stream-processor.js.map +1 -0
- package/dist/react/hook.d.ts +55 -0
- package/dist/react/hook.d.ts.map +1 -0
- package/dist/react/hook.js +132 -0
- package/dist/react/hook.js.map +1 -0
- package/dist/react/index.d.ts +49 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +48 -0
- package/dist/react/index.js.map +1 -0
- package/dist/server/claude-spawn.d.ts +52 -0
- package/dist/server/claude-spawn.d.ts.map +1 -0
- package/dist/server/claude-spawn.js +147 -0
- package/dist/server/claude-spawn.js.map +1 -0
- package/dist/server/conversation.d.ts +113 -0
- package/dist/server/conversation.d.ts.map +1 -0
- package/dist/server/conversation.js +520 -0
- package/dist/server/conversation.js.map +1 -0
- package/dist/server/index.d.ts +35 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +39 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/sse-emitter.d.ts +42 -0
- package/dist/server/sse-emitter.d.ts.map +1 -0
- package/dist/server/sse-emitter.js +56 -0
- package/dist/server/sse-emitter.js.map +1 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +3 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/tool-utils.d.ts +25 -0
- package/dist/shared/tool-utils.d.ts.map +1 -0
- package/dist/shared/tool-utils.js +49 -0
- package/dist/shared/tool-utils.js.map +1 -0
- package/dist/shared/types.d.ts +82 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +5 -0
- package/dist/shared/types.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude conversation lifecycle management.
|
|
3
|
+
*
|
|
4
|
+
* The ClaudeManager class handles:
|
|
5
|
+
* - Spawning and tracking Claude CLI conversations
|
|
6
|
+
* - Session persistence to the filesystem
|
|
7
|
+
* - Resuming conversations with --resume flag
|
|
8
|
+
* - Prewarming (spawning without an initial message)
|
|
9
|
+
* - SSE client subscription management
|
|
10
|
+
*/
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import { spawnClaudeConversation, } from './claude-spawn.js';
|
|
14
|
+
import { sendSSE, broadcastSSEWithSession } from './sse-emitter.js';
|
|
15
|
+
import { getRelevantToolParam } from '../shared/tool-utils.js';
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Helper functions
|
|
18
|
+
// ============================================================================
|
|
19
|
+
function generateSessionId() {
|
|
20
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
21
|
+
}
|
|
22
|
+
function generateMessageId() {
|
|
23
|
+
return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
24
|
+
}
|
|
25
|
+
function resolveSystemPrompt(prompt) {
|
|
26
|
+
if (typeof prompt === 'string') {
|
|
27
|
+
return prompt;
|
|
28
|
+
}
|
|
29
|
+
return fs.readFileSync(prompt.file, 'utf-8');
|
|
30
|
+
}
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// ClaudeManager class
|
|
33
|
+
// ============================================================================
|
|
34
|
+
export class ClaudeManager {
|
|
35
|
+
config;
|
|
36
|
+
conversations = new Map();
|
|
37
|
+
constructor(config) {
|
|
38
|
+
this.config = {
|
|
39
|
+
sessionDir: config.sessionDir,
|
|
40
|
+
claudePath: config.claudePath ?? 'claude',
|
|
41
|
+
defaultAllowedTools: config.defaultAllowedTools ?? [
|
|
42
|
+
'Read',
|
|
43
|
+
'Write',
|
|
44
|
+
'Edit',
|
|
45
|
+
'Bash',
|
|
46
|
+
'Glob',
|
|
47
|
+
'Grep',
|
|
48
|
+
],
|
|
49
|
+
autoPrewarm: config.autoPrewarm ?? false,
|
|
50
|
+
};
|
|
51
|
+
// Ensure session directory exists
|
|
52
|
+
if (!fs.existsSync(this.config.sessionDir)) {
|
|
53
|
+
fs.mkdirSync(this.config.sessionDir, { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Start a new conversation.
|
|
58
|
+
*
|
|
59
|
+
* If a prewarmed conversation exists for this ID, it will be reused.
|
|
60
|
+
* Otherwise, a new Claude process is spawned.
|
|
61
|
+
*/
|
|
62
|
+
start(id, options) {
|
|
63
|
+
const systemPrompt = resolveSystemPrompt(options.systemPrompt);
|
|
64
|
+
const allowedTools = options.allowedTools ?? this.config.defaultAllowedTools;
|
|
65
|
+
// Check for prewarmed conversation
|
|
66
|
+
const existing = this.conversations.get(id);
|
|
67
|
+
if (existing && existing.isPrewarmed) {
|
|
68
|
+
return this.activatePrewarmed(existing, options.initialMessage);
|
|
69
|
+
}
|
|
70
|
+
// Kill existing non-prewarmed conversation if any
|
|
71
|
+
if (existing) {
|
|
72
|
+
existing.claude.kill();
|
|
73
|
+
this.conversations.delete(id);
|
|
74
|
+
}
|
|
75
|
+
// Generate session ID
|
|
76
|
+
const sessionId = generateSessionId();
|
|
77
|
+
// Create conversation state
|
|
78
|
+
const state = {
|
|
79
|
+
id,
|
|
80
|
+
sessionId,
|
|
81
|
+
claudeSessionId: null,
|
|
82
|
+
claude: null,
|
|
83
|
+
messages: [],
|
|
84
|
+
activeStreams: new Set(),
|
|
85
|
+
createdAt: new Date(),
|
|
86
|
+
isStreaming: false,
|
|
87
|
+
isPrewarmed: false,
|
|
88
|
+
expectingClose: false,
|
|
89
|
+
cwd: options.cwd,
|
|
90
|
+
systemPrompt,
|
|
91
|
+
allowedTools,
|
|
92
|
+
};
|
|
93
|
+
// Spawn Claude
|
|
94
|
+
state.claude = this.spawnClaude(state, { systemPrompt, allowedTools });
|
|
95
|
+
this.conversations.set(id, state);
|
|
96
|
+
// Send initial message if provided
|
|
97
|
+
if (options.initialMessage) {
|
|
98
|
+
console.log(`[ClaudeManager] Sending initial message to ${id}: "${options.initialMessage.slice(0, 80)}..."`);
|
|
99
|
+
const userMsg = this.createUserMessage(options.initialMessage);
|
|
100
|
+
state.messages.push(userMsg);
|
|
101
|
+
this.saveSession(state);
|
|
102
|
+
state.claude.sendMessage(options.initialMessage);
|
|
103
|
+
}
|
|
104
|
+
return this.createConversationHandle(state);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get an active conversation by ID.
|
|
108
|
+
*/
|
|
109
|
+
get(id) {
|
|
110
|
+
const state = this.conversations.get(id);
|
|
111
|
+
if (!state)
|
|
112
|
+
return undefined;
|
|
113
|
+
return this.createConversationHandle(state);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Resume a conversation from a persisted session.
|
|
117
|
+
*
|
|
118
|
+
* Loads the session from disk and spawns Claude with --resume flag.
|
|
119
|
+
*/
|
|
120
|
+
resume(id, options) {
|
|
121
|
+
// Check for existing active conversation
|
|
122
|
+
const existing = this.conversations.get(id);
|
|
123
|
+
if (existing) {
|
|
124
|
+
return this.createConversationHandle(existing);
|
|
125
|
+
}
|
|
126
|
+
// Load persisted session
|
|
127
|
+
const session = this.loadSession(id);
|
|
128
|
+
if (!session || !session.claudeSessionId) {
|
|
129
|
+
throw new Error(`No persisted session found for conversation ${id}`);
|
|
130
|
+
}
|
|
131
|
+
const systemPrompt = resolveSystemPrompt(options.systemPrompt);
|
|
132
|
+
const allowedTools = options.allowedTools ?? this.config.defaultAllowedTools;
|
|
133
|
+
// Create conversation state with persisted messages
|
|
134
|
+
const state = {
|
|
135
|
+
id,
|
|
136
|
+
sessionId: session.sessionId,
|
|
137
|
+
claudeSessionId: session.claudeSessionId,
|
|
138
|
+
claude: null,
|
|
139
|
+
messages: session.messages.map((m) => ({
|
|
140
|
+
...m,
|
|
141
|
+
timestamp: m.timestamp ? new Date(m.timestamp) : undefined,
|
|
142
|
+
})),
|
|
143
|
+
activeStreams: new Set(),
|
|
144
|
+
createdAt: new Date(session.createdAt),
|
|
145
|
+
isStreaming: false,
|
|
146
|
+
isPrewarmed: false,
|
|
147
|
+
expectingClose: false,
|
|
148
|
+
cwd: options.cwd,
|
|
149
|
+
systemPrompt,
|
|
150
|
+
allowedTools,
|
|
151
|
+
};
|
|
152
|
+
// Spawn Claude with --resume flag
|
|
153
|
+
state.claude = this.spawnClaude(state, {
|
|
154
|
+
systemPrompt,
|
|
155
|
+
allowedTools,
|
|
156
|
+
resumeSessionId: session.claudeSessionId,
|
|
157
|
+
});
|
|
158
|
+
this.conversations.set(id, state);
|
|
159
|
+
return this.createConversationHandle(state);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Stop a conversation's current response.
|
|
163
|
+
*
|
|
164
|
+
* Sends SIGINT to pause generation without killing the process.
|
|
165
|
+
*/
|
|
166
|
+
stop(id) {
|
|
167
|
+
const state = this.conversations.get(id);
|
|
168
|
+
if (!state)
|
|
169
|
+
return;
|
|
170
|
+
if (state.isStreaming) {
|
|
171
|
+
state.claude.interrupt();
|
|
172
|
+
state.isStreaming = false;
|
|
173
|
+
this.broadcastToConversation(state, 'stopped', { reason: 'User requested stop' });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Clear a conversation completely.
|
|
178
|
+
*
|
|
179
|
+
* Kills the process, deletes the persisted session, and optionally
|
|
180
|
+
* prewarms a new conversation.
|
|
181
|
+
*/
|
|
182
|
+
clear(id) {
|
|
183
|
+
const state = this.conversations.get(id);
|
|
184
|
+
if (state) {
|
|
185
|
+
// Notify connected clients
|
|
186
|
+
this.broadcastToConversation(state, 'cleared', { reason: 'User requested clear' });
|
|
187
|
+
// Kill Claude process
|
|
188
|
+
state.claude.kill();
|
|
189
|
+
}
|
|
190
|
+
// Delete from memory
|
|
191
|
+
this.conversations.delete(id);
|
|
192
|
+
// Delete persisted session
|
|
193
|
+
this.deleteSession(id);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Prewarm a conversation by spawning Claude without sending a message.
|
|
197
|
+
*
|
|
198
|
+
* This makes the first response faster since Claude is already running.
|
|
199
|
+
*/
|
|
200
|
+
prewarm(id, options) {
|
|
201
|
+
// Check if conversation already exists
|
|
202
|
+
if (this.conversations.has(id)) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
// Check if there's a persisted session - don't prewarm if user should resume
|
|
206
|
+
const session = this.loadSession(id);
|
|
207
|
+
if (session) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const systemPrompt = resolveSystemPrompt(options.systemPrompt);
|
|
211
|
+
const allowedTools = options.allowedTools ?? this.config.defaultAllowedTools;
|
|
212
|
+
const sessionId = generateSessionId();
|
|
213
|
+
// Create prewarmed conversation state
|
|
214
|
+
const state = {
|
|
215
|
+
id,
|
|
216
|
+
sessionId,
|
|
217
|
+
claudeSessionId: null,
|
|
218
|
+
claude: null,
|
|
219
|
+
messages: [],
|
|
220
|
+
activeStreams: new Set(),
|
|
221
|
+
createdAt: new Date(),
|
|
222
|
+
isStreaming: false,
|
|
223
|
+
isPrewarmed: true,
|
|
224
|
+
expectingClose: false,
|
|
225
|
+
cwd: options.cwd,
|
|
226
|
+
systemPrompt,
|
|
227
|
+
allowedTools,
|
|
228
|
+
};
|
|
229
|
+
// Spawn Claude (prewarmed agents only need to capture init message)
|
|
230
|
+
state.claude = this.spawnClaudePrewarmed(state, { systemPrompt, allowedTools });
|
|
231
|
+
this.conversations.set(id, state);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Check if a persisted session exists for an ID.
|
|
235
|
+
*/
|
|
236
|
+
hasPersistedSession(id) {
|
|
237
|
+
return this.loadSession(id) !== null;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Get status information for a conversation.
|
|
241
|
+
*/
|
|
242
|
+
getStatus(id) {
|
|
243
|
+
const state = this.conversations.get(id);
|
|
244
|
+
const session = this.loadSession(id);
|
|
245
|
+
if (state) {
|
|
246
|
+
return {
|
|
247
|
+
active: true,
|
|
248
|
+
messageCount: state.messages.length,
|
|
249
|
+
isStreaming: state.isStreaming,
|
|
250
|
+
sessionId: state.sessionId,
|
|
251
|
+
claudeSessionId: state.claudeSessionId,
|
|
252
|
+
hasPersistedSession: session !== null,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
active: false,
|
|
257
|
+
messageCount: 0,
|
|
258
|
+
isStreaming: false,
|
|
259
|
+
sessionId: session?.sessionId ?? null,
|
|
260
|
+
claudeSessionId: session?.claudeSessionId ?? null,
|
|
261
|
+
hasPersistedSession: session !== null,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Clear all conversations (for testing or shutdown).
|
|
266
|
+
*/
|
|
267
|
+
clearAll() {
|
|
268
|
+
Array.from(this.conversations.values()).forEach((state) => {
|
|
269
|
+
state.claude.kill();
|
|
270
|
+
});
|
|
271
|
+
this.conversations.clear();
|
|
272
|
+
}
|
|
273
|
+
// ============================================================================
|
|
274
|
+
// Private methods
|
|
275
|
+
// ============================================================================
|
|
276
|
+
spawnClaude(state, options) {
|
|
277
|
+
const spawnOptions = {
|
|
278
|
+
cwd: state.cwd,
|
|
279
|
+
systemPrompt: options.systemPrompt,
|
|
280
|
+
claudePath: this.config.claudePath,
|
|
281
|
+
allowedTools: options.allowedTools,
|
|
282
|
+
resumeSessionId: options.resumeSessionId,
|
|
283
|
+
onMessage: (data) => this.handleClaudeMessage(state, data),
|
|
284
|
+
onError: (err) => this.handleClaudeError(state, err),
|
|
285
|
+
onClose: (code) => this.handleClaudeClose(state, code),
|
|
286
|
+
};
|
|
287
|
+
return spawnClaudeConversation(spawnOptions);
|
|
288
|
+
}
|
|
289
|
+
spawnClaudePrewarmed(state, options) {
|
|
290
|
+
// Prewarmed agents only capture the init message
|
|
291
|
+
const spawnOptions = {
|
|
292
|
+
cwd: state.cwd,
|
|
293
|
+
systemPrompt: options.systemPrompt,
|
|
294
|
+
claudePath: this.config.claudePath,
|
|
295
|
+
allowedTools: options.allowedTools,
|
|
296
|
+
onMessage: (data) => {
|
|
297
|
+
const msg = data;
|
|
298
|
+
if (msg.type === 'system' && msg.subtype === 'init') {
|
|
299
|
+
if (typeof msg.session_id === 'string') {
|
|
300
|
+
state.claudeSessionId = msg.session_id;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
// Other messages handled when user sends first message
|
|
304
|
+
},
|
|
305
|
+
onError: (err) => {
|
|
306
|
+
console.error(`[ClaudeManager] Prewarmed agent error for ${state.id}:`, err);
|
|
307
|
+
this.broadcastToConversation(state, 'error', { message: err.message });
|
|
308
|
+
},
|
|
309
|
+
onClose: (code) => {
|
|
310
|
+
console.log(`[ClaudeManager] Prewarmed agent closed for ${state.id}: code=${code}`);
|
|
311
|
+
if (state.expectingClose) {
|
|
312
|
+
state.expectingClose = false;
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
this.broadcastToConversation(state, 'closed', { code });
|
|
316
|
+
this.conversations.delete(state.id);
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
return spawnClaudeConversation(spawnOptions);
|
|
320
|
+
}
|
|
321
|
+
activatePrewarmed(state, initialMessage) {
|
|
322
|
+
// Upgrade from prewarmed to active
|
|
323
|
+
state.isPrewarmed = false;
|
|
324
|
+
// Replace the minimal onMessage handler with the full one
|
|
325
|
+
// Note: We can't replace handlers on existing process, so we
|
|
326
|
+
// need to rely on the message handler being flexible enough
|
|
327
|
+
// to handle both prewarmed and active states.
|
|
328
|
+
// The message handler checks state.isPrewarmed.
|
|
329
|
+
// Actually, we need to respawn with full handlers
|
|
330
|
+
const oldClaude = state.claude;
|
|
331
|
+
state.claude = this.spawnClaude(state, {
|
|
332
|
+
systemPrompt: state.systemPrompt,
|
|
333
|
+
allowedTools: state.allowedTools,
|
|
334
|
+
resumeSessionId: state.claudeSessionId ?? undefined,
|
|
335
|
+
});
|
|
336
|
+
state.expectingClose = true;
|
|
337
|
+
oldClaude.kill();
|
|
338
|
+
// Send initial message if provided
|
|
339
|
+
if (initialMessage) {
|
|
340
|
+
const userMsg = this.createUserMessage(initialMessage);
|
|
341
|
+
state.messages.push(userMsg);
|
|
342
|
+
this.saveSession(state);
|
|
343
|
+
state.claude.sendMessage(initialMessage);
|
|
344
|
+
}
|
|
345
|
+
return this.createConversationHandle(state);
|
|
346
|
+
}
|
|
347
|
+
handleClaudeMessage(state, data) {
|
|
348
|
+
const msg = data;
|
|
349
|
+
console.log(`[ClaudeManager] Message from Claude for ${state.id}: type=${msg.type}, subtype=${msg.subtype || '-'}`);
|
|
350
|
+
if (msg.type === 'system' && msg.subtype === 'init') {
|
|
351
|
+
// Capture Claude's session ID for resume functionality
|
|
352
|
+
if (typeof msg.session_id === 'string') {
|
|
353
|
+
state.claudeSessionId = msg.session_id;
|
|
354
|
+
}
|
|
355
|
+
this.broadcastToConversation(state, 'init', {
|
|
356
|
+
sessionId: msg.session_id,
|
|
357
|
+
resumed: !!msg.resumed,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
else if (msg.type === 'assistant' && msg.message) {
|
|
361
|
+
state.isStreaming = true;
|
|
362
|
+
const content = msg.message;
|
|
363
|
+
if (Array.isArray(content.content)) {
|
|
364
|
+
for (const part of content.content) {
|
|
365
|
+
if (typeof part === 'object' && part) {
|
|
366
|
+
const partType = part.type;
|
|
367
|
+
if (partType === 'tool_use') {
|
|
368
|
+
// Emit tool event for separate visual rendering
|
|
369
|
+
const toolPart = part;
|
|
370
|
+
const toolName = toolPart.name || 'tool';
|
|
371
|
+
const param = getRelevantToolParam(toolName, toolPart.input);
|
|
372
|
+
this.broadcastToConversation(state, 'tool', {
|
|
373
|
+
name: toolName,
|
|
374
|
+
param,
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
else if (partType === 'tool_result') {
|
|
378
|
+
// Tool result - no need to emit anything, UI handles it
|
|
379
|
+
}
|
|
380
|
+
else if ('text' in part) {
|
|
381
|
+
this.broadcastToConversation(state, 'assistant', {
|
|
382
|
+
text: part.text,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
else if (msg.type === 'result') {
|
|
390
|
+
state.isStreaming = false;
|
|
391
|
+
const resultText = typeof msg.result === 'string' ? msg.result : '';
|
|
392
|
+
// Save assistant message to history
|
|
393
|
+
const assistantMsg = {
|
|
394
|
+
id: generateMessageId(),
|
|
395
|
+
role: 'assistant',
|
|
396
|
+
content: resultText,
|
|
397
|
+
timestamp: new Date(),
|
|
398
|
+
};
|
|
399
|
+
state.messages.push(assistantMsg);
|
|
400
|
+
this.broadcastToConversation(state, 'result', { result: msg.result });
|
|
401
|
+
this.saveSession(state);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
handleClaudeError(state, err) {
|
|
405
|
+
console.error(`[ClaudeManager] Agent error for ${state.id}:`, err);
|
|
406
|
+
this.broadcastToConversation(state, 'error', { message: err.message });
|
|
407
|
+
}
|
|
408
|
+
handleClaudeClose(state, code) {
|
|
409
|
+
console.log(`[ClaudeManager] Agent closed for ${state.id}: code=${code}`);
|
|
410
|
+
if (state.expectingClose) {
|
|
411
|
+
state.expectingClose = false;
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
this.broadcastToConversation(state, 'closed', { code });
|
|
415
|
+
this.conversations.delete(state.id);
|
|
416
|
+
}
|
|
417
|
+
createUserMessage(content, hidden = false) {
|
|
418
|
+
return {
|
|
419
|
+
id: generateMessageId(),
|
|
420
|
+
role: 'user',
|
|
421
|
+
content,
|
|
422
|
+
timestamp: new Date(),
|
|
423
|
+
hidden,
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
broadcastToConversation(state, event, data) {
|
|
427
|
+
broadcastSSEWithSession(state.activeStreams, event, data, state.sessionId);
|
|
428
|
+
}
|
|
429
|
+
createConversationHandle(state) {
|
|
430
|
+
const manager = this;
|
|
431
|
+
return {
|
|
432
|
+
get id() {
|
|
433
|
+
return state.id;
|
|
434
|
+
},
|
|
435
|
+
get sessionId() {
|
|
436
|
+
return state.sessionId;
|
|
437
|
+
},
|
|
438
|
+
get claudeSessionId() {
|
|
439
|
+
return state.claudeSessionId;
|
|
440
|
+
},
|
|
441
|
+
get status() {
|
|
442
|
+
if (state.isPrewarmed)
|
|
443
|
+
return 'ready';
|
|
444
|
+
if (state.isStreaming)
|
|
445
|
+
return 'streaming';
|
|
446
|
+
if (!state.claude)
|
|
447
|
+
return 'stopped';
|
|
448
|
+
return 'ready';
|
|
449
|
+
},
|
|
450
|
+
get messages() {
|
|
451
|
+
return state.messages;
|
|
452
|
+
},
|
|
453
|
+
get isPrewarmed() {
|
|
454
|
+
return state.isPrewarmed;
|
|
455
|
+
},
|
|
456
|
+
send(message) {
|
|
457
|
+
const userMsg = manager.createUserMessage(message);
|
|
458
|
+
state.messages.push(userMsg);
|
|
459
|
+
manager.broadcastToConversation(state, 'user', { content: message });
|
|
460
|
+
manager.saveSession(state);
|
|
461
|
+
state.claude.sendMessage(message);
|
|
462
|
+
},
|
|
463
|
+
stop() {
|
|
464
|
+
manager.stop(state.id);
|
|
465
|
+
},
|
|
466
|
+
subscribe(res) {
|
|
467
|
+
state.activeStreams.add(res);
|
|
468
|
+
// Send history replay (filter hidden messages)
|
|
469
|
+
sendSSE(res, 'history', {
|
|
470
|
+
messages: state.messages.filter((m) => !m.hidden),
|
|
471
|
+
sessionId: state.sessionId,
|
|
472
|
+
});
|
|
473
|
+
// Handle disconnect
|
|
474
|
+
res.on('close', () => {
|
|
475
|
+
state.activeStreams.delete(res);
|
|
476
|
+
});
|
|
477
|
+
},
|
|
478
|
+
unsubscribe(res) {
|
|
479
|
+
state.activeStreams.delete(res);
|
|
480
|
+
},
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
// ============================================================================
|
|
484
|
+
// Session persistence
|
|
485
|
+
// ============================================================================
|
|
486
|
+
getSessionPath(id) {
|
|
487
|
+
return path.join(this.config.sessionDir, `${id}.json`);
|
|
488
|
+
}
|
|
489
|
+
saveSession(state) {
|
|
490
|
+
const sessionPath = this.getSessionPath(state.id);
|
|
491
|
+
const sessionData = {
|
|
492
|
+
claudeSessionId: state.claudeSessionId,
|
|
493
|
+
sessionId: state.sessionId,
|
|
494
|
+
messages: state.messages,
|
|
495
|
+
createdAt: state.createdAt.toISOString(),
|
|
496
|
+
lastMessageAt: new Date().toISOString(),
|
|
497
|
+
};
|
|
498
|
+
fs.writeFileSync(sessionPath, JSON.stringify(sessionData, null, 2));
|
|
499
|
+
}
|
|
500
|
+
loadSession(id) {
|
|
501
|
+
const sessionPath = this.getSessionPath(id);
|
|
502
|
+
if (!fs.existsSync(sessionPath)) {
|
|
503
|
+
return null;
|
|
504
|
+
}
|
|
505
|
+
try {
|
|
506
|
+
const data = fs.readFileSync(sessionPath, 'utf-8');
|
|
507
|
+
return JSON.parse(data);
|
|
508
|
+
}
|
|
509
|
+
catch {
|
|
510
|
+
return null;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
deleteSession(id) {
|
|
514
|
+
const sessionPath = this.getSessionPath(id);
|
|
515
|
+
if (fs.existsSync(sessionPath)) {
|
|
516
|
+
fs.unlinkSync(sessionPath);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
//# sourceMappingURL=conversation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation.js","sourceRoot":"","sources":["../../src/server/conversation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side Claude Code integration
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { ClaudeManager } from '@anthropic/claude-code-lib/server';
|
|
7
|
+
*
|
|
8
|
+
* const manager = new ClaudeManager({
|
|
9
|
+
* sessionDir: './data/sessions',
|
|
10
|
+
* });
|
|
11
|
+
*
|
|
12
|
+
* // In your route handler:
|
|
13
|
+
* const conversation = manager.start('user-123', {
|
|
14
|
+
* systemPrompt: 'You are a helpful assistant.',
|
|
15
|
+
* cwd: process.cwd(),
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // Subscribe to SSE events
|
|
19
|
+
* conversation.subscribe(res);
|
|
20
|
+
*
|
|
21
|
+
* // Send a message
|
|
22
|
+
* conversation.send('Hello!');
|
|
23
|
+
*
|
|
24
|
+
* // Stop streaming
|
|
25
|
+
* conversation.stop();
|
|
26
|
+
*
|
|
27
|
+
* // Clear conversation
|
|
28
|
+
* manager.clear('user-123');
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export * from '../shared/index.js';
|
|
32
|
+
export { spawnClaude, spawnClaudeConversation, type ClaudeSpawnOptions, type ClaudeProcess, type ClaudeConversationOptions, type ClaudeConversation as ClaudeConversationProcess, } from './claude-spawn.js';
|
|
33
|
+
export { setupSSEResponse, sendSSE, broadcastSSE, broadcastSSEWithSession, } from './sse-emitter.js';
|
|
34
|
+
export { ClaudeManager, type ClaudeManagerConfig, type StartOptions, type Conversation, type ConversationStatus, } from './conversation.js';
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,cAAc,oBAAoB,CAAC;AAGnC,OAAO,EACL,WAAW,EACX,uBAAuB,EACvB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,IAAI,yBAAyB,GACrD,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,gBAAgB,EAChB,OAAO,EACP,YAAY,EACZ,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side Claude Code integration
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { ClaudeManager } from '@anthropic/claude-code-lib/server';
|
|
7
|
+
*
|
|
8
|
+
* const manager = new ClaudeManager({
|
|
9
|
+
* sessionDir: './data/sessions',
|
|
10
|
+
* });
|
|
11
|
+
*
|
|
12
|
+
* // In your route handler:
|
|
13
|
+
* const conversation = manager.start('user-123', {
|
|
14
|
+
* systemPrompt: 'You are a helpful assistant.',
|
|
15
|
+
* cwd: process.cwd(),
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // Subscribe to SSE events
|
|
19
|
+
* conversation.subscribe(res);
|
|
20
|
+
*
|
|
21
|
+
* // Send a message
|
|
22
|
+
* conversation.send('Hello!');
|
|
23
|
+
*
|
|
24
|
+
* // Stop streaming
|
|
25
|
+
* conversation.stop();
|
|
26
|
+
*
|
|
27
|
+
* // Clear conversation
|
|
28
|
+
* manager.clear('user-123');
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
// Re-export shared types and utilities
|
|
32
|
+
export * from '../shared/index.js';
|
|
33
|
+
// Export Claude spawn utilities
|
|
34
|
+
export { spawnClaude, spawnClaudeConversation, } from './claude-spawn.js';
|
|
35
|
+
// Export SSE utilities
|
|
36
|
+
export { setupSSEResponse, sendSSE, broadcastSSE, broadcastSSEWithSession, } from './sse-emitter.js';
|
|
37
|
+
// Export conversation management
|
|
38
|
+
export { ClaudeManager, } from './conversation.js';
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,uCAAuC;AACvC,cAAc,oBAAoB,CAAC;AAEnC,gCAAgC;AAChC,OAAO,EACL,WAAW,EACX,uBAAuB,GAKxB,MAAM,mBAAmB,CAAC;AAE3B,uBAAuB;AACvB,OAAO,EACL,gBAAgB,EAChB,OAAO,EACP,YAAY,EACZ,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAE1B,iCAAiC;AACjC,OAAO,EACL,aAAa,GAKd,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-Sent Events (SSE) response formatting helpers.
|
|
3
|
+
*
|
|
4
|
+
* These utilities help format SSE responses according to the specification,
|
|
5
|
+
* with proper event names and JSON data payloads.
|
|
6
|
+
*/
|
|
7
|
+
import { ServerResponse } from 'http';
|
|
8
|
+
/**
|
|
9
|
+
* Set up an HTTP response for SSE streaming.
|
|
10
|
+
*
|
|
11
|
+
* @param res - The HTTP response object
|
|
12
|
+
*/
|
|
13
|
+
export declare function setupSSEResponse(res: ServerResponse): void;
|
|
14
|
+
/**
|
|
15
|
+
* Send a Server-Sent Event to a single response.
|
|
16
|
+
*
|
|
17
|
+
* @param res - The HTTP response object
|
|
18
|
+
* @param event - The event type (e.g., 'init', 'assistant', 'result')
|
|
19
|
+
* @param data - The event data (will be JSON stringified)
|
|
20
|
+
*/
|
|
21
|
+
export declare function sendSSE(res: ServerResponse, event: string, data: unknown): void;
|
|
22
|
+
/**
|
|
23
|
+
* Broadcast an SSE event to multiple responses.
|
|
24
|
+
*
|
|
25
|
+
* @param responses - Set of HTTP response objects
|
|
26
|
+
* @param event - The event type
|
|
27
|
+
* @param data - The event data (will be JSON stringified)
|
|
28
|
+
*/
|
|
29
|
+
export declare function broadcastSSE(responses: Set<ServerResponse>, event: string, data: unknown): void;
|
|
30
|
+
/**
|
|
31
|
+
* Broadcast an SSE event with a session ID attached.
|
|
32
|
+
*
|
|
33
|
+
* This is important for clients to filter out stale events from previous
|
|
34
|
+
* sessions (e.g., when clear() is called mid-stream).
|
|
35
|
+
*
|
|
36
|
+
* @param responses - Set of HTTP response objects
|
|
37
|
+
* @param event - The event type
|
|
38
|
+
* @param data - The event data (sessionId will be added)
|
|
39
|
+
* @param sessionId - The current session ID
|
|
40
|
+
*/
|
|
41
|
+
export declare function broadcastSSEWithSession(responses: Set<ServerResponse>, event: string, data: Record<string, unknown>, sessionId: string): void;
|
|
42
|
+
//# sourceMappingURL=sse-emitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-emitter.d.ts","sourceRoot":"","sources":["../../src/server/sse-emitter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAEtC;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAI1D;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAI/E;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,EAC9B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,OAAO,GACZ,IAAI,CAIN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,EAC9B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,EAAE,MAAM,GAChB,IAAI,CAGN"}
|