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..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 @@ -18,16 +18,19 @@ 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 = { type: 'object', properties: { - [PREF_AI_INLINE_COMPLETION_ENABLE]: { + [PREF_AI_INLINE_COMPLETION_AUTOMATIC_ENABLE]: { title: AI_CORE_PREFERENCES_TITLE, type: 'boolean', - description: 'Enable AI completions inline within any (Monaco) editor.', - default: false + 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" or the default shortcut "SHIFT+Space".', + default: true }, [PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS]: { title: 'Excluded File 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 9d7c610979606..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 @@ -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_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,8 @@ 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_AUTOMATIC_ENABLE + || event.preferenceName === PREF_AI_INLINE_COMPLETION_EXCLUDED_EXTENSIONS) { this.toDispose.get('inlineCompletions')?.dispose(); this.toDispose.set('inlineCompletions', handler()); } @@ -60,21 +62,29 @@ export class AIFrontendApplicationContribution implements FrontendApplicationCon }); } - protected handleInlineCompletions(): Disposable { - const enable = this.preferenceService.get(PREF_AI_INLINE_COMPLETION_ENABLE, false) && this.activationService.isActive; + registerKeybindings(keybindings: KeybindingRegistry): void { + keybindings.registerKeybinding({ + command: 'editor.action.inlineSuggest.trigger', + keybinding: 'Shift+Space', + when: '!editorReadonly && editorTextFocus' + }); + } - if (!enable) { + protected handleInlineCompletions(): Disposable { + 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, []); 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: [] }; }