@opensumi/ide-ai-native 3.8.1-next-1740965430.0 → 3.8.1-next-1741071284.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-core.contribution.js +1 -1
- package/lib/browser/ai-core.contribution.js.map +1 -1
- package/lib/browser/chat/chat-agent.service.d.ts +0 -8
- package/lib/browser/chat/chat-agent.service.d.ts.map +1 -1
- package/lib/browser/chat/chat-agent.service.js +0 -34
- package/lib/browser/chat/chat-agent.service.js.map +1 -1
- package/lib/browser/chat/chat-model.d.ts.map +1 -1
- package/lib/browser/chat/chat-model.js +2 -3
- package/lib/browser/chat/chat-model.js.map +1 -1
- package/lib/browser/chat/chat-proxy.service.d.ts.map +1 -1
- package/lib/browser/chat/chat-proxy.service.js +1 -1
- package/lib/browser/chat/chat-proxy.service.js.map +1 -1
- package/lib/browser/chat/chat.module.less +2 -1
- package/lib/browser/chat/chat.view.d.ts.map +1 -1
- package/lib/browser/chat/chat.view.js +60 -9
- package/lib/browser/chat/chat.view.js.map +1 -1
- package/lib/browser/components/ChatContext/index.js +2 -2
- package/lib/browser/components/ChatContext/index.js.map +1 -1
- package/lib/browser/components/ChatInput.d.ts.map +1 -1
- package/lib/browser/components/ChatInput.js +1 -25
- package/lib/browser/components/ChatInput.js.map +1 -1
- package/lib/browser/components/ChatToolRender.d.ts.map +1 -1
- package/lib/browser/components/ChatToolRender.js +3 -2
- package/lib/browser/components/ChatToolRender.js.map +1 -1
- package/lib/browser/components/chat-history.module.less +1 -1
- package/lib/browser/components/components.module.less +0 -20
- package/lib/browser/context/llm-context.service.d.ts +5 -18
- package/lib/browser/context/llm-context.service.d.ts.map +1 -1
- package/lib/browser/context/llm-context.service.js +47 -80
- package/lib/browser/context/llm-context.service.js.map +1 -1
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js +1 -1
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js.map +1 -1
- package/lib/browser/contrib/intelligent-completions/view/default.d.ts.map +1 -1
- package/lib/browser/contrib/intelligent-completions/view/default.js +6 -0
- package/lib/browser/contrib/intelligent-completions/view/default.js.map +1 -1
- package/lib/browser/layout/layout.module.less +4 -4
- package/lib/browser/mcp/tools/components/index.module.less +0 -1
- package/lib/browser/mcp/tools/createNewFileWithText.d.ts.map +1 -1
- package/lib/browser/mcp/tools/createNewFileWithText.js +0 -1
- package/lib/browser/mcp/tools/createNewFileWithText.js.map +1 -1
- package/lib/browser/mcp/tools/getDiagnosticsByPath.d.ts.map +1 -1
- package/lib/browser/mcp/tools/getDiagnosticsByPath.js +0 -1
- package/lib/browser/mcp/tools/getDiagnosticsByPath.js.map +1 -1
- package/lib/browser/mcp/tools/handlers/RunCommand.d.ts.map +1 -1
- package/lib/browser/mcp/tools/handlers/RunCommand.js +0 -2
- package/lib/browser/mcp/tools/handlers/RunCommand.js.map +1 -1
- package/lib/browser/mcp/tools/runTerminalCmd.d.ts.map +1 -1
- package/lib/browser/mcp/tools/runTerminalCmd.js +0 -1
- package/lib/browser/mcp/tools/runTerminalCmd.js.map +1 -1
- package/lib/browser/preferences/schema.d.ts.map +1 -1
- package/lib/browser/preferences/schema.js +1 -0
- package/lib/browser/preferences/schema.js.map +1 -1
- package/lib/common/llm-context.d.ts +9 -13
- package/lib/common/llm-context.d.ts.map +1 -1
- package/lib/common/llm-context.js.map +1 -1
- package/lib/common/prompts/context-prompt-provider.d.ts +3 -4
- package/lib/common/prompts/context-prompt-provider.d.ts.map +1 -1
- package/lib/common/prompts/context-prompt-provider.js +22 -33
- package/lib/common/prompts/context-prompt-provider.js.map +1 -1
- package/package.json +23 -23
- package/src/browser/ai-core.contribution.ts +1 -1
- package/src/browser/chat/chat-agent.service.ts +3 -42
- package/src/browser/chat/chat-model.ts +6 -11
- package/src/browser/chat/chat-proxy.service.ts +1 -2
- package/src/browser/chat/chat.module.less +2 -1
- package/src/browser/chat/chat.view.tsx +95 -10
- package/src/browser/components/ChatContext/index.tsx +2 -2
- package/src/browser/components/ChatInput.tsx +3 -67
- package/src/browser/components/ChatToolRender.tsx +2 -1
- package/src/browser/components/chat-history.module.less +1 -1
- package/src/browser/components/components.module.less +0 -20
- package/src/browser/context/llm-context.service.ts +54 -93
- package/src/browser/contrib/intelligent-completions/intelligent-completions.controller.ts +1 -1
- package/src/browser/contrib/intelligent-completions/view/default.ts +7 -0
- package/src/browser/layout/layout.module.less +4 -4
- package/src/browser/mcp/tools/components/index.module.less +0 -1
- package/src/browser/mcp/tools/createNewFileWithText.ts +0 -1
- package/src/browser/mcp/tools/getDiagnosticsByPath.ts +0 -1
- package/src/browser/mcp/tools/handlers/RunCommand.ts +0 -2
- package/src/browser/mcp/tools/runTerminalCmd.ts +0 -1
- package/src/browser/preferences/schema.ts +1 -0
- package/src/common/llm-context.ts +4 -10
- package/src/common/prompts/context-prompt-provider.ts +29 -38
|
@@ -4,15 +4,16 @@ import { Autowired, Injectable } from '@opensumi/di';
|
|
|
4
4
|
import {
|
|
5
5
|
CancellationToken,
|
|
6
6
|
ChatFeatureRegistryToken,
|
|
7
|
-
ChatMessageRole,
|
|
8
7
|
ChatServiceToken,
|
|
9
8
|
Disposable,
|
|
10
9
|
Emitter,
|
|
10
|
+
IChatContent,
|
|
11
11
|
IChatProgress,
|
|
12
12
|
IDisposable,
|
|
13
13
|
ILogger,
|
|
14
|
-
toDisposable
|
|
14
|
+
toDisposable,
|
|
15
15
|
} from '@opensumi/ide-core-common';
|
|
16
|
+
import { ChatMessageRole } from '@opensumi/ide-core-common';
|
|
16
17
|
import { IChatMessage } from '@opensumi/ide-core-common/lib/types/ai-native';
|
|
17
18
|
|
|
18
19
|
import {
|
|
@@ -25,8 +26,6 @@ import {
|
|
|
25
26
|
IChatFollowup,
|
|
26
27
|
IChatMessageStructure,
|
|
27
28
|
} from '../../common';
|
|
28
|
-
import { LLMContextService, LLMContextServiceToken } from '../../common/llm-context';
|
|
29
|
-
import { ChatAgentPromptProvider } from '../../common/prompts/context-prompt-provider';
|
|
30
29
|
import { IChatFeatureRegistry } from '../types';
|
|
31
30
|
|
|
32
31
|
import { ChatService } from './chat.api.service';
|
|
@@ -37,12 +36,6 @@ export class ChatAgentService extends Disposable implements IChatAgentService {
|
|
|
37
36
|
|
|
38
37
|
private defaultAgentId: string | undefined;
|
|
39
38
|
|
|
40
|
-
private initialUserMessageMap: Map<string, string> = new Map();
|
|
41
|
-
|
|
42
|
-
private shouldUpdateContext = false;
|
|
43
|
-
|
|
44
|
-
private contextVersion: number;
|
|
45
|
-
|
|
46
39
|
private readonly _onDidChangeAgents = new Emitter<void>();
|
|
47
40
|
readonly onDidChangeAgents = this._onDidChangeAgents.event;
|
|
48
41
|
|
|
@@ -52,12 +45,6 @@ export class ChatAgentService extends Disposable implements IChatAgentService {
|
|
|
52
45
|
@Autowired(ILogger)
|
|
53
46
|
logger: ILogger;
|
|
54
47
|
|
|
55
|
-
@Autowired(LLMContextServiceToken)
|
|
56
|
-
protected readonly contextService: LLMContextService;
|
|
57
|
-
|
|
58
|
-
@Autowired(ChatAgentPromptProvider)
|
|
59
|
-
protected readonly promptProvider: ChatAgentPromptProvider;
|
|
60
|
-
|
|
61
48
|
@Autowired(ChatServiceToken)
|
|
62
49
|
private aiChatService: ChatService;
|
|
63
50
|
|
|
@@ -67,12 +54,6 @@ export class ChatAgentService extends Disposable implements IChatAgentService {
|
|
|
67
54
|
constructor() {
|
|
68
55
|
super();
|
|
69
56
|
this.addDispose(this._onDidChangeAgents);
|
|
70
|
-
this.addDispose(this.contextService.onDidContextFilesChangeEvent((event) => {
|
|
71
|
-
if (event.version !== this.contextVersion) {
|
|
72
|
-
this.contextVersion = event.version;
|
|
73
|
-
this.shouldUpdateContext = true;
|
|
74
|
-
}
|
|
75
|
-
}));
|
|
76
57
|
}
|
|
77
58
|
|
|
78
59
|
registerAgent(agent: IChatAgent): IDisposable {
|
|
@@ -139,8 +120,6 @@ export class ChatAgentService extends Disposable implements IChatAgentService {
|
|
|
139
120
|
if (!data) {
|
|
140
121
|
throw new Error(`No agent with id ${id}`);
|
|
141
122
|
}
|
|
142
|
-
|
|
143
|
-
// system
|
|
144
123
|
if (data.agent.metadata.systemPrompt) {
|
|
145
124
|
history.unshift({
|
|
146
125
|
role: ChatMessageRole.System,
|
|
@@ -148,28 +127,10 @@ export class ChatAgentService extends Disposable implements IChatAgentService {
|
|
|
148
127
|
});
|
|
149
128
|
}
|
|
150
129
|
|
|
151
|
-
// 发送第一条消息时携带初始 context
|
|
152
|
-
if (!this.initialUserMessageMap.has(id)) {
|
|
153
|
-
this.initialUserMessageMap.set(id, request.message);
|
|
154
|
-
const rawMessage = request.message;
|
|
155
|
-
request.message = this.provideContextMessage(rawMessage);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (this.shouldUpdateContext) {
|
|
159
|
-
request.message = this.provideContextMessage(request.message);
|
|
160
|
-
this.shouldUpdateContext = false;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
130
|
const result = await data.agent.invoke(request, progress, history, token);
|
|
164
131
|
return result;
|
|
165
132
|
}
|
|
166
133
|
|
|
167
|
-
private provideContextMessage(message: string) {
|
|
168
|
-
const context = this.contextService.serialize();
|
|
169
|
-
const fullMessage = this.promptProvider.provideContextPrompt(context, message);
|
|
170
|
-
return fullMessage;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
134
|
populateChatInput(id: string, message: IChatMessageStructure) {
|
|
174
135
|
this.aiChatService.sendMessage({
|
|
175
136
|
...message,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Injectable } from '@opensumi/di';
|
|
1
|
+
import { Autowired, INJECTOR_TOKEN, Injectable, Injector } from '@opensumi/di';
|
|
2
2
|
import {
|
|
3
3
|
Disposable,
|
|
4
4
|
Emitter,
|
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
IChatProgress,
|
|
9
9
|
IChatToolContent,
|
|
10
10
|
IChatTreeData,
|
|
11
|
+
ILogger,
|
|
12
|
+
memoize,
|
|
11
13
|
uuid,
|
|
12
14
|
} from '@opensumi/ide-core-common';
|
|
13
15
|
import { MarkdownString, isMarkdownString } from '@opensumi/monaco-editor-core/esm/vs/base/common/htmlContent';
|
|
@@ -272,18 +274,13 @@ export class ChatRequestModel implements IChatRequestModel {
|
|
|
272
274
|
export class ChatModel extends Disposable implements IChatModel {
|
|
273
275
|
private static requestIdPool = 0;
|
|
274
276
|
|
|
275
|
-
constructor(initParams?: {
|
|
276
|
-
sessionId?: string;
|
|
277
|
-
history?: MsgHistoryManager;
|
|
278
|
-
requests?: ChatRequestModel[];
|
|
279
|
-
}) {
|
|
277
|
+
constructor(initParams?: { sessionId?: string; history?: MsgHistoryManager; requests?: ChatRequestModel[] }) {
|
|
280
278
|
super();
|
|
281
279
|
this.#sessionId = initParams?.sessionId ?? uuid();
|
|
282
280
|
this.history = initParams?.history ?? new MsgHistoryManager();
|
|
283
281
|
if (initParams?.requests) {
|
|
284
282
|
this.#requests = new Map(initParams.requests.map((r) => [r.requestId, r]));
|
|
285
283
|
}
|
|
286
|
-
|
|
287
284
|
}
|
|
288
285
|
|
|
289
286
|
#sessionId: string;
|
|
@@ -303,11 +300,9 @@ export class ChatModel extends Disposable implements IChatModel {
|
|
|
303
300
|
readonly history: MsgHistoryManager;
|
|
304
301
|
|
|
305
302
|
addRequest(message: IChatRequestMessage): ChatRequestModel {
|
|
306
|
-
const msg = message;
|
|
307
|
-
|
|
308
303
|
const requestId = `${this.sessionId}_request_${ChatModel.requestIdPool++}`;
|
|
309
|
-
const response = new ChatResponseModel(requestId, this,
|
|
310
|
-
const request = new ChatRequestModel(requestId, this,
|
|
304
|
+
const response = new ChatResponseModel(requestId, this, message.agentId);
|
|
305
|
+
const request = new ChatRequestModel(requestId, this, message, response);
|
|
311
306
|
|
|
312
307
|
this.#requests.set(requestId, request);
|
|
313
308
|
return request;
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
ChatServiceToken,
|
|
9
9
|
Deferred,
|
|
10
10
|
Disposable,
|
|
11
|
-
getOperatingSystemName,
|
|
12
11
|
IAIBackService,
|
|
13
12
|
IAIReporter,
|
|
14
13
|
IApplicationService,
|
|
@@ -93,7 +92,7 @@ export class ChatProxyService extends Disposable {
|
|
|
93
92
|
AINativeSettingSectionsId.SystemPrompt,
|
|
94
93
|
'You are a powerful AI coding assistant working in OpenSumi, a top IDE framework. You collaborate with a USER to solve coding tasks, which may involve creating, modifying, or debugging code, or answering questions. When the USER sends a message, relevant context (e.g., open files, cursor position, edit history, linter errors) may be attached. Use this information as needed.\n\n<tool_calling>\nYou have access to tools to assist with tasks. Follow these rules:\n1. Always adhere to the tool call schema and provide all required parameters.\n2. Only use tools explicitly provided; ignore unavailable ones.\n3. Avoid mentioning tool names to the USER (e.g., say "I will edit your file" instead of "I need to use the edit_file tool").\n4. Only call tools when necessary; respond directly if the task is general or you already know the answer.\n5. Explain to the USER why you’re using a tool before calling it.\n</tool_calling>\n\n<making_code_changes>\nWhen modifying code:\n1. Use code edit tools instead of outputting code unless explicitly requested.\n2. Limit tool calls to one per turn.\n3. Ensure generated code is immediately executable by including necessary imports, dependencies, and endpoints.\n4. For new projects, create a dependency management file (e.g., requirements.txt) and a README.\n5. For web apps, design a modern, user-friendly UI.\n6. Avoid generating non-textual or excessively long code.\n7. Read file contents before editing, unless appending a small change or creating a new file.\n8. Fix introduced linter errors if possible, but stop after 3 attempts and ask the USER for guidance.\n9. Reapply reasonable code edits if they weren’t followed initially.\n</making_code_changes>\n\nUse the appropriate tools to fulfill the USER’s request, ensuring all required parameters are provided or inferred from context.',
|
|
95
94
|
) +
|
|
96
|
-
`\n\n<user_info>\nThe user's OS is ${
|
|
95
|
+
`\n\n<user_info>\nThe user's OS version is ${this.applicationService.frontendOS}. The absolute path of the user's workspace is ${this.appConfig.workspaceDir}.\n</user_info>`,
|
|
97
96
|
},
|
|
98
97
|
invoke: async (
|
|
99
98
|
request: IChatAgentRequest,
|
|
@@ -279,6 +279,7 @@
|
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
+
|
|
282
283
|
.chat_tips_container {
|
|
283
284
|
display: flex;
|
|
284
285
|
align-items: center;
|
|
@@ -289,6 +290,6 @@
|
|
|
289
290
|
}
|
|
290
291
|
|
|
291
292
|
.chat_history {
|
|
292
|
-
width: calc(100% -
|
|
293
|
+
width: calc(100% - 60px);
|
|
293
294
|
color: var(--design-text-foreground);
|
|
294
295
|
}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
AINativeConfigService,
|
|
6
6
|
CommandService,
|
|
7
7
|
getIcon,
|
|
8
|
+
useEventEffect,
|
|
8
9
|
useInjectable,
|
|
9
10
|
useUpdateOnEvent,
|
|
10
11
|
} from '@opensumi/ide-core-browser';
|
|
@@ -41,6 +42,8 @@ import {
|
|
|
41
42
|
IChatMessageStructure,
|
|
42
43
|
TokenMCPServerProxyService,
|
|
43
44
|
} from '../../common';
|
|
45
|
+
import { LLMContextService, LLMContextServiceToken } from '../../common/llm-context';
|
|
46
|
+
import { ChatAgentPromptProvider } from '../../common/prompts/context-prompt-provider';
|
|
44
47
|
import { ChatContext } from '../components/ChatContext';
|
|
45
48
|
import { CodeBlockWrapperInput } from '../components/ChatEditor';
|
|
46
49
|
import ChatHistory, { IChatHistoryItem } from '../components/ChatHistory';
|
|
@@ -79,11 +82,18 @@ export const AIChatView = () => {
|
|
|
79
82
|
const chatAgentService = useInjectable<IChatAgentService>(IChatAgentService);
|
|
80
83
|
const chatFeatureRegistry = useInjectable<ChatFeatureRegistry>(ChatFeatureRegistryToken);
|
|
81
84
|
const chatRenderRegistry = useInjectable<ChatRenderRegistry>(ChatRenderRegistryToken);
|
|
85
|
+
const contextService = useInjectable<LLMContextService>(LLMContextServiceToken);
|
|
86
|
+
const promptProvider = useInjectable<ChatAgentPromptProvider>(ChatAgentPromptProvider);
|
|
87
|
+
const mcpServerProxyService = useInjectable<MCPServerProxyService>(TokenMCPServerProxyService);
|
|
82
88
|
|
|
83
89
|
const layoutService = useInjectable<IMainLayoutService>(IMainLayoutService);
|
|
84
90
|
const msgHistoryManager = aiChatService.sessionModel.history;
|
|
85
91
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
|
92
|
+
const autoScroll = React.useRef<boolean>(true);
|
|
86
93
|
const chatInputRef = React.useRef<{ setInputValue: (v: string) => void } | null>(null);
|
|
94
|
+
const dialogService = useInjectable<IDialogService>(IDialogService);
|
|
95
|
+
const aiNativeConfigService = useInjectable<AINativeConfigService>(AINativeConfigService);
|
|
96
|
+
const commandService = useInjectable<CommandService>(CommandService);
|
|
87
97
|
|
|
88
98
|
const [shortcutCommands, setShortcutCommands] = React.useState<ChatSlashCommandItemModel[]>([]);
|
|
89
99
|
|
|
@@ -105,6 +115,8 @@ export const AIChatView = () => {
|
|
|
105
115
|
const [defaultAgentId, setDefaultAgentId] = React.useState<string>('');
|
|
106
116
|
const [command, setCommand] = React.useState('');
|
|
107
117
|
const [theme, setTheme] = React.useState<string | null>(null);
|
|
118
|
+
const [mcpToolsCount, setMcpToolsCount] = React.useState<number>(0);
|
|
119
|
+
const [mcpServersCount, setMcpServersCount] = React.useState<number>(0);
|
|
108
120
|
|
|
109
121
|
React.useEffect(() => {
|
|
110
122
|
const featureSlashCommands = chatFeatureRegistry.getAllShortcutSlashCommand();
|
|
@@ -154,8 +166,29 @@ export const AIChatView = () => {
|
|
|
154
166
|
[],
|
|
155
167
|
);
|
|
156
168
|
|
|
169
|
+
const onDidWheel = React.useCallback(
|
|
170
|
+
(e: WheelEvent) => {
|
|
171
|
+
// 向上滚动
|
|
172
|
+
if (e.deltaY < 0) {
|
|
173
|
+
autoScroll.current = false;
|
|
174
|
+
} else {
|
|
175
|
+
autoScroll.current = true;
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
[autoScroll],
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
React.useEffect(() => {
|
|
182
|
+
if (containerRef.current) {
|
|
183
|
+
containerRef.current.addEventListener('wheel', onDidWheel);
|
|
184
|
+
return () => {
|
|
185
|
+
containerRef.current?.removeEventListener('wheel', onDidWheel);
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
}, [autoScroll]);
|
|
189
|
+
|
|
157
190
|
const scrollToBottom = React.useCallback(() => {
|
|
158
|
-
if (containerRef && containerRef.current) {
|
|
191
|
+
if (containerRef && containerRef.current && autoScroll.current) {
|
|
159
192
|
const lastElement = containerRef.current.lastElementChild;
|
|
160
193
|
if (lastElement) {
|
|
161
194
|
lastElement.scrollIntoView({ behavior: 'smooth', block: 'end' });
|
|
@@ -165,7 +198,7 @@ export const AIChatView = () => {
|
|
|
165
198
|
containerRef.current.classList.add(SCROLL_CLASSNAME);
|
|
166
199
|
}
|
|
167
200
|
}
|
|
168
|
-
}, [containerRef]);
|
|
201
|
+
}, [containerRef, autoScroll]);
|
|
169
202
|
|
|
170
203
|
const handleDispatchMessage = React.useCallback(
|
|
171
204
|
(dispatch: TDispatchAction) => {
|
|
@@ -187,7 +220,7 @@ export const AIChatView = () => {
|
|
|
187
220
|
disposer.addDispose(
|
|
188
221
|
chatApiService.onScrollToBottom(() => {
|
|
189
222
|
requestAnimationFrame(() => {
|
|
190
|
-
scrollToBottom();
|
|
223
|
+
// scrollToBottom();
|
|
191
224
|
});
|
|
192
225
|
}),
|
|
193
226
|
);
|
|
@@ -504,7 +537,10 @@ export const AIChatView = () => {
|
|
|
504
537
|
const { message, agentId, command, reportExtra } = value;
|
|
505
538
|
const { actionType, actionSource } = reportExtra || {};
|
|
506
539
|
|
|
507
|
-
const
|
|
540
|
+
const context = contextService.serialize();
|
|
541
|
+
const fullMessage = await promptProvider.provideContextPrompt(context, message);
|
|
542
|
+
|
|
543
|
+
const request = aiChatService.createRequest(fullMessage, agentId!, command);
|
|
508
544
|
if (!request) {
|
|
509
545
|
return;
|
|
510
546
|
}
|
|
@@ -653,6 +689,32 @@ export const AIChatView = () => {
|
|
|
653
689
|
};
|
|
654
690
|
}, [aiChatService.sessionModel]);
|
|
655
691
|
|
|
692
|
+
useEventEffect(
|
|
693
|
+
mcpServerProxyService.onChangeMCPServers,
|
|
694
|
+
() => {
|
|
695
|
+
mcpServerProxyService.getAllMCPTools().then((tools) => {
|
|
696
|
+
setMcpToolsCount(tools.length);
|
|
697
|
+
});
|
|
698
|
+
mcpServerProxyService.$getServers().then((servers) => {
|
|
699
|
+
setMcpServersCount(servers.length);
|
|
700
|
+
});
|
|
701
|
+
},
|
|
702
|
+
[mcpServerProxyService],
|
|
703
|
+
);
|
|
704
|
+
|
|
705
|
+
const handleShowMCPTools = React.useCallback(async () => {
|
|
706
|
+
const tools = await mcpServerProxyService.getAllMCPTools();
|
|
707
|
+
dialogService.open({
|
|
708
|
+
message: <MCPToolsDialog tools={tools} />,
|
|
709
|
+
type: MessageType.Empty,
|
|
710
|
+
buttons: ['关闭'],
|
|
711
|
+
});
|
|
712
|
+
}, [mcpServerProxyService, dialogService]);
|
|
713
|
+
|
|
714
|
+
const handleShowMCPConfig = React.useCallback(() => {
|
|
715
|
+
commandService.executeCommand(OPEN_MCP_CONFIG_COMMAND.id);
|
|
716
|
+
}, [commandService]);
|
|
717
|
+
|
|
656
718
|
return (
|
|
657
719
|
<div id={styles.ai_chat_view}>
|
|
658
720
|
<div className={styles.header_container}>
|
|
@@ -692,6 +754,18 @@ export const AIChatView = () => {
|
|
|
692
754
|
</Popover>
|
|
693
755
|
))}
|
|
694
756
|
</div>
|
|
757
|
+
<div className={styles.header_operate_right}>
|
|
758
|
+
{aiNativeConfigService.capabilities.supportsMCP && (
|
|
759
|
+
<>
|
|
760
|
+
<div className={styles.tag} onClick={handleShowMCPConfig}>
|
|
761
|
+
{`MCP Servers: ${mcpServersCount}`}
|
|
762
|
+
</div>
|
|
763
|
+
<div className={styles.tag} onClick={handleShowMCPTools}>
|
|
764
|
+
{`MCP Tools: ${mcpToolsCount}`}
|
|
765
|
+
</div>
|
|
766
|
+
</>
|
|
767
|
+
)}
|
|
768
|
+
</div>
|
|
695
769
|
</div>
|
|
696
770
|
<ChatInputWrapperRender
|
|
697
771
|
onSend={(value, agentId, command) =>
|
|
@@ -734,8 +808,6 @@ export function DefaultChatViewHeader({
|
|
|
734
808
|
const aiNativeConfigService = useInjectable<AINativeConfigService>(AINativeConfigService);
|
|
735
809
|
const mcpServerProxyService = useInjectable<MCPServerProxyService>(TokenMCPServerProxyService);
|
|
736
810
|
const aiChatService = useInjectable<ChatInternalService>(IChatInternalService);
|
|
737
|
-
const commandService = useInjectable<CommandService>(CommandService);
|
|
738
|
-
|
|
739
811
|
const [historyList, setHistoryList] = React.useState<IChatHistoryItem[]>([]);
|
|
740
812
|
const [currentTitle, setCurrentTitle] = React.useState<string>('');
|
|
741
813
|
const handleNewChat = React.useCallback(() => {
|
|
@@ -756,10 +828,6 @@ export function DefaultChatViewHeader({
|
|
|
756
828
|
[aiChatService],
|
|
757
829
|
);
|
|
758
830
|
|
|
759
|
-
const handleShowMCPConfig = React.useCallback(() => {
|
|
760
|
-
commandService.executeCommand(OPEN_MCP_CONFIG_COMMAND.id);
|
|
761
|
-
}, [commandService]);
|
|
762
|
-
|
|
763
831
|
const handleShowMCPTools = React.useCallback(async () => {
|
|
764
832
|
const tools = await mcpServerProxyService.getAllMCPTools();
|
|
765
833
|
dialogService.open({
|
|
@@ -848,6 +916,23 @@ export function DefaultChatViewHeader({
|
|
|
848
916
|
ariaLabel={localize('aiNative.operate.clear.title')}
|
|
849
917
|
/>
|
|
850
918
|
</Popover>
|
|
919
|
+
{aiNativeConfigService.capabilities.supportsMCP && (
|
|
920
|
+
<Popover
|
|
921
|
+
overlayClassName={styles.popover_icon}
|
|
922
|
+
id={'ai-chat-header-tools'}
|
|
923
|
+
position={PopoverPosition.left}
|
|
924
|
+
title={localize('aiNative.operate.tools.title')}
|
|
925
|
+
>
|
|
926
|
+
<EnhanceIcon
|
|
927
|
+
wrapperClassName={styles.action_btn}
|
|
928
|
+
className={getIcon('menubar-tool')}
|
|
929
|
+
onClick={handleShowMCPTools}
|
|
930
|
+
tabIndex={0}
|
|
931
|
+
role='button'
|
|
932
|
+
ariaLabel={localize('aiNative.operate.tools.title')}
|
|
933
|
+
/>
|
|
934
|
+
</Popover>
|
|
935
|
+
)}
|
|
851
936
|
<Popover
|
|
852
937
|
overlayClassName={styles.popover_icon}
|
|
853
938
|
id={'ai-chat-header-close'}
|
|
@@ -39,7 +39,7 @@ export const ChatContext = memo(() => {
|
|
|
39
39
|
50,
|
|
40
40
|
)((files) => {
|
|
41
41
|
if (files) {
|
|
42
|
-
updateAddedFiles(
|
|
42
|
+
updateAddedFiles(files);
|
|
43
43
|
}
|
|
44
44
|
}, contextService);
|
|
45
45
|
|
|
@@ -57,7 +57,7 @@ export const ChatContext = memo(() => {
|
|
|
57
57
|
}, []);
|
|
58
58
|
|
|
59
59
|
const onDidDeselect = useCallback((uri: URI) => {
|
|
60
|
-
contextService.removeFileFromContext(uri
|
|
60
|
+
contextService.removeFileFromContext(uri);
|
|
61
61
|
}, []);
|
|
62
62
|
|
|
63
63
|
const onDidClickFile = useCallback((uri: URI) => {
|
|
@@ -1,29 +1,18 @@
|
|
|
1
1
|
import cls from 'classnames';
|
|
2
2
|
import React, { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { useInjectable, useLatest } from '@opensumi/ide-core-browser';
|
|
5
5
|
import { Icon, Popover, PopoverPosition, getIcon } from '@opensumi/ide-core-browser/lib/components';
|
|
6
6
|
import { EnhanceIcon } from '@opensumi/ide-core-browser/lib/components/ai-native';
|
|
7
7
|
import { InteractiveInput } from '@opensumi/ide-core-browser/lib/components/ai-native/interactive-input/index';
|
|
8
|
-
import {
|
|
9
|
-
ChatAgentViewServiceToken,
|
|
10
|
-
ChatFeatureRegistryToken,
|
|
11
|
-
MessageType,
|
|
12
|
-
localize,
|
|
13
|
-
runWhenIdle,
|
|
14
|
-
} from '@opensumi/ide-core-common';
|
|
15
|
-
import { CommandService } from '@opensumi/ide-core-common/lib/command';
|
|
8
|
+
import { ChatAgentViewServiceToken, ChatFeatureRegistryToken, localize, runWhenIdle } from '@opensumi/ide-core-common';
|
|
16
9
|
import { MonacoCommandRegistry } from '@opensumi/ide-editor/lib/browser/monaco-contrib/command/command.service';
|
|
17
|
-
import { IDialogService } from '@opensumi/ide-overlay';
|
|
18
10
|
|
|
19
|
-
import { AT_SIGN_SYMBOL, IChatAgentService, SLASH_SYMBOL
|
|
11
|
+
import { AT_SIGN_SYMBOL, IChatAgentService, SLASH_SYMBOL } from '../../common';
|
|
20
12
|
import { ChatAgentViewService } from '../chat/chat-agent.view.service';
|
|
21
13
|
import { ChatSlashCommandItemModel } from '../chat/chat-model';
|
|
22
14
|
import { ChatProxyService } from '../chat/chat-proxy.service';
|
|
23
15
|
import { ChatFeatureRegistry } from '../chat/chat.feature.registry';
|
|
24
|
-
import { OPEN_MCP_CONFIG_COMMAND } from '../mcp/config/mcp-config.commands';
|
|
25
|
-
import { MCPServerProxyService } from '../mcp/mcp-server-proxy.service';
|
|
26
|
-
import { MCPToolsDialog } from '../mcp/mcp-tools-dialog.view';
|
|
27
16
|
import { IChatSlashCommandItem } from '../types';
|
|
28
17
|
|
|
29
18
|
import styles from './components.module.less';
|
|
@@ -205,29 +194,12 @@ export const ChatInput = React.forwardRef((props: IChatInputProps, ref) => {
|
|
|
205
194
|
const [isExpand, setIsExpand] = useState(false);
|
|
206
195
|
const [placeholder, setPlaceHolder] = useState(localize('aiNative.chat.input.placeholder.default'));
|
|
207
196
|
|
|
208
|
-
const dialogService = useInjectable<IDialogService>(IDialogService);
|
|
209
|
-
const aiNativeConfigService = useInjectable<AINativeConfigService>(AINativeConfigService);
|
|
210
|
-
const mcpServerProxyService = useInjectable<MCPServerProxyService>(TokenMCPServerProxyService);
|
|
211
197
|
const monacoCommandRegistry = useInjectable<MonacoCommandRegistry>(MonacoCommandRegistry);
|
|
212
198
|
const chatAgentService = useInjectable<IChatAgentService>(IChatAgentService);
|
|
213
199
|
const chatFeatureRegistry = useInjectable<ChatFeatureRegistry>(ChatFeatureRegistryToken);
|
|
214
|
-
const commandService = useInjectable<CommandService>(CommandService);
|
|
215
200
|
|
|
216
201
|
const currentAgentIdRef = useLatest(agentId);
|
|
217
202
|
|
|
218
|
-
const handleShowMCPConfig = React.useCallback(() => {
|
|
219
|
-
commandService.executeCommand(OPEN_MCP_CONFIG_COMMAND.id);
|
|
220
|
-
}, [commandService]);
|
|
221
|
-
|
|
222
|
-
const handleShowMCPTools = React.useCallback(async () => {
|
|
223
|
-
const tools = await mcpServerProxyService.getAllMCPTools();
|
|
224
|
-
dialogService.open({
|
|
225
|
-
message: <MCPToolsDialog tools={tools} />,
|
|
226
|
-
type: MessageType.Empty,
|
|
227
|
-
buttons: ['关闭'],
|
|
228
|
-
});
|
|
229
|
-
}, [mcpServerProxyService, dialogService]);
|
|
230
|
-
|
|
231
203
|
useImperativeHandle(ref, () => ({
|
|
232
204
|
setInputValue: (v: string) => {
|
|
233
205
|
setValue(v);
|
|
@@ -489,42 +461,6 @@ export const ChatInput = React.forwardRef((props: IChatInputProps, ref) => {
|
|
|
489
461
|
height={inputHeight}
|
|
490
462
|
popoverPosition={PopoverPosition.left}
|
|
491
463
|
/>
|
|
492
|
-
<div className={styles.chat_input_footer}>
|
|
493
|
-
{aiNativeConfigService.capabilities.supportsMCP && (
|
|
494
|
-
<div className={styles.mcp_desc}>
|
|
495
|
-
<Popover
|
|
496
|
-
overlayClassName={styles.popover_icon}
|
|
497
|
-
id={'ai-chat-header-mcp-server'}
|
|
498
|
-
position={PopoverPosition.left}
|
|
499
|
-
title={'MCP Server'}
|
|
500
|
-
>
|
|
501
|
-
<EnhanceIcon
|
|
502
|
-
wrapperClassName={styles.action_btn}
|
|
503
|
-
className={'codicon codicon-server'}
|
|
504
|
-
onClick={handleShowMCPConfig}
|
|
505
|
-
tabIndex={0}
|
|
506
|
-
role='button'
|
|
507
|
-
ariaLabel={'MCP Server'}
|
|
508
|
-
/>
|
|
509
|
-
</Popover>
|
|
510
|
-
<Popover
|
|
511
|
-
overlayClassName={styles.popover_icon}
|
|
512
|
-
id={'ai-chat-header-tools'}
|
|
513
|
-
position={PopoverPosition.left}
|
|
514
|
-
title={localize('aiNative.operate.tools.title')}
|
|
515
|
-
>
|
|
516
|
-
<EnhanceIcon
|
|
517
|
-
wrapperClassName={styles.action_btn}
|
|
518
|
-
className={getIcon('menubar-tool')}
|
|
519
|
-
onClick={handleShowMCPTools}
|
|
520
|
-
tabIndex={0}
|
|
521
|
-
role='button'
|
|
522
|
-
ariaLabel={localize('aiNative.operate.tools.title')}
|
|
523
|
-
/>
|
|
524
|
-
</Popover>
|
|
525
|
-
</div>
|
|
526
|
-
)}
|
|
527
|
-
</div>
|
|
528
464
|
</div>
|
|
529
465
|
);
|
|
530
466
|
});
|
|
@@ -67,12 +67,13 @@ export const ChatToolRender = (props: { value: IChatToolContent['content']; mess
|
|
|
67
67
|
<div className={styles['chat-tool-render']}>
|
|
68
68
|
<div className={styles['tool-header']} onClick={toggleExpand}>
|
|
69
69
|
<div className={styles['tool-name']}>
|
|
70
|
-
<
|
|
70
|
+
<span className={cls(styles['expand-icon'], { [styles.expanded]: isExpanded })}>▶</span>
|
|
71
71
|
{label}
|
|
72
72
|
</div>
|
|
73
73
|
{value.state && (
|
|
74
74
|
<div className={styles['tool-state']}>
|
|
75
75
|
<span className={styles['state-icon']}>{stateInfo.icon}</span>
|
|
76
|
+
<span className={styles['state-label']}>{stateInfo.label}</span>
|
|
76
77
|
</div>
|
|
77
78
|
)}
|
|
78
79
|
</div>
|
|
@@ -96,7 +96,6 @@
|
|
|
96
96
|
.chat_input_container {
|
|
97
97
|
position: relative;
|
|
98
98
|
border-radius: 9px;
|
|
99
|
-
padding: 10px 0px 0px 0px;
|
|
100
99
|
border: 1px solid var(--kt-input-border);
|
|
101
100
|
background-color: var(--design-chatInput-background);
|
|
102
101
|
&.active {
|
|
@@ -506,22 +505,3 @@
|
|
|
506
505
|
}
|
|
507
506
|
}
|
|
508
507
|
}
|
|
509
|
-
|
|
510
|
-
.chat_input_footer {
|
|
511
|
-
padding: 0px 10px;
|
|
512
|
-
display: flex;
|
|
513
|
-
align-items: center;
|
|
514
|
-
font-size: 12px;
|
|
515
|
-
|
|
516
|
-
.model_selector {
|
|
517
|
-
display: flex;
|
|
518
|
-
font-size: 11px;
|
|
519
|
-
align-items: center;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
.mcp_desc {
|
|
523
|
-
padding: 5px 0px;
|
|
524
|
-
display: flex;
|
|
525
|
-
align-items: center;
|
|
526
|
-
}
|
|
527
|
-
}
|