import * as vscode from 'vscode'; import { MultiStreamService } from './multiStreamService'; import { StreamListDataProvider } from './streamListDataProvider'; import { LogLevel } from './types'; import { LogWebviewProvider } from './logWebviewProvider'; export async function activate(context: vscode.ExtensionContext) { console.log('DSL Agent Logs extension is now active'); // 设置 context key 以显示面板 await vscode.commands.executeCommand('setContext', 'dsl-agent-logs.enabled', true); const multiStreamService = new MultiStreamService(); context.subscriptions.push({ dispose: () => multiStreamService.dispose() }); const streamListDataProvider = new StreamListDataProvider(multiStreamService); const webviewProvider = new LogWebviewProvider(context.extensionUri, multiStreamService); const webviewViewDisposable = vscode.window.registerWebviewViewProvider( 'dsl-agent-logs-view', webviewProvider, { webviewOptions: { retainContextWhenHidden: true } } ); const streamListView = vscode.window.createTreeView('dsl-agent-logs-streams', { treeDataProvider: streamListDataProvider, showCollapseAll: false }); const updateFilterContext = () => { const activeStreamId = multiStreamService.getActiveStreamId(); const filter = activeStreamId ? multiStreamService.getFilter(activeStreamId) : {}; vscode.commands.executeCommand('setContext', 'dsl-agent-logs.hasLevelFilter', !!filter.level); vscode.commands.executeCommand('setContext', 'dsl-agent-logs.hasSearchFilter', !!filter.searchText); }; const updateStreamSelection = () => { setTimeout(() => { const activeItem = streamListDataProvider.getActiveItem(); if (activeItem) { streamListView.reveal(activeItem, { select: true, focus: false }).then( () => { }, () => { } ); } }, 100); }; multiStreamService.onDidChangeActiveStream(() => { updateFilterContext(); updateStreamSelection(); }); multiStreamService.onDidChangeStreams(() => { updateStreamSelection(); }); updateFilterContext(); context.subscriptions.push(webviewViewDisposable); context.subscriptions.push(webviewProvider); context.subscriptions.push(streamListView); context.subscriptions.push( vscode.commands.registerCommand('dsl-agent-logs.activate', async () => { await vscode.commands.executeCommand('icube.dslAgent.startGlobalLogStream'); }) ); context.subscriptions.push( vscode.commands.registerCommand('dsl-agent-logs.selectStream', (streamId: string) => { multiStreamService.setActiveStreamId(streamId); }) ); context.subscriptions.push( vscode.commands.registerCommand('dsl-agent-logs.removeStream', async (node: any) => { if (!node || !node.stream) { return; } const stream = node.stream; await multiStreamService.removeStream(stream.id); }) ); context.subscriptions.push( vscode.commands.registerCommand('dsl-agent-logs.enableStream', async (node: any) => { if (!node || !node.stream) { return; } const stream = node.stream; await multiStreamService.toggleStream(stream.id, true); }) ); context.subscriptions.push( vscode.commands.registerCommand('dsl-agent-logs.disableStream', async (node: any) => { if (!node || !node.stream) { return; } const stream = node.stream; await multiStreamService.toggleStream(stream.id, false); }) ); context.subscriptions.push( vscode.commands.registerCommand('dsl-agent-logs.clear', () => { const activeStreamId = multiStreamService.getActiveStreamId(); if (!activeStreamId) { vscode.window.showWarningMessage('There is no stream'); return; } multiStreamService.clearAllLogs(activeStreamId); }) ); context.subscriptions.push( vscode.commands.registerCommand('dsl-agent-logs.export', async () => { const activeStreamId = multiStreamService.getActiveStreamId(); if (!activeStreamId) { vscode.window.showWarningMessage('There is no stream'); return; } const logs = multiStreamService.getLogsByStream(activeStreamId); if (logs.length === 0) { vscode.window.showInformationMessage('No logs to export'); return; } const streams = multiStreamService.getStreams(); const stream = streams.find(s => s.id === activeStreamId); const streamName = stream?.name || activeStreamId; const content = logs.map((log: any) => log.rawText).join('\n'); const uri = await vscode.window.showSaveDialog({ defaultUri: vscode.Uri.file(`dsl-agent-logs-${streamName}.log`), filters: { 'Log Files': ['log', 'txt'] } }); if (uri) { const encoder = new TextEncoder(); await vscode.workspace.fs.writeFile(uri, encoder.encode(content)); vscode.window.showInformationMessage(`Logs exported to ${uri.fsPath}`); } }) ); context.subscriptions.push( vscode.commands.registerCommand('dsl-agent-logs.filterByLevel', async () => { const activeStreamId = multiStreamService.getActiveStreamId(); if (!activeStreamId) { return; } const currentFilter = multiStreamService.getFilter(activeStreamId); const levels = [ { label: '$(error) ERROR', level: LogLevel.ERROR, description: 'Show only error logs' }, { label: '$(warning) WARN', level: LogLevel.WARN, description: 'Show only warning logs' }, { label: '$(info) INFO', level: LogLevel.INFO, description: 'Show only info logs' }, { label: '$(debug) DEBUG', level: LogLevel.DEBUG, description: 'Show only debug logs' } ]; const selected = await vscode.window.showQuickPick(levels, { placeHolder: 'Select log level to filter' }); if (selected) { multiStreamService.setFilter(activeStreamId, { level: selected.level, searchText: currentFilter.searchText }); updateFilterContext(); } }) ); context.subscriptions.push( vscode.commands.registerCommand('dsl-agent-logs.clearLevelFilter', () => { const activeStreamId = multiStreamService.getActiveStreamId(); if (!activeStreamId) { return; } const currentFilter = multiStreamService.getFilter(activeStreamId); multiStreamService.setFilter(activeStreamId, { searchText: currentFilter.searchText }); updateFilterContext(); }) ); context.subscriptions.push( vscode.commands.registerCommand('dsl-agent-logs.search', async () => { const activeStreamId = multiStreamService.getActiveStreamId(); if (!activeStreamId) { return; } const currentFilter = multiStreamService.getFilter(activeStreamId); const searchText = await vscode.window.showInputBox({ prompt: 'Enter search text', placeHolder: 'Search in logs...' }); if (searchText !== undefined && searchText !== '') { multiStreamService.setFilter(activeStreamId, { level: currentFilter.level, searchText }); updateFilterContext(); } }) ); context.subscriptions.push( vscode.commands.registerCommand('dsl-agent-logs.clearSearchFilter', () => { const activeStreamId = multiStreamService.getActiveStreamId(); if (!activeStreamId) { return; } const currentFilter = multiStreamService.getFilter(activeStreamId); multiStreamService.setFilter(activeStreamId, { level: currentFilter.level }); updateFilterContext(); }) ); context.subscriptions.push( vscode.commands.registerCommand('dsl-agent-logs.addLogEntry', (streamId: string, streamName: string, logEntry: any) => { const normalizedEntry = { ...logEntry, timestamp: typeof logEntry.timestamp === 'string' ? new Date(logEntry.timestamp) : logEntry.timestamp, level: logEntry.level as any }; multiStreamService.addLogEntry(streamId, streamName, normalizedEntry); } ) ); const api = { addLogEntry: multiStreamService.addLogEntry.bind(multiStreamService), removeStream: multiStreamService.removeStream.bind(multiStreamService), toggleStream: multiStreamService.toggleStream.bind(multiStreamService), getStreams: multiStreamService.getStreams.bind(multiStreamService), clearAllLogs: multiStreamService.clearAllLogs.bind(multiStreamService) }; return api; } export async function deactivate() { console.log('DSL Agent Logs extension is now deactivated'); try { await vscode.commands.executeCommand('icube.dslAgent.stopGlobalLogStream'); } catch (error) { console.error('[DSL Agent Logs] Failed to stop log stream:', error); } }