Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/vs/sessions/AI_CUSTOMIZATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ The management editor opens as a compact modal editor. The modal title and welco

The first sidebar entry is a static `Overview` navigation item. It is styled like the other sidebar labels and does not mirror the active harness label; harness identity is represented by the modal title and welcome heading instead.

Dense management-editor affordances, including group and tool-list chevrons, use compact codicon glyphs and the compact codicon font-size token.

The Tools section can browse the Marketplace in the core workbench, where extension gallery browsing and installation are available. The Sessions window hides Tools Marketplace browsing and only shows the tool enablement list.

The Plugins section keeps plugin maintenance close to plugin creation: its compact toolbar includes an accessible Update Plugins button beside Create Plugin. This invokes the shared `workbench.agentPlugins.checkForUpdates` command, matching the Update Plugins action in the installed Agent Plugins view title; holding Alt/Shift on that view-title action invokes the existing force-update command. Update actions are disabled while the shared operation is running. Progress is shown while checking, followed by a notification listing updated or failed plugins, or confirming that plugins are already up to date.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export class ToggleChatSpeechToTextAction extends Action2 {
id: ToggleChatSpeechToTextAction.ID,
title: localize2('chat.speechToText.start', "Dictate (Speech to Text)"),
category: CHAT_CATEGORY,
icon: Codicon.mic,
icon: Codicon.micCompact,
f1: false,
toggled: {
condition: ChatContextKeys.speechToTextRecording,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { IAgentHostSessionWorkingDirectoryResolver } from './agentHostSessionWor
import { IAgentHostNewSessionFolderService } from './agentHostNewSessionFolderService.js';
import { IAgentHostUntitledProvisionalSessionService } from './agentHostUntitledProvisionalSessionService.js';
import { toAgentHostBackendSessionUri } from './agentHostSessionUri.js';
import { getCompactCodicon } from '../../chatIcons.js';

const FILTER_THRESHOLD = 10;

Expand Down Expand Up @@ -544,7 +545,7 @@ export class AgentHostChatInputPicker extends Disposable {

const icon = getConfigIcon(this._property, value);
if (icon) {
dom.append(trigger, renderIcon(icon));
dom.append(trigger, renderIcon(getCompactCodicon(icon)));
}
// Mirror the sessions-side picker: elevated approval levels get themed colors.
if (this._property === SessionConfigKey.AutoApprove) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export class AgentHostFolderPickerActionItem extends ChatInputPickerActionViewIt
const label = folder ? folder.name : (selected ? basename(selected) : localize('agentHost.selectFolder', "Folder"));
dom.reset(
element,
...renderLabelWithIcons(`$(folder)`),
...renderLabelWithIcons(`$(folder-compact)`),
dom.$('span.chat-input-picker-label', undefined, label),
);
// Set the aria label after the visible text is in place: the base class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
}

.codicon {
font-size: 12px;
font-size: var(--vscode-codiconFontSize-compact);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
}

.unified-send-button .codicon {
font-size: 14px !important;
font-size: var(--vscode-codiconFontSize-compact) !important;
color: var(--vscode-button-foreground) !important;
}

Expand Down Expand Up @@ -149,7 +149,7 @@
}

.unified-quick-access-pr-badge .codicon {
font-size: 12px;
font-size: var(--vscode-codiconFontSize-compact);
}

/* Action text styling (e.g., "Run 'zsh' command?") */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
align-items: center;
margin-left: 4px;
color: var(--vscode-charts-blue);
font-size: 12px;
font-size: var(--vscode-codiconFontSize-compact);
pointer-events: none;

&.visible {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ class GroupHeaderRenderer implements IListRenderer<IGroupHeaderEntry, IGroupHead

// Chevron
templateData.chevron.className = 'group-chevron';
templateData.chevron.classList.add(...ThemeIcon.asClassNameArray(element.collapsed ? Codicon.chevronRight : Codicon.chevronDown));
templateData.chevron.classList.add(...ThemeIcon.asClassNameArray(element.collapsed ? Codicon.chevronRightCompact : Codicon.chevronDownCompact));

// Icon
templateData.icon.className = 'group-icon';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1443,7 +1443,7 @@ export class AICustomizationManagementEditor extends EditorPane {
const setGroupCollapsed = (collapsed: boolean): void => {
groupItems.style.display = collapsed ? 'none' : '';
chevron.className = 'group-chevron';
chevron.classList.add(...ThemeIcon.asClassNameArray(collapsed ? Codicon.chevronRight : Codicon.chevronDown));
chevron.classList.add(...ThemeIcon.asClassNameArray(collapsed ? Codicon.chevronRightCompact : Codicon.chevronDownCompact));
groupToggle.setAttribute('aria-expanded', String(!collapsed));
this.migrationListScrollable?.scanDomNode();
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class CustomizationGroupHeaderRenderer<T extends ICustomizationGroupHeade
templateData.elementDisposables.clear();

templateData.chevron.className = 'group-chevron';
templateData.chevron.classList.add(...ThemeIcon.asClassNameArray(element.collapsed ? Codicon.chevronRight : Codicon.chevronDown));
templateData.chevron.classList.add(...ThemeIcon.asClassNameArray(element.collapsed ? Codicon.chevronRightCompact : Codicon.chevronDownCompact));

templateData.icon.className = 'group-icon';
templateData.icon.classList.add(...ThemeIcon.asClassNameArray(element.icon));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@
}

.ai-customization-management-editor .harness-dropdown-chevron {
font-size: 12px;
font-size: var(--vscode-codiconFontSize-compact);
flex-shrink: 0;
opacity: 0.7;
}
Expand Down Expand Up @@ -461,7 +461,7 @@
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-size: var(--vscode-codiconFontSize-compact);
opacity: 0.7;
order: 10;
margin-left: auto;
Expand Down Expand Up @@ -1243,7 +1243,7 @@ per-word capitalization does not survive translation. */
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-size: var(--vscode-codiconFontSize-compact);
color: var(--vscode-foreground);
opacity: 0.7;
cursor: pointer;
Expand Down Expand Up @@ -1456,7 +1456,7 @@ per-word capitalization does not survive translation. */
}

.ai-customization-management-editor .ai-customization-embedded-detail .embedded-detail-scope .codicon {
font-size: 12px;
font-size: var(--vscode-codiconFontSize-compact);
}

.ai-customization-management-editor .ai-customization-embedded-detail .embedded-detail-description {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -676,8 +676,8 @@ export class ToolsListWidget extends Disposable {
this._rowStore.add(autorun(reader => {
const expanded = vm.forceExpanded || this._expanded.read(reader).has(ts.id);
group.style.display = expanded ? '' : 'none';
chevron.classList.toggle('codicon-chevron-down', expanded);
chevron.classList.toggle('codicon-chevron-right', !expanded);
chevron.classList.toggle('codicon-chevron-down-compact', expanded);
chevron.classList.toggle('codicon-chevron-right-compact', !expanded);
row.setAttribute('aria-expanded', String(expanded));
this._treeScrollable.scanDomNode();
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ export class FileAttachmentWidget extends AbstractChatAttachmentWidget {
}

private renderOmittedWarning(friendlyName: string, ariaLabel: string) {
const pillIcon = dom.$('div.chat-attached-context-pill', {}, dom.$('span.codicon.codicon-warning'));
const pillIcon = dom.$('div.chat-attached-context-pill', {}, dom.$('span.codicon.codicon-warning-compact'));
const textLabel = dom.$('span.chat-attached-context-custom-text', {}, friendlyName);
this.element.appendChild(pillIcon);
this.element.appendChild(textLabel);
Expand Down Expand Up @@ -547,7 +547,7 @@ export class ImageAttachmentWidget extends AbstractChatAttachmentWidget {

const imageElements = this._register(new MutableDisposable<IDisposable>());
const renderImageElements = (buffer: Uint8Array) => {
imageElements.value = createImageElements(resource, attachment.name, fullName, this.element, buffer, attachment.id, this.hoverService, ariaLabel, currentLanguageModelName, clickHandler, this.currentLanguageModel, omittedState);
imageElements.value = createImageElements(resource, attachment.name, fullName, this.element, buffer, attachment.id, this.hoverService, ariaLabel, currentLanguageModelName, clickHandler, this.currentLanguageModel, omittedState, options.isCurrentInput === true);
// createImageElements resets the label; restore the deletion hint after each render.
this.element.ariaLabel = this.appendDeletionHint(ariaLabel);
};
Expand Down Expand Up @@ -692,7 +692,8 @@ function createImageElements(resource: URI | undefined, name: string, fullName:
currentLanguageModelName: string | undefined,
clickHandler: () => void,
currentLanguageModel?: ILanguageModelChatMetadataAndIdentifier,
omittedState?: OmittedState): IDisposable {
omittedState?: OmittedState,
useCompactWarningIcon = false): IDisposable {

const disposable = new DisposableStore();
if (omittedState === OmittedState.Partial) {
Expand All @@ -705,8 +706,14 @@ function createImageElements(resource: URI | undefined, name: string, fullName:
if (resource) {
element.style.cursor = 'pointer';
}
const createPillIcon = (icon: ThemeIcon) => {
const iconElement = dom.$('span');
iconElement.classList.add(...ThemeIcon.asClassNameArray(icon));
return dom.$('div.chat-attached-context-pill', {}, iconElement);
};
const supportsVision = modelSupportsVision(currentLanguageModel);
const pillIcon = dom.$('div.chat-attached-context-pill', {}, dom.$(supportsVision ? 'span.codicon.codicon-file-media' : 'span.codicon.codicon-warning'));
const warningIcon = useCompactWarningIcon ? Codicon.warningCompact : Codicon.warning;
const pillIcon = createPillIcon(supportsVision ? Codicon.fileMediaCompact : warningIcon);
const textLabel = dom.$('span.chat-attached-context-custom-text', {}, name);
element.appendChild(pillIcon);
element.appendChild(textLabel);
Expand Down Expand Up @@ -741,7 +748,7 @@ function createImageElements(resource: URI | undefined, name: string, fullName:
} else {
const onImageFailed = () => {
// reset to original icon on error or invalid image
const pillIcon = dom.$('div.chat-attached-context-pill', {}, dom.$('span.codicon.codicon-file-media'));
const pillIcon = createPillIcon(Codicon.fileMediaCompact);
replacePill(pillIcon);
};
const hoverFullName = omittedState === OmittedState.Partial ? localize('chat.imageAttachmentWarning', "This GIF was partially omitted - current frame will be sent.") : fullName;
Expand Down Expand Up @@ -1241,7 +1248,7 @@ export class NotebookCellOutputChatAttachmentWidget extends AbstractChatAttachme
resource: URI,
attachment: INotebookOutputVariableEntry,
currentLanguageModel: ILanguageModelChatMetadataAndIdentifier | undefined,
options: { shouldFocusClearButton: boolean; supportsDeletion: boolean },
options: { shouldFocusClearButton: boolean; supportsDeletion: boolean; isCurrentInput?: boolean },
container: HTMLElement,
contextResourceLabels: ResourceLabels,
@ICommandService commandService: ICommandService,
Expand All @@ -1262,7 +1269,7 @@ export class NotebookCellOutputChatAttachmentWidget extends AbstractChatAttachme
case 'image/png':
case 'image/jpeg':
case 'image/svg': {
this.renderImageOutput(resource, attachment);
this.renderImageOutput(resource, attachment, options.isCurrentInput === true);
break;
}
default: {
Expand Down Expand Up @@ -1298,7 +1305,7 @@ export class NotebookCellOutputChatAttachmentWidget extends AbstractChatAttachme
this.element.ariaLabel = this.appendDeletionHint(this.getAriaLabel(attachment));
this.label.setFile(resource, { hidePath: true, icon: ThemeIcon.fromId('output') });
}
private renderImageOutput(resource: URI, attachment: INotebookOutputVariableEntry) {
private renderImageOutput(resource: URI, attachment: INotebookOutputVariableEntry, useCompactWarningIcon: boolean) {
let ariaLabel: string;
if (attachment.omittedState === OmittedState.Full) {
ariaLabel = localize('chat.omittedNotebookImageAttachment', "Omitted this Notebook ouput: {0}", attachment.name);
Expand All @@ -1311,7 +1318,7 @@ export class NotebookCellOutputChatAttachmentWidget extends AbstractChatAttachme
const clickHandler = async () => await this.openResource(resource, { editorOptions: { preserveFocus: true } }, false, undefined);
const currentLanguageModelName = this.currentLanguageModel ? this.languageModelsService.lookupLanguageModel(this.currentLanguageModel.identifier)?.name ?? this.currentLanguageModel.identifier : undefined;
const buffer = this.getOutputItem(resource, attachment)?.data.buffer ?? new Uint8Array();
this._register(createImageElements(resource, attachment.name, attachment.name, this.element, buffer, attachment.id, this.hoverService, ariaLabel, currentLanguageModelName, clickHandler, this.currentLanguageModel, attachment.omittedState));
this._register(createImageElements(resource, attachment.name, attachment.name, this.element, buffer, attachment.id, this.hoverService, ariaLabel, currentLanguageModelName, clickHandler, this.currentLanguageModel, attachment.omittedState, useCompactWarningIcon));
this.element.ariaLabel = this.appendDeletionHint(ariaLabel);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { IHoverService } from '../../../../../platform/hover/browser/hover.js';
import { ILabelService } from '../../../../../platform/label/common/label.js';
import { IOpenerService } from '../../../../../platform/opener/common/opener.js';
import { IChatDebugCustomizationLogEntry, IChatDebugEventCustomizationSummaryContent, IChatDebugEventFileListContent } from '../../common/chatDebugService.js';
import { getCompactCodicon } from '../chatIcons.js';
import { InlineAnchorWidget } from '../widget/chatContentParts/chatInlineAnchorWidget.js';
import { setupCollapsibleToggle } from './chatDebugCollapsible.js';

Expand Down Expand Up @@ -189,7 +190,7 @@ export function renderCustomizationDiscoveryContent(content: IChatDebugEventFile

for (const file of files) {
const row = DOM.append(listEl, $('div.chat-debug-file-list-row'));
DOM.append(row, $(`span.chat-debug-file-list-icon${ThemeIcon.asCSSSelector(Codicon.check)}`));
DOM.append(row, $(`span.chat-debug-file-list-icon${ThemeIcon.asCSSSelector(Codicon.checkCompact)}`));
row.appendChild(createInlineFileLink(file.uri, file.name ?? file.uri.path, FileKind.FILE, openerService, modelService, languageService, hoverService, labelService, disposables));
const relativeLabel = labelService.getUriLabel(file.uri, { relative: true });
row.setAttribute('aria-label', relativeLabel);
Expand Down Expand Up @@ -231,7 +232,7 @@ export function renderCustomizationDiscoveryContent(content: IChatDebugEventFile

for (const file of files) {
const row = DOM.append(listEl, $('div.chat-debug-file-list-row'));
DOM.append(row, $(`span.chat-debug-file-list-icon${ThemeIcon.asCSSSelector(Codicon.close)}`));
DOM.append(row, $(`span.chat-debug-file-list-icon${ThemeIcon.asCSSSelector(Codicon.closeCompact)}`));

// Build per-file detail (error message / duplicate info)
let detail = '';
Expand Down Expand Up @@ -477,7 +478,7 @@ export function renderCustomizationSummaryContent(content: IChatDebugEventCustom
}
for (const entry of groupEntries) {
const row = DOM.append(listEl, $('div.chat-debug-file-list-row'));
DOM.append(row, $(`span.chat-debug-file-list-icon${ThemeIcon.asCSSSelector(icon)}`));
DOM.append(row, $(`span.chat-debug-file-list-icon${ThemeIcon.asCSSSelector(getCompactCodicon(icon))}`));

if (entry.uri) {
row.appendChild(createInlineFileLink(
Expand All @@ -495,7 +496,7 @@ export function renderCustomizationSummaryContent(content: IChatDebugEventCustom
} else {
for (const entry of entries) {
const row = DOM.append(listEl, $('div.chat-debug-file-list-row'));
DOM.append(row, $(`span.chat-debug-file-list-icon${ThemeIcon.asCSSSelector(icon)}`));
DOM.append(row, $(`span.chat-debug-file-list-icon${ThemeIcon.asCSSSelector(getCompactCodicon(icon))}`));

// Hide the reason for skills (e.g. "local") and custom-agents — it's noise in the UI.
const showReason = entry.category !== 'skill' && entry.category !== 'custom-agent';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1873,11 +1873,11 @@ function currentDeltaComponent(side: ISideData): IComponentDrift {
/** Codicon name for a break-cause category (rail chips, health card). */
function categoryIcon(category: CacheBreakCategory): string {
switch (category) {
case CacheBreakCategory.Healthy: return 'check';
case CacheBreakCategory.Healthy: return 'check-compact';
case CacheBreakCategory.Expiration: return 'clock';
case CacheBreakCategory.Model: return 'hubot';
case CacheBreakCategory.Tools: return 'tools';
case CacheBreakCategory.System: return 'gear';
case CacheBreakCategory.System: return 'gear-compact';
case CacheBreakCategory.Options: return 'symbol-parameter';
case CacheBreakCategory.History: return 'history';
case CacheBreakCategory.Unknown: return 'question';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@
flex-shrink: 0;
width: 16px;
text-align: center;
font-size: var(--vscode-codiconFontSize-compact);
}
.chat-debug-file-link {
color: var(--vscode-textLink-foreground);
Expand Down Expand Up @@ -1197,7 +1198,7 @@ button.chat-debug-cache-finding.is-clickable:focus-visible {
color: var(--vscode-descriptionForeground);
}
.chat-debug-cache-session-health-chip .codicon {
font-size: 12px;
font-size: var(--vscode-codiconFontSize-compact);
}
.chat-debug-cache-session-health-chip.cause-tools,
.chat-debug-cache-session-health-chip.cause-system,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class ChatEditorOverlayWidget extends Disposable {

const progressNode = document.createElement('div');
progressNode.classList.add('chat-editor-overlay-progress');
append(progressNode, renderIcon(ThemeIcon.modify(Codicon.loading, 'spin')));
append(progressNode, renderIcon(ThemeIcon.modify(Codicon.loadingCompact, 'spin')));
const textProgress = append(progressNode, $('span.progress-message'));
this._domNode.appendChild(progressNode);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,12 +274,12 @@ export class ChatEditingExplanationWidget extends Disposable implements IOverlay
this._readIndicator.classList.remove('partial', 'unread');
this._readIndicator.title = nls.localize('markAsUnread', "Mark as unread");
} else if (someRead) {
this._readIndicator.appendChild(renderIcon(Codicon.circleFilled));
this._readIndicator.appendChild(renderIcon(Codicon.circleFilledCompact));
this._readIndicator.classList.remove('read', 'unread');
this._readIndicator.classList.add('partial');
this._readIndicator.title = nls.localize('markAllAsRead', "Mark all as read");
} else {
this._readIndicator.appendChild(renderIcon(Codicon.circleFilled));
this._readIndicator.appendChild(renderIcon(Codicon.circleFilledCompact));
this._readIndicator.classList.remove('read', 'partial');
this._readIndicator.classList.add('unread');
this._readIndicator.title = nls.localize('markAsRead', "Mark as read");
Expand Down Expand Up @@ -450,7 +450,7 @@ export class ChatEditingExplanationWidget extends Disposable implements IOverlay
element.classList.add('read');
element.classList.remove('unread');
} else {
element.appendChild(renderIcon(Codicon.circleFilled));
element.appendChild(renderIcon(Codicon.circleFilledCompact));
element.classList.remove('read');
element.classList.add('unread');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
gap: 6px;
}

.chat-editor-overlay-widget .chat-editor-overlay-progress > .codicon {
font-size: var(--vscode-codiconFontSize-compact);
}

.chat-editor-overlay-widget.busy .chat-editor-overlay-progress {
display: inline-flex;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@
background-color: var(--vscode-toolbar-hoverBackground);
}

.chat-explanation-read-indicator > .codicon,
.chat-explanation-item-read > .codicon {
font-size: var(--vscode-codiconFontSize-compact);
}

.chat-explanation-read-indicator.unread {
color: var(--vscode-textLink-foreground);
opacity: 1;
Expand Down Expand Up @@ -221,7 +226,7 @@
border-radius: 3px;
color: var(--vscode-foreground);
opacity: 0.3;
font-size: 12px;
font-size: var(--vscode-codiconFontSize-compact);
}

.chat-explanation-item:hover .chat-explanation-item-read {
Expand Down
Loading