@opensumi/ide-ai-native 3.8.3-next-1741763229.0 → 3.8.3-next-1741763277.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 -49
  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 -5
  16. package/lib/browser/components/ChatEditor.d.ts.map +1 -1
  17. package/lib/browser/components/ChatEditor.js +6 -45
  18. package/lib/browser/components/ChatEditor.js.map +1 -1
  19. package/lib/browser/components/components.module.less +0 -19
  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 +20 -63
  34. package/src/browser/components/{chat-context → ChatContext}/index.tsx +1 -1
  35. package/src/browser/components/ChatEditor.tsx +9 -72
  36. package/src/browser/components/components.module.less +0 -19
  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 -327
  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 -327
  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
@@ -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 {
@@ -38,14 +31,13 @@ import { IMessageService } from '@opensumi/ide-overlay';
38
31
 
39
32
  import 'react-chat-elements/dist/main.css';
40
33
  import { AI_CHAT_VIEW_ID, IChatAgentService, IChatInternalService, IChatMessageStructure } from '../../common';
41
- import { LLMContextService, LLMContextServiceToken } from '../../common/llm-context';
42
34
  import { CodeBlockData } from '../../common/types';
43
35
  import { FileChange, FileListDisplay } from '../components/ChangeList';
36
+ import { ChatContext } from '../components/ChatContext';
44
37
  import { CodeBlockWrapperInput } from '../components/ChatEditor';
45
38
  import ChatHistory, { IChatHistoryItem } from '../components/ChatHistory';
46
39
  import { ChatInput } from '../components/ChatInput';
47
40
  import { ChatMarkdown } from '../components/ChatMarkdown';
48
- import { ChatMentionInput } from '../components/ChatMentionInput';
49
41
  import { ChatNotify, ChatReply } from '../components/ChatReply';
50
42
  import { SlashCustomRender } from '../components/SlashCustomRender';
51
43
  import { MessageData, createMessageByAI, createMessageByUser } from '../components/utils';
@@ -113,8 +105,6 @@ export const AIChatView = () => {
113
105
  const chatFeatureRegistry = useInjectable<ChatFeatureRegistry>(ChatFeatureRegistryToken);
114
106
  const chatRenderRegistry = useInjectable<ChatRenderRegistry>(ChatRenderRegistryToken);
115
107
  const mcpServerRegistry = useInjectable<IMCPServerRegistry>(TokenMCPServerRegistry);
116
- const aiNativeConfigService = useInjectable<AINativeConfigService>(AINativeConfigService);
117
- const llmContextService = useInjectable<LLMContextService>(LLMContextServiceToken);
118
108
 
119
109
  const layoutService = useInjectable<IMainLayoutService>(IMainLayoutService);
120
110
  const msgHistoryManager = aiChatService.sessionModel.history;
@@ -124,7 +114,6 @@ export const AIChatView = () => {
124
114
  const editorService = useInjectable<WorkbenchEditorService>(WorkbenchEditorService);
125
115
  const appConfig = useInjectable<AppConfig>(AppConfig);
126
116
  const applyService = useInjectable<BaseApplyService>(BaseApplyService);
127
- const labelService = useInjectable<LabelService>(LabelService);
128
117
  const [shortcutCommands, setShortcutCommands] = React.useState<ChatSlashCommandItemModel[]>([]);
129
118
 
130
119
  const [changeList, setChangeList] = React.useState<FileChange[]>(getFileChanges(applyService.getSessionCodeBlocks()));
@@ -195,9 +184,6 @@ export const AIChatView = () => {
195
184
  if (chatRenderRegistry.chatInputRender) {
196
185
  return chatRenderRegistry.chatInputRender;
197
186
  }
198
- if (aiNativeConfigService.capabilities.supportsMCP) {
199
- return ChatMentionInput;
200
- }
201
187
  return ChatInput;
202
188
  }, [chatRenderRegistry.chatInputRender]);
203
189
 
@@ -276,7 +262,7 @@ export const AIChatView = () => {
276
262
  if (loading) {
277
263
  return;
278
264
  }
279
- await handleSend(message.message, message.agentId, message.command);
265
+ await handleSend(message);
280
266
  } else {
281
267
  if (message.agentId) {
282
268
  setAgentId(message.agentId);
@@ -363,7 +349,6 @@ export const AIChatView = () => {
363
349
  text={message}
364
350
  agentId={visibleAgentId}
365
351
  command={command}
366
- labelService={labelService}
367
352
  />
368
353
  ),
369
354
  },
@@ -469,13 +454,7 @@ export const AIChatView = () => {
469
454
  text: ChatUserRoleRender ? (
470
455
  <ChatUserRoleRender content={message} agentId={visibleAgentId} command={command} />
471
456
  ) : (
472
- <CodeBlockWrapperInput
473
- labelService={labelService}
474
- relationId={relationId}
475
- text={message}
476
- agentId={visibleAgentId}
477
- command={command}
478
- />
457
+ <CodeBlockWrapperInput relationId={relationId} text={message} agentId={visibleAgentId} command={command} />
479
458
  ),
480
459
  },
481
460
  styles.chat_message_code,
@@ -659,44 +638,11 @@ export const AIChatView = () => {
659
638
  );
660
639
 
661
640
  const handleSend = React.useCallback(
662
- async (message: string, agentId?: string, command?: string) => {
663
- const reportExtra = {
664
- actionSource: ActionSourceEnum.Chat,
665
- actionType: ActionTypeEnum.Send,
666
- };
667
- agentId = agentId ? agentId : ChatProxyService.AGENT_ID;
668
- // 提取并替换 {{@file:xxx}} 中的文件内容
669
- let processedContent = message;
670
- const filePattern = /\{\{@file:(.*?)\}\}/g;
671
- const fileMatches = message.match(filePattern);
672
- let isCleanContext = false;
673
- if (fileMatches) {
674
- for (const match of fileMatches) {
675
- const filePath = match.replace(/\{\{@file:(.*?)\}\}/, '$1');
676
- if (filePath && !isCleanContext) {
677
- isCleanContext = true;
678
- llmContextService.cleanFileContext();
679
- }
680
- const fileUri = new URI(filePath);
681
- llmContextService.addFileToContext(fileUri, undefined, true);
682
- // 获取文件内容
683
- // 替换占位符,后续支持自定义渲染时可替换为自定义渲染标签
684
- processedContent = processedContent.replace(match, `\`<attached_file>${fileUri.displayName}\``);
685
- }
686
- }
641
+ async (value: IChatMessageStructure) => {
642
+ const { message, command, reportExtra } = value;
687
643
 
688
- const folderPattern = /\{\{@folder:(.*?)\}\}/g;
689
- const folderMatches = processedContent.match(folderPattern);
690
- if (folderMatches) {
691
- for (const match of folderMatches) {
692
- const folderPath = match.replace(/\{\{@folder:(.*?)\}\}/, '$1');
693
- const folderUri = new URI(folderPath);
694
- llmContextService.addFolderToContext(folderUri);
695
- // 替换占位符,后续支持自定义渲染时可替换为自定义渲染标签
696
- processedContent = processedContent.replace(match, `\`<attached_folder>${folderUri.displayName}\``);
697
- }
698
- }
699
- return handleAgentReply({ message: processedContent, agentId, command, reportExtra });
644
+ const agentId = value.agentId ? value.agentId : ChatProxyService.AGENT_ID;
645
+ return handleAgentReply({ message, agentId, command, reportExtra });
700
646
  },
701
647
  [handleAgentReply],
702
648
  );
@@ -813,6 +759,7 @@ export const AIChatView = () => {
813
759
  </div>
814
760
  ) : null}
815
761
  <div className={styles.chat_input_wrap}>
762
+ <ChatContext />
816
763
  <div className={styles.header_operate}>
817
764
  <div className={styles.header_operate_left}>
818
765
  {shortcutCommands.map((command) => (
@@ -843,7 +790,17 @@ export const AIChatView = () => {
843
790
  />
844
791
  )}
845
792
  <ChatInputWrapperRender
846
- 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
+ }
847
804
  disabled={loading}
848
805
  enableOptions={true}
849
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,15 +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 { IClipboardService, LabelService, getIcon, useInjectable, uuid } from '@opensumi/ide-core-browser';
6
- 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';
7
7
  import { EnhanceIcon } from '@opensumi/ide-core-browser/lib/components/ai-native';
8
8
  import {
9
9
  ActionSourceEnum,
10
10
  ActionTypeEnum,
11
11
  ChatFeatureRegistryToken,
12
12
  IAIReporter,
13
- URI,
14
13
  localize,
15
14
  runWhenIdle,
16
15
  } from '@opensumi/ide-core-common';
@@ -140,26 +139,16 @@ const CodeBlock = ({
140
139
  renderText,
141
140
  agentId = '',
142
141
  command = '',
143
- labelService,
144
142
  }: {
145
143
  content?: string;
146
144
  relationId: string;
147
145
  renderText?: (t: string) => React.ReactNode;
148
146
  agentId?: string;
149
147
  command?: string;
150
- labelService?: LabelService;
151
148
  }) => {
152
149
  const rgInlineCode = /`([^`]+)`/g;
153
150
  const rgBlockCode = /```([^]+?)```/g;
154
151
  const rgBlockCodeBefore = /```([^]+)?/g;
155
- const rgAttachedFile = /<attached_file>(.*)/g;
156
- const rgAttachedFolder = /<attached_folder>(.*)/g;
157
- const renderAttachment = (text: string, isFolder = false, key: string) => (
158
- <span className={styles.attachment} key={key}>
159
- <Icon iconClass={isFolder ? getIcon('folder') : labelService?.getIcon(new URI(text || 'file'))} />
160
- <span className={styles.attachment_text}>{text}</span>
161
- </span>
162
- );
163
152
 
164
153
  const renderCodeEditor = (content: string) => {
165
154
  const language = content.split('\n')[0].trim().toLowerCase();
@@ -204,47 +193,11 @@ const CodeBlock = ({
204
193
  renderedContent.push(text);
205
194
  }
206
195
  } else {
207
- // 处理文件和文件夹标记
208
- const processedText = text;
209
- const fileMatches = [...text.matchAll(rgAttachedFile)];
210
- const folderMatches = [...text.matchAll(rgAttachedFolder)];
211
- if (fileMatches.length || folderMatches.length) {
212
- let lastIndex = 0;
213
- const fragments: (string | React.ReactNode)[] = [];
214
-
215
- // 处理文件标记
216
- fileMatches.forEach((match, matchIndex) => {
217
- if (match.index !== undefined) {
218
- const spanText = processedText.slice(lastIndex, match.index);
219
- if (spanText) {
220
- fragments.push(<span key={`${index}-${matchIndex}`}>{spanText}</span>);
221
- }
222
- fragments.push(renderAttachment(match[1], false, `${index}-tag-${matchIndex}`));
223
- lastIndex = match.index + match[0].length;
224
- }
225
- });
226
-
227
- // 处理文件夹标记
228
- folderMatches.forEach((match, matchIndex) => {
229
- if (match.index !== undefined) {
230
- const spanText = processedText.slice(lastIndex, match.index);
231
- if (spanText) {
232
- fragments.push(<span key={`${index}-${matchIndex}`}>{spanText}</span>);
233
- }
234
- fragments.push(renderAttachment(match[1], true, `${index}-tag-${matchIndex}`));
235
- lastIndex = match.index + match[0].length;
236
- }
237
- });
238
-
239
- fragments.push(processedText.slice(lastIndex));
240
- renderedContent.push(...fragments);
241
- } else {
242
- renderedContent.push(
243
- <span className={styles.code_inline} key={index}>
244
- {text}
245
- </span>,
246
- );
247
- }
196
+ renderedContent.push(
197
+ <span className={styles.code_inline} key={index}>
198
+ {text}
199
+ </span>,
200
+ );
248
201
  }
249
202
  });
250
203
  } else {
@@ -263,23 +216,15 @@ export const CodeBlockWrapper = ({
263
216
  renderText,
264
217
  relationId,
265
218
  agentId,
266
- labelService,
267
219
  }: {
268
220
  text?: string;
269
221
  relationId: string;
270
222
  renderText?: (t: string) => React.ReactNode;
271
223
  agentId?: string;
272
- labelService?: LabelService;
273
224
  }) => (
274
225
  <div className={styles.ai_chat_code_wrapper}>
275
226
  <div className={styles.render_text}>
276
- <CodeBlock
277
- content={text}
278
- labelService={labelService}
279
- renderText={renderText}
280
- relationId={relationId}
281
- agentId={agentId}
282
- />
227
+ <CodeBlock content={text} renderText={renderText} relationId={relationId} agentId={agentId} />
283
228
  </div>
284
229
  </div>
285
230
  );
@@ -289,13 +234,11 @@ export const CodeBlockWrapperInput = ({
289
234
  relationId,
290
235
  agentId,
291
236
  command,
292
- labelService,
293
237
  }: {
294
238
  text: string;
295
239
  relationId: string;
296
240
  agentId?: string;
297
241
  command?: string;
298
- labelService?: LabelService;
299
242
  }) => {
300
243
  const chatFeatureRegistry = useInjectable<ChatFeatureRegistry>(ChatFeatureRegistryToken);
301
244
  const [tag, setTag] = useState<string>('');
@@ -328,13 +271,7 @@ export const CodeBlockWrapperInput = ({
328
271
  </div>
329
272
  )}
330
273
  {command && <div className={styles.tag}>/ {command}</div>}
331
- <CodeBlock
332
- content={txt}
333
- labelService={labelService}
334
- relationId={relationId}
335
- agentId={agentId}
336
- command={command}
337
- />
274
+ <CodeBlock content={txt} relationId={relationId} agentId={agentId} command={command} />
338
275
  </div>
339
276
  </div>
340
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,21 +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
- }
581
-
582
- .attachment_text {
583
- line-height: 20px;
584
- vertical-align: middle;
585
- font-size: 12px;
586
- }
@@ -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
  }