feat(vscode) Agent Manager (#87)
* Add Agent Manager * Basic Mock UP * Fix Comand naming Ctrl+P Uses Category to group * Move the UI in views * Agent Manager Landing Page * Fix attachment buig * Change Session Name for multi run to incoporate groupSlug * First running UI * Fix Max Model Multi Run * Rework Agent Group detection * ignore false positives with ' ' in it * Simplify Logic * remove unused dropdowns * Clean up * Update Changelog
This commit is contained in:
@@ -3,6 +3,7 @@ import { handleBridgeMessage, type BridgeRequest, type BridgeResponse } from './
|
||||
import { getThemeKindName } from './theme';
|
||||
import type { OpenCodeManager, ConnectionStatus } from './opencode';
|
||||
import { getWebviewShikiThemes } from './shikiThemes';
|
||||
import { getWebviewHtml } from './webviewHtml';
|
||||
|
||||
export class ChatViewProvider implements vscode.WebviewViewProvider {
|
||||
public static readonly viewType = 'openchamber.chatView';
|
||||
@@ -307,153 +308,17 @@ export class ChatViewProvider implements vscode.WebviewViewProvider {
|
||||
}
|
||||
|
||||
private _getHtmlForWebview(webview: vscode.Webview) {
|
||||
const scriptPath = vscode.Uri.joinPath(this._extensionUri, 'dist', 'webview', 'assets', 'index.js');
|
||||
const scriptUri = webview.asWebviewUri(scriptPath);
|
||||
|
||||
const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || '';
|
||||
const themeKind = getThemeKindName(vscode.window.activeColorTheme.kind);
|
||||
// Use cached values which are updated by onStatusChange callback
|
||||
const initialStatus = this._cachedStatus;
|
||||
const cliAvailable = this._openCodeManager?.isCliAvailable() ?? false;
|
||||
|
||||
// Use VS Code CSS variables for proper theme integration
|
||||
// These variables are automatically provided by VS Code to webviews
|
||||
//
|
||||
// Logo geometry matches OpenChamberLogo.tsx:
|
||||
// edge=48, cos30=0.866, sin30=0.5, centerY=50
|
||||
// top=(50, 2), left=(8.432, 26), right=(91.568, 26), center=(50, 50)
|
||||
// bottomLeft=(8.432, 74), bottomRight=(91.568, 74), bottom=(50, 98)
|
||||
// topFaceCenterY = (2 + 26 + 50 + 26) / 4 = 26
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource} 'unsafe-inline'; script-src ${webview.cspSource} 'unsafe-inline' 'unsafe-eval'; connect-src * ws: wss: http: https:; img-src ${webview.cspSource} data: https:; font-src ${webview.cspSource} data:;">
|
||||
<style>
|
||||
html, body, #root { height: 100%; width: 100%; margin: 0; padding: 0; }
|
||||
body {
|
||||
overflow: hidden;
|
||||
background: var(--vscode-editor-background, var(--vscode-sideBar-background));
|
||||
font-family: var(--vscode-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
/* Initial loading screen styles - uses VS Code theme variables */
|
||||
#initial-loading {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
z-index: 9999;
|
||||
background: var(--vscode-editor-background, var(--vscode-sideBar-background));
|
||||
transition: opacity 0.3s ease-out;
|
||||
}
|
||||
#initial-loading.fade-out {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
/* Logo colors use VS Code foreground color */
|
||||
#initial-loading .logo-stroke {
|
||||
stroke: var(--vscode-foreground);
|
||||
}
|
||||
#initial-loading .logo-fill {
|
||||
fill: var(--vscode-foreground);
|
||||
opacity: 0.15;
|
||||
}
|
||||
#initial-loading .logo-fill-solid {
|
||||
fill: var(--vscode-foreground);
|
||||
}
|
||||
#initial-loading .logo-fill-dim {
|
||||
fill: var(--vscode-foreground);
|
||||
opacity: 0.4;
|
||||
}
|
||||
/* Animation on inner logo only, like OpenChamberLogo.tsx */
|
||||
#initial-loading .logo-inner {
|
||||
animation: logoPulse 3s ease-in-out infinite;
|
||||
}
|
||||
#initial-loading .status-text {
|
||||
font-size: 13px;
|
||||
color: var(--vscode-descriptionForeground, var(--vscode-foreground));
|
||||
text-align: center;
|
||||
}
|
||||
#initial-loading .error-text {
|
||||
font-size: 12px;
|
||||
color: var(--vscode-errorForeground, #f48771);
|
||||
text-align: center;
|
||||
max-width: 280px;
|
||||
}
|
||||
@keyframes logoPulse {
|
||||
0%, 100% { opacity: 0.4; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
</style>
|
||||
<title>OpenChamber</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Initial loading screen with simplified OpenChamber logo -->
|
||||
<div id="initial-loading">
|
||||
<svg class="logo" width="70" height="70" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Left face -->
|
||||
<path class="logo-fill logo-stroke" d="M50 50 L8.432 26 L8.432 74 L50 98 Z" stroke-width="2" stroke-linejoin="round"/>
|
||||
<!-- Right face -->
|
||||
<path class="logo-fill logo-stroke" d="M50 50 L91.568 26 L91.568 74 L50 98 Z" stroke-width="2" stroke-linejoin="round"/>
|
||||
<!-- Top face (no fill, stroke only) -->
|
||||
<path class="logo-stroke" d="M50 2 L8.432 26 L50 50 L91.568 26 Z" fill="none" stroke-width="2" stroke-linejoin="round"/>
|
||||
|
||||
<!-- OpenCode logo on top face with pulse animation -->
|
||||
<g class="logo-inner" transform="matrix(0.866, 0.5, -0.866, 0.5, 50, 26) scale(0.75)">
|
||||
<path class="logo-fill-solid" fill-rule="evenodd" clip-rule="evenodd" d="M-16 -20 L16 -20 L16 20 L-16 20 Z M-8 -12 L-8 12 L8 12 L8 -12 Z"/>
|
||||
<path class="logo-fill-dim" d="M-8 -4 L8 -4 L8 12 L-8 12 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
<div class="status-text" id="loading-status">
|
||||
${initialStatus === 'connecting' ? 'Starting OpenCode API…' : initialStatus === 'connected' ? 'Initializing…' : 'Connecting…'}
|
||||
</div>
|
||||
${!cliAvailable ? `<div class="error-text">OpenCode CLI not found. Please install it first.</div>` : ''}
|
||||
</div>
|
||||
|
||||
<div id="root"></div>
|
||||
<script>
|
||||
// Polyfill process for Node.js modules running in browser
|
||||
window.process = window.process || { env: { NODE_ENV: 'production' }, platform: '', version: '', browser: true };
|
||||
|
||||
window.__VSCODE_CONFIG__ = {
|
||||
workspaceFolder: "${workspaceFolder.replace(/\\/g, '\\\\')}",
|
||||
theme: "${themeKind}",
|
||||
connectionStatus: "${initialStatus}",
|
||||
cliAvailable: ${cliAvailable}
|
||||
};
|
||||
window.__OPENCHAMBER_HOME__ = "${workspaceFolder.replace(/\\/g, '\\\\')}";
|
||||
|
||||
// Handle connection status updates to update loading screen
|
||||
window.addEventListener('message', function(event) {
|
||||
var msg = event.data;
|
||||
if (msg && msg.type === 'connectionStatus') {
|
||||
var statusEl = document.getElementById('loading-status');
|
||||
if (statusEl) {
|
||||
if (msg.status === 'connecting') {
|
||||
statusEl.textContent = 'Starting OpenCode API…';
|
||||
statusEl.classList.remove('error-text');
|
||||
} else if (msg.status === 'connected') {
|
||||
statusEl.textContent = 'Connected!';
|
||||
statusEl.classList.remove('error-text');
|
||||
} else if (msg.status === 'error') {
|
||||
statusEl.textContent = msg.error || 'Connection error';
|
||||
statusEl.classList.add('error-text');
|
||||
} else {
|
||||
statusEl.textContent = 'Reconnecting…';
|
||||
statusEl.classList.remove('error-text');
|
||||
}
|
||||
}
|
||||
}
|
||||
return getWebviewHtml({
|
||||
webview,
|
||||
extensionUri: this._extensionUri,
|
||||
workspaceFolder,
|
||||
initialStatus,
|
||||
cliAvailable,
|
||||
});
|
||||
</script>
|
||||
<script type="module" src="${scriptUri}"></script>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user