mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-17 01:13:32 +01:00
add pluginUri and extensionId to ICustomizationItem: fix slash command qualification (#313217)
* add pluginUri and extensionId to ICustomizationItem: fix slash command qualification * Update src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentHostLocalCustomizations.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * update * update * update --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
974736ed9a
commit
21ef72b45b
+17
-1
@@ -88,11 +88,13 @@ export class CopilotCLICustomizationProvider extends Disposable implements vscod
|
||||
*/
|
||||
private async getAgentItems(_token: vscode.CancellationToken): Promise<vscode.ChatSessionCustomizationItem[]> {
|
||||
const agentInfos = await this.copilotCLIAgents.getAgents();
|
||||
return agentInfos.map(({ agent, sourceUri }) => ({
|
||||
return agentInfos.map(({ agent, sourceUri, pluginUri, extensionId }) => ({
|
||||
uri: sourceUri,
|
||||
type: vscode.ChatSessionCustomizationType.Agent,
|
||||
name: agent.displayName || agent.name,
|
||||
description: agent.description,
|
||||
extensionId,
|
||||
pluginUri
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -133,7 +135,10 @@ export class CopilotCLICustomizationProvider extends Disposable implements vscod
|
||||
uri,
|
||||
type: vscode.ChatSessionCustomizationType.Instructions,
|
||||
name: basename(uri),
|
||||
description: undefined,
|
||||
groupKey: 'agent-instructions',
|
||||
extensionId: undefined,
|
||||
pluginUri: undefined
|
||||
});
|
||||
}
|
||||
|
||||
@@ -166,6 +171,8 @@ export class CopilotCLICustomizationProvider extends Disposable implements vscod
|
||||
groupKey: 'context-instructions',
|
||||
badge,
|
||||
badgeTooltip,
|
||||
extensionId: instruction.extensionId,
|
||||
pluginUri: instruction.pluginUri
|
||||
});
|
||||
} else {
|
||||
items.push({
|
||||
@@ -174,6 +181,8 @@ export class CopilotCLICustomizationProvider extends Disposable implements vscod
|
||||
name,
|
||||
description,
|
||||
groupKey: 'on-demand-instructions',
|
||||
extensionId: instruction.extensionId,
|
||||
pluginUri: instruction.pluginUri
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -189,6 +198,7 @@ export class CopilotCLICustomizationProvider extends Disposable implements vscod
|
||||
uri: s.uri,
|
||||
type: vscode.ChatSessionCustomizationType.Skill,
|
||||
name: s.name,
|
||||
description: s.description,
|
||||
extensionId: s.extensionId,
|
||||
pluginUri: s.pluginUri,
|
||||
}));
|
||||
@@ -203,6 +213,9 @@ export class CopilotCLICustomizationProvider extends Disposable implements vscod
|
||||
uri: h.uri,
|
||||
type: vscode.ChatSessionCustomizationType.Hook,
|
||||
name: basename(h.uri).replace(/\.json$/i, ''),
|
||||
description: undefined,
|
||||
extensionId: h.extensionId,
|
||||
pluginUri: h.pluginUri,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -214,6 +227,9 @@ export class CopilotCLICustomizationProvider extends Disposable implements vscod
|
||||
uri: p.uri,
|
||||
type: vscode.ChatSessionCustomizationType.Plugins,
|
||||
name: basename(p.uri),
|
||||
description: undefined,
|
||||
extensionId: undefined,
|
||||
pluginUri: undefined,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ function makeSkill(uri: URI, name: string): vscode.ChatSkill {
|
||||
|
||||
/** Creates a ChatHook stub. */
|
||||
function makeHook(uri: URI): vscode.ChatHook {
|
||||
return { uri };
|
||||
return { uri, source: 'local' };
|
||||
}
|
||||
|
||||
/** Creates a ChatPlugin stub. */
|
||||
|
||||
+13
@@ -108,6 +108,8 @@ export class ClaudeCustomizationProvider extends Disposable implements vscode.Ch
|
||||
type: vscode.ChatSessionCustomizationType.Agent,
|
||||
name: agent.name,
|
||||
description: agent.description,
|
||||
extensionId: undefined,
|
||||
pluginUri: undefined,
|
||||
// No groupKey — vscode infers Built-in from non-file: scheme
|
||||
});
|
||||
}
|
||||
@@ -121,6 +123,9 @@ export class ClaudeCustomizationProvider extends Disposable implements vscode.Ch
|
||||
uri: agent.uri,
|
||||
type: vscode.ChatSessionCustomizationType.Agent,
|
||||
name,
|
||||
description: agent.description,
|
||||
extensionId: agent.extensionId,
|
||||
pluginUri: agent.pluginUri,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -142,6 +147,9 @@ export class ClaudeCustomizationProvider extends Disposable implements vscode.Ch
|
||||
uri: skill.uri,
|
||||
type: vscode.ChatSessionCustomizationType.Skill,
|
||||
name: skill.name,
|
||||
description: skill.description,
|
||||
extensionId: skill.extensionId,
|
||||
pluginUri: skill.pluginUri,
|
||||
};
|
||||
skillItems.push(item);
|
||||
}
|
||||
@@ -183,6 +191,9 @@ export class ClaudeCustomizationProvider extends Disposable implements vscode.Ch
|
||||
uri,
|
||||
type: vscode.ChatSessionCustomizationType.Instructions,
|
||||
name,
|
||||
description: undefined,
|
||||
extensionId: undefined,
|
||||
pluginUri: undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -225,6 +236,8 @@ export class ClaudeCustomizationProvider extends Disposable implements vscode.Ch
|
||||
type: vscode.ChatSessionCustomizationType.Hook,
|
||||
name: `${eventId}${matcherLabel}`,
|
||||
description: hook.command,
|
||||
extensionId: undefined,
|
||||
pluginUri: undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,12 +271,15 @@ export class MainThreadChatAgents2 extends Disposable implements MainThreadChatA
|
||||
return {
|
||||
uri: hookFile.uri,
|
||||
sessionTypes: hookFile.sessionTypes,
|
||||
source: this._toChatResourceSource(hookFile.storage),
|
||||
extensionId: hookFile.extension?.identifier.value,
|
||||
pluginUri: hookFile.pluginUri,
|
||||
};
|
||||
}
|
||||
|
||||
private _toPluginDto(plugin: IAgentPlugin): IPluginDto {
|
||||
return {
|
||||
uri: plugin.uri
|
||||
uri: plugin.uri,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -753,8 +756,8 @@ export class MainThreadChatAgents2 extends Disposable implements MainThreadChatA
|
||||
groupKey: item.groupKey,
|
||||
badge: item.badge,
|
||||
badgeTooltip: item.badgeTooltip,
|
||||
extensionId: undefined,
|
||||
pluginUri: undefined
|
||||
extensionId: item.extensionId,
|
||||
pluginUri: item.pluginUri ? URI.revive(item.pluginUri) : undefined
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1719,6 +1719,9 @@ export interface ISlashCommandDto extends IChatResourceDto {
|
||||
export interface IHookDto {
|
||||
readonly uri: UriComponents;
|
||||
readonly sessionTypes?: readonly string[];
|
||||
readonly source: IChatResourceSourceDto;
|
||||
readonly extensionId?: string;
|
||||
readonly pluginUri?: UriComponents;
|
||||
}
|
||||
|
||||
export interface IPluginDto {
|
||||
@@ -1738,7 +1741,8 @@ export interface IChatSessionCustomizationItemDto {
|
||||
readonly description?: string;
|
||||
readonly groupKey?: string;
|
||||
readonly badge?: string;
|
||||
|
||||
readonly extensionId?: string;
|
||||
readonly pluginUri?: UriComponents;
|
||||
readonly badgeTooltip?: string;
|
||||
}
|
||||
export interface IChatParticipantMetadata {
|
||||
|
||||
@@ -589,7 +589,13 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS
|
||||
}
|
||||
|
||||
private toHook(dto: IHookDto): vscode.ChatHook {
|
||||
return Object.freeze({ uri: URI.revive(dto.uri), sessionTypes: dto.sessionTypes });
|
||||
return Object.freeze({
|
||||
uri: URI.revive(dto.uri),
|
||||
sessionTypes: dto.sessionTypes,
|
||||
source: dto.source,
|
||||
extensionId: dto.extensionId,
|
||||
pluginUri: dto.pluginUri ? URI.revive(dto.pluginUri) : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
private toPlugin(dto: IPluginDto): vscode.ChatPlugin {
|
||||
@@ -830,7 +836,9 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS
|
||||
description: item.description,
|
||||
groupKey: item.groupKey,
|
||||
badge: item.badge,
|
||||
badgeTooltip: item.badgeTooltip
|
||||
badgeTooltip: item.badgeTooltip,
|
||||
extensionId: item.extensionId,
|
||||
pluginUri: item.pluginUri,
|
||||
} satisfies IChatSessionCustomizationItemDto));
|
||||
} catch (err) {
|
||||
return undefined;
|
||||
|
||||
+11
-6
@@ -7,16 +7,17 @@ import { CancellationToken } from '../../../../../../base/common/cancellation.js
|
||||
import { Emitter, Event } from '../../../../../../base/common/event.js';
|
||||
import { Disposable } from '../../../../../../base/common/lifecycle.js';
|
||||
import { ResourceMap } from '../../../../../../base/common/map.js';
|
||||
import { basename, dirname, isEqualOrParent } from '../../../../../../base/common/resources.js';
|
||||
import { basename, isEqualOrParent } from '../../../../../../base/common/resources.js';
|
||||
import { URI } from '../../../../../../base/common/uri.js';
|
||||
import { type URI as ProtocolURI } from '../../../../../../platform/agentHost/common/state/protocol/state.js';
|
||||
import { type CustomizationRef } from '../../../../../../platform/agentHost/common/state/sessionState.js';
|
||||
import { PromptsType } from '../../../common/promptSyntax/promptTypes.js';
|
||||
import { IPromptPath, IPromptsService, PromptsStorage } from '../../../common/promptSyntax/service/promptsService.js';
|
||||
import { IPromptsService, PromptsStorage } from '../../../common/promptSyntax/service/promptsService.js';
|
||||
import { type ICustomizationSyncProvider, type ICustomizationItem, type ICustomizationItemProvider } from '../../../common/customizationHarnessService.js';
|
||||
import { IAgentPluginService } from '../../../common/plugins/agentPluginService.js';
|
||||
import { getFriendlyName } from '../../aiCustomization/aiCustomizationItemSource.js';
|
||||
import type { SyncedCustomizationBundler } from './syncedCustomizationBundler.js';
|
||||
import { getSkillFolderName } from '../../../common/promptSyntax/config/promptFileLocations.js';
|
||||
|
||||
/**
|
||||
* Prompt types that participate in auto-sync to an agent host harness.
|
||||
@@ -48,6 +49,8 @@ export interface ILocalCustomizationFile {
|
||||
readonly type: PromptsType;
|
||||
readonly storage: PromptsStorage;
|
||||
readonly disabled: boolean;
|
||||
readonly pluginUri?: URI;
|
||||
readonly extensionId?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,11 +73,13 @@ export async function enumerateLocalCustomizationsForHarness(
|
||||
);
|
||||
for (let i = 0; i < lists.length; i++) {
|
||||
const storage = SYNCABLE_STORAGE_SOURCES[i];
|
||||
for (const file of lists[i] as readonly IPromptPath[]) {
|
||||
for (const file of lists[i]) {
|
||||
result.push({
|
||||
uri: file.uri,
|
||||
type,
|
||||
storage,
|
||||
pluginUri: file.pluginUri,
|
||||
extensionId: file.extension?.identifier.value,
|
||||
disabled: syncProvider.isDisabled(file.uri),
|
||||
});
|
||||
}
|
||||
@@ -131,7 +136,7 @@ export class LocalAgentHostCustomizationItemProvider extends Disposable implemen
|
||||
let description: string | undefined;
|
||||
if (file.type === PromptsType.skill) {
|
||||
const parsed = skillByUri.get(file.uri);
|
||||
name = parsed?.name ?? basename(dirname(file.uri));
|
||||
name = parsed?.name ?? getSkillFolderName(file.uri);
|
||||
description = parsed?.description;
|
||||
} else {
|
||||
name = getFriendlyName(basename(file.uri));
|
||||
@@ -143,8 +148,8 @@ export class LocalAgentHostCustomizationItemProvider extends Disposable implemen
|
||||
description,
|
||||
storage: file.storage,
|
||||
enabled: !file.disabled,
|
||||
extensionId: undefined,
|
||||
pluginUri: undefined,
|
||||
extensionId: file.extensionId,
|
||||
pluginUri: file.pluginUri,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -169,8 +169,11 @@ async function appendProviderData(lines: string[], provider: ICustomizationItemP
|
||||
if (item.itemKey) {
|
||||
lines.push(` itemKey: ${item.itemKey}`);
|
||||
}
|
||||
if (item.extensionLabel) {
|
||||
lines.push(` extensionLabel: ${item.extensionLabel}`);
|
||||
if (item.extensionId) {
|
||||
lines.push(` extensionId: ${item.extensionId}`);
|
||||
}
|
||||
if (item.pluginUri) {
|
||||
lines.push(` pluginUri: ${item.pluginUri.toString()}`);
|
||||
}
|
||||
if (item.badge) {
|
||||
lines.push(` badge: ${item.badge}`);
|
||||
|
||||
+21
-45
@@ -62,7 +62,7 @@ export interface IAICustomizationListItem {
|
||||
/** True when item comes from the default chat extension (grouped under Built-in). */
|
||||
readonly isBuiltin?: boolean;
|
||||
/** Display name of the contributing extension (for non-built-in extension items). */
|
||||
readonly extensionLabel?: string;
|
||||
readonly extensionId?: string;
|
||||
/** Server-reported loading/sync status for remote customizations. */
|
||||
readonly status?: 'loading' | 'loaded' | 'degraded' | 'error';
|
||||
/** Human-readable status detail (e.g. error message or warning). */
|
||||
@@ -199,7 +199,7 @@ export class AICustomizationItemNormalizer {
|
||||
}
|
||||
|
||||
normalizeItem(item: ICustomizationItem, promptType: PromptsType, uriUseCounts = new ResourceMap<number>()): IAICustomizationListItem {
|
||||
const { storage, groupKey, isBuiltin, extensionLabel } = this.resolveSource(item);
|
||||
const { storage, groupKey, isBuiltin, extensionId, pluginUri } = this.inferStorageAndGroup(item);
|
||||
const seenCount = uriUseCounts.get(item.uri) ?? 0;
|
||||
uriUseCounts.set(item.uri, seenCount + 1);
|
||||
const duplicateSuffix = seenCount === 0 ? '' : `#${seenCount}`;
|
||||
@@ -217,64 +217,49 @@ export class AICustomizationItemNormalizer {
|
||||
promptType,
|
||||
disabled: item.enabled === false,
|
||||
groupKey,
|
||||
pluginUri: storage === PromptsStorage.plugin ? this.findPluginUri(item.uri) : undefined,
|
||||
pluginUri,
|
||||
displayName: item.name,
|
||||
badge: item.badge,
|
||||
badgeTooltip: item.badgeTooltip,
|
||||
typeIcon: promptType === PromptsType.instructions && storage ? storageToIcon(storage) : undefined,
|
||||
isBuiltin,
|
||||
extensionLabel,
|
||||
extensionId,
|
||||
status: item.status,
|
||||
statusMessage: item.statusMessage,
|
||||
};
|
||||
}
|
||||
|
||||
private resolveSource(item: ICustomizationItem): { storage?: PromptsStorage; groupKey?: string; isBuiltin?: boolean; extensionLabel?: string } {
|
||||
const inferred = this.inferStorageAndGroup(item.uri);
|
||||
private inferStorageAndGroup(item: ICustomizationItem): { storage: PromptsStorage; groupKey?: string; isBuiltin?: boolean; extensionId?: string; pluginUri?: URI } {
|
||||
const groupKey = item.groupKey;
|
||||
const isBuiltin = groupKey === BUILTIN_STORAGE;
|
||||
|
||||
// Use provider-supplied values when available; otherwise fall back to URI inference.
|
||||
const storage = item.storage ?? inferred.storage;
|
||||
const extensionLabel = item.extensionLabel ?? inferred.extensionLabel;
|
||||
|
||||
if (!item.groupKey) {
|
||||
return { ...inferred, storage, extensionLabel };
|
||||
}
|
||||
|
||||
switch (item.groupKey) {
|
||||
case BUILTIN_STORAGE: {
|
||||
// Preserve a provider-supplied BUILTIN_STORAGE so the management
|
||||
// editor's "edit built-in and save as user/workspace copy" flow
|
||||
// activates. Otherwise fall back to extension storage (the
|
||||
// historical source of built-in items).
|
||||
const builtinStorage = (item.storage as PromptsStorage | typeof BUILTIN_STORAGE | undefined) === BUILTIN_STORAGE
|
||||
? (BUILTIN_STORAGE as unknown as PromptsStorage)
|
||||
: PromptsStorage.extension;
|
||||
return { storage: builtinStorage, groupKey: BUILTIN_STORAGE, isBuiltin: true, extensionLabel };
|
||||
if (item.extensionId) {
|
||||
const extensionIdentifier = new ExtensionIdentifier(item.extensionId);
|
||||
if (isChatExtensionItem(extensionIdentifier, this.productService)) {
|
||||
return { storage: PromptsStorage.extension, groupKey: BUILTIN_STORAGE, isBuiltin: true, extensionId: item.extensionId };
|
||||
}
|
||||
default:
|
||||
return { storage, groupKey: item.groupKey, extensionLabel };
|
||||
return { storage: PromptsStorage.extension, extensionId: item.extensionId, groupKey, isBuiltin };
|
||||
}
|
||||
if (item.pluginUri) {
|
||||
return { storage: PromptsStorage.plugin, pluginUri: item.pluginUri, groupKey, isBuiltin };
|
||||
}
|
||||
}
|
||||
|
||||
private inferStorageAndGroup(uri: URI): { storage?: PromptsStorage; groupKey?: string; isBuiltin?: boolean; extensionLabel?: string } {
|
||||
if (uri.scheme !== Schemas.file) {
|
||||
return { storage: PromptsStorage.extension, groupKey: BUILTIN_STORAGE, isBuiltin: true };
|
||||
}
|
||||
const uri = item.uri;
|
||||
|
||||
const activeProjectRoot = this.workspaceService.getActiveProjectRoot();
|
||||
if (activeProjectRoot && isEqualOrParent(uri, activeProjectRoot)) {
|
||||
return { storage: PromptsStorage.local };
|
||||
return { storage: PromptsStorage.local, groupKey, isBuiltin };
|
||||
}
|
||||
|
||||
for (const folder of this.workspaceContextService.getWorkspace().folders) {
|
||||
if (isEqualOrParent(uri, folder.uri)) {
|
||||
return { storage: PromptsStorage.local };
|
||||
return { storage: PromptsStorage.local, groupKey, isBuiltin };
|
||||
}
|
||||
}
|
||||
|
||||
for (const plugin of this.agentPluginService.plugins.get()) {
|
||||
if (isEqualOrParent(uri, plugin.uri)) {
|
||||
return { storage: PromptsStorage.plugin };
|
||||
return { storage: PromptsStorage.plugin, pluginUri: plugin.uri, groupKey, isBuiltin };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,22 +267,13 @@ export class AICustomizationItemNormalizer {
|
||||
if (extensionId) {
|
||||
const extensionIdentifier = new ExtensionIdentifier(extensionId);
|
||||
if (isChatExtensionItem(extensionIdentifier, this.productService)) {
|
||||
return { storage: PromptsStorage.extension, groupKey: BUILTIN_STORAGE, isBuiltin: true };
|
||||
return { storage: PromptsStorage.extension, groupKey: BUILTIN_STORAGE, isBuiltin: true, extensionId };
|
||||
}
|
||||
return { storage: PromptsStorage.extension, extensionLabel: extensionIdentifier.value };
|
||||
return { storage: PromptsStorage.extension, extensionId, groupKey, isBuiltin };
|
||||
}
|
||||
|
||||
return { storage: PromptsStorage.user };
|
||||
}
|
||||
|
||||
private findPluginUri(itemUri: URI): URI | undefined {
|
||||
for (const plugin of this.agentPluginService.plugins.get()) {
|
||||
if (isEqualOrParent(itemUri, plugin.uri)) {
|
||||
return plugin.uri;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
@@ -285,8 +285,8 @@ class AICustomizationItemRenderer implements IListRenderer<IFileItemEntry, IAICu
|
||||
let content: string;
|
||||
if (element.isBuiltin) {
|
||||
content = `${element.name}\n${localize('builtinSource', "Built-in")}`;
|
||||
} else if (element.extensionLabel) {
|
||||
content = `${element.name}\n${localize('fromExtension', "Extension: {0}", element.extensionLabel)}`;
|
||||
} else if (element.extensionId) {
|
||||
content = `${element.name}\n${localize('fromExtension', "Extension: {0}", element.extensionId)}`;
|
||||
} else {
|
||||
const isWorkspaceItem = element.storage === PromptsStorage.local;
|
||||
const uriLabel = this.labelService.getUriLabel(element.uri, { relative: isWorkspaceItem });
|
||||
|
||||
@@ -20,6 +20,7 @@ import { CancellationToken } from '../../../../base/common/cancellation.js';
|
||||
import { SessionType } from './chatSessionsService.js';
|
||||
import { CustomAgent } from './promptSyntax/service/promptsServiceImpl.js';
|
||||
import { ExtensionIdentifier } from '../../../../platform/extensions/common/extensions.js';
|
||||
import { getCanonicalPluginCommandId } from './plugins/agentPluginService.js';
|
||||
|
||||
export const ICustomizationHarnessService = createDecorator<ICustomizationHarnessService>('customizationHarnessService');
|
||||
|
||||
@@ -164,8 +165,6 @@ export interface ICustomizationItem {
|
||||
readonly description?: string;
|
||||
/** Storage origin (local, user, extension, plugin). Set by providers that know the source. */
|
||||
readonly storage?: PromptsStorage;
|
||||
/** Display name of the contributing extension (e.g. "GitHub Copilot Chat"). */
|
||||
readonly extensionLabel?: string;
|
||||
/** The extension identifier that contributed this customization, if any. */
|
||||
readonly extensionId: string | undefined;
|
||||
/** The URI of the plugin that contributed this customization, if any. */
|
||||
@@ -644,7 +643,7 @@ export class CustomizationHarnessServiceBase implements ICustomizationHarnessSer
|
||||
result.push({
|
||||
uri: item.uri,
|
||||
type: item.type as PromptsType.prompt | PromptsType.skill,
|
||||
name: item.name,
|
||||
name: item.pluginUri ? getCanonicalPluginCommandId({ uri: item.pluginUri }, item.name) : item.name,
|
||||
description: item.description,
|
||||
userInvocable: true, // todo we need a way for providers to specify this if some items aren't user-invocable`
|
||||
storage: item.storage ?? PromptsStorage.local,
|
||||
@@ -697,23 +696,13 @@ export class CustomizationHarnessServiceBase implements ICustomizationHarnessSer
|
||||
}
|
||||
|
||||
public async resolvePromptSlashCommand(name: string, sessionType: string, token: CancellationToken): Promise<IResolvedChatPromptSlashCommand | undefined> {
|
||||
const harness = this.findHarnessById(sessionType);
|
||||
if (!harness || !harness.itemProvider) {
|
||||
return this.promptsService.resolvePromptSlashCommand(name, sessionType, token);
|
||||
}
|
||||
|
||||
const items = await harness.itemProvider.provideChatSessionCustomizations(token);
|
||||
const item = items?.find(cmd => cmd.name === name);
|
||||
if (item) {
|
||||
const parsedPromptFile = await this.promptsService.parseNew(item.uri, token);
|
||||
const commands = await this.getSlashCommands(sessionType, token);
|
||||
const command = commands.find(cmd => cmd.name === name);
|
||||
if (command) {
|
||||
const parsedPromptFile = await this.promptsService.parseNew(command.uri, token);
|
||||
return {
|
||||
uri: item.uri,
|
||||
type: item.type as PromptsType.prompt | PromptsType.skill,
|
||||
name: item.name,
|
||||
description: item.description,
|
||||
userInvocable: parsedPromptFile.header?.userInvocable ?? true,
|
||||
storage: item.storage ?? PromptsStorage.local,
|
||||
sessionTypes: [sessionType],
|
||||
...command,
|
||||
userInvocable: parsedPromptFile.header?.userInvocable ?? command.userInvocable,
|
||||
parsedPromptFile,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -244,6 +244,22 @@ declare module 'vscode' {
|
||||
* Optional session types that describe when the hook should be offered.
|
||||
*/
|
||||
readonly sessionTypes?: readonly string[];
|
||||
|
||||
/**
|
||||
* Where the chat resource was loaded from.
|
||||
*/
|
||||
readonly source: ChatResourceSource;
|
||||
|
||||
/**
|
||||
* The contributing extension identifier when {@link source} is `extension`.
|
||||
*/
|
||||
readonly extensionId?: string;
|
||||
|
||||
/**
|
||||
* The contributing plugin URI when {@link source} is `plugin`.
|
||||
*/
|
||||
readonly pluginUri?: Uri;
|
||||
|
||||
}
|
||||
|
||||
export interface ChatPlugin {
|
||||
@@ -252,6 +268,7 @@ declare module 'vscode' {
|
||||
* Optional session types that describe when the plugin should be offered.
|
||||
*/
|
||||
readonly sessionTypes?: readonly string[];
|
||||
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
@@ -89,6 +89,16 @@ declare module 'vscode' {
|
||||
*/
|
||||
readonly description?: string;
|
||||
|
||||
/**
|
||||
* The extension identifier that contributed this customization, if any.
|
||||
*/
|
||||
readonly extensionId?: string;
|
||||
|
||||
/**
|
||||
* The URI of the plugin that contributed this customization, if any.
|
||||
*/
|
||||
readonly pluginUri?: Uri;
|
||||
|
||||
/**
|
||||
* Optional group key for display grouping. Items sharing the same
|
||||
* `groupKey` are placed under a shared collapsible header in the
|
||||
|
||||
Reference in New Issue
Block a user