/** * @file Main extension file for Claude Code Agent Monitor VSCode extension * Sets up the extension, registers commands, and manages the status bar item. * Implements a dynamic dashboard view that checks for active servers on ports 5173 and 4820. * Provides real-time status updates in the sidebar and status bar with background polling. * * @author Nguyễn Ngọc Trí Vĩ */ const vscode = require("vscode"); const http = require("http"); const { DashboardWebviewProvider } = require("./sidebar"); let statusBarItem; let outputChannel; function activate(context) { outputChannel = vscode.window.createOutputChannel("Claude Code Monitor"); outputChannel.appendLine("[activate] " + new Date().toISOString()); context.subscriptions.push(outputChannel); const statusProvider = new DashboardWebviewProvider(context, outputChannel); context.subscriptions.push( vscode.window.registerWebviewViewProvider("claude-code-monitor-view", statusProvider, { webviewOptions: { retainContextWhenHidden: true }, }) ); statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100); statusBarItem.command = "claude-code-agent-monitor.openDashboard"; context.subscriptions.push(statusBarItem); updateStatusBar(); const statusInterval = setInterval(() => { updateStatusBar(); }, 5000); // Auto-refresh every 5 seconds let openDashboard = vscode.commands.registerCommand( "claude-code-agent-monitor.openDashboard", async (target) => { const panel = vscode.window.createWebviewPanel( "agentMonitor", "Claude Code Agent Monitor", vscode.ViewColumn.One, { enableScripts: true, retainContextWhenHidden: true } ); const updateWebview = async () => { const ports = [5173, 4820]; let activePort = null; for (const port of ports) { if (await checkPort(port)) { activePort = port; break; } } if (activePort) { let suffix = ""; if (target) { suffix = target.includes("-") ? `/sessions/${target}` : `/${target}`; } panel.webview.html = getDashboardHtml(activePort, suffix); } else { panel.webview.html = getErrorHtml(); } }; panel.webview.onDidReceiveMessage((m) => { if (m.command === "retry") updateWebview(); }); await updateWebview(); } ); let openInBrowser = vscode.commands.registerCommand( "claude-code-agent-monitor.openInBrowser", async () => { const isDevUp = await checkPort(5173); const url = isDevUp ? "http://localhost:5173" : "http://localhost:4820"; vscode.env.openExternal(vscode.Uri.parse(url)); } ); let refreshStatus = vscode.commands.registerCommand( "claude-code-agent-monitor.refreshStatus", () => { statusProvider.refresh(); updateStatusBar(); vscode.window.showInformationMessage("Claude Code Monitor refreshed."); } ); let clearHistory = vscode.commands.registerCommand( "claude-code-agent-monitor.clearHistory", async () => { if ( (await vscode.window.showWarningMessage("Clear all history?", { modal: true }, "Yes")) === "Yes" ) { try { const res = await request("DELETE", 4820, "/api/sessions"); if (res.statusCode === 200) { statusProvider.refresh(); updateStatusBar(); vscode.window.showInformationMessage("History cleared."); } } catch (e) { vscode.window.showErrorMessage("Failed to clear history."); } } } ); context.subscriptions.push(openDashboard, openInBrowser, refreshStatus, clearHistory); context.subscriptions.push({ dispose: () => clearInterval(statusInterval) }); } async function updateStatusBar() { try { const stats = await fetchJson(4820, "/api/stats"); if (stats) { statusBarItem.text = `$(pulse) Claude: ${stats.sessions || 0}s | ${stats.agents || 0}a`; statusBarItem.show(); } else statusBarItem.hide(); } catch (e) { statusBarItem.hide(); } } function checkPort(port) { return new Promise((r) => { const req = http.get({ hostname: "localhost", port, path: "/", timeout: 500 }, (res) => { r(true); res.resume(); }); req.on("error", () => r(false)); }); } function fetchJson(port, path) { return new Promise((res, rej) => { const req = http.get({ hostname: "localhost", port, path, timeout: 800 }, (r) => { let d = ""; r.on("data", (c) => (d += c)); r.on("end", () => { try { res(JSON.parse(d)); } catch (e) { rej(e); } }); }); req.on("error", rej); }); } function request(method, port, path) { return new Promise((res, rej) => { const req = http.request({ hostname: "localhost", port, path, method }, res); req.on("error", rej); req.end(); }); } function getDashboardHtml(port, suffix) { return `
Live Dashboard: ${suffix || "/"}
localhost:${port}
`; } function getErrorHtml() { return `

Dashboard Offline

Unable to connect to the Claude Code Monitor server

Quick Setup Guide

Initialize Repository
git clone https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git cd Claude-Code-Agent-Monitor npm run setup
Launch Dashboard
npm run dev

Troubleshooting

Ensure no other services are occupying ports 5173 or 4820. If the problem persists, check the documentation.

View Documentation
`; } function deactivate() { if (statusBarItem) statusBarItem.dispose(); } module.exports = { activate, deactivate };