From cca5fdb7fc2432eae3343bb892f019e87b3701b9 Mon Sep 17 00:00:00 2001 From: hacke2 Date: Mon, 11 Nov 2024 19:29:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=20Code=20Edits=20(#5?= =?UTF-8?q?6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ai/browser/ai-native.contribution.ts | 51 ++++++++++++++++++++++-- src/ai/browser/prompt.ts | 38 ++++++++++++++++++ 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/src/ai/browser/ai-native.contribution.ts b/src/ai/browser/ai-native.contribution.ts index 379e78b..16306b3 100644 --- a/src/ai/browser/ai-native.contribution.ts +++ b/src/ai/browser/ai-native.contribution.ts @@ -8,11 +8,12 @@ import { IAIBackService, CancellationToken, ChatResponse, + ECodeEditsSourceTyping, } from '@opensumi/ide-core-common'; import { ClientAppContribution, Domain, getIcon } from '@opensumi/ide-core-browser'; import { ComponentContribution, ComponentRegistry } from '@opensumi/ide-core-browser/lib/layout'; -import { AINativeCoreContribution, ERunStrategy, IChatFeatureRegistry, IInlineChatFeatureRegistry, IProblemFixContext, IProblemFixProviderRegistry, IRenameCandidatesProviderRegistry, ITerminalProviderRegistry, TChatSlashCommandSend, TerminalSuggestionReadableStream } from '@opensumi/ide-ai-native/lib/browser/types'; -import { ICodeEditor, MarkdownString, NewSymbolNameTag } from '@opensumi/ide-monaco'; +import { AINativeCoreContribution, ERunStrategy, IChatFeatureRegistry, IInlineChatFeatureRegistry, IIntelligentCompletionsRegistry, IProblemFixContext, IProblemFixProviderRegistry, IRenameCandidatesProviderRegistry, ITerminalProviderRegistry, TChatSlashCommandSend, TerminalSuggestionReadableStream } from '@opensumi/ide-ai-native/lib/browser/types'; +import { ICodeEditor, MarkdownString, NewSymbolNameTag, Range } from '@opensumi/ide-monaco'; import { MessageService } from '@opensumi/ide-overlay/lib/browser/message.service'; import { BaseTerminalDetectionLineMatcher, JavaMatcher, MatcherType, NodeMatcher, NPMMatcher, ShellMatcher, TSCMatcher } from '@opensumi/ide-ai-native/lib/browser/contrib/terminal/matcher'; import { ChatService } from '@opensumi/ide-ai-native/lib/browser/chat/chat.api.service'; @@ -22,12 +23,13 @@ import { listenReadable } from '@opensumi/ide-utils/lib/stream'; import { AI_MENU_BAR_LEFT_ACTION, EInlineOperation } from './constants' import { LeftToolbar } from './components/left-toolbar' -import { explainPrompt, testPrompt, optimizePrompt, detectIntentPrompt, RenamePromptManager, terminalCommandSuggestionPrompt } from './prompt' +import { explainPrompt, testPrompt, optimizePrompt, detectIntentPrompt, RenamePromptManager, terminalCommandSuggestionPrompt, codeEditsLintErrorPrompt } from './prompt' import { CommandRender } from './command/command-render' import { AITerminalDebugService } from './ai-terminal-debug.service' import { InlineChatOperationModel } from './inline-chat-operation' import { AICommandService } from './command/command.service' import hiPng from './assets/hi.png' +import { ILinterErrorData } from '@opensumi/ide-ai-native/lib/browser/contrib/intelligent-completions/source/lint-error.source'; @Domain(ComponentContribution, AINativeCoreContribution) export class AINativeContribution implements ComponentContribution, AINativeCoreContribution { @@ -551,4 +553,47 @@ ${editor.getModel()!.getValueInRange(editRange)} }, }); } + + registerIntelligentCompletionFeature(registry: IIntelligentCompletionsRegistry): void { + registry.registerCodeEditsProvider(async (editor, _position, bean, token) => { + const model = editor.getModel(); + if (!model) { + return; + } + + if (bean.typing === ECodeEditsSourceTyping.LinterErrors) { + const errors = (bean.data as ILinterErrorData).errors; + + if (errors.length === 0) { + return; + } + + const lastItem = errors[errors.length - 1]; + const lastRange = lastItem.range; + + const waringRange = Range.fromPositions( + { lineNumber: errors[0].range.startPosition.lineNumber, column: 1 }, + { lineNumber: lastRange.endPosition.lineNumber, column: model!.getLineMaxColumn(lastRange.endPosition.lineNumber) } + ); + + const prompt = codeEditsLintErrorPrompt(model.getValueInRange(waringRange), errors); + const response = await this.aiBackService.request(prompt, {}, token); + + if (response.data) { + const controller = new InlineChatController({ enableCodeblockRender: true }); + const codeData = controller['calculateCodeBlocks'](response.data); + + return { + items: [ + { + insertText: codeData, + range: waringRange + } + ] + }; + } + } + return undefined; + }); + } } diff --git a/src/ai/browser/prompt.ts b/src/ai/browser/prompt.ts index 264ae92..6e1dd6d 100644 --- a/src/ai/browser/prompt.ts +++ b/src/ai/browser/prompt.ts @@ -1,3 +1,4 @@ +import { IMarkerErrorData } from '@opensumi/ide-ai-native/lib/browser/contrib/intelligent-completions/source/lint-error.source'; import { EInlineOperation } from './constants' export const explainPrompt = (language: string, code: string) => { @@ -87,3 +88,40 @@ ${below.slice(0, 500)} return lines; } } + + +export const codeEditsLintErrorPrompt = (text: string, errors: IMarkerErrorData[]) => { + return ` + #Role: 代码领域的 IDE 专家 + + #Profile: + - description: 熟悉各种编程语言并擅长解决由语言服务引起的各种问题,能够快速定位问题并提供解决方案,专注于代码质量和错误修复的专家 + + ##Goals: + - 修复代码中的 error 错误,提升代码质量 + + ##Constrains: + - 仅修改必要的代码以修复错误 + - 保持代码的原始功能和逻辑不变 + - 保持代码的缩进规则不变,这是强规定,你需要检查代码的缩进规则,并保持这个缩进规则 + + ##Skills: + - 熟悉 Java/TypeScript/JavaScript/Python 等语言 + - 能够根据错误信息快速定位问题并提供解决方案 + + ##Workflows: + - 分析提供的代码和错误信息 + - 提供修复步骤和修改后的代码 + + ##CodeSnippet: + - 以下是有问题的代码片段 +\`\`\` +${text} +\`\`\` + + ##LintErrors: + ${JSON.stringify(errors.map(e => ({ message: e.message })))} + + 请根据上述错误信息,直接提供修复后的代码,不需要解释 +`; +};