Skip to content

Commit 7083a23

Browse files
Copilotianjennings
andauthored
Fix IDE preview not showing in VSCode extension (#29)
* Initial plan * Fix VSCode extension preview not showing: process recent files on startup, add registration heartbeat, fix WebSocket protocol Co-authored-by: ianjennings <318295+ianjennings@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ianjennings <318295+ianjennings@users.noreply.github.com>
1 parent e7502b6 commit 7083a23

1 file changed

Lines changed: 23 additions & 4 deletions

File tree

src/extension.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const previewWatchers: Map<string, vscode.FileSystemWatcher> = new Map();
1717
// Local HTTP server for receiving session notifications from SDK
1818
let httpServer: http.Server | undefined;
1919
let serverPort: number | undefined;
20+
let registrationHeartbeat: ReturnType<typeof setInterval> | undefined;
2021

2122
// Path to the TestDriver directory (used for IPC between SDK and extension)
2223
const SESSION_DIR = path.join(os.homedir(), '.testdriver');
@@ -201,6 +202,9 @@ function startHttpServer(context: vscode.ExtensionContext) {
201202
serverPort = address.port;
202203
console.log(`TestDriver extension server listening on port ${serverPort}`);
203204
registerInstance();
205+
// Refresh the registration timestamp every 30 seconds so the SDK
206+
// never considers this instance stale (SDK threshold is 60 seconds).
207+
registrationHeartbeat = setInterval(registerInstance, 30000);
204208
}
205209
});
206210

@@ -291,17 +295,26 @@ function setupPreviewWatchers(context: vscode.ExtensionContext) {
291295
previewWatchers.set(folder.uri.fsPath, watcher);
292296
context.subscriptions.push(watcher);
293297

294-
cleanupStalePreviewFiles(previewsDir);
298+
processOrCleanupPreviewFiles(context, previewsDir);
295299
}
296300
}
297301

298-
function cleanupStalePreviewFiles(previewsDir: string) {
302+
// Process recent preview files (written within the last 30 seconds) and delete stale ones.
303+
// This handles the race condition where a file is written before the watcher is fully active.
304+
function processOrCleanupPreviewFiles(context: vscode.ExtensionContext, previewsDir: string) {
305+
const RECENT_THRESHOLD_MS = 30000;
299306
try {
300307
const files = fs.readdirSync(previewsDir);
301308
for (const file of files) {
302309
if (file.endsWith('.json')) {
310+
const filePath = path.join(previewsDir, file);
303311
try {
304-
fs.unlinkSync(path.join(previewsDir, file));
312+
const stats = fs.statSync(filePath);
313+
if (Date.now() - stats.mtimeMs < RECENT_THRESHOLD_MS) {
314+
handlePreviewFile(context, vscode.Uri.file(filePath));
315+
} else {
316+
fs.unlinkSync(filePath);
317+
}
305318
} catch { /* ignore */ }
306319
}
307320
}
@@ -425,7 +438,8 @@ function connectToWebSocket(debuggerUrl: string, panel: vscode.WebviewPanel, ses
425438

426439
try {
427440
const url = new URL(debuggerUrl);
428-
const wsUrl = `ws://${url.host}`;
441+
const wsProtocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
442+
const wsUrl = `${wsProtocol}//${url.host}`;
429443
const ws = new WebSocket(wsUrl);
430444
websocketConnections.set(sessionId, ws);
431445

@@ -706,6 +720,11 @@ function getDebuggerHtml(debuggerUrl: string, encodedData: string): string {
706720
export function deactivate() {
707721
closeAllDebuggerPanels();
708722

723+
if (registrationHeartbeat) {
724+
clearInterval(registrationHeartbeat);
725+
registrationHeartbeat = undefined;
726+
}
727+
709728
if (httpServer) {
710729
httpServer.close();
711730
httpServer = undefined;

0 commit comments

Comments
 (0)