Skip to content
This repository was archived by the owner on Sep 23, 2025. It is now read-only.

Commit d82d30a

Browse files
committed
Add shell PID filtering to log messages
- Server: Modified send_log() to include terminal_shell_pid in payload - Extension: Added log message handling with shell PID filtering - Extension: Updated extractShellPidFromMessage to include log messages - Log messages now display in correct VSCode window with [LEVEL] prefix - Prevents 'unknown message type: log' errors Completes shell PID filtering for all message types: - present_review ✅ - get_selection ✅ - log ✅ All messages now properly filtered by terminal ownership for multi-window support.
1 parent 5197dd3 commit d82d30a

File tree

3 files changed

+97
-72
lines changed

3 files changed

+97
-72
lines changed

extension/src/extension.ts

Lines changed: 61 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ReviewWebviewProvider } from './reviewWebview';
77

88
// 💡: Types for IPC communication with MCP server
99
interface IPCMessage {
10-
type: 'present_review' | 'log' | 'get_selection';
10+
type: 'present_review' | 'log' | 'get_selection' | 'response';
1111
payload: {
1212
content: string;
1313
mode: 'replace' | 'update-section' | 'append';
@@ -31,7 +31,7 @@ class DaemonClient implements vscode.Disposable {
3131
private context: vscode.ExtensionContext,
3232
private reviewProvider: ReviewWebviewProvider,
3333
private outputChannel: vscode.OutputChannel
34-
) {}
34+
) { }
3535

3636
start(): void {
3737
this.outputChannel.appendLine('Starting daemon client...');
@@ -56,7 +56,7 @@ class DaemonClient implements vscode.Disposable {
5656

5757
this.socket.on('error', (error) => {
5858
// Only log at debug level to avoid spam during normal startup
59-
this.outputChannel.appendLine(`Daemon connection failed: ${error.message} (will retry in ${this.RECONNECT_INTERVAL_MS/1000}s)`);
59+
this.outputChannel.appendLine(`Daemon connection failed: ${error.message} (will retry in ${this.RECONNECT_INTERVAL_MS / 1000}s)`);
6060
this.scheduleReconnect();
6161
});
6262

@@ -73,11 +73,11 @@ class DaemonClient implements vscode.Disposable {
7373

7474
this.socket.on('data', (data) => {
7575
this.buffer += data.toString();
76-
76+
7777
// Process all complete messages (ending with \n)
7878
let lines = this.buffer.split('\n');
7979
this.buffer = lines.pop() || ''; // Keep incomplete line in buffer
80-
80+
8181
for (const line of lines) {
8282
if (line.trim()) { // Skip empty lines
8383
try {
@@ -100,7 +100,7 @@ class DaemonClient implements vscode.Disposable {
100100
private async handleIncomingMessage(message: IPCMessage): Promise<void> {
101101
// Extract shell PID from message payload for filtering
102102
const shellPid = this.extractShellPidFromMessage(message);
103-
103+
104104
if (shellPid) {
105105
// Check if this message is intended for our VSCode window
106106
const isForOurWindow = await this.isMessageForOurWindow(shellPid);
@@ -109,7 +109,6 @@ class DaemonClient implements vscode.Disposable {
109109
return;
110110
}
111111
}
112-
113112
if (message.type === 'present_review') {
114113
try {
115114
const reviewPayload = message.payload as {
@@ -119,51 +118,67 @@ class DaemonClient implements vscode.Disposable {
119118
baseUri?: string;
120119
terminal_shell_pid: number;
121120
};
122-
121+
123122
this.reviewProvider.updateReview(
124-
reviewPayload.content,
125-
reviewPayload.mode,
123+
reviewPayload.content,
124+
reviewPayload.mode,
126125
reviewPayload.baseUri
127126
);
128127

129128
// Send success response back through daemon
130129
this.sendResponse(message.id, { success: true });
131130
} catch (error) {
132131
this.outputChannel.appendLine(`Error handling present_review: ${error}`);
133-
this.sendResponse(message.id, {
134-
success: false,
135-
error: error instanceof Error ? error.message : String(error)
132+
this.sendResponse(message.id, {
133+
success: false,
134+
error: error instanceof Error ? error.message : String(error)
136135
});
137136
}
138137
} else if (message.type === 'get_selection') {
139138
try {
140139
const selectionData = this.getCurrentSelection();
141-
this.sendResponse(message.id, {
142-
success: true,
143-
data: selectionData
140+
this.sendResponse(message.id, {
141+
success: true,
142+
data: selectionData
144143
});
145144
} catch (error) {
146145
this.outputChannel.appendLine(`Error handling get_selection: ${error}`);
147-
this.sendResponse(message.id, {
148-
success: false,
149-
error: error instanceof Error ? error.message : String(error)
146+
this.sendResponse(message.id, {
147+
success: false,
148+
error: error instanceof Error ? error.message : String(error)
150149
});
151150
}
151+
} else if (message.type === 'log') {
152+
// Handle log messages - no response needed, just display in output channel
153+
try {
154+
const logPayload = message.payload as {
155+
level: string;
156+
message: string;
157+
terminal_shell_pid: number;
158+
};
159+
160+
const levelPrefix = logPayload.level.toUpperCase();
161+
this.outputChannel.appendLine(`[${levelPrefix}] ${logPayload.message}`);
162+
} catch (error) {
163+
this.outputChannel.appendLine(`Error handling log message: ${error}`);
164+
}
165+
} else if (message.type == 'response') {
166+
// Ignore this, response messages are messages that WE send to clients.
152167
} else {
153168
this.outputChannel.appendLine(`Received unknown message type: ${message.type}`);
154-
this.sendResponse(message.id, {
155-
success: false,
156-
error: `Unknown message type: ${message.type}`
169+
this.sendResponse(message.id, {
170+
success: false,
171+
error: `Unknown message type: ${message.type}`
157172
});
158173
}
159174
}
160175

161176
private extractShellPidFromMessage(message: IPCMessage): number | null {
162177
try {
163-
if (message.type === 'present_review' || message.type === 'get_selection') {
178+
if (message.type === 'present_review' || message.type === 'get_selection' || message.type === 'log') {
164179
const payload = message.payload as any;
165180
const shellPid = payload.terminal_shell_pid;
166-
181+
167182
if (typeof shellPid === 'number') {
168183
return shellPid;
169184
} else {
@@ -181,7 +196,7 @@ class DaemonClient implements vscode.Disposable {
181196
try {
182197
// Get all terminal PIDs in the current VSCode window
183198
const terminals = vscode.window.terminals;
184-
199+
185200
for (const terminal of terminals) {
186201
try {
187202
const terminalPid = await terminal.processId;
@@ -193,7 +208,7 @@ class DaemonClient implements vscode.Disposable {
193208
continue;
194209
}
195210
}
196-
211+
197212
return false;
198213
} catch (error) {
199214
this.outputChannel.appendLine(`Error checking if message is for our window: ${error}`);
@@ -269,13 +284,13 @@ class DaemonClient implements vscode.Disposable {
269284
this.outputChannel.appendLine('Warning: Could not discover VSCode PID, using fallback');
270285
return crypto.randomUUID();
271286
})();
272-
287+
273288
return `/tmp/dialectic-daemon-${vscodePid}.sock`;
274289
}
275290

276291
private scheduleReconnect(): void {
277292
if (this.isDisposed) return;
278-
293+
279294
this.clearReconnectTimer();
280295
this.reconnectTimer = setTimeout(() => {
281296
this.connectToDaemon();
@@ -292,12 +307,12 @@ class DaemonClient implements vscode.Disposable {
292307
dispose(): void {
293308
this.isDisposed = true;
294309
this.clearReconnectTimer();
295-
310+
296311
if (this.socket) {
297312
this.socket.destroy();
298313
this.socket = null;
299314
}
300-
315+
301316
this.outputChannel.appendLine('Daemon client disposed');
302317
}
303318
}
@@ -495,23 +510,23 @@ function formatSelectionMessage(
495510
// 💡: PID Discovery Testing - Log all relevant PIDs for debugging
496511
async function logPIDDiscovery(outputChannel: vscode.OutputChannel): Promise<void> {
497512
outputChannel.appendLine('=== PID DISCOVERY TESTING ===');
498-
513+
499514
// Extension process info
500515
outputChannel.appendLine(`Extension process PID: ${process.pid}`);
501516
outputChannel.appendLine(`Extension parent PID: ${process.ppid}`);
502-
517+
503518
// Try to find VSCode PID by walking up the process tree
504519
const vscodePid = findVSCodePID(outputChannel);
505520
if (vscodePid) {
506521
outputChannel.appendLine(`Found VSCode PID: ${vscodePid}`);
507522
} else {
508523
outputChannel.appendLine('Could not find VSCode PID');
509524
}
510-
525+
511526
// Log terminal PIDs (handle the Promise properly)
512527
const terminals = vscode.window.terminals;
513528
outputChannel.appendLine(`Found ${terminals.length} terminals:`);
514-
529+
515530
for (let i = 0; i < terminals.length; i++) {
516531
const terminal = terminals[i];
517532
try {
@@ -522,7 +537,7 @@ async function logPIDDiscovery(outputChannel: vscode.OutputChannel): Promise<voi
522537
outputChannel.appendLine(` Terminal ${i}: name="${terminal.name}", PID=<error: ${error}>`);
523538
}
524539
}
525-
540+
526541
// Set up terminal monitoring
527542
const terminalListener = vscode.window.onDidOpenTerminal(async (terminal) => {
528543
try {
@@ -532,50 +547,50 @@ async function logPIDDiscovery(outputChannel: vscode.OutputChannel): Promise<voi
532547
outputChannel.appendLine(`NEW TERMINAL: name="${terminal.name}", PID=<error: ${error}>`);
533548
}
534549
});
535-
550+
536551
outputChannel.appendLine('=== END PID DISCOVERY ===');
537552
}
538553

539554
// 💡: Attempt to find VSCode PID by walking up process tree
540555
function findVSCodePID(outputChannel: vscode.OutputChannel): number | null {
541556
const { execSync } = require('child_process');
542-
557+
543558
try {
544559
let currentPid = process.pid;
545-
560+
546561
// Walk up the process tree
547562
for (let i = 0; i < 10; i++) { // Safety limit
548563
try {
549564
// Get process info (works on macOS/Linux)
550565
const psOutput = execSync(`ps -p ${currentPid} -o pid,ppid,comm,args`, { encoding: 'utf8' });
551566
const lines = psOutput.trim().split('\n');
552-
567+
553568
if (lines.length < 2) break;
554-
569+
555570
const processLine = lines[1].trim();
556571
const parts = processLine.split(/\s+/);
557572
const pid = parseInt(parts[0]);
558573
const ppid = parseInt(parts[1]);
559574
const command = parts.slice(3).join(' '); // Full command line
560-
575+
561576
// Check if this looks like the main VSCode process (not helper processes)
562-
if ((command.includes('Visual Studio Code') || command.includes('Code.app') || command.includes('Electron'))
577+
if ((command.includes('Visual Studio Code') || command.includes('Code.app') || command.includes('Electron'))
563578
&& !command.includes('Code Helper')) {
564579
outputChannel.appendLine(`Found VSCode PID: ${pid}`);
565580
return pid;
566581
}
567-
582+
568583
currentPid = ppid;
569584
if (ppid <= 1) break; // Reached init process
570-
585+
571586
} catch (error) {
572587
break;
573588
}
574589
}
575-
590+
576591
outputChannel.appendLine('Could not find VSCode PID in process tree');
577592
return null;
578-
593+
579594
} catch (error) {
580595
outputChannel.appendLine(`PID discovery error: ${error}`);
581596
return null;

0 commit comments

Comments
 (0)