@opensumi/ide-ai-native 3.8.1-next-1740556231.0 → 3.8.1-next-1740625266.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 (123) hide show
  1. package/lib/browser/ai-core.contextkeys.d.ts +1 -1
  2. package/lib/browser/ai-core.contextkeys.d.ts.map +1 -1
  3. package/lib/browser/ai-core.contextkeys.js +1 -1
  4. package/lib/browser/ai-core.contextkeys.js.map +1 -1
  5. package/lib/browser/ai-core.contribution.d.ts.map +1 -1
  6. package/lib/browser/ai-core.contribution.js +10 -3
  7. package/lib/browser/ai-core.contribution.js.map +1 -1
  8. package/lib/browser/chat/chat.view.d.ts.map +1 -1
  9. package/lib/browser/chat/chat.view.js +30 -1
  10. package/lib/browser/chat/chat.view.js.map +1 -1
  11. package/lib/browser/contrib/inline-completions/inline-completions.controller.js +1 -1
  12. package/lib/browser/contrib/inline-completions/inline-completions.controller.js.map +1 -1
  13. package/lib/browser/contrib/intelligent-completions/index.d.ts +2 -1
  14. package/lib/browser/contrib/intelligent-completions/index.d.ts.map +1 -1
  15. package/lib/browser/contrib/intelligent-completions/index.js +4 -1
  16. package/lib/browser/contrib/intelligent-completions/index.js.map +1 -1
  17. package/lib/browser/contrib/intelligent-completions/intelligent-completions.contribution.js +2 -2
  18. package/lib/browser/contrib/intelligent-completions/intelligent-completions.contribution.js.map +1 -1
  19. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.d.ts.map +1 -1
  20. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js +5 -4
  21. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js.map +1 -1
  22. package/lib/browser/contrib/intelligent-completions/view/code-edits-previewer.d.ts.map +1 -1
  23. package/lib/browser/contrib/intelligent-completions/view/code-edits-previewer.js +4 -2
  24. package/lib/browser/contrib/intelligent-completions/view/code-edits-previewer.js.map +1 -1
  25. package/lib/browser/contrib/intelligent-completions/view/default.d.ts.map +1 -1
  26. package/lib/browser/contrib/intelligent-completions/view/default.js +17 -11
  27. package/lib/browser/contrib/intelligent-completions/view/default.js.map +1 -1
  28. package/lib/browser/index.d.ts.map +1 -1
  29. package/lib/browser/index.js +4 -0
  30. package/lib/browser/index.js.map +1 -1
  31. package/lib/browser/mcp/config/components/mcp-config.module.less +178 -0
  32. package/lib/browser/mcp/config/components/mcp-config.view.d.ts +3 -0
  33. package/lib/browser/mcp/config/components/mcp-config.view.d.ts.map +1 -0
  34. package/lib/browser/mcp/config/components/mcp-config.view.js +150 -0
  35. package/lib/browser/mcp/config/components/mcp-config.view.js.map +1 -0
  36. package/lib/browser/mcp/config/components/mcp-server-form.d.ts +16 -0
  37. package/lib/browser/mcp/config/components/mcp-server-form.d.ts.map +1 -0
  38. package/lib/browser/mcp/config/components/mcp-server-form.js +84 -0
  39. package/lib/browser/mcp/config/components/mcp-server-form.js.map +1 -0
  40. package/lib/browser/mcp/config/components/mcp-server-form.module.less +78 -0
  41. package/lib/browser/mcp/config/mcp-config.commands.d.ts +10 -0
  42. package/lib/browser/mcp/config/mcp-config.commands.d.ts.map +1 -0
  43. package/lib/browser/mcp/config/mcp-config.commands.js +35 -0
  44. package/lib/browser/mcp/config/mcp-config.commands.js.map +1 -0
  45. package/lib/browser/mcp/config/mcp-config.contribution.d.ts +16 -0
  46. package/lib/browser/mcp/config/mcp-config.contribution.d.ts.map +1 -0
  47. package/lib/browser/mcp/config/mcp-config.contribution.js +62 -0
  48. package/lib/browser/mcp/config/mcp-config.contribution.js.map +1 -0
  49. package/lib/browser/mcp/mcp-server-proxy.service.d.ts +6 -0
  50. package/lib/browser/mcp/mcp-server-proxy.service.d.ts.map +1 -1
  51. package/lib/browser/mcp/mcp-server-proxy.service.js +10 -1
  52. package/lib/browser/mcp/mcp-server-proxy.service.js.map +1 -1
  53. package/lib/browser/mcp/mcp-server.feature.registry.d.ts.map +1 -1
  54. package/lib/browser/mcp/mcp-server.feature.registry.js +3 -2
  55. package/lib/browser/mcp/mcp-server.feature.registry.js.map +1 -1
  56. package/lib/browser/preferences/schema.d.ts.map +1 -1
  57. package/lib/browser/preferences/schema.js +16 -0
  58. package/lib/browser/preferences/schema.js.map +1 -1
  59. package/lib/common/index.d.ts +8 -1
  60. package/lib/common/index.d.ts.map +1 -1
  61. package/lib/common/index.js +3 -1
  62. package/lib/common/index.js.map +1 -1
  63. package/lib/common/mcp-server-manager.d.ts +17 -1
  64. package/lib/common/mcp-server-manager.d.ts.map +1 -1
  65. package/lib/common/mcp-server-manager.js.map +1 -1
  66. package/lib/common/tool-invocation-registry.d.ts +2 -2
  67. package/lib/common/tool-invocation-registry.d.ts.map +1 -1
  68. package/lib/common/tool-invocation-registry.js +1 -1
  69. package/lib/common/tool-invocation-registry.js.map +1 -1
  70. package/lib/common/types.d.ts +6 -0
  71. package/lib/common/types.d.ts.map +1 -1
  72. package/lib/common/utils.d.ts.map +1 -1
  73. package/lib/common/utils.js +2 -1
  74. package/lib/common/utils.js.map +1 -1
  75. package/lib/node/base-language-model.d.ts.map +1 -1
  76. package/lib/node/base-language-model.js +5 -4
  77. package/lib/node/base-language-model.js.map +1 -1
  78. package/lib/node/mcp/sumi-mcp-server.d.ts +17 -3
  79. package/lib/node/mcp/sumi-mcp-server.d.ts.map +1 -1
  80. package/lib/node/mcp/sumi-mcp-server.js +59 -6
  81. package/lib/node/mcp/sumi-mcp-server.js.map +1 -1
  82. package/lib/node/mcp-server-manager-impl.d.ts +4 -3
  83. package/lib/node/mcp-server-manager-impl.d.ts.map +1 -1
  84. package/lib/node/mcp-server-manager-impl.js +26 -6
  85. package/lib/node/mcp-server-manager-impl.js.map +1 -1
  86. package/lib/node/mcp-server.d.ts +5 -16
  87. package/lib/node/mcp-server.d.ts.map +1 -1
  88. package/lib/node/mcp-server.js +12 -6
  89. package/lib/node/mcp-server.js.map +1 -1
  90. package/lib/node/openai/openai-language-model.d.ts +4 -3
  91. package/lib/node/openai/openai-language-model.d.ts.map +1 -1
  92. package/lib/node/openai/openai-language-model.js +3 -2
  93. package/lib/node/openai/openai-language-model.js.map +1 -1
  94. package/package.json +27 -27
  95. package/src/browser/ai-core.contextkeys.ts +3 -3
  96. package/src/browser/ai-core.contribution.ts +13 -4
  97. package/src/browser/chat/chat.view.tsx +47 -0
  98. package/src/browser/contrib/inline-completions/inline-completions.controller.ts +1 -1
  99. package/src/browser/contrib/intelligent-completions/index.ts +5 -1
  100. package/src/browser/contrib/intelligent-completions/intelligent-completions.contribution.ts +3 -3
  101. package/src/browser/contrib/intelligent-completions/intelligent-completions.controller.ts +6 -5
  102. package/src/browser/contrib/intelligent-completions/view/code-edits-previewer.ts +4 -2
  103. package/src/browser/contrib/intelligent-completions/view/default.ts +27 -19
  104. package/src/browser/index.ts +4 -0
  105. package/src/browser/mcp/config/components/mcp-config.module.less +178 -0
  106. package/src/browser/mcp/config/components/mcp-config.view.tsx +215 -0
  107. package/src/browser/mcp/config/components/mcp-server-form.module.less +78 -0
  108. package/src/browser/mcp/config/components/mcp-server-form.tsx +144 -0
  109. package/src/browser/mcp/config/mcp-config.commands.ts +29 -0
  110. package/src/browser/mcp/config/mcp-config.contribution.ts +65 -0
  111. package/src/browser/mcp/mcp-server-proxy.service.ts +14 -2
  112. package/src/browser/mcp/mcp-server.feature.registry.ts +3 -2
  113. package/src/browser/preferences/schema.ts +16 -0
  114. package/src/common/index.ts +7 -1
  115. package/src/common/mcp-server-manager.ts +17 -1
  116. package/src/common/tool-invocation-registry.ts +2 -2
  117. package/src/common/types.ts +6 -0
  118. package/src/common/utils.ts +3 -1
  119. package/src/node/base-language-model.ts +7 -4
  120. package/src/node/mcp/sumi-mcp-server.ts +67 -9
  121. package/src/node/mcp-server-manager-impl.ts +30 -9
  122. package/src/node/mcp-server.ts +11 -14
  123. package/src/node/openai/openai-language-model.ts +7 -4
@@ -1,13 +1,13 @@
1
1
  import { Autowired, Injectable, Optional } from '@opensumi/di';
2
2
  import { IContextKey, IContextKeyService, IScopedContextKeyService } from '@opensumi/ide-core-browser';
3
3
  import {
4
+ CodeEditsIsVisible,
4
5
  InlineChatIsVisible,
5
6
  InlineCompletionIsTrigger,
6
7
  InlineDiffPartialEditsIsVisible,
7
8
  InlineHintWidgetIsVisible,
8
9
  InlineInputWidgetIsStreaming,
9
10
  InlineInputWidgetIsVisible,
10
- MultiLineEditsIsVisible,
11
11
  } from '@opensumi/ide-core-browser/lib/contextkey/ai-native';
12
12
  import { ContextKeyService } from '@opensumi/monaco-editor-core/esm/vs/platform/contextkey/browser/contextKeyService';
13
13
  import { IContextKeyServiceTarget } from '@opensumi/monaco-editor-core/esm/vs/platform/contextkey/common/contextkey';
@@ -25,7 +25,7 @@ export class AINativeContextKey {
25
25
  public readonly inlineInputWidgetIsVisible: IContextKey<boolean>;
26
26
  public readonly inlineInputWidgetIsStreaming: IContextKey<boolean>;
27
27
  public readonly inlineDiffPartialEditsIsVisible: IContextKey<boolean>;
28
- public readonly multiLineEditsIsVisible: IContextKey<boolean>;
28
+ public readonly codeEditsIsVisible: IContextKey<boolean>;
29
29
  public get contextKeyService() {
30
30
  return this._contextKeyService;
31
31
  }
@@ -38,6 +38,6 @@ export class AINativeContextKey {
38
38
  this.inlineInputWidgetIsVisible = InlineInputWidgetIsVisible.bind(this._contextKeyService);
39
39
  this.inlineInputWidgetIsStreaming = InlineInputWidgetIsStreaming.bind(this._contextKeyService);
40
40
  this.inlineDiffPartialEditsIsVisible = InlineDiffPartialEditsIsVisible.bind(this._contextKeyService);
41
- this.multiLineEditsIsVisible = MultiLineEditsIsVisible.bind(this._contextKeyService);
41
+ this.codeEditsIsVisible = CodeEditsIsVisible.bind(this._contextKeyService);
42
42
  }
43
43
  }
@@ -76,6 +76,7 @@ import {
76
76
  AI_CHAT_LOGO_AVATAR_ID,
77
77
  AI_CHAT_VIEW_ID,
78
78
  AI_MENU_BAR_DEBUG_TOOLBAR,
79
+ BUILTIN_MCP_SERVER_NAME,
79
80
  ChatProxyServiceToken,
80
81
  IChatInternalService,
81
82
  IChatManagerService,
@@ -338,15 +339,23 @@ export class AINativeBrowserContribution
338
339
  }
339
340
 
340
341
  if (supportsMCP) {
341
- // 初始化内置 MCP Server
342
- this.sumiMCPServerBackendProxy.initBuiltinMCPServer();
343
-
344
342
  // 从 preferences 获取并初始化外部 MCP Servers
345
343
  const mcpServers = this.preferenceService.getValid<MCPServerDescription[]>(
346
344
  AINativeSettingSectionsId.MCPServers,
347
345
  );
346
+
347
+ // 查找内置 MCP Server 的配置
348
+ const builtinServer = mcpServers?.find((server) => server.name === BUILTIN_MCP_SERVER_NAME);
349
+
350
+ // 总是初始化内置服务器,根据配置决定是否启用
351
+ this.sumiMCPServerBackendProxy.initBuiltinMCPServer(builtinServer?.enabled ?? true);
352
+
353
+ // 初始化其他外部 MCP Servers
348
354
  if (mcpServers && mcpServers.length > 0) {
349
- this.sumiMCPServerBackendProxy.initExternalMCPServers(mcpServers);
355
+ const externalServers = mcpServers.filter((server) => server.name !== BUILTIN_MCP_SERVER_NAME);
356
+ if (externalServers.length > 0) {
357
+ this.sumiMCPServerBackendProxy.initExternalMCPServers(externalServers);
358
+ }
350
359
  }
351
360
  }
352
361
  });
@@ -3,6 +3,7 @@ import { MessageList } from 'react-chat-elements';
3
3
 
4
4
  import {
5
5
  AINativeConfigService,
6
+ CommandService,
6
7
  getIcon,
7
8
  useEventEffect,
8
9
  useInjectable,
@@ -52,6 +53,7 @@ import { ChatNotify, ChatReply } from '../components/ChatReply';
52
53
  import { SlashCustomRender } from '../components/SlashCustomRender';
53
54
  import { MessageData, createMessageByAI, createMessageByUser } from '../components/utils';
54
55
  import { WelcomeMessage } from '../components/WelcomeMsg';
56
+ import { OPEN_MCP_CONFIG_COMMAND } from '../mcp/config/mcp-config.commands';
55
57
  import { MCPServerProxyService } from '../mcp/mcp-server-proxy.service';
56
58
  import { MCPToolsDialog } from '../mcp/mcp-tools-dialog.view';
57
59
  import { ChatViewHeaderRender, TSlashCommandCustomRender } from '../types';
@@ -63,6 +65,7 @@ import { ChatFeatureRegistry } from './chat.feature.registry';
63
65
  import { ChatInternalService } from './chat.internal.service';
64
66
  import styles from './chat.module.less';
65
67
  import { ChatRenderRegistry } from './chat.render.registry';
68
+
66
69
  const SCROLL_CLASSNAME = 'chat_scroll';
67
70
 
68
71
  interface TDispatchAction {
@@ -81,11 +84,15 @@ export const AIChatView = () => {
81
84
  const chatRenderRegistry = useInjectable<ChatRenderRegistry>(ChatRenderRegistryToken);
82
85
  const contextService = useInjectable<LLMContextService>(LLMContextServiceToken);
83
86
  const promptProvider = useInjectable<ChatAgentPromptProvider>(ChatAgentPromptProvider);
87
+ const mcpServerProxyService = useInjectable<MCPServerProxyService>(TokenMCPServerProxyService);
84
88
 
85
89
  const layoutService = useInjectable<IMainLayoutService>(IMainLayoutService);
86
90
  const msgHistoryManager = aiChatService.sessionModel.history;
87
91
  const containerRef = React.useRef<HTMLDivElement>(null);
88
92
  const chatInputRef = React.useRef<{ setInputValue: (v: string) => void } | null>(null);
93
+ const dialogService = useInjectable<IDialogService>(IDialogService);
94
+ const aiNativeConfigService = useInjectable<AINativeConfigService>(AINativeConfigService);
95
+ const commandService = useInjectable<CommandService>(CommandService);
89
96
 
90
97
  const [shortcutCommands, setShortcutCommands] = React.useState<ChatSlashCommandItemModel[]>([]);
91
98
 
@@ -107,6 +114,8 @@ export const AIChatView = () => {
107
114
  const [defaultAgentId, setDefaultAgentId] = React.useState<string>('');
108
115
  const [command, setCommand] = React.useState('');
109
116
  const [theme, setTheme] = React.useState<string | null>(null);
117
+ const [mcpToolsCount, setMcpToolsCount] = React.useState<number>(0);
118
+ const [mcpServersCount, setMcpServersCount] = React.useState<number>(0);
110
119
 
111
120
  React.useEffect(() => {
112
121
  const featureSlashCommands = chatFeatureRegistry.getAllShortcutSlashCommand();
@@ -658,6 +667,32 @@ export const AIChatView = () => {
658
667
  };
659
668
  }, [aiChatService.sessionModel]);
660
669
 
670
+ useEventEffect(
671
+ mcpServerProxyService.onChangeMCPServers,
672
+ () => {
673
+ mcpServerProxyService.getAllMCPTools().then((tools) => {
674
+ setMcpToolsCount(tools.length);
675
+ });
676
+ mcpServerProxyService.$getServers().then((servers) => {
677
+ setMcpServersCount(servers.length);
678
+ });
679
+ },
680
+ [mcpServerProxyService],
681
+ );
682
+
683
+ const handleShowMCPTools = React.useCallback(async () => {
684
+ const tools = await mcpServerProxyService.getAllMCPTools();
685
+ dialogService.open({
686
+ message: <MCPToolsDialog tools={tools} />,
687
+ type: MessageType.Empty,
688
+ buttons: ['关闭'],
689
+ });
690
+ }, [mcpServerProxyService, dialogService]);
691
+
692
+ const handleShowMCPConfig = React.useCallback(() => {
693
+ commandService.executeCommand(OPEN_MCP_CONFIG_COMMAND.id);
694
+ }, [commandService]);
695
+
661
696
  return (
662
697
  <div id={styles.ai_chat_view}>
663
698
  <div className={styles.header_container}>
@@ -697,6 +732,18 @@ export const AIChatView = () => {
697
732
  </Popover>
698
733
  ))}
699
734
  </div>
735
+ <div className={styles.header_operate_right}>
736
+ {aiNativeConfigService.capabilities.supportsMCP && (
737
+ <>
738
+ <div className={styles.tag} onClick={handleShowMCPConfig}>
739
+ {`MCP Servers: ${mcpServersCount}`}
740
+ </div>
741
+ <div className={styles.tag} onClick={handleShowMCPTools}>
742
+ {`MCP Tools: ${mcpToolsCount}`}
743
+ </div>
744
+ </>
745
+ )}
746
+ </div>
700
747
  </div>
701
748
  <ChatInputWrapperRender
702
749
  onSend={(value, agentId, command) =>
@@ -170,7 +170,7 @@ export class InlineCompletionsController extends BaseAIMonacoEditorController {
170
170
  }
171
171
 
172
172
  // 如果上一次补全结果还在,则不重复请求
173
- const isVisible = this.aiNativeContextKey.multiLineEditsIsVisible.get();
173
+ const isVisible = this.aiNativeContextKey.codeEditsIsVisible.get();
174
174
  if (isVisible) {
175
175
  return;
176
176
  }
@@ -69,7 +69,11 @@ export class CodeEditsResultValue<T extends ICodeEdit = ICodeEdit> extends Dispo
69
69
  }));
70
70
  }
71
71
 
72
- public get range(): IRange {
72
+ public get firstRange(): IRange {
73
73
  return this.raw.items[0].range;
74
74
  }
75
+
76
+ public get firstText(): string {
77
+ return this.raw.items[0].insertText;
78
+ }
75
79
  }
@@ -8,7 +8,7 @@ import {
8
8
  KeybindingScope,
9
9
  } from '@opensumi/ide-core-browser';
10
10
  import { AI_CODE_EDITS_COMMANDS } from '@opensumi/ide-core-browser/lib/ai-native/command';
11
- import { MultiLineEditsIsVisible } from '@opensumi/ide-core-browser/lib/contextkey/ai-native';
11
+ import { CodeEditsIsVisible } from '@opensumi/ide-core-browser/lib/contextkey/ai-native';
12
12
  import { CommandContribution, CommandRegistry, Domain } from '@opensumi/ide-core-common';
13
13
  import { WorkbenchEditorService } from '@opensumi/ide-editor';
14
14
  import { WorkbenchEditorServiceImpl } from '@opensumi/ide-editor/lib/browser/workbench-editor.service';
@@ -61,7 +61,7 @@ export class IntelligentCompletionsContribution implements KeybindingContributio
61
61
  keybindings.registerKeybinding({
62
62
  command: AI_CODE_EDITS_COMMANDS.DISCARD.id,
63
63
  keybinding: Key.ESCAPE.code,
64
- when: MultiLineEditsIsVisible.raw,
64
+ when: CodeEditsIsVisible.raw,
65
65
  priority: 100,
66
66
  });
67
67
 
@@ -69,7 +69,7 @@ export class IntelligentCompletionsContribution implements KeybindingContributio
69
69
  {
70
70
  command: AI_CODE_EDITS_COMMANDS.ACCEPT.id,
71
71
  keybinding: Key.TAB.code,
72
- when: MultiLineEditsIsVisible.raw,
72
+ when: CodeEditsIsVisible.raw,
73
73
  },
74
74
  KeybindingScope.USER,
75
75
  );
@@ -5,7 +5,7 @@ import {
5
5
  KeybindingScope,
6
6
  PreferenceService,
7
7
  } from '@opensumi/ide-core-browser';
8
- import { MultiLineEditsIsVisible } from '@opensumi/ide-core-browser/lib/contextkey/ai-native';
8
+ import { CodeEditsIsVisible } from '@opensumi/ide-core-browser/lib/contextkey/ai-native';
9
9
  import {
10
10
  AINativeSettingSectionsId,
11
11
  CodeEditsRT,
@@ -98,13 +98,13 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
98
98
  this.monacoEditor,
99
99
  ]);
100
100
 
101
- const multiLineEditsIsVisibleKey = new Set([MultiLineEditsIsVisible.raw]);
101
+ const multiLineEditsIsVisibleKey = new Set([CodeEditsIsVisible.raw]);
102
102
  this.multiLineEditsIsVisibleObs = observableFromEvent(
103
103
  this,
104
104
  Event.filter(this.aiNativeContextKey.contextKeyService!.onDidChangeContext, (e: ContextKeyChangeEvent) =>
105
105
  e.payload.affectsSome(multiLineEditsIsVisibleKey),
106
106
  ),
107
- () => !!this.aiNativeContextKey.multiLineEditsIsVisible.get(),
107
+ () => !!this.aiNativeContextKey.codeEditsIsVisible.get(),
108
108
  );
109
109
 
110
110
  this.registerFeature(this.monacoEditor);
@@ -205,7 +205,7 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
205
205
 
206
206
  public hide() {
207
207
  this.cancelToken();
208
- this.aiNativeContextKey.multiLineEditsIsVisible.reset();
208
+ this.aiNativeContextKey.codeEditsIsVisible.reset();
209
209
  this.codeEditsPreviewer.hide();
210
210
  }
211
211
 
@@ -273,6 +273,7 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
273
273
  public trigger(tx: ITransaction): void {
274
274
  const triggerSource = this.codeEditsSourceCollection.getSource(TriggerCodeEditsSource) as TriggerCodeEditsSource;
275
275
  if (triggerSource) {
276
+ this.hide();
276
277
  triggerSource.triggerSignal.trigger(tx);
277
278
  }
278
279
  }
@@ -314,7 +315,7 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
314
315
  handleChange: (context) => {
315
316
  if (context.didChange(this.codeEditsSourceCollection.codeEditsContextBean)) {
316
317
  // 如果上一次补全结果还在,则不重复请求
317
- const isVisible = this.aiNativeContextKey.multiLineEditsIsVisible.get();
318
+ const isVisible = this.aiNativeContextKey.codeEditsIsVisible.get();
318
319
  return !isVisible;
319
320
  }
320
321
  return false;
@@ -51,19 +51,21 @@ export class CodeEditsPreviewer extends Disposable {
51
51
 
52
52
  public render(completionModel: CodeEditsResultValue) {
53
53
  this.view?.render(completionModel);
54
- this.aiNativeContextKey.multiLineEditsIsVisible.set(true);
54
+ this.aiNativeContextKey.codeEditsIsVisible.set(true);
55
55
  }
56
56
 
57
57
  public hide() {
58
58
  this.view?.hide();
59
- this.aiNativeContextKey.multiLineEditsIsVisible.set(false);
59
+ this.aiNativeContextKey.codeEditsIsVisible.set(false);
60
60
  }
61
61
 
62
62
  public accept() {
63
63
  this.view?.accept();
64
+ this.aiNativeContextKey.codeEditsIsVisible.set(false);
64
65
  }
65
66
 
66
67
  public discard() {
67
68
  this.view?.discard();
69
+ this.aiNativeContextKey.codeEditsIsVisible.set(false);
68
70
  }
69
71
  }
@@ -80,17 +80,23 @@ export class DefaultCodeEditsView extends BaseCodeEditsView {
80
80
  return;
81
81
  }
82
82
 
83
- asyncTransaction(async (tx) => {
84
- const position = this.editorObs.positions.get()?.[0];
85
- if (!position) {
86
- return;
87
- }
83
+ const position = this.editorObs.positions.get()?.[0];
84
+ if (!position) {
85
+ return;
86
+ }
88
87
 
89
- const model = this.editorObs.model.get();
90
- if (!model) {
91
- return;
92
- }
88
+ const model = this.editorObs.model.get();
89
+ if (!model) {
90
+ return;
91
+ }
93
92
 
93
+ const originalContent = model.getValueInRange(completionModel.firstRange);
94
+ // edits 的内容与原内容一样就不展示
95
+ if (originalContent === completionModel.firstText) {
96
+ return;
97
+ }
98
+
99
+ asyncTransaction(async (tx) => {
94
100
  const versionId = this.editorObs.versionId.get();
95
101
  const context: InlineCompletionContext = {
96
102
  triggerKind: InlineCompletionTriggerKind.Automatic,
@@ -103,16 +109,16 @@ export class DefaultCodeEditsView extends BaseCodeEditsView {
103
109
  const inlineEdits: InlineCompletionProviderResult = await provideInlineCompletions(
104
110
  {
105
111
  all: () => [
106
- {
107
- provideInlineCompletions: () => {},
108
- provideInlineEditsForRange(model, range, context, token) {
109
- return completionModel;
110
- },
111
- freeInlineCompletions: () => [],
112
- } as InlineCompletionsProvider<ICodeEditsResult<ICodeEdit>>,
113
- ],
112
+ {
113
+ provideInlineCompletions: () => {},
114
+ provideInlineEditsForRange(model, range, context, token) {
115
+ return completionModel;
116
+ },
117
+ freeInlineCompletions: () => [],
118
+ } as InlineCompletionsProvider<ICodeEditsResult<ICodeEdit>>,
119
+ ],
114
120
  } as unknown as LanguageFeatureRegistry<InlineCompletionsProvider>,
115
- Range.lift(completionModel.range),
121
+ Range.lift(completionModel.firstRange),
116
122
  model,
117
123
  context,
118
124
  );
@@ -122,9 +128,11 @@ export class DefaultCodeEditsView extends BaseCodeEditsView {
122
128
  request,
123
129
  model,
124
130
  this.editorObs.versionId,
125
- constObservable(1000),
131
+ constObservable(4000),
126
132
  );
133
+
127
134
  source.inlineCompletions.set(completions, tx);
135
+ source.loading.set(false, tx);
128
136
  });
129
137
  }
130
138
 
@@ -55,6 +55,8 @@ import { RenameCandidatesProviderRegistry } from './contrib/rename/rename.featur
55
55
  import { TerminalAIContribution } from './contrib/terminal/terminal-ai.contributon';
56
56
  import { TerminalFeatureRegistry } from './contrib/terminal/terminal.feature.registry';
57
57
  import { LanguageParserService } from './languages/service';
58
+ import { MCPConfigCommandContribution } from './mcp/config/mcp-config.commands';
59
+ import { MCPConfigContribution } from './mcp/config/mcp-config.contribution';
58
60
  import { MCPServerProxyService } from './mcp/mcp-server-proxy.service';
59
61
  import { MCPServerRegistry } from './mcp/mcp-server.feature.registry';
60
62
  import { CreateNewFileWithTextTool } from './mcp/tools/createNewFileWithText';
@@ -91,6 +93,8 @@ export class AINativeModule extends BrowserModule {
91
93
  AICodeActionContribution,
92
94
  AINativePreferencesContribution,
93
95
  IntelligentCompletionsContribution,
96
+ MCPConfigContribution,
97
+ MCPConfigCommandContribution,
94
98
 
95
99
  // MCP Server Contributions START
96
100
  ListDirTool,
@@ -0,0 +1,178 @@
1
+ .container {
2
+ padding: 20px;
3
+ color: var(--foreground);
4
+ }
5
+
6
+ .header {
7
+ display: flex;
8
+ justify-content: space-between;
9
+ align-items: flex-start;
10
+ margin-bottom: 24px;
11
+ }
12
+
13
+ .title {
14
+ margin: 0 0 8px 0;
15
+ font-size: 24px;
16
+ font-weight: 600;
17
+ }
18
+
19
+ .description {
20
+ margin: 0;
21
+ color: var(--descriptionForeground);
22
+ font-size: 14px;
23
+ }
24
+
25
+ .addButton {
26
+ padding: 8px 16px;
27
+ border-radius: 4px;
28
+ background-color: var(--button-primary-background);
29
+ color: var(--button-primary-foreground);
30
+ border: none;
31
+ cursor: pointer;
32
+ font-size: 13px;
33
+
34
+ &:hover {
35
+ background-color: var(--button-primary-hover-background);
36
+ }
37
+ }
38
+
39
+ .serversList {
40
+ display: flex;
41
+ flex-direction: column;
42
+ gap: 12px;
43
+ }
44
+
45
+ .serverItem {
46
+ padding: 16px;
47
+ border-radius: 8px;
48
+ background-color: var(--editorWidget-background);
49
+ border: 1px solid var(--border-color);
50
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
51
+ transition: all 0.2s ease;
52
+
53
+ &:hover {
54
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
55
+ border-color: var(--focusBorder);
56
+ }
57
+ }
58
+
59
+ .serverHeader {
60
+ display: flex;
61
+ justify-content: space-between;
62
+ align-items: center;
63
+ margin-bottom: 12px;
64
+ }
65
+
66
+ .serverTitleRow {
67
+ display: flex;
68
+ align-items: center;
69
+ gap: 8px;
70
+ }
71
+
72
+ .serverName {
73
+ margin: 0;
74
+ font-size: 14px;
75
+ font-weight: 500;
76
+ }
77
+
78
+ .serverStatus,
79
+ .serverType {
80
+ font-size: 12px;
81
+ padding: 2px 8px;
82
+ border-radius: 12px;
83
+ font-weight: 500;
84
+ display: inline-flex;
85
+ align-items: center;
86
+ }
87
+
88
+ .serverType {
89
+ background-color: var(--editor-background);
90
+ color: var(--descriptionForeground);
91
+ }
92
+
93
+ .running {
94
+ background-color: var(--notification-info-background);
95
+ color: var(--notification-info-foreground);
96
+ }
97
+
98
+ .stopped {
99
+ background-color: var(--notification-error-background);
100
+ color: var(--notification-error-foreground);
101
+ }
102
+
103
+ .serverActions {
104
+ display: flex;
105
+ gap: 4px;
106
+ }
107
+
108
+ .iconButton {
109
+ padding: 4px;
110
+ border: none;
111
+ background: none;
112
+ color: var(--icon-foreground);
113
+ cursor: pointer;
114
+ border-radius: 4px;
115
+
116
+ &:hover {
117
+ background-color: var(--list-hover-background);
118
+ }
119
+ }
120
+
121
+ .serverDetail {
122
+ margin-top: 12px;
123
+ padding: 12px;
124
+ border-radius: 6px;
125
+ background-color: var(--editor-background);
126
+ font-size: 13px;
127
+
128
+ &:not(:last-child) {
129
+ margin-bottom: 8px;
130
+ }
131
+ }
132
+
133
+ .detailRow {
134
+ display: flex;
135
+ gap: 8px;
136
+ margin-bottom: 4px;
137
+ align-items: center;
138
+
139
+ &:last-child {
140
+ margin-bottom: 0;
141
+ }
142
+ }
143
+
144
+ .detailLabel {
145
+ color: var(--descriptionForeground);
146
+ min-width: 70px;
147
+ height: 24px;
148
+ display: flex;
149
+ align-items: center;
150
+ }
151
+
152
+ .detailContent {
153
+ color: var(--foreground);
154
+ word-break: break-all;
155
+ flex: 1;
156
+ background-color: var(--editor-background);
157
+ padding: 4px 8px;
158
+ border-radius: 4px;
159
+ font-family: var(--monaco-monospace-font);
160
+ min-height: 24px;
161
+ display: flex;
162
+ align-items: center;
163
+ gap: 8px;
164
+ flex-wrap: wrap;
165
+ }
166
+
167
+ .toolTag {
168
+ display: inline-flex;
169
+ align-items: center;
170
+ padding: 2px 8px;
171
+ background-color: var(--editorWidget-background);
172
+ color: var(--button-secondary-foreground);
173
+ border-radius: 12px;
174
+ font-size: 12px;
175
+ font-weight: 500;
176
+ transition: all 0.2s ease;
177
+ border: 1px solid var(--border-color);
178
+ }