@opensumi/ide-ai-native 3.7.2-next-1740107209.0 → 3.7.2-next-1740365741.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.d.ts +3 -1
- package/lib/browser/ai-core.contribution.d.ts.map +1 -1
- package/lib/browser/ai-core.contribution.js +13 -1
- package/lib/browser/ai-core.contribution.js.map +1 -1
- package/lib/browser/chat/chat-manager.service.d.ts +30 -2
- package/lib/browser/chat/chat-manager.service.d.ts.map +1 -1
- package/lib/browser/chat/chat-manager.service.js +45 -1
- package/lib/browser/chat/chat-manager.service.js.map +1 -1
- package/lib/browser/chat/chat-model.d.ts +33 -6
- package/lib/browser/chat/chat-model.d.ts.map +1 -1
- package/lib/browser/chat/chat-model.js +50 -29
- package/lib/browser/chat/chat-model.js.map +1 -1
- package/lib/browser/chat/chat-proxy.service.d.ts +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.internal.service.d.ts +4 -2
- package/lib/browser/chat/chat.internal.service.d.ts.map +1 -1
- package/lib/browser/chat/chat.internal.service.js +31 -12
- package/lib/browser/chat/chat.internal.service.js.map +1 -1
- package/lib/browser/chat/chat.module.less +8 -42
- package/lib/browser/chat/chat.view.d.ts.map +1 -1
- package/lib/browser/chat/chat.view.js +85 -31
- package/lib/browser/chat/chat.view.js.map +1 -1
- package/lib/browser/components/ChatContext/index.d.ts.map +1 -1
- package/lib/browser/components/ChatContext/index.js +18 -2
- package/lib/browser/components/ChatContext/index.js.map +1 -1
- package/lib/browser/components/ChatContext/style.module.less +12 -0
- package/lib/browser/components/ChatHistory.d.ts +21 -0
- package/lib/browser/components/ChatHistory.d.ts.map +1 -0
- package/lib/browser/components/ChatHistory.js +148 -0
- package/lib/browser/components/ChatHistory.js.map +1 -0
- package/lib/browser/components/ChatReply.d.ts.map +1 -1
- package/lib/browser/components/ChatReply.js +3 -1
- package/lib/browser/components/ChatReply.js.map +1 -1
- package/lib/browser/components/ChatThinking.js +1 -1
- package/lib/browser/components/ChatThinking.js.map +1 -1
- package/lib/browser/components/ChatToolRender.d.ts +1 -1
- package/lib/browser/components/ChatToolRender.d.ts.map +1 -1
- package/lib/browser/components/ChatToolRender.js +15 -18
- package/lib/browser/components/ChatToolRender.js.map +1 -1
- package/lib/browser/components/chat-history.css +139 -0
- package/lib/browser/components/components.module.less +2 -2
- package/lib/browser/components/utils.d.ts +2 -2
- package/lib/browser/context/llm-context.service.d.ts +1 -0
- package/lib/browser/context/llm-context.service.d.ts.map +1 -1
- package/lib/browser/context/llm-context.service.js +24 -18
- package/lib/browser/context/llm-context.service.js.map +1 -1
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +5 -13
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/layout/layout.module.less +1 -1
- package/lib/browser/mcp/mcp-server.feature.registry.d.ts.map +1 -1
- package/lib/browser/mcp/mcp-server.feature.registry.js +2 -1
- package/lib/browser/mcp/mcp-server.feature.registry.js.map +1 -1
- package/lib/browser/mcp/tools/components/SearchResult.d.ts +11 -0
- package/lib/browser/mcp/tools/components/SearchResult.d.ts.map +1 -0
- package/lib/browser/mcp/tools/components/SearchResult.js +60 -0
- package/lib/browser/mcp/tools/components/SearchResult.js.map +1 -0
- package/lib/browser/mcp/tools/components/Terminal.d.ts +4 -0
- package/lib/browser/mcp/tools/components/Terminal.d.ts.map +1 -0
- package/lib/browser/mcp/tools/components/Terminal.js +64 -0
- package/lib/browser/mcp/tools/components/Terminal.js.map +1 -0
- package/lib/browser/mcp/tools/components/index.module.less +101 -0
- package/lib/browser/mcp/tools/{findFilesByNameSubstring.d.ts → fileSearch.d.ts} +3 -2
- package/lib/browser/mcp/tools/fileSearch.d.ts.map +1 -0
- package/lib/browser/mcp/tools/fileSearch.js +94 -0
- package/lib/browser/mcp/tools/fileSearch.js.map +1 -0
- package/lib/browser/mcp/tools/{getFileTextByPath.d.ts → grepSearch.d.ts} +4 -3
- package/lib/browser/mcp/tools/grepSearch.d.ts.map +1 -0
- package/lib/browser/mcp/tools/grepSearch.js +118 -0
- package/lib/browser/mcp/tools/grepSearch.js.map +1 -0
- package/lib/browser/mcp/tools/handlers/RunCommand.d.ts +43 -0
- package/lib/browser/mcp/tools/handlers/RunCommand.d.ts.map +1 -0
- package/lib/browser/mcp/tools/handlers/RunCommand.js +104 -0
- package/lib/browser/mcp/tools/handlers/RunCommand.js.map +1 -0
- package/lib/browser/mcp/tools/listDir.d.ts.map +1 -1
- package/lib/browser/mcp/tools/listDir.js +1 -0
- package/lib/browser/mcp/tools/listDir.js.map +1 -1
- package/lib/browser/mcp/tools/readFile.d.ts.map +1 -1
- package/lib/browser/mcp/tools/readFile.js +1 -0
- package/lib/browser/mcp/tools/readFile.js.map +1 -1
- package/lib/browser/mcp/tools/runTerminalCmd.d.ts +1 -6
- package/lib/browser/mcp/tools/runTerminalCmd.d.ts.map +1 -1
- package/lib/browser/mcp/tools/runTerminalCmd.js +9 -55
- package/lib/browser/mcp/tools/runTerminalCmd.js.map +1 -1
- package/lib/browser/model/msg-history-manager.d.ts +15 -0
- package/lib/browser/model/msg-history-manager.d.ts.map +1 -1
- package/lib/browser/model/msg-history-manager.js +28 -9
- package/lib/browser/model/msg-history-manager.js.map +1 -1
- package/lib/common/mcp-server-manager.d.ts +1 -1
- package/lib/common/mcp-server-manager.d.ts.map +1 -1
- package/lib/common/mcp-server-manager.js.map +1 -1
- package/lib/common/tool-invocation-registry.d.ts +2 -1
- package/lib/common/tool-invocation-registry.d.ts.map +1 -1
- package/lib/common/tool-invocation-registry.js.map +1 -1
- package/lib/node/base-language-model.d.ts.map +1 -1
- package/lib/node/base-language-model.js +1 -1
- package/lib/node/base-language-model.js.map +1 -1
- package/lib/node/mcp/sumi-mcp-server.d.ts +1 -1
- package/lib/node/mcp/sumi-mcp-server.d.ts.map +1 -1
- package/lib/node/mcp/sumi-mcp-server.js +5 -2
- package/lib/node/mcp/sumi-mcp-server.js.map +1 -1
- package/lib/node/mcp-server-manager-impl.d.ts +1 -1
- package/lib/node/mcp-server-manager-impl.d.ts.map +1 -1
- package/lib/node/mcp-server-manager-impl.js +4 -4
- package/lib/node/mcp-server-manager-impl.js.map +1 -1
- package/lib/node/mcp-server.d.ts +2 -2
- package/lib/node/mcp-server.d.ts.map +1 -1
- package/lib/node/mcp-server.js +2 -1
- package/lib/node/mcp-server.js.map +1 -1
- package/package.json +23 -22
- package/src/browser/ai-core.contribution.ts +13 -1
- package/src/browser/chat/chat-manager.service.ts +83 -7
- package/src/browser/chat/chat-model.ts +62 -12
- package/src/browser/chat/chat-proxy.service.ts +1 -1
- package/src/browser/chat/chat.internal.service.ts +23 -5
- package/src/browser/chat/chat.module.less +8 -42
- package/src/browser/chat/chat.view.tsx +143 -60
- package/src/browser/components/ChatContext/index.tsx +19 -3
- package/src/browser/components/ChatContext/style.module.less +12 -0
- package/src/browser/components/ChatHistory.tsx +292 -0
- package/src/browser/components/ChatReply.tsx +5 -1
- package/src/browser/components/ChatThinking.tsx +1 -1
- package/src/browser/components/ChatToolRender.tsx +13 -15
- package/src/browser/components/chat-history.css +139 -0
- package/src/browser/components/components.module.less +2 -2
- package/src/browser/context/llm-context.service.ts +30 -18
- package/src/browser/index.ts +5 -13
- package/src/browser/layout/layout.module.less +1 -1
- package/src/browser/mcp/mcp-server.feature.registry.ts +2 -1
- package/src/browser/mcp/tools/components/SearchResult.tsx +92 -0
- package/src/browser/mcp/tools/components/Terminal.tsx +97 -0
- package/src/browser/mcp/tools/components/index.module.less +101 -0
- package/src/browser/mcp/tools/fileSearch.ts +99 -0
- package/src/browser/mcp/tools/grepSearch.ts +121 -0
- package/src/browser/mcp/tools/handlers/RunCommand.ts +115 -0
- package/src/browser/mcp/tools/listDir.ts +1 -0
- package/src/browser/mcp/tools/readFile.ts +1 -0
- package/src/browser/mcp/tools/runTerminalCmd.ts +7 -68
- package/src/browser/model/msg-history-manager.ts +34 -1
- package/src/common/mcp-server-manager.ts +18 -13
- package/src/common/tool-invocation-registry.ts +122 -124
- package/src/node/base-language-model.ts +3 -2
- package/src/node/mcp/sumi-mcp-server.ts +5 -2
- package/src/node/mcp-server-manager-impl.ts +11 -4
- package/src/node/mcp-server.ts +3 -2
- package/lib/browser/mcp/tools/findFilesByNameSubstring.d.ts.map +0 -1
- package/lib/browser/mcp/tools/findFilesByNameSubstring.js +0 -91
- package/lib/browser/mcp/tools/findFilesByNameSubstring.js.map +0 -1
- package/lib/browser/mcp/tools/getCurrentFilePath.d.ts +0 -8
- package/lib/browser/mcp/tools/getCurrentFilePath.d.ts.map +0 -1
- package/lib/browser/mcp/tools/getCurrentFilePath.js +0 -48
- package/lib/browser/mcp/tools/getCurrentFilePath.js.map +0 -1
- package/lib/browser/mcp/tools/getFileTextByPath.d.ts.map +0 -1
- package/lib/browser/mcp/tools/getFileTextByPath.js +0 -96
- package/lib/browser/mcp/tools/getFileTextByPath.js.map +0 -1
- package/lib/browser/mcp/tools/getOpenEditorFileText.d.ts +0 -8
- package/lib/browser/mcp/tools/getOpenEditorFileText.d.ts.map +0 -1
- package/lib/browser/mcp/tools/getOpenEditorFileText.js +0 -49
- package/lib/browser/mcp/tools/getOpenEditorFileText.js.map +0 -1
- package/lib/browser/mcp/tools/getSelectedText.d.ts +0 -8
- package/lib/browser/mcp/tools/getSelectedText.d.ts.map +0 -1
- package/lib/browser/mcp/tools/getSelectedText.js +0 -56
- package/lib/browser/mcp/tools/getSelectedText.js.map +0 -1
- package/lib/browser/mcp/tools/replaceOpenEditorFile.d.ts +0 -8
- package/lib/browser/mcp/tools/replaceOpenEditorFile.d.ts.map +0 -1
- package/lib/browser/mcp/tools/replaceOpenEditorFile.js +0 -80
- package/lib/browser/mcp/tools/replaceOpenEditorFile.js.map +0 -1
- package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.d.ts +0 -8
- package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.d.ts.map +0 -1
- package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.js +0 -83
- package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.js.map +0 -1
- package/src/browser/mcp/tools/findFilesByNameSubstring.ts +0 -92
- package/src/browser/mcp/tools/getCurrentFilePath.ts +0 -48
- package/src/browser/mcp/tools/getFileTextByPath.ts +0 -96
- package/src/browser/mcp/tools/getOpenEditorFileText.ts +0 -49
- package/src/browser/mcp/tools/getSelectedText.ts +0 -56
- package/src/browser/mcp/tools/replaceOpenEditorFile.ts +0 -81
- package/src/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.ts +0 -90
|
@@ -80,9 +80,29 @@ export class ChatResponseModel extends Disposable {
|
|
|
80
80
|
return this.#onDidChange.event;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
constructor(
|
|
83
|
+
constructor(
|
|
84
|
+
requestId: string,
|
|
85
|
+
public readonly session: IChatModel,
|
|
86
|
+
public readonly agentId: string,
|
|
87
|
+
initParams?: {
|
|
88
|
+
isComplete: boolean;
|
|
89
|
+
isCanceled: boolean;
|
|
90
|
+
responseContents: IChatProgressResponseContent[];
|
|
91
|
+
responseText: string;
|
|
92
|
+
errorDetails: IChatResponseErrorDetails | undefined;
|
|
93
|
+
followups: IChatFollowup[] | undefined;
|
|
94
|
+
},
|
|
95
|
+
) {
|
|
84
96
|
super();
|
|
85
97
|
this.#requestId = requestId;
|
|
98
|
+
if (initParams) {
|
|
99
|
+
this.#responseContents = initParams.responseContents;
|
|
100
|
+
this.#responseText = initParams.responseText;
|
|
101
|
+
this.#isComplete = initParams.isComplete;
|
|
102
|
+
this.#isCanceled = initParams.isCanceled;
|
|
103
|
+
this.#errorDetails = initParams.errorDetails;
|
|
104
|
+
this.#followups = initParams.followups;
|
|
105
|
+
}
|
|
86
106
|
}
|
|
87
107
|
|
|
88
108
|
updateContent(progress: IChatProgress, quiet?: boolean): void {
|
|
@@ -215,6 +235,16 @@ export class ChatResponseModel extends Disposable {
|
|
|
215
235
|
this.#followups = followups;
|
|
216
236
|
this.#onDidChange.fire();
|
|
217
237
|
}
|
|
238
|
+
|
|
239
|
+
toJSON() {
|
|
240
|
+
return {
|
|
241
|
+
isCanceled: this.isCanceled,
|
|
242
|
+
responseContents: this.responseContents,
|
|
243
|
+
responseText: this.responseText,
|
|
244
|
+
errorDetails: this.errorDetails,
|
|
245
|
+
followups: this.followups,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
218
248
|
}
|
|
219
249
|
|
|
220
250
|
export class ChatRequestModel implements IChatRequestModel {
|
|
@@ -231,19 +261,29 @@ export class ChatRequestModel implements IChatRequestModel {
|
|
|
231
261
|
) {
|
|
232
262
|
this.#requestId = requestId;
|
|
233
263
|
}
|
|
264
|
+
|
|
265
|
+
toJSON() {
|
|
266
|
+
return {
|
|
267
|
+
requestId: this.requestId,
|
|
268
|
+
message: this.message,
|
|
269
|
+
response: this.response,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
234
272
|
}
|
|
235
273
|
|
|
236
|
-
@Injectable({ multiple: true })
|
|
237
274
|
export class ChatModel extends Disposable implements IChatModel {
|
|
238
275
|
private static requestIdPool = 0;
|
|
239
276
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
277
|
+
constructor(initParams?: { sessionId?: string; history?: MsgHistoryManager; requests?: ChatRequestModel[] }) {
|
|
278
|
+
super();
|
|
279
|
+
this.#sessionId = initParams?.sessionId ?? uuid();
|
|
280
|
+
this.history = initParams?.history ?? new MsgHistoryManager();
|
|
281
|
+
if (initParams?.requests) {
|
|
282
|
+
this.#requests = new Map(initParams.requests.map((r) => [r.requestId, r]));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
245
285
|
|
|
246
|
-
#sessionId: string
|
|
286
|
+
#sessionId: string;
|
|
247
287
|
get sessionId(): string {
|
|
248
288
|
return this.#sessionId;
|
|
249
289
|
}
|
|
@@ -253,11 +293,12 @@ export class ChatModel extends Disposable implements IChatModel {
|
|
|
253
293
|
return Array.from(this.#requests.values());
|
|
254
294
|
}
|
|
255
295
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
return this.injector.get(MsgHistoryManager, []);
|
|
296
|
+
restoreRequests(requests: ChatRequestModel[]): void {
|
|
297
|
+
this.#requests = new Map(requests.map((r) => [r.requestId, r]));
|
|
259
298
|
}
|
|
260
299
|
|
|
300
|
+
readonly history: MsgHistoryManager;
|
|
301
|
+
|
|
261
302
|
addRequest(message: IChatRequestMessage): ChatRequestModel {
|
|
262
303
|
const requestId = `${this.sessionId}_request_${ChatModel.requestIdPool++}`;
|
|
263
304
|
const response = new ChatResponseModel(requestId, this, message.agentId);
|
|
@@ -279,7 +320,8 @@ export class ChatModel extends Disposable implements IChatModel {
|
|
|
279
320
|
if (basicKind.includes(kind)) {
|
|
280
321
|
request.response.updateContent(progress, quiet);
|
|
281
322
|
} else {
|
|
282
|
-
|
|
323
|
+
// eslint-disable-next-line no-console
|
|
324
|
+
console.error(`Couldn't handle progress: ${JSON.stringify(progress)}`);
|
|
283
325
|
}
|
|
284
326
|
}
|
|
285
327
|
|
|
@@ -291,6 +333,14 @@ export class ChatModel extends Disposable implements IChatModel {
|
|
|
291
333
|
super.dispose();
|
|
292
334
|
this.#requests.forEach((r) => r.response.dispose());
|
|
293
335
|
}
|
|
336
|
+
|
|
337
|
+
toJSON() {
|
|
338
|
+
return {
|
|
339
|
+
sessionId: this.sessionId,
|
|
340
|
+
history: this.history,
|
|
341
|
+
requests: this.requests,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
294
344
|
}
|
|
295
345
|
|
|
296
346
|
@Injectable({ multiple: true })
|
|
@@ -39,7 +39,7 @@ import { ChatFeatureRegistry } from './chat.feature.registry';
|
|
|
39
39
|
@Injectable()
|
|
40
40
|
export class ChatProxyService extends Disposable {
|
|
41
41
|
// 避免和插件注册的 agent id 冲突
|
|
42
|
-
static readonly AGENT_ID = '
|
|
42
|
+
static readonly AGENT_ID = 'Default_Chat_Agent';
|
|
43
43
|
|
|
44
44
|
@Autowired(IChatAgentService)
|
|
45
45
|
private readonly chatAgentService: IChatAgentService;
|
|
@@ -43,9 +43,15 @@ export class ChatInternalService extends Disposable {
|
|
|
43
43
|
return this.#sessionModel;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
init() {
|
|
47
|
+
this.chatManagerService.onStorageInit(() => {
|
|
48
|
+
const sessions = this.chatManagerService.getSessions();
|
|
49
|
+
if (sessions.length > 0) {
|
|
50
|
+
this.activateSession(sessions[sessions.length - 1].sessionId);
|
|
51
|
+
} else {
|
|
52
|
+
this.createSessionModel();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
public setLatestRequestId(id: string): void {
|
|
@@ -70,12 +76,24 @@ export class ChatInternalService extends Disposable {
|
|
|
70
76
|
this._onCancelRequest.fire();
|
|
71
77
|
}
|
|
72
78
|
|
|
73
|
-
|
|
74
|
-
this.chatManagerService.clearSession(this.#sessionModel.sessionId);
|
|
79
|
+
createSessionModel() {
|
|
75
80
|
this.#sessionModel = this.chatManagerService.startSession();
|
|
76
81
|
this._onChangeSession.fire(this.#sessionModel.sessionId);
|
|
77
82
|
}
|
|
78
83
|
|
|
84
|
+
clearSessionModel(sessionId?: string) {
|
|
85
|
+
sessionId = sessionId || this.#sessionModel.sessionId;
|
|
86
|
+
this.chatManagerService.clearSession(sessionId);
|
|
87
|
+
if (sessionId === this.#sessionModel.sessionId) {
|
|
88
|
+
this.#sessionModel = this.chatManagerService.startSession();
|
|
89
|
+
}
|
|
90
|
+
this._onChangeSession.fire(this.#sessionModel.sessionId);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getSessions() {
|
|
94
|
+
return this.chatManagerService.getSessions();
|
|
95
|
+
}
|
|
96
|
+
|
|
79
97
|
activateSession(sessionId: string) {
|
|
80
98
|
const targetSession = this.chatManagerService.getSession(sessionId);
|
|
81
99
|
if (!targetSession) {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
height: 100%;
|
|
5
5
|
border-radius: 12px;
|
|
6
6
|
overflow: hidden;
|
|
7
|
-
font-size:
|
|
7
|
+
font-size: 12px;
|
|
8
8
|
user-select: text;
|
|
9
9
|
|
|
10
10
|
border-top-left-radius: 12px;
|
|
@@ -75,53 +75,14 @@
|
|
|
75
75
|
|
|
76
76
|
.header_container {
|
|
77
77
|
height: 36px;
|
|
78
|
-
|
|
79
|
-
justify-content: space-between;
|
|
80
|
-
align-items: center;
|
|
81
|
-
padding: 12px 0 12px 16px;
|
|
78
|
+
padding: 8px 8px 8px 16px;
|
|
82
79
|
box-sizing: border-box;
|
|
83
80
|
background-color: var(--editorGroupHeader-tabsBackground);
|
|
84
81
|
user-select: none;
|
|
85
82
|
|
|
86
|
-
.
|
|
83
|
+
.header {
|
|
87
84
|
display: flex;
|
|
88
85
|
align-items: center;
|
|
89
|
-
height: 16px;
|
|
90
|
-
color: var(--design-title-foreground);
|
|
91
|
-
font-size: 12px;
|
|
92
|
-
|
|
93
|
-
.ai_avatar_icon {
|
|
94
|
-
width: 18px;
|
|
95
|
-
height: 18px;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
.avatar_icon_normal {
|
|
99
|
-
width: 18px;
|
|
100
|
-
height: 18px;
|
|
101
|
-
font-size: 14px !important;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
& > * {
|
|
105
|
-
margin-right: 8px;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.right {
|
|
110
|
-
display: flex;
|
|
111
|
-
align-items: center;
|
|
112
|
-
padding-right: 10px;
|
|
113
|
-
.popover_icon {
|
|
114
|
-
margin-left: 2px;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
.action_btn {
|
|
118
|
-
display: flex;
|
|
119
|
-
align-items: center;
|
|
120
|
-
justify-content: center;
|
|
121
|
-
width: 22px;
|
|
122
|
-
height: 22px;
|
|
123
|
-
padding: 0;
|
|
124
|
-
}
|
|
125
86
|
}
|
|
126
87
|
}
|
|
127
88
|
|
|
@@ -317,3 +278,8 @@
|
|
|
317
278
|
}
|
|
318
279
|
}
|
|
319
280
|
}
|
|
281
|
+
|
|
282
|
+
.chat_history {
|
|
283
|
+
width: calc(100% - 60px);
|
|
284
|
+
color: var(--design-text-foreground);
|
|
285
|
+
}
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
ChatRenderRegistryToken,
|
|
22
22
|
ChatServiceToken,
|
|
23
23
|
Disposable,
|
|
24
|
+
DisposableCollection,
|
|
24
25
|
IAIReporter,
|
|
25
26
|
IChatComponent,
|
|
26
27
|
IChatContent,
|
|
@@ -43,6 +44,7 @@ import { LLMContextService, LLMContextServiceToken } from '../../common/llm-cont
|
|
|
43
44
|
import { ChatAgentPromptProvider } from '../../common/prompts/context-prompt-provider';
|
|
44
45
|
import { ChatContext } from '../components/ChatContext';
|
|
45
46
|
import { CodeBlockWrapperInput } from '../components/ChatEditor';
|
|
47
|
+
import ChatHistory, { IChatHistoryItem } from '../components/ChatHistory';
|
|
46
48
|
import { ChatInput } from '../components/ChatInput';
|
|
47
49
|
import { ChatMarkdown } from '../components/ChatMarkdown';
|
|
48
50
|
import { ChatNotify, ChatReply } from '../components/ChatReply';
|
|
@@ -67,6 +69,8 @@ interface TDispatchAction {
|
|
|
67
69
|
payload?: MessageData[];
|
|
68
70
|
}
|
|
69
71
|
|
|
72
|
+
const MAX_TITLE_LENGTH = 100;
|
|
73
|
+
|
|
70
74
|
export const AIChatView = () => {
|
|
71
75
|
const aiChatService = useInjectable<ChatInternalService>(IChatInternalService);
|
|
72
76
|
const chatApiService = useInjectable<ChatService>(ChatServiceToken);
|
|
@@ -78,12 +82,9 @@ export const AIChatView = () => {
|
|
|
78
82
|
const promptProvider = useInjectable<ChatAgentPromptProvider>(ChatAgentPromptProvider);
|
|
79
83
|
|
|
80
84
|
const layoutService = useInjectable<IMainLayoutService>(IMainLayoutService);
|
|
81
|
-
const mcpServerProxyService = useInjectable<MCPServerProxyService>(TokenMCPServerProxyService);
|
|
82
85
|
const msgHistoryManager = aiChatService.sessionModel.history;
|
|
83
86
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
|
84
87
|
const chatInputRef = React.useRef<{ setInputValue: (v: string) => void } | null>(null);
|
|
85
|
-
const dialogService = useInjectable<IDialogService>(IDialogService);
|
|
86
|
-
const aiNativeConfigService = useInjectable<AINativeConfigService>(AINativeConfigService);
|
|
87
88
|
|
|
88
89
|
const [shortcutCommands, setShortcutCommands] = React.useState<ChatSlashCommandItemModel[]>([]);
|
|
89
90
|
|
|
@@ -105,7 +106,6 @@ export const AIChatView = () => {
|
|
|
105
106
|
const [defaultAgentId, setDefaultAgentId] = React.useState<string>('');
|
|
106
107
|
const [command, setCommand] = React.useState('');
|
|
107
108
|
const [theme, setTheme] = React.useState<string | null>(null);
|
|
108
|
-
const [mcpToolsCount, setMcpToolsCount] = React.useState<number>(0);
|
|
109
109
|
|
|
110
110
|
React.useEffect(() => {
|
|
111
111
|
const featureSlashCommands = chatFeatureRegistry.getAllShortcutSlashCommand();
|
|
@@ -448,7 +448,9 @@ export const AIChatView = () => {
|
|
|
448
448
|
setLoading(false);
|
|
449
449
|
}}
|
|
450
450
|
onRegenerate={() => {
|
|
451
|
-
|
|
451
|
+
if (request) {
|
|
452
|
+
aiChatService.sendRequest(request, true);
|
|
453
|
+
}
|
|
452
454
|
}}
|
|
453
455
|
msgId={msgId}
|
|
454
456
|
/>
|
|
@@ -611,7 +613,8 @@ export const AIChatView = () => {
|
|
|
611
613
|
});
|
|
612
614
|
} else if (msg.role === ChatMessageRole.Assistant && msg.requestId) {
|
|
613
615
|
const request = aiChatService.sessionModel.getRequest(msg.requestId)!;
|
|
614
|
-
|
|
616
|
+
// 从storage恢复时,request为undefined
|
|
617
|
+
if (request && !request.response.isComplete) {
|
|
615
618
|
setLoading(true);
|
|
616
619
|
}
|
|
617
620
|
await renderReply({
|
|
@@ -621,7 +624,7 @@ export const AIChatView = () => {
|
|
|
621
624
|
agentId: msg.agentId,
|
|
622
625
|
command: msg.agentCommand,
|
|
623
626
|
startTime: msg.replyStartTime!,
|
|
624
|
-
request
|
|
627
|
+
request,
|
|
625
628
|
});
|
|
626
629
|
} else if (msg.role === ChatMessageRole.Assistant && msg.content) {
|
|
627
630
|
await renderSimpleMarkdownReply({
|
|
@@ -654,25 +657,6 @@ export const AIChatView = () => {
|
|
|
654
657
|
};
|
|
655
658
|
}, [aiChatService.sessionModel]);
|
|
656
659
|
|
|
657
|
-
useEventEffect(
|
|
658
|
-
mcpServerProxyService.onChangeMCPServers,
|
|
659
|
-
() => {
|
|
660
|
-
mcpServerProxyService.getAllMCPTools().then((tools) => {
|
|
661
|
-
setMcpToolsCount(tools.length);
|
|
662
|
-
});
|
|
663
|
-
},
|
|
664
|
-
[mcpServerProxyService],
|
|
665
|
-
);
|
|
666
|
-
|
|
667
|
-
const handleShowMCPTools = React.useCallback(async () => {
|
|
668
|
-
const tools = await mcpServerProxyService.getAllMCPTools();
|
|
669
|
-
dialogService.open({
|
|
670
|
-
message: <MCPToolsDialog tools={tools} />,
|
|
671
|
-
type: MessageType.Empty,
|
|
672
|
-
buttons: ['关闭'],
|
|
673
|
-
});
|
|
674
|
-
}, [mcpServerProxyService, dialogService]);
|
|
675
|
-
|
|
676
660
|
return (
|
|
677
661
|
<div id={styles.ai_chat_view}>
|
|
678
662
|
<div className={styles.header_container}>
|
|
@@ -705,13 +689,6 @@ export const AIChatView = () => {
|
|
|
705
689
|
</Popover>
|
|
706
690
|
))}
|
|
707
691
|
</div>
|
|
708
|
-
<div className={styles.header_operate_right}>
|
|
709
|
-
{aiNativeConfigService.capabilities.supportsMCP && (
|
|
710
|
-
<div className={styles.tag} onClick={handleShowMCPTools}>
|
|
711
|
-
{`MCP Tools: ${mcpToolsCount}`}
|
|
712
|
-
</div>
|
|
713
|
-
)}
|
|
714
|
-
</div>
|
|
715
692
|
</div>
|
|
716
693
|
<ChatInputWrapperRender
|
|
717
694
|
onSend={(value, agentId, command) =>
|
|
@@ -750,44 +727,150 @@ export function DefaultChatViewHeader({
|
|
|
750
727
|
handleClear: () => any;
|
|
751
728
|
handleCloseChatView: () => any;
|
|
752
729
|
}) {
|
|
753
|
-
const
|
|
730
|
+
const dialogService = useInjectable<IDialogService>(IDialogService);
|
|
731
|
+
const aiNativeConfigService = useInjectable<AINativeConfigService>(AINativeConfigService);
|
|
732
|
+
const mcpServerProxyService = useInjectable<MCPServerProxyService>(TokenMCPServerProxyService);
|
|
733
|
+
const aiChatService = useInjectable<ChatInternalService>(IChatInternalService);
|
|
734
|
+
const [historyList, setHistoryList] = React.useState<IChatHistoryItem[]>([]);
|
|
735
|
+
const [currentTitle, setCurrentTitle] = React.useState<string>('');
|
|
736
|
+
const handleNewChat = React.useCallback(() => {
|
|
737
|
+
if (aiChatService.sessionModel.history.getMessages().length > 0) {
|
|
738
|
+
aiChatService.createSessionModel();
|
|
739
|
+
}
|
|
740
|
+
}, [aiChatService]);
|
|
741
|
+
const handleHistoryItemSelect = React.useCallback(
|
|
742
|
+
(item: IChatHistoryItem) => {
|
|
743
|
+
aiChatService.activateSession(item.id);
|
|
744
|
+
},
|
|
745
|
+
[aiChatService],
|
|
746
|
+
);
|
|
747
|
+
const handleHistoryItemDelete = React.useCallback(
|
|
748
|
+
(item: IChatHistoryItem) => {
|
|
749
|
+
aiChatService.clearSessionModel(item.id);
|
|
750
|
+
},
|
|
751
|
+
[aiChatService],
|
|
752
|
+
);
|
|
753
|
+
|
|
754
|
+
const handleShowMCPTools = React.useCallback(async () => {
|
|
755
|
+
const tools = await mcpServerProxyService.getAllMCPTools();
|
|
756
|
+
dialogService.open({
|
|
757
|
+
message: <MCPToolsDialog tools={tools} />,
|
|
758
|
+
type: MessageType.Empty,
|
|
759
|
+
buttons: ['关闭'],
|
|
760
|
+
});
|
|
761
|
+
}, [mcpServerProxyService, dialogService]);
|
|
762
|
+
|
|
763
|
+
React.useEffect(() => {
|
|
764
|
+
const getHistoryList = () => {
|
|
765
|
+
const currentMessages = aiChatService.sessionModel.history.getMessages();
|
|
766
|
+
setCurrentTitle(
|
|
767
|
+
currentMessages.length > 0
|
|
768
|
+
? currentMessages[currentMessages.length - 1].content.slice(0, MAX_TITLE_LENGTH)
|
|
769
|
+
: '',
|
|
770
|
+
);
|
|
771
|
+
setHistoryList(
|
|
772
|
+
aiChatService.getSessions().map((session) => {
|
|
773
|
+
const history = session.history;
|
|
774
|
+
const messages = history.getMessages();
|
|
775
|
+
const title = messages.length > 0 ? messages[0].content.slice(0, MAX_TITLE_LENGTH) : '';
|
|
776
|
+
const updatedAt = messages.length > 0 ? messages[messages.length - 1].replyStartTime || 0 : 0;
|
|
777
|
+
// const loading = session.requests[session.requests.length - 1]?.response.isComplete;
|
|
778
|
+
return {
|
|
779
|
+
id: session.sessionId,
|
|
780
|
+
title,
|
|
781
|
+
updatedAt,
|
|
782
|
+
// TODO: 后续支持
|
|
783
|
+
loading: false,
|
|
784
|
+
};
|
|
785
|
+
}),
|
|
786
|
+
);
|
|
787
|
+
};
|
|
788
|
+
getHistoryList();
|
|
789
|
+
const toDispose = new DisposableCollection();
|
|
790
|
+
const sessionListenIds = new Set<string>();
|
|
791
|
+
toDispose.push(
|
|
792
|
+
aiChatService.onChangeSession((sessionId) => {
|
|
793
|
+
getHistoryList();
|
|
794
|
+
if (sessionListenIds.has(sessionId)) {
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
sessionListenIds.add(sessionId);
|
|
798
|
+
toDispose.push(
|
|
799
|
+
aiChatService.sessionModel.history.onMessageChange(() => {
|
|
800
|
+
getHistoryList();
|
|
801
|
+
}),
|
|
802
|
+
);
|
|
803
|
+
}),
|
|
804
|
+
);
|
|
805
|
+
toDispose.push(
|
|
806
|
+
aiChatService.sessionModel.history.onMessageChange(() => {
|
|
807
|
+
getHistoryList();
|
|
808
|
+
}),
|
|
809
|
+
);
|
|
810
|
+
return () => {
|
|
811
|
+
toDispose.dispose();
|
|
812
|
+
};
|
|
813
|
+
}, [aiChatService]);
|
|
754
814
|
|
|
755
815
|
return (
|
|
756
|
-
|
|
757
|
-
<
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
816
|
+
<div className={styles.header}>
|
|
817
|
+
<ChatHistory
|
|
818
|
+
className={styles.chat_history}
|
|
819
|
+
// 取对话名称
|
|
820
|
+
currentId={aiChatService.sessionModel.sessionId}
|
|
821
|
+
title={currentTitle || localize('aiNative.chat.ai.assistant.name')}
|
|
822
|
+
historyList={historyList}
|
|
823
|
+
onNewChat={handleNewChat}
|
|
824
|
+
onHistoryItemSelect={handleHistoryItemSelect}
|
|
825
|
+
onHistoryItemDelete={handleHistoryItemDelete}
|
|
826
|
+
onHistoryItemChange={() => {}}
|
|
827
|
+
/>
|
|
828
|
+
<Popover
|
|
829
|
+
overlayClassName={styles.popover_icon}
|
|
830
|
+
id={'ai-chat-header-clear'}
|
|
831
|
+
title={localize('aiNative.operate.clear.title')}
|
|
832
|
+
>
|
|
833
|
+
<EnhanceIcon
|
|
834
|
+
wrapperClassName={styles.action_btn}
|
|
835
|
+
className={getIcon('clear')}
|
|
836
|
+
onClick={handleClear}
|
|
837
|
+
tabIndex={0}
|
|
838
|
+
role='button'
|
|
839
|
+
ariaLabel={localize('aiNative.operate.clear.title')}
|
|
840
|
+
/>
|
|
841
|
+
</Popover>
|
|
842
|
+
{aiNativeConfigService.capabilities.supportsMCP && (
|
|
761
843
|
<Popover
|
|
762
844
|
overlayClassName={styles.popover_icon}
|
|
763
|
-
id={'ai-chat-header-
|
|
764
|
-
title={localize('aiNative.operate.clear.title')}
|
|
765
|
-
>
|
|
766
|
-
<EnhanceIcon
|
|
767
|
-
wrapperClassName={styles.action_btn}
|
|
768
|
-
className={getIcon('clear')}
|
|
769
|
-
onClick={handleClear}
|
|
770
|
-
tabIndex={0}
|
|
771
|
-
role='button'
|
|
772
|
-
ariaLabel={localize('aiNative.operate.clear.title')}
|
|
773
|
-
/>
|
|
774
|
-
</Popover>
|
|
775
|
-
<Popover
|
|
776
|
-
overlayClassName={styles.popover_icon}
|
|
777
|
-
id={'ai-chat-header-close'}
|
|
845
|
+
id={'ai-chat-header-tools'}
|
|
778
846
|
position={PopoverPosition.left}
|
|
779
|
-
title={localize('aiNative.operate.
|
|
847
|
+
title={localize('aiNative.operate.tools.title')}
|
|
780
848
|
>
|
|
781
849
|
<EnhanceIcon
|
|
782
850
|
wrapperClassName={styles.action_btn}
|
|
783
|
-
className={getIcon('
|
|
784
|
-
onClick={
|
|
851
|
+
className={getIcon('menubar-tool')}
|
|
852
|
+
onClick={handleShowMCPTools}
|
|
785
853
|
tabIndex={0}
|
|
786
854
|
role='button'
|
|
787
|
-
ariaLabel={localize('aiNative.operate.
|
|
855
|
+
ariaLabel={localize('aiNative.operate.tools.title')}
|
|
788
856
|
/>
|
|
789
857
|
</Popover>
|
|
790
|
-
|
|
791
|
-
|
|
858
|
+
)}
|
|
859
|
+
<Popover
|
|
860
|
+
overlayClassName={styles.popover_icon}
|
|
861
|
+
id={'ai-chat-header-close'}
|
|
862
|
+
position={PopoverPosition.left}
|
|
863
|
+
title={localize('aiNative.operate.close.title')}
|
|
864
|
+
>
|
|
865
|
+
<EnhanceIcon
|
|
866
|
+
wrapperClassName={styles.action_btn}
|
|
867
|
+
className={getIcon('window-close')}
|
|
868
|
+
onClick={handleCloseChatView}
|
|
869
|
+
tabIndex={0}
|
|
870
|
+
role='button'
|
|
871
|
+
ariaLabel={localize('aiNative.operate.close.title')}
|
|
872
|
+
/>
|
|
873
|
+
</Popover>
|
|
874
|
+
</div>
|
|
792
875
|
);
|
|
793
876
|
}
|
|
@@ -18,6 +18,11 @@ import { FileContext, LLMContextService, LLMContextServiceToken } from '../../..
|
|
|
18
18
|
import { ContextSelector } from './ContextSelector';
|
|
19
19
|
import styles from './style.module.less';
|
|
20
20
|
|
|
21
|
+
const getCollapsedHeight = () => ({ height: 0, opacity: 0 });
|
|
22
|
+
const getRealHeight = (node) => ({ height: node.scrollHeight, opacity: 1 });
|
|
23
|
+
const getCurrentHeight = (node) => ({ height: node.offsetHeight });
|
|
24
|
+
const skipOpacityTransition = (_, event) => (event as TransitionEvent).propertyName === 'height';
|
|
25
|
+
|
|
21
26
|
export const ChatContext = memo(() => {
|
|
22
27
|
const [addedFiles, updateAddedFiles] = useState<FileContext[]>([]);
|
|
23
28
|
const [contextOverlay, toggleContextOverlay] = useState(false);
|
|
@@ -76,13 +81,24 @@ export const ChatContext = memo(() => {
|
|
|
76
81
|
<Collapse
|
|
77
82
|
// @ts-ignore
|
|
78
83
|
expandIcon={({ isActive }) => (isActive ? <Icon icon='down' /> : <Icon icon='right' />)}
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
openMotion={{
|
|
85
|
+
motionName: 'rc-collapse-motion',
|
|
86
|
+
onEnterStart: getCollapsedHeight,
|
|
87
|
+
onEnterActive: getRealHeight,
|
|
88
|
+
onLeaveStart: getCurrentHeight,
|
|
89
|
+
onLeaveActive: getCollapsedHeight,
|
|
90
|
+
onEnterEnd: skipOpacityTransition,
|
|
91
|
+
onLeaveEnd: skipOpacityTransition,
|
|
92
|
+
motionDeadline: 100,
|
|
93
|
+
leavedClassName: styles.collapse_hide,
|
|
94
|
+
}}
|
|
81
95
|
>
|
|
82
96
|
<Panel
|
|
83
97
|
header={
|
|
84
98
|
<div className={styles.context_header}>
|
|
85
|
-
<h3 className={styles.chat_context_title}>
|
|
99
|
+
<h3 className={styles.chat_context_title}>
|
|
100
|
+
Context {addedFiles.length > 0 ? ` (${addedFiles.length} files)` : ''}
|
|
101
|
+
</h3>
|
|
86
102
|
<Popover
|
|
87
103
|
overlayClassName={styles.popover_icon}
|
|
88
104
|
id={'ai-context-header-clear'}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
padding: 10px;
|
|
6
6
|
border-radius: 4px;
|
|
7
7
|
border: 1px solid var(--design-borderColor);
|
|
8
|
+
user-select: none;
|
|
8
9
|
|
|
9
10
|
:global(.rc-collapse) {
|
|
10
11
|
background-color: transparent !important;
|
|
@@ -19,6 +20,16 @@
|
|
|
19
20
|
|
|
20
21
|
:global(.rc-collapse-expand-icon) {
|
|
21
22
|
line-height: 1;
|
|
23
|
+
|
|
24
|
+
:global(.kt-icon) {
|
|
25
|
+
display: flex;
|
|
26
|
+
justify-content: center;
|
|
27
|
+
align-items: center;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.collapse_hide {
|
|
32
|
+
display: none;
|
|
22
33
|
}
|
|
23
34
|
|
|
24
35
|
:global(.rc-collapse-header) {
|
|
@@ -63,6 +74,7 @@
|
|
|
63
74
|
.context_list {
|
|
64
75
|
font-size: 12px;
|
|
65
76
|
overflow-y: auto;
|
|
77
|
+
user-select: none;
|
|
66
78
|
|
|
67
79
|
.list_desc {
|
|
68
80
|
margin: 0px 10px;
|