import { AI_CODE_EDITS_COMMANDS } from '@opensumi/ide-core-browser/lib/ai-native/command'; import { CommandService } from '@opensumi/ide-core-common'; import { InlineCompletionContext, InlineCompletionTriggerKind, InlineCompletionsProvider, Position, Range, } from '@opensumi/ide-monaco'; import { IObservable, asyncTransaction, constObservable, derived, transaction, } from '@opensumi/ide-monaco/lib/common/observable'; import { equalsIfDefined, itemEquals } from '@opensumi/monaco-editor-core/esm/vs/base/common/equals'; import { LanguageFeatureRegistry } from '@opensumi/monaco-editor-core/esm/vs/editor/common/languageFeatureRegistry'; import { InlineCompletionsController } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/controller/inlineCompletionsController'; import { InlineCompletionsModel } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel'; import { InlineCompletionsSource, UpToDateInlineCompletions, } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsSource'; import { InlineCompletionProviderResult, provideInlineCompletions, } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions'; import { CodeEditsResultValue, ICodeEdit, ICodeEditsResult } from '../index'; import { BaseCodeEditsView } from './base'; /** * copy from @opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions */ class UpdateRequest { constructor( public readonly position: Position, public readonly context: InlineCompletionContext, public readonly versionId: number, ) {} public satisfies(other: UpdateRequest): boolean { return ( this.position.equals(other.position) && equalsIfDefined(this.context.selectedSuggestionInfo, other.context.selectedSuggestionInfo, itemEquals()) && (other.context.triggerKind === InlineCompletionTriggerKind.Automatic || this.context.triggerKind === InlineCompletionTriggerKind.Explicit) && this.versionId === other.versionId ); } public get isExplicitRequest() { return this.context.triggerKind === InlineCompletionTriggerKind.Explicit; } } export class DefaultCodeEditsView extends BaseCodeEditsView { private monacoCompletionsModel: IObservable = derived(this, (reader) => { const inlineCompletionsController = InlineCompletionsController.get(this.monacoEditor); if (!inlineCompletionsController) { return; } return inlineCompletionsController.model.read(reader); }); private monacoCompletionsSource: IObservable = derived(this, (reader) => { const model = this.monacoCompletionsModel.read(reader); if (!model) { return; } const source = model['_source'] as InlineCompletionsSource; return source; }); public render(completionModel: CodeEditsResultValue): void { const source = this.monacoCompletionsSource.get(); if (!source) { return; } const position = this.editorObs.positions.get()?.[0]; if (!position) { return; } const model = this.editorObs.model.get(); if (!model) { return; } const originalContent = model.getValueInRange(completionModel.firstRange); // edits 的内容与原内容一样就不展示 if (originalContent === completionModel.firstText) { return; } asyncTransaction(async (tx) => { const versionId = this.editorObs.versionId.get(); const context: InlineCompletionContext = { triggerKind: InlineCompletionTriggerKind.Automatic, selectedSuggestionInfo: undefined, includeInlineCompletions: false, includeInlineEdits: true, }; const request = new UpdateRequest(position, context, versionId!); const inlineEdits: InlineCompletionProviderResult = await provideInlineCompletions( { all: () => [ { provideInlineCompletions: () => {}, provideInlineEditsForRange(model, range, context, token) { return completionModel; }, freeInlineCompletions: () => [], handleRejection: (completions, item) => { const commandService: CommandService = this.injector.get(CommandService); commandService.executeCommand(AI_CODE_EDITS_COMMANDS.DISCARD.id); }, } as InlineCompletionsProvider>, ], } as unknown as LanguageFeatureRegistry, Range.lift(completionModel.firstRange), model, context, ); const completions = new UpToDateInlineCompletions( inlineEdits, request, model, this.editorObs.versionId, constObservable(4000), ); source.inlineCompletions.set(completions, tx); source.loading.set(false, tx); }); } public accept(): void { const model = this.monacoCompletionsModel.get(); model?.accept(); } public discard(): void { const model = this.monacoCompletionsModel.get(); transaction((tx) => { model?.stop('explicitCancel', tx); }); } public hide(): void { this.monacoCompletionsSource.get()?.inlineCompletions?.set(undefined, undefined); } }