Skip to content

Commit b4dd6d7

Browse files
authored
feat: support intelligent completions always visible (#4039)
1 parent acc8715 commit b4dd6d7

3 files changed

Lines changed: 42 additions & 11 deletions

File tree

packages/ai-native/src/browser/contrib/inline-completions/inline-completions.handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
Sequencer,
1212
runWhenIdle,
1313
} from '@opensumi/ide-core-common';
14-
import { EditorSelectionChangeEvent, IEditor } from '@opensumi/ide-editor/lib/browser';
14+
import { EditorSelectionChangeEvent } from '@opensumi/ide-editor/lib/browser';
1515
import { ICodeEditor, InlineCompletions, Position, Range } from '@opensumi/ide-monaco';
1616
import { monacoApi } from '@opensumi/ide-monaco/lib/browser/monaco-api';
1717
import { InlineCompletionContextKeys } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/inlineCompletionContextKeys';

packages/ai-native/src/browser/contrib/intelligent-completions/intelligent-completions.controller.ts

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ import {
55
IAICompletionOption,
66
IDisposable,
77
IntelligentCompletionsRegistryToken,
8+
isDefined,
89
runWhenIdle,
910
} from '@opensumi/ide-core-common';
1011
import { ICodeEditor, ICursorPositionChangedEvent, IRange, ITextModel, Range } from '@opensumi/ide-monaco';
1112
import { empty } from '@opensumi/ide-utils/lib/strings';
13+
import { IObservable, autorun } from '@opensumi/monaco-editor-core/esm/vs/base/common/observable';
14+
import { GhostTextWidget } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/ghostTextWidget';
15+
import { InlineCompletionsController } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsController';
1216

1317
import { AINativeContextKey } from '../../contextkey/ai-native.contextkey.service';
1418
import { REWRITE_DECORATION_INLINE_ADD, RewriteWidget } from '../../widget/rewrite/rewrite-widget';
@@ -25,6 +29,7 @@ import { IIntelligentCompletionsResult } from './intelligent-completions';
2529
import { IntelligentCompletionsRegistry } from './intelligent-completions.feature.registry';
2630
import { MultiLineDecorationModel } from './multi-line.decoration';
2731

32+
2833
export class IntelligentCompletionsController extends BaseAIMonacoEditorController {
2934
public static readonly ID = 'editor.contrib.ai.intelligent.completions';
3035

@@ -36,20 +41,22 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
3641
return this.injector.get(IntelligentCompletionsRegistryToken);
3742
}
3843

39-
private multiLineDecorationModel: MultiLineDecorationModel;
40-
private additionsDeletionsDecorationModel: AdditionsDeletionsDecorationModel;
41-
42-
private aiNativeContextKey: AINativeContextKey;
43-
4444
private get model(): ITextModel {
4545
return this.monacoEditor.getModel()!;
4646
}
4747

48+
private multiLineDecorationModel: MultiLineDecorationModel;
49+
private additionsDeletionsDecorationModel: AdditionsDeletionsDecorationModel;
50+
private aiNativeContextKey: AINativeContextKey;
4851
private rewriteWidget: RewriteWidget | null;
4952
private whenMultiLineEditsVisibleDisposable: Disposable;
5053

5154
public mount(): IDisposable {
5255
this.whenMultiLineEditsVisibleDisposable = new Disposable();
56+
this.multiLineDecorationModel = new MultiLineDecorationModel(this.monacoEditor);
57+
this.additionsDeletionsDecorationModel = new AdditionsDeletionsDecorationModel(this.monacoEditor);
58+
this.aiNativeContextKey = this.injector.get(AINativeContextKey, [this.monacoEditor.contextKeyService]);
59+
5360
return this.registerFeature(this.monacoEditor);
5461
}
5562

@@ -66,6 +73,12 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
6673
return;
6774
}
6875

76+
// 如果上一次补全结果还在,则不重复请求
77+
const isVisible = this.aiNativeContextKey.multiLineEditsIsVisible.get();
78+
if (isVisible) {
79+
return;
80+
}
81+
6982
const position = this.monacoEditor.getPosition()!;
7083
const intelligentCompletionModel = await provider(this.monacoEditor, position, bean, this.token);
7184

@@ -81,7 +94,7 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
8194
}
8295

8396
private applyInlineDecorations(completionModel: IIntelligentCompletionsResult) {
84-
const { items } = completionModel;
97+
const { items, alwaysVisible } = completionModel;
8598

8699
const position = this.monacoEditor.getPosition()!;
87100
const model = this.monacoEditor.getModel();
@@ -160,6 +173,27 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
160173
}
161174
}),
162175
);
176+
177+
if (isDefined(alwaysVisible) && alwaysVisible) {
178+
const inlineCompletionsController = InlineCompletionsController.get(this.monacoEditor);
179+
if (inlineCompletionsController) {
180+
/**
181+
* https://github.com/microsoft/vscode/blob/1.88.1/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsController.ts#L67
182+
* 当 _ghostTextWidgets 发生变化时,说明是由下拉补全引起的 “内联补全” 字符出现,此时需要将其销毁
183+
*/
184+
this.whenMultiLineEditsVisibleDisposable.addDispose(
185+
autorun((reader) => {
186+
const ghostTextWidgetsObservable = inlineCompletionsController['_ghostTextWidgets'] as IObservable<
187+
readonly GhostTextWidget[]
188+
>;
189+
ghostTextWidgetsObservable.read(reader);
190+
191+
const ghostTextWidget = ghostTextWidgetsObservable.get()[0];
192+
ghostTextWidget?.dispose();
193+
}),
194+
);
195+
}
196+
}
163197
}
164198

165199
private async renderRewriteWidget(
@@ -241,10 +275,6 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
241275
}
242276

243277
public registerFeature(monacoEditor: ICodeEditor): IDisposable {
244-
this.multiLineDecorationModel = new MultiLineDecorationModel(monacoEditor);
245-
this.additionsDeletionsDecorationModel = new AdditionsDeletionsDecorationModel(monacoEditor);
246-
this.aiNativeContextKey = this.injector.get(AINativeContextKey, [monacoEditor.contextKeyService]);
247-
248278
this.addDispose(
249279
Event.any<any>(
250280
monacoEditor.onDidChangeCursorPosition,

packages/startup/entry/sample-modules/ai-native/ai-native.contribution.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ export class AINativeContribution implements AINativeCoreContribution {
494494
},
495495
],
496496
enableMultiLine: true,
497+
alwaysVisible: true,
497498
};
498499
} catch (error) {
499500
if (error.name === 'AbortError') {

0 commit comments

Comments
 (0)