From f1562a2187c0cb644d851352ddcc119aed31c86f Mon Sep 17 00:00:00 2001 From: Eugen Neufeld Date: Tue, 25 Feb 2025 01:03:21 +0100 Subject: [PATCH] Add variable support with #{} syntax in prompttemplate --- .../data/prompttemplate.tmLanguage.json | 21 +++++++++++++ .../browser/prompttemplate-contribution.ts | 30 +++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/packages/ai-core/data/prompttemplate.tmLanguage.json b/packages/ai-core/data/prompttemplate.tmLanguage.json index 30a02cb34c4b4..7ec3e4cf072d6 100644 --- a/packages/ai-core/data/prompttemplate.tmLanguage.json +++ b/packages/ai-core/data/prompttemplate.tmLanguage.json @@ -97,6 +97,27 @@ "match": "[a-zA-Z_][a-zA-Z0-9_\\-]*" } ] + }, + { + "name": "variable.parameter.prompttemplate", + "begin": "#{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.variable.begin" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.variable.end" + } + }, + "patterns": [ + { + "name": "keyword.control", + "match": "[a-zA-Z_][a-zA-Z0-9_\\-]*" + } + ] } ], "repository": {}, diff --git a/packages/ai-core/src/browser/prompttemplate-contribution.ts b/packages/ai-core/src/browser/prompttemplate-contribution.ts index 19eef9b7ac28a..74bb83a295889 100644 --- a/packages/ai-core/src/browser/prompttemplate-contribution.ts +++ b/packages/ai-core/src/browser/prompttemplate-contribution.ts @@ -24,6 +24,7 @@ import { codicon, Widget } from '@theia/core/lib/browser'; import { EditorWidget, ReplaceOperation } from '@theia/editor/lib/browser'; import { PromptCustomizationService, PromptService, ToolInvocationRegistry } from '../common'; import { ProviderResult } from '@theia/monaco-editor-core/esm/vs/editor/common/languages'; +import { AIVariableService } from '../common/variable-service'; const PROMPT_TEMPLATE_LANGUAGE_ID = 'theia-ai-prompt-template'; const PROMPT_TEMPLATE_TEXTMATE_SCOPE = 'source.prompttemplate'; @@ -59,19 +60,25 @@ export class PromptTemplateContribution implements LanguageGrammarDefinitionCont @inject(ToolInvocationRegistry) protected readonly toolInvocationRegistry: ToolInvocationRegistry; + @inject(AIVariableService) + protected readonly variableService: AIVariableService; + readonly config: monaco.languages.LanguageConfiguration = { 'brackets': [ ['${', '}'], - ['~{', '}'] + ['~{', '}'], + ['#{', '}'] ], 'autoClosingPairs': [ { 'open': '${', 'close': '}' }, { 'open': '~{', 'close': '}' }, + { 'open': '#{', 'close': '}' } ], 'surroundingPairs': [ { 'open': '${', 'close': '}' }, - { 'open': '~{', 'close': '}' } + { 'open': '~{', 'close': '}' }, + { 'open': '#{', 'close': '}' } ] }; @@ -95,6 +102,12 @@ export class PromptTemplateContribution implements LanguageGrammarDefinitionCont provideCompletionItems: (model, position, _context, _token): ProviderResult => this.provideFunctionCompletions(model, position), }); + monaco.languages.registerCompletionItemProvider(PROMPT_TEMPLATE_LANGUAGE_ID, { + // Monaco only supports single character trigger characters + triggerCharacters: ['{'], + provideCompletionItems: (model, position, _context, _token): ProviderResult => this.provideVariableCompletions(model, position), + }); + const textmateGrammar = require('../../data/prompttemplate.tmLanguage.json'); const grammarDefinitionProvider: GrammarDefinitionProvider = { getGrammarDefinition: function (): Promise { @@ -122,6 +135,19 @@ export class PromptTemplateContribution implements LanguageGrammarDefinitionCont ); } + provideVariableCompletions(model: monaco.editor.ITextModel, position: monaco.Position): ProviderResult { + return this.getSuggestions( + model, + position, + '#{', + this.variableService.getVariables(), + monaco.languages.CompletionItemKind.Variable, + variable => variable.id, + variable => variable.name, + variable => variable.description ?? '' + ); + } + getCompletionRange(model: monaco.editor.ITextModel, position: monaco.Position, triggerCharacters: string): monaco.Range | undefined { // Check if the characters before the current position are the trigger characters const lineContent = model.getLineContent(position.lineNumber);