@opensumi/ide-ai-native 3.8.3-next-1741767755.0 → 3.8.3-next-1741769014.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.
Files changed (74) hide show
  1. package/lib/browser/chat/chat-agent.service.d.ts +1 -1
  2. package/lib/browser/chat/chat-agent.service.d.ts.map +1 -1
  3. package/lib/browser/chat/chat-agent.service.js +7 -7
  4. package/lib/browser/chat/chat-agent.service.js.map +1 -1
  5. package/lib/browser/chat/chat.view.d.ts.map +1 -1
  6. package/lib/browser/chat/chat.view.js +18 -52
  7. package/lib/browser/chat/chat.view.js.map +1 -1
  8. package/lib/browser/components/{chat-context/context-selector.d.ts → ChatContext/ContextSelector.d.ts} +1 -1
  9. package/lib/browser/components/ChatContext/ContextSelector.d.ts.map +1 -0
  10. package/lib/browser/components/{chat-context/context-selector.js → ChatContext/ContextSelector.js} +1 -1
  11. package/lib/browser/components/ChatContext/ContextSelector.js.map +1 -0
  12. package/lib/browser/components/ChatContext/index.d.ts.map +1 -0
  13. package/lib/browser/components/{chat-context → ChatContext}/index.js +2 -2
  14. package/lib/browser/components/ChatContext/index.js.map +1 -0
  15. package/lib/browser/components/ChatEditor.d.ts +2 -11
  16. package/lib/browser/components/ChatEditor.d.ts.map +1 -1
  17. package/lib/browser/components/ChatEditor.js +6 -66
  18. package/lib/browser/components/ChatEditor.js.map +1 -1
  19. package/lib/browser/components/components.module.less +0 -25
  20. package/lib/browser/context/llm-context.service.d.ts +2 -10
  21. package/lib/browser/context/llm-context.service.d.ts.map +1 -1
  22. package/lib/browser/context/llm-context.service.js +2 -71
  23. package/lib/browser/context/llm-context.service.js.map +1 -1
  24. package/lib/common/llm-context.d.ts +1 -15
  25. package/lib/common/llm-context.d.ts.map +1 -1
  26. package/lib/common/llm-context.js.map +1 -1
  27. package/lib/common/prompts/context-prompt-provider.d.ts +2 -12
  28. package/lib/common/prompts/context-prompt-provider.d.ts.map +1 -1
  29. package/lib/common/prompts/context-prompt-provider.js +30 -94
  30. package/lib/common/prompts/context-prompt-provider.js.map +1 -1
  31. package/package.json +23 -23
  32. package/src/browser/chat/chat-agent.service.ts +7 -7
  33. package/src/browser/chat/chat.view.tsx +21 -72
  34. package/src/browser/components/{chat-context → ChatContext}/index.tsx +1 -1
  35. package/src/browser/components/ChatEditor.tsx +9 -126
  36. package/src/browser/components/components.module.less +0 -25
  37. package/src/browser/context/llm-context.service.ts +3 -81
  38. package/src/common/llm-context.ts +1 -16
  39. package/src/common/prompts/context-prompt-provider.ts +36 -126
  40. package/lib/browser/components/ChatMentionInput.d.ts +0 -25
  41. package/lib/browser/components/ChatMentionInput.d.ts.map +0 -1
  42. package/lib/browser/components/ChatMentionInput.js +0 -221
  43. package/lib/browser/components/ChatMentionInput.js.map +0 -1
  44. package/lib/browser/components/chat-context/context-selector.d.ts.map +0 -1
  45. package/lib/browser/components/chat-context/context-selector.js.map +0 -1
  46. package/lib/browser/components/chat-context/index.d.ts.map +0 -1
  47. package/lib/browser/components/chat-context/index.js.map +0 -1
  48. package/lib/browser/components/mention-input/mention-input.d.ts +0 -5
  49. package/lib/browser/components/mention-input/mention-input.d.ts.map +0 -1
  50. package/lib/browser/components/mention-input/mention-input.js +0 -753
  51. package/lib/browser/components/mention-input/mention-input.js.map +0 -1
  52. package/lib/browser/components/mention-input/mention-input.module.less +0 -328
  53. package/lib/browser/components/mention-input/mention-item.d.ts +0 -10
  54. package/lib/browser/components/mention-input/mention-item.d.ts.map +0 -1
  55. package/lib/browser/components/mention-input/mention-item.js +0 -16
  56. package/lib/browser/components/mention-input/mention-item.js.map +0 -1
  57. package/lib/browser/components/mention-input/mention-panel.d.ts +0 -15
  58. package/lib/browser/components/mention-input/mention-panel.d.ts.map +0 -1
  59. package/lib/browser/components/mention-input/mention-panel.js +0 -49
  60. package/lib/browser/components/mention-input/mention-panel.js.map +0 -1
  61. package/lib/browser/components/mention-input/types.d.ts +0 -76
  62. package/lib/browser/components/mention-input/types.d.ts.map +0 -1
  63. package/lib/browser/components/mention-input/types.js +0 -16
  64. package/lib/browser/components/mention-input/types.js.map +0 -1
  65. package/src/browser/components/ChatMentionInput.tsx +0 -268
  66. package/src/browser/components/mention-input/mention-input.module.less +0 -328
  67. package/src/browser/components/mention-input/mention-input.tsx +0 -943
  68. package/src/browser/components/mention-input/mention-item.tsx +0 -24
  69. package/src/browser/components/mention-input/mention-panel.tsx +0 -89
  70. package/src/browser/components/mention-input/types.ts +0 -82
  71. /package/lib/browser/components/{chat-context → ChatContext}/index.d.ts +0 -0
  72. /package/lib/browser/components/{chat-context → ChatContext}/style.module.less +0 -0
  73. /package/src/browser/components/{chat-context/context-selector.tsx → ChatContext/ContextSelector.tsx} +0 -0
  74. /package/src/browser/components/{chat-context → ChatContext}/style.module.less +0 -0
@@ -59,7 +59,7 @@ export class ChatAgentService extends Disposable implements IChatAgentService {
59
59
  private readonly aiReporter: IAIReporter;
60
60
 
61
61
  @Autowired(LLMContextServiceToken)
62
- protected readonly llmContextService: LLMContextService;
62
+ protected readonly contextService: LLMContextService;
63
63
 
64
64
  @Autowired(ChatAgentPromptProvider)
65
65
  protected readonly promptProvider: ChatAgentPromptProvider;
@@ -74,7 +74,7 @@ export class ChatAgentService extends Disposable implements IChatAgentService {
74
74
  super();
75
75
  this.addDispose(this._onDidChangeAgents);
76
76
  this.addDispose(
77
- this.llmContextService.onDidContextFilesChangeEvent((event) => {
77
+ this.contextService.onDidContextFilesChangeEvent((event) => {
78
78
  if (event.version !== this.contextVersion) {
79
79
  this.contextVersion = event.version;
80
80
  this.shouldUpdateContext = true;
@@ -152,9 +152,9 @@ export class ChatAgentService extends Disposable implements IChatAgentService {
152
152
  if (!this.initialUserMessageMap.has(request.sessionId)) {
153
153
  this.initialUserMessageMap.set(request.sessionId, request.message);
154
154
  const rawMessage = request.message;
155
- request.message = await this.provideContextMessage(rawMessage, request.sessionId);
155
+ request.message = this.provideContextMessage(rawMessage, request.sessionId);
156
156
  } else if (this.shouldUpdateContext || request.regenerate || history.length === 0) {
157
- request.message = await this.provideContextMessage(request.message, request.sessionId);
157
+ request.message = this.provideContextMessage(request.message, request.sessionId);
158
158
  this.shouldUpdateContext = false;
159
159
  }
160
160
 
@@ -162,9 +162,9 @@ export class ChatAgentService extends Disposable implements IChatAgentService {
162
162
  return result;
163
163
  }
164
164
 
165
- private async provideContextMessage(message: string, sessionId: string) {
166
- const context = await this.llmContextService.serialize();
167
- const fullMessage = await this.promptProvider.provideContextPrompt(context, message);
165
+ private provideContextMessage(message: string, sessionId: string) {
166
+ const context = this.contextService.serialize();
167
+ const fullMessage = this.promptProvider.provideContextPrompt(context, message);
168
168
  this.aiReporter.send({
169
169
  msgType: AIServiceType.Chat,
170
170
  actionType: ActionTypeEnum.ContextEnhance,
@@ -1,14 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { MessageList } from 'react-chat-elements';
3
3
 
4
- import {
5
- AINativeConfigService,
6
- AppConfig,
7
- LabelService,
8
- getIcon,
9
- useInjectable,
10
- useUpdateOnEvent,
11
- } from '@opensumi/ide-core-browser';
4
+ import { AppConfig, getIcon, useInjectable, useUpdateOnEvent } from '@opensumi/ide-core-browser';
12
5
  import { Popover, PopoverPosition } from '@opensumi/ide-core-browser/lib/components';
13
6
  import { EnhanceIcon } from '@opensumi/ide-core-browser/lib/components/ai-native';
14
7
  import {
@@ -21,7 +14,6 @@ import {
21
14
  ChatMessageRole,
22
15
  ChatRenderRegistryToken,
23
16
  ChatServiceToken,
24
- CommandService,
25
17
  Disposable,
26
18
  DisposableCollection,
27
19
  IAIReporter,
@@ -36,18 +28,16 @@ import {
36
28
  import { WorkbenchEditorService } from '@opensumi/ide-editor';
37
29
  import { IMainLayoutService } from '@opensumi/ide-main-layout';
38
30
  import { IMessageService } from '@opensumi/ide-overlay';
39
- import 'react-chat-elements/dist/main.css';
40
- import { IWorkspaceService } from '@opensumi/ide-workspace';
41
31
 
32
+ import 'react-chat-elements/dist/main.css';
42
33
  import { AI_CHAT_VIEW_ID, IChatAgentService, IChatInternalService, IChatMessageStructure } from '../../common';
43
- import { LLMContextService, LLMContextServiceToken } from '../../common/llm-context';
44
34
  import { CodeBlockData } from '../../common/types';
45
35
  import { FileChange, FileListDisplay } from '../components/ChangeList';
36
+ import { ChatContext } from '../components/ChatContext';
46
37
  import { CodeBlockWrapperInput } from '../components/ChatEditor';
47
38
  import ChatHistory, { IChatHistoryItem } from '../components/ChatHistory';
48
39
  import { ChatInput } from '../components/ChatInput';
49
40
  import { ChatMarkdown } from '../components/ChatMarkdown';
50
- import { ChatMentionInput } from '../components/ChatMentionInput';
51
41
  import { ChatNotify, ChatReply } from '../components/ChatReply';
52
42
  import { SlashCustomRender } from '../components/SlashCustomRender';
53
43
  import { MessageData, createMessageByAI, createMessageByUser } from '../components/utils';
@@ -115,8 +105,6 @@ export const AIChatView = () => {
115
105
  const chatFeatureRegistry = useInjectable<ChatFeatureRegistry>(ChatFeatureRegistryToken);
116
106
  const chatRenderRegistry = useInjectable<ChatRenderRegistry>(ChatRenderRegistryToken);
117
107
  const mcpServerRegistry = useInjectable<IMCPServerRegistry>(TokenMCPServerRegistry);
118
- const aiNativeConfigService = useInjectable<AINativeConfigService>(AINativeConfigService);
119
- const llmContextService = useInjectable<LLMContextService>(LLMContextServiceToken);
120
108
 
121
109
  const layoutService = useInjectable<IMainLayoutService>(IMainLayoutService);
122
110
  const msgHistoryManager = aiChatService.sessionModel.history;
@@ -126,9 +114,6 @@ export const AIChatView = () => {
126
114
  const editorService = useInjectable<WorkbenchEditorService>(WorkbenchEditorService);
127
115
  const appConfig = useInjectable<AppConfig>(AppConfig);
128
116
  const applyService = useInjectable<BaseApplyService>(BaseApplyService);
129
- const labelService = useInjectable<LabelService>(LabelService);
130
- const workspaceService = useInjectable<IWorkspaceService>(IWorkspaceService);
131
- const commandService = useInjectable<CommandService>(CommandService);
132
117
  const [shortcutCommands, setShortcutCommands] = React.useState<ChatSlashCommandItemModel[]>([]);
133
118
 
134
119
  const [changeList, setChangeList] = React.useState<FileChange[]>(getFileChanges(applyService.getSessionCodeBlocks()));
@@ -199,9 +184,6 @@ export const AIChatView = () => {
199
184
  if (chatRenderRegistry.chatInputRender) {
200
185
  return chatRenderRegistry.chatInputRender;
201
186
  }
202
- if (aiNativeConfigService.capabilities.supportsMCP) {
203
- return ChatMentionInput;
204
- }
205
187
  return ChatInput;
206
188
  }, [chatRenderRegistry.chatInputRender]);
207
189
 
@@ -280,7 +262,7 @@ export const AIChatView = () => {
280
262
  if (loading) {
281
263
  return;
282
264
  }
283
- await handleSend(message.message, message.agentId, message.command);
265
+ await handleSend(message);
284
266
  } else {
285
267
  if (message.agentId) {
286
268
  setAgentId(message.agentId);
@@ -367,9 +349,6 @@ export const AIChatView = () => {
367
349
  text={message}
368
350
  agentId={visibleAgentId}
369
351
  command={command}
370
- labelService={labelService}
371
- workspaceService={workspaceService}
372
- commandService={commandService}
373
352
  />
374
353
  ),
375
354
  },
@@ -475,15 +454,7 @@ export const AIChatView = () => {
475
454
  text: ChatUserRoleRender ? (
476
455
  <ChatUserRoleRender content={message} agentId={visibleAgentId} command={command} />
477
456
  ) : (
478
- <CodeBlockWrapperInput
479
- labelService={labelService}
480
- relationId={relationId}
481
- text={message}
482
- agentId={visibleAgentId}
483
- command={command}
484
- workspaceService={workspaceService}
485
- commandService={commandService}
486
- />
457
+ <CodeBlockWrapperInput relationId={relationId} text={message} agentId={visibleAgentId} command={command} />
487
458
  ),
488
459
  },
489
460
  styles.chat_message_code,
@@ -667,44 +638,11 @@ export const AIChatView = () => {
667
638
  );
668
639
 
669
640
  const handleSend = React.useCallback(
670
- async (message: string, agentId?: string, command?: string) => {
671
- const reportExtra = {
672
- actionSource: ActionSourceEnum.Chat,
673
- actionType: ActionTypeEnum.Send,
674
- };
675
- agentId = agentId ? agentId : ChatProxyService.AGENT_ID;
676
- // 提取并替换 {{@file:xxx}} 中的文件内容
677
- let processedContent = message;
678
- const filePattern = /\{\{@file:(.*?)\}\}/g;
679
- const fileMatches = message.match(filePattern);
680
- let isCleanContext = false;
681
- if (fileMatches) {
682
- for (const match of fileMatches) {
683
- const filePath = match.replace(/\{\{@file:(.*?)\}\}/, '$1');
684
- if (filePath && !isCleanContext) {
685
- isCleanContext = true;
686
- llmContextService.cleanFileContext();
687
- }
688
- const fileUri = new URI(filePath);
689
- llmContextService.addFileToContext(fileUri, undefined, true);
690
- // 获取文件内容
691
- // 替换占位符,后续支持自定义渲染时可替换为自定义渲染标签
692
- processedContent = processedContent.replace(match, `\`<attached_file>${fileUri.displayName}\``);
693
- }
694
- }
641
+ async (value: IChatMessageStructure) => {
642
+ const { message, command, reportExtra } = value;
695
643
 
696
- const folderPattern = /\{\{@folder:(.*?)\}\}/g;
697
- const folderMatches = processedContent.match(folderPattern);
698
- if (folderMatches) {
699
- for (const match of folderMatches) {
700
- const folderPath = match.replace(/\{\{@folder:(.*?)\}\}/, '$1');
701
- const folderUri = new URI(folderPath);
702
- llmContextService.addFolderToContext(folderUri);
703
- // 替换占位符,后续支持自定义渲染时可替换为自定义渲染标签
704
- processedContent = processedContent.replace(match, `\`<attached_folder>${folderUri.displayName}\``);
705
- }
706
- }
707
- return handleAgentReply({ message: processedContent, agentId, command, reportExtra });
644
+ const agentId = value.agentId ? value.agentId : ChatProxyService.AGENT_ID;
645
+ return handleAgentReply({ message, agentId, command, reportExtra });
708
646
  },
709
647
  [handleAgentReply],
710
648
  );
@@ -821,6 +759,7 @@ export const AIChatView = () => {
821
759
  </div>
822
760
  ) : null}
823
761
  <div className={styles.chat_input_wrap}>
762
+ <ChatContext />
824
763
  <div className={styles.header_operate}>
825
764
  <div className={styles.header_operate_left}>
826
765
  {shortcutCommands.map((command) => (
@@ -851,7 +790,17 @@ export const AIChatView = () => {
851
790
  />
852
791
  )}
853
792
  <ChatInputWrapperRender
854
- onSend={handleSend}
793
+ onSend={(value, agentId, command) =>
794
+ handleSend({
795
+ message: value,
796
+ agentId,
797
+ command,
798
+ reportExtra: {
799
+ actionSource: ActionSourceEnum.Chat,
800
+ actionType: ActionTypeEnum.Send,
801
+ },
802
+ })
803
+ }
855
804
  disabled={loading}
856
805
  enableOptions={true}
857
806
  theme={theme}
@@ -15,7 +15,7 @@ import { WorkbenchEditorService } from '@opensumi/ide-editor/lib/browser/types';
15
15
 
16
16
  import { FileContext, LLMContextService, LLMContextServiceToken } from '../../../common/llm-context';
17
17
 
18
- import { ContextSelector } from './context-selector';
18
+ import { ContextSelector } from './ContextSelector';
19
19
  import styles from './style.module.less';
20
20
 
21
21
  const getCollapsedHeight = () => ({ height: 0, opacity: 0 });
@@ -2,24 +2,14 @@ import capitalize from 'lodash/capitalize';
2
2
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
3
3
  import Highlight from 'react-highlight';
4
4
 
5
- import {
6
- EDITOR_COMMANDS,
7
- FILE_COMMANDS,
8
- IClipboardService,
9
- LabelService,
10
- getIcon,
11
- useInjectable,
12
- uuid,
13
- } from '@opensumi/ide-core-browser';
14
- import { Icon, Popover } from '@opensumi/ide-core-browser/lib/components';
5
+ import { IClipboardService, getIcon, useInjectable, uuid } from '@opensumi/ide-core-browser';
6
+ import { Popover } from '@opensumi/ide-core-browser/lib/components';
15
7
  import { EnhanceIcon } from '@opensumi/ide-core-browser/lib/components/ai-native';
16
8
  import {
17
9
  ActionSourceEnum,
18
10
  ActionTypeEnum,
19
11
  ChatFeatureRegistryToken,
20
- CommandService,
21
12
  IAIReporter,
22
- URI,
23
13
  localize,
24
14
  runWhenIdle,
25
15
  } from '@opensumi/ide-core-common';
@@ -32,9 +22,6 @@ import { ChatFeatureRegistry } from '../chat/chat.feature.registry';
32
22
 
33
23
  import styles from './components.module.less';
34
24
  import { highLightLanguageSupport } from './highLight';
35
- import { MentionType } from './mention-input/types';
36
-
37
- import type { IWorkspaceService } from '@opensumi/ide-workspace';
38
25
 
39
26
  import './highlightTheme.less';
40
27
 
@@ -152,56 +139,16 @@ const CodeBlock = ({
152
139
  renderText,
153
140
  agentId = '',
154
141
  command = '',
155
- labelService,
156
- commandService,
157
- workspaceService,
158
142
  }: {
159
143
  content?: string;
160
144
  relationId: string;
161
145
  renderText?: (t: string) => React.ReactNode;
162
146
  agentId?: string;
163
147
  command?: string;
164
- labelService?: LabelService;
165
- commandService?: CommandService;
166
- workspaceService?: IWorkspaceService;
167
148
  }) => {
168
149
  const rgInlineCode = /`([^`]+)`/g;
169
150
  const rgBlockCode = /```([^]+?)```/g;
170
151
  const rgBlockCodeBefore = /```([^]+)?/g;
171
- const rgAttachedFile = /<attached_file>(.*)/g;
172
- const rgAttachedFolder = /<attached_folder>(.*)/g;
173
- const handleAttachmentClick = useCallback(
174
- async (text: string, type: MentionType) => {
175
- const roots = await workspaceService?.roots;
176
- let uri;
177
- if (!roots) {
178
- return;
179
- }
180
- for (const root of roots) {
181
- uri = new URI(root.uri).resolve(text);
182
- try {
183
- await commandService?.executeCommand(FILE_COMMANDS.LOCATION.id, uri);
184
- if (type === MentionType.FILE) {
185
- await commandService?.executeCommand(EDITOR_COMMANDS.OPEN_RESOURCE.id, uri);
186
- }
187
- break;
188
- } catch {
189
- continue;
190
- }
191
- }
192
- },
193
- [commandService, workspaceService],
194
- );
195
- const renderAttachment = (text: string, isFolder = false, key: string) => (
196
- <span
197
- className={styles.attachment}
198
- key={key}
199
- onClick={() => handleAttachmentClick(text, isFolder ? MentionType.FOLDER : MentionType.FILE)}
200
- >
201
- <Icon iconClass={isFolder ? getIcon('folder') : labelService?.getIcon(new URI(text || 'file'))} />
202
- <span className={styles.attachment_text}>{text}</span>
203
- </span>
204
- );
205
152
 
206
153
  const renderCodeEditor = (content: string) => {
207
154
  const language = content.split('\n')[0].trim().toLowerCase();
@@ -246,47 +193,11 @@ const CodeBlock = ({
246
193
  renderedContent.push(text);
247
194
  }
248
195
  } else {
249
- // 处理文件和文件夹标记
250
- const processedText = text;
251
- const fileMatches = [...text.matchAll(rgAttachedFile)];
252
- const folderMatches = [...text.matchAll(rgAttachedFolder)];
253
- if (fileMatches.length || folderMatches.length) {
254
- let lastIndex = 0;
255
- const fragments: (string | React.ReactNode)[] = [];
256
-
257
- // 处理文件标记
258
- fileMatches.forEach((match, matchIndex) => {
259
- if (match.index !== undefined) {
260
- const spanText = processedText.slice(lastIndex, match.index);
261
- if (spanText) {
262
- fragments.push(<span key={`${index}-${matchIndex}`}>{spanText}</span>);
263
- }
264
- fragments.push(renderAttachment(match[1], false, `${index}-tag-${matchIndex}`));
265
- lastIndex = match.index + match[0].length;
266
- }
267
- });
268
-
269
- // 处理文件夹标记
270
- folderMatches.forEach((match, matchIndex) => {
271
- if (match.index !== undefined) {
272
- const spanText = processedText.slice(lastIndex, match.index);
273
- if (spanText) {
274
- fragments.push(<span key={`${index}-${matchIndex}`}>{spanText}</span>);
275
- }
276
- fragments.push(renderAttachment(match[1], true, `${index}-tag-${matchIndex}`));
277
- lastIndex = match.index + match[0].length;
278
- }
279
- });
280
-
281
- fragments.push(processedText.slice(lastIndex));
282
- renderedContent.push(...fragments);
283
- } else {
284
- renderedContent.push(
285
- <span className={styles.code_inline} key={index}>
286
- {text}
287
- </span>,
288
- );
289
- }
196
+ renderedContent.push(
197
+ <span className={styles.code_inline} key={index}>
198
+ {text}
199
+ </span>,
200
+ );
290
201
  }
291
202
  });
292
203
  } else {
@@ -305,29 +216,15 @@ export const CodeBlockWrapper = ({
305
216
  renderText,
306
217
  relationId,
307
218
  agentId,
308
- labelService,
309
- commandService,
310
- workspaceService,
311
219
  }: {
312
220
  text?: string;
313
221
  relationId: string;
314
222
  renderText?: (t: string) => React.ReactNode;
315
223
  agentId?: string;
316
- labelService?: LabelService;
317
- commandService?: CommandService;
318
- workspaceService?: IWorkspaceService;
319
224
  }) => (
320
225
  <div className={styles.ai_chat_code_wrapper}>
321
226
  <div className={styles.render_text}>
322
- <CodeBlock
323
- content={text}
324
- labelService={labelService}
325
- renderText={renderText}
326
- relationId={relationId}
327
- agentId={agentId}
328
- commandService={commandService}
329
- workspaceService={workspaceService}
330
- />
227
+ <CodeBlock content={text} renderText={renderText} relationId={relationId} agentId={agentId} />
331
228
  </div>
332
229
  </div>
333
230
  );
@@ -337,17 +234,11 @@ export const CodeBlockWrapperInput = ({
337
234
  relationId,
338
235
  agentId,
339
236
  command,
340
- labelService,
341
- workspaceService,
342
- commandService,
343
237
  }: {
344
238
  text: string;
345
239
  relationId: string;
346
240
  agentId?: string;
347
241
  command?: string;
348
- labelService?: LabelService;
349
- workspaceService?: IWorkspaceService;
350
- commandService?: CommandService;
351
242
  }) => {
352
243
  const chatFeatureRegistry = useInjectable<ChatFeatureRegistry>(ChatFeatureRegistryToken);
353
244
  const [tag, setTag] = useState<string>('');
@@ -380,15 +271,7 @@ export const CodeBlockWrapperInput = ({
380
271
  </div>
381
272
  )}
382
273
  {command && <div className={styles.tag}>/ {command}</div>}
383
- <CodeBlock
384
- content={txt}
385
- labelService={labelService}
386
- relationId={relationId}
387
- agentId={agentId}
388
- command={command}
389
- workspaceService={workspaceService}
390
- commandService={commandService}
391
- />
274
+ <CodeBlock content={txt} relationId={relationId} agentId={agentId} command={command} />
392
275
  </div>
393
276
  </div>
394
277
  );
@@ -519,7 +519,6 @@
519
519
  display: flex;
520
520
  font-size: 11px;
521
521
  align-items: center;
522
- min-width: 150px;
523
522
  }
524
523
 
525
524
  .mcp_desc {
@@ -566,27 +565,3 @@
566
565
  color: var(--descriptionForeground);
567
566
  }
568
567
  }
569
-
570
- .attachment {
571
- display: inline-flex;
572
- align-items: center;
573
- padding: 0 4px;
574
- margin: 0 2px;
575
- background: var(--badge-background);
576
- color: var(--badge-foreground);
577
- border-radius: 3px;
578
- vertical-align: middle;
579
- font-size: 12px;
580
- cursor: pointer;
581
- :global {
582
- .kt-icon {
583
- margin-right: 3px;
584
- }
585
- }
586
- }
587
-
588
- .attachment_text {
589
- line-height: 20px;
590
- vertical-align: middle;
591
- font-size: 12px;
592
- }
@@ -10,7 +10,6 @@ import {
10
10
  IEditorDocumentModelService,
11
11
  } from '@opensumi/ide-editor/lib/browser/doc-model/types';
12
12
  import { EditorSelectionChangeEvent } from '@opensumi/ide-editor/lib/browser/types';
13
- import { FileType, IFileServiceClient } from '@opensumi/ide-file-service';
14
13
  import { IMarkerService } from '@opensumi/ide-markers/lib/common/types';
15
14
  import { Range } from '@opensumi/ide-monaco';
16
15
 
@@ -27,18 +26,13 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
27
26
  @Autowired(IMarkerService)
28
27
  protected readonly markerService: IMarkerService;
29
28
 
30
- @Autowired(IFileServiceClient)
31
- protected readonly fileService: IFileServiceClient;
32
-
33
29
  private isAutoCollecting = false;
34
30
 
35
31
  private contextVersion = 0;
36
32
 
37
33
  private readonly maxAttachFilesLimit = 10;
38
- private readonly maxAttachFoldersLimit = 10;
39
34
  private readonly maxViewFilesLimit = 20;
40
- private attachedFiles: FileContext[] = [];
41
- private attachedFolders: FileContext[] = [];
35
+ private readonly attachedFiles: FileContext[] = [];
42
36
  private readonly recentlyViewFiles: FileContext[] = [];
43
37
  private readonly onDidContextFilesChangeEmitter = new Emitter<{
44
38
  viewed: FileContext[];
@@ -59,18 +53,6 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
59
53
  }
60
54
  }
61
55
 
62
- private addFolderToList(folder: FileContext, list: FileContext[], maxLimit: number) {
63
- const existingIndex = list.findIndex((f) => f.uri.toString() === folder.uri.toString());
64
- if (existingIndex > -1) {
65
- list.splice(existingIndex, 1);
66
- }
67
-
68
- list.push(folder);
69
- if (list.length > maxLimit) {
70
- list.shift();
71
- }
72
- }
73
-
74
56
  addFileToContext(uri: URI, selection?: [number, number], isManual = false): void {
75
57
  if (!uri) {
76
58
  return;
@@ -88,24 +70,12 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
88
70
  this.notifyContextChange();
89
71
  }
90
72
 
91
- addFolderToContext(uri: URI): void {
92
- if (!uri) {
93
- return;
94
- }
95
-
96
- const file = { uri };
97
-
98
- this.addFolderToList(file, this.attachedFolders, this.maxAttachFoldersLimit);
99
- this.notifyContextChange();
100
- }
101
-
102
73
  private notifyContextChange(): void {
103
74
  this.onDidContextFilesChangeEmitter.fire(this.getAllContextFiles());
104
75
  }
105
76
 
106
77
  cleanFileContext() {
107
- this.attachedFiles = [];
108
- this.attachedFolders = [];
78
+ this.attachedFiles.length = 0;
109
79
  this.notifyContextChange();
110
80
  }
111
81
 
@@ -113,7 +83,6 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
113
83
  return {
114
84
  viewed: this.recentlyViewFiles,
115
85
  attached: this.attachedFiles,
116
- attachedFolders: this.attachedFolders,
117
86
  version: this.contextVersion++,
118
87
  };
119
88
  }
@@ -191,63 +160,16 @@ export class LLMContextServiceImpl extends WithEventBus implements LLMContextSer
191
160
  this.dispose();
192
161
  }
193
162
 
194
- async serialize(): Promise<SerializedContext> {
163
+ serialize(): SerializedContext {
195
164
  const files = this.getAllContextFiles();
196
165
  const workspaceRoot = URI.file(this.appConfig.workspaceDir);
197
166
 
198
167
  return {
199
168
  recentlyViewFiles: this.serializeRecentlyViewFiles(files.viewed, workspaceRoot),
200
169
  attachedFiles: this.serializeAttachedFiles(files.attached, workspaceRoot),
201
- attachedFolders: await this.serializeAttachedFolders(files.attachedFolders, workspaceRoot),
202
170
  };
203
171
  }
204
172
 
205
- private async serializeAttachedFolders(folders: FileContext[], workspaceRoot: URI): Promise<string[]> {
206
- // 去重
207
- const folderPath = Array.from(new Set(folders.map((folder) => folder.uri.toString())));
208
- return Promise.all(
209
- folderPath.map(async (folder) => {
210
- const folderUri = new URI(folder);
211
- const root = workspaceRoot.relative(folderUri)?.toString() || '/';
212
- return `\`\`\`\n${root}\n${(await this.getPartiaFolderStructure(folderUri.codeUri.fsPath))
213
- .map((line) => `- ${line}`)
214
- .join('\n')}\n\`\`\`\n`;
215
- }),
216
- );
217
- }
218
-
219
- private async getPartiaFolderStructure(folder: string, level = 2): Promise<string[]> {
220
- const result: string[] = [];
221
- const stat = await this.fileService.getFileStat(folder);
222
-
223
- for (const child of stat?.children || []) {
224
- const relativePath = new URI(folder).relative(new URI(child.uri))!.toString();
225
-
226
- if (child.isSymbolicLink) {
227
- // 处理软链接
228
- const target = await this.fileService.getFileStat(child.realUri || child.uri);
229
- if (target) {
230
- result.push(`${relativePath} -> ${target} (symbolic link)`);
231
- } else {
232
- result.push(`${relativePath} (broken symbolic link)`);
233
- }
234
- continue;
235
- }
236
-
237
- if (child.type === FileType.Directory) {
238
- result.push(`${relativePath}/`);
239
- if (level > 1) {
240
- const subDirStructure = await this.getPartiaFolderStructure(child.uri, level - 1);
241
- result.push(...subDirStructure.map((subEntry) => `${relativePath}/${subEntry}`));
242
- }
243
- } else if (child.type === FileType.File) {
244
- result.push(relativePath);
245
- }
246
- }
247
-
248
- return result;
249
- }
250
-
251
173
  private serializeRecentlyViewFiles(files: FileContext[], workspaceRoot: URI): string[] {
252
174
  return files
253
175
  .map((file) => workspaceRoot.relative(file.uri)?.toString() || file.uri.parent.toString())
@@ -1,14 +1,8 @@
1
1
  import { Event, URI } from '@opensumi/ide-core-common/lib/utils';
2
2
 
3
3
  export interface LLMContextService {
4
- /**
5
- * 开始自动收集
6
- */
7
4
  startAutoCollection(): void;
8
5
 
9
- /**
10
- * 停止自动收集
11
- */
12
6
  stopAutoCollection(): void;
13
7
 
14
8
  /**
@@ -16,19 +10,11 @@ export interface LLMContextService {
16
10
  */
17
11
  addFileToContext(uri: URI, selection?: [number, number], isManual?: boolean): void;
18
12
 
19
- /**
20
- * 添加文件夹到 context 中
21
- */
22
- addFolderToContext(uri: URI, isManual?: boolean): void;
23
-
24
13
  /**
25
14
  * 清除上下文
26
15
  */
27
16
  cleanFileContext(): void;
28
17
 
29
- /**
30
- * 上下文文件变化事件
31
- */
32
18
  onDidContextFilesChangeEvent: Event<{ viewed: FileContext[]; attached: FileContext[]; version: number }>;
33
19
 
34
20
  /**
@@ -38,7 +24,7 @@ export interface LLMContextService {
38
24
  removeFileFromContext(uri: URI, isManual?: boolean): void;
39
25
 
40
26
  /** 导出为可序列化格式 */
41
- serialize(): Promise<SerializedContext>;
27
+ serialize(): SerializedContext;
42
28
  }
43
29
 
44
30
  export interface FileContext {
@@ -58,5 +44,4 @@ export interface AttachFileContext {
58
44
  export interface SerializedContext {
59
45
  recentlyViewFiles: string[];
60
46
  attachedFiles: Array<AttachFileContext>;
61
- attachedFolders: string[];
62
47
  }