@opensumi/ide-ai-native 3.7.2-next-1739859371.0 → 3.7.2-next-1739945875.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/ai-core.contribution.d.ts +3 -0
- package/lib/browser/ai-core.contribution.d.ts.map +1 -1
- package/lib/browser/ai-core.contribution.js +68 -2
- package/lib/browser/ai-core.contribution.js.map +1 -1
- package/lib/browser/chat/chat-model.d.ts +2 -2
- package/lib/browser/chat/chat-model.d.ts.map +1 -1
- package/lib/browser/chat/chat-model.js +16 -5
- package/lib/browser/chat/chat-model.js.map +1 -1
- package/lib/browser/chat/chat-proxy.service.d.ts +4 -0
- package/lib/browser/chat/chat-proxy.service.d.ts.map +1 -1
- package/lib/browser/chat/chat-proxy.service.js +43 -0
- package/lib/browser/chat/chat-proxy.service.js.map +1 -1
- package/lib/browser/chat/chat.view.d.ts.map +1 -1
- package/lib/browser/chat/chat.view.js +29 -2
- package/lib/browser/chat/chat.view.js.map +1 -1
- package/lib/browser/components/ChatContext/ContextSelector.d.ts +12 -0
- package/lib/browser/components/ChatContext/ContextSelector.d.ts.map +1 -0
- package/lib/browser/components/ChatContext/ContextSelector.js +113 -0
- package/lib/browser/components/ChatContext/ContextSelector.js.map +1 -0
- package/lib/browser/components/ChatContext/index.d.ts +4 -0
- package/lib/browser/components/ChatContext/index.d.ts.map +1 -0
- package/lib/browser/components/ChatContext/index.js +84 -0
- package/lib/browser/components/ChatContext/index.js.map +1 -0
- package/lib/browser/components/ChatContext/style.module.less +189 -0
- package/lib/browser/components/ChatInput.d.ts.map +1 -1
- package/lib/browser/components/ChatInput.js.map +1 -1
- package/lib/browser/components/ChatReply.d.ts.map +1 -1
- package/lib/browser/components/ChatReply.js +25 -0
- package/lib/browser/components/ChatReply.js.map +1 -1
- package/lib/browser/components/ChatToolRender.d.ts +6 -0
- package/lib/browser/components/ChatToolRender.d.ts.map +1 -0
- package/lib/browser/components/ChatToolRender.js +53 -0
- package/lib/browser/components/ChatToolRender.js.map +1 -0
- package/lib/browser/components/ChatToolRender.module.less +86 -0
- package/lib/browser/components/components.module.less +32 -31
- package/lib/browser/components/utils.d.ts +2 -2
- package/lib/browser/context/llm-context.contribution.d.ts +7 -0
- package/lib/browser/context/llm-context.contribution.d.ts.map +1 -0
- package/lib/browser/context/llm-context.contribution.js +21 -0
- package/lib/browser/context/llm-context.contribution.js.map +1 -0
- package/lib/browser/context/llm-context.service.d.ts +24 -0
- package/lib/browser/context/llm-context.service.d.ts.map +1 -0
- package/lib/browser/context/llm-context.service.js +136 -0
- package/lib/browser/context/llm-context.service.js.map +1 -0
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.d.ts +2 -2
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.d.ts.map +1 -1
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js.map +1 -1
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.d.ts +4 -0
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.d.ts.map +1 -1
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.js +7 -0
- package/lib/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.js.map +1 -1
- package/lib/browser/index.d.ts +11 -3
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +56 -3
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/mcp/mcp-server-proxy.service.d.ts +25 -0
- package/lib/browser/mcp/mcp-server-proxy.service.d.ts.map +1 -0
- package/lib/browser/mcp/mcp-server-proxy.service.js +56 -0
- package/lib/browser/mcp/mcp-server-proxy.service.js.map +1 -0
- package/lib/browser/mcp/mcp-server.feature.registry.d.ts +16 -0
- package/lib/browser/mcp/mcp-server.feature.registry.d.ts.map +1 -0
- package/lib/browser/mcp/mcp-server.feature.registry.js +53 -0
- package/lib/browser/mcp/mcp-server.feature.registry.js.map +1 -0
- package/lib/browser/mcp/mcp-tools-dialog.module.less +44 -0
- package/lib/browser/mcp/mcp-tools-dialog.view.d.ts +8 -0
- package/lib/browser/mcp/mcp-tools-dialog.view.d.ts.map +1 -0
- package/lib/browser/mcp/mcp-tools-dialog.view.js +16 -0
- package/lib/browser/mcp/mcp-tools-dialog.view.js.map +1 -0
- package/lib/browser/mcp/tools/createNewFileWithText.d.ts +9 -0
- package/lib/browser/mcp/tools/createNewFileWithText.d.ts.map +1 -0
- package/lib/browser/mcp/tools/createNewFileWithText.js +83 -0
- package/lib/browser/mcp/tools/createNewFileWithText.js.map +1 -0
- package/lib/browser/mcp/tools/findFilesByNameSubstring.d.ts +9 -0
- package/lib/browser/mcp/tools/findFilesByNameSubstring.d.ts.map +1 -0
- package/lib/browser/mcp/tools/findFilesByNameSubstring.js +92 -0
- package/lib/browser/mcp/tools/findFilesByNameSubstring.js.map +1 -0
- package/lib/browser/mcp/tools/getCurrentFilePath.d.ts +8 -0
- package/lib/browser/mcp/tools/getCurrentFilePath.d.ts.map +1 -0
- package/lib/browser/mcp/tools/getCurrentFilePath.js +49 -0
- package/lib/browser/mcp/tools/getCurrentFilePath.js.map +1 -0
- package/lib/browser/mcp/tools/getDiagnosticsByPath.d.ts +10 -0
- package/lib/browser/mcp/tools/getDiagnosticsByPath.d.ts.map +1 -0
- package/lib/browser/mcp/tools/getDiagnosticsByPath.js +119 -0
- package/lib/browser/mcp/tools/getDiagnosticsByPath.js.map +1 -0
- package/lib/browser/mcp/tools/getFileTextByPath.d.ts +9 -0
- package/lib/browser/mcp/tools/getFileTextByPath.d.ts.map +1 -0
- package/lib/browser/mcp/tools/getFileTextByPath.js +97 -0
- package/lib/browser/mcp/tools/getFileTextByPath.js.map +1 -0
- package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.d.ts +11 -0
- package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.d.ts.map +1 -0
- package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.js +119 -0
- package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.js.map +1 -0
- package/lib/browser/mcp/tools/getOpenEditorFileText.d.ts +8 -0
- package/lib/browser/mcp/tools/getOpenEditorFileText.d.ts.map +1 -0
- package/lib/browser/mcp/tools/getOpenEditorFileText.js +50 -0
- package/lib/browser/mcp/tools/getOpenEditorFileText.js.map +1 -0
- package/lib/browser/mcp/tools/getSelectedText.d.ts +8 -0
- package/lib/browser/mcp/tools/getSelectedText.d.ts.map +1 -0
- package/lib/browser/mcp/tools/getSelectedText.js +57 -0
- package/lib/browser/mcp/tools/getSelectedText.js.map +1 -0
- package/lib/browser/mcp/tools/handlers/ListDir.d.ts +21 -0
- package/lib/browser/mcp/tools/handlers/ListDir.d.ts.map +1 -0
- package/lib/browser/mcp/tools/handlers/ListDir.js +112 -0
- package/lib/browser/mcp/tools/handlers/ListDir.js.map +1 -0
- package/lib/browser/mcp/tools/handlers/ReadFile.d.ts +47 -0
- package/lib/browser/mcp/tools/handlers/ReadFile.d.ts.map +1 -0
- package/lib/browser/mcp/tools/handlers/ReadFile.js +147 -0
- package/lib/browser/mcp/tools/handlers/ReadFile.js.map +1 -0
- package/lib/browser/mcp/tools/listDir.d.ts +8 -0
- package/lib/browser/mcp/tools/listDir.d.ts.map +1 -0
- package/lib/browser/mcp/tools/listDir.js +65 -0
- package/lib/browser/mcp/tools/listDir.js.map +1 -0
- package/lib/browser/mcp/tools/readFile.d.ts +8 -0
- package/lib/browser/mcp/tools/readFile.d.ts.map +1 -0
- package/lib/browser/mcp/tools/readFile.js +82 -0
- package/lib/browser/mcp/tools/readFile.js.map +1 -0
- package/lib/browser/mcp/tools/replaceOpenEditorFile.d.ts +8 -0
- package/lib/browser/mcp/tools/replaceOpenEditorFile.d.ts.map +1 -0
- package/lib/browser/mcp/tools/replaceOpenEditorFile.js +79 -0
- package/lib/browser/mcp/tools/replaceOpenEditorFile.js.map +1 -0
- package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.d.ts +8 -0
- package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.d.ts.map +1 -0
- package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.js +84 -0
- package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.js.map +1 -0
- package/lib/browser/mcp/tools/runTerminalCmd.d.ts +18 -0
- package/lib/browser/mcp/tools/runTerminalCmd.d.ts.map +1 -0
- package/lib/browser/mcp/tools/runTerminalCmd.js +96 -0
- package/lib/browser/mcp/tools/runTerminalCmd.js.map +1 -0
- package/lib/browser/preferences/schema.d.ts.map +1 -1
- package/lib/browser/preferences/schema.js +60 -0
- package/lib/browser/preferences/schema.js.map +1 -1
- package/lib/browser/types.d.ts +64 -3
- package/lib/browser/types.d.ts.map +1 -1
- package/lib/browser/types.js +5 -1
- package/lib/browser/types.js.map +1 -1
- package/lib/browser/widget/inline-chat/inline-chat-editor.controller.js +1 -1
- package/lib/browser/widget/inline-chat/inline-chat-editor.controller.js.map +1 -1
- package/lib/browser/widget/inline-diff/inline-diff.controller.d.ts.map +1 -1
- package/lib/browser/widget/inline-input/inline-input.controller.d.ts.map +1 -1
- package/lib/common/index.d.ts +9 -0
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +4 -1
- package/lib/common/index.js.map +1 -1
- package/lib/common/llm-context.d.ts +37 -0
- package/lib/common/llm-context.d.ts.map +1 -0
- package/lib/common/llm-context.js +5 -0
- package/lib/common/llm-context.js.map +1 -0
- package/lib/common/mcp-server-manager.d.ts +40 -0
- package/lib/common/mcp-server-manager.d.ts.map +1 -0
- package/lib/common/mcp-server-manager.js +6 -0
- package/lib/common/mcp-server-manager.js.map +1 -0
- package/lib/common/tool-invocation-registry.d.ts +91 -0
- package/lib/common/tool-invocation-registry.d.ts.map +1 -0
- package/lib/common/tool-invocation-registry.js +90 -0
- package/lib/common/tool-invocation-registry.js.map +1 -0
- package/lib/common/types.d.ts +17 -0
- package/lib/common/types.d.ts.map +1 -1
- package/lib/node/anthropic/anthropic-language-model.d.ts +9 -0
- package/lib/node/anthropic/anthropic-language-model.d.ts.map +1 -0
- package/lib/node/anthropic/anthropic-language-model.js +26 -0
- package/lib/node/anthropic/anthropic-language-model.js.map +1 -0
- package/lib/node/base-language-model.d.ts +14 -0
- package/lib/node/base-language-model.d.ts.map +1 -0
- package/lib/node/base-language-model.js +136 -0
- package/lib/node/base-language-model.js.map +1 -0
- package/lib/node/deepseek/deepseek-language-model.d.ts +9 -0
- package/lib/node/deepseek/deepseek-language-model.d.ts.map +1 -0
- package/lib/node/deepseek/deepseek-language-model.js +26 -0
- package/lib/node/deepseek/deepseek-language-model.js.map +1 -0
- package/lib/node/index.d.ts.map +1 -1
- package/lib/node/index.js +19 -0
- package/lib/node/index.js.map +1 -1
- package/lib/node/mcp/sumi-mcp-server.d.ts +91 -0
- package/lib/node/mcp/sumi-mcp-server.d.ts.map +1 -0
- package/lib/node/mcp/sumi-mcp-server.js +172 -0
- package/lib/node/mcp/sumi-mcp-server.js.map +1 -0
- package/lib/node/mcp-server-manager-impl.d.ts +27 -0
- package/lib/node/mcp-server-manager-impl.d.ts.map +1 -0
- package/lib/node/mcp-server-manager-impl.js +127 -0
- package/lib/node/mcp-server-manager-impl.js.map +1 -0
- package/lib/node/mcp-server.d.ts +207 -0
- package/lib/node/mcp-server.d.ts.map +1 -0
- package/lib/node/mcp-server.js +91 -0
- package/lib/node/mcp-server.js.map +1 -0
- package/lib/node/openai/openai-language-model.d.ts +9 -0
- package/lib/node/openai/openai-language-model.d.ts.map +1 -0
- package/lib/node/openai/openai-language-model.js +29 -0
- package/lib/node/openai/openai-language-model.js.map +1 -0
- package/package.json +34 -22
- package/src/browser/ai-core.contribution.ts +77 -1
- package/src/browser/chat/chat-model.ts +24 -6
- package/src/browser/chat/chat-proxy.service.ts +42 -0
- package/src/browser/chat/chat.view.tsx +59 -6
- package/src/browser/components/ChatContext/ContextSelector.tsx +177 -0
- package/src/browser/components/ChatContext/index.tsx +135 -0
- package/src/browser/components/ChatContext/style.module.less +189 -0
- package/src/browser/components/ChatInput.tsx +1 -0
- package/src/browser/components/ChatReply.tsx +32 -0
- package/src/browser/components/ChatToolRender.module.less +86 -0
- package/src/browser/components/ChatToolRender.tsx +77 -0
- package/src/browser/components/components.module.less +32 -31
- package/src/browser/context/llm-context.contribution.ts +14 -0
- package/src/browser/context/llm-context.service.ts +156 -0
- package/src/browser/contrib/intelligent-completions/intelligent-completions.controller.ts +2 -3
- package/src/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.ts +11 -0
- package/src/browser/index.ts +68 -4
- package/src/browser/mcp/mcp-server-proxy.service.ts +53 -0
- package/src/browser/mcp/mcp-server.feature.registry.ts +54 -0
- package/src/browser/mcp/mcp-tools-dialog.module.less +44 -0
- package/src/browser/mcp/mcp-tools-dialog.view.tsx +24 -0
- package/src/browser/mcp/tools/createNewFileWithText.ts +83 -0
- package/src/browser/mcp/tools/findFilesByNameSubstring.ts +93 -0
- package/src/browser/mcp/tools/getCurrentFilePath.ts +49 -0
- package/src/browser/mcp/tools/getDiagnosticsByPath.ts +123 -0
- package/src/browser/mcp/tools/getFileTextByPath.ts +97 -0
- package/src/browser/mcp/tools/getOpenEditorFileDiagnostics.ts +121 -0
- package/src/browser/mcp/tools/getOpenEditorFileText.ts +50 -0
- package/src/browser/mcp/tools/getSelectedText.ts +57 -0
- package/src/browser/mcp/tools/handlers/ListDir.ts +117 -0
- package/src/browser/mcp/tools/handlers/ReadFile.ts +174 -0
- package/src/browser/mcp/tools/listDir.ts +66 -0
- package/src/browser/mcp/tools/readFile.ts +82 -0
- package/src/browser/mcp/tools/replaceOpenEditorFile.ts +80 -0
- package/src/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.ts +91 -0
- package/src/browser/mcp/tools/runTerminalCmd.ts +107 -0
- package/src/browser/preferences/schema.ts +60 -0
- package/src/browser/types.ts +92 -3
- package/src/browser/widget/inline-chat/inline-chat-editor.controller.ts +1 -1
- package/src/browser/widget/inline-diff/inline-diff.controller.ts +1 -1
- package/src/browser/widget/inline-input/inline-input.controller.ts +1 -1
- package/src/common/index.ts +14 -0
- package/src/common/llm-context.ts +41 -0
- package/src/common/mcp-server-manager.ts +46 -0
- package/src/common/tool-invocation-registry.ts +170 -0
- package/src/common/types.ts +22 -0
- package/src/node/anthropic/anthropic-language-model.ts +25 -0
- package/src/node/base-language-model.ts +163 -0
- package/src/node/deepseek/deepseek-language-model.ts +25 -0
- package/src/node/index.ts +21 -0
- package/src/node/mcp/sumi-mcp-server.ts +197 -0
- package/src/node/mcp-server-manager-impl.ts +148 -0
- package/src/node/mcp-server.ts +126 -0
- package/src/node/openai/openai-language-model.ts +25 -0
package/src/browser/types.ts
CHANGED
|
@@ -13,11 +13,20 @@ import {
|
|
|
13
13
|
MaybePromise,
|
|
14
14
|
MergeConflictEditorMode,
|
|
15
15
|
} from '@opensumi/ide-core-common';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
ICodeEditor,
|
|
18
|
+
IRange,
|
|
19
|
+
ISelection,
|
|
20
|
+
ITextModel,
|
|
21
|
+
InlineEditProvider,
|
|
22
|
+
NewSymbolNamesProvider,
|
|
23
|
+
Position,
|
|
24
|
+
} from '@opensumi/ide-monaco';
|
|
17
25
|
import { SumiReadableStream } from '@opensumi/ide-utils/lib/stream';
|
|
18
26
|
import { IMarker } from '@opensumi/monaco-editor-core/esm/vs/platform/markers/common/markers';
|
|
19
27
|
|
|
20
28
|
import { IChatWelcomeMessageContent, ISampleQuestions, ITerminalCommandSuggestionDesc } from '../common';
|
|
29
|
+
import { SerializedContext } from '../common/llm-context';
|
|
21
30
|
|
|
22
31
|
import {
|
|
23
32
|
ICodeEditsContextBean,
|
|
@@ -226,14 +235,39 @@ export type ICodeEditsProvider = (
|
|
|
226
235
|
token: CancellationToken,
|
|
227
236
|
) => MaybePromise<ICodeEditsResult | undefined>;
|
|
228
237
|
|
|
238
|
+
export type IIntelligentInlineEditProvider = (
|
|
239
|
+
editor: ICodeEditor,
|
|
240
|
+
position: IPosition,
|
|
241
|
+
contextBean: IAICompletionOption,
|
|
242
|
+
token: CancellationToken,
|
|
243
|
+
) => MaybePromise<IIntelligentCompletionsResult>;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Interface for registering intelligent completion providers and code edits providers.
|
|
247
|
+
*/
|
|
229
248
|
export interface IIntelligentCompletionsRegistry {
|
|
230
249
|
/**
|
|
231
|
-
*
|
|
250
|
+
* Registers an intelligent completion provider.
|
|
251
|
+
* @deprecated Use the `registerInlineCompletionsProvider` method instead.
|
|
252
|
+
* @param provider - The intelligent completion provider to register.
|
|
232
253
|
*/
|
|
233
254
|
registerIntelligentCompletionProvider(provider: IIntelligentCompletionProvider): void;
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Registers an inline completions provider.
|
|
258
|
+
* @param provider - The intelligent completion provider to register.
|
|
259
|
+
*/
|
|
234
260
|
registerInlineCompletionsProvider(provider: IIntelligentCompletionProvider): void;
|
|
261
|
+
|
|
235
262
|
/**
|
|
236
|
-
*
|
|
263
|
+
* Registers an inline edit provider.
|
|
264
|
+
* @param provider The inline edit provider to register.
|
|
265
|
+
*/
|
|
266
|
+
registerInlineEditProvider(provider: InlineEditProvider): void;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Registers a code edits provider.
|
|
270
|
+
* @param provider - The code edits provider to register.
|
|
237
271
|
*/
|
|
238
272
|
registerCodeEditsProvider(provider: ICodeEditsProvider): void;
|
|
239
273
|
}
|
|
@@ -292,6 +326,51 @@ export interface AINativeCoreContribution {
|
|
|
292
326
|
* proposed api
|
|
293
327
|
*/
|
|
294
328
|
registerIntelligentCompletionFeature?(registry: IIntelligentCompletionsRegistry): void;
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* 注册 Agent 模式下的 chat prompt provider
|
|
332
|
+
* @param provider
|
|
333
|
+
*/
|
|
334
|
+
registerChatAgentPromptProvider?(): void;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// MCP Server 的 贡献点
|
|
338
|
+
export const MCPServerContribution = Symbol('MCPServerContribution');
|
|
339
|
+
|
|
340
|
+
export const TokenMCPServerRegistry = Symbol('TokenMCPServerRegistry');
|
|
341
|
+
|
|
342
|
+
export interface MCPServerContribution {
|
|
343
|
+
registerMCPServer(registry: IMCPServerRegistry): void;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export interface MCPLogger {
|
|
347
|
+
appendLine(message: string): void;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export interface MCPToolDefinition {
|
|
351
|
+
name: string;
|
|
352
|
+
description: string;
|
|
353
|
+
inputSchema: any; // JSON Schema
|
|
354
|
+
handler: (
|
|
355
|
+
args: any,
|
|
356
|
+
logger: MCPLogger,
|
|
357
|
+
) => Promise<{
|
|
358
|
+
content: { type: string; text: string }[];
|
|
359
|
+
isError?: boolean;
|
|
360
|
+
}>;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export interface IMCPServerRegistry {
|
|
364
|
+
registerMCPTool(tool: MCPToolDefinition): void;
|
|
365
|
+
getMCPTools(): MCPToolDefinition[];
|
|
366
|
+
callMCPTool(
|
|
367
|
+
name: string,
|
|
368
|
+
args: any,
|
|
369
|
+
): Promise<{
|
|
370
|
+
content: { type: string; text: string }[];
|
|
371
|
+
isError?: boolean;
|
|
372
|
+
}>;
|
|
373
|
+
// 后续支持其他 MCP 功能
|
|
295
374
|
}
|
|
296
375
|
|
|
297
376
|
export interface IChatComponentConfig {
|
|
@@ -326,3 +405,13 @@ export interface IAIMiddleware {
|
|
|
326
405
|
provideInlineCompletions?: IProvideInlineCompletionsSignature;
|
|
327
406
|
};
|
|
328
407
|
}
|
|
408
|
+
|
|
409
|
+
export const ChatAgentPromptProvider = Symbol('ChatAgentPromptProvider');
|
|
410
|
+
|
|
411
|
+
export interface ChatAgentPromptProvider {
|
|
412
|
+
/**
|
|
413
|
+
* 提供上下文提示
|
|
414
|
+
* @param context 上下文
|
|
415
|
+
*/
|
|
416
|
+
provideContextPrompt(context: SerializedContext, userMessage: string): MaybePromise<string>;
|
|
417
|
+
}
|
|
@@ -222,7 +222,7 @@ export class InlineChatEditorController extends BaseAIMonacoEditorController {
|
|
|
222
222
|
|
|
223
223
|
protected async showInlineChat(monacoEditor: monaco.ICodeEditor): Promise<void> {
|
|
224
224
|
// 调试状态下禁用 inline chat。影响调试体验
|
|
225
|
-
const inDebugMode = this.contextKeyService.
|
|
225
|
+
const inDebugMode = this.contextKeyService.getContextKeyValue(CONTEXT_IN_DEBUG_MODE_KEY);
|
|
226
226
|
if (inDebugMode) {
|
|
227
227
|
return;
|
|
228
228
|
}
|
|
@@ -51,7 +51,7 @@ export class InlineDiffController extends BaseAIMonacoEditorController {
|
|
|
51
51
|
|
|
52
52
|
private previewerStore: Map<string, IInlineDiffPreviewer>;
|
|
53
53
|
private currentPreviewer: ISettableObservable<IInlineDiffPreviewer | undefined>;
|
|
54
|
-
private modelChangeObs: IObservable<monaco.editor.ITextModel
|
|
54
|
+
private modelChangeObs: IObservable<monaco.editor.ITextModel>;
|
|
55
55
|
|
|
56
56
|
mount(): IDisposable {
|
|
57
57
|
this.previewerStore = new Map();
|
|
@@ -67,7 +67,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {
|
|
|
67
67
|
private aiNativeContextKey: AINativeContextKey;
|
|
68
68
|
|
|
69
69
|
private inputValue: ISettableObservable<string>;
|
|
70
|
-
private modelChangeObs: IObservable<monaco.editor.ITextModel
|
|
70
|
+
private modelChangeObs: IObservable<monaco.editor.ITextModel>;
|
|
71
71
|
private inlineInputWidgetStore: Map<
|
|
72
72
|
string,
|
|
73
73
|
InlineInputWidgetStoreInEmptyLine | InlineInputWidgetStoreInSelection | null
|
package/src/common/index.ts
CHANGED
|
@@ -16,6 +16,9 @@ import { IChatMessage } from '@opensumi/ide-core-common/lib/types/ai-native';
|
|
|
16
16
|
import { DESIGN_MENUBAR_CONTAINER_VIEW_ID } from '@opensumi/ide-design/lib/common/constants';
|
|
17
17
|
import { IPosition, ITextModel, InlineCompletionContext } from '@opensumi/ide-monaco/lib/common';
|
|
18
18
|
|
|
19
|
+
import { MCPServerDescription } from './mcp-server-manager';
|
|
20
|
+
import { MCPTool } from './types';
|
|
21
|
+
|
|
19
22
|
export const IAINativeService = Symbol('IAINativeService');
|
|
20
23
|
|
|
21
24
|
/**
|
|
@@ -116,6 +119,17 @@ export const IChatAgentService = Symbol('IChatAgentService');
|
|
|
116
119
|
|
|
117
120
|
export const ChatProxyServiceToken = Symbol('ChatProxyServiceToken');
|
|
118
121
|
|
|
122
|
+
// 暴露给 Node.js 层,使其可以感知 Opensumi 注册的 MCP 能力
|
|
123
|
+
export const TokenMCPServerProxyService = Symbol('TokenMCPServerProxyService');
|
|
124
|
+
|
|
125
|
+
export interface ISumiMCPServerBackend {
|
|
126
|
+
initBuiltinMCPServer(): void;
|
|
127
|
+
initExternalMCPServers(servers: MCPServerDescription[]): void;
|
|
128
|
+
getAllMCPTools(): Promise<MCPTool[]>;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export const SumiMCPServerProxyServicePath = 'SumiMCPServerProxyServicePath';
|
|
132
|
+
|
|
119
133
|
export interface IChatAgentService {
|
|
120
134
|
readonly onDidChangeAgents: Event<void>;
|
|
121
135
|
readonly onDidSendMessage: Event<IChatProgress>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Event, URI } from '@opensumi/ide-core-common/lib/utils';
|
|
2
|
+
|
|
3
|
+
export interface LLMContextService {
|
|
4
|
+
startAutoCollection(): void;
|
|
5
|
+
|
|
6
|
+
stopAutoCollection(): void;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 添加文件到 context 中
|
|
10
|
+
*/
|
|
11
|
+
addFileToContext(uri: URI, selection?: [number, number], isManual?: boolean): void;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 清除上下文
|
|
15
|
+
*/
|
|
16
|
+
cleanFileContext(): void;
|
|
17
|
+
|
|
18
|
+
onDidContextFilesChangeEvent: Event<FileContext[]>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 从 context 中移除文件
|
|
22
|
+
* @param uri URI
|
|
23
|
+
*/
|
|
24
|
+
removeFileFromContext(uri: URI): void;
|
|
25
|
+
|
|
26
|
+
/** 导出为可序列化格式 */
|
|
27
|
+
serialize(): SerializedContext;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface FileContext {
|
|
31
|
+
uri: URI;
|
|
32
|
+
selection?: [number, number];
|
|
33
|
+
isManual: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const LLMContextServiceToken = Symbol('LLMContextService');
|
|
37
|
+
|
|
38
|
+
export interface SerializedContext {
|
|
39
|
+
recentlyViewFiles: string[];
|
|
40
|
+
attachedFiles: Array<{ content: string; lineErrors: string[]; path: string; language: string }>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
+
|
|
3
|
+
export interface MCPServerManager {
|
|
4
|
+
callTool(serverName: string, toolName: string, arg_string: string): ReturnType<Client['callTool']>;
|
|
5
|
+
removeServer(name: string): void;
|
|
6
|
+
addOrUpdateServer(description: MCPServerDescription): void;
|
|
7
|
+
// invoke in node.js only
|
|
8
|
+
addOrUpdateServerDirectly(server: any): void;
|
|
9
|
+
initBuiltinServer(builtinMCPServer: any): void;
|
|
10
|
+
getTools(serverName: string): ReturnType<Client['listTools']>;
|
|
11
|
+
getServerNames(): Promise<string[]>;
|
|
12
|
+
startServer(serverName: string): Promise<void>;
|
|
13
|
+
stopServer(serverName: string): Promise<void>;
|
|
14
|
+
getStartedServers(): Promise<string[]>;
|
|
15
|
+
registerTools(serverName: string): Promise<void>;
|
|
16
|
+
addExternalMCPServers(servers: MCPServerDescription[]): void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type MCPTool = Awaited<ReturnType<MCPServerManager['getTools']>>['tools'][number];
|
|
20
|
+
|
|
21
|
+
export type MCPToolParameter = Awaited<ReturnType<MCPServerManager['getTools']>>['tools'][number]['inputSchema'];
|
|
22
|
+
|
|
23
|
+
export interface MCPServerDescription {
|
|
24
|
+
/**
|
|
25
|
+
* The unique name of the MCP server.
|
|
26
|
+
*/
|
|
27
|
+
name: string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The command to execute the MCP server.
|
|
31
|
+
*/
|
|
32
|
+
command: string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* An array of arguments to pass to the command.
|
|
36
|
+
*/
|
|
37
|
+
args?: string[];
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Optional environment variables to set when starting the server.
|
|
41
|
+
*/
|
|
42
|
+
env?: { [key: string]: string };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const MCPServerManager = Symbol('MCPServerManager');
|
|
46
|
+
export const MCPServerManagerPath = 'ServicesMCPServerManager';
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
import { Injectable } from '@opensumi/di';
|
|
4
|
+
|
|
5
|
+
import { MCPToolParameter } from './mcp-server-manager';
|
|
6
|
+
|
|
7
|
+
export const ToolParameterSchema = z.object({
|
|
8
|
+
type: z.enum(['string', 'number', 'boolean', 'object', 'array']),
|
|
9
|
+
description: z.string().optional(),
|
|
10
|
+
enum: z.array(z.any()).optional(),
|
|
11
|
+
items: z.lazy(() => ToolParameterSchema).optional(),
|
|
12
|
+
properties: z.record(z.lazy(() => ToolParameterSchema)).optional(),
|
|
13
|
+
required: z.array(z.string()).optional(),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export type ToolParameter = z.infer<typeof ToolParameterSchema>;
|
|
17
|
+
|
|
18
|
+
export interface ToolRequest {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
parameters?: any;
|
|
22
|
+
description?: string;
|
|
23
|
+
handler: (arg_string: string) => Promise<any>;
|
|
24
|
+
providerName?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export namespace ToolRequest {
|
|
28
|
+
export function isToolParameter(obj: unknown): obj is ToolParameter {
|
|
29
|
+
return ToolParameterSchema.safeParse(obj).success;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const ToolInvocationRegistry = Symbol('ToolInvocationRegistry');
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 为 Agent 提供的所有可用函数调用的注册表
|
|
37
|
+
*/
|
|
38
|
+
export interface ToolInvocationRegistry {
|
|
39
|
+
/**
|
|
40
|
+
* 在注册表中注册一个工具
|
|
41
|
+
*
|
|
42
|
+
* @param tool - 要注册的 `ToolRequest` 对象
|
|
43
|
+
*/
|
|
44
|
+
registerTool(tool: ToolRequest): void;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 从注册表中获取特定的 `ToolRequest`
|
|
48
|
+
*
|
|
49
|
+
* @param toolId - 要获取的工具的唯一标识符
|
|
50
|
+
* @returns 对应提供的工具 ID 的 `ToolRequest` 对象,
|
|
51
|
+
* 如果在注册表中找不到该工具,则返回 `undefined`
|
|
52
|
+
*/
|
|
53
|
+
getFunction(toolId: string): ToolRequest | undefined;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 从注册表中获取多个 `ToolRequest`
|
|
57
|
+
*
|
|
58
|
+
* @param toolIds - 要获取的工具 ID 列表
|
|
59
|
+
* @returns 指定工具 ID 的 `ToolRequest` 对象数组
|
|
60
|
+
* 如果找不到某个工具 ID,将在返回的数组中跳过该工具
|
|
61
|
+
*/
|
|
62
|
+
getFunctions(...toolIds: string[]): ToolRequest[];
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 获取当前注册表中的所有 `ToolRequest`
|
|
66
|
+
*
|
|
67
|
+
* @returns 注册表中所有 `ToolRequest` 对象的数组
|
|
68
|
+
*/
|
|
69
|
+
getAllFunctions(): ToolRequest[];
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 注销特定工具提供者的所有工具
|
|
73
|
+
*
|
|
74
|
+
* @param providerName - 要移除其工具的工具提供者名称(在 `ToolRequest` 中指定)
|
|
75
|
+
*/
|
|
76
|
+
unregisterAllTools(providerName: string): void;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const ToolProvider = Symbol('ToolProvider');
|
|
80
|
+
export interface ToolProvider {
|
|
81
|
+
getTool(): ToolRequest;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export class ToolInvocationRegistryImpl implements ToolInvocationRegistry {
|
|
85
|
+
private tools: Map<string, ToolRequest> = new Map<string, ToolRequest>();
|
|
86
|
+
|
|
87
|
+
unregisterAllTools(providerName: string): void {
|
|
88
|
+
const toolsToRemove: string[] = [];
|
|
89
|
+
for (const [id, tool] of this.tools.entries()) {
|
|
90
|
+
if (tool.providerName === providerName) {
|
|
91
|
+
toolsToRemove.push(id);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
toolsToRemove.forEach((id) => this.tools.delete(id));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
getAllFunctions(): ToolRequest[] {
|
|
98
|
+
return Array.from(this.tools.values());
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
registerTool(tool: ToolRequest): void {
|
|
102
|
+
if (this.tools.has(tool.id)) {
|
|
103
|
+
// TODO: 使用适当的日志机制
|
|
104
|
+
this.tools.set(tool.id, tool);
|
|
105
|
+
} else {
|
|
106
|
+
this.tools.set(tool.id, tool);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
getFunction(toolId: string): ToolRequest | undefined {
|
|
111
|
+
return this.tools.get(toolId);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
getFunctions(...toolIds: string[]): ToolRequest[] {
|
|
115
|
+
const tools: ToolRequest[] = toolIds.map((toolId) => {
|
|
116
|
+
const tool = this.tools.get(toolId);
|
|
117
|
+
if (tool) {
|
|
118
|
+
return tool;
|
|
119
|
+
} else {
|
|
120
|
+
throw new Error(`找不到 ID 为 ${toolId} 的函数`);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
return tools;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* 管理多个 ToolInvocationRegistry 实例的管理器,每个实例与一个 clientId 关联
|
|
129
|
+
*/
|
|
130
|
+
export interface IToolInvocationRegistryManager {
|
|
131
|
+
/**
|
|
132
|
+
* 获取或创建特定 clientId 的 ToolInvocationRegistry
|
|
133
|
+
*/
|
|
134
|
+
getRegistry(clientId: string): ToolInvocationRegistry;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 移除特定 clientId 的 ToolInvocationRegistry
|
|
138
|
+
*/
|
|
139
|
+
removeRegistry(clientId: string): void;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* 检查特定 clientId 是否存在对应的注册表
|
|
143
|
+
*/
|
|
144
|
+
hasRegistry(clientId: string): boolean;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export const ToolInvocationRegistryManager = Symbol('ToolInvocationRegistryManager');
|
|
148
|
+
|
|
149
|
+
@Injectable()
|
|
150
|
+
export class ToolInvocationRegistryManagerImpl implements IToolInvocationRegistryManager {
|
|
151
|
+
private registries: Map<string, ToolInvocationRegistry> = new Map();
|
|
152
|
+
|
|
153
|
+
getRegistry(clientId: string): ToolInvocationRegistry {
|
|
154
|
+
let registry = this.registries.get(clientId);
|
|
155
|
+
if (!registry) {
|
|
156
|
+
registry = new ToolInvocationRegistryImpl();
|
|
157
|
+
this.registries.set(clientId, registry);
|
|
158
|
+
}
|
|
159
|
+
return registry;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
removeRegistry(clientId: string): void {
|
|
163
|
+
this.registries.delete(clientId);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
hasRegistry(clientId: string): boolean {
|
|
167
|
+
return this.registries.has(clientId);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
package/src/common/types.ts
CHANGED
|
@@ -18,3 +18,25 @@ export interface INearestCodeBlock {
|
|
|
18
18
|
offset: number;
|
|
19
19
|
type?: NearestCodeBlockType;
|
|
20
20
|
}
|
|
21
|
+
|
|
22
|
+
// SUMI MCP Server 网页部分暴露给 Node.js 部分的能力
|
|
23
|
+
export interface IMCPServerProxyService {
|
|
24
|
+
$callMCPTool(
|
|
25
|
+
name: string,
|
|
26
|
+
args: any,
|
|
27
|
+
): Promise<{
|
|
28
|
+
content: { type: string; text: string }[];
|
|
29
|
+
isError?: boolean;
|
|
30
|
+
}>;
|
|
31
|
+
// 获取 browser 层注册的 MCP 工具列表 (Browser tab 维度)
|
|
32
|
+
$getMCPTools(): Promise<MCPTool[]>;
|
|
33
|
+
// 通知前端 MCP 服务注册表发生了变化
|
|
34
|
+
$updateMCPServers(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface MCPTool {
|
|
38
|
+
name: string;
|
|
39
|
+
description: string;
|
|
40
|
+
inputSchema: any;
|
|
41
|
+
providerName: string;
|
|
42
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AnthropicProvider, createAnthropic } from '@ai-sdk/anthropic';
|
|
2
|
+
|
|
3
|
+
import { Injectable } from '@opensumi/di';
|
|
4
|
+
import { IAIBackServiceOption } from '@opensumi/ide-core-common';
|
|
5
|
+
import { AINativeSettingSectionsId } from '@opensumi/ide-core-common/lib/settings/ai-native';
|
|
6
|
+
|
|
7
|
+
import { BaseLanguageModel } from '../base-language-model';
|
|
8
|
+
|
|
9
|
+
export const AnthropicModelIdentifier = Symbol('AnthropicModelIdentifier');
|
|
10
|
+
|
|
11
|
+
@Injectable()
|
|
12
|
+
export class AnthropicModel extends BaseLanguageModel {
|
|
13
|
+
protected initializeProvider(options: IAIBackServiceOption): AnthropicProvider {
|
|
14
|
+
const apiKey = options.apiKey;
|
|
15
|
+
if (!apiKey) {
|
|
16
|
+
throw new Error(`Please provide Anthropic API Key in preferences (${AINativeSettingSectionsId.AnthropicApiKey})`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return createAnthropic({ apiKey });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
protected getModelIdentifier(provider: AnthropicProvider) {
|
|
23
|
+
return provider('claude-3-5-sonnet-20241022');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { CoreMessage, jsonSchema, streamText, tool } from 'ai';
|
|
2
|
+
|
|
3
|
+
import { Autowired, Injectable } from '@opensumi/di';
|
|
4
|
+
import { ChatMessageRole, IAIBackServiceOption, IChatMessage } from '@opensumi/ide-core-common';
|
|
5
|
+
import { ChatReadableStream } from '@opensumi/ide-core-node';
|
|
6
|
+
import { CancellationToken } from '@opensumi/ide-utils';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
IToolInvocationRegistryManager,
|
|
10
|
+
ToolInvocationRegistryManager,
|
|
11
|
+
ToolRequest,
|
|
12
|
+
} from '../common/tool-invocation-registry';
|
|
13
|
+
|
|
14
|
+
@Injectable()
|
|
15
|
+
export abstract class BaseLanguageModel {
|
|
16
|
+
@Autowired(ToolInvocationRegistryManager)
|
|
17
|
+
protected readonly toolInvocationRegistryManager: IToolInvocationRegistryManager;
|
|
18
|
+
|
|
19
|
+
protected abstract initializeProvider(options: IAIBackServiceOption): any;
|
|
20
|
+
|
|
21
|
+
private convertChatMessageRole(role: ChatMessageRole) {
|
|
22
|
+
switch (role) {
|
|
23
|
+
case ChatMessageRole.System:
|
|
24
|
+
return 'system';
|
|
25
|
+
case ChatMessageRole.User:
|
|
26
|
+
return 'user';
|
|
27
|
+
case ChatMessageRole.Assistant:
|
|
28
|
+
return 'assistant';
|
|
29
|
+
case ChatMessageRole.Function:
|
|
30
|
+
return 'tool';
|
|
31
|
+
default:
|
|
32
|
+
return 'user';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async request(
|
|
37
|
+
request: string,
|
|
38
|
+
chatReadableStream: ChatReadableStream,
|
|
39
|
+
options: IAIBackServiceOption,
|
|
40
|
+
cancellationToken?: CancellationToken,
|
|
41
|
+
): Promise<any> {
|
|
42
|
+
const provider = this.initializeProvider(options);
|
|
43
|
+
const clientId = options.clientId;
|
|
44
|
+
if (!clientId) {
|
|
45
|
+
throw new Error('clientId is required');
|
|
46
|
+
}
|
|
47
|
+
const registry = this.toolInvocationRegistryManager.getRegistry(clientId);
|
|
48
|
+
const allFunctions = registry.getAllFunctions();
|
|
49
|
+
return this.handleStreamingRequest(
|
|
50
|
+
provider,
|
|
51
|
+
request,
|
|
52
|
+
allFunctions,
|
|
53
|
+
chatReadableStream,
|
|
54
|
+
options.history || [],
|
|
55
|
+
cancellationToken,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private convertToolRequestToAITool(toolRequest: ToolRequest) {
|
|
60
|
+
return tool({
|
|
61
|
+
description: toolRequest.description || '',
|
|
62
|
+
// TODO 这里应该是 z.object 而不是 JSON Schema
|
|
63
|
+
parameters: jsonSchema(toolRequest.parameters),
|
|
64
|
+
execute: async (args: any) => await toolRequest.handler(JSON.stringify(args)),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
protected abstract getModelIdentifier(provider: any): any;
|
|
69
|
+
|
|
70
|
+
protected async handleStreamingRequest(
|
|
71
|
+
provider: any,
|
|
72
|
+
request: string,
|
|
73
|
+
tools: ToolRequest[],
|
|
74
|
+
chatReadableStream: ChatReadableStream,
|
|
75
|
+
history: IChatMessage[] = [],
|
|
76
|
+
cancellationToken?: CancellationToken,
|
|
77
|
+
): Promise<any> {
|
|
78
|
+
try {
|
|
79
|
+
const aiTools = Object.fromEntries(tools.map((tool) => [tool.name, this.convertToolRequestToAITool(tool)]));
|
|
80
|
+
|
|
81
|
+
const abortController = new AbortController();
|
|
82
|
+
if (cancellationToken) {
|
|
83
|
+
cancellationToken.onCancellationRequested(() => {
|
|
84
|
+
abortController.abort();
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const messages: CoreMessage[] = [
|
|
89
|
+
...history.map((msg) => ({
|
|
90
|
+
role: this.convertChatMessageRole(msg.role) as any, // 这个 SDK 包里的类型不太好完全对应,
|
|
91
|
+
content: msg.content,
|
|
92
|
+
})),
|
|
93
|
+
{ role: 'user', content: request },
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
const stream = await streamText({
|
|
97
|
+
model: this.getModelIdentifier(provider),
|
|
98
|
+
maxTokens: 4096,
|
|
99
|
+
tools: aiTools,
|
|
100
|
+
messages,
|
|
101
|
+
abortSignal: abortController.signal,
|
|
102
|
+
experimental_toolCallStreaming: true,
|
|
103
|
+
maxSteps: 12,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
for await (const chunk of stream.fullStream) {
|
|
107
|
+
if (chunk.type === 'text-delta') {
|
|
108
|
+
chatReadableStream.emitData({ kind: 'content', content: chunk.textDelta });
|
|
109
|
+
} else if (chunk.type === 'tool-call') {
|
|
110
|
+
chatReadableStream.emitData({
|
|
111
|
+
kind: 'toolCall',
|
|
112
|
+
content: {
|
|
113
|
+
id: chunk.toolCallId || Date.now().toString(),
|
|
114
|
+
type: 'function',
|
|
115
|
+
function: { name: chunk.toolName, arguments: JSON.stringify(chunk.args) },
|
|
116
|
+
state: 'complete',
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
} else if (chunk.type === 'tool-call-streaming-start') {
|
|
120
|
+
chatReadableStream.emitData({
|
|
121
|
+
kind: 'toolCall',
|
|
122
|
+
content: {
|
|
123
|
+
id: chunk.toolCallId,
|
|
124
|
+
type: 'function',
|
|
125
|
+
function: { name: chunk.toolName },
|
|
126
|
+
state: 'streaming-start',
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
} else if (chunk.type === 'tool-call-delta') {
|
|
130
|
+
chatReadableStream.emitData({
|
|
131
|
+
kind: 'toolCall',
|
|
132
|
+
content: {
|
|
133
|
+
id: chunk.toolCallId,
|
|
134
|
+
type: 'function',
|
|
135
|
+
function: { name: chunk.toolName, arguments: chunk.argsTextDelta },
|
|
136
|
+
state: 'streaming',
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
} else if (chunk.type === 'tool-result') {
|
|
140
|
+
chatReadableStream.emitData({
|
|
141
|
+
kind: 'toolCall',
|
|
142
|
+
content: {
|
|
143
|
+
id: chunk.toolCallId,
|
|
144
|
+
type: 'function',
|
|
145
|
+
function: { name: chunk.toolName, arguments: JSON.stringify(chunk.args) },
|
|
146
|
+
result: chunk.result,
|
|
147
|
+
state: 'result',
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
} else if (chunk.type === 'error') {
|
|
151
|
+
chatReadableStream.emitError(new Error(chunk.error as string));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
chatReadableStream.end();
|
|
156
|
+
} catch (error) {
|
|
157
|
+
// Use a logger service in production instead of console
|
|
158
|
+
chatReadableStream.emitError(error);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return chatReadableStream;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { DeepSeekProvider, createDeepSeek } from '@ai-sdk/deepseek';
|
|
2
|
+
|
|
3
|
+
import { Injectable } from '@opensumi/di';
|
|
4
|
+
import { IAIBackServiceOption } from '@opensumi/ide-core-common';
|
|
5
|
+
import { AINativeSettingSectionsId } from '@opensumi/ide-core-common/lib/settings/ai-native';
|
|
6
|
+
|
|
7
|
+
import { BaseLanguageModel } from '../base-language-model';
|
|
8
|
+
|
|
9
|
+
export const DeepSeekModelIdentifier = Symbol('DeepSeekModelIdentifier');
|
|
10
|
+
|
|
11
|
+
@Injectable()
|
|
12
|
+
export class DeepSeekModel extends BaseLanguageModel {
|
|
13
|
+
protected initializeProvider(options: IAIBackServiceOption): DeepSeekProvider {
|
|
14
|
+
const apiKey = options.apiKey;
|
|
15
|
+
if (!apiKey) {
|
|
16
|
+
throw new Error(`Please provide Deepseek API Key in preferences (${AINativeSettingSectionsId.DeepseekApiKey})`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return createDeepSeek({ apiKey });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
protected getModelIdentifier(provider: DeepSeekProvider) {
|
|
23
|
+
return provider('deepseek-chat');
|
|
24
|
+
}
|
|
25
|
+
}
|