@opensumi/ide-ai-native 3.9.1-next-1747791726.0 → 3.9.1-next-1747829468.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 (35) hide show
  1. package/lib/browser/chat/apply.service.d.ts +0 -3
  2. package/lib/browser/chat/apply.service.d.ts.map +1 -1
  3. package/lib/browser/chat/apply.service.js +0 -47
  4. package/lib/browser/chat/apply.service.js.map +1 -1
  5. package/lib/browser/components/utils.d.ts +2 -2
  6. package/lib/browser/mcp/base-apply.service.d.ts +2 -3
  7. package/lib/browser/mcp/base-apply.service.d.ts.map +1 -1
  8. package/lib/browser/mcp/base-apply.service.js +5 -23
  9. package/lib/browser/mcp/base-apply.service.js.map +1 -1
  10. package/lib/browser/mcp/mcp-server.feature.registry.d.ts.map +1 -1
  11. package/lib/browser/mcp/mcp-server.feature.registry.js +7 -1
  12. package/lib/browser/mcp/mcp-server.feature.registry.js.map +1 -1
  13. package/lib/browser/mcp/tools/fileSearch.d.ts.map +1 -1
  14. package/lib/browser/mcp/tools/fileSearch.js +9 -5
  15. package/lib/browser/mcp/tools/fileSearch.js.map +1 -1
  16. package/lib/browser/mcp/tools/grepSearch.d.ts.map +1 -1
  17. package/lib/browser/mcp/tools/grepSearch.js +9 -5
  18. package/lib/browser/mcp/tools/grepSearch.js.map +1 -1
  19. package/lib/browser/mcp/tools/listDir.d.ts.map +1 -1
  20. package/lib/browser/mcp/tools/listDir.js +19 -15
  21. package/lib/browser/mcp/tools/listDir.js.map +1 -1
  22. package/lib/node/mcp-server.sse.d.ts +187 -1
  23. package/lib/node/mcp-server.sse.d.ts.map +1 -1
  24. package/lib/node/mcp-server.sse.js +2 -2
  25. package/lib/node/mcp-server.sse.js.map +1 -1
  26. package/lib/node/mcp-server.stdio.d.ts +187 -1
  27. package/lib/node/mcp-server.stdio.d.ts.map +1 -1
  28. package/package.json +25 -25
  29. package/src/browser/chat/apply.service.ts +1 -62
  30. package/src/browser/mcp/base-apply.service.ts +9 -30
  31. package/src/browser/mcp/mcp-server.feature.registry.ts +6 -1
  32. package/src/browser/mcp/tools/fileSearch.ts +8 -5
  33. package/src/browser/mcp/tools/grepSearch.ts +8 -5
  34. package/src/browser/mcp/tools/listDir.ts +15 -12
  35. package/src/node/mcp-server.sse.ts +1 -2
@@ -1,16 +1,6 @@
1
1
  import { Autowired, Injectable } from '@opensumi/di';
2
- import {
3
- AIBackSerivcePath,
4
- CancellationTokenSource,
5
- IAIBackService,
6
- IChatProgress,
7
- URI,
8
- path,
9
- } from '@opensumi/ide-core-browser';
10
- import { CommandService } from '@opensumi/ide-core-common/lib/command';
2
+ import { AIBackSerivcePath, IAIBackService, IChatProgress, URI, path } from '@opensumi/ide-core-browser';
11
3
  import { IEditorDocumentModelService } from '@opensumi/ide-editor/lib/browser';
12
- import { CodeAction, CodeActionContext, CodeActionTriggerType, ICodeEditor } from '@opensumi/ide-monaco';
13
- import { languageFeaturesService } from '@opensumi/ide-monaco/lib/browser/monaco-api/languages';
14
4
  import { SumiReadableStream } from '@opensumi/ide-utils/lib/stream';
15
5
  import { Range } from '@opensumi/monaco-editor-core';
16
6
 
@@ -20,59 +10,8 @@ import { BaseApplyService } from '../mcp/base-apply.service';
20
10
 
21
11
  import { ChatProxyService } from './chat-proxy.service';
22
12
 
23
- /**
24
- * Filter code actions to only apply batch fixes
25
- * Skip individual fixes as consecutive WorkspaceEdits may interfere with each other
26
- * @param codeAction The code action to check
27
- * @returns boolean indicating if the action is auto-fixable
28
- */
29
- function isAutoFixable(codeAction: CodeAction): boolean {
30
- return codeAction.title.toLowerCase().includes('all');
31
- }
32
-
33
13
  @Injectable()
34
14
  export class ApplyService extends BaseApplyService {
35
- @Autowired(CommandService)
36
- private commandService: CommandService;
37
-
38
- protected async postApplyHandler(editor: ICodeEditor): Promise<void> {
39
- const model = editor.getModel();
40
- if (!model) {
41
- return Promise.resolve();
42
- }
43
- const providers = languageFeaturesService.codeActionProvider.ordered(model);
44
-
45
- if (!providers) {
46
- return Promise.resolve();
47
- }
48
-
49
- const [provider] = providers;
50
- const range = model.getFullModelRange();
51
- const context: CodeActionContext = {
52
- trigger: CodeActionTriggerType.Auto,
53
- };
54
- const ts = new CancellationTokenSource();
55
- const actionList = await provider.provideCodeActions(model, range, context, ts.token);
56
-
57
- // 提取所有可修复的代码操作
58
- const fixableActions = actionList?.actions.filter(isAutoFixable) || [];
59
-
60
- if (fixableActions.length === 0) {
61
- return Promise.resolve();
62
- }
63
-
64
- // 执行所有可修复的代码操作
65
- await Promise.allSettled(
66
- fixableActions.map(async (action) => {
67
- if (action.command) {
68
- try {
69
- await this.commandService.executeCommand(action.command.id, ...(action.command.arguments || []));
70
- } catch (err) {}
71
- }
72
- }),
73
- );
74
- }
75
-
76
15
  @Autowired(IEditorDocumentModelService)
77
16
  private readonly modelService: IEditorDocumentModelService;
78
17
 
@@ -63,8 +63,6 @@ export abstract class BaseApplyService extends WithEventBus {
63
63
 
64
64
  private currentSessionId?: string;
65
65
 
66
- protected abstract postApplyHandler(editor: ICodeEditor): Promise<void>;
67
-
68
66
  constructor() {
69
67
  super();
70
68
  this.addDispose(
@@ -315,26 +313,10 @@ export abstract class BaseApplyService extends WithEventBus {
315
313
  );
316
314
  codeBlock.updatedCode = res.updatedCode;
317
315
  codeBlock.status = 'pending';
318
-
319
- // apply 结果流式输出完成后,自动尝试修复代码中的 lint 错误
320
- if (this.postApplyHandler && typeof this.postApplyHandler === 'function') {
321
- try {
322
- await this.postApplyHandler(result.group.codeEditor.monacoEditor);
323
- } catch (error) {}
324
- }
325
-
326
- const textModel = result.group.codeEditor.monacoEditor.getModel();
327
- const diagnosticInfos = this.getDiagnosticInfos(textModel!.uri.toString(), res.result?.rangesFromDiffHunk || []);
328
-
329
316
  // 用户实际接受的 apply 结果
330
- if (res.result) {
331
- codeBlock.applyResult = {
332
- diff: res.result?.diff,
333
- diagnosticInfos,
334
- };
335
- }
336
-
317
+ codeBlock.applyResult = res.result;
337
318
  this.updateCodeBlock(codeBlock);
319
+
338
320
  return codeBlock;
339
321
  } catch (err) {
340
322
  codeBlock.status = 'failed';
@@ -354,8 +336,8 @@ export abstract class BaseApplyService extends WithEventBus {
354
336
  codeBlock: CodeBlockData,
355
337
  updatedContentOrStream: string | SumiReadableStream<IChatProgress>,
356
338
  range?: Range,
357
- ): Promise<{ result?: { diff: string; rangesFromDiffHunk: Range[] }; updatedCode: string }> {
358
- const deferred = new Deferred<{ result?: { diff: string; rangesFromDiffHunk: Range[] }; updatedCode: string }>();
339
+ ): Promise<{ result?: { diff: string; diagnosticInfos: IMarker[] }; updatedCode: string }> {
340
+ const deferred = new Deferred<{ result?: { diff: string; diagnosticInfos: IMarker[] }; updatedCode: string }>();
359
341
  const inlineDiffController = InlineDiffController.get(editor)!;
360
342
  range = range || editor.getModel()!.getFullModelRange();
361
343
 
@@ -391,11 +373,7 @@ export abstract class BaseApplyService extends WithEventBus {
391
373
 
392
374
  this.listenPartialEdit(editor.getModel()!, codeBlock).then((result) => {
393
375
  if (result) {
394
- const diagnosticInfos = this.getDiagnosticInfos(editor.getModel()!.uri.toString(), rangesFromDiffHunk);
395
- codeBlock.applyResult = {
396
- diff: result.diff,
397
- diagnosticInfos,
398
- };
376
+ codeBlock.applyResult = result;
399
377
  }
400
378
  this.updateCodeBlock(codeBlock);
401
379
  this.editorService.save(URI.file(path.join(this.appConfig.workspaceDir, codeBlock.relativePath)));
@@ -406,10 +384,11 @@ export abstract class BaseApplyService extends WithEventBus {
406
384
  updatedContent,
407
385
  codeBlock.relativePath,
408
386
  );
387
+ const diagnosticInfos = this.getDiagnosticInfos(editor.getModel()!.uri.toString(), rangesFromDiffHunk);
409
388
  deferred.resolve({
410
389
  result: {
411
390
  diff,
412
- rangesFromDiffHunk,
391
+ diagnosticInfos,
413
392
  },
414
393
  updatedCode: updatedContent,
415
394
  });
@@ -555,7 +534,7 @@ export abstract class BaseApplyService extends WithEventBus {
555
534
  }
556
535
 
557
536
  protected listenPartialEdit(model: ITextModel, codeBlock: CodeBlockData) {
558
- const deferred = new Deferred<{ diff: string; rangesFromDiffHunk: Range[] }>();
537
+ const deferred = new Deferred<{ diff: string; diagnosticInfos: IMarker[] }>();
559
538
  const uriString = model.uri.toString();
560
539
  const toDispose = this.inlineDiffService.onPartialEdit((event) => {
561
540
  if (
@@ -595,7 +574,7 @@ export abstract class BaseApplyService extends WithEventBus {
595
574
  });
596
575
  deferred.resolve({
597
576
  diff,
598
- rangesFromDiffHunk,
577
+ diagnosticInfos,
599
578
  });
600
579
  } else {
601
580
  // 用户全部取消
@@ -44,7 +44,12 @@ export class MCPServerRegistry implements IMCPServerRegistry {
44
44
  }
45
45
 
46
46
  registerMCPTool(tool: MCPToolDefinition): void {
47
- this.tools.push(tool);
47
+ const existingIndex = this.tools.findIndex((t) => t.name === tool.name);
48
+ if (existingIndex !== -1) {
49
+ this.tools[existingIndex] = tool;
50
+ } else {
51
+ this.tools.push(tool);
52
+ }
48
53
  }
49
54
 
50
55
  registerToolComponent(
@@ -80,11 +80,14 @@ export class FileSearchTool implements MCPServerContribution {
80
80
  });
81
81
 
82
82
  const messages = this.chatInternalService.sessionModel.history.getMessages();
83
- this.chatInternalService.sessionModel.history.setMessageAdditional(messages[messages.length - 1].id, {
84
- [args.toolCallId]: {
85
- files,
86
- },
87
- });
83
+ const messageId = messages[messages.length - 1]?.id;
84
+ if (messageId) {
85
+ this.chatInternalService.sessionModel.history.setMessageAdditional(messageId, {
86
+ [args.toolCallId]: {
87
+ files,
88
+ },
89
+ });
90
+ }
88
91
 
89
92
  logger.appendLine(`Found ${files.length} files matching "${args.query}"`);
90
93
 
@@ -111,11 +111,14 @@ export class GrepSearchTool implements MCPServerContribution {
111
111
  }
112
112
  deferred.resolve(results.join('\n\n'));
113
113
  const messages = this.chatInternalService.sessionModel.history.getMessages();
114
- this.chatInternalService.sessionModel.history.setMessageAdditional(messages[messages.length - 1].id, {
115
- [args.toolCallId]: {
116
- files,
117
- },
118
- });
114
+ const messageId = messages[messages.length - 1]?.id;
115
+ if (messageId) {
116
+ this.chatInternalService.sessionModel.history.setMessageAdditional(messageId, {
117
+ [args.toolCallId]: {
118
+ files,
119
+ },
120
+ });
121
+ }
119
122
  });
120
123
  const text = await deferred.promise;
121
124
  return {
@@ -63,18 +63,21 @@ export class ListDirTool implements MCPServerContribution {
63
63
 
64
64
  // 设置消息的附加数据
65
65
  const messages = this.chatInternalService.sessionModel.history.getMessages();
66
- this.chatInternalService.sessionModel.history.setMessageAdditional(messages[messages.length - 1].id, {
67
- [args.toolCallId]: {
68
- files: fileUris,
69
- title: `Listed directory "${args.relativeWorkspacePath}"`,
70
- details: result.files.map((file) => ({
71
- type: file.isDirectory ? 'dir' : 'file',
72
- name: file.name,
73
- info: file.isDirectory ? `${file.numChildren ?? '?'} items` : `${file.size}KB, ${file.numLines} lines`,
74
- lastModified: file.lastModified,
75
- })),
76
- },
77
- });
66
+ const messageId = messages[messages.length - 1]?.id;
67
+ if (messageId) {
68
+ this.chatInternalService.sessionModel.history.setMessageAdditional(messageId, {
69
+ [args.toolCallId]: {
70
+ files: fileUris,
71
+ title: `Listed directory "${args.relativeWorkspacePath}"`,
72
+ details: result.files.map((file) => ({
73
+ type: file.isDirectory ? 'dir' : 'file',
74
+ name: file.name,
75
+ info: file.isDirectory ? `${file.numChildren ?? '?'} items` : `${file.size}KB, ${file.numLines} lines`,
76
+ lastModified: file.lastModified,
77
+ })),
78
+ },
79
+ });
80
+ }
78
81
 
79
82
  logger.appendLine(`Listed ${fileUris.length} files in directory "${args.relativeWorkspacePath}"`);
80
83
 
@@ -1,5 +1,6 @@
1
1
  // have to import with extension since the exports map is ./* -> ./dist/cjs/*
2
2
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
3
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
3
4
  import { EventSource } from 'eventsource';
4
5
 
5
6
  import { ILogger } from '@opensumi/ide-core-common';
@@ -47,8 +48,6 @@ export class SSEMCPServer implements IMCPServer {
47
48
  }
48
49
  this.logger?.log(`Starting server "${this.name}" with url: ${this.url}`);
49
50
 
50
- const SSEClientTransport = (await import('@modelcontextprotocol/sdk/client/sse.js')).SSEClientTransport;
51
-
52
51
  const transport = new SSEClientTransport(new URL(this.url), this.transportOptions);
53
52
 
54
53
  transport.onerror = (error) => {