@theia/ai-ide 1.63.0-next.24 → 1.63.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/lib/browser/ai-configuration/agent-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/agent-configuration-widget.js +7 -2
- package/lib/browser/ai-configuration/agent-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/ai-configuration-view-contribution.js +1 -1
- package/lib/browser/ai-configuration/ai-configuration-view-contribution.js.map +1 -1
- package/lib/browser/ai-configuration/ai-configuration-widget.d.ts +0 -1
- package/lib/browser/ai-configuration/ai-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/ai-configuration-widget.js +0 -1
- package/lib/browser/ai-configuration/ai-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/mcp-configuration-widget.d.ts +4 -1
- package/lib/browser/ai-configuration/mcp-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/mcp-configuration-widget.js +59 -11
- package/lib/browser/ai-configuration/mcp-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.d.ts +0 -1
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.js +1 -4
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/template-settings-renderer.js +1 -1
- package/lib/browser/ai-configuration/template-settings-renderer.js.map +1 -1
- package/lib/browser/ai-configuration/tools-configuration-widget.d.ts +0 -1
- package/lib/browser/ai-configuration/tools-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/tools-configuration-widget.js +6 -21
- package/lib/browser/ai-configuration/tools-configuration-widget.js.map +1 -1
- package/lib/browser/app-tester-chat-agent.d.ts +5 -3
- package/lib/browser/app-tester-chat-agent.d.ts.map +1 -1
- package/lib/browser/app-tester-chat-agent.js +41 -31
- package/lib/browser/app-tester-chat-agent.js.map +1 -1
- package/lib/browser/architect-agent.d.ts.map +1 -1
- package/lib/browser/architect-agent.js +6 -3
- package/lib/browser/architect-agent.js.map +1 -1
- package/lib/browser/frontend-module.d.ts +1 -0
- package/lib/browser/frontend-module.d.ts.map +1 -1
- package/lib/browser/frontend-module.js +1 -0
- package/lib/browser/frontend-module.js.map +1 -1
- package/lib/browser/summarize-session-command-contribution.d.ts +8 -1
- package/lib/browser/summarize-session-command-contribution.d.ts.map +1 -1
- package/lib/browser/summarize-session-command-contribution.js +60 -6
- package/lib/browser/summarize-session-command-contribution.js.map +1 -1
- package/lib/browser/task-context-file-storage-service.d.ts +4 -2
- package/lib/browser/task-context-file-storage-service.d.ts.map +1 -1
- package/lib/browser/task-context-file-storage-service.js +19 -9
- package/lib/browser/task-context-file-storage-service.js.map +1 -1
- package/lib/browser/workspace-preferences.d.ts +1 -0
- package/lib/browser/workspace-preferences.d.ts.map +1 -1
- package/lib/browser/workspace-preferences.js +9 -1
- package/lib/browser/workspace-preferences.js.map +1 -1
- package/lib/browser/workspace-search-provider.d.ts +5 -1
- package/lib/browser/workspace-search-provider.d.ts.map +1 -1
- package/lib/browser/workspace-search-provider.js +57 -17
- package/lib/browser/workspace-search-provider.js.map +1 -1
- package/lib/browser/workspace-search-provider.spec.d.ts +2 -0
- package/lib/browser/workspace-search-provider.spec.d.ts.map +1 -0
- package/lib/browser/workspace-search-provider.spec.js +227 -0
- package/lib/browser/workspace-search-provider.spec.js.map +1 -0
- package/lib/common/architect-prompt-template.d.ts +4 -2
- package/lib/common/architect-prompt-template.d.ts.map +1 -1
- package/lib/common/architect-prompt-template.js +201 -35
- package/lib/common/architect-prompt-template.js.map +1 -1
- package/lib/common/coder-replace-prompt-template.d.ts +4 -4
- package/lib/common/coder-replace-prompt-template.d.ts.map +1 -1
- package/lib/common/coder-replace-prompt-template.js +8 -8
- package/lib/common/coder-replace-prompt-template.js.map +1 -1
- package/lib/common/summarize-session-commands.d.ts +1 -0
- package/lib/common/summarize-session-commands.d.ts.map +1 -1
- package/lib/common/summarize-session-commands.js +5 -1
- package/lib/common/summarize-session-commands.js.map +1 -1
- package/lib/common/universal-chat-agent.js +2 -2
- package/lib/common/workspace-search-provider-util.d.ts +17 -0
- package/lib/common/workspace-search-provider-util.d.ts.map +1 -0
- package/lib/common/workspace-search-provider-util.js +51 -0
- package/lib/common/workspace-search-provider-util.js.map +1 -0
- package/package.json +19 -18
- package/src/browser/ai-configuration/agent-configuration-widget.tsx +7 -5
- package/src/browser/ai-configuration/ai-configuration-view-contribution.ts +1 -1
- package/src/browser/ai-configuration/ai-configuration-widget.tsx +0 -1
- package/src/browser/ai-configuration/mcp-configuration-widget.tsx +82 -14
- package/src/browser/ai-configuration/prompt-fragments-configuration-widget.tsx +1 -4
- package/src/browser/ai-configuration/template-settings-renderer.tsx +1 -1
- package/src/browser/ai-configuration/tools-configuration-widget.tsx +8 -23
- package/src/browser/app-tester-chat-agent.ts +43 -33
- package/src/browser/architect-agent.ts +8 -5
- package/src/browser/frontend-module.ts +2 -0
- package/src/browser/style/index.css +23 -28
- package/src/browser/summarize-session-command-contribution.ts +64 -8
- package/src/browser/task-context-file-storage-service.ts +20 -10
- package/src/browser/workspace-preferences.ts +9 -0
- package/src/browser/workspace-search-provider.spec.ts +255 -0
- package/src/browser/workspace-search-provider.ts +62 -16
- package/src/common/architect-prompt-template.ts +201 -35
- package/src/common/coder-replace-prompt-template.ts +8 -8
- package/src/common/summarize-session-commands.ts +5 -0
- package/src/common/universal-chat-agent.ts +2 -2
- package/src/common/workspace-search-provider-util.ts +50 -0
|
@@ -18,7 +18,14 @@ import { ReactWidget } from '@theia/core/lib/browser';
|
|
|
18
18
|
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
19
19
|
import * as React from '@theia/core/shared/react';
|
|
20
20
|
import { HoverService } from '@theia/core/lib/browser/hover-service';
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
isLocalMCPServerDescription,
|
|
23
|
+
isRemoteMCPServerDescription,
|
|
24
|
+
MCPFrontendNotificationService,
|
|
25
|
+
MCPFrontendService,
|
|
26
|
+
MCPServerDescription,
|
|
27
|
+
MCPServerStatus
|
|
28
|
+
} from '@theia/ai-mcp/lib/common/mcp-server-manager';
|
|
22
29
|
import { MessageService, nls } from '@theia/core';
|
|
23
30
|
import { PROMPT_VARIABLE } from '@theia/ai-core/lib/common/prompt-variable-contribution';
|
|
24
31
|
|
|
@@ -67,12 +74,15 @@ export class AIMCPConfigurationWidget extends ReactWidget {
|
|
|
67
74
|
}
|
|
68
75
|
switch (status) {
|
|
69
76
|
case MCPServerStatus.Running:
|
|
77
|
+
case MCPServerStatus.Connected:
|
|
70
78
|
return { bg: 'var(--theia-successBackground)', fg: 'var(--theia-successForeground)' };
|
|
71
79
|
case MCPServerStatus.Starting:
|
|
80
|
+
case MCPServerStatus.Connecting:
|
|
72
81
|
return { bg: 'var(--theia-warningBackground)', fg: 'var(--theia-warningForeground)' };
|
|
73
82
|
case MCPServerStatus.Errored:
|
|
74
83
|
return { bg: 'var(--theia-errorBackground)', fg: 'var(--theia-errorForeground)' };
|
|
75
84
|
case MCPServerStatus.NotRunning:
|
|
85
|
+
case MCPServerStatus.NotConnected:
|
|
76
86
|
default:
|
|
77
87
|
return { bg: 'var(--theia-inputValidation-infoBackground)', fg: 'var(--theia-inputValidation-infoForeground)' };
|
|
78
88
|
}
|
|
@@ -106,10 +116,14 @@ export class AIMCPConfigurationWidget extends ReactWidget {
|
|
|
106
116
|
);
|
|
107
117
|
}
|
|
108
118
|
|
|
109
|
-
protected renderStatusBadge(
|
|
110
|
-
const colors = this.getStatusColor(status);
|
|
111
|
-
|
|
119
|
+
protected renderStatusBadge(server: MCPServerDescription): React.ReactNode {
|
|
120
|
+
const colors = this.getStatusColor(server.status);
|
|
121
|
+
let displayStatus = server.status;
|
|
122
|
+
if (!displayStatus) {
|
|
123
|
+
displayStatus = isRemoteMCPServerDescription(server) ? MCPServerStatus.NotConnected : MCPServerStatus.NotRunning;
|
|
124
|
+
}
|
|
112
125
|
const spanRef = React.createRef<HTMLSpanElement>();
|
|
126
|
+
const error = server.error;
|
|
113
127
|
return (
|
|
114
128
|
<div className="mcp-status-container">
|
|
115
129
|
<span className="mcp-status-badge" style={{
|
|
@@ -136,12 +150,15 @@ export class AIMCPConfigurationWidget extends ReactWidget {
|
|
|
136
150
|
return (
|
|
137
151
|
<div className="mcp-server-header">
|
|
138
152
|
<div className="mcp-server-name">{server.name}</div>
|
|
139
|
-
{this.renderStatusBadge(server
|
|
153
|
+
{this.renderStatusBadge(server)}
|
|
140
154
|
</div>
|
|
141
155
|
);
|
|
142
156
|
}
|
|
143
157
|
|
|
144
158
|
protected renderCommandSection(server: MCPServerDescription): React.ReactNode {
|
|
159
|
+
if (!isLocalMCPServerDescription(server)) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
145
162
|
return (
|
|
146
163
|
<div className="mcp-server-section">
|
|
147
164
|
<span className="mcp-section-label">{nls.localize('theia/ai/mcpConfiguration/command', 'Command: ')}</span>
|
|
@@ -151,7 +168,7 @@ export class AIMCPConfigurationWidget extends ReactWidget {
|
|
|
151
168
|
}
|
|
152
169
|
|
|
153
170
|
protected renderArgumentsSection(server: MCPServerDescription): React.ReactNode {
|
|
154
|
-
if (!server.args || server.args.length === 0) {
|
|
171
|
+
if (!isLocalMCPServerDescription(server) || !server.args || server.args.length === 0) {
|
|
155
172
|
return;
|
|
156
173
|
}
|
|
157
174
|
return (
|
|
@@ -163,7 +180,7 @@ export class AIMCPConfigurationWidget extends ReactWidget {
|
|
|
163
180
|
}
|
|
164
181
|
|
|
165
182
|
protected renderEnvironmentSection(server: MCPServerDescription): React.ReactNode {
|
|
166
|
-
if (!server.env || Object.keys(server.env).length === 0) {
|
|
183
|
+
if (!isLocalMCPServerDescription(server) || !server.env || Object.keys(server.env).length === 0) {
|
|
167
184
|
return;
|
|
168
185
|
}
|
|
169
186
|
return (
|
|
@@ -172,7 +189,7 @@ export class AIMCPConfigurationWidget extends ReactWidget {
|
|
|
172
189
|
<div className="mcp-env-block">
|
|
173
190
|
{Object.entries(server.env).map(([key, value]) => (
|
|
174
191
|
<div key={key}>
|
|
175
|
-
{key}={key.toLowerCase().includes('token') ? '******' : value}
|
|
192
|
+
{key}={key.toLowerCase().includes('token') ? '******' : String(value)}
|
|
176
193
|
</div>
|
|
177
194
|
))}
|
|
178
195
|
</div>
|
|
@@ -180,6 +197,42 @@ export class AIMCPConfigurationWidget extends ReactWidget {
|
|
|
180
197
|
);
|
|
181
198
|
}
|
|
182
199
|
|
|
200
|
+
protected renderServerUrlSection(server: MCPServerDescription): React.ReactNode {
|
|
201
|
+
if (!isRemoteMCPServerDescription(server)) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
return (
|
|
205
|
+
<div className="mcp-server-section">
|
|
206
|
+
<span className="mcp-section-label">{nls.localize('theia/ai/mcpConfiguration/serverUrl', 'Server URL: ')}</span>
|
|
207
|
+
<code className="mcp-code-block">{server.serverUrl}</code>
|
|
208
|
+
</div>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
protected renderServerAuthTokenHeaderSection(server: MCPServerDescription): React.ReactNode {
|
|
213
|
+
if (!isRemoteMCPServerDescription(server) || !server.serverAuthTokenHeader) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
return (
|
|
217
|
+
<div className="mcp-server-section">
|
|
218
|
+
<span className="mcp-section-label">{nls.localize('theia/ai/mcpConfiguration/serverAuthTokenHeader', 'Authentication Header Name: ')}</span>
|
|
219
|
+
<code className="mcp-code-block">{server.serverAuthTokenHeader}</code>
|
|
220
|
+
</div>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
protected renderServerAuthTokenSection(server: MCPServerDescription): React.ReactNode {
|
|
225
|
+
if (!isRemoteMCPServerDescription(server) || !server.serverAuthToken) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
return (
|
|
229
|
+
<div className="mcp-server-section">
|
|
230
|
+
<span className="mcp-section-label">{nls.localize('theia/ai/mcpConfiguration/serverAuthToken', 'Authentication Token: ')}</span>
|
|
231
|
+
<code className="mcp-code-block">******</code>
|
|
232
|
+
</div>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
183
236
|
protected renderAutostartSection(server: MCPServerDescription): React.ReactNode {
|
|
184
237
|
return (
|
|
185
238
|
<div className="mcp-server-section">
|
|
@@ -286,19 +339,31 @@ export class AIMCPConfigurationWidget extends ReactWidget {
|
|
|
286
339
|
}
|
|
287
340
|
|
|
288
341
|
protected renderServerControls(server: MCPServerDescription): React.ReactNode {
|
|
289
|
-
const isStoppable = server.status === MCPServerStatus.Running
|
|
290
|
-
|
|
342
|
+
const isStoppable = server.status === MCPServerStatus.Running
|
|
343
|
+
|| server.status === MCPServerStatus.Connected
|
|
344
|
+
|| server.status === MCPServerStatus.Starting
|
|
345
|
+
|| server.status === MCPServerStatus.Connecting;
|
|
346
|
+
const isStartable = server.status === MCPServerStatus.NotRunning
|
|
347
|
+
|| server.status === MCPServerStatus.NotConnected
|
|
348
|
+
|| server.status === MCPServerStatus.Errored;
|
|
349
|
+
|
|
350
|
+
const startLabel = isRemoteMCPServerDescription(server)
|
|
351
|
+
? nls.localize('theia/ai/mcpConfiguration/connectServer', 'Connnect')
|
|
352
|
+
: nls.localize('theia/ai/mcpConfiguration/startServer', 'Start Server');
|
|
353
|
+
const stopLabel = isRemoteMCPServerDescription(server)
|
|
354
|
+
? nls.localize('theia/ai/mcpConfiguration/disconnectServer', 'Disconnnect')
|
|
355
|
+
: nls.localize('theia/ai/mcpConfiguration/stopServer', 'Stop Server');
|
|
291
356
|
return (
|
|
292
357
|
<div className="mcp-server-controls">
|
|
293
358
|
{isStartable && this.renderButton(
|
|
294
|
-
<><i className="codicon codicon-play"></i> {
|
|
295
|
-
|
|
359
|
+
<><i className="codicon codicon-play"></i> {startLabel}</>,
|
|
360
|
+
startLabel,
|
|
296
361
|
() => this.handleStartServer(server.name),
|
|
297
362
|
'mcp-server-button play-button'
|
|
298
363
|
)}
|
|
299
364
|
{isStoppable && this.renderButton(
|
|
300
|
-
<><i className="codicon codicon-close"></i> {
|
|
301
|
-
|
|
365
|
+
<><i className="codicon codicon-close"></i> {stopLabel}</>,
|
|
366
|
+
stopLabel,
|
|
302
367
|
() => this.handleStopServer(server.name),
|
|
303
368
|
'mcp-server-button stop-button'
|
|
304
369
|
)}
|
|
@@ -313,6 +378,9 @@ export class AIMCPConfigurationWidget extends ReactWidget {
|
|
|
313
378
|
{this.renderCommandSection(server)}
|
|
314
379
|
{this.renderArgumentsSection(server)}
|
|
315
380
|
{this.renderEnvironmentSection(server)}
|
|
381
|
+
{this.renderServerUrlSection(server)}
|
|
382
|
+
{this.renderServerAuthTokenHeaderSection(server)}
|
|
383
|
+
{this.renderServerAuthTokenSection(server)}
|
|
316
384
|
{this.renderAutostartSection(server)}
|
|
317
385
|
{this.renderToolsSection(server)}
|
|
318
386
|
{this.renderServerControls(server)}
|
|
@@ -26,7 +26,6 @@ import {
|
|
|
26
26
|
BasePromptFragment
|
|
27
27
|
} from '@theia/ai-core/lib/common/prompt-service';
|
|
28
28
|
import * as React from '@theia/core/shared/react';
|
|
29
|
-
import '../../../src/browser/style/index.css';
|
|
30
29
|
import { AgentService } from '@theia/ai-core/lib/common/agent-service';
|
|
31
30
|
import { Agent } from '@theia/ai-core/lib/common/agent';
|
|
32
31
|
import { CustomizationSource } from '@theia/ai-core/lib/browser/frontend-prompt-customization-service';
|
|
@@ -347,9 +346,7 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
347
346
|
|
|
348
347
|
const shouldReset = await dialog.open();
|
|
349
348
|
if (shouldReset) {
|
|
350
|
-
this.
|
|
351
|
-
this.promptService.resetToBuiltIn(fragments[0].id);
|
|
352
|
-
});
|
|
349
|
+
this.promptService.resetAllToBuiltIn();
|
|
353
350
|
}
|
|
354
351
|
};
|
|
355
352
|
|
|
@@ -77,7 +77,7 @@ export const PromptVariantRenderer: React.FC<PromptVariantRendererProps> = ({
|
|
|
77
77
|
>
|
|
78
78
|
{isInvalidVariant && (
|
|
79
79
|
<option value="invalid" disabled>
|
|
80
|
-
{nls.localize('theia/ai/core/templateSettings/unavailableVariant', '
|
|
80
|
+
{nls.localize('theia/ai/core/templateSettings/unavailableVariant', 'Selected variant not available, default will be used')}
|
|
81
81
|
</option>
|
|
82
82
|
)}
|
|
83
83
|
{variantIds.map(variantId => (
|
|
@@ -20,10 +20,10 @@ import * as React from '@theia/core/shared/react';
|
|
|
20
20
|
import { ToolConfirmationManager, ToolConfirmationMode } from '@theia/ai-chat/lib/browser/chat-tool-preferences';
|
|
21
21
|
import { ToolInvocationRegistry } from '@theia/ai-core';
|
|
22
22
|
|
|
23
|
-
const TOOL_OPTIONS: { value: ToolConfirmationMode, label: string, icon: string
|
|
24
|
-
{ value: ToolConfirmationMode.DISABLED, label: 'Disabled', icon: 'close'
|
|
25
|
-
{ value: ToolConfirmationMode.CONFIRM, label: 'Confirm', icon: 'question'
|
|
26
|
-
{ value: ToolConfirmationMode.
|
|
23
|
+
const TOOL_OPTIONS: { value: ToolConfirmationMode, label: string, icon: string }[] = [
|
|
24
|
+
{ value: ToolConfirmationMode.DISABLED, label: 'Disabled', icon: 'close' },
|
|
25
|
+
{ value: ToolConfirmationMode.CONFIRM, label: 'Confirm', icon: 'question' },
|
|
26
|
+
{ value: ToolConfirmationMode.ALWAYS_ALLOW, label: 'Always Allow', icon: 'thumbsup' },
|
|
27
27
|
];
|
|
28
28
|
|
|
29
29
|
@injectable()
|
|
@@ -102,18 +102,6 @@ export class AIToolsConfigurationWidget extends ReactWidget {
|
|
|
102
102
|
await this.updateDefaultConfirmation(newState);
|
|
103
103
|
};
|
|
104
104
|
|
|
105
|
-
protected getColoring(mode: ToolConfirmationMode, renderDefault = false): string {
|
|
106
|
-
if (!renderDefault && mode === this.defaultState) {
|
|
107
|
-
return '';
|
|
108
|
-
}
|
|
109
|
-
if (mode === ToolConfirmationMode.YOLO) {
|
|
110
|
-
return ' ai-tools-configuration-tool-select--yolo';
|
|
111
|
-
} else if (mode === ToolConfirmationMode.DISABLED) {
|
|
112
|
-
return ' ai-tools-configuration-tool-select--disabled';
|
|
113
|
-
}
|
|
114
|
-
return ' ai-tools-configuration-tool-select--confirm';
|
|
115
|
-
}
|
|
116
|
-
|
|
117
105
|
protected async resetAllToolsToDefault(): Promise<void> {
|
|
118
106
|
const dialog = new ConfirmDialog({
|
|
119
107
|
title: 'Reset All Tool Confirmation Modes',
|
|
@@ -135,13 +123,13 @@ export class AIToolsConfigurationWidget extends ReactWidget {
|
|
|
135
123
|
<div className='ai-tools-configuration-default-section' style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
|
136
124
|
<div className='ai-tools-configuration-default-label'>Default Tool Confirmation Mode:</div>
|
|
137
125
|
<select
|
|
138
|
-
className=
|
|
126
|
+
className="ai-tools-configuration-default-select"
|
|
139
127
|
value={this.defaultState}
|
|
140
128
|
onChange={this.handleDefaultStateChange}
|
|
141
129
|
style={{ marginLeft: 8 }}
|
|
142
130
|
>
|
|
143
131
|
{TOOL_OPTIONS.map(opt => (
|
|
144
|
-
<option
|
|
132
|
+
<option key={opt.value} value={opt.value}>{opt.label}</option>
|
|
145
133
|
))}
|
|
146
134
|
</select>
|
|
147
135
|
<button
|
|
@@ -159,10 +147,7 @@ export class AIToolsConfigurationWidget extends ReactWidget {
|
|
|
159
147
|
{this.tools.map(tool => {
|
|
160
148
|
const state = this.toolConfirmationModes[tool] || this.defaultState;
|
|
161
149
|
const isDefault = state === this.defaultState;
|
|
162
|
-
|
|
163
|
-
if (!isDefault) {
|
|
164
|
-
selectClass += `${this.getColoring(state)}`;
|
|
165
|
-
}
|
|
150
|
+
const selectClass = 'ai-tools-configuration-tool-select';
|
|
166
151
|
return (
|
|
167
152
|
<li
|
|
168
153
|
key={tool}
|
|
@@ -178,7 +163,7 @@ export class AIToolsConfigurationWidget extends ReactWidget {
|
|
|
178
163
|
onChange={e => this.handleToolConfirmationModeChange(tool, e)}
|
|
179
164
|
>
|
|
180
165
|
{TOOL_OPTIONS.map(opt => (
|
|
181
|
-
<option
|
|
166
|
+
<option key={opt.value} value={opt.value}>
|
|
182
167
|
{opt.label}
|
|
183
168
|
</option>
|
|
184
169
|
))}
|
|
@@ -26,7 +26,22 @@ import { inject, injectable } from '@theia/core/shared/inversify';
|
|
|
26
26
|
import { MCP_SERVERS_PREF } from '@theia/ai-mcp/lib/browser/mcp-preferences';
|
|
27
27
|
import { PreferenceScope, PreferenceService } from '@theia/core/lib/browser';
|
|
28
28
|
|
|
29
|
-
export const
|
|
29
|
+
export const REQUIRED_MCP_SERVERS: MCPServerDescription[] = [
|
|
30
|
+
{
|
|
31
|
+
name: 'playwright',
|
|
32
|
+
command: 'npx',
|
|
33
|
+
args: ['-y', '@playwright/mcp@latest'],
|
|
34
|
+
autostart: false,
|
|
35
|
+
env: {},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'playwright-visual',
|
|
39
|
+
command: 'npx',
|
|
40
|
+
args: ['-y', '@playwright/mcp@latest', '--vision'],
|
|
41
|
+
autostart: false,
|
|
42
|
+
env: {},
|
|
43
|
+
}
|
|
44
|
+
];
|
|
30
45
|
|
|
31
46
|
// Prompt templates
|
|
32
47
|
export const appTesterTemplate: BasePromptFragment = {
|
|
@@ -45,7 +60,8 @@ Your role is to inspect the application for user-specified test scenarios throug
|
|
|
45
60
|
4. Help fix issues when needed
|
|
46
61
|
|
|
47
62
|
## Available Playwright Testing Tools
|
|
48
|
-
You have access to these powerful automation tools:
|
|
63
|
+
You have access to these powerful automation tools:
|
|
64
|
+
${REQUIRED_MCP_SERVERS.map(server => `{{prompt:mcp_${server.name}_tools}}`)}
|
|
49
65
|
|
|
50
66
|
## Workflow Approach
|
|
51
67
|
1. **Understand Requirements**: Ask the user to clearly define what needs to be tested
|
|
@@ -86,30 +102,29 @@ export class AppTesterChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
86
102
|
+ 'It can automate testing workflows and provide detailed feedback on application functionality.');
|
|
87
103
|
|
|
88
104
|
override iconClass: string = 'codicon codicon-beaker';
|
|
89
|
-
protected override systemPromptId: string = 'app-tester-
|
|
90
|
-
override prompts = [{ id: 'app-tester-
|
|
105
|
+
protected override systemPromptId: string = 'app-tester-system';
|
|
106
|
+
override prompts = [{ id: 'app-tester-system', defaultVariant: appTesterTemplate, variants: [appTesterTemplateVariant] }];
|
|
91
107
|
|
|
92
108
|
/**
|
|
93
109
|
* Override invoke to check if the Playwright MCP server is running, and if not, ask the user if it should be started.
|
|
94
110
|
*/
|
|
95
111
|
override async invoke(request: MutableChatRequestModel): Promise<void> {
|
|
96
112
|
try {
|
|
97
|
-
|
|
98
|
-
if (!startedServers.includes(EXPECTED_MCP_SERVER_NAME)) {
|
|
113
|
+
if (await this.requiresStartingServers()) {
|
|
99
114
|
// Ask the user if they want to start the server
|
|
100
115
|
request.response.response.addContent(new QuestionResponseContentImpl(
|
|
101
|
-
'The Playwright MCP
|
|
116
|
+
'The Playwright MCP servers are not running. Would you like to start them now? This may install the Playwright MCP servers.',
|
|
102
117
|
[
|
|
103
|
-
{ text: 'Yes, start the
|
|
118
|
+
{ text: 'Yes, start the servers', value: 'yes' },
|
|
104
119
|
{ text: 'No, cancel', value: 'no' }
|
|
105
120
|
],
|
|
106
121
|
request,
|
|
107
122
|
async selectedOption => {
|
|
108
123
|
if (selectedOption.value === 'yes') {
|
|
109
124
|
// Show progress
|
|
110
|
-
const progress = request.response.addProgressMessage({ content: 'Starting Playwright MCP
|
|
125
|
+
const progress = request.response.addProgressMessage({ content: 'Starting Playwright MCP servers.', show: 'whileIncomplete' });
|
|
111
126
|
try {
|
|
112
|
-
await this.
|
|
127
|
+
await this.startServers();
|
|
113
128
|
// Remove progress, continue with normal flow
|
|
114
129
|
request.response.updateProgressMessage({ ...progress, show: 'whileIncomplete', status: 'completed' });
|
|
115
130
|
await super.invoke(request);
|
|
@@ -121,7 +136,7 @@ export class AppTesterChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
121
136
|
}
|
|
122
137
|
} else {
|
|
123
138
|
// Continue without starting the server
|
|
124
|
-
request.response.response.addContent(new MarkdownChatResponseContentImpl('Please setup the MCP
|
|
139
|
+
request.response.response.addContent(new MarkdownChatResponseContentImpl('Please setup the MCP servers.'));
|
|
125
140
|
request.response.complete();
|
|
126
141
|
}
|
|
127
142
|
}
|
|
@@ -139,39 +154,34 @@ export class AppTesterChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
139
154
|
}
|
|
140
155
|
}
|
|
141
156
|
|
|
157
|
+
protected async requiresStartingServers(): Promise<boolean> {
|
|
158
|
+
const allStarted = await Promise.all(REQUIRED_MCP_SERVERS.map(server => this.mcpService.isServerStarted(server.name)));
|
|
159
|
+
return allStarted.some(started => !started);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
protected async startServers(): Promise<void> {
|
|
163
|
+
await Promise.all(REQUIRED_MCP_SERVERS.map(server => this.ensureServerStarted(server)));
|
|
164
|
+
|
|
165
|
+
}
|
|
166
|
+
|
|
142
167
|
/**
|
|
143
168
|
* Starts the Playwright MCP server if it doesn't exist or isn't running.
|
|
144
169
|
*
|
|
145
170
|
* @returns A promise that resolves when the server is started
|
|
146
171
|
*/
|
|
147
|
-
async
|
|
172
|
+
async ensureServerStarted(server: MCPServerDescription): Promise<void> {
|
|
148
173
|
try {
|
|
149
|
-
|
|
150
|
-
if (startedServers.includes(EXPECTED_MCP_SERVER_NAME)) {
|
|
174
|
+
if ((await this.mcpService.isServerStarted(server.name))) {
|
|
151
175
|
return;
|
|
152
176
|
}
|
|
153
|
-
|
|
154
|
-
const mcpServer: MCPServerDescription = {
|
|
155
|
-
name: EXPECTED_MCP_SERVER_NAME,
|
|
156
|
-
command: 'npx',
|
|
157
|
-
args: ['-y', '@playwright/mcp@latest'],
|
|
158
|
-
autostart: false,
|
|
159
|
-
env: {},
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
const availableServers = await this.mcpService.getServerNames();
|
|
163
|
-
if (!availableServers.includes(EXPECTED_MCP_SERVER_NAME)) {
|
|
177
|
+
if (!(await this.mcpService.hasServer(server.name))) {
|
|
164
178
|
const currentServers = this.preferenceService.get<Record<string, MCPServerDescription>>(MCP_SERVERS_PREF, {});
|
|
165
|
-
await this.preferenceService.set(MCP_SERVERS_PREF, {
|
|
166
|
-
|
|
167
|
-
mcpServer
|
|
168
|
-
}, PreferenceScope.User);
|
|
169
|
-
|
|
170
|
-
await this.mcpService.addOrUpdateServer(mcpServer);
|
|
179
|
+
await this.preferenceService.set(MCP_SERVERS_PREF, { ...currentServers, server }, PreferenceScope.User);
|
|
180
|
+
await this.mcpService.addOrUpdateServer(server);
|
|
171
181
|
}
|
|
172
|
-
await this.mcpService.startServer(
|
|
182
|
+
await this.mcpService.startServer(server.name);
|
|
173
183
|
} catch (error) {
|
|
174
|
-
this.logger.error(`Error starting
|
|
184
|
+
this.logger.error(`Error starting MCP server ${server.name}: ${error}`);
|
|
175
185
|
throw error;
|
|
176
186
|
}
|
|
177
187
|
}
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
import { AbstractStreamParsingChatAgent, ChatRequestModel, ChatService, ChatSession, MutableChatModel, MutableChatRequestModel } from '@theia/ai-chat/lib/common';
|
|
17
17
|
import { LanguageModelRequirement } from '@theia/ai-core';
|
|
18
18
|
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
19
|
-
import {
|
|
19
|
+
import { architectSystemVariants, architectTaskSummaryVariants } from '../common/architect-prompt-template';
|
|
20
20
|
import { FILE_CONTENT_FUNCTION_ID, GET_WORKSPACE_FILE_LIST_FUNCTION_ID } from '../common/workspace-functions';
|
|
21
21
|
import { nls } from '@theia/core';
|
|
22
22
|
import { MarkdownStringImpl } from '@theia/core/lib/common/markdown-rendering';
|
|
23
|
-
import { AI_SUMMARIZE_SESSION_AS_TASK_FOR_CODER } from '../common/summarize-session-commands';
|
|
23
|
+
import { AI_SUMMARIZE_SESSION_AS_TASK_FOR_CODER, AI_UPDATE_TASK_CONTEXT_COMMAND } from '../common/summarize-session-commands';
|
|
24
24
|
|
|
25
25
|
@injectable()
|
|
26
26
|
export class ArchitectAgent extends AbstractStreamParsingChatAgent {
|
|
@@ -38,9 +38,9 @@ export class ArchitectAgent extends AbstractStreamParsingChatAgent {
|
|
|
38
38
|
'An AI assistant integrated into Theia IDE, designed to assist software developers. This agent can access the users workspace, it can get a list of all available files \
|
|
39
39
|
and folders and retrieve their content. It cannot modify files. It can therefore answer questions about the current project, project files and source code in the \
|
|
40
40
|
workspace, such as how to build the project, where to put source code, where to find specific code or configurations, etc.');
|
|
41
|
-
override prompts = [
|
|
41
|
+
override prompts = [architectSystemVariants, architectTaskSummaryVariants];
|
|
42
42
|
override functions = [GET_WORKSPACE_FILE_LIST_FUNCTION_ID, FILE_CONTENT_FUNCTION_ID];
|
|
43
|
-
protected override systemPromptId: string | undefined =
|
|
43
|
+
protected override systemPromptId: string | undefined = architectSystemVariants.id;
|
|
44
44
|
|
|
45
45
|
override async invoke(request: MutableChatRequestModel): Promise<void> {
|
|
46
46
|
await super.invoke(request);
|
|
@@ -52,7 +52,10 @@ export class ArchitectAgent extends AbstractStreamParsingChatAgent {
|
|
|
52
52
|
const session = this.chatService.getSessions().find(candidate => candidate.model.id === model.id);
|
|
53
53
|
if (!(model instanceof MutableChatModel) || !session) { return; }
|
|
54
54
|
if (!model.isEmpty()) {
|
|
55
|
-
model.setSuggestions([
|
|
55
|
+
model.setSuggestions([
|
|
56
|
+
new MarkdownStringImpl(`[Summarize this session as a task for Coder](command:${AI_SUMMARIZE_SESSION_AS_TASK_FOR_CODER.id}).`),
|
|
57
|
+
new MarkdownStringImpl(`[Update current task context](command:${AI_UPDATE_TASK_CONTEXT_COMMAND.id}).`)
|
|
58
|
+
]);
|
|
56
59
|
}
|
|
57
60
|
}
|
|
58
61
|
}
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
+
import '../../src/browser/style/index.css';
|
|
18
|
+
|
|
17
19
|
import { ContainerModule } from '@theia/core/shared/inversify';
|
|
18
20
|
import { ChatAgent, DefaultChatAgentId, FallbackChatAgentId } from '@theia/ai-chat/lib/common';
|
|
19
21
|
import { Agent, AIVariableContribution, bindToolProvider } from '@theia/ai-core/lib/common';
|
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
padding: var(--theia-ui-padding);
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
+
.ai-configuration-widget [role="tablist"] {
|
|
6
|
+
overflow: scroll;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.ai-configuration-widget [role="tablist"]::-webkit-scrollbar {
|
|
10
|
+
height: 4px;
|
|
11
|
+
}
|
|
12
|
+
|
|
5
13
|
.theia-ai-settings-container {
|
|
6
14
|
padding: var(--theia-ui-padding);
|
|
7
15
|
}
|
|
@@ -90,8 +98,15 @@
|
|
|
90
98
|
flex-direction: row;
|
|
91
99
|
}
|
|
92
100
|
|
|
93
|
-
|
|
94
|
-
|
|
101
|
+
#ai-agent-configuration-container-widget
|
|
102
|
+
.ai-agent-configuration-main
|
|
103
|
+
.configuration-agents-list {
|
|
104
|
+
min-width: 160px;
|
|
105
|
+
overflow: hidden;
|
|
106
|
+
white-space: nowrap;
|
|
107
|
+
text-overflow: ellipsis;
|
|
108
|
+
padding-left: 0;
|
|
109
|
+
padding: var(--theia-ui-padding);
|
|
95
110
|
}
|
|
96
111
|
|
|
97
112
|
.configuration-agent-panel {
|
|
@@ -128,9 +143,12 @@
|
|
|
128
143
|
}
|
|
129
144
|
|
|
130
145
|
/* Prompt Fragments Configuration Styles */
|
|
146
|
+
.configuration-variables-list,
|
|
147
|
+
.token-usage-configuration-container,
|
|
148
|
+
.ai-tools-configuration-container,
|
|
131
149
|
.ai-prompt-fragments-configuration {
|
|
132
150
|
padding: var(--theia-ui-padding);
|
|
133
|
-
max-width:
|
|
151
|
+
max-width: 600px;
|
|
134
152
|
margin: 0 auto;
|
|
135
153
|
}
|
|
136
154
|
|
|
@@ -422,7 +440,8 @@
|
|
|
422
440
|
gap: 8px;
|
|
423
441
|
}
|
|
424
442
|
|
|
425
|
-
.prompt-fragment-title h2,
|
|
443
|
+
.prompt-fragment-title h2,
|
|
444
|
+
h4 {
|
|
426
445
|
margin-right: 8px;
|
|
427
446
|
margin: 0;
|
|
428
447
|
}
|
|
@@ -448,10 +467,6 @@
|
|
|
448
467
|
}
|
|
449
468
|
|
|
450
469
|
/* MCP Configuration Styles */
|
|
451
|
-
.mcp-configuration-container {
|
|
452
|
-
padding: 16px;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
470
|
.mcp-configuration-title {
|
|
456
471
|
margin: 0 0 16px 0;
|
|
457
472
|
border-bottom: 1px solid var(--theia-panelTitle-activeBorder);
|
|
@@ -673,11 +688,6 @@
|
|
|
673
688
|
* AI Tools Configuration Widget Styles
|
|
674
689
|
* Only touch styles in this section for the tools configuration widget
|
|
675
690
|
*/
|
|
676
|
-
.ai-tools-configuration-container {
|
|
677
|
-
padding: 16px;
|
|
678
|
-
max-width: 600px;
|
|
679
|
-
}
|
|
680
|
-
|
|
681
691
|
.ai-tools-configuration-default-section {
|
|
682
692
|
margin-bottom: 24px;
|
|
683
693
|
}
|
|
@@ -688,7 +698,6 @@
|
|
|
688
698
|
}
|
|
689
699
|
|
|
690
700
|
.ai-tools-configuration-default-select {
|
|
691
|
-
font-weight: bold;
|
|
692
701
|
font-size: 14px;
|
|
693
702
|
padding: 4px;
|
|
694
703
|
}
|
|
@@ -728,7 +737,6 @@
|
|
|
728
737
|
}
|
|
729
738
|
|
|
730
739
|
.ai-tools-configuration-tool-select {
|
|
731
|
-
font-weight: bold;
|
|
732
740
|
margin-right: 8px;
|
|
733
741
|
}
|
|
734
742
|
|
|
@@ -736,22 +744,9 @@
|
|
|
736
744
|
font-size: 18px;
|
|
737
745
|
}
|
|
738
746
|
|
|
739
|
-
.ai-tools-configuration-tool-select--yolo {
|
|
740
|
-
color: green !important;
|
|
741
|
-
}
|
|
742
|
-
.ai-tools-configuration-tool-select--disabled {
|
|
743
|
-
color: red !important;
|
|
744
|
-
}
|
|
745
|
-
.ai-tools-configuration-tool-select--confirm {
|
|
746
|
-
color: orange !important;
|
|
747
|
-
}
|
|
748
747
|
/* End AI Tools Configuration Widget Styles */
|
|
749
748
|
|
|
750
749
|
/* Token Usage Configuration Styles */
|
|
751
|
-
.token-usage-configuration-container {
|
|
752
|
-
padding: 16px;
|
|
753
|
-
}
|
|
754
|
-
|
|
755
750
|
.token-usage-configuration-title {
|
|
756
751
|
margin: 0 0 16px 0;
|
|
757
752
|
border-bottom: 1px solid var(--theia-widget-border);
|