@dsiloed/silo-link 1.0.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/LICENSE +21 -0
- package/README.md +350 -0
- package/dist/api/dsiloed-client.d.ts +32 -0
- package/dist/api/dsiloed-client.d.ts.map +1 -0
- package/dist/api/dsiloed-client.js +240 -0
- package/dist/api/dsiloed-client.js.map +1 -0
- package/dist/cable/action-cable-client.d.ts +28 -0
- package/dist/cable/action-cable-client.d.ts.map +1 -0
- package/dist/cable/action-cable-client.js +194 -0
- package/dist/cable/action-cable-client.js.map +1 -0
- package/dist/cable/subscription-manager.d.ts +29 -0
- package/dist/cable/subscription-manager.d.ts.map +1 -0
- package/dist/cable/subscription-manager.js +125 -0
- package/dist/cable/subscription-manager.js.map +1 -0
- package/dist/cli/commands.d.ts +4 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +144 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/daemon.d.ts +5 -0
- package/dist/cli/daemon.d.ts.map +1 -0
- package/dist/cli/daemon.js +35 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/config/config-manager.d.ts +7 -0
- package/dist/config/config-manager.d.ts.map +1 -0
- package/dist/config/config-manager.js +76 -0
- package/dist/config/config-manager.js.map +1 -0
- package/dist/config/jwt-generator.d.ts +15 -0
- package/dist/config/jwt-generator.d.ts.map +1 -0
- package/dist/config/jwt-generator.js +54 -0
- package/dist/config/jwt-generator.js.map +1 -0
- package/dist/core/bridge.d.ts +37 -0
- package/dist/core/bridge.d.ts.map +1 -0
- package/dist/core/bridge.js +247 -0
- package/dist/core/bridge.js.map +1 -0
- package/dist/core/claude-launcher.d.ts +78 -0
- package/dist/core/claude-launcher.d.ts.map +1 -0
- package/dist/core/claude-launcher.js +352 -0
- package/dist/core/claude-launcher.js.map +1 -0
- package/dist/core/message-queue.d.ts +47 -0
- package/dist/core/message-queue.d.ts.map +1 -0
- package/dist/core/message-queue.js +139 -0
- package/dist/core/message-queue.js.map +1 -0
- package/dist/core/session-manager.d.ts +24 -0
- package/dist/core/session-manager.d.ts.map +1 -0
- package/dist/core/session-manager.js +111 -0
- package/dist/core/session-manager.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +27 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +109 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/register-tools.d.ts +19 -0
- package/dist/mcp/tools/register-tools.d.ts.map +1 -0
- package/dist/mcp/tools/register-tools.js +385 -0
- package/dist/mcp/tools/register-tools.js.map +1 -0
- package/dist/types/index.d.ts +74 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Manages Claude Code child processes.
|
|
4
|
+
*
|
|
5
|
+
* Strategy:
|
|
6
|
+
* - For SiloLink-spawned sessions: nudge via stdin when idle (preserves context)
|
|
7
|
+
* - Respawn ONLY when the process actually exits
|
|
8
|
+
* - On respawn, use `claude --resume <id>` to restore context
|
|
9
|
+
* - Store Claude session ID in DSiloed agent_session metadata
|
|
10
|
+
* - Kill all child processes on SiloLink shutdown
|
|
11
|
+
*/
|
|
12
|
+
export class ClaudeLauncher {
|
|
13
|
+
config;
|
|
14
|
+
sessionManager;
|
|
15
|
+
dsiloedClient;
|
|
16
|
+
childProcess = null;
|
|
17
|
+
tmuxSessions = new Map(); // tmuxName -> conversationId
|
|
18
|
+
tmuxMonitorTimer = null;
|
|
19
|
+
idleCheckTimer = null;
|
|
20
|
+
launchingConversations = new Set();
|
|
21
|
+
messageQueue = null;
|
|
22
|
+
enabled;
|
|
23
|
+
lastNudgeAt = 0;
|
|
24
|
+
nudgeCount = 0; // Consecutive nudges without activity change
|
|
25
|
+
lastActivitySnapshot = new Map(); // sessionId -> lastActivity timestamp
|
|
26
|
+
// Last Claude Code session ID (for --resume)
|
|
27
|
+
lastClaudeSessionId = null;
|
|
28
|
+
constructor(config, sessionManager, dsiloedClient, messageQueue) {
|
|
29
|
+
this.config = config;
|
|
30
|
+
this.sessionManager = sessionManager;
|
|
31
|
+
this.dsiloedClient = dsiloedClient || null;
|
|
32
|
+
this.messageQueue = messageQueue || null;
|
|
33
|
+
this.enabled = !!(config.claude_command && config.claude_working_directory);
|
|
34
|
+
}
|
|
35
|
+
isEnabled() {
|
|
36
|
+
return this.enabled;
|
|
37
|
+
}
|
|
38
|
+
isAutoRespawnEnabled() {
|
|
39
|
+
return this.enabled && !!this.config.claude_auto_respawn;
|
|
40
|
+
}
|
|
41
|
+
hasLiveProcess() {
|
|
42
|
+
return this.tmuxSessions.size > 0;
|
|
43
|
+
}
|
|
44
|
+
getLastClaudeSessionId() {
|
|
45
|
+
return this.lastClaudeSessionId;
|
|
46
|
+
}
|
|
47
|
+
setLastResumeId(resumeId) {
|
|
48
|
+
this.lastClaudeSessionId = resumeId;
|
|
49
|
+
console.log(`[ClaudeLauncher] Restored resume ID from previous session: ${resumeId}`);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Start the idle monitor that nudges idle sessions or respawns dead ones.
|
|
53
|
+
*/
|
|
54
|
+
startIdleMonitor() {
|
|
55
|
+
if (!this.isAutoRespawnEnabled())
|
|
56
|
+
return;
|
|
57
|
+
const checkInterval = Math.max((this.config.claude_idle_timeout_ms || 30000) / 2, 5000);
|
|
58
|
+
this.idleCheckTimer = setInterval(() => this.checkIdle(), checkInterval);
|
|
59
|
+
console.log(` Claude auto-manage enabled (idle timeout: ${this.config.claude_idle_timeout_ms || 30000}ms)`);
|
|
60
|
+
}
|
|
61
|
+
stopIdleMonitor() {
|
|
62
|
+
if (this.idleCheckTimer) {
|
|
63
|
+
clearInterval(this.idleCheckTimer);
|
|
64
|
+
this.idleCheckTimer = null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Launch a new Claude Code session. Uses --resume if a previous session ID is available.
|
|
69
|
+
*/
|
|
70
|
+
async launch(reason = 'manual', conversationId) {
|
|
71
|
+
if (!this.enabled) {
|
|
72
|
+
console.log('[ClaudeLauncher] Not configured — set claude_command and claude_working_directory in config');
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
const convKey = conversationId || 0;
|
|
76
|
+
if (this.launchingConversations.has(convKey)) {
|
|
77
|
+
console.log(`[ClaudeLauncher] Already launching for conversation ${convKey}, skipping`);
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
this.launchingConversations.add(convKey);
|
|
81
|
+
try {
|
|
82
|
+
const command = this.config.claude_command || 'claude';
|
|
83
|
+
const cwd = this.config.claude_working_directory || process.cwd();
|
|
84
|
+
const args = ['--dangerously-skip-permissions'];
|
|
85
|
+
let prompt;
|
|
86
|
+
// Try to resume previous session if we have an ID
|
|
87
|
+
if (this.lastClaudeSessionId && (reason === 'process-exit' || reason === 'inbound-message')) {
|
|
88
|
+
args.push('--resume', this.lastClaudeSessionId);
|
|
89
|
+
console.log(`[ClaudeLauncher] Resuming session: ${this.lastClaudeSessionId}`);
|
|
90
|
+
prompt = 'Continue polling SiloLink for messages. Check memory for context if needed.';
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
if (reason === 'process-exit' || reason === 'inbound-message') {
|
|
94
|
+
const registerParams = conversationId
|
|
95
|
+
? `{ "conversation_id": ${conversationId} }`
|
|
96
|
+
: `{}`;
|
|
97
|
+
prompt = [
|
|
98
|
+
`Call mcp__silolink__remote_register with these exact parameters: ${registerParams}. After registering, IMMEDIATELY send a remote_notify message telling the user you are ready. Then enter the poll loop using remote_poll. See CLAUDE.md for the poll loop pattern.`,
|
|
99
|
+
'',
|
|
100
|
+
'Context: This is a new session replacing a previous one that ended.',
|
|
101
|
+
'Before entering the poll loop:',
|
|
102
|
+
'1. Check your memory files for context on recent work',
|
|
103
|
+
'2. Briefly review what was being worked on',
|
|
104
|
+
'3. Save any important context from the conversation history to memory',
|
|
105
|
+
'4. Send a remote_notify telling the user you are ready and what context you loaded',
|
|
106
|
+
'5. Then enter the poll loop and process any pending messages',
|
|
107
|
+
'',
|
|
108
|
+
'CRITICAL: The user is NOT watching the terminal. You MUST send a remote_notify progress update after EVERY major step (file edits, commits, merges, deploys, errors). Do not go silent while working.',
|
|
109
|
+
].join('\n');
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
prompt = this.config.claude_session_prompt ||
|
|
113
|
+
'Register with SiloLink as "portablemind" and enter the poll loop.';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
console.log(`[ClaudeLauncher] Launching Claude Code via tmux (reason: ${reason})`);
|
|
117
|
+
console.log(` Command: ${command} ${args.join(' ')}`);
|
|
118
|
+
console.log(` Working directory: ${cwd}`);
|
|
119
|
+
console.log(` Prompt: ${prompt.substring(0, 100)}...`);
|
|
120
|
+
const tmuxSession = `silolink-claude-${Date.now()}`;
|
|
121
|
+
// Create a new tmux session running Claude Code in a real TTY
|
|
122
|
+
const claudeCmd = `cd ${cwd} && ${command} ${args.join(' ')}`;
|
|
123
|
+
const tmuxCreate = spawn('tmux', [
|
|
124
|
+
'new-session', '-d', '-s', tmuxSession, '-x', '200', '-y', '50', claudeCmd,
|
|
125
|
+
], {
|
|
126
|
+
stdio: 'ignore',
|
|
127
|
+
detached: true,
|
|
128
|
+
env: {
|
|
129
|
+
...process.env,
|
|
130
|
+
SILOLINK_MCP_URL: `http://localhost:${this.config.mcp_port}/mcp`,
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
tmuxCreate.unref();
|
|
134
|
+
// Wait for tmux session to start, then send the prompt
|
|
135
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
136
|
+
// Check if tmux session exists
|
|
137
|
+
const checkResult = spawn('tmux', ['has-session', '-t', tmuxSession], { stdio: 'ignore' });
|
|
138
|
+
const sessionExists = await new Promise(resolve => {
|
|
139
|
+
checkResult.on('exit', code => resolve(code === 0));
|
|
140
|
+
});
|
|
141
|
+
if (!sessionExists) {
|
|
142
|
+
console.error(`[ClaudeLauncher] tmux session ${tmuxSession} failed to start`);
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
console.log(`[ClaudeLauncher] tmux session "${tmuxSession}" created`);
|
|
146
|
+
this.tmuxSessions.set(tmuxSession, conversationId || 0);
|
|
147
|
+
// Send the prompt to Claude via tmux send-keys after MCP servers initialize
|
|
148
|
+
const sessionToPrompt = tmuxSession;
|
|
149
|
+
const promptToSend = prompt;
|
|
150
|
+
setTimeout(() => {
|
|
151
|
+
const escapedPrompt = promptToSend.replace(/"/g, '\\"').replace(/\n/g, ' ');
|
|
152
|
+
const sendKeys = spawn('tmux', ['send-keys', '-t', sessionToPrompt, escapedPrompt], { stdio: 'pipe' });
|
|
153
|
+
sendKeys.on('exit', (code) => {
|
|
154
|
+
if (code === 0) {
|
|
155
|
+
console.log(`[ClaudeLauncher] Sent prompt to tmux session "${sessionToPrompt}" (${promptToSend.length} chars)`);
|
|
156
|
+
// Send Enter separately after a short delay to avoid bracketed paste swallowing it
|
|
157
|
+
setTimeout(() => {
|
|
158
|
+
spawn('tmux', ['send-keys', '-t', sessionToPrompt, 'Enter'], { stdio: 'pipe' });
|
|
159
|
+
}, 500);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
console.error(`[ClaudeLauncher] Failed to send prompt to tmux session "${sessionToPrompt}" (exit code: ${code})`);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
sendKeys.on('error', (err) => {
|
|
166
|
+
console.error(`[ClaudeLauncher] Error sending prompt to "${sessionToPrompt}": ${err.message}`);
|
|
167
|
+
});
|
|
168
|
+
}, 8000); // Wait 8s for MCP to initialize
|
|
169
|
+
// Monitor the tmux session for exit
|
|
170
|
+
this.monitorTmuxSession(tmuxSession);
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
setTimeout(() => { this.launchingConversations.delete(convKey); }, 10000);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Store the Claude resume ID in the DSiloed agent session metadata.
|
|
179
|
+
*/
|
|
180
|
+
async storeResumeId(resumeId) {
|
|
181
|
+
if (!this.dsiloedClient)
|
|
182
|
+
return;
|
|
183
|
+
const sessions = this.sessionManager.getAll();
|
|
184
|
+
for (const session of sessions) {
|
|
185
|
+
if (session.agentSessionId) {
|
|
186
|
+
session.claudeResumeId = resumeId;
|
|
187
|
+
await this.dsiloedClient.updateAgentSession(session.agentSessionId, {
|
|
188
|
+
metadata: { claude_resume_id: resumeId },
|
|
189
|
+
});
|
|
190
|
+
console.log(`[ClaudeLauncher] Stored resume ID in agent session ${session.agentSessionId}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Called when an inbound message arrives and no active session can handle it.
|
|
196
|
+
*/
|
|
197
|
+
async launchOnMessage(conversationId) {
|
|
198
|
+
if (!this.enabled)
|
|
199
|
+
return false;
|
|
200
|
+
// Check if there's already a session registered for this conversation
|
|
201
|
+
if (conversationId) {
|
|
202
|
+
const existingSession = this.sessionManager.getByConversationId(conversationId);
|
|
203
|
+
if (existingSession) {
|
|
204
|
+
console.log(`[ClaudeLauncher] Session already exists for conversation ${conversationId} — skipping`);
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return this.launch('inbound-message', conversationId);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Check for idle sessions — nudge if process alive, respawn if dead.
|
|
212
|
+
* If a session has been nudged multiple times without responding and has
|
|
213
|
+
* pending messages, kill and relaunch it (hung session recovery).
|
|
214
|
+
*/
|
|
215
|
+
async checkIdle() {
|
|
216
|
+
const sessions = this.sessionManager.getAll();
|
|
217
|
+
const idleTimeout = this.config.claude_idle_timeout_ms || 30000;
|
|
218
|
+
const maxNudges = 3; // Kill after 3 failed nudges (~90s with no response)
|
|
219
|
+
const now = Date.now();
|
|
220
|
+
if (sessions.length === 0)
|
|
221
|
+
return;
|
|
222
|
+
const allIdle = sessions.every(s => now - s.lastActivity.getTime() > idleTimeout);
|
|
223
|
+
if (!allIdle) {
|
|
224
|
+
// Activity detected — reset nudge counter and update snapshots
|
|
225
|
+
this.nudgeCount = 0;
|
|
226
|
+
for (const s of sessions) {
|
|
227
|
+
this.lastActivitySnapshot.set(s.sessionId, s.lastActivity.getTime());
|
|
228
|
+
}
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (this.hasLiveProcess()) {
|
|
232
|
+
// Check if activity changed since last nudge
|
|
233
|
+
const activityChanged = sessions.some(s => {
|
|
234
|
+
const prev = this.lastActivitySnapshot.get(s.sessionId) || 0;
|
|
235
|
+
return s.lastActivity.getTime() > prev;
|
|
236
|
+
});
|
|
237
|
+
if (activityChanged) {
|
|
238
|
+
this.nudgeCount = 0;
|
|
239
|
+
}
|
|
240
|
+
// Update snapshots
|
|
241
|
+
for (const s of sessions) {
|
|
242
|
+
this.lastActivitySnapshot.set(s.sessionId, s.lastActivity.getTime());
|
|
243
|
+
}
|
|
244
|
+
// Check if any session has pending messages in the queue
|
|
245
|
+
const hasPendingMessages = this.messageQueue && sessions.some(s => this.messageQueue.queueSize(s.sessionId) > 0);
|
|
246
|
+
if (this.nudgeCount >= maxNudges && hasPendingMessages) {
|
|
247
|
+
// Session is hung with undelivered messages — kill and relaunch
|
|
248
|
+
console.log(`[ClaudeLauncher] Session hung (${this.nudgeCount} nudges with no response, messages pending) — killing and relaunching`);
|
|
249
|
+
const hungSessions = sessions.filter(s => this.messageQueue.queueSize(s.sessionId) > 0);
|
|
250
|
+
for (const s of hungSessions) {
|
|
251
|
+
this.killByConversation(s.conversationId);
|
|
252
|
+
this.sessionManager.unregister(s.sessionId);
|
|
253
|
+
// Relaunch for this conversation
|
|
254
|
+
await this.launch('inbound-message', s.conversationId);
|
|
255
|
+
}
|
|
256
|
+
this.nudgeCount = 0;
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
// Process alive but idle — nudge via stdin
|
|
260
|
+
this.nudge();
|
|
261
|
+
this.nudgeCount++;
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
else if (this.launchingConversations.size === 0) {
|
|
265
|
+
const lastConvId = sessions[0]?.conversationId;
|
|
266
|
+
if (!this.lastClaudeSessionId) {
|
|
267
|
+
this.lastClaudeSessionId = sessions[0]?.claudeResumeId || null;
|
|
268
|
+
}
|
|
269
|
+
console.log(`[ClaudeLauncher] Sessions orphaned (process dead), respawning...`);
|
|
270
|
+
this.nudgeCount = 0;
|
|
271
|
+
await this.launch('process-exit', lastConvId);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Monitor a tmux session and detect when it exits.
|
|
276
|
+
*/
|
|
277
|
+
monitorTmuxSession(sessionName) {
|
|
278
|
+
// Start monitor if not already running
|
|
279
|
+
if (!this.tmuxMonitorTimer) {
|
|
280
|
+
this.tmuxMonitorTimer = setInterval(() => this.checkTmuxSessions(), 5000);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
checkTmuxSessions() {
|
|
284
|
+
for (const [name] of this.tmuxSessions) {
|
|
285
|
+
const check = spawn('tmux', ['has-session', '-t', name], { stdio: 'ignore' });
|
|
286
|
+
check.on('exit', (code) => {
|
|
287
|
+
if (code !== 0) {
|
|
288
|
+
console.log(`[ClaudeLauncher] tmux session "${name}" ended`);
|
|
289
|
+
this.tmuxSessions.delete(name);
|
|
290
|
+
if (this.tmuxSessions.size === 0 && this.tmuxMonitorTimer) {
|
|
291
|
+
clearInterval(this.tmuxMonitorTimer);
|
|
292
|
+
this.tmuxMonitorTimer = null;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Send a message to all running Claude sessions via tmux send-keys.
|
|
300
|
+
*/
|
|
301
|
+
nudge() {
|
|
302
|
+
if (this.tmuxSessions.size === 0)
|
|
303
|
+
return false;
|
|
304
|
+
const now = Date.now();
|
|
305
|
+
if (now - this.lastNudgeAt < 10000)
|
|
306
|
+
return false;
|
|
307
|
+
this.lastNudgeAt = now;
|
|
308
|
+
const message = 'Continue polling SiloLink for messages. Do not stop the poll loop.';
|
|
309
|
+
for (const [name] of this.tmuxSessions) {
|
|
310
|
+
spawn('tmux', ['send-keys', '-t', name, message, 'Enter'], { stdio: 'ignore' });
|
|
311
|
+
}
|
|
312
|
+
console.log(`[ClaudeLauncher] Nudged ${this.tmuxSessions.size} Claude session(s) via tmux`);
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Kill the Claude session for a specific conversation.
|
|
317
|
+
*/
|
|
318
|
+
killByConversation(conversationId) {
|
|
319
|
+
for (const [name, convId] of this.tmuxSessions) {
|
|
320
|
+
if (convId === conversationId) {
|
|
321
|
+
console.log(`[ClaudeLauncher] Killing tmux session "${name}" (conversation ${conversationId})`);
|
|
322
|
+
spawn('tmux', ['kill-session', '-t', name], { stdio: 'ignore' });
|
|
323
|
+
this.tmuxSessions.delete(name);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
console.log(`[ClaudeLauncher] No tmux session found for conversation ${conversationId}`);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Kill all running Claude Code sessions.
|
|
331
|
+
*/
|
|
332
|
+
kill() {
|
|
333
|
+
for (const [name] of this.tmuxSessions) {
|
|
334
|
+
console.log(`[ClaudeLauncher] Killing tmux session "${name}"`);
|
|
335
|
+
spawn('tmux', ['kill-session', '-t', name], { stdio: 'ignore' });
|
|
336
|
+
}
|
|
337
|
+
this.tmuxSessions.clear();
|
|
338
|
+
if (this.tmuxMonitorTimer) {
|
|
339
|
+
clearInterval(this.tmuxMonitorTimer);
|
|
340
|
+
this.tmuxMonitorTimer = null;
|
|
341
|
+
}
|
|
342
|
+
if (this.childProcess) {
|
|
343
|
+
this.childProcess.kill('SIGTERM');
|
|
344
|
+
this.childProcess = null;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
destroy() {
|
|
348
|
+
this.stopIdleMonitor();
|
|
349
|
+
this.kill();
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
//# sourceMappingURL=claude-launcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-launcher.js","sourceRoot":"","sources":["../../src/core/claude-launcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { InboundMessage } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Message queue with delivery acknowledgment.
|
|
4
|
+
*
|
|
5
|
+
* Messages are NEVER removed from the queue until the next successful
|
|
6
|
+
* interaction confirms the prior message was delivered. This ensures
|
|
7
|
+
* messages survive MCP transport failures, tool rejections, and
|
|
8
|
+
* connection drops.
|
|
9
|
+
*
|
|
10
|
+
* Flow:
|
|
11
|
+
* 1. Message arrives → pushed to queue, waiter notified (if waiting)
|
|
12
|
+
* 2. waitForMessage returns the message → message stays in queue, marked as "pending delivery"
|
|
13
|
+
* 3. Next waitForMessage/checkMessages call → acknowledges prior delivery, removes from queue
|
|
14
|
+
* 4. If no acknowledgment (connection dropped) → message stays in queue for retry
|
|
15
|
+
*/
|
|
16
|
+
export declare class MessageQueue {
|
|
17
|
+
private queues;
|
|
18
|
+
private waiters;
|
|
19
|
+
private pendingAck;
|
|
20
|
+
enqueue(sessionId: string, message: InboundMessage): void;
|
|
21
|
+
/**
|
|
22
|
+
* Get the next message, acknowledging any previously returned message.
|
|
23
|
+
* The returned message stays in the queue until the NEXT call acknowledges it.
|
|
24
|
+
*/
|
|
25
|
+
waitForMessage(sessionId: string, timeoutMs: number): Promise<InboundMessage>;
|
|
26
|
+
/**
|
|
27
|
+
* Non-blocking check for all queued messages. Acknowledges any pending delivery.
|
|
28
|
+
*/
|
|
29
|
+
dequeueAll(sessionId: string): InboundMessage[];
|
|
30
|
+
/**
|
|
31
|
+
* Non-blocking peek: returns the first message without consuming it.
|
|
32
|
+
* Acknowledges any previously delivered message first.
|
|
33
|
+
* Returns null if no messages are queued.
|
|
34
|
+
*/
|
|
35
|
+
poll(sessionId: string): InboundMessage | null;
|
|
36
|
+
/**
|
|
37
|
+
* Acknowledge that the previously returned message was successfully delivered.
|
|
38
|
+
* Removes it from the queue.
|
|
39
|
+
*/
|
|
40
|
+
private acknowledge;
|
|
41
|
+
clearSession(sessionId: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Get queue size for a session (for debugging)
|
|
44
|
+
*/
|
|
45
|
+
queueSize(sessionId: string): number;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=message-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-queue.d.ts","sourceRoot":"","sources":["../../src/core/message-queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQxD;;;;;;;;;;;;;GAaG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,OAAO,CAAkC;IAEjD,OAAO,CAAC,UAAU,CAAkC;IAEpD,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI;IAoBzD;;;OAGG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAuC7E;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,EAAE;IAU/C;;;;OAIG;IACH,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAW9C;;;OAGG;IACH,OAAO,CAAC,WAAW;IAgBnB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAWrC;;OAEG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;CAGrC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message queue with delivery acknowledgment.
|
|
3
|
+
*
|
|
4
|
+
* Messages are NEVER removed from the queue until the next successful
|
|
5
|
+
* interaction confirms the prior message was delivered. This ensures
|
|
6
|
+
* messages survive MCP transport failures, tool rejections, and
|
|
7
|
+
* connection drops.
|
|
8
|
+
*
|
|
9
|
+
* Flow:
|
|
10
|
+
* 1. Message arrives → pushed to queue, waiter notified (if waiting)
|
|
11
|
+
* 2. waitForMessage returns the message → message stays in queue, marked as "pending delivery"
|
|
12
|
+
* 3. Next waitForMessage/checkMessages call → acknowledges prior delivery, removes from queue
|
|
13
|
+
* 4. If no acknowledgment (connection dropped) → message stays in queue for retry
|
|
14
|
+
*/
|
|
15
|
+
export class MessageQueue {
|
|
16
|
+
queues = new Map();
|
|
17
|
+
waiters = new Map();
|
|
18
|
+
// Track the last message ID returned to a caller — acknowledged on next call
|
|
19
|
+
pendingAck = new Map();
|
|
20
|
+
enqueue(sessionId, message) {
|
|
21
|
+
let queue = this.queues.get(sessionId);
|
|
22
|
+
if (!queue) {
|
|
23
|
+
queue = [];
|
|
24
|
+
this.queues.set(sessionId, queue);
|
|
25
|
+
}
|
|
26
|
+
queue.push(message);
|
|
27
|
+
console.log(`[MessageQueue] Enqueued message ${message.id} for session ${sessionId} (queue size: ${queue.length})`);
|
|
28
|
+
// Wake up waiter if one exists
|
|
29
|
+
const waiter = this.waiters.get(sessionId);
|
|
30
|
+
if (waiter) {
|
|
31
|
+
clearTimeout(waiter.timer);
|
|
32
|
+
this.waiters.delete(sessionId);
|
|
33
|
+
// Don't consume — just notify. The waiter's handler will call peek/ack.
|
|
34
|
+
waiter.resolve(message);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get the next message, acknowledging any previously returned message.
|
|
39
|
+
* The returned message stays in the queue until the NEXT call acknowledges it.
|
|
40
|
+
*/
|
|
41
|
+
waitForMessage(sessionId, timeoutMs) {
|
|
42
|
+
// Acknowledge previously returned message
|
|
43
|
+
this.acknowledge(sessionId);
|
|
44
|
+
// Check queue for pending messages
|
|
45
|
+
const queue = this.queues.get(sessionId);
|
|
46
|
+
if (queue && queue.length > 0) {
|
|
47
|
+
const message = queue[0]; // Peek, don't shift
|
|
48
|
+
this.pendingAck.set(sessionId, message.id);
|
|
49
|
+
console.log(`[MessageQueue] Returning queued message ${message.id} (pending ack, queue size: ${queue.length})`);
|
|
50
|
+
return Promise.resolve(message);
|
|
51
|
+
}
|
|
52
|
+
// Cancel any existing waiter
|
|
53
|
+
const existing = this.waiters.get(sessionId);
|
|
54
|
+
if (existing) {
|
|
55
|
+
clearTimeout(existing.timer);
|
|
56
|
+
existing.reject(new Error('Superseded by new waiter'));
|
|
57
|
+
}
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
const timer = setTimeout(() => {
|
|
60
|
+
this.waiters.delete(sessionId);
|
|
61
|
+
reject(new Error('Timeout waiting for message'));
|
|
62
|
+
}, timeoutMs);
|
|
63
|
+
this.waiters.set(sessionId, {
|
|
64
|
+
resolve: (message) => {
|
|
65
|
+
// Message was just enqueued — peek it without removing
|
|
66
|
+
this.pendingAck.set(sessionId, message.id);
|
|
67
|
+
console.log(`[MessageQueue] Waiter resolved with message ${message.id} (pending ack)`);
|
|
68
|
+
resolve(message);
|
|
69
|
+
},
|
|
70
|
+
reject,
|
|
71
|
+
timer
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Non-blocking check for all queued messages. Acknowledges any pending delivery.
|
|
77
|
+
*/
|
|
78
|
+
dequeueAll(sessionId) {
|
|
79
|
+
this.acknowledge(sessionId);
|
|
80
|
+
const queue = this.queues.get(sessionId);
|
|
81
|
+
if (!queue || queue.length === 0)
|
|
82
|
+
return [];
|
|
83
|
+
// Return copies and clear queue (check_messages consumes all)
|
|
84
|
+
const messages = [...queue];
|
|
85
|
+
queue.length = 0;
|
|
86
|
+
return messages;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Non-blocking peek: returns the first message without consuming it.
|
|
90
|
+
* Acknowledges any previously delivered message first.
|
|
91
|
+
* Returns null if no messages are queued.
|
|
92
|
+
*/
|
|
93
|
+
poll(sessionId) {
|
|
94
|
+
this.acknowledge(sessionId);
|
|
95
|
+
const queue = this.queues.get(sessionId);
|
|
96
|
+
if (!queue || queue.length === 0)
|
|
97
|
+
return null;
|
|
98
|
+
const message = queue[0];
|
|
99
|
+
this.pendingAck.set(sessionId, message.id);
|
|
100
|
+
console.log(`[MessageQueue] Poll returned message ${message.id} (pending ack, queue size: ${queue.length})`);
|
|
101
|
+
return message;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Acknowledge that the previously returned message was successfully delivered.
|
|
105
|
+
* Removes it from the queue.
|
|
106
|
+
*/
|
|
107
|
+
acknowledge(sessionId) {
|
|
108
|
+
const ackId = this.pendingAck.get(sessionId);
|
|
109
|
+
if (ackId === undefined)
|
|
110
|
+
return;
|
|
111
|
+
const queue = this.queues.get(sessionId);
|
|
112
|
+
if (queue) {
|
|
113
|
+
const index = queue.findIndex(m => m.id === ackId);
|
|
114
|
+
if (index !== -1) {
|
|
115
|
+
queue.splice(index, 1);
|
|
116
|
+
console.log(`[MessageQueue] Acknowledged and removed message ${ackId} (queue size: ${queue.length})`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Delete pendingAck AFTER removing from queue to prevent stuck messages
|
|
120
|
+
this.pendingAck.delete(sessionId);
|
|
121
|
+
}
|
|
122
|
+
clearSession(sessionId) {
|
|
123
|
+
this.queues.delete(sessionId);
|
|
124
|
+
this.pendingAck.delete(sessionId);
|
|
125
|
+
const waiter = this.waiters.get(sessionId);
|
|
126
|
+
if (waiter) {
|
|
127
|
+
clearTimeout(waiter.timer);
|
|
128
|
+
waiter.reject(new Error('Session cleared'));
|
|
129
|
+
this.waiters.delete(sessionId);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Get queue size for a session (for debugging)
|
|
134
|
+
*/
|
|
135
|
+
queueSize(sessionId) {
|
|
136
|
+
return this.queues.get(sessionId)?.length || 0;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=message-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-queue.js","sourceRoot":"","sources":["../../src/core/message-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Session } from '../types/index.js';
|
|
2
|
+
export declare class SessionManager {
|
|
3
|
+
private sessions;
|
|
4
|
+
private mcpToSession;
|
|
5
|
+
private conversationToSession;
|
|
6
|
+
private cleanupTimer;
|
|
7
|
+
private onSessionCleaned?;
|
|
8
|
+
constructor(onSessionCleaned?: (session: Session) => void);
|
|
9
|
+
register(session: Session): void;
|
|
10
|
+
unregister(sessionId: string): Session | undefined;
|
|
11
|
+
get(sessionId: string): Session | undefined;
|
|
12
|
+
getByMcpSessionId(mcpSessionId: string): Session | undefined;
|
|
13
|
+
getByConversationId(conversationId: number): Session | undefined;
|
|
14
|
+
getAll(): Session[];
|
|
15
|
+
touchActivity(sessionId: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* Checks that the 3 internal maps are consistent with each other.
|
|
18
|
+
* Returns true if everything is in sync, false otherwise.
|
|
19
|
+
*/
|
|
20
|
+
validate(): boolean;
|
|
21
|
+
private cleanupIdle;
|
|
22
|
+
destroy(): void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=session-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/core/session-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAIjD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,qBAAqB,CAAkC;IAC/D,OAAO,CAAC,YAAY,CAA+C;IACnE,OAAO,CAAC,gBAAgB,CAAC,CAA6B;gBAE1C,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI;IAKzD,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAMhC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAUlD,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI3C,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAK5D,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAKhE,MAAM,IAAI,OAAO,EAAE;IAInB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAOtC;;;OAGG;IACH,QAAQ,IAAI,OAAO;IAyDnB,OAAO,CAAC,WAAW;IAcnB,OAAO,IAAI,IAAI;CAShB"}
|