@theia/ai-ide 1.66.0-next.44 → 1.66.0-next.67
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 +5 -3
- package/lib/browser/ai-configuration/agent-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/language-model-renderer.d.ts.map +1 -1
- package/lib/browser/ai-configuration/language-model-renderer.js +4 -3
- package/lib/browser/ai-configuration/language-model-renderer.js.map +1 -1
- package/lib/browser/ai-configuration/model-aliases-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/model-aliases-configuration-widget.js +4 -3
- package/lib/browser/ai-configuration/model-aliases-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/token-usage-configuration-widget.js +1 -1
- package/lib/browser/ai-configuration/token-usage-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/tools-configuration-widget.d.ts +1 -1
- package/lib/browser/ai-configuration/tools-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/tools-configuration-widget.js +12 -12
- package/lib/browser/ai-configuration/tools-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/variable-configuration-widget.d.ts +1 -1
- package/lib/browser/ai-configuration/variable-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/variable-configuration-widget.js +4 -3
- package/lib/browser/ai-configuration/variable-configuration-widget.js.map +1 -1
- package/lib/browser/app-tester-chat-agent.d.ts.map +1 -1
- package/lib/browser/app-tester-chat-agent.js +10 -7
- 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 +2 -2
- package/lib/browser/architect-agent.js.map +1 -1
- package/lib/browser/coder-agent.d.ts.map +1 -1
- package/lib/browser/coder-agent.js +6 -5
- package/lib/browser/coder-agent.js.map +1 -1
- package/lib/browser/file-changeset-functions.d.ts +10 -0
- package/lib/browser/file-changeset-functions.d.ts.map +1 -1
- package/lib/browser/file-changeset-functions.js +51 -3
- package/lib/browser/file-changeset-functions.js.map +1 -1
- package/lib/browser/file-changeset-functions.spec.js +18 -0
- package/lib/browser/file-changeset-functions.spec.js.map +1 -1
- package/lib/browser/frontend-module.d.ts.map +1 -1
- package/lib/browser/frontend-module.js +2 -0
- package/lib/browser/frontend-module.js.map +1 -1
- package/lib/browser/github-chat-agent.d.ts.map +1 -1
- package/lib/browser/github-chat-agent.js +18 -16
- package/lib/browser/github-chat-agent.js.map +1 -1
- package/lib/common/coder-replace-prompt-template.d.ts +2 -0
- package/lib/common/coder-replace-prompt-template.d.ts.map +1 -1
- package/lib/common/coder-replace-prompt-template.js +20 -8
- package/lib/common/coder-replace-prompt-template.js.map +1 -1
- package/lib/common/command-chat-agents.d.ts.map +1 -1
- package/lib/common/command-chat-agents.js +9 -9
- package/lib/common/command-chat-agents.js.map +1 -1
- package/lib/common/file-changeset-function-ids.d.ts +1 -0
- package/lib/common/file-changeset-function-ids.d.ts.map +1 -1
- package/lib/common/file-changeset-function-ids.js +2 -1
- package/lib/common/file-changeset-function-ids.js.map +1 -1
- package/lib/common/orchestrator-chat-agent.d.ts.map +1 -1
- package/lib/common/orchestrator-chat-agent.js +4 -4
- package/lib/common/orchestrator-chat-agent.js.map +1 -1
- package/lib/common/workspace-preferences.js +2 -2
- package/lib/common/workspace-preferences.js.map +1 -1
- package/package.json +21 -21
- package/src/browser/ai-configuration/agent-configuration-widget.tsx +5 -3
- package/src/browser/ai-configuration/language-model-renderer.tsx +9 -4
- package/src/browser/ai-configuration/model-aliases-configuration-widget.tsx +8 -4
- package/src/browser/ai-configuration/template-settings-renderer.tsx +1 -1
- package/src/browser/ai-configuration/token-usage-configuration-widget.tsx +1 -1
- package/src/browser/ai-configuration/tools-configuration-widget.tsx +15 -14
- package/src/browser/ai-configuration/variable-configuration-widget.tsx +4 -3
- package/src/browser/app-tester-chat-agent.ts +15 -7
- package/src/browser/architect-agent.ts +4 -2
- package/src/browser/coder-agent.ts +10 -6
- package/src/browser/file-changeset-functions.spec.ts +28 -1
- package/src/browser/file-changeset-functions.ts +47 -3
- package/src/browser/frontend-module.ts +5 -1
- package/src/browser/github-chat-agent.ts +23 -17
- package/src/common/coder-replace-prompt-template.ts +23 -8
- package/src/common/command-chat-agents.ts +13 -9
- package/src/common/file-changeset-function-ids.ts +1 -0
- package/src/common/orchestrator-chat-agent.ts +5 -4
- package/src/common/workspace-preferences.ts +2 -2
|
@@ -58,16 +58,20 @@ export class AppTesterChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
58
58
|
if (await this.requiresStartingServers()) {
|
|
59
59
|
// Ask the user if they want to start the server
|
|
60
60
|
request.response.response.addContent(new QuestionResponseContentImpl(
|
|
61
|
-
|
|
61
|
+
nls.localize('theia/ai/ide/app-tester/startPlaywrightServers/question',
|
|
62
|
+
'The Playwright MCP servers are not running. Would you like to start them now? This may install the Playwright MCP servers.'),
|
|
62
63
|
[
|
|
63
|
-
{ text: 'Yes, start the servers', value: 'yes' },
|
|
64
|
-
{ text: 'No, cancel', value: 'no' }
|
|
64
|
+
{ text: nls.localize('theia/ai/ide/app-tester/startPlaywrightServers/yes', 'Yes, start the servers'), value: 'yes' },
|
|
65
|
+
{ text: nls.localize('theia/ai/ide/app-tester/startPlaywrightServers/no', 'No, cancel'), value: 'no' }
|
|
65
66
|
],
|
|
66
67
|
request,
|
|
67
68
|
async selectedOption => {
|
|
68
69
|
if (selectedOption.value === 'yes') {
|
|
69
70
|
// Show progress
|
|
70
|
-
const progress = request.response.addProgressMessage({
|
|
71
|
+
const progress = request.response.addProgressMessage({
|
|
72
|
+
content: nls.localize('theia/ai/ide/app-tester/startPlaywrightServers/progress', 'Starting Playwright MCP servers.'),
|
|
73
|
+
show: 'whileIncomplete'
|
|
74
|
+
});
|
|
71
75
|
try {
|
|
72
76
|
await this.startServers();
|
|
73
77
|
// Remove progress, continue with normal flow
|
|
@@ -75,13 +79,16 @@ export class AppTesterChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
75
79
|
await super.invoke(request);
|
|
76
80
|
} catch (error) {
|
|
77
81
|
request.response.response.addContent(new ErrorChatResponseContentImpl(
|
|
78
|
-
new Error('Failed to start Playwright MCP server: '
|
|
82
|
+
new Error(nls.localize('theia/ai/ide/app-tester/startPlaywrightServers/error', 'Failed to start Playwright MCP server: {0}',
|
|
83
|
+
error instanceof Error ? error.message : String(error)))
|
|
79
84
|
));
|
|
80
85
|
request.response.complete();
|
|
81
86
|
}
|
|
82
87
|
} else {
|
|
83
88
|
// Continue without starting the server
|
|
84
|
-
request.response.response.addContent(new MarkdownChatResponseContentImpl(
|
|
89
|
+
request.response.response.addContent(new MarkdownChatResponseContentImpl(
|
|
90
|
+
nls.localize('theia/ai/ide/app-tester/startPlaywrightServers/canceled', 'Please setup the MCP servers.')
|
|
91
|
+
));
|
|
85
92
|
request.response.complete();
|
|
86
93
|
}
|
|
87
94
|
}
|
|
@@ -93,7 +100,8 @@ export class AppTesterChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
93
100
|
await super.invoke(request);
|
|
94
101
|
} catch (error) {
|
|
95
102
|
request.response.response.addContent(new ErrorChatResponseContentImpl(
|
|
96
|
-
new Error('Error checking Playwright MCP server status: '
|
|
103
|
+
new Error(nls.localize('theia/ai/ide/app-tester/errorCheckingPlaywrightServerStatus', 'Error checking Playwright MCP server status: {0}',
|
|
104
|
+
error instanceof Error ? error.message : String(error)))
|
|
97
105
|
));
|
|
98
106
|
request.response.complete();
|
|
99
107
|
}
|
|
@@ -51,8 +51,10 @@ export class ArchitectAgent extends AbstractStreamParsingChatAgent {
|
|
|
51
51
|
if (!(model instanceof MutableChatModel) || !session) { return; }
|
|
52
52
|
if (!model.isEmpty()) {
|
|
53
53
|
model.setSuggestions([
|
|
54
|
-
new MarkdownStringImpl(`[
|
|
55
|
-
|
|
54
|
+
new MarkdownStringImpl(`[${nls.localize('theia/ai/ide/architectAgent/suggestion/summarizeSessionAsTaskForCoder',
|
|
55
|
+
'Summarize this session as a task for Coder')}](command:${AI_SUMMARIZE_SESSION_AS_TASK_FOR_CODER.id}).`),
|
|
56
|
+
new MarkdownStringImpl(`[${nls.localize('theia/ai/ide/architectAgent/suggestion/updateTaskContext',
|
|
57
|
+
'Update current task context')}](command:${AI_UPDATE_TASK_CONTEXT_COMMAND.id}).`)
|
|
56
58
|
]);
|
|
57
59
|
}
|
|
58
60
|
}
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
import { AbstractStreamParsingChatAgent, ChatRequestModel, ChatService, ChatSession, MutableChatModel, MutableChatRequestModel } from '@theia/ai-chat/lib/common';
|
|
17
17
|
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
18
|
-
import { CODER_SYSTEM_PROMPT_ID, getCoderAgentModePromptTemplate, getCoderPromptTemplateEdit, getCoderPromptTemplateSimpleEdit }
|
|
18
|
+
import { CODER_SYSTEM_PROMPT_ID, getCoderAgentModePromptTemplate, getCoderPromptTemplateEdit, getCoderPromptTemplateEditNext, getCoderPromptTemplateSimpleEdit }
|
|
19
|
+
from '../common/coder-replace-prompt-template';
|
|
19
20
|
import { LanguageModelRequirement, PromptVariantSet } from '@theia/ai-core';
|
|
20
21
|
import { nls } from '@theia/core';
|
|
21
22
|
import { MarkdownStringImpl } from '@theia/core/lib/common/markdown-rendering';
|
|
@@ -39,7 +40,7 @@ export class CoderAgent extends AbstractStreamParsingChatAgent {
|
|
|
39
40
|
override prompts: PromptVariantSet[] = [{
|
|
40
41
|
id: CODER_SYSTEM_PROMPT_ID,
|
|
41
42
|
defaultVariant: getCoderPromptTemplateEdit(),
|
|
42
|
-
variants: [getCoderPromptTemplateSimpleEdit(), getCoderAgentModePromptTemplate()]
|
|
43
|
+
variants: [getCoderPromptTemplateSimpleEdit(), getCoderAgentModePromptTemplate(), getCoderPromptTemplateEditNext()]
|
|
43
44
|
}];
|
|
44
45
|
protected override systemPromptId: string | undefined = CODER_SYSTEM_PROMPT_ID;
|
|
45
46
|
override async invoke(request: MutableChatRequestModel): Promise<void> {
|
|
@@ -55,13 +56,16 @@ export class CoderAgent extends AbstractStreamParsingChatAgent {
|
|
|
55
56
|
model.setSuggestions([
|
|
56
57
|
{
|
|
57
58
|
kind: 'callback',
|
|
58
|
-
callback: () => this.chatService.sendRequest(session.id, {
|
|
59
|
-
|
|
59
|
+
callback: () => this.chatService.sendRequest(session.id, {
|
|
60
|
+
text: `@Coder ${nls.localize('theia/ai/ide/coderAgent/suggestion/fixProblems/prompt', 'please look at {1} and fix any problems.', '#_f')}`
|
|
61
|
+
}),
|
|
62
|
+
content: nls.localize('theia/ai/ide/coderAgent/suggestion/fixProblems/content', '[Fix problems]({0}) in the current file.', '_callback')
|
|
60
63
|
},
|
|
61
64
|
]);
|
|
62
65
|
} else {
|
|
63
|
-
model.setSuggestions([new MarkdownStringImpl(
|
|
64
|
-
|
|
66
|
+
model.setSuggestions([new MarkdownStringImpl(nls.localize('theia/ai/ide/coderAgent/suggestion/startNewChat',
|
|
67
|
+
'Keep chats short and focused. [Start a new chat]({0}) for a new task or [start a new chat with a summary of this one]({1}).',
|
|
68
|
+
`command:${AI_CHAT_NEW_CHAT_WINDOW_COMMAND.id}`, `command:${ChatCommands.AI_CHAT_NEW_WITH_TASK_CONTEXT.id}`))]);
|
|
65
69
|
}
|
|
66
70
|
}
|
|
67
71
|
|
|
@@ -30,7 +30,9 @@ import {
|
|
|
30
30
|
GetProposedFileState,
|
|
31
31
|
ReplaceContentInFileFunctionHelper,
|
|
32
32
|
FileChangeSetTitleProvider,
|
|
33
|
-
DefaultFileChangeSetTitleProvider
|
|
33
|
+
DefaultFileChangeSetTitleProvider,
|
|
34
|
+
ReplaceContentInFileFunctionHelperV2,
|
|
35
|
+
SuggestFileReplacements_Next
|
|
34
36
|
} from './file-changeset-functions';
|
|
35
37
|
import { MutableChatRequestModel, MutableChatResponseModel, ChangeSet, ChangeSetElement, MutableChatModel } from '@theia/ai-chat';
|
|
36
38
|
import { Container } from '@theia/core/shared/inversify';
|
|
@@ -108,6 +110,8 @@ describe('File Changeset Functions Cancellation Tests', () => {
|
|
|
108
110
|
container.bind(WriteFileReplacements).toSelf();
|
|
109
111
|
container.bind(ClearFileChanges).toSelf();
|
|
110
112
|
container.bind(GetProposedFileState).toSelf();
|
|
113
|
+
container.bind(ReplaceContentInFileFunctionHelperV2).toSelf();
|
|
114
|
+
container.bind(SuggestFileReplacements_Next).toSelf();
|
|
111
115
|
});
|
|
112
116
|
|
|
113
117
|
afterEach(() => {
|
|
@@ -209,4 +213,27 @@ describe('File Changeset Functions Cancellation Tests', () => {
|
|
|
209
213
|
expect(jsonResponse.error).to.equal('Operation cancelled by user');
|
|
210
214
|
|
|
211
215
|
});
|
|
216
|
+
|
|
217
|
+
it('SuggestFileReplacements_Next should respect cancellation token', async () => {
|
|
218
|
+
const suggestFileReplacementsNext = container.get(SuggestFileReplacements_Next);
|
|
219
|
+
cancellationTokenSource.cancel();
|
|
220
|
+
|
|
221
|
+
const handler = suggestFileReplacementsNext.getTool().handler;
|
|
222
|
+
const result = await handler(
|
|
223
|
+
JSON.stringify({
|
|
224
|
+
path: 'test.txt',
|
|
225
|
+
replacements: [{ oldContent: 'old', newContent: 'new', multiple: true }]
|
|
226
|
+
}),
|
|
227
|
+
mockCtx as MutableChatRequestModel
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
const jsonResponse = typeof result === 'string' ? JSON.parse(result) : result;
|
|
231
|
+
expect(jsonResponse.error).to.equal('Operation cancelled by user');
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('SuggestFileReplacements_Next should have correct ID', () => {
|
|
235
|
+
const suggestFileReplacementsNext = container.get(SuggestFileReplacements_Next);
|
|
236
|
+
expect(SuggestFileReplacements_Next.ID).to.equal('suggestFileReplacements_Next');
|
|
237
|
+
expect(suggestFileReplacementsNext.getTool().id).to.equal('suggestFileReplacements_Next');
|
|
238
|
+
});
|
|
212
239
|
});
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
import { ChangeSet, MutableChatRequestModel } from '@theia/ai-chat';
|
|
17
17
|
import { ChangeSetElementArgs, ChangeSetFileElement, ChangeSetFileElementFactory } from '@theia/ai-chat/lib/browser/change-set-file-element';
|
|
18
18
|
import { ToolProvider, ToolRequest, ToolRequestParameters, ToolRequestParametersProperties } from '@theia/ai-core';
|
|
19
|
-
import {
|
|
19
|
+
import { ContentReplacerV1Impl, Replacement, ContentReplacer } from '@theia/core/lib/common/content-replacer';
|
|
20
|
+
import { ContentReplacerV2Impl } from '@theia/core/lib/common/content-replacer-v2-impl';
|
|
20
21
|
import { URI } from '@theia/core/lib/common/uri';
|
|
21
22
|
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
22
23
|
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
|
@@ -29,7 +30,8 @@ import {
|
|
|
29
30
|
SUGGEST_FILE_CONTENT_ID,
|
|
30
31
|
SUGGEST_FILE_REPLACEMENTS_ID,
|
|
31
32
|
WRITE_FILE_CONTENT_ID,
|
|
32
|
-
WRITE_FILE_REPLACEMENTS_ID
|
|
33
|
+
WRITE_FILE_REPLACEMENTS_ID,
|
|
34
|
+
SUGGEST_FILE_REPLACEMENTS_NEXT_ID
|
|
33
35
|
} from '../common/file-changeset-function-ids';
|
|
34
36
|
|
|
35
37
|
export const FileChangeSetTitleProvider = Symbol('FileChangeSetTitleProvider');
|
|
@@ -206,7 +208,11 @@ export class ReplaceContentInFileFunctionHelper {
|
|
|
206
208
|
private replacer: ContentReplacer;
|
|
207
209
|
|
|
208
210
|
constructor() {
|
|
209
|
-
this.replacer = new
|
|
211
|
+
this.replacer = new ContentReplacerV1Impl();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
protected setReplacer(replacer: ContentReplacer): void {
|
|
215
|
+
this.replacer = replacer;
|
|
210
216
|
}
|
|
211
217
|
|
|
212
218
|
getToolMetadata(supportMultipleReplace: boolean = false, immediateApplication: boolean = false): { description: string, parameters: ToolRequestParameters } {
|
|
@@ -596,6 +602,44 @@ export class GetProposedFileState implements ToolProvider {
|
|
|
596
602
|
}
|
|
597
603
|
}
|
|
598
604
|
|
|
605
|
+
@injectable()
|
|
606
|
+
export class ReplaceContentInFileFunctionHelperV2 extends ReplaceContentInFileFunctionHelper {
|
|
607
|
+
constructor() {
|
|
608
|
+
super();
|
|
609
|
+
this.setReplacer(new ContentReplacerV2Impl());
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
@injectable()
|
|
614
|
+
export class SuggestFileReplacements_Next implements ToolProvider {
|
|
615
|
+
static ID = SUGGEST_FILE_REPLACEMENTS_NEXT_ID;
|
|
616
|
+
|
|
617
|
+
@inject(ReplaceContentInFileFunctionHelperV2)
|
|
618
|
+
protected readonly replaceContentInFileFunctionHelper: ReplaceContentInFileFunctionHelperV2;
|
|
619
|
+
|
|
620
|
+
getTool(): ToolRequest {
|
|
621
|
+
const metadata = this.replaceContentInFileFunctionHelper.getToolMetadata(true);
|
|
622
|
+
return {
|
|
623
|
+
id: SuggestFileReplacements_Next.ID,
|
|
624
|
+
name: SuggestFileReplacements_Next.ID,
|
|
625
|
+
description: `Proposes to replace sections of content in an existing file by providing a list of replacements.
|
|
626
|
+
Each replacement consists of oldContent to be matched and newContent to insert in its place.
|
|
627
|
+
By default, a single occurrence of each oldContent is expected. If the 'multiple' flag is set to true, all occurrences will be replaced.
|
|
628
|
+
If the expected number of occurrences is not found, the function will return an error. In this case try a different approach.
|
|
629
|
+
For deletions, use an empty newContent.
|
|
630
|
+
The proposed changes will be applied when the user accepts.
|
|
631
|
+
Multiple calls for the same file will merge replacements unless the reset parameter is set to true.`,
|
|
632
|
+
parameters: metadata.parameters,
|
|
633
|
+
handler: async (args: string, ctx: MutableChatRequestModel): Promise<string> => {
|
|
634
|
+
if (ctx?.response?.cancellationToken?.isCancellationRequested) {
|
|
635
|
+
return JSON.stringify({ error: 'Operation cancelled by user' });
|
|
636
|
+
}
|
|
637
|
+
return this.replaceContentInFileFunctionHelper.createChangesetFromToolCall(args, ctx);
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
599
643
|
@injectable()
|
|
600
644
|
export class DefaultFileChangeSetTitleProvider implements FileChangeSetTitleProvider {
|
|
601
645
|
getChangeSetTitle(ctx: MutableChatRequestModel): string {
|
|
@@ -56,7 +56,9 @@ import {
|
|
|
56
56
|
WriteFileReplacements,
|
|
57
57
|
SimpleWriteFileReplacements,
|
|
58
58
|
FileChangeSetTitleProvider,
|
|
59
|
-
DefaultFileChangeSetTitleProvider
|
|
59
|
+
DefaultFileChangeSetTitleProvider,
|
|
60
|
+
ReplaceContentInFileFunctionHelperV2,
|
|
61
|
+
SuggestFileReplacements_Next
|
|
60
62
|
} from './file-changeset-functions';
|
|
61
63
|
import { OrchestratorChatAgent, OrchestratorChatAgentId } from '../common/orchestrator-chat-agent';
|
|
62
64
|
import { UniversalChatAgent, UniversalChatAgentId } from '../common/universal-chat-agent';
|
|
@@ -159,6 +161,8 @@ export default new ContainerModule((bind, _unbind, _isBound, rebind) => {
|
|
|
159
161
|
bind(FileChangeSetTitleProvider).to(DefaultFileChangeSetTitleProvider).inSingletonScope();
|
|
160
162
|
bindToolProvider(SuggestFileReplacements, bind);
|
|
161
163
|
bindToolProvider(WriteFileReplacements, bind);
|
|
164
|
+
bind(ReplaceContentInFileFunctionHelperV2).toSelf().inSingletonScope();
|
|
165
|
+
bindToolProvider(SuggestFileReplacements_Next, bind);
|
|
162
166
|
bindToolProvider(ListChatContext, bind);
|
|
163
167
|
bindToolProvider(ResolveChatContext, bind);
|
|
164
168
|
bind(AIConfigurationSelectionService).toSelf().inSingletonScope();
|
|
@@ -54,7 +54,7 @@ export class GitHubChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
54
54
|
identifier: 'default/code',
|
|
55
55
|
}];
|
|
56
56
|
protected defaultLanguageModelPurpose: string = 'chat';
|
|
57
|
-
override description = nls.localize('theia/ai/
|
|
57
|
+
override description = nls.localize('theia/ai/ide/github/description', 'This agent helps you interact with GitHub repositories, issues, pull requests, and other GitHub '
|
|
58
58
|
+ 'features through the GitHub MCP server. '
|
|
59
59
|
+ 'It can help you manage your repositories, create issues, handle pull requests, and perform various GitHub operations.');
|
|
60
60
|
|
|
@@ -70,26 +70,26 @@ export class GitHubChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
70
70
|
try {
|
|
71
71
|
if (await this.requiresConfiguration()) {
|
|
72
72
|
// Ask the user if they want to configure the GitHub server
|
|
73
|
-
request.response.response.addContent(new QuestionResponseContentImpl(
|
|
73
|
+
request.response.response.addContent(new QuestionResponseContentImpl(nls.localize('theia/ai/ide/github/configureGitHubServer/question',
|
|
74
74
|
'The GitHub MCP server is not configured. Would you like to configure it now? '
|
|
75
|
-
+ 'This will open the settings.json file where you can add your GitHub access token.',
|
|
75
|
+
+ 'This will open the settings.json file where you can add your GitHub access token.'),
|
|
76
76
|
[
|
|
77
|
-
{ text: 'Yes, configure GitHub server', value: 'configure' },
|
|
78
|
-
{ text: 'No, cancel', value: 'cancel' }
|
|
77
|
+
{ text: nls.localize('theia/ai/ide/github/configureGitHubServer/yes', 'Yes, configure GitHub server'), value: 'configure' },
|
|
78
|
+
{ text: nls.localize('theia/ai/ide/github/configureGitHubServer/no', 'No, cancel'), value: 'cancel' }
|
|
79
79
|
],
|
|
80
80
|
request,
|
|
81
81
|
async selectedOption => {
|
|
82
82
|
if (selectedOption.value === 'configure') {
|
|
83
83
|
await this.offerConfiguration();
|
|
84
|
-
request.response.response.addContent(new MarkdownChatResponseContentImpl(
|
|
84
|
+
request.response.response.addContent(new MarkdownChatResponseContentImpl(nls.localize('theia/ai/ide/github/configureGitHubServer/followup',
|
|
85
85
|
'Settings file opened. Please add your GitHub Personal Access Token to the `serverAuthToken` property in the GitHub server configuration, then '
|
|
86
86
|
+ ' save and try again.\n\n' +
|
|
87
87
|
'You can create a Personal Access Token at: https://github.com/settings/tokens'
|
|
88
|
-
));
|
|
88
|
+
)));
|
|
89
89
|
request.response.complete();
|
|
90
90
|
} else {
|
|
91
|
-
request.response.response.addContent(new MarkdownChatResponseContentImpl(
|
|
92
|
-
|
|
91
|
+
request.response.response.addContent(new MarkdownChatResponseContentImpl(nls.localize('theia/ai/ide/github/configureGitHubServer/canceled',
|
|
92
|
+
'GitHub server configuration cancelled. Please configure the GitHub MCP server to use this agent.')));
|
|
93
93
|
request.response.complete();
|
|
94
94
|
}
|
|
95
95
|
}
|
|
@@ -100,28 +100,33 @@ export class GitHubChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
100
100
|
|
|
101
101
|
if (await this.requiresStartingServer()) {
|
|
102
102
|
// Ask the user if they want to start the server
|
|
103
|
-
request.response.response.addContent(new QuestionResponseContentImpl(
|
|
104
|
-
'The GitHub MCP server is configured but not running. Would you like to start it now?',
|
|
103
|
+
request.response.response.addContent(new QuestionResponseContentImpl(nls.localize('theia/ai/ide/github/startGitHubServer/question',
|
|
104
|
+
'The GitHub MCP server is configured but not running. Would you like to start it now?'),
|
|
105
105
|
[
|
|
106
|
-
{ text: 'Yes, start the server', value: 'yes' },
|
|
107
|
-
{ text: 'No, cancel', value: 'no' }
|
|
106
|
+
{ text: nls.localize('theia/ai/ide/github/startGitHubServer/yes', 'Yes, start the server'), value: 'yes' },
|
|
107
|
+
{ text: nls.localize('theia/ai/ide/github/startGitHubServer/no', 'No, cancel'), value: 'no' }
|
|
108
108
|
],
|
|
109
109
|
request,
|
|
110
110
|
async selectedOption => {
|
|
111
111
|
if (selectedOption.value === 'yes') {
|
|
112
|
-
const progress = request.response.addProgressMessage({
|
|
112
|
+
const progress = request.response.addProgressMessage({
|
|
113
|
+
content: nls.localize('theia/ai/ide/github/startGitHubServer/progress', 'Starting GitHub MCP server.'),
|
|
114
|
+
show: 'whileIncomplete'
|
|
115
|
+
});
|
|
113
116
|
try {
|
|
114
117
|
await this.startServer();
|
|
115
118
|
request.response.updateProgressMessage({ ...progress, show: 'whileIncomplete', status: 'completed' });
|
|
116
119
|
await super.invoke(request);
|
|
117
120
|
} catch (error) {
|
|
118
121
|
request.response.response.addContent(new ErrorChatResponseContentImpl(
|
|
119
|
-
new Error('Failed to start GitHub MCP server: '
|
|
122
|
+
new Error(nls.localize('theia/ai/ide/github/startGitHubServer/error', 'Failed to start GitHub MCP server: {0}',
|
|
123
|
+
error instanceof Error ? error.message : String(error)))
|
|
120
124
|
));
|
|
121
125
|
request.response.complete();
|
|
122
126
|
}
|
|
123
127
|
} else {
|
|
124
|
-
request.response.response.addContent(new MarkdownChatResponseContentImpl(
|
|
128
|
+
request.response.response.addContent(new MarkdownChatResponseContentImpl(nls.localize('theia/ai/ide/github/startGitHubServer/canceled',
|
|
129
|
+
'Please start the GitHub MCP server to use this agent.')));
|
|
125
130
|
request.response.complete();
|
|
126
131
|
}
|
|
127
132
|
}
|
|
@@ -134,7 +139,8 @@ export class GitHubChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
134
139
|
await super.invoke(request);
|
|
135
140
|
} catch (error) {
|
|
136
141
|
request.response.response.addContent(new ErrorChatResponseContentImpl(
|
|
137
|
-
new Error('Error checking GitHub MCP server status: '
|
|
142
|
+
new Error(nls.localize('theia/ai/ide/github/errorCheckingGitHubServerStatus', 'Error checking GitHub MCP server status: {0}',
|
|
143
|
+
error instanceof Error ? error.message : String(error)))
|
|
138
144
|
));
|
|
139
145
|
request.response.complete();
|
|
140
146
|
}
|
|
@@ -28,13 +28,15 @@ import {
|
|
|
28
28
|
SUGGEST_FILE_REPLACEMENTS_ID,
|
|
29
29
|
WRITE_FILE_REPLACEMENTS_ID,
|
|
30
30
|
CLEAR_FILE_CHANGES_ID,
|
|
31
|
-
GET_PROPOSED_CHANGES_ID
|
|
31
|
+
GET_PROPOSED_CHANGES_ID,
|
|
32
|
+
SUGGEST_FILE_REPLACEMENTS_NEXT_ID
|
|
32
33
|
} from './file-changeset-function-ids';
|
|
33
34
|
|
|
34
35
|
export const CODER_SYSTEM_PROMPT_ID = 'coder-system';
|
|
35
36
|
|
|
36
37
|
export const CODER_SIMPLE_EDIT_TEMPLATE_ID = 'coder-system-simple-edit';
|
|
37
38
|
export const CODER_EDIT_TEMPLATE_ID = 'coder-system-edit';
|
|
39
|
+
export const CODER_EDIT_NEXT_TEMPLATE_ID = 'coder-system-edit-next';
|
|
38
40
|
export const CODER_AGENT_MODE_TEMPLATE_ID = 'coder-system-agent-mode';
|
|
39
41
|
|
|
40
42
|
export function getCoderAgentModePromptTemplate(): BasePromptFragment {
|
|
@@ -159,10 +161,8 @@ You are an autonomous AI agent. Do not stop until:
|
|
|
159
161
|
};
|
|
160
162
|
}
|
|
161
163
|
|
|
162
|
-
|
|
163
|
-
return {
|
|
164
|
-
id: CODER_EDIT_TEMPLATE_ID,
|
|
165
|
-
template: `{{!-- This prompt is licensed under the MIT License (https://opensource.org/license/mit).
|
|
164
|
+
function getCoderEditPromptTemplate(suggestFileReplacementsId: string): string {
|
|
165
|
+
return `{{!-- This prompt is licensed under the MIT License (https://opensource.org/license/mit).
|
|
166
166
|
Made improvements or adaptations to this prompt template? We'd love for you to share it with the community! Contribute back here:
|
|
167
167
|
https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-contribution --}}
|
|
168
168
|
You are an AI assistant integrated into Theia IDE, designed to assist software developers with code tasks. You can interact with the code base and suggest changes, \
|
|
@@ -189,9 +189,9 @@ This also applies for newly created files!
|
|
|
189
189
|
- **Always Retrieve Current Content**: Use getFileContent to get the original content of the target file.
|
|
190
190
|
- **View Pending Changes**: Use ~{${GET_PROPOSED_CHANGES_ID}} to see the current proposed state of a file, including all pending changes.
|
|
191
191
|
- **Change Content**: Use one of these methods to propose changes:
|
|
192
|
-
- ~{${
|
|
192
|
+
- ~{${suggestFileReplacementsId}}: For targeted replacements of specific text sections. Multiple calls will merge changes unless you set the reset parameter to true.
|
|
193
193
|
- ~{${SUGGEST_FILE_CONTENT_ID}}: For complete file rewrites when you need to replace the entire content.
|
|
194
|
-
- If ~{${
|
|
194
|
+
- If ~{${suggestFileReplacementsId}} continuously fails use ~{${SUGGEST_FILE_CONTENT_ID}}.
|
|
195
195
|
- ~{${CLEAR_FILE_CHANGES_ID}}: To clear all pending changes for a file and start fresh.
|
|
196
196
|
|
|
197
197
|
The changes will be presented as an applicable diff to the user in any case. The user can then accept or reject each change individually. Before you run tasks that depend on the \
|
|
@@ -229,7 +229,22 @@ You have previously proposed changes for the following files. Some suggestions m
|
|
|
229
229
|
- Tasks such as building or liniting run on the workspace state, the user has to accept the changes beforehand
|
|
230
230
|
- Do not run a build or any error checking before the users asks you to
|
|
231
231
|
- Focus on the task that the user described
|
|
232
|
-
|
|
232
|
+
`;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function getCoderPromptTemplateEdit(): BasePromptFragment {
|
|
236
|
+
return {
|
|
237
|
+
id: CODER_EDIT_TEMPLATE_ID,
|
|
238
|
+
template: getCoderEditPromptTemplate(SUGGEST_FILE_REPLACEMENTS_ID)
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export function getCoderPromptTemplateEditNext(): BasePromptFragment {
|
|
243
|
+
return {
|
|
244
|
+
id: CODER_EDIT_NEXT_TEMPLATE_ID,
|
|
245
|
+
template: getCoderEditPromptTemplate(SUGGEST_FILE_REPLACEMENTS_NEXT_ID),
|
|
246
|
+
...({ variantOf: CODER_EDIT_TEMPLATE_ID })
|
|
247
|
+
};
|
|
233
248
|
}
|
|
234
249
|
|
|
235
250
|
export function getCoderPromptTemplateSimpleEdit(): BasePromptFragment {
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
CommandRegistry,
|
|
30
30
|
MessageService,
|
|
31
31
|
generateUuid,
|
|
32
|
+
nls,
|
|
32
33
|
} from '@theia/core';
|
|
33
34
|
|
|
34
35
|
import { commandTemplate } from './command-prompt-template';
|
|
@@ -55,12 +56,13 @@ export class CommandChatAgent extends AbstractTextToModelParsingChatAgent<Parsed
|
|
|
55
56
|
}];
|
|
56
57
|
protected defaultLanguageModelPurpose: string = 'command';
|
|
57
58
|
|
|
58
|
-
override description = '
|
|
59
|
-
|
|
59
|
+
override description = nls.localize('theia/ai/ide/commandAgent/description',
|
|
60
|
+
'This agent is aware of all commands that the user can execute within the Theia IDE, the tool that the user is currently working with. ' +
|
|
61
|
+
'Based on the user request, it can find the right command and then let the user execute it.');
|
|
60
62
|
override prompts = [commandTemplate];
|
|
61
63
|
override agentSpecificVariables = [{
|
|
62
64
|
name: 'command-ids',
|
|
63
|
-
description: 'The list of available commands in Theia.',
|
|
65
|
+
description: nls.localize('theia/ai/ide/commandAgent/vars/commandIds/description', 'The list of available commands in Theia.'),
|
|
64
66
|
usedInPrompt: true
|
|
65
67
|
}];
|
|
66
68
|
|
|
@@ -107,7 +109,7 @@ export class CommandChatAgent extends AbstractTextToModelParsingChatAgent<Parsed
|
|
|
107
109
|
|
|
108
110
|
return new HorizontalLayoutChatResponseContentImpl([
|
|
109
111
|
new MarkdownChatResponseContentImpl(
|
|
110
|
-
'I found this command that might help you:'
|
|
112
|
+
nls.localize('theia/ai/ide/commandAgent/response/theiaCommand', 'I found this command that might help you:')
|
|
111
113
|
),
|
|
112
114
|
new CommandChatResponseContentImpl(theiaCommand, undefined, args),
|
|
113
115
|
]);
|
|
@@ -116,22 +118,24 @@ export class CommandChatAgent extends AbstractTextToModelParsingChatAgent<Parsed
|
|
|
116
118
|
const commandArgs = parsedCommand.arguments !== undefined && parsedCommand.arguments.length > 0 ? parsedCommand.arguments : [];
|
|
117
119
|
const args = [id, ...commandArgs];
|
|
118
120
|
const customCallback: CustomCallback = {
|
|
119
|
-
label: 'AI command',
|
|
121
|
+
label: nls.localize('theia/ai/ide/commandAgent/commandCallback/label', 'AI command'),
|
|
120
122
|
callback: () => this.commandCallback(...args),
|
|
121
123
|
};
|
|
122
124
|
return new HorizontalLayoutChatResponseContentImpl([
|
|
123
125
|
new MarkdownChatResponseContentImpl(
|
|
124
|
-
'Try executing this:'
|
|
126
|
+
nls.localize('theia/ai/ide/commandAgent/response/customHandler', 'Try executing this:')
|
|
125
127
|
),
|
|
126
128
|
new CommandChatResponseContentImpl(undefined, customCallback, args),
|
|
127
129
|
]);
|
|
128
130
|
} else {
|
|
129
|
-
return new MarkdownChatResponseContentImpl(parsedCommand.message ?? '
|
|
131
|
+
return new MarkdownChatResponseContentImpl(parsedCommand.message ?? nls.localize('theia/ai/ide/commandAgent/response/noCommand',
|
|
132
|
+
'Sorry, I can\'t find such a command'));
|
|
130
133
|
}
|
|
131
134
|
}
|
|
132
135
|
|
|
133
136
|
protected async commandCallback(...commandArgs: unknown[]): Promise<void> {
|
|
134
|
-
this.messageService.info(
|
|
135
|
-
|
|
137
|
+
this.messageService.info(nls.localize('theia/ai/ide/commandAgent/commandCallback/message',
|
|
138
|
+
'Executing callback with args {0}. The first arg is the command id registered for the dynamically registered command. ' +
|
|
139
|
+
'The other args are the actual args for the handler.', commandArgs.join(', ')), nls.localize('theia/ai/ide/commandAgent/commandCallback/confirmAction', 'Got it'));
|
|
136
140
|
}
|
|
137
141
|
}
|
|
@@ -20,3 +20,4 @@ export const SUGGEST_FILE_REPLACEMENTS_ID = 'suggestFileReplacements';
|
|
|
20
20
|
export const WRITE_FILE_REPLACEMENTS_ID = 'writeFileReplacements';
|
|
21
21
|
export const CLEAR_FILE_CHANGES_ID = 'clearFileChanges';
|
|
22
22
|
export const GET_PROPOSED_CHANGES_ID = 'getProposedFileState';
|
|
23
|
+
export const SUGGEST_FILE_REPLACEMENTS_NEXT_ID = 'suggestFileReplacements_Next';
|
|
@@ -50,7 +50,7 @@ export class OrchestratorChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
50
50
|
protected chatAgentService: ChatAgentService;
|
|
51
51
|
|
|
52
52
|
override async invoke(request: MutableChatRequestModel): Promise<void> {
|
|
53
|
-
request.response.addProgressMessage({ content: 'Determining the most appropriate agent', status: 'inProgress' });
|
|
53
|
+
request.response.addProgressMessage({ content: nls.localize('theia/ai/ide/orchestrator/progressMessage', 'Determining the most appropriate agent'), status: 'inProgress' });
|
|
54
54
|
// We use a dedicated id for the orchestrator request
|
|
55
55
|
const orchestratorRequestId = generateUuid();
|
|
56
56
|
request.addData(OrchestratorRequestIdKey, orchestratorRequestId);
|
|
@@ -114,15 +114,16 @@ export class OrchestratorChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
114
114
|
if (firstRegisteredAgent) {
|
|
115
115
|
agentIds = [firstRegisteredAgent];
|
|
116
116
|
} else {
|
|
117
|
-
throw new Error(
|
|
117
|
+
throw new Error(nls.localize('theia/ai/ide/orchestrator/error/noAgents',
|
|
118
|
+
'No chat agent available to handle request. Please check your configuration whether any are enabled.'));
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
// TODO support delegating to more than one agent
|
|
122
123
|
const delegatedToAgent = agentIds[0];
|
|
123
124
|
request.response.response.addContent(new InformationalChatResponseContentImpl(
|
|
124
|
-
`*Orchestrator*: Delegating to
|
|
125
|
-
|
|
125
|
+
`*Orchestrator*: ${nls.localize('theia/ai/ide/orchestrator/response/delegatingToAgent', 'Delegating to \`@{0}\`', delegatedToAgent)}
|
|
126
|
+
|
|
126
127
|
---
|
|
127
128
|
|
|
128
129
|
`
|
|
@@ -34,13 +34,13 @@ export const WorkspacePreferencesSchema: PreferenceSchema = {
|
|
|
34
34
|
title: nls.localize('theia/ai/workspace/considerGitignore/title', 'Consider .gitignore'),
|
|
35
35
|
description: nls.localize('theia/ai/workspace/considerGitignore/description',
|
|
36
36
|
'If enabled, excludes files/folders specified in a global .gitignore file (expected location is the workspace root).'),
|
|
37
|
-
default:
|
|
37
|
+
default: true
|
|
38
38
|
},
|
|
39
39
|
[USER_EXCLUDE_PATTERN_PREF]: {
|
|
40
40
|
type: 'array',
|
|
41
41
|
title: nls.localize('theia/ai/workspace/excludedPattern/title', 'Excluded File Patterns'),
|
|
42
42
|
description: nls.localize('theia/ai/workspace/excludedPattern/description', 'List of patterns (glob or regex) for files/folders to exclude.'),
|
|
43
|
-
default: ['node_modules', 'lib'
|
|
43
|
+
default: ['node_modules', 'lib'],
|
|
44
44
|
items: {
|
|
45
45
|
type: 'string'
|
|
46
46
|
}
|