@@ -4,12 +4,15 @@ import {
44 getCurrentAgentId ,
55 AgentConfig ,
66 checkForRegistryUpdates ,
7+ checkAllBuiltInAvailability ,
8+ AvailabilityStatus ,
79} from "./agentRegistry" ;
810
911export class SettingsViewProvider implements vscode . WebviewViewProvider {
1012 public static readonly viewType = "symposium.settingsView" ;
1113 #view?: vscode . WebviewView ;
1214 #extensionUri: vscode . Uri ;
15+ #availabilityCache: Map < string , AvailabilityStatus > = new Map ( ) ;
1316
1417 constructor ( extensionUri : vscode . Uri ) {
1518 this . #extensionUri = extensionUri ;
@@ -22,6 +25,15 @@ export class SettingsViewProvider implements vscode.WebviewViewProvider {
2225 } ) ;
2326 }
2427
28+ /**
29+ * Refresh availability checks for built-in agents.
30+ * Call this at activation and when the settings panel becomes visible.
31+ */
32+ async refreshAvailability ( ) : Promise < void > {
33+ this . #availabilityCache = await checkAllBuiltInAvailability ( ) ;
34+ this . #sendConfiguration( ) ;
35+ }
36+
2537 public resolveWebviewView (
2638 webviewView : vscode . WebviewView ,
2739 context : vscode . WebviewViewResolveContext ,
@@ -39,8 +51,8 @@ export class SettingsViewProvider implements vscode.WebviewViewProvider {
3951 // Handle webview visibility changes
4052 webviewView . onDidChangeVisibility ( ( ) => {
4153 if ( webviewView . visible ) {
42- // Refresh configuration when view becomes visible
43- this . #sendConfiguration ( ) ;
54+ // Refresh availability checks and configuration when view becomes visible
55+ this . refreshAvailability ( ) ;
4456 }
4557 } ) ;
4658
@@ -171,12 +183,18 @@ export class SettingsViewProvider implements vscode.WebviewViewProvider {
171183 const config = vscode . workspace . getConfiguration ( "symposium" ) ;
172184 const bypassList = config . get < string [ ] > ( "bypassPermissions" , [ ] ) ;
173185
174- // Get effective agents (built-ins + settings) and merge bypass settings
186+ // Get effective agents (built-ins + settings) and merge bypass/availability settings
175187 const effectiveAgents = getEffectiveAgents ( ) ;
176- const agents = effectiveAgents . map ( ( agent ) => ( {
177- ...agent ,
178- bypassPermissions : bypassList . includes ( agent . id ) ,
179- } ) ) ;
188+ const agents = effectiveAgents . map ( ( agent ) => {
189+ const availability = this . #availabilityCache. get ( agent . id ) ;
190+ return {
191+ ...agent ,
192+ bypassPermissions : bypassList . includes ( agent . id ) ,
193+ // Only built-in agents have availability checks (registry agents are always available)
194+ disabled : availability ? ! availability . available : false ,
195+ disabledReason : availability ?. reason ,
196+ } ;
197+ } ) ;
180198
181199 const currentAgentId = getCurrentAgentId ( ) ;
182200 const requireModifierToSend = config . get < boolean > (
@@ -265,6 +283,18 @@ export class SettingsViewProvider implements vscode.WebviewViewProvider {
265283 .badge.bypass:hover {
266284 opacity: 0.8;
267285 }
286+ .agent-item.disabled {
287+ opacity: 0.5;
288+ cursor: default;
289+ }
290+ .agent-item.disabled:hover {
291+ background: var(--vscode-list-inactiveSelectionBackground);
292+ }
293+ .disabled-reason {
294+ font-size: 11px;
295+ color: var(--vscode-descriptionForeground);
296+ font-style: italic;
297+ }
268298 .toggle {
269299 font-size: 11px;
270300 color: var(--vscode-descriptionForeground);
@@ -376,44 +406,52 @@ export class SettingsViewProvider implements vscode.WebviewViewProvider {
376406 for (const agent of agents) {
377407 const displayName = agent.name || agent.id;
378408 const isActive = agent.id === currentAgentId;
409+ const isDisabled = agent.disabled;
379410
380411 const item = document.createElement('div');
381- item.className = 'agent-item' + (isActive ? ' active' : '');
412+ item.className = 'agent-item' + (isActive ? ' active' : '') + (isDisabled ? ' disabled' : '') ;
382413
383414 const badges = [];
384415 if (isActive) {
385416 badges.push('<span class="badge">Active</span>');
386417 }
387- if (agent.bypassPermissions) {
418+ if (agent.bypassPermissions && !isDisabled ) {
388419 badges.push('<span class="badge bypass" title="Click to disable bypass permissions">Bypass Permissions</span>');
389420 }
390421
391422 const versionHtml = agent.version
392423 ? \`<span class="agent-version">v\${agent.version}</span>\`
393424 : '';
394425
426+ const disabledHtml = isDisabled && agent.disabledReason
427+ ? \`<span class="disabled-reason">(\${agent.disabledReason})</span>\`
428+ : '';
429+
395430 item.innerHTML = \`
396431 <div class="agent-name">
397432 <span>\${displayName}</span>
398433 \${versionHtml}
434+ \${disabledHtml}
399435 </div>
400436 <div class="badges">\${badges.join('')}</div>
401437 \`;
402438
403- // Handle clicking on the agent name (switch agent)
404- const nameSpan = item.querySelector('.agent-name');
405- nameSpan.onclick = (e) => {
406- e.stopPropagation();
407- vscode.postMessage({ type: 'set-current-agent', agentId: agent.id, agentName: displayName });
408- };
409-
410- // Handle clicking on the bypass badge (toggle bypass)
411- const bypassBadge = item.querySelector('.badge.bypass');
412- if (bypassBadge) {
413- bypassBadge.onclick = (e) => {
439+ // Handle clicking on the agent name (switch agent) - only if not disabled
440+ if (!isDisabled) {
441+ const nameSpan = item.querySelector('.agent-name');
442+ nameSpan.onclick = (e) => {
414443 e.stopPropagation();
415- vscode.postMessage({ type: 'toggle-bypass-permissions ', agentId: agent.id });
444+ vscode.postMessage({ type: 'set-current-agent ', agentId: agent.id, agentName: displayName });
416445 };
446+
447+ // Handle clicking on the bypass badge (toggle bypass)
448+ const bypassBadge = item.querySelector('.badge.bypass');
449+ if (bypassBadge) {
450+ bypassBadge.onclick = (e) => {
451+ e.stopPropagation();
452+ vscode.postMessage({ type: 'toggle-bypass-permissions', agentId: agent.id });
453+ };
454+ }
417455 }
418456
419457 list.appendChild(item);
0 commit comments