Skip to content

Commit

Permalink
feat: 实现 Code Edits (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
hacke2 authored Nov 11, 2024
1 parent 17c4a92 commit cca5fdb
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 3 deletions.
51 changes: 48 additions & 3 deletions src/ai/browser/ai-native.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
});
}
}
38 changes: 38 additions & 0 deletions src/ai/browser/prompt.ts
Original file line number Diff line number Diff line change
@@ -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) => {
Expand Down Expand Up @@ -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 })))}
请根据上述错误信息,直接提供修复后的代码,不需要解释
`;
};

0 comments on commit cca5fdb

Please sign in to comment.