Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/chat/common/plugins/agentPluginService.ts
13405 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { IDisposable } from '../../../../../base/common/lifecycle.js';
7
import { IObservable } from '../../../../../base/common/observable.js';
8
import { basename } from '../../../../../base/common/resources.js';
9
import { URI } from '../../../../../base/common/uri.js';
10
import { SyncDescriptor0 } from '../../../../../platform/instantiation/common/descriptors.js';
11
import { createDecorator } from '../../../../../platform/instantiation/common/instantiation.js';
12
import { type INamedPluginResource, type IMcpServerDefinition, type IParsedHookCommand } from '../../../../../platform/agentPlugins/common/pluginParsers.js';
13
import { ContributionEnablementState, IEnablementModel } from '../enablement.js';
14
import { HookType } from '../promptSyntax/hookTypes.js';
15
import { IMarketplacePlugin } from './pluginMarketplaceService.js';
16
17
export const IAgentPluginService = createDecorator<IAgentPluginService>('agentPluginService');
18
19
export interface IAgentPluginHook {
20
readonly type: HookType;
21
readonly hooks: readonly IParsedHookCommand[];
22
/** URI where this hook is defined -- not unique, multiple hooks may be in a manifest */
23
readonly uri: URI;
24
readonly originalId: string;
25
}
26
27
export type IAgentPluginCommand = INamedPluginResource;
28
export type IAgentPluginSkill = INamedPluginResource;
29
export type IAgentPluginAgent = INamedPluginResource;
30
export type IAgentPluginInstruction = INamedPluginResource;
31
export type IAgentPluginMcpServerDefinition = IMcpServerDefinition;
32
33
export interface IAgentPlugin {
34
readonly uri: URI;
35
/** Human-readable display name for the plugin. */
36
readonly label: string;
37
readonly enablement: IObservable<ContributionEnablementState>;
38
/** Removes this plugin from its discovery source (config or installed storage). */
39
remove(): void;
40
readonly hooks: IObservable<readonly IAgentPluginHook[]>;
41
readonly commands: IObservable<readonly IAgentPluginCommand[]>;
42
readonly skills: IObservable<readonly IAgentPluginSkill[]>;
43
readonly agents: IObservable<readonly IAgentPluginAgent[]>;
44
readonly instructions: IObservable<readonly IAgentPluginInstruction[]>;
45
readonly mcpServerDefinitions: IObservable<readonly IAgentPluginMcpServerDefinition[]>;
46
/** Set when the plugin was installed from a marketplace repository. */
47
readonly fromMarketplace?: IMarketplacePlugin;
48
}
49
50
export interface IAgentPluginService {
51
readonly _serviceBrand: undefined;
52
readonly plugins: IObservable<readonly IAgentPlugin[]>;
53
readonly enablementModel: IEnablementModel;
54
}
55
56
export interface IAgentPluginDiscovery extends IDisposable {
57
readonly plugins: IObservable<readonly IAgentPlugin[]>;
58
start(enablementModel: IEnablementModel): void;
59
}
60
61
export function getCanonicalPluginCommandId(plugin: { readonly uri: URI }, commandName: string): string {
62
const pluginSegment = basename(plugin.uri);
63
const prefix = normalizePluginToken(pluginSegment);
64
const normalizedCommand = normalizePluginToken(commandName);
65
if (normalizedCommand.startsWith(`${prefix}:`)) {
66
return normalizedCommand;
67
}
68
69
// When the skill name matches the plugin name, use just the plugin
70
// name so the user can invoke `/plugin-name` instead of the redundant
71
// `/plugin-name:plugin-name`.
72
if (prefix === normalizedCommand) {
73
return prefix;
74
}
75
76
return `${prefix}:${normalizedCommand}`;
77
}
78
79
function normalizePluginToken(value: string): string {
80
return value
81
.trim()
82
.toLowerCase()
83
.replace(/\s+/g, '-')
84
.replace(/[^a-z0-9_.:-]/g, '-')
85
.replace(/-+/g, '-')
86
.replace(/^[-:.]+|[-:.]+$/g, '');
87
}
88
89
class AgentPluginDiscoveryRegistry {
90
private readonly _discovery: SyncDescriptor0<IAgentPluginDiscovery>[] = [];
91
92
register(descriptor: SyncDescriptor0<IAgentPluginDiscovery>): void {
93
this._discovery.push(descriptor);
94
}
95
96
getAll(): readonly SyncDescriptor0<IAgentPluginDiscovery>[] {
97
return this._discovery;
98
}
99
}
100
101
export const agentPluginDiscoveryRegistry = new AgentPluginDiscoveryRegistry();
102
103
104
105