-
Notifications
You must be signed in to change notification settings - Fork 369
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(auto-edit): add basic webview debug-panel (#7304)
- Integrates the basic auto-edit debug panel. This includes all the infrastructure: - Build config updates. - Command to open the panel. - HTML and CSS files used to render the panel. - Integration with the analytics logger used to pipe auto-edit request updates to the webview. - Actual content will be added to a follow-up PR. - Built on top of #7303
- Loading branch information
1 parent
558db4e
commit 5ee987e
Showing
13 changed files
with
484 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
import * as vscode from 'vscode' | ||
|
||
import { manipulateWebviewHTML } from '../../chat/chat-view/ChatController' | ||
import type { AutoeditDebugMessageFromExtension } from './debug-protocol' | ||
|
||
import { autoeditDebugStore } from './debug-store' | ||
|
||
/** | ||
* A panel that displays debug information about auto-edit requests. | ||
*/ | ||
export class AutoeditDebugPanel { | ||
public static currentPanel: AutoeditDebugPanel | undefined | ||
private static readonly viewType = 'codyAutoeditDebugPanel' | ||
|
||
private readonly panel: vscode.WebviewPanel | ||
private readonly extensionContext: vscode.ExtensionContext | ||
private disposables: vscode.Disposable[] = [] | ||
private updatePending = false | ||
private readonly throttleMs = 500 // Throttle updates to at most once per 500ms | ||
|
||
private constructor(panel: vscode.WebviewPanel, extensionContext: vscode.ExtensionContext) { | ||
this.panel = panel | ||
this.extensionContext = extensionContext | ||
|
||
// Set the webview's initial content | ||
void this.updateContent() | ||
|
||
// Listen for when the panel is disposed | ||
// This happens when the user closes the panel or when the panel is closed programmatically | ||
this.panel.onDidDispose(() => this.dispose(), null, this.disposables) | ||
|
||
// Subscribe to store changes with throttling | ||
this.disposables.push( | ||
autoeditDebugStore.onDidChange(() => { | ||
// If an update is already pending, don't schedule another one | ||
if (!this.updatePending) { | ||
this.updatePending = true | ||
setTimeout(() => { | ||
this.updatePending = false | ||
void this.updateContent() | ||
}, this.throttleMs) | ||
} | ||
}) | ||
) | ||
|
||
// Handle messages from the webview | ||
this.panel.webview.onDidReceiveMessage( | ||
message => { | ||
if (message.type === 'ready') { | ||
// Send the initial data when the webview is ready | ||
void this.updateContent() | ||
} | ||
}, | ||
null, | ||
this.disposables | ||
) | ||
} | ||
|
||
/** | ||
* Type-safe wrapper for sending messages to the webview. | ||
* Ensures that only valid messages defined in the protocol are sent. | ||
*/ | ||
private postMessageToWebview(message: AutoeditDebugMessageFromExtension): void { | ||
this.panel.webview.postMessage(message) | ||
} | ||
|
||
/** | ||
* Shows the debug panel in the editor. | ||
* If the panel already exists, it will be revealed. | ||
*/ | ||
public static showPanel(extensionContext: vscode.ExtensionContext): void { | ||
// Try to reveal existing panel if available | ||
if (AutoeditDebugPanel.currentPanel) { | ||
try { | ||
const viewColumn = AutoeditDebugPanel.currentPanel.panel.viewColumn | ||
AutoeditDebugPanel.currentPanel.panel.reveal(viewColumn, false) | ||
return | ||
} catch (error) { | ||
console.log('Error revealing panel:', error) | ||
AutoeditDebugPanel.currentPanel = undefined | ||
} | ||
} | ||
|
||
// Determine view column for a new panel | ||
let viewColumn = vscode.ViewColumn.Beside | ||
|
||
if (vscode.window.activeTextEditor?.viewColumn === vscode.ViewColumn.One) { | ||
viewColumn = vscode.ViewColumn.Two | ||
} else if (vscode.window.activeTextEditor?.viewColumn) { | ||
viewColumn = vscode.window.activeTextEditor.viewColumn | ||
} | ||
|
||
// Create a new panel | ||
const panel = vscode.window.createWebviewPanel( | ||
AutoeditDebugPanel.viewType, | ||
'Cody Auto-Edit Debug Panel', | ||
viewColumn, | ||
{ | ||
enableScripts: true, | ||
localResourceRoots: [vscode.Uri.joinPath(extensionContext.extensionUri, 'dist')], | ||
} | ||
) | ||
|
||
AutoeditDebugPanel.currentPanel = new AutoeditDebugPanel(panel, extensionContext) | ||
} | ||
|
||
/** | ||
* Updates the content of the panel with the latest auto-edit requests. | ||
*/ | ||
private async updateContent(): Promise<void> { | ||
const entries = autoeditDebugStore.getAutoeditRequestDebugStates() | ||
|
||
// Send the updated entries to the webview using the type-safe protocol | ||
this.postMessageToWebview({ | ||
type: 'updateEntries', | ||
entries, | ||
}) | ||
|
||
// If no HTML content is set yet, set the initial HTML | ||
if (!this.panel.webview.html) { | ||
this.panel.webview.html = await this.getHtmlForWebview(this.panel.webview) | ||
} | ||
} | ||
|
||
/** | ||
* Generates the HTML for the webview panel, including the React app. | ||
*/ | ||
private async getHtmlForWebview(webview: vscode.Webview): Promise<string> { | ||
// Read the compiled HTML file using VS Code's file system API | ||
try { | ||
const htmlPath = vscode.Uri.joinPath( | ||
this.extensionContext.extensionUri, | ||
'dist', | ||
'webviews', | ||
'autoedit-debug.html' | ||
) | ||
const htmlBytes = await vscode.workspace.fs.readFile(htmlPath) | ||
const htmlContent = new TextDecoder('utf-8').decode(htmlBytes) | ||
|
||
// Create URI for the webview resources | ||
const webviewResourcesUri = webview.asWebviewUri( | ||
vscode.Uri.joinPath(this.extensionContext.extensionUri, 'dist', 'webviews') | ||
) | ||
|
||
// Use the shared manipulateWebviewHTML function | ||
return manipulateWebviewHTML(htmlContent, { | ||
cspSource: webview.cspSource, | ||
resources: webviewResourcesUri, | ||
}) | ||
} catch (error) { | ||
console.error('Error getting HTML for webview:', error) | ||
return '' | ||
} | ||
} | ||
|
||
/** | ||
* Dispose of the panel when it's closed. | ||
*/ | ||
public dispose(): void { | ||
AutoeditDebugPanel.currentPanel = undefined | ||
|
||
// Clean up our resources | ||
this.panel.dispose() | ||
|
||
while (this.disposables.length) { | ||
const disposable = this.disposables.pop() | ||
if (disposable) { | ||
disposable.dispose() | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import type { AutoeditRequestDebugState } from './debug-store' | ||
|
||
export type AutoeditDebugMessageFromExtension = { | ||
type: 'updateEntries' | ||
entries: ReadonlyArray<AutoeditRequestDebugState> | ||
} | ||
|
||
export type AutoeditDebugMessageFromWebview = { type: 'ready' } | ||
|
||
export interface VSCodeAutoeditDebugWrapper { | ||
postMessage: (message: AutoeditDebugMessageFromWebview) => void | ||
onMessage: (callback: (message: AutoeditDebugMessageFromExtension) => void) => () => void | ||
} |
Oops, something went wrong.