Skip to content

Commit cea3465

Browse files
committed
Merge branch 'v3.1'
2 parents 584bdd5 + 43ba89b commit cea3465

75 files changed

Lines changed: 306 additions & 259 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
3-
"version": "3.1.1"
3+
"version": "3.1.2"
44
}

packages/addons/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@opensumi/ide-addons",
3-
"version": "3.1.1",
3+
"version": "3.1.2",
44
"files": [
55
"lib",
66
"src"

packages/ai-native/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@opensumi/ide-ai-native",
3-
"version": "3.1.1",
3+
"version": "3.1.2",
44
"files": [
55
"lib",
66
"src"

packages/ai-native/src/browser/ai-core.contribution.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import { IMainLayoutService } from '@opensumi/ide-main-layout';
5353
import { Position } from '@opensumi/ide-monaco';
5454
import { ISettingRegistry, SettingContribution } from '@opensumi/ide-preferences';
5555
import { EditorContributionInstantiation } from '@opensumi/monaco-editor-core/esm/vs/editor/browser/editorExtensions';
56+
import { HideInlineCompletion } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/commands';
5657

5758
import {
5859
AI_CHAT_CONTAINER_ID,
@@ -351,14 +352,19 @@ export class AINativeBrowserContribution
351352
commands.registerCommand(AI_INLINE_COMPLETION_VISIBLE, {
352353
execute: async (visible: boolean) => {
353354
if (!visible) {
354-
await this.commandService.executeCommand('editor.action.inlineSuggest.hide');
355355
this.aiCompletionsService.hideStatusBarItem();
356-
this.aiInlineCompletionsProvider.resetContextKey();
357356
this.aiInlineCompletionsProvider.cancelRequest();
358357
this.aiCompletionsService.setVisibleCompletion(false);
359358
}
360359
},
361360
});
361+
362+
/**
363+
* 当 inline completion 消失时
364+
*/
365+
commands.afterExecuteCommand(HideInlineCompletion.ID, () => {
366+
this.commandService.executeCommand(AI_INLINE_COMPLETION_VISIBLE.id, false);
367+
});
362368
}
363369

364370
registerRenderer(registry: SlotRendererRegistry): void {

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

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
import { Autowired, INJECTOR_TOKEN, Injectable, Injector } from '@opensumi/di';
22
import { PreferenceService } from '@opensumi/ide-core-browser';
33
import { AI_INLINE_COMPLETION_REPORTER } from '@opensumi/ide-core-browser/lib/ai-native/command';
4-
import { AINativeSettingSectionsId, DisposableStore, URI, WithEventBus, sleep, uuid } from '@opensumi/ide-core-common';
4+
import {
5+
AINativeSettingSectionsId,
6+
DisposableStore,
7+
URI,
8+
WithEventBus,
9+
raceCancellation,
10+
sleep,
11+
uuid,
12+
} from '@opensumi/ide-core-common';
513
import { IAICompletionResultModel } from '@opensumi/ide-core-common/lib/types/ai-native';
614
import { AISerivceType, IAIReporter } from '@opensumi/ide-core-common/lib/types/ai-native/reporter';
715
import { IEditor } from '@opensumi/ide-editor';
816
import * as monaco from '@opensumi/ide-monaco';
917

10-
import { AINativeContextKey } from '../../contextkey/ai-native.contextkey.service';
11-
1218
import { DEFAULT_COMPLECTION_MODEL } from './constants';
1319
import { CompletionRequestBean, IInlineCompletionCache, InlineCompletionItem } from './model/competionModel';
1420
import { PromptCache } from './promptCache';
@@ -159,9 +165,6 @@ export class CompletionRequestTask {
159165

160166
// 组装请求参数,向远程发起请求
161167
const completionRequestBean = await this.constructRequestBean(context, token);
162-
if (token.isCancellationRequested) {
163-
return [];
164-
}
165168
if (this.isCancelFlag) {
166169
return [];
167170
}
@@ -171,9 +174,10 @@ export class CompletionRequestTask {
171174

172175
let rs: IAICompletionResultModel | null;
173176
const cacheData = this.promptCache.getCache(completionRequestBean.prompt);
174-
const relationId = this.aiReporter.start(AISerivceType.Completion, { message: AISerivceType.Completion });
175-
this.aiCompletionsService.setLastRelationId(relationId);
177+
const relationId =
178+
cacheData?.relationId || this.aiReporter.start(AISerivceType.Completion, { message: AISerivceType.Completion });
176179

180+
this.aiCompletionsService.setLastRelationId(relationId);
177181
// 如果存在缓存
178182
if (cacheData) {
179183
rs = cacheData;
@@ -200,7 +204,7 @@ export class CompletionRequestTask {
200204
this.aiCompletionsService.setLastSessionId(rs.sessionId);
201205

202206
// 如果是取消直接返回
203-
if ((rs && rs.isCancel) || this.isCancelFlag) {
207+
if ((rs && rs.isCancel) || token.isCancellationRequested || this.isCancelFlag) {
204208
this.aiCompletionsService.reporterEnd(relationId, {
205209
success: true,
206210
replytime: Date.now() - requestStartTime,
@@ -212,7 +216,7 @@ export class CompletionRequestTask {
212216
}
213217

214218
if (rs && rs.codeModelList && rs.codeModelList.length > 0) {
215-
this.promptCache.setCache(completionRequestBean.prompt, rs);
219+
this.promptCache.setCache(completionRequestBean.prompt, { ...rs, relationId });
216220
}
217221
// 返回补全结果为空直接返回
218222
if (rs.codeModelList.length === 0) {
@@ -266,6 +270,7 @@ export class CompletionRequestTask {
266270
position.column + insertText.length + textAfterCursor.length,
267271
),
268272
sessionId: rs.sessionId,
273+
relationId,
269274
command: {
270275
id: AI_INLINE_COMPLETION_REPORTER.id,
271276
title: '',
@@ -323,8 +328,6 @@ export class AIInlineCompletionsProvider extends WithEventBus {
323328
@Autowired(PreferenceService)
324329
private readonly preferenceService: PreferenceService;
325330

326-
private aiNativeContextKey: AINativeContextKey;
327-
328331
/**
329332
* 该补全是否是手动触发
330333
*/
@@ -353,8 +356,6 @@ export class AIInlineCompletionsProvider extends WithEventBus {
353356
}
354357

355358
public mountEditor(editor: IEditor): void {
356-
this.aiNativeContextKey = this.injector.get(AINativeContextKey, [(editor.monacoEditor as any)._contextKeyService]);
357-
358359
this.isManual = false;
359360
this.isDelEvent = false;
360361
this.reqStack = new ReqStack();
@@ -367,10 +368,6 @@ export class AIInlineCompletionsProvider extends WithEventBus {
367368
}
368369
}
369370

370-
resetContextKey() {
371-
this.aiNativeContextKey.inlineCompletionIsTrigger.reset();
372-
}
373-
374371
/**
375372
* 用户触发编辑器后,事件的回调
376373
* @param document
@@ -385,8 +382,6 @@ export class AIInlineCompletionsProvider extends WithEventBus {
385382
context: monaco.languages.InlineCompletionContext,
386383
token: monaco.CancellationToken,
387384
) {
388-
this.aiNativeContextKey.inlineCompletionIsTrigger.set(true);
389-
390385
// bugfix: 修复当鼠标移动到代码补全上会触发一次手势事件,增加防抖,当手势触发后,能够防抖一次
391386
if (context.triggerKind === monaco.InlineCompletionTriggerKind.Automatic) {
392387
if (
@@ -412,20 +407,19 @@ export class AIInlineCompletionsProvider extends WithEventBus {
412407
// 重置防止不触发自动补全事件
413408
this.updateIsManual(false);
414409

415-
// 如果用户已取消
416-
if (token?.isCancellationRequested) {
417-
this.aiCompletionsService.updateStatusBarItem('cancelled ', false);
418-
return undefined;
419-
}
420-
421410
// 放入队列
422411
const requestImp = this.injector.get(CompletionRequestTask, [model, position, token, _isManual]);
423412

424413
this.reqStack.addReq(requestImp);
425414

426415
// 如果是自动补全需要 debounce
427416
if (!_isManual) {
428-
await sleep(this.inlineComletionsDebounceTime);
417+
await raceCancellation(sleep(this.inlineComletionsDebounceTime), token);
418+
}
419+
420+
// 如果用户已取消
421+
if (token?.isCancellationRequested) {
422+
return undefined;
429423
}
430424

431425
const list = await this.reqStack.runReq();

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

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ import debounce from 'lodash/debounce';
22

33
import { Autowired, Injectable } from '@opensumi/di';
44
import { IDisposable } from '@opensumi/ide-core-browser';
5-
import { Disposable, IEventBus, Sequencer } from '@opensumi/ide-core-common';
5+
import { AI_INLINE_COMPLETION_VISIBLE } from '@opensumi/ide-core-browser/lib/ai-native/command';
6+
import { CommandServiceImpl, Disposable, IEventBus, Sequencer, runWhenIdle } from '@opensumi/ide-core-common';
7+
import { CommandRegistry, CommandRegistryImpl, CommandService } from '@opensumi/ide-core-common';
68
import { EditorSelectionChangeEvent, IEditor } from '@opensumi/ide-editor/lib/browser';
9+
import { InlineCompletions, Position, Range } from '@opensumi/ide-monaco';
710
import { monacoApi } from '@opensumi/ide-monaco/lib/browser/monaco-api';
11+
import { InlineCompletionContextKeys } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/inlineCompletionContextKeys';
812

913
import { IAIMiddleware } from '../../types';
1014
import { IAIMonacoContribHandler } from '../base';
@@ -17,12 +21,21 @@ export class InlineCompletionHandler extends IAIMonacoContribHandler {
1721
@Autowired(IEventBus)
1822
private eventBus: IEventBus;
1923

24+
@Autowired(CommandService)
25+
private commandService: CommandServiceImpl;
26+
27+
@Autowired(CommandRegistry)
28+
private commandRegistry: CommandRegistryImpl;
29+
2030
@Autowired(AIInlineCompletionsProvider)
2131
private readonly aiInlineCompletionsProvider: AIInlineCompletionsProvider;
2232

2333
@Autowired(AICompletionsService)
2434
private aiCompletionsService: AICompletionsService;
2535

36+
private sequencer = new Sequencer();
37+
private preDidShowItems: InlineCompletions | undefined;
38+
2639
public registerInlineCompletionFeature(editor: IEditor): IDisposable {
2740
const { monacoEditor } = editor;
2841
// 判断用户是否选择了一块区域或者移动光标 取消掉请补全求
@@ -37,9 +50,6 @@ export class InlineCompletionHandler extends IAIMonacoContribHandler {
3750
if (selection.startLineNumber !== selection.endLineNumber || selection.startColumn !== selection.endColumn) {
3851
this.aiInlineCompletionsProvider.cancelRequest();
3952
}
40-
requestAnimationFrame(() => {
41-
this.aiCompletionsService.setVisibleCompletion(false);
42-
});
4353
};
4454

4555
const debouncedSelectionChange = debounce(selectionChange, 50, {
@@ -68,12 +78,8 @@ export class InlineCompletionHandler extends IAIMonacoContribHandler {
6878
}
6979
}
7080
}),
71-
monacoEditor.onWillChangeModel(() => {
72-
this.aiCompletionsService.hideStatusBarItem();
73-
}),
7481
monacoEditor.onDidBlurEditorText(() => {
75-
this.aiCompletionsService.hideStatusBarItem();
76-
this.aiCompletionsService.setVisibleCompletion(false);
82+
this.commandService.executeCommand(AI_INLINE_COMPLETION_VISIBLE.id, false);
7783
}),
7884
);
7985

@@ -95,13 +101,32 @@ export class InlineCompletionHandler extends IAIMonacoContribHandler {
95101
mountEditor(editor: IEditor) {
96102
const toDispose = new Disposable();
97103
this.aiInlineCompletionsProvider.mountEditor(editor);
98-
toDispose.addDispose(this.aiInlineCompletionsProvider);
104+
99105
toDispose.addDispose(super.mountEditor(editor));
106+
toDispose.addDispose(this.aiInlineCompletionsProvider);
107+
108+
const inlineVisibleKey = new Set([InlineCompletionContextKeys.inlineSuggestionVisible.key]);
109+
toDispose.addDispose(
110+
editor.monacoEditor.contextKeyService.onDidChangeContext((e) => {
111+
// inline completion 真正消失时
112+
if (e.affectsSome(inlineVisibleKey)) {
113+
const inlineSuggestionVisible = InlineCompletionContextKeys.inlineSuggestionVisible.getValue(
114+
editor.monacoEditor.contextKeyService,
115+
);
116+
if (!inlineSuggestionVisible && this.preDidShowItems) {
117+
runWhenIdle(() => {
118+
this.preDidShowItems = undefined;
119+
this.commandService.executeCommand(AI_INLINE_COMPLETION_VISIBLE.id, false);
120+
});
121+
}
122+
}
123+
}),
124+
);
100125
return toDispose;
101126
}
102127

103128
doContribute(): IDisposable {
104-
const sequencer = new Sequencer();
129+
let prePosition: Position | undefined;
105130

106131
return monacoApi.languages.registerInlineCompletionsProvider('*', {
107132
groupId: 'ai-native-inline-completions',
@@ -111,15 +136,34 @@ export class InlineCompletionHandler extends IAIMonacoContribHandler {
111136
return;
112137
}
113138

114-
const list = await sequencer.queue(() =>
139+
let resultList: InlineCompletions;
140+
141+
/**
142+
* 如果新字符在 inline completion 的 ghost text 内,则走缓存,不重新请求
143+
*/
144+
if (this.preDidShowItems) {
145+
if (!prePosition) {
146+
prePosition = position.delta(0, -1);
147+
}
148+
149+
const lineBefore = model.getValueInRange(Range.fromPositions(prePosition, position));
150+
if (this.preDidShowItems.items[0].insertText.toString().startsWith(lineBefore)) {
151+
return this.preDidShowItems;
152+
} else {
153+
prePosition = undefined;
154+
}
155+
}
156+
157+
resultList = await this.sequencer.queue(() =>
115158
this.aiInlineCompletionsProvider.provideInlineCompletionItems(model, position, context, token),
116159
);
117160

118-
return list;
161+
return resultList;
119162
},
120163
freeInlineCompletions() {},
121164
handleItemDidShow: (completions) => {
122165
if (completions.items.length > 0) {
166+
this.preDidShowItems = completions;
123167
this.aiCompletionsService.setVisibleCompletion(true);
124168
}
125169
},

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,5 @@ export interface CompletionResultModelCache {
7878
*/
7979
export interface InlineCompletionItem extends monaco.languages.InlineCompletion {
8080
sessionId: string;
81+
relationId: string;
8182
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export class PromptCache {
1414
@Autowired(IHashCalculateService)
1515
private hashCalculateService: IHashCalculateService;
1616

17-
private cacheMap = new StaleLRUMap<string, IAICompletionResultModel>(15, 10, 60 * 1000);
17+
private cacheMap = new StaleLRUMap<string, IAICompletionResultModel & { relationId: string }>(15, 10, 60 * 1000);
1818

1919
getCache(prompt: string) {
2020
if (!isCacheEnable()) {

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,11 @@ export class AICompletionsService extends Disposable {
106106
}
107107

108108
public async reporterEnd(relationId: string, data: CompletionRT) {
109-
this.aiReporter.end(relationId, {
109+
const reportData = {
110110
...data,
111111
isValid: typeof data.renderingTime === 'number' ? data.renderingTime > 750 : false,
112-
});
112+
};
113+
this.aiReporter.end(relationId, reportData);
113114
}
114115

115116
public setVisibleCompletion(visible: boolean) {

packages/collaboration/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@opensumi/ide-collaboration",
3-
"version": "3.1.1",
3+
"version": "3.1.2",
44
"files": [
55
"lib",
66
"src"

0 commit comments

Comments
 (0)