@theia/ai-ide 1.64.0-next.28 → 1.64.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 +5 -2
- package/lib/browser/ai-configuration/agent-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/agent-configuration-widget.js +15 -1
- package/lib/browser/ai-configuration/agent-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/ai-configuration-service.d.ts +6 -1
- package/lib/browser/ai-configuration/ai-configuration-service.d.ts.map +1 -1
- package/lib/browser/ai-configuration/ai-configuration-service.js +10 -1
- package/lib/browser/ai-configuration/ai-configuration-service.js.map +1 -1
- package/lib/browser/ai-configuration/ai-configuration-widget.d.ts +2 -0
- package/lib/browser/ai-configuration/ai-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/ai-configuration-widget.js +7 -1
- package/lib/browser/ai-configuration/ai-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/language-model-renderer.d.ts +4 -2
- package/lib/browser/ai-configuration/language-model-renderer.d.ts.map +1 -1
- package/lib/browser/ai-configuration/language-model-renderer.js +49 -71
- package/lib/browser/ai-configuration/language-model-renderer.js.map +1 -1
- package/lib/browser/ai-configuration/model-aliases-configuration-widget.d.ts +41 -0
- package/lib/browser/ai-configuration/model-aliases-configuration-widget.d.ts.map +1 -0
- package/lib/browser/ai-configuration/model-aliases-configuration-widget.js +225 -0
- package/lib/browser/ai-configuration/model-aliases-configuration-widget.js.map +1 -0
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.d.ts +7 -3
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.js +35 -13
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/template-settings-renderer.d.ts.map +1 -1
- package/lib/browser/ai-configuration/template-settings-renderer.js +11 -6
- package/lib/browser/ai-configuration/template-settings-renderer.js.map +1 -1
- package/lib/browser/ai-ide-activation-service.d.ts +18 -0
- package/lib/browser/ai-ide-activation-service.d.ts.map +1 -0
- package/lib/browser/ai-ide-activation-service.js +72 -0
- package/lib/browser/ai-ide-activation-service.js.map +1 -0
- package/lib/browser/ai-ide-preferences.d.ts +4 -0
- package/lib/browser/ai-ide-preferences.d.ts.map +1 -0
- package/lib/browser/ai-ide-preferences.js +43 -0
- package/lib/browser/ai-ide-preferences.js.map +1 -0
- package/lib/browser/app-tester-chat-agent.d.ts +3 -6
- package/lib/browser/app-tester-chat-agent.d.ts.map +1 -1
- package/lib/browser/app-tester-chat-agent.js +6 -71
- package/lib/browser/app-tester-chat-agent.js.map +1 -1
- package/lib/browser/app-tester-prompt-template.d.ts +6 -0
- package/lib/browser/app-tester-prompt-template.d.ts.map +1 -0
- package/lib/browser/app-tester-prompt-template.js +79 -0
- package/lib/browser/app-tester-prompt-template.js.map +1 -0
- package/lib/browser/architect-agent.js +1 -1
- package/lib/browser/architect-agent.js.map +1 -1
- package/lib/browser/coder-agent.js +1 -1
- package/lib/browser/coder-agent.js.map +1 -1
- package/lib/browser/context-functions.d.ts.map +1 -1
- package/lib/browser/context-functions.js +12 -0
- package/lib/browser/context-functions.js.map +1 -1
- package/lib/browser/context-functions.spec.d.ts +2 -0
- package/lib/browser/context-functions.spec.d.ts.map +1 -0
- package/lib/browser/context-functions.spec.js +93 -0
- package/lib/browser/context-functions.spec.js.map +1 -0
- package/lib/browser/file-changeset-function.spec.d.ts +2 -0
- package/lib/browser/file-changeset-function.spec.d.ts.map +1 -0
- package/lib/browser/file-changeset-function.spec.js +45 -0
- package/lib/browser/file-changeset-function.spec.js.map +1 -0
- package/lib/browser/file-changeset-functions.d.ts +13 -3
- package/lib/browser/file-changeset-functions.d.ts.map +1 -1
- package/lib/browser/file-changeset-functions.js +100 -29
- package/lib/browser/file-changeset-functions.js.map +1 -1
- package/lib/browser/file-changeset-functions.spec.d.ts +2 -0
- package/lib/browser/file-changeset-functions.spec.d.ts.map +1 -0
- package/lib/browser/file-changeset-functions.spec.js +161 -0
- package/lib/browser/file-changeset-functions.spec.js.map +1 -0
- package/lib/browser/frontend-module.d.ts.map +1 -1
- package/lib/browser/frontend-module.js +20 -0
- package/lib/browser/frontend-module.js.map +1 -1
- package/lib/browser/ide-chat-welcome-message-provider.js +2 -2
- package/lib/browser/ide-chat-welcome-message-provider.js.map +1 -1
- package/lib/browser/test/tool-provider-cancellation-test-util.spec.d.ts +2 -0
- package/lib/browser/test/tool-provider-cancellation-test-util.spec.d.ts.map +1 -0
- package/lib/browser/test/tool-provider-cancellation-test-util.spec.js +52 -0
- package/lib/browser/test/tool-provider-cancellation-test-util.spec.js.map +1 -0
- package/lib/browser/workspace-functions.d.ts +3 -3
- package/lib/browser/workspace-functions.d.ts.map +1 -1
- package/lib/browser/workspace-functions.js +79 -28
- package/lib/browser/workspace-functions.js.map +1 -1
- package/lib/browser/workspace-functions.spec.d.ts +2 -0
- package/lib/browser/workspace-functions.spec.d.ts.map +1 -0
- package/lib/browser/workspace-functions.spec.js +161 -0
- package/lib/browser/workspace-functions.spec.js.map +1 -0
- package/lib/browser/workspace-launch-provider.d.ts +24 -0
- package/lib/browser/workspace-launch-provider.d.ts.map +1 -0
- package/lib/browser/workspace-launch-provider.js +216 -0
- package/lib/browser/workspace-launch-provider.js.map +1 -0
- package/lib/browser/workspace-launch-provider.spec.d.ts +2 -0
- package/lib/browser/workspace-launch-provider.spec.d.ts.map +1 -0
- package/lib/browser/workspace-launch-provider.spec.js +245 -0
- package/lib/browser/workspace-launch-provider.spec.js.map +1 -0
- package/lib/browser/workspace-search-provider.d.ts.map +1 -1
- package/lib/browser/workspace-search-provider.js +9 -0
- package/lib/browser/workspace-search-provider.js.map +1 -1
- package/lib/browser/workspace-search-provider.spec.js +59 -203
- package/lib/browser/workspace-search-provider.spec.js.map +1 -1
- package/lib/browser/workspace-task-provider.d.ts.map +1 -1
- package/lib/browser/workspace-task-provider.js +8 -1
- package/lib/browser/workspace-task-provider.js.map +1 -1
- package/lib/browser/workspace-task-provider.spec.d.ts +2 -0
- package/lib/browser/workspace-task-provider.spec.d.ts.map +1 -0
- package/lib/browser/workspace-task-provider.spec.js +109 -0
- package/lib/browser/workspace-task-provider.spec.js.map +1 -0
- package/lib/common/architect-prompt-template.d.ts.map +1 -1
- package/lib/common/architect-prompt-template.js +11 -0
- package/lib/common/architect-prompt-template.js.map +1 -1
- package/lib/common/command-chat-agents.js +1 -1
- package/lib/common/command-chat-agents.js.map +1 -1
- package/lib/common/orchestrator-chat-agent.js +1 -1
- package/lib/common/orchestrator-chat-agent.js.map +1 -1
- package/lib/common/universal-chat-agent.js +1 -1
- package/lib/common/universal-chat-agent.js.map +1 -1
- package/lib/common/workspace-functions.d.ts +3 -0
- package/lib/common/workspace-functions.d.ts.map +1 -1
- package/lib/common/workspace-functions.js +4 -1
- package/lib/common/workspace-functions.js.map +1 -1
- package/package.json +18 -17
- package/src/browser/ai-configuration/agent-configuration-widget.tsx +18 -2
- package/src/browser/ai-configuration/ai-configuration-service.ts +14 -1
- package/src/browser/ai-configuration/ai-configuration-widget.tsx +7 -1
- package/src/browser/ai-configuration/language-model-renderer.tsx +87 -59
- package/src/browser/ai-configuration/model-aliases-configuration-widget.tsx +279 -0
- package/src/browser/ai-configuration/prompt-fragments-configuration-widget.tsx +43 -13
- package/src/browser/ai-configuration/template-settings-renderer.tsx +11 -7
- package/src/browser/ai-ide-activation-service.ts +65 -0
- package/src/browser/ai-ide-preferences.ts +44 -0
- package/src/browser/app-tester-chat-agent.ts +5 -73
- package/src/browser/app-tester-prompt-template.ts +81 -0
- package/src/browser/architect-agent.ts +1 -1
- package/src/browser/coder-agent.ts +1 -1
- package/src/browser/context-functions.spec.ts +102 -0
- package/src/browser/context-functions.ts +11 -0
- package/src/browser/file-changeset-function.spec.ts +52 -0
- package/src/browser/file-changeset-functions.spec.ts +212 -0
- package/src/browser/file-changeset-functions.ts +102 -25
- package/src/browser/frontend-module.ts +29 -1
- package/src/browser/ide-chat-welcome-message-provider.tsx +4 -4
- package/src/browser/style/index.css +111 -6
- package/src/browser/test/tool-provider-cancellation-test-util.spec.ts +60 -0
- package/src/browser/workspace-functions.spec.ts +199 -0
- package/src/browser/workspace-functions.ts +105 -32
- package/src/browser/workspace-launch-provider.spec.ts +320 -0
- package/src/browser/workspace-launch-provider.ts +231 -0
- package/src/browser/workspace-search-provider.spec.ts +79 -229
- package/src/browser/workspace-search-provider.ts +10 -1
- package/src/browser/workspace-task-provider.spec.ts +125 -0
- package/src/browser/workspace-task-provider.ts +7 -2
- package/src/common/architect-prompt-template.ts +11 -0
- package/src/common/command-chat-agents.ts +1 -1
- package/src/common/orchestrator-chat-agent.ts +1 -1
- package/src/common/universal-chat-agent.ts +1 -1
- package/src/common/workspace-functions.ts +3 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 EclipseSource GmbH.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
import * as React from '@theia/core/shared/react';
|
|
17
|
+
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
18
|
+
import { ReactWidget } from '@theia/core/lib/browser/widgets/react-widget';
|
|
19
|
+
import { LanguageModelAliasRegistry, LanguageModelAlias } from '@theia/ai-core/lib/common/language-model-alias';
|
|
20
|
+
import { FrontendLanguageModelRegistry, LanguageModel, LanguageModelRegistry, LanguageModelRequirement } from '@theia/ai-core/lib/common/language-model';
|
|
21
|
+
import { nls } from '@theia/core/lib/common/nls';
|
|
22
|
+
import { AIConfigurationSelectionService } from './ai-configuration-service';
|
|
23
|
+
import { AgentService, AISettingsService } from '@theia/ai-core';
|
|
24
|
+
|
|
25
|
+
export interface ModelAliasesConfigurationProps {
|
|
26
|
+
languageModelAliasRegistry: LanguageModelAliasRegistry;
|
|
27
|
+
languageModelRegistry: LanguageModelRegistry;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@injectable()
|
|
31
|
+
export class ModelAliasesConfigurationWidget extends ReactWidget {
|
|
32
|
+
static readonly ID = 'ai-model-aliases-configuration-widget';
|
|
33
|
+
static readonly LABEL = nls.localize('theia/ai/core/modelAliasesConfiguration/label', 'Model Aliases');
|
|
34
|
+
|
|
35
|
+
@inject(LanguageModelAliasRegistry)
|
|
36
|
+
protected readonly languageModelAliasRegistry: LanguageModelAliasRegistry;
|
|
37
|
+
@inject(LanguageModelRegistry)
|
|
38
|
+
protected readonly languageModelRegistry: FrontendLanguageModelRegistry;
|
|
39
|
+
@inject(AIConfigurationSelectionService)
|
|
40
|
+
protected readonly aiConfigurationSelectionService: AIConfigurationSelectionService;
|
|
41
|
+
@inject(AISettingsService)
|
|
42
|
+
protected readonly aiSettingsService: AISettingsService;
|
|
43
|
+
@inject(AgentService)
|
|
44
|
+
protected readonly agentService: AgentService;
|
|
45
|
+
|
|
46
|
+
protected aliases: LanguageModelAlias[] = [];
|
|
47
|
+
protected languageModels: LanguageModel[] = [];
|
|
48
|
+
/**
|
|
49
|
+
* Map from alias ID to a list of agent IDs that have a language model requirement for that alias.
|
|
50
|
+
*/
|
|
51
|
+
protected matchingAgentIdsForAliasMap: Map<string, string[]> = new Map();
|
|
52
|
+
/**
|
|
53
|
+
* Map from alias ID to the resolved LanguageModel (what the alias currently evaluates to).
|
|
54
|
+
*/
|
|
55
|
+
protected resolvedModelForAlias: Map<string, LanguageModel | undefined> = new Map();
|
|
56
|
+
|
|
57
|
+
@postConstruct()
|
|
58
|
+
protected init(): void {
|
|
59
|
+
this.id = ModelAliasesConfigurationWidget.ID;
|
|
60
|
+
this.title.label = ModelAliasesConfigurationWidget.LABEL;
|
|
61
|
+
this.title.closable = false;
|
|
62
|
+
|
|
63
|
+
const aliasesPromise = this.loadAliases();
|
|
64
|
+
const languageModelsPromise = this.loadLanguageModels();
|
|
65
|
+
const matchingAgentsPromise = this.loadMatchingAgentIdsForAllAliases();
|
|
66
|
+
Promise.all([aliasesPromise, languageModelsPromise, matchingAgentsPromise]).then(() => this.update());
|
|
67
|
+
|
|
68
|
+
this.languageModelAliasRegistry.ready.then(() =>
|
|
69
|
+
this.toDispose.push(this.languageModelAliasRegistry.onDidChange(async () => {
|
|
70
|
+
await this.loadAliases();
|
|
71
|
+
this.update();
|
|
72
|
+
}))
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
this.toDispose.pushAll([
|
|
76
|
+
this.languageModelRegistry.onChange(async () => {
|
|
77
|
+
await this.loadAliases();
|
|
78
|
+
await this.loadLanguageModels();
|
|
79
|
+
this.update();
|
|
80
|
+
}),
|
|
81
|
+
this.aiSettingsService.onDidChange(async () => {
|
|
82
|
+
await this.loadMatchingAgentIdsForAllAliases();
|
|
83
|
+
this.update();
|
|
84
|
+
}),
|
|
85
|
+
this.aiConfigurationSelectionService.onDidAliasChange(() => this.update())
|
|
86
|
+
]);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
protected async loadAliases(): Promise<void> {
|
|
90
|
+
await this.languageModelAliasRegistry.ready;
|
|
91
|
+
this.aliases = this.languageModelAliasRegistry.getAliases();
|
|
92
|
+
// Set the initial selection if not set
|
|
93
|
+
if (this.aliases.length > 0 && !this.aiConfigurationSelectionService.getSelectedAliasId()) {
|
|
94
|
+
this.aiConfigurationSelectionService.setSelectedAliasId(this.aliases[0].id);
|
|
95
|
+
}
|
|
96
|
+
await this.loadMatchingAgentIdsForAllAliases();
|
|
97
|
+
// Resolve evaluated models for each alias
|
|
98
|
+
this.resolvedModelForAlias = new Map();
|
|
99
|
+
for (const alias of this.aliases) {
|
|
100
|
+
const model = await this.languageModelRegistry.getReadyLanguageModel(alias.id);
|
|
101
|
+
this.resolvedModelForAlias.set(alias.id, model);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
protected async loadLanguageModels(): Promise<void> {
|
|
106
|
+
this.languageModels = await this.languageModelRegistry.getLanguageModels();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Loads a map from alias ID to a list of agent IDs that have a language model requirement for that alias.
|
|
111
|
+
*/
|
|
112
|
+
protected async loadMatchingAgentIdsForAllAliases(): Promise<void> {
|
|
113
|
+
const agents = this.agentService.getAllAgents();
|
|
114
|
+
const aliasMap: Map<string, string[]> = new Map();
|
|
115
|
+
for (const alias of this.aliases) {
|
|
116
|
+
const matchingAgentIds: string[] = [];
|
|
117
|
+
for (const agent of agents) {
|
|
118
|
+
const requirementSetting = await this.aiSettingsService.getAgentSettings(agent.id);
|
|
119
|
+
if (requirementSetting?.languageModelRequirements) {
|
|
120
|
+
// requirement is set via settings, check if it is this alias
|
|
121
|
+
if (requirementSetting?.languageModelRequirements?.find(e => e.identifier === alias.id)) {
|
|
122
|
+
matchingAgentIds.push(agent.id);
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
// requirement is NOT set via settings, check if this alias is the default for this agent
|
|
126
|
+
if (agent.languageModelRequirements.some((req: LanguageModelRequirement) => req.identifier === alias.id)) {
|
|
127
|
+
matchingAgentIds.push(agent.id);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
aliasMap.set(alias.id, matchingAgentIds);
|
|
132
|
+
}
|
|
133
|
+
this.matchingAgentIdsForAliasMap = aliasMap;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
protected handleAliasSelectedModelIdChange = (alias: LanguageModelAlias, event: React.ChangeEvent<HTMLSelectElement>): void => {
|
|
137
|
+
const newModelId = event.target.value || undefined;
|
|
138
|
+
const updatedAlias: LanguageModelAlias = {
|
|
139
|
+
...alias,
|
|
140
|
+
selectedModelId: newModelId
|
|
141
|
+
};
|
|
142
|
+
this.languageModelAliasRegistry.ready.then(() => {
|
|
143
|
+
this.languageModelAliasRegistry.addAlias(updatedAlias);
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
render(): React.ReactNode {
|
|
148
|
+
const selectedAliasId = this.aiConfigurationSelectionService.getSelectedAliasId();
|
|
149
|
+
const selectedAlias = this.aliases.find(alias => alias.id === selectedAliasId);
|
|
150
|
+
return (
|
|
151
|
+
<div className="model-alias-configuration-main">
|
|
152
|
+
<div className="model-alias-configuration-list preferences-tree-widget theia-TreeContainer ai-model-alias-list">
|
|
153
|
+
<ul>
|
|
154
|
+
{this.aliases.map(alias => (
|
|
155
|
+
<li
|
|
156
|
+
key={alias.id}
|
|
157
|
+
className={`theia-TreeNode theia-CompositeTreeNode${alias.id === selectedAliasId ? ' theia-mod-selected' : ''}`}
|
|
158
|
+
onClick={() => this.aiConfigurationSelectionService.setSelectedAliasId(alias.id)}
|
|
159
|
+
>
|
|
160
|
+
<span>{alias.id}</span>
|
|
161
|
+
</li>
|
|
162
|
+
))}
|
|
163
|
+
</ul>
|
|
164
|
+
</div>
|
|
165
|
+
<div className="model-alias-configuration-panel preferences-editor-widget">
|
|
166
|
+
{selectedAlias ? this.renderAliasDetail(selectedAlias, this.languageModels) : (
|
|
167
|
+
<div>
|
|
168
|
+
{nls.localize('theia/ai/core/modelAliasesConfiguration/selectAlias', 'Please select a Model Alias.')}
|
|
169
|
+
</div>
|
|
170
|
+
)}
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
protected renderAliasDetail(alias: LanguageModelAlias, languageModels: LanguageModel[]): React.ReactNode {
|
|
177
|
+
const availableModelIds = languageModels.map(m => m.id);
|
|
178
|
+
const selectedModelId = alias.selectedModelId ?? '';
|
|
179
|
+
const isInvalidModel = !!selectedModelId && !availableModelIds.includes(alias.selectedModelId ?? '');
|
|
180
|
+
const agentIds = this.matchingAgentIdsForAliasMap.get(alias.id) || [];
|
|
181
|
+
const agents = this.agentService.getAllAgents().filter(agent => agentIds.includes(agent.id));
|
|
182
|
+
const resolvedModel = this.resolvedModelForAlias.get(alias.id);
|
|
183
|
+
return (
|
|
184
|
+
<div>
|
|
185
|
+
<div className="settings-section-title settings-section-category-title ai-alias-detail-title">
|
|
186
|
+
<span>{alias.id}</span>
|
|
187
|
+
</div>
|
|
188
|
+
{alias.description && <div className="ai-alias-detail-description">{alias.description}</div>}
|
|
189
|
+
<div className="ai-alias-detail-selected-model">
|
|
190
|
+
<label>{nls.localize('theia/ai/core/modelAliasesConfiguration/selectedModelId', 'Selected Model')}: </label>
|
|
191
|
+
<select
|
|
192
|
+
className={`theia-select template-variant-selector ${isInvalidModel ? 'error' : ''}`}
|
|
193
|
+
value={isInvalidModel ? 'invalid' : selectedModelId}
|
|
194
|
+
onChange={event => this.handleAliasSelectedModelIdChange(alias, event)}
|
|
195
|
+
>
|
|
196
|
+
{isInvalidModel && (
|
|
197
|
+
<option value="invalid" disabled>
|
|
198
|
+
{nls.localize('theia/ai/core/modelAliasesConfiguration/unavailableModel', 'Selected model is no longer available')}
|
|
199
|
+
</option>
|
|
200
|
+
)}
|
|
201
|
+
<option value="" className='ai-language-model-item-ready'>
|
|
202
|
+
{nls.localize('theia/ai/core/modelAliasesConfiguration/defaultList', '[Default list]')}
|
|
203
|
+
</option>
|
|
204
|
+
{[...languageModels]
|
|
205
|
+
.sort((a, b) => (a.name ?? a.id).localeCompare(b.name ?? b.id))
|
|
206
|
+
.map(model => {
|
|
207
|
+
const isNotReady = model.status.status !== 'ready';
|
|
208
|
+
return (
|
|
209
|
+
<option
|
|
210
|
+
key={model.id}
|
|
211
|
+
value={model.id}
|
|
212
|
+
className={isNotReady ? 'ai-language-model-item-not-ready' : 'ai-language-model-item-ready'}
|
|
213
|
+
title={isNotReady && model.status.message ? model.status.message : undefined}
|
|
214
|
+
>
|
|
215
|
+
{model.name ?? model.id} {isNotReady ? '✗' : '✓'}
|
|
216
|
+
</option>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
)}
|
|
220
|
+
</select>
|
|
221
|
+
</div>
|
|
222
|
+
{alias.selectedModelId === undefined &&
|
|
223
|
+
<><div className="ai-alias-detail-defaults">
|
|
224
|
+
<ol>
|
|
225
|
+
{alias.defaultModelIds.map(modelId => {
|
|
226
|
+
const model = this.languageModels.find(m => m.id === modelId);
|
|
227
|
+
const isReady = model?.status.status === 'ready';
|
|
228
|
+
return (
|
|
229
|
+
<li key={modelId}>
|
|
230
|
+
{isReady ? (
|
|
231
|
+
<span className={modelId === resolvedModel?.id ? 'ai-alias-priority-item-resolved' : 'ai-alias-priority-item-ready'}>
|
|
232
|
+
{modelId} <span className="ai-model-status-ready" title="Ready">✓</span>
|
|
233
|
+
</span>
|
|
234
|
+
) : (
|
|
235
|
+
<span className="ai-model-default-not-ready">
|
|
236
|
+
{modelId} <span className="ai-model-status-not-ready" title="Not ready">✗</span>
|
|
237
|
+
</span>
|
|
238
|
+
)}
|
|
239
|
+
</li>
|
|
240
|
+
);
|
|
241
|
+
})}
|
|
242
|
+
</ol>
|
|
243
|
+
</div><div className="ai-alias-evaluates-to-container">
|
|
244
|
+
<label className="ai-alias-evaluates-to-label">{nls.localize('theia/ai/core/modelAliasesConfiguration/evaluatesTo', 'Evaluates to')}:</label>
|
|
245
|
+
{resolvedModel ? (
|
|
246
|
+
<span className="ai-alias-evaluates-to-value">
|
|
247
|
+
{resolvedModel.name ?? resolvedModel.id}
|
|
248
|
+
{resolvedModel.status.status === 'ready' ? (
|
|
249
|
+
<span className="ai-model-status-ready" title="Ready">✓</span>
|
|
250
|
+
) : (
|
|
251
|
+
<span className="ai-model-status-not-ready" title={resolvedModel.status.message || 'Not ready'}>✗</span>
|
|
252
|
+
)}
|
|
253
|
+
</span>
|
|
254
|
+
) : (
|
|
255
|
+
<span className="ai-alias-evaluates-to-unresolved">
|
|
256
|
+
{nls.localize('theia/ai/core/modelAliasesConfiguration/noResolvedModel', 'No model ready for this alias.')}
|
|
257
|
+
</span>
|
|
258
|
+
)}
|
|
259
|
+
</div></>
|
|
260
|
+
}
|
|
261
|
+
<div className="ai-alias-detail-agents">
|
|
262
|
+
<label>{nls.localize('theia/ai/core/modelAliasesConfiguration/agents', 'Agents using this Alias')}:</label>
|
|
263
|
+
<ul>
|
|
264
|
+
{agents.length > 0 ? (
|
|
265
|
+
agents.map(agent => (
|
|
266
|
+
<li key={agent.id}>
|
|
267
|
+
<span>{agent.name}</span>
|
|
268
|
+
{agent.id !== agent.name && <span className="ai-alias-agent-id">({agent.id})</span>}
|
|
269
|
+
</li>
|
|
270
|
+
))
|
|
271
|
+
) : (
|
|
272
|
+
<span>{nls.localize('theia/ai/core/modelAliasesConfiguration/noAgents', 'No agents use this alias.')}</span>
|
|
273
|
+
)}
|
|
274
|
+
</ul>
|
|
275
|
+
</div>
|
|
276
|
+
</div >
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
@@ -77,15 +77,20 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
77
77
|
protected availableAgents: Agent[] = [];
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
|
-
* Maps prompt variant set IDs to their
|
|
80
|
+
* Maps prompt variant set IDs to their resolved variant IDs
|
|
81
81
|
*/
|
|
82
|
-
protected
|
|
82
|
+
protected effectiveVariantIds: Map<string, string | undefined> = new Map();
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
85
|
* Maps prompt variant set IDs to their default variant IDs
|
|
86
86
|
*/
|
|
87
87
|
protected defaultVariantIds: Map<string, string | undefined> = new Map();
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Maps prompt variant set IDs to their user selected variant IDs
|
|
91
|
+
*/
|
|
92
|
+
protected userSelectedVariantIds: Map<string, string | undefined> = new Map();
|
|
93
|
+
|
|
89
94
|
@inject(PromptService) protected promptService: PromptService;
|
|
90
95
|
@inject(AgentService) protected agentService: AgentService;
|
|
91
96
|
|
|
@@ -103,10 +108,6 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
103
108
|
this.promptService.onPromptsChange(() => {
|
|
104
109
|
this.loadPromptFragments();
|
|
105
110
|
}),
|
|
106
|
-
this.promptService.onSelectedVariantChange(notification => {
|
|
107
|
-
this.selectedVariantIds.set(notification.promptVariantSetId, notification.variantId);
|
|
108
|
-
this.update();
|
|
109
|
-
}),
|
|
110
111
|
this.agentService.onDidChangeAgents(() => {
|
|
111
112
|
this.loadAgents();
|
|
112
113
|
})
|
|
@@ -117,7 +118,7 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
117
118
|
* Loads all prompt fragments and prompt variant sets from the prompt service.
|
|
118
119
|
* Preserves UI expansion states and updates variant information.
|
|
119
120
|
*/
|
|
120
|
-
protected
|
|
121
|
+
protected loadPromptFragments(): void {
|
|
121
122
|
this.promptFragmentMap = this.promptService.getAllPromptFragments();
|
|
122
123
|
this.promptVariantsMap = this.promptService.getPromptVariantSets();
|
|
123
124
|
this.activePromptFragments = this.promptService.getActivePromptFragments();
|
|
@@ -154,11 +155,13 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
154
155
|
})
|
|
155
156
|
);
|
|
156
157
|
|
|
157
|
-
// Update variant information (selected/default) for prompt variant sets
|
|
158
|
+
// Update variant information (selected/default/effective) for prompt variant sets
|
|
158
159
|
for (const promptVariantSetId of this.promptVariantsMap.keys()) {
|
|
159
|
-
const
|
|
160
|
-
const defaultId =
|
|
161
|
-
this.
|
|
160
|
+
const effectiveId = this.promptService.getEffectiveVariantId(promptVariantSetId);
|
|
161
|
+
const defaultId = this.promptService.getDefaultVariantId(promptVariantSetId);
|
|
162
|
+
const selectedId = this.promptService.getSelectedVariantId(promptVariantSetId) ?? defaultId;
|
|
163
|
+
this.userSelectedVariantIds.set(promptVariantSetId, selectedId);
|
|
164
|
+
this.effectiveVariantIds.set(promptVariantSetId, effectiveId);
|
|
162
165
|
this.defaultVariantIds.set(promptVariantSetId, defaultId);
|
|
163
166
|
}
|
|
164
167
|
|
|
@@ -405,8 +408,9 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
405
408
|
protected renderPromptVariantSet(promptVariantSetId: string, variantIds: string[]): React.ReactNode {
|
|
406
409
|
const isSectionExpanded = this.expandedPromptVariantSetIds.has(promptVariantSetId);
|
|
407
410
|
|
|
408
|
-
// Get selected and default variant IDs from our class properties
|
|
409
|
-
const selectedVariantId = this.
|
|
411
|
+
// Get selected, effective, and default variant IDs from our class properties
|
|
412
|
+
const selectedVariantId = this.userSelectedVariantIds.get(promptVariantSetId);
|
|
413
|
+
const effectiveVariantId = this.effectiveVariantIds.get(promptVariantSetId);
|
|
410
414
|
const defaultVariantId = this.defaultVariantIds.get(promptVariantSetId);
|
|
411
415
|
|
|
412
416
|
// Get variant fragments grouped by ID
|
|
@@ -421,6 +425,31 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
421
425
|
|
|
422
426
|
const relatedAgents = this.getAgentsUsingPromptVariantId(promptVariantSetId);
|
|
423
427
|
|
|
428
|
+
// Determine warning/error state
|
|
429
|
+
let variantSetMessage: React.ReactNode | undefined = undefined;
|
|
430
|
+
if (effectiveVariantId === undefined) {
|
|
431
|
+
// Error: effectiveId is undefined, so nothing works
|
|
432
|
+
variantSetMessage = (
|
|
433
|
+
<div className="prompt-variant-error">
|
|
434
|
+
<span className="codicon codicon-error"></span>
|
|
435
|
+
{nls.localize('theia/ai/core/promptFragmentsConfiguration/variantSetError',
|
|
436
|
+
'The selected variant does not exist and no default could be found. Please check your configuration.')}
|
|
437
|
+
</div>
|
|
438
|
+
);
|
|
439
|
+
} else {
|
|
440
|
+
const needsWarning = selectedVariantId ? effectiveVariantId !== selectedVariantId : effectiveVariantId !== defaultVariantId;
|
|
441
|
+
if (needsWarning) {
|
|
442
|
+
// Warning: selectedId is set but does not exist, so default is used
|
|
443
|
+
variantSetMessage = (
|
|
444
|
+
<div className="prompt-variant-warning">
|
|
445
|
+
<span className="codicon codicon-warning"></span>
|
|
446
|
+
{nls.localize('theia/ai/core/promptFragmentsConfiguration/variantSetWarning',
|
|
447
|
+
'The selected variant does not exist. The default variant is being used instead.')}
|
|
448
|
+
</div>
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
424
453
|
return (
|
|
425
454
|
<div className="prompt-fragment-section" key={`variant-${promptVariantSetId}`}>
|
|
426
455
|
<div
|
|
@@ -446,6 +475,7 @@ export class AIPromptFragmentsConfigurationWidget extends ReactWidget {
|
|
|
446
475
|
</div>
|
|
447
476
|
{isSectionExpanded && (
|
|
448
477
|
<div className="prompt-fragment-body">
|
|
478
|
+
{variantSetMessage}
|
|
449
479
|
<div className="prompt-fragment-description">
|
|
450
480
|
<p>{nls.localize('theia/ai/core/promptFragmentsConfiguration/variantsOfSystemPrompt', 'Variants of this prompt variant set:')}</p>
|
|
451
481
|
</div>
|
|
@@ -33,14 +33,18 @@ export const PromptVariantRenderer: React.FC<PromptVariantRendererProps> = ({
|
|
|
33
33
|
const [selectedVariant, setSelectedVariant] = React.useState<string>(defaultVariantId!);
|
|
34
34
|
|
|
35
35
|
React.useEffect(() => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
const currentVariant = promptService.getSelectedVariantId(promptVariantSet.id);
|
|
37
|
+
setSelectedVariant(currentVariant ?? defaultVariantId!);
|
|
38
|
+
|
|
39
|
+
const disposable = promptService.onSelectedVariantChange(notification => {
|
|
40
|
+
if (notification.promptVariantSetId === promptVariantSet.id) {
|
|
41
|
+
setSelectedVariant(notification.variantId ?? defaultVariantId!);
|
|
41
42
|
}
|
|
42
|
-
})
|
|
43
|
-
|
|
43
|
+
});
|
|
44
|
+
return () => {
|
|
45
|
+
disposable.dispose();
|
|
46
|
+
};
|
|
47
|
+
}, [promptVariantSet.id, promptService, defaultVariantId]);
|
|
44
48
|
|
|
45
49
|
const isInvalidVariant = !variantIds.includes(selectedVariant);
|
|
46
50
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 EclipseSource GmbH.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
17
|
+
import { FrontendApplicationContribution, PreferenceService } from '@theia/core/lib/browser';
|
|
18
|
+
import { Emitter, MaybePromise, Event, } from '@theia/core';
|
|
19
|
+
import { ContextKeyService, ContextKey } from '@theia/core/lib/browser/context-key-service';
|
|
20
|
+
import { AIActivationService, ENABLE_AI_CONTEXT_KEY } from '@theia/ai-core/lib/browser/ai-activation-service';
|
|
21
|
+
import { PREFERENCE_NAME_ENABLE_AI } from './ai-ide-preferences';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Implements AI Activation Service based on preferences.
|
|
25
|
+
*/
|
|
26
|
+
@injectable()
|
|
27
|
+
export class AIIdeActivationServiceImpl implements AIActivationService, FrontendApplicationContribution {
|
|
28
|
+
@inject(ContextKeyService)
|
|
29
|
+
protected readonly contextKeyService: ContextKeyService;
|
|
30
|
+
|
|
31
|
+
@inject(PreferenceService)
|
|
32
|
+
protected preferenceService: PreferenceService;
|
|
33
|
+
|
|
34
|
+
protected isAiEnabledKey: ContextKey<boolean>;
|
|
35
|
+
|
|
36
|
+
protected onDidChangeAIEnabled = new Emitter<boolean>();
|
|
37
|
+
get onDidChangeActiveStatus(): Event<boolean> {
|
|
38
|
+
return this.onDidChangeAIEnabled.event;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
get isActive(): boolean {
|
|
42
|
+
return this.isAiEnabledKey.get() ?? false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
protected updateEnableValue(value: boolean): void {
|
|
46
|
+
if (value !== this.isAiEnabledKey.get()) {
|
|
47
|
+
this.isAiEnabledKey.set(value);
|
|
48
|
+
this.onDidChangeAIEnabled.fire(value);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
initialize(): MaybePromise<void> {
|
|
53
|
+
this.isAiEnabledKey = this.contextKeyService.createKey(ENABLE_AI_CONTEXT_KEY, false);
|
|
54
|
+
// make sure we don't miss once preferences are ready
|
|
55
|
+
this.preferenceService.ready.then(() => {
|
|
56
|
+
const enableValue = this.preferenceService.get<boolean>(PREFERENCE_NAME_ENABLE_AI, false);
|
|
57
|
+
this.updateEnableValue(enableValue);
|
|
58
|
+
});
|
|
59
|
+
this.preferenceService.onPreferenceChanged(e => {
|
|
60
|
+
if (e.preferenceName === PREFERENCE_NAME_ENABLE_AI) {
|
|
61
|
+
this.updateEnableValue(e.newValue);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 EclipseSource GmbH.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { AI_CORE_PREFERENCES_TITLE, ENABLE_AI_CONTEXT_KEY } from '@theia/ai-core/lib/browser';
|
|
18
|
+
import { nls } from '@theia/core';
|
|
19
|
+
import { PreferenceSchema } from '@theia/core/lib/browser';
|
|
20
|
+
|
|
21
|
+
// We reuse the context key for the preference name
|
|
22
|
+
export const PREFERENCE_NAME_ENABLE_AI = ENABLE_AI_CONTEXT_KEY;
|
|
23
|
+
|
|
24
|
+
export const aiIdePreferenceSchema: PreferenceSchema = {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
[PREFERENCE_NAME_ENABLE_AI]: {
|
|
28
|
+
title: AI_CORE_PREFERENCES_TITLE,
|
|
29
|
+
markdownDescription: nls.localize('theia/ai/ide/enableAI/mdDescription',
|
|
30
|
+
'❗ This setting allows you to access the latest AI capabilities (Beta version).\
|
|
31
|
+
\n\
|
|
32
|
+
Please note that these features are in a beta phase, which means they may \
|
|
33
|
+
undergo changes and will be further improved. It is important to be aware that these features may generate\
|
|
34
|
+
continuous requests to the language models (LLMs) you provide access to. This might incur costs that you\
|
|
35
|
+
need to monitor closely. By enabling this option, you acknowledge these risks.\
|
|
36
|
+
\n\
|
|
37
|
+
**Please note! The settings below in this section will only take effect\n\
|
|
38
|
+
once the main feature setting is enabled. After enabling the feature, you need to configure at least one\
|
|
39
|
+
LLM provider below. Also see [the documentation](https://theia-ide.org/docs/user_ai/)**.'),
|
|
40
|
+
type: 'boolean',
|
|
41
|
+
default: false,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
@@ -16,83 +16,15 @@
|
|
|
16
16
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
17
17
|
// *****************************************************************************
|
|
18
18
|
|
|
19
|
-
import { CHAT_CONTEXT_DETAILS_VARIABLE_ID } from '@theia/ai-chat';
|
|
20
19
|
import { AbstractStreamParsingChatAgent } from '@theia/ai-chat/lib/common/chat-agents';
|
|
21
20
|
import { ErrorChatResponseContentImpl, MarkdownChatResponseContentImpl, MutableChatRequestModel, QuestionResponseContentImpl } from '@theia/ai-chat/lib/common/chat-model';
|
|
22
|
-
import {
|
|
21
|
+
import { LanguageModelRequirement } from '@theia/ai-core/lib/common';
|
|
23
22
|
import { MCPFrontendService, MCPServerDescription } from '@theia/ai-mcp/lib/common/mcp-server-manager';
|
|
24
23
|
import { nls } from '@theia/core';
|
|
25
24
|
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
26
25
|
import { MCP_SERVERS_PREF } from '@theia/ai-mcp/lib/browser/mcp-preferences';
|
|
27
26
|
import { PreferenceScope, PreferenceService } from '@theia/core/lib/browser';
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
export const REQUIRED_MCP_SERVERS: MCPServerDescription[] = [
|
|
31
|
-
{
|
|
32
|
-
name: 'playwright',
|
|
33
|
-
command: 'npx',
|
|
34
|
-
args: ['-y', '@playwright/mcp@latest',
|
|
35
|
-
'--cdp-endpoint',
|
|
36
|
-
'http://localhost:9222/'],
|
|
37
|
-
autostart: false,
|
|
38
|
-
env: {},
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
name: 'playwright-visual',
|
|
42
|
-
command: 'npx',
|
|
43
|
-
args: ['-y', '@playwright/mcp@latest', '--vision',
|
|
44
|
-
'--cdp-endpoint',
|
|
45
|
-
'http://localhost:9222/'],
|
|
46
|
-
autostart: false,
|
|
47
|
-
env: {},
|
|
48
|
-
}
|
|
49
|
-
];
|
|
50
|
-
|
|
51
|
-
// Prompt templates
|
|
52
|
-
export const appTesterTemplate: BasePromptFragment = {
|
|
53
|
-
id: 'app-tester-system-default',
|
|
54
|
-
template: `{{!-- This prompt is licensed under the MIT License (https://opensource.org/license/mit).
|
|
55
|
-
Made improvements or adaptations to this prompt template? We'd love for you to share it with the community! Contribute back here:
|
|
56
|
-
https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-contribution --}}
|
|
57
|
-
|
|
58
|
-
You are AppTester, an AI assistant integrated into Theia IDE specifically designed to help developers test running applications using Playwright.
|
|
59
|
-
Your role is to inspect the application for user-specified test scenarios through the Playwright MCP server.
|
|
60
|
-
|
|
61
|
-
## Your Workflow
|
|
62
|
-
1. Help the user build and launch their application
|
|
63
|
-
2. Use Playwright browser automation to validate test scenarios
|
|
64
|
-
3. Report results and provide actionable feedback
|
|
65
|
-
4. Help fix issues when needed
|
|
66
|
-
|
|
67
|
-
## Available Playwright Testing Tools
|
|
68
|
-
You have access to these powerful automation tools:
|
|
69
|
-
${REQUIRED_MCP_SERVERS.map(server => `{{prompt:mcp_${server.name}_tools}}`)}
|
|
70
|
-
|
|
71
|
-
- **~{${LAUNCH_BROWSER_FUNCTION_ID}}**: Launch the browser. This is required before performing any browser interactions. Always launch a new browser when starting a test session.
|
|
72
|
-
- **~{${IS_BROWSER_RUNNING_FUNCTION_ID}}**: Check if the browser is running. If a tool fails by saying that the connection failed, you can verify the connection by using this tool.
|
|
73
|
-
- **~{${CLOSE_BROWSER_FUNCTION_ID}}**: Close the browser.
|
|
74
|
-
- **~{${QUERY_DOM_FUNCTION_ID}}**: Query the DOM for specific elements and their properties. Only use when explicitly requested by the user.
|
|
75
|
-
- **browser_snapshot**: Capture the current state of the page for verification or debugging purposes.
|
|
76
|
-
|
|
77
|
-
Prefer snapshots for investigating the page.
|
|
78
|
-
|
|
79
|
-
## Workflow Approach
|
|
80
|
-
1. **Understand Requirements**: Ask the user to clearly define what needs to be tested
|
|
81
|
-
2. **Launch Browser**: Start a fresh browser instance for testing
|
|
82
|
-
3. **Navigate and Test**: Execute the test scenario methodically
|
|
83
|
-
4. **Document Results**: Provide detailed results with screenshots when helpful
|
|
84
|
-
5. **Clean Up**: Always close the browser when testing is complete
|
|
85
|
-
|
|
86
|
-
## Current Context
|
|
87
|
-
Some files and other pieces of data may have been added by the user to the context of the chat. If any have, the details can be found below.
|
|
88
|
-
{{${CHAT_CONTEXT_DETAILS_VARIABLE_ID}}}
|
|
89
|
-
`
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
export const appTesterTemplateVariant: BasePromptFragment = {
|
|
93
|
-
id: 'app-tester-system-empty',
|
|
94
|
-
template: '',
|
|
95
|
-
};
|
|
27
|
+
import { appTesterTemplate, appTesterTemplateVariant, REQUIRED_MCP_SERVERS } from './app-tester-prompt-template';
|
|
96
28
|
|
|
97
29
|
export const AppTesterChatAgentId = 'AppTester';
|
|
98
30
|
@injectable()
|
|
@@ -108,15 +40,15 @@ export class AppTesterChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
108
40
|
name = AppTesterChatAgentId;
|
|
109
41
|
languageModelRequirements: LanguageModelRequirement[] = [{
|
|
110
42
|
purpose: 'chat',
|
|
111
|
-
identifier: '
|
|
43
|
+
identifier: 'default/code',
|
|
112
44
|
}];
|
|
113
45
|
protected defaultLanguageModelPurpose: string = 'chat';
|
|
114
46
|
override description = nls.localize('theia/ai/chat/app-tester/description', 'This agent tests your application user interface to verify user-specified test scenarios through the Playwright MCP server. '
|
|
115
47
|
+ 'It can automate testing workflows and provide detailed feedback on application functionality.');
|
|
116
48
|
|
|
117
49
|
override iconClass: string = 'codicon codicon-beaker';
|
|
118
|
-
|
|
119
|
-
|
|
50
|
+
protected override systemPromptId: string = 'app-tester-system';
|
|
51
|
+
override prompts = [{ id: 'app-tester-system', defaultVariant: appTesterTemplate, variants: [appTesterTemplateVariant] }];
|
|
120
52
|
|
|
121
53
|
/**
|
|
122
54
|
* Override invoke to check if the Playwright MCP server is running, and if not, ask the user if it should be started.
|