@codingame/monaco-vscode-mcp-service-override 23.2.2 → 24.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +19 -19
- package/package.json +2 -15
- package/vscode/src/vs/platform/mcp/common/allowedMcpServersService.d.ts +1 -1
- package/vscode/src/vs/platform/mcp/common/allowedMcpServersService.js +2 -2
- package/vscode/src/vs/platform/mcp/common/mcpGalleryService.d.ts +2 -2
- package/vscode/src/vs/platform/mcp/common/mcpGalleryService.js +4 -8
- package/vscode/src/vs/platform/mcp/common/mcpManagementIpc.d.ts +2 -2
- package/vscode/src/vs/platform/mcp/common/mcpManagementService.d.ts +2 -2
- package/vscode/src/vs/platform/mcp/common/mcpManagementService.js +3 -3
- package/vscode/src/vs/platform/mcp/common/mcpResourceScannerService.d.ts +2 -2
- package/vscode/src/vs/platform/mcp/common/mcpResourceScannerService.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcp.contribution.js +8 -8
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpAddContextContribution.d.ts +3 -2
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpAddContextContribution.js +43 -27
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommands.js +70 -70
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpDiscovery.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpElicitationService.d.ts +10 -4
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpElicitationService.js +198 -35
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.js +21 -21
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpMigration.js +9 -9
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpResourceQuickAccess.d.ts +24 -5
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpResourceQuickAccess.js +178 -51
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerActions.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerActions.js +35 -35
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.d.ts +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.js +37 -37
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditorInput.js +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerIcons.js +5 -5
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.js +7 -7
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.d.ts +3 -3
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.js +26 -26
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.d.ts +3 -3
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.js +12 -12
- package/vscode/src/vs/workbench/contrib/mcp/browser/openPanelChatAndGetWidget.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/browser/openPanelChatAndGetWidget.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/extensionMcpDiscovery.js +5 -5
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/installedMcpServersDiscovery.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.js +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpRemoteDiscovery.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceMcpDiscoveryAdapter.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpContextKeys.js +4 -4
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpDevMode.js +4 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpLanguageModelToolContribution.js +20 -14
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.js +14 -14
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpResourceFilesystem.d.ts +3 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpResourceFilesystem.js +19 -3
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingLog.js +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.js +21 -20
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServer.d.ts +6 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServer.js +79 -47
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.d.ts +3 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.js +8 -6
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.d.ts +47 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.js +229 -14
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpService.js +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpTaskManager.d.ts +68 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpTaskManager.js +168 -0
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpService.js +10 -10
- package/vscode/src/vs/workbench/services/mcp/browser/mcpGalleryManifestService.d.ts +17 -2
- package/vscode/src/vs/workbench/services/mcp/browser/mcpGalleryManifestService.js +60 -10
- package/vscode/src/vs/workbench/services/mcp/common/mcpWorkbenchManagementService.d.ts +1 -1
- package/vscode/src/vs/workbench/services/mcp/common/mcpWorkbenchManagementService.js +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CancellationToken } from "@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation";
|
|
2
|
-
import { DisposableStore, IDisposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
|
|
2
|
+
import { DisposableStore, IDisposable, Disposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
|
|
3
|
+
import { IObservable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/observable";
|
|
3
4
|
import { URI } from "@codingame/monaco-vscode-api/vscode/vs/base/common/uri";
|
|
4
5
|
import { IFileService } from "@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service";
|
|
5
6
|
import { IInstantiationService } from "@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation";
|
|
@@ -11,28 +12,46 @@ import { IEditorService } from "@codingame/monaco-vscode-api/vscode/vs/workbench
|
|
|
11
12
|
import { IViewsService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/services/views/common/viewsService.service";
|
|
12
13
|
import { IChatWidgetService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/browser/chat.service";
|
|
13
14
|
import { IChatAttachmentResolveService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/browser/chatAttachmentResolveService.service";
|
|
14
|
-
import { IChatRequestVariableEntry } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/chatVariableEntries";
|
|
15
15
|
import { IMcpResource, IMcpResourceTemplate, IMcpServer } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes";
|
|
16
16
|
import { IMcpService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes.service";
|
|
17
|
-
|
|
17
|
+
import { ChatContextPickAttachment } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/browser/chatContextPickService";
|
|
18
|
+
export declare class McpResourcePickHelper extends Disposable {
|
|
18
19
|
private readonly _mcpService;
|
|
19
20
|
private readonly _fileService;
|
|
20
21
|
private readonly _quickInputService;
|
|
21
22
|
private readonly _notificationService;
|
|
22
23
|
private readonly _chatAttachmentResolveService;
|
|
24
|
+
private _resources;
|
|
25
|
+
private _pickItemsStack;
|
|
26
|
+
private _inDirectory;
|
|
23
27
|
static sep(server: IMcpServer): IQuickPickSeparator;
|
|
28
|
+
addCurrentMCPQuickPickItemLevel(server: IMcpServer, resources: (IMcpResource | IMcpResourceTemplate)[]): void;
|
|
29
|
+
navigateBack(): boolean;
|
|
24
30
|
static item(resource: IMcpResource | IMcpResourceTemplate): IQuickPickItem;
|
|
25
31
|
hasServersWithResources: import("@codingame/monaco-vscode-api/vscode/vs/base/common/observable").IObservableWithChange<boolean, void>;
|
|
26
32
|
explicitServers?: IMcpServer[];
|
|
27
33
|
constructor(_mcpService: IMcpService, _fileService: IFileService, _quickInputService: IQuickInputService, _notificationService: INotificationService, _chatAttachmentResolveService: IChatAttachmentResolveService);
|
|
28
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Navigate to a resource if it's a directory.
|
|
36
|
+
* Returns true if the resource is a directory with children (navigation succeeded).
|
|
37
|
+
* Returns false if the resource is a leaf file (no navigation).
|
|
38
|
+
* When returning true, statefully updates the picker state to display directory contents.
|
|
39
|
+
*/
|
|
40
|
+
navigate(resource: IMcpResource | IMcpResourceTemplate, server: IMcpServer): Promise<boolean>;
|
|
41
|
+
toAttachment(resource: IMcpResource | IMcpResourceTemplate, server: IMcpServer): Promise<ChatContextPickAttachment> | "noop";
|
|
42
|
+
checkIfDirectoryAndPopulate(resource: IMcpResource | IMcpResourceTemplate, server: IMcpServer): Promise<boolean>;
|
|
29
43
|
toURI(resource: IMcpResource | IMcpResourceTemplate): Promise<URI | undefined>;
|
|
44
|
+
checkIfNestedResources: () => boolean;
|
|
30
45
|
private _resourceToAttachment;
|
|
31
46
|
private _resourceTemplateToAttachment;
|
|
32
47
|
private _verifyUriIfNeeded;
|
|
33
48
|
private _resourceTemplateToURI;
|
|
34
49
|
private _promptForTemplateValue;
|
|
35
|
-
|
|
50
|
+
private _isDirectoryResource;
|
|
51
|
+
getPicks(token?: CancellationToken): IObservable<{
|
|
52
|
+
picks: Map<IMcpServer, (IMcpResourceTemplate | IMcpResource)[]>;
|
|
53
|
+
isBusy: boolean;
|
|
54
|
+
}>;
|
|
36
55
|
}
|
|
37
56
|
export declare abstract class AbstractMcpResourceAccessPick {
|
|
38
57
|
private readonly _scopeTo;
|
|
@@ -4,7 +4,7 @@ import { RunOnceScheduler, disposableTimeout, DeferredPromise } from '@codingame
|
|
|
4
4
|
import { CancellationTokenSource, CancellationToken } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
|
|
5
5
|
import { Codicon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/codicons';
|
|
6
6
|
import { Event } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
|
|
7
|
-
import { DisposableStore, toDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
7
|
+
import { Disposable, DisposableStore, toDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
8
8
|
import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
|
|
9
9
|
import { ThemeIcon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/themables';
|
|
10
10
|
import { generateUuid } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uuid';
|
|
@@ -21,11 +21,15 @@ import { IChatWidgetService } from '@codingame/monaco-vscode-api/vscode/vs/workb
|
|
|
21
21
|
import { IChatAttachmentResolveService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/browser/chatAttachmentResolveService.service';
|
|
22
22
|
import { isMcpResourceTemplate, McpCapability, McpResourceURI, McpConnectionState } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes';
|
|
23
23
|
import { IMcpService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes.service';
|
|
24
|
+
import { McpIcons } from '../common/mcpIcons.js';
|
|
24
25
|
import { openPanelChatAndGetWidget } from './openPanelChatAndGetWidget.js';
|
|
25
|
-
import {
|
|
26
|
+
import { LinkedList } from '@codingame/monaco-vscode-api/vscode/vs/base/common/linkedList';
|
|
27
|
+
import { asArray } from '@codingame/monaco-vscode-api/vscode/vs/base/common/arrays';
|
|
26
28
|
import { autorun } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/reactions/autorun';
|
|
29
|
+
import { observableValue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableValue';
|
|
30
|
+
import { derived } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/derived';
|
|
27
31
|
|
|
28
|
-
let McpResourcePickHelper = class McpResourcePickHelper {
|
|
32
|
+
let McpResourcePickHelper = class McpResourcePickHelper extends Disposable {
|
|
29
33
|
static sep(server) {
|
|
30
34
|
return {
|
|
31
35
|
id: server.definition.id,
|
|
@@ -33,6 +37,32 @@ let McpResourcePickHelper = class McpResourcePickHelper {
|
|
|
33
37
|
label: server.definition.label,
|
|
34
38
|
};
|
|
35
39
|
}
|
|
40
|
+
addCurrentMCPQuickPickItemLevel(server, resources) {
|
|
41
|
+
let isValidPush = false;
|
|
42
|
+
isValidPush = this._pickItemsStack.isEmpty();
|
|
43
|
+
if (!isValidPush) {
|
|
44
|
+
const stackedItem = this._pickItemsStack.peek();
|
|
45
|
+
if (stackedItem?.server === server && stackedItem.resources === resources) {
|
|
46
|
+
isValidPush = false;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
isValidPush = true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (isValidPush) {
|
|
53
|
+
this._pickItemsStack.push({ server, resources });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
navigateBack() {
|
|
57
|
+
const items = this._pickItemsStack.pop();
|
|
58
|
+
if (items) {
|
|
59
|
+
this._inDirectory.set({ server: items.server, resources: items.resources }, undefined);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
36
66
|
static item(resource) {
|
|
37
67
|
const iconPath = resource.icons.getUrl(22);
|
|
38
68
|
if (isMcpResourceTemplate(resource)) {
|
|
@@ -40,7 +70,7 @@ let McpResourcePickHelper = class McpResourcePickHelper {
|
|
|
40
70
|
id: resource.template.template,
|
|
41
71
|
label: resource.title || resource.name,
|
|
42
72
|
description: resource.description,
|
|
43
|
-
detail: ( localize(
|
|
73
|
+
detail: ( localize(8864, 'Resource template: {0}', resource.template.template)),
|
|
44
74
|
iconPath,
|
|
45
75
|
};
|
|
46
76
|
}
|
|
@@ -53,11 +83,15 @@ let McpResourcePickHelper = class McpResourcePickHelper {
|
|
|
53
83
|
};
|
|
54
84
|
}
|
|
55
85
|
constructor(_mcpService, _fileService, _quickInputService, _notificationService, _chatAttachmentResolveService) {
|
|
86
|
+
super();
|
|
56
87
|
this._mcpService = _mcpService;
|
|
57
88
|
this._fileService = _fileService;
|
|
58
89
|
this._quickInputService = _quickInputService;
|
|
59
90
|
this._notificationService = _notificationService;
|
|
60
91
|
this._chatAttachmentResolveService = _chatAttachmentResolveService;
|
|
92
|
+
this._resources = observableValue(this, { picks: ( new Map()), isBusy: true });
|
|
93
|
+
this._pickItemsStack = ( new LinkedList());
|
|
94
|
+
this._inDirectory = observableValue(this, undefined);
|
|
61
95
|
this.hasServersWithResources = derived(reader => {
|
|
62
96
|
let enabled = false;
|
|
63
97
|
for (const server of this._mcpService.servers.read(reader)) {
|
|
@@ -72,13 +106,62 @@ let McpResourcePickHelper = class McpResourcePickHelper {
|
|
|
72
106
|
}
|
|
73
107
|
return enabled;
|
|
74
108
|
});
|
|
109
|
+
this.checkIfNestedResources = () => !this._pickItemsStack.isEmpty();
|
|
110
|
+
}
|
|
111
|
+
async navigate(resource, server) {
|
|
112
|
+
if (isMcpResourceTemplate(resource)) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
const uri = resource.uri;
|
|
116
|
+
let stat = undefined;
|
|
117
|
+
try {
|
|
118
|
+
stat = await this._fileService.resolve(uri, { resolveMetadata: false });
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
if (stat && this._isDirectoryResource(resource) && (stat.children?.length ?? 0) > 0) {
|
|
124
|
+
const currentResources = this._resources.get().picks.get(server);
|
|
125
|
+
if (currentResources) {
|
|
126
|
+
this.addCurrentMCPQuickPickItemLevel(server, currentResources);
|
|
127
|
+
}
|
|
128
|
+
const childResources = ( stat.children.map(child => {
|
|
129
|
+
const mcpUri = McpResourceURI.fromServer(server.definition, ( child.resource.toString()));
|
|
130
|
+
return {
|
|
131
|
+
uri: mcpUri,
|
|
132
|
+
mcpUri: child.resource.path,
|
|
133
|
+
name: child.name,
|
|
134
|
+
title: child.name,
|
|
135
|
+
description: resource.description,
|
|
136
|
+
mimeType: undefined,
|
|
137
|
+
sizeInBytes: child.size,
|
|
138
|
+
icons: McpIcons.fromParsed(undefined)
|
|
139
|
+
};
|
|
140
|
+
}));
|
|
141
|
+
this._inDirectory.set({ server, resources: childResources }, undefined);
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
75
145
|
}
|
|
76
|
-
|
|
146
|
+
toAttachment(resource, server) {
|
|
147
|
+
const noop = 'noop';
|
|
148
|
+
if (this._isDirectoryResource(resource)) {
|
|
149
|
+
this.checkIfDirectoryAndPopulate(resource, server);
|
|
150
|
+
return noop;
|
|
151
|
+
}
|
|
77
152
|
if (isMcpResourceTemplate(resource)) {
|
|
78
|
-
return this._resourceTemplateToAttachment(resource);
|
|
153
|
+
return this._resourceTemplateToAttachment(resource).then(val => val || noop);
|
|
79
154
|
}
|
|
80
155
|
else {
|
|
81
|
-
return this._resourceToAttachment(resource);
|
|
156
|
+
return this._resourceToAttachment(resource).then(val => val || noop);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async checkIfDirectoryAndPopulate(resource, server) {
|
|
160
|
+
try {
|
|
161
|
+
return !(await this.navigate(resource, server));
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
return false;
|
|
82
165
|
}
|
|
83
166
|
}
|
|
84
167
|
async toURI(resource) {
|
|
@@ -120,7 +203,7 @@ let McpResourcePickHelper = class McpResourcePickHelper {
|
|
|
120
203
|
return uri;
|
|
121
204
|
}
|
|
122
205
|
this._notificationService.warn(( localize(
|
|
123
|
-
|
|
206
|
+
8865,
|
|
124
207
|
"The resource {0} was not found.",
|
|
125
208
|
(McpResourceURI.toServer(uri).resourceURL.toString())
|
|
126
209
|
)));
|
|
@@ -161,13 +244,13 @@ let McpResourcePickHelper = class McpResourcePickHelper {
|
|
|
161
244
|
}
|
|
162
245
|
}
|
|
163
246
|
let placeholder = ( localize(
|
|
164
|
-
|
|
247
|
+
8866,
|
|
165
248
|
"Value for ${0} in {1}",
|
|
166
249
|
variable.name.toUpperCase(),
|
|
167
250
|
rt.template.resolve(variablesWithPlaceholders).replaceAll('%24', '$')
|
|
168
251
|
));
|
|
169
252
|
if (variable.optional) {
|
|
170
|
-
placeholder += ' (' + ( localize(
|
|
253
|
+
placeholder += ' (' + ( localize(8867, "Optional")) + ')';
|
|
171
254
|
}
|
|
172
255
|
input.placeholder = placeholder;
|
|
173
256
|
input.value = '';
|
|
@@ -180,11 +263,12 @@ let McpResourcePickHelper = class McpResourcePickHelper {
|
|
|
180
263
|
items.unshift({ id: currentID, label: value });
|
|
181
264
|
}
|
|
182
265
|
else if (variable.optional) {
|
|
183
|
-
items.unshift({ id: currentID, label: ( localize(
|
|
266
|
+
items.unshift({ id: currentID, label: ( localize(8868, "<Empty>")) });
|
|
184
267
|
}
|
|
185
268
|
input.items = items;
|
|
186
269
|
};
|
|
187
|
-
let changeCancellation =
|
|
270
|
+
let changeCancellation = ( new CancellationTokenSource());
|
|
271
|
+
store.add(toDisposable(() => changeCancellation.dispose(true)));
|
|
188
272
|
const getCompletionItems = () => {
|
|
189
273
|
const inputValue = input.value;
|
|
190
274
|
let promise = completions.get(inputValue);
|
|
@@ -222,8 +306,7 @@ let McpResourcePickHelper = class McpResourcePickHelper {
|
|
|
222
306
|
store.add(input.onDidChangeValue(value => {
|
|
223
307
|
input.busy = true;
|
|
224
308
|
changeCancellation.dispose(true);
|
|
225
|
-
|
|
226
|
-
changeCancellation = store.add(( new CancellationTokenSource()));
|
|
309
|
+
changeCancellation = ( new CancellationTokenSource());
|
|
227
310
|
getCompletionItemsScheduler.cancel();
|
|
228
311
|
setItems(value);
|
|
229
312
|
if (( completions.has(input.value))) {
|
|
@@ -236,12 +319,23 @@ let McpResourcePickHelper = class McpResourcePickHelper {
|
|
|
236
319
|
getCompletionItems();
|
|
237
320
|
})).finally(() => store.dispose());
|
|
238
321
|
}
|
|
239
|
-
|
|
322
|
+
_isDirectoryResource(resource) {
|
|
323
|
+
if (resource.mimeType && resource.mimeType === 'inode/directory') {
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
else if (isMcpResourceTemplate(resource)) {
|
|
327
|
+
return resource.template.template.endsWith('/');
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
return resource.uri.path.endsWith('/');
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
getPicks(token) {
|
|
240
334
|
const cts = ( new CancellationTokenSource(token));
|
|
241
|
-
|
|
242
|
-
|
|
335
|
+
let isBusyLoadingPicks = true;
|
|
336
|
+
this._register(toDisposable(() => cts.dispose(true)));
|
|
243
337
|
let showInSequence = true;
|
|
244
|
-
|
|
338
|
+
this._register(disposableTimeout(() => {
|
|
245
339
|
showInSequence = false;
|
|
246
340
|
publish();
|
|
247
341
|
}, 5_000));
|
|
@@ -261,10 +355,10 @@ let McpResourcePickHelper = class McpResourcePickHelper {
|
|
|
261
355
|
break;
|
|
262
356
|
}
|
|
263
357
|
}
|
|
264
|
-
|
|
358
|
+
this._resources.set({ picks: output, isBusy: isBusyLoadingPicks }, undefined);
|
|
265
359
|
};
|
|
266
360
|
const servers = ( new Map());
|
|
267
|
-
|
|
361
|
+
Promise.all(( (this.explicitServers || this._mcpService.servers.get()).map(async (server) => {
|
|
268
362
|
let cap = server.capabilities.get();
|
|
269
363
|
const rec = {
|
|
270
364
|
templates: ( new DeferredPromise()),
|
|
@@ -279,8 +373,8 @@ let McpResourcePickHelper = class McpResourcePickHelper {
|
|
|
279
373
|
resolve(undefined);
|
|
280
374
|
}
|
|
281
375
|
});
|
|
282
|
-
|
|
283
|
-
|
|
376
|
+
this._register(cts.token.onCancellationRequested(() => resolve(undefined)));
|
|
377
|
+
this._register(autorun(reader => {
|
|
284
378
|
const cap2 = server.capabilities.read(reader);
|
|
285
379
|
if (cap2 !== undefined) {
|
|
286
380
|
resolve(cap2);
|
|
@@ -303,9 +397,15 @@ let McpResourcePickHelper = class McpResourcePickHelper {
|
|
|
303
397
|
rec.templates.complete([]);
|
|
304
398
|
rec.resources.complete([]);
|
|
305
399
|
}
|
|
306
|
-
publish();
|
|
307
400
|
}))).finally(() => {
|
|
308
|
-
|
|
401
|
+
isBusyLoadingPicks = false;
|
|
402
|
+
publish();
|
|
403
|
+
});
|
|
404
|
+
return derived(this, reader => {
|
|
405
|
+
const directoryResource = this._inDirectory.read(reader);
|
|
406
|
+
return directoryResource
|
|
407
|
+
? { picks: ( new Map([[directoryResource.server, directoryResource.resources]])), isBusy: false }
|
|
408
|
+
: this._resources.read(reader);
|
|
309
409
|
});
|
|
310
410
|
}
|
|
311
411
|
};
|
|
@@ -328,51 +428,78 @@ let AbstractMcpResourceAccessPick = class AbstractMcpResourceAccessPick {
|
|
|
328
428
|
picker.canAcceptInBackground = true;
|
|
329
429
|
picker.busy = true;
|
|
330
430
|
picker.keepScrollPosition = true;
|
|
331
|
-
const
|
|
332
|
-
const
|
|
431
|
+
const store = ( new DisposableStore());
|
|
432
|
+
const goBackId = '_goback_';
|
|
433
|
+
const attachButton = ( localize(8869, "Attach to chat"));
|
|
434
|
+
const helper = store.add(this._instantiationService.createInstance(McpResourcePickHelper));
|
|
333
435
|
if (this._scopeTo) {
|
|
334
436
|
helper.explicitServers = [this._scopeTo];
|
|
335
437
|
}
|
|
336
|
-
helper.getPicks(
|
|
438
|
+
const picksObservable = helper.getPicks(token);
|
|
439
|
+
store.add(autorun(reader => {
|
|
440
|
+
const pickItems = picksObservable.read(reader);
|
|
441
|
+
const isBusy = pickItems.isBusy;
|
|
337
442
|
const items = [];
|
|
338
|
-
for (const [server, resources] of
|
|
443
|
+
for (const [server, resources] of pickItems.picks) {
|
|
339
444
|
items.push(McpResourcePickHelper.sep(server));
|
|
340
445
|
for (const resource of resources) {
|
|
341
446
|
const pickItem = McpResourcePickHelper.item(resource);
|
|
342
447
|
pickItem.buttons = [{ iconClass: ThemeIcon.asClassName(Codicon.attach), tooltip: attachButton }];
|
|
343
|
-
items.push({ ...pickItem, resource });
|
|
448
|
+
items.push({ ...pickItem, resource, server });
|
|
344
449
|
}
|
|
345
450
|
}
|
|
451
|
+
if (helper.checkIfNestedResources()) {
|
|
452
|
+
const goBackItem = {
|
|
453
|
+
id: goBackId,
|
|
454
|
+
label: ( localize(8870, 'Go back ↩')),
|
|
455
|
+
alwaysShow: true
|
|
456
|
+
};
|
|
457
|
+
items.push(goBackItem);
|
|
458
|
+
}
|
|
346
459
|
picker.items = items;
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
});
|
|
350
|
-
const store = ( new DisposableStore());
|
|
460
|
+
picker.busy = isBusy;
|
|
461
|
+
}));
|
|
351
462
|
store.add(picker.onDidTriggerItemButton(event => {
|
|
352
463
|
if (event.button.tooltip === attachButton) {
|
|
353
464
|
picker.busy = true;
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
465
|
+
const resourceItem = event.item;
|
|
466
|
+
const attachment = helper.toAttachment(resourceItem.resource, resourceItem.server);
|
|
467
|
+
if (attachment instanceof Promise) {
|
|
468
|
+
attachment.then(async (a) => {
|
|
469
|
+
if (a !== 'noop') {
|
|
470
|
+
const widget = await openPanelChatAndGetWidget(this._viewsService, this._chatWidgetService);
|
|
471
|
+
widget?.attachmentModel.addContext(...asArray(a));
|
|
472
|
+
}
|
|
473
|
+
picker.hide();
|
|
474
|
+
});
|
|
475
|
+
}
|
|
361
476
|
}
|
|
362
477
|
}));
|
|
478
|
+
store.add(picker.onDidHide(() => {
|
|
479
|
+
helper.dispose();
|
|
480
|
+
}));
|
|
363
481
|
store.add(picker.onDidAccept(async (event) => {
|
|
364
|
-
|
|
365
|
-
picker.
|
|
366
|
-
}
|
|
367
|
-
if (runOptions?.handleAccept) {
|
|
368
|
-
runOptions.handleAccept?.(picker.activeItems[0], event.inBackground);
|
|
369
|
-
}
|
|
370
|
-
else {
|
|
482
|
+
try {
|
|
483
|
+
picker.busy = true;
|
|
371
484
|
const [item] = picker.selectedItems;
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
485
|
+
if (item.id === goBackId) {
|
|
486
|
+
helper.navigateBack();
|
|
487
|
+
picker.busy = false;
|
|
488
|
+
return;
|
|
375
489
|
}
|
|
490
|
+
const resourceItem = item;
|
|
491
|
+
const resource = resourceItem.resource;
|
|
492
|
+
const isNested = await helper.navigate(resource, resourceItem.server);
|
|
493
|
+
if (!isNested) {
|
|
494
|
+
const uri = await helper.toURI(resource);
|
|
495
|
+
if (uri) {
|
|
496
|
+
picker.hide();
|
|
497
|
+
this._editorService.openEditor({ resource: uri, options: { preserveFocus: event.inBackground } });
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
finally {
|
|
502
|
+
picker.busy = false;
|
|
376
503
|
}
|
|
377
504
|
}));
|
|
378
505
|
return store;
|
|
@@ -392,7 +519,7 @@ let McpResourceQuickPick = class McpResourceQuickPick extends AbstractMcpResourc
|
|
|
392
519
|
async pick(token = CancellationToken.None) {
|
|
393
520
|
const store = ( new DisposableStore());
|
|
394
521
|
const qp = store.add(this._quickInputService.createQuickPick({ useSeparators: true }));
|
|
395
|
-
qp.placeholder = ( localize(
|
|
522
|
+
qp.placeholder = ( localize(8871, "Search for resources"));
|
|
396
523
|
store.add(this.applyToPick(qp, token));
|
|
397
524
|
store.add(qp.onDidHide(() => store.dispose()));
|
|
398
525
|
qp.show();
|
|
@@ -19,7 +19,7 @@ import { IWorkspaceContextService } from "@codingame/monaco-vscode-api/vscode/vs
|
|
|
19
19
|
import { IQuickInputService } from "@codingame/monaco-vscode-api/vscode/vs/platform/quickinput/common/quickInput.service";
|
|
20
20
|
import { IWorkbenchEnvironmentService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/services/environment/common/environmentService.service";
|
|
21
21
|
import { ILabelService } from "@codingame/monaco-vscode-api/vscode/vs/platform/label/common/label.service";
|
|
22
|
-
import { ExtensionAction } from "@codingame/monaco-vscode-
|
|
22
|
+
import { ExtensionAction } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/extensions/browser/extensionsActions";
|
|
23
23
|
import { ActionWithDropdownActionViewItem, IActionWithDropdownActionViewItemOptions } from "@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/dropdown/dropdownActionViewItem";
|
|
24
24
|
import { IContextMenuProvider } from "@codingame/monaco-vscode-api/vscode/vs/base/browser/contextmenu";
|
|
25
25
|
export interface IMcpServerActionChangeEvent extends IActionChangeEvent {
|