Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
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: 1 addition & 1 deletion src/vs/platform/agentHost/node/agentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4406,7 +4406,7 @@ export class AgentService extends Disposable implements IAgentService {
const sessionArchived = ((sessionState?.status ?? 0) & SessionStatus.IsArchived) === SessionStatus.IsArchived;
const turn = chatState?.turns.at(-1);
const errorPart = getErrorResponsePart(turn);
const provider = this._findProviderForSession(sessionChannel);
const provider = this._providerService.getProviderForSession(sessionChannel);
if (chatState?.activeTurn) {
this._stateManager.rejectClientAction(channel, action, origin, 'Cannot resume while a turn is active.');
return;
Expand Down
2 changes: 1 addition & 1 deletion src/vs/platform/agentHost/test/node/agentService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ suite('AgentService (node dispatcher)', () => {

suite('failed turn resume', () => {
async function createErroredTurn(): Promise<{ session: URI; chat: string }> {
service.registerProvider(copilotAgent);
registerTestAgentProvider(service, copilotAgent);
const session = await service.createSession({ provider: 'copilot' });
const chat = buildDefaultChatUri(session.toString());
const stateManager = getStateManager(service);
Expand Down
4 changes: 3 additions & 1 deletion src/vs/sessions/common/agentHostSessionsProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { URI } from '../../base/common/uri.js';
import { AuthenticateParams, AuthenticateResult, IAgentConnection } from '../../platform/agentHost/common/agentService.js';
import { RemoteAgentHostConnectionStatus } from '../../platform/agentHost/common/remoteAgentHostService.js';
import { ResolveSessionConfigResult, SessionConfigValueItem } from '../../platform/agentHost/common/state/protocol/commands.js';
import { AgentCustomization, Customization, McpServerStatus, RootConfigState, type CustomizationEnablement, type McpServerState, type RootState } from '../../platform/agentHost/common/state/protocol/state.js';
import { AgentCustomization, Customization, McpServerStatus, RootConfigState, type CustomizationEnablement, type McpServerState, type RootState, type TextRange } from '../../platform/agentHost/common/state/protocol/state.js';
import { type CustomizationDisabledReason } from '../../platform/agentHost/common/customizationEnablement.js';
import { ISessionsProvider } from '../services/sessions/common/sessionsProvider.js';
import { ISessionAgentRef } from '../services/sessions/common/session.js';
Expand Down Expand Up @@ -40,6 +40,8 @@ export interface IAgentHostMcpServer {
readonly disabledReason?: CustomizationDisabledReason;
readonly status: McpServerStatus;
readonly state: McpServerState;
readonly sourceUri?: URI;
readonly sourceRange?: TextRange;
readonly logOutputChannelId?: string;
/** Starts or restarts the server. Providers that cannot control lifecycle may no-op. */
start(): Promise<void>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ export class SessionsAICustomizationWorkspaceService implements IAICustomization
}

readonly managementSections: readonly AICustomizationManagementSection[] = [
AICustomizationManagementSection.Agents,
AICustomizationManagementSection.Plugins,
AICustomizationManagementSection.McpServers,
AICustomizationManagementSection.Skills,
AICustomizationManagementSection.Instructions,
AICustomizationManagementSection.Agents,
AICustomizationManagementSection.Hooks,
AICustomizationManagementSection.Automations,
AICustomizationManagementSection.McpServers,
AICustomizationManagementSection.Plugins,
AICustomizationManagementSection.Tools,
AICustomizationManagementSection.Automations,
AICustomizationManagementSection.HarnessSettings,
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,18 @@ const CUSTOMIZATION_OVERVIEW_ITEM: ICustomizationItemConfig = {

export const CUSTOMIZATION_ITEMS: ICustomizationItemConfig[] = [
{
id: 'sessions.customization.agents',
label: localize('agents', "Agents"),
icon: agentIcon,
section: AICustomizationManagementSection.Agents,
modelSection: AICustomizationManagementSection.Agents,
id: 'sessions.customization.plugins',
label: localize('plugins', "Plugins"),
icon: pluginIcon,
section: AICustomizationManagementSection.Plugins,
isPlugins: true,
},
{
id: 'sessions.customization.mcpServers',
label: localize('mcpServers', "MCP Servers"),
icon: mcpServerIcon,
section: AICustomizationManagementSection.McpServers,
isMcp: true,
},
{
id: 'sessions.customization.skills',
Expand All @@ -88,27 +95,20 @@ export const CUSTOMIZATION_ITEMS: ICustomizationItemConfig[] = [
section: AICustomizationManagementSection.Instructions,
modelSection: AICustomizationManagementSection.Instructions,
},
{
id: 'sessions.customization.agents',
label: localize('agents', "Agents"),
icon: agentIcon,
section: AICustomizationManagementSection.Agents,
modelSection: AICustomizationManagementSection.Agents,
},
{
id: 'sessions.customization.hooks',
label: localize('hooks', "Hooks"),
icon: hookIcon,
section: AICustomizationManagementSection.Hooks,
modelSection: AICustomizationManagementSection.Hooks,
},
{
id: 'sessions.customization.mcpServers',
label: localize('mcpServers', "MCP Servers"),
icon: mcpServerIcon,
section: AICustomizationManagementSection.McpServers,
isMcp: true,
},
{
id: 'sessions.customization.plugins',
label: localize('plugins', "Plugins"),
icon: pluginIcon,
section: AICustomizationManagementSection.Plugins,
isPlugins: true,
},
{
id: 'sessions.customization.tools',
label: localize('tools', "Tools"),
Expand All @@ -131,6 +131,7 @@ export async function openCustomizationOverviewPage(editorService: IEditorServic
}

const input = AICustomizationManagementEditorInput.getOrCreate();
input.setTargetLabel(harnessService.getActiveDescriptor().label);
const pane = await editorService.openEditor(input, { pinned: true });
if (pane instanceof AICustomizationManagementEditor) {
pane.showWelcomePage();
Expand All @@ -144,6 +145,7 @@ async function openCustomizationSectionPage(editorService: IEditorService, harne
}

const input = AICustomizationManagementEditorInput.getOrCreate();
input.setTargetLabel(harnessService.getActiveDescriptor().label);
const pane = await editorService.openEditor(input, { pinned: true });
if (pane instanceof AICustomizationManagementEditor) {
pane.selectSectionById(section);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class InstallPluginAction extends Action {
() => pluginInstallService.installPlugin({
name: item.name,
description: item.description,
version: '',
version: item.version ?? '',
source: item.source,
sourceDescriptor: item.sourceDescriptor,
marketplace: item.marketplace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ export class AgentPluginEditor extends EditorPane {
const expectedUri = this.pluginInstallService.getPluginInstallUri({
name: item.name,
description: item.description,
version: '',
version: item.version ?? '',
source: item.source,
sourceDescriptor: item.sourceDescriptor,
marketplace: item.marketplace,
Expand All @@ -246,6 +246,7 @@ export class AgentPluginEditor extends EditorPane {
kind: AgentPluginItemKind.Marketplace,
name: item.name,
description: mp.description,
version: mp.version,
source: mp.source,
sourceDescriptor: mp.sourceDescriptor,
marketplace: mp.marketplace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface IMarketplacePluginItem {
readonly kind: AgentPluginItemKind.Marketplace;
readonly name: string;
readonly description: string;
readonly version?: string;
readonly source: string;
readonly sourceDescriptor: IPluginSourceDescriptor;
readonly marketplace: string;
Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/contrib/chat/browser/agentPluginsView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ function marketplacePluginToItem(plugin: IMarketplacePlugin): IMarketplacePlugin
kind: AgentPluginItemKind.Marketplace,
name: plugin.name,
description: plugin.description,
version: plugin.version,
source: plugin.source,
sourceDescriptor: plugin.sourceDescriptor,
marketplace: plugin.marketplace,
Expand Down Expand Up @@ -466,7 +467,7 @@ export class AgentPluginsListView extends AbstractExtensionsListView<IAgentPlugi
const expectedUri = this.pluginInstallService.getPluginInstallUri({
name: m.name,
description: m.description,
version: '',
version: m.version ?? '',
source: m.source,
sourceDescriptor: m.sourceDescriptor,
marketplace: m.marketplace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,9 @@ export class AgentHostContribution extends Disposable implements IWorkbenchContr
syncedUri => this._activeClientService.getOrigin(syncedUri)));
itemProvider.setDraftCustomAgents(ambientScope.customAgents);
itemProvider.setDraftCustomizations(ambientScope.customizations);
// `[Agent Host]` suffix disambiguates from the extension-host Copilot CLI harness, which uses the same displayName.
store.add(this._customizationHarnessService.registerExternalHarness({
id: sessionType,
label: localize('agentHostHarnessLabel.local', "{0} [Agent Host]", agent.displayName),
label: agent.displayName,
icon: ThemeIcon.fromId(Codicon.server.id),
// The Tools section is surfaced for the Copilot CLI agent host only.
hiddenSections: agent.provider === 'copilotcli' ? [AICustomizationManagementSection.Prompts] : [AICustomizationManagementSection.Tools, AICustomizationManagementSection.Prompts],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ export abstract class AbstractAgentHostCustomizationService extends Disposable i
disabledReason: getCustomizationDisabledReason(server, plugin),
status: server.state.kind,
state: server.state,
sourceUri: URI.parse(server.uri),
Comment thread
hawkticehurst marked this conversation as resolved.
Outdated
sourceRange: server.range,
logOutputChannelId: channelIdForMcpServer(sessionResource.toString(), server.id),
setEnabled: (enabled: boolean) => target.setCustomizationEnablement(server.id, withCustomizationEnablement(server.enablement, CustomizationEnablementKind.Session, { kind: CustomizationEnablementKind.Session, enabled })),
start: () => target.startMcpServer(server.id),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { parse as parseJSONC } from '../../../../../base/common/json.js';
import { ResourceMap } from '../../../../../base/common/map.js';
import { Schemas } from '../../../../../base/common/network.js';
import { OS } from '../../../../../base/common/platform.js';
import { basename, dirname } from '../../../../../base/common/resources.js';
import { basename } from '../../../../../base/common/resources.js';
import { ThemeIcon } from '../../../../../base/common/themables.js';
import { URI } from '../../../../../base/common/uri.js';
import { localize } from '../../../../../nls.js';
Expand Down Expand Up @@ -277,7 +277,7 @@ export async function mergeBuiltinSkills(
items: readonly IAICustomizationListItem[],
promptType: PromptsType,
promptsService: IPromptsService,
workspaceService: IAICustomizationWorkspaceService,
_workspaceService: IAICustomizationWorkspaceService,
itemNormalizer: AICustomizationItemNormalizer,
): Promise<IAICustomizationListItem[]> {
const builtinPaths: readonly { uri: URI; name?: string; description?: string }[] = await promptsService.listPromptFilesForStorage(PromptsType.skill, PromptsStorage.builtIn, CancellationToken.None);
Expand All @@ -294,9 +294,6 @@ export async function mergeBuiltinSkills(
// re-discovered the bundled copy by scanning disk).
const deduped = items.filter(item => !builtinUris.has(item.uri));

const uiIntegrations = workspaceService.getSkillUIIntegrations();
const uiIntegrationBadge = localize('uiIntegrationBadge', "UI Integration");

// Collect names of user/workspace skills so we can hide the built-in
// copy once the user has added an override at either level.
const overriddenNames = new Set<string>();
Expand All @@ -321,8 +318,6 @@ export async function mergeBuiltinSkills(
if (overriddenNames.has(name)) {
continue;
}
const folderName = basename(dirname(p.uri));
const uiTooltip = uiIntegrations.get(folderName);
const builtinItem: ICustomizationItem = {
uri: p.uri,
type: PromptsType.skill,
Expand All @@ -331,8 +326,6 @@ export async function mergeBuiltinSkills(
source: AICustomizationSources.builtin,
groupKey: BUILTIN_STORAGE,
enabled: !disabledPromptFiles.has(p.uri),
badge: uiTooltip ? uiIntegrationBadge : undefined,
badgeTooltip: uiTooltip,
extensionId: undefined,
pluginUri: undefined,
userInvocable: true,
Expand Down
Loading
Loading