Skip to content

Commit 0713a7a

Browse files
committed
Refactor AI customization components and add new tests for coverage
1 parent 36fce8c commit 0713a7a

25 files changed

Lines changed: 951 additions & 218 deletions

src/vs/workbench/contrib/chat/browser/agentPluginActions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class InstallPluginAction extends Action {
3838
() => pluginInstallService.installPlugin({
3939
name: item.name,
4040
description: item.description,
41-
version: '',
41+
version: item.version ?? '',
4242
source: item.source,
4343
sourceDescriptor: item.sourceDescriptor,
4444
marketplace: item.marketplace,

src/vs/workbench/contrib/chat/browser/agentPluginEditor/agentPluginEditor.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ export class AgentPluginEditor extends EditorPane {
224224
const expectedUri = this.pluginInstallService.getPluginInstallUri({
225225
name: item.name,
226226
description: item.description,
227-
version: '',
227+
version: item.version ?? '',
228228
source: item.source,
229229
sourceDescriptor: item.sourceDescriptor,
230230
marketplace: item.marketplace,
@@ -246,6 +246,7 @@ export class AgentPluginEditor extends EditorPane {
246246
kind: AgentPluginItemKind.Marketplace,
247247
name: item.name,
248248
description: mp.description,
249+
version: mp.version,
249250
source: mp.source,
250251
sourceDescriptor: mp.sourceDescriptor,
251252
marketplace: mp.marketplace,

src/vs/workbench/contrib/chat/browser/agentPluginEditor/agentPluginItems.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export interface IMarketplacePluginItem {
2626
readonly kind: AgentPluginItemKind.Marketplace;
2727
readonly name: string;
2828
readonly description: string;
29+
readonly version?: string;
2930
readonly source: string;
3031
readonly sourceDescriptor: IPluginSourceDescriptor;
3132
readonly marketplace: string;

src/vs/workbench/contrib/chat/browser/agentPluginsView.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ function marketplacePluginToItem(plugin: IMarketplacePlugin): IMarketplacePlugin
6969
kind: AgentPluginItemKind.Marketplace,
7070
name: plugin.name,
7171
description: plugin.description,
72+
version: plugin.version,
7273
source: plugin.source,
7374
sourceDescriptor: plugin.sourceDescriptor,
7475
marketplace: plugin.marketplace,
@@ -466,7 +467,7 @@ export class AgentPluginsListView extends AbstractExtensionsListView<IAgentPlugi
466467
const expectedUri = this.pluginInstallService.getPluginInstallUri({
467468
name: m.name,
468469
description: m.description,
469-
version: '',
470+
version: m.version ?? '',
470471
source: m.source,
471472
sourceDescriptor: m.sourceDescriptor,
472473
marketplace: m.marketplace,

src/vs/workbench/contrib/chat/browser/aiCustomization/aiCustomizationListWidget.ts

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import { ICustomizationHarnessService } from '../../common/customizationHarnessS
4848
import { ICommandService } from '../../../../../platform/commands/common/commands.js';
4949
import { IAICustomizationListItem } from './aiCustomizationItemSource.js';
5050
import { IAICustomizationItemsModel, ItemsModelSection } from './aiCustomizationItemsModel.js';
51+
import { createCustomizationCardPrimaryAction, CustomizationCardListController } from './customizationCardList.js';
5152

5253
export { truncateToFirstLine } from './aiCustomizationListWidgetUtils.js';
5354

@@ -513,6 +514,10 @@ export function getAlwaysVisibleCustomizationGroupKeys(section: AICustomizationM
513514
: [];
514515
}
515516

517+
export function getTargetedCreateActionLabel(label: string, compactLabel?: string): string {
518+
return compactLabel ?? label.replace(/^\$\([^)]+\)\s*/, '');
519+
}
520+
516521
/**
517522
* Returns the ARIA status announcement string for a given section, item
518523
* count, and whether a search filter is active. Exported for testing.
@@ -573,6 +578,7 @@ export function getCountAnnouncement(section: AICustomizationManagementSection,
573578
*/
574579
interface ICreateAction {
575580
readonly label: string;
581+
readonly compactLabel?: string;
576582
readonly enabled: boolean;
577583
readonly tooltip?: string;
578584
readonly kind?: 'generate';
@@ -1219,13 +1225,15 @@ export class AICustomizationListWidget extends Disposable {
12191225
if (hasWorkspace) {
12201226
actions.push({
12211227
label: localize('newHook', "New Hook"),
1228+
compactLabel: localize('newHook', "New Hook"),
12221229
enabled: true,
12231230
target: 'workspace',
12241231
run: () => { this._onDidRequestCreateManual.fire({ type: promptType, target: 'local' }); },
12251232
});
12261233
}
12271234
actions.push({
12281235
label: localize('newHook', "New Hook"),
1236+
compactLabel: localize('newHook', "New Hook"),
12291237
enabled: true,
12301238
target: 'user',
12311239
run: () => { this._onDidRequestCreateManual.fire({ type: promptType, target: 'user' }); },
@@ -1250,6 +1258,7 @@ export class AICustomizationListWidget extends Disposable {
12501258
// Sessions or non-local harness with workspace: workspace is primary
12511259
actions.push({
12521260
label: localize('newWorkspaceCustomization', "New {0} (Workspace)", createTypeLabel),
1261+
compactLabel: localize('newCustomization', "New {0}", createTypeLabel),
12531262
enabled: true,
12541263
target: 'workspace',
12551264
run: () => { this._onDidRequestCreateManual.fire({ type: promptType, target: 'local' }); },
@@ -1259,6 +1268,7 @@ export class AICustomizationListWidget extends Disposable {
12591268
// No workspace: user is primary
12601269
actions.push({
12611270
label: localize('newUserCustomization', "New {0} (User)", createTypeLabel),
1271+
compactLabel: localize('newCustomization', "New {0}", createTypeLabel),
12621272
enabled: true,
12631273
target: 'user',
12641274
run: () => { this._onDidRequestCreateManual.fire({ type: promptType, target: 'user' }); },
@@ -1271,6 +1281,7 @@ export class AICustomizationListWidget extends Disposable {
12711281
if (hasWorkspace && !addedTargets.has('workspace')) {
12721282
actions.push({
12731283
label: localize('newWorkspaceCustomization', "New {0} (Workspace)", createTypeLabel),
1284+
compactLabel: localize('newCustomization', "New {0}", createTypeLabel),
12741285
enabled: true,
12751286
target: 'workspace',
12761287
run: () => { this._onDidRequestCreateManual.fire({ type: promptType, target: 'local' }); },
@@ -1280,6 +1291,7 @@ export class AICustomizationListWidget extends Disposable {
12801291
if (!addedTargets.has('user')) {
12811292
actions.push({
12821293
label: localize('newUserCustomization', "New {0} (User)", createTypeLabel),
1294+
compactLabel: localize('newCustomization', "New {0}", createTypeLabel),
12831295
enabled: true,
12841296
target: 'user',
12851297
run: () => { this._onDidRequestCreateManual.fire({ type: promptType, target: 'user' }); },
@@ -1598,13 +1610,14 @@ export class AICustomizationListWidget extends Disposable {
15981610
}
15991611

16001612
const inventory = DOM.append(section, $('.plugin-card-grid.plugin-inventory-list.customization-inventory-list'));
1613+
const cardList = this.cardDisposables.add(new CustomizationCardListController(inventory, group.label));
16011614
if (group.items.length === 0) {
16021615
const empty = DOM.append(inventory, $('.plugin-inventory-empty'));
16031616
empty.textContent = this.getEmptyGroupMessage(group.groupKey);
16041617
continue;
16051618
}
16061619
for (const item of group.items) {
1607-
this.appendCustomizationCardRow(inventory, item, group.label);
1620+
this.appendCustomizationCardRow(inventory, item, group.label, cardList);
16081621
}
16091622
}
16101623
if (shouldRestoreFocus) {
@@ -1686,9 +1699,7 @@ export class AICustomizationListWidget extends Disposable {
16861699
}
16871700

16881701
private formatTargetedCreateActionLabel(action: ICreateAction): string {
1689-
return action.label
1690-
.replace(/^\$\([^)]+\)\s*/, '')
1691-
.replace(/\s+\((?:Workspace|User)\)$/, '');
1702+
return getTargetedCreateActionLabel(action.label, action.compactLabel);
16921703
}
16931704

16941705
private showCreateActionsMenu(createActions: readonly ICreateAction[], anchor: HTMLElement): void {
@@ -1764,7 +1775,7 @@ export class AICustomizationListWidget extends Disposable {
17641775
this.cardDisposables.add(button.onDidClick(() => this.executePrimaryCreateAction()));
17651776
}
17661777

1767-
private appendCustomizationCardRow(parent: HTMLElement, item: IAICustomizationListItem, groupLabel: string): void {
1778+
private appendCustomizationCardRow(parent: HTMLElement, item: IAICustomizationListItem, groupLabel: string, cardList: CustomizationCardListController): void {
17681779
const row = DOM.append(parent, $('.plugin-list-item.plugin-home-row.customization-home-row'));
17691780
row.classList.toggle('disabled', item.disabled);
17701781
const displayName = item.displayName ?? formatDisplayName(item.name);
@@ -1774,10 +1785,7 @@ export class AICustomizationListWidget extends Disposable {
17741785
const accessibleLabel = item.disabled
17751786
? localize('customizationCardAriaLabelDisabled', "{0}. {1}. Disabled", displayName, accessibleSecondaryText || groupLabel)
17761787
: localize('customizationCardAriaLabel', "{0}. {1}", displayName, accessibleSecondaryText || groupLabel);
1777-
const primary = DOM.append(row, $('.customization-row-primary'));
1778-
primary.tabIndex = 0;
1779-
primary.setAttribute('role', 'button');
1780-
primary.setAttribute('aria-label', accessibleLabel);
1788+
const primary = createCustomizationCardPrimaryAction(row, accessibleLabel, 'customization-row-primary');
17811789
this.firstCardFocusElement ??= primary;
17821790
if (!this.cardRowsByUri.has(item.uri.toString())) {
17831791
this.cardRowsByUri.set(item.uri.toString(), primary);
@@ -1787,12 +1795,6 @@ export class AICustomizationListWidget extends Disposable {
17871795
this.lastCardFocusItemId = item.id;
17881796
}));
17891797
this.cardDisposables.add(DOM.addDisposableListener(primary, 'click', () => this._onDidSelectItem.fire(item)));
1790-
this.cardDisposables.add(DOM.addDisposableListener(primary, 'keydown', e => {
1791-
if (e.key === 'Enter' || e.key === ' ') {
1792-
e.preventDefault();
1793-
this._onDidSelectItem.fire(item);
1794-
}
1795-
}));
17961798
this.cardDisposables.add(this.hoverService.setupDelayedHover(row, () => ({
17971799
content: `${displayName}\n${this.labelService.getUriLabel(item.uri, { relative: item.source === AICustomizationSources.local })}`,
17981800
appearance: { compact: true, skipFadeInAnimation: true },
@@ -1826,6 +1828,13 @@ export class AICustomizationListWidget extends Disposable {
18261828
this.lastCardFocusItemId = item.id;
18271829
}));
18281830
this.cardDisposables.add(more.onDidClick(() => this.showCardItemActions(item, more.element)));
1831+
cardList.addItem({
1832+
row,
1833+
primaryAction: primary,
1834+
label: displayName,
1835+
actions: [more.element],
1836+
contextMenuAction: more.element,
1837+
});
18291838
}
18301839

18311840
private getItemStatusLabel(item: IAICustomizationListItem): string | undefined {

src/vs/workbench/contrib/chat/browser/aiCustomization/aiCustomizationManagementEditor.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,9 @@ export class AICustomizationManagementEditor extends EditorPane {
16151615
container.style.display = '';
16161616
const content = DOM.append(container, $('.customization-migration-banner-content'));
16171617
DOM.append(content, $('p.customization-migration-banner-message')).textContent = banner.message;
1618+
if (banner.consequence) {
1619+
DOM.append(content, $('p.customization-migration-banner-consequence')).textContent = banner.consequence;
1620+
}
16181621
if (this.migrationLinkElement) {
16191622
content.appendChild(this.migrationLinkElement);
16201623
}

src/vs/workbench/contrib/chat/browser/aiCustomization/aiCustomizationManagementEditorInput.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export class AICustomizationManagementEditorInput extends EditorInput implements
5555

5656
override getName(): string {
5757
if (this._targetLabel) {
58-
return localize('aiCustomizationManagementEditorNameWithTarget', "Agent Customizations {0}", this._targetLabel);
58+
return localize('aiCustomizationManagementEditorNameWithTarget', "Agent Customizations - {0}", this._targetLabel);
5959
}
6060
return localize('aiCustomizationManagementEditorName', "Agent Customizations");
6161
}

0 commit comments

Comments
 (0)