From 38b747776bb1e67757469f6612c9129ae026bb27 Mon Sep 17 00:00:00 2001 From: Martin Fleck Date: Thu, 31 Oct 2024 10:42:43 +0100 Subject: [PATCH 1/3] [AI] Improve handling of inline code completion - Add preference to turn on/off automatic trigger while editing - Add shortcut for explicit, manual trigger through command --- .../ai-code-completion-frontend-module.ts | 6 +++-- .../browser/ai-code-completion-preference.ts | 7 ++++++ ...-code-frontend-application-contribution.ts | 24 +++++++++++++++---- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/packages/ai-code-completion/src/browser/ai-code-completion-frontend-module.ts b/packages/ai-code-completion/src/browser/ai-code-completion-frontend-module.ts index 7a06ea5f2be97..449a37f15ec52 100644 --- a/packages/ai-code-completion/src/browser/ai-code-completion-frontend-module.ts +++ b/packages/ai-code-completion/src/browser/ai-code-completion-frontend-module.ts @@ -18,7 +18,7 @@ import { ILogger } from '@theia/core'; import { ContainerModule } from '@theia/core/shared/inversify'; import { CodeCompletionAgent, CodeCompletionAgentImpl } from '../common/code-completion-agent'; import { AIFrontendApplicationContribution } from './ai-code-frontend-application-contribution'; -import { FrontendApplicationContribution, PreferenceContribution } from '@theia/core/lib/browser'; +import { FrontendApplicationContribution, KeybindingContribution, PreferenceContribution } from '@theia/core/lib/browser'; import { Agent } from '@theia/ai-core'; import { AICodeCompletionPreferencesSchema } from './ai-code-completion-preference'; import { AICodeInlineCompletionsProvider } from './ai-code-inline-completion-provider'; @@ -32,6 +32,8 @@ export default new ContainerModule(bind => { bind(CodeCompletionAgent).toService(CodeCompletionAgentImpl); bind(Agent).toService(CodeCompletionAgentImpl); bind(AICodeInlineCompletionsProvider).toSelf().inSingletonScope(); - bind(FrontendApplicationContribution).to(AIFrontendApplicationContribution).inSingletonScope(); + bind(AIFrontendApplicationContribution).toSelf().inSingletonScope(); + bind(FrontendApplicationContribution).to(AIFrontendApplicationContribution); + bind(KeybindingContribution).toService(AIFrontendApplicationContribution); bind(PreferenceContribution).toConstantValue({ schema: AICodeCompletionPreferencesSchema }); }); diff --git a/packages/ai-code-completion/src/browser/ai-code-completion-preference.ts b/packages/ai-code-completion/src/browser/ai-code-completion-preference.ts index 60cab4a55a59b..93b8ddb6c5d23 100644 --- a/packages/ai-code-completion/src/browser/ai-code-completion-preference.ts +++ b/packages/ai-code-completion/src/browser/ai-code-completion-preference.ts @@ -18,6 +18,7 @@ import { PreferenceSchema } from '@theia/core/lib/browser/preferences/preference import { AI_CORE_PREFERENCES_TITLE } from '@theia/ai-core/lib/browser/ai-core-preferences'; export const PREF_AI_INLINE_COMPLETION_ENABLE = 'ai-features.codeCompletion.enableCodeCompletion'; +export const PREF_AI_INLINE_COMPLETION_AUTOMATIC_ENABLE = 'ai-features.codeCompletion.automaticCodeCompletion'; export const PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS = 'ai-features.codeCompletion.excludedFileExtensions'; export const AICodeCompletionPreferencesSchema: PreferenceSchema = { @@ -29,6 +30,12 @@ export const AICodeCompletionPreferencesSchema: PreferenceSchema = { description: 'Enable AI completions inline within any (Monaco) editor.', default: false }, + [PREF_AI_INLINE_COMPLETION_AUTOMATIC_ENABLE]: { + title: AI_CORE_PREFERENCES_TITLE, + type: 'boolean', + description: 'Automatically trigger AI completions inline within any (Monaco) editor while editing.', + default: true + }, [PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS]: { title: 'Excluded File Extensions', type: 'array', diff --git a/packages/ai-code-completion/src/browser/ai-code-frontend-application-contribution.ts b/packages/ai-code-completion/src/browser/ai-code-frontend-application-contribution.ts index 9d7c610979606..fdf9d24520578 100644 --- a/packages/ai-code-completion/src/browser/ai-code-frontend-application-contribution.ts +++ b/packages/ai-code-completion/src/browser/ai-code-frontend-application-contribution.ts @@ -16,15 +16,16 @@ import * as monaco from '@theia/monaco-editor-core'; -import { FrontendApplicationContribution, PreferenceService } from '@theia/core/lib/browser'; +import { FrontendApplicationContribution, KeybindingContribution, KeybindingRegistry, PreferenceService } from '@theia/core/lib/browser'; import { inject, injectable } from '@theia/core/shared/inversify'; import { AIActivationService } from '@theia/ai-core/lib/browser'; import { Disposable } from '@theia/core'; import { AICodeInlineCompletionsProvider } from './ai-code-inline-completion-provider'; -import { PREF_AI_INLINE_COMPLETION_ENABLE, PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS } from './ai-code-completion-preference'; +import { PREF_AI_INLINE_COMPLETION_AUTOMATIC_ENABLE, PREF_AI_INLINE_COMPLETION_ENABLE, PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS } from './ai-code-completion-preference'; +import { InlineCompletionTriggerKind } from '@theia/monaco-editor-core/esm/vs/editor/common/languages'; @injectable() -export class AIFrontendApplicationContribution implements FrontendApplicationContribution { +export class AIFrontendApplicationContribution implements FrontendApplicationContribution, KeybindingContribution { @inject(AICodeInlineCompletionsProvider) private inlineCodeCompletionProvider: AICodeInlineCompletionsProvider; @@ -48,7 +49,9 @@ export class AIFrontendApplicationContribution implements FrontendApplicationCon this.toDispose.set('inlineCompletions', handler()); this.preferenceService.onPreferenceChanged(event => { - if (event.preferenceName === PREF_AI_INLINE_COMPLETION_ENABLE || event.preferenceName === PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS) { + if (event.preferenceName === PREF_AI_INLINE_COMPLETION_ENABLE + || event.preferenceName === PREF_AI_INLINE_COMPLETION_AUTOMATIC_ENABLE + || event.preferenceName === PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS) { this.toDispose.get('inlineCompletions')?.dispose(); this.toDispose.set('inlineCompletions', handler()); } @@ -60,6 +63,14 @@ export class AIFrontendApplicationContribution implements FrontendApplicationCon }); } + registerKeybindings(keybindings: KeybindingRegistry): void { + keybindings.registerKeybinding({ + command: 'editor.action.inlineSuggest.trigger', + keybinding: 'Ctrl+Shift+Space', + when: '!editorReadonly && editorTextFocus' + }); + } + protected handleInlineCompletions(): Disposable { const enable = this.preferenceService.get(PREF_AI_INLINE_COMPLETION_ENABLE, false) && this.activationService.isActive; @@ -67,14 +78,17 @@ export class AIFrontendApplicationContribution implements FrontendApplicationCon return Disposable.NULL; } + const automatic = this.preferenceService.get(PREF_AI_INLINE_COMPLETION_AUTOMATIC_ENABLE, true); const excludedExtensions = this.preferenceService.get(PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS, []); return monaco.languages.registerInlineCompletionsProvider( { scheme: 'file' }, { provideInlineCompletions: (model, position, context, token) => { + if (!automatic && context.triggerKind === InlineCompletionTriggerKind.Automatic) { + return { items: [] }; + } const fileName = model.uri.toString(); - if (excludedExtensions.some(ext => fileName.endsWith(ext))) { return { items: [] }; } From 06f2bed670a464f00fb6fd445cc23fca14157eb0 Mon Sep 17 00:00:00 2001 From: Jonas Helming Date: Sun, 3 Nov 2024 23:42:13 +0100 Subject: [PATCH 2/3] Remove enable setting Signed-off-by: Jonas Helming --- .../src/browser/ai-code-completion-preference.ts | 10 +++------- .../ai-code-frontend-application-contribution.ts | 12 ++++-------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/packages/ai-code-completion/src/browser/ai-code-completion-preference.ts b/packages/ai-code-completion/src/browser/ai-code-completion-preference.ts index 93b8ddb6c5d23..db9306b324191 100644 --- a/packages/ai-code-completion/src/browser/ai-code-completion-preference.ts +++ b/packages/ai-code-completion/src/browser/ai-code-completion-preference.ts @@ -24,16 +24,12 @@ export const PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS = 'ai-features.codeCo export const AICodeCompletionPreferencesSchema: PreferenceSchema = { type: 'object', properties: { - [PREF_AI_INLINE_COMPLETION_ENABLE]: { - title: AI_CORE_PREFERENCES_TITLE, - type: 'boolean', - description: 'Enable AI completions inline within any (Monaco) editor.', - default: false - }, [PREF_AI_INLINE_COMPLETION_AUTOMATIC_ENABLE]: { title: AI_CORE_PREFERENCES_TITLE, type: 'boolean', - description: 'Automatically trigger AI completions inline within any (Monaco) editor while editing.', + description: 'Automatically trigger AI completions inline within any (Monaco) editor while editing.\ + \n\ + Alternativly, you can manually trigger the code via the command "Trigger Inline Suggestion" and the default shortcut "SHIFT+Space".', default: true }, [PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS]: { diff --git a/packages/ai-code-completion/src/browser/ai-code-frontend-application-contribution.ts b/packages/ai-code-completion/src/browser/ai-code-frontend-application-contribution.ts index fdf9d24520578..b8deb75791d68 100644 --- a/packages/ai-code-completion/src/browser/ai-code-frontend-application-contribution.ts +++ b/packages/ai-code-completion/src/browser/ai-code-frontend-application-contribution.ts @@ -21,7 +21,7 @@ import { inject, injectable } from '@theia/core/shared/inversify'; import { AIActivationService } from '@theia/ai-core/lib/browser'; import { Disposable } from '@theia/core'; import { AICodeInlineCompletionsProvider } from './ai-code-inline-completion-provider'; -import { PREF_AI_INLINE_COMPLETION_AUTOMATIC_ENABLE, PREF_AI_INLINE_COMPLETION_ENABLE, PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS } from './ai-code-completion-preference'; +import { PREF_AI_INLINE_COMPLETION_AUTOMATIC_ENABLE, PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS } from './ai-code-completion-preference'; import { InlineCompletionTriggerKind } from '@theia/monaco-editor-core/esm/vs/editor/common/languages'; @injectable() @@ -49,8 +49,7 @@ export class AIFrontendApplicationContribution implements FrontendApplicationCon this.toDispose.set('inlineCompletions', handler()); this.preferenceService.onPreferenceChanged(event => { - if (event.preferenceName === PREF_AI_INLINE_COMPLETION_ENABLE - || event.preferenceName === PREF_AI_INLINE_COMPLETION_AUTOMATIC_ENABLE + if (event.preferenceName === PREF_AI_INLINE_COMPLETION_AUTOMATIC_ENABLE || event.preferenceName === PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS) { this.toDispose.get('inlineCompletions')?.dispose(); this.toDispose.set('inlineCompletions', handler()); @@ -66,18 +65,15 @@ export class AIFrontendApplicationContribution implements FrontendApplicationCon registerKeybindings(keybindings: KeybindingRegistry): void { keybindings.registerKeybinding({ command: 'editor.action.inlineSuggest.trigger', - keybinding: 'Ctrl+Shift+Space', + keybinding: 'Shift+Space', when: '!editorReadonly && editorTextFocus' }); } protected handleInlineCompletions(): Disposable { - const enable = this.preferenceService.get(PREF_AI_INLINE_COMPLETION_ENABLE, false) && this.activationService.isActive; - - if (!enable) { + if (!this.activationService.isActive) { return Disposable.NULL; } - const automatic = this.preferenceService.get(PREF_AI_INLINE_COMPLETION_AUTOMATIC_ENABLE, true); const excludedExtensions = this.preferenceService.get(PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS, []); From c4e2f595e2835f7ebb939610212c438ab9dab164 Mon Sep 17 00:00:00 2001 From: Jonas Helming Date: Thu, 7 Nov 2024 10:25:30 +0100 Subject: [PATCH 3/3] Update packages/ai-code-completion/src/browser/ai-code-completion-preference.ts Co-authored-by: Stefan Dirix --- .../src/browser/ai-code-completion-preference.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ai-code-completion/src/browser/ai-code-completion-preference.ts b/packages/ai-code-completion/src/browser/ai-code-completion-preference.ts index db9306b324191..01edd996a5243 100644 --- a/packages/ai-code-completion/src/browser/ai-code-completion-preference.ts +++ b/packages/ai-code-completion/src/browser/ai-code-completion-preference.ts @@ -29,7 +29,7 @@ export const AICodeCompletionPreferencesSchema: PreferenceSchema = { type: 'boolean', description: 'Automatically trigger AI completions inline within any (Monaco) editor while editing.\ \n\ - Alternativly, you can manually trigger the code via the command "Trigger Inline Suggestion" and the default shortcut "SHIFT+Space".', + Alternativly, you can manually trigger the code via the command "Trigger Inline Suggestion" or the default shortcut "SHIFT+Space".', default: true }, [PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS]: {