diff --git a/packages/ai-chat/src/common/universal-chat-agent.ts b/packages/ai-chat/src/common/universal-chat-agent.ts
index ab8838d7578e6..95318ac3ab360 100644
--- a/packages/ai-chat/src/common/universal-chat-agent.ts
+++ b/packages/ai-chat/src/common/universal-chat-agent.ts
@@ -76,6 +76,12 @@ simple solutions.
`
};
+export const universalTemplateVariant: PromptTemplate = {
+ id: 'universal-system-empty',
+ template: '',
+ variantOf: universalTemplate.id,
+};
+
@injectable()
export class UniversalChatAgent extends AbstractStreamParsingChatAgent implements ChatAgent {
name: string;
@@ -96,7 +102,7 @@ export class UniversalChatAgent extends AbstractStreamParsingChatAgent implement
+ 'questions the user might ask. The universal agent currently does not have any context by default, i.e. it cannot '
+ 'access the current user context or the workspace.';
this.variables = [];
- this.promptTemplates = [universalTemplate];
+ this.promptTemplates = [universalTemplate, universalTemplateVariant];
this.functions = [];
this.agentSpecificVariables = [];
}
diff --git a/packages/ai-core/src/browser/ai-configuration/agent-configuration-widget.tsx b/packages/ai-core/src/browser/ai-configuration/agent-configuration-widget.tsx
index 35abb84b328e5..8329e25ab5e1f 100644
--- a/packages/ai-core/src/browser/ai-configuration/agent-configuration-widget.tsx
+++ b/packages/ai-core/src/browser/ai-configuration/agent-configuration-widget.tsx
@@ -137,14 +137,31 @@ export class AIAgentConfigurationWidget extends ReactWidget {
Enable Agent
-
- {agent.promptTemplates?.map(template =>
-
)}
+
+ Prompt Templates
+
+ {(() => {
+ const defaultTemplates = agent.promptTemplates?.filter(template => !template.variantOf) || [];
+ return defaultTemplates.length > 0 ? (
+ defaultTemplates.map(template => (
+
+
+
+ ))
+ ) : (
+
No default template available
+ );
+ })()}
+
+
= ({ agentId, template, promptCustomizationService }) => {
+export const TemplateRenderer: React.FC = ({
+ agentId,
+ template,
+ promptCustomizationService,
+ promptService,
+ aiSettingsService,
+}) => {
+ const [variantIds, setVariantIds] = React.useState([]);
+ const [selectedVariant, setSelectedVariant] = React.useState(DEFAULT_VARIANT);
+
+ React.useEffect(() => {
+ (async () => {
+ const variants = promptService.getVariantIds(template.id);
+ setVariantIds([DEFAULT_VARIANT, ...variants]);
+
+ const agentSettings = await aiSettingsService.getAgentSettings(agentId);
+ const currentVariant =
+ agentSettings?.selectedVariants?.[template.id] || DEFAULT_VARIANT;
+ setSelectedVariant(currentVariant);
+ })();
+ }, [template.id, promptService, aiSettingsService, agentId]);
+
+ const handleVariantChange = async (event: React.ChangeEvent) => {
+ const newVariant = event.target.value;
+ setSelectedVariant(newVariant);
+
+ const agentSettings = await aiSettingsService.getAgentSettings(agentId);
+ const selectedVariants = agentSettings?.selectedVariants || {};
+
+ const updatedVariants = { ...selectedVariants };
+ if (newVariant === DEFAULT_VARIANT) {
+ delete updatedVariants[template.id];
+ } else {
+ updatedVariants[template.id] = newVariant;
+ }
+
+ await aiSettingsService.updateAgentSettings(agentId, {
+ selectedVariants: updatedVariants,
+ });
+ };
+
const openTemplate = React.useCallback(async () => {
- promptCustomizationService.editTemplate(template.id, template.template);
- }, [template, promptCustomizationService]);
+ const templateId = selectedVariant === DEFAULT_VARIANT ? template.id : selectedVariant;
+ const selectedTemplate = promptService.getRawPrompt(templateId);
+ promptCustomizationService.editTemplate(templateId, selectedTemplate?.template || '');
+ }, [selectedVariant, template.id, promptService, promptCustomizationService]);
+
const resetTemplate = React.useCallback(async () => {
- promptCustomizationService.resetTemplate(template.id);
- }, [promptCustomizationService, template]);
-
- return <>
- {template.id}
-
-
- >;
+ const templateId = selectedVariant === DEFAULT_VARIANT ? template.id : selectedVariant;
+ promptCustomizationService.resetTemplate(templateId);
+ }, [selectedVariant, template.id, promptCustomizationService]);
+
+ return (
+
+
+ {template.id}
+
+
+ {variantIds.length > 1 && (
+ <>
+
+
+ >
+ )}
+
+
+
+
+ );
};
diff --git a/packages/ai-core/src/browser/style/index.css b/packages/ai-core/src/browser/style/index.css
index 36cdad9c19221..a42e41b29a9a2 100644
--- a/packages/ai-core/src/browser/style/index.css
+++ b/packages/ai-core/src/browser/style/index.css
@@ -14,14 +14,42 @@
margin-left: var(--theia-ui-padding);
}
+.theia-settings-container .settings-section-subcategory-title.ai-settings-section-subcategory-title {
+ padding-left: 0;
+}
+
.ai-templates {
- display: grid;
- /** Display content in 3 columns */
- grid-template-columns: 1fr auto auto;
- /** add a 3px gap between rows */
- row-gap: 3px;
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+}
+
+.template-renderer {
+ display: flex;
+ flex-direction: column;
+ padding: 10px;
+}
+
+.template-header {
+ margin-bottom: 8px;
}
+.template-controls {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.template-select-label {
+ margin-right: 5px;
+}
+
+.template-variant-selector {
+ min-width: 120px;
+}
+
+
+
#ai-variable-configuration-container-widget,
#ai-agent-configuration-container-widget {
margin-top: 5px;
diff --git a/packages/ai-core/src/common/agent-service.ts b/packages/ai-core/src/common/agent-service.ts
index 4b351fb93250d..4c8a4ac2e7bdf 100644
--- a/packages/ai-core/src/common/agent-service.ts
+++ b/packages/ai-core/src/common/agent-service.ts
@@ -99,7 +99,7 @@ export class AgentServiceImpl implements AgentService {
registerAgent(agent: Agent): void {
this._agents.push(agent);
agent.promptTemplates.forEach(
- template => this.promptService.storePrompt(template.id, template.template)
+ template => this.promptService.storePromptTemplate(template)
);
this.onDidChangeAgentsEmitter.fire();
}
diff --git a/packages/ai-core/src/common/prompt-service.spec.ts b/packages/ai-core/src/common/prompt-service.spec.ts
index 106ef4fc85df0..00807e59db11a 100644
--- a/packages/ai-core/src/common/prompt-service.spec.ts
+++ b/packages/ai-core/src/common/prompt-service.spec.ts
@@ -37,10 +37,10 @@ describe('PromptService', () => {
container.bind(AIVariableService).toConstantValue(variableService);
promptService = container.get(PromptService);
- promptService.storePrompt('1', 'Hello, {{name}}!');
- promptService.storePrompt('2', 'Goodbye, {{name}}!');
- promptService.storePrompt('3', 'Ciao, {{invalid}}!');
- promptService.storePrompt('8', 'Hello, {{{name}}}');
+ promptService.storePromptTemplate({ id: '1', template: 'Hello, {{name}}!' });
+ promptService.storePromptTemplate({ id: '2', template: 'Goodbye, {{name}}!' });
+ promptService.storePromptTemplate({ id: '3', template: 'Ciao, {{invalid}}!' });
+ promptService.storePromptTemplate({ id: '8', template: 'Hello, {{{name}}}' });
});
it('should initialize prompts from PromptCollectionService', () => {
@@ -62,7 +62,7 @@ describe('PromptService', () => {
});
it('should store a new prompt', () => {
- promptService.storePrompt('3', 'Welcome, {{name}}!');
+ promptService.storePromptTemplate({ id: '3', template: 'Welcome, {{name}}!' });
const newPrompt = promptService.getRawPrompt('3');
expect(newPrompt?.template).to.equal('Welcome, {{name}}!');
});
@@ -88,10 +88,10 @@ describe('PromptService', () => {
});
it('should ignore whitespace in variables', async () => {
- promptService.storePrompt('4', 'Hello, {{name }}!');
- promptService.storePrompt('5', 'Hello, {{ name}}!');
- promptService.storePrompt('6', 'Hello, {{ name }}!');
- promptService.storePrompt('7', 'Hello, {{ name }}!');
+ promptService.storePromptTemplate({ id: '4', template: 'Hello, {{name }}!' });
+ promptService.storePromptTemplate({ id: '5', template: 'Hello, {{ name}}!' });
+ promptService.storePromptTemplate({ id: '6', template: 'Hello, {{ name }}!' });
+ promptService.storePromptTemplate({ id: '7', template: 'Hello, {{ name }}!' });
for (let i = 4; i <= 7; i++) {
const prompt = await promptService.getPrompt(`${i}`, { name: 'John' });
expect(prompt?.text).to.equal('Hello, John!');
@@ -109,10 +109,10 @@ describe('PromptService', () => {
});
it('should ignore whitespace in variables (three bracket)', async () => {
- promptService.storePrompt('9', 'Hello, {{{name }}}');
- promptService.storePrompt('10', 'Hello, {{{ name}}}');
- promptService.storePrompt('11', 'Hello, {{{ name }}}');
- promptService.storePrompt('12', 'Hello, {{{ name }}}');
+ promptService.storePromptTemplate({ id: '9', template: 'Hello, {{{name }}}' });
+ promptService.storePromptTemplate({ id: '10', template: 'Hello, {{{ name}}}' });
+ promptService.storePromptTemplate({ id: '11', template: 'Hello, {{{ name }}}' });
+ promptService.storePromptTemplate({ id: '12', template: 'Hello, {{{ name }}}' });
for (let i = 9; i <= 12; i++) {
const prompt = await promptService.getPrompt(`${i}`, { name: 'John' });
expect(prompt?.text).to.equal('Hello, John');
@@ -120,26 +120,24 @@ describe('PromptService', () => {
});
it('should ignore invalid prompts with unmatched brackets', async () => {
- promptService.storePrompt('9', 'Hello, {{name');
- promptService.storePrompt('10', 'Hello, {{{name');
- promptService.storePrompt('11', 'Hello, name}}}}');
+ promptService.storePromptTemplate({ id: '9', template: 'Hello, {{name' });
+ promptService.storePromptTemplate({ id: '10', template: 'Hello, {{{name' });
+ promptService.storePromptTemplate({ id: '11', template: 'Hello, name}}}}' });
const prompt1 = await promptService.getPrompt('9', { name: 'John' });
expect(prompt1?.text).to.equal('Hello, {{name'); // Not matching due to missing closing brackets
-
const prompt2 = await promptService.getPrompt('10', { name: 'John' });
expect(prompt2?.text).to.equal('Hello, {{{name'); // Matches pattern due to valid three-start-two-end brackets
-
const prompt3 = await promptService.getPrompt('11', { name: 'John' });
expect(prompt3?.text).to.equal('Hello, name}}}}'); // Extra closing bracket, does not match cleanly
});
it('should handle a mixture of two and three brackets correctly', async () => {
- promptService.storePrompt('12', 'Hi, {{name}}}'); // (invalid)
- promptService.storePrompt('13', 'Hello, {{{name}}'); // (invalid)
- promptService.storePrompt('14', 'Greetings, {{{name}}}}'); // (invalid)
- promptService.storePrompt('15', 'Bye, {{{{name}}}'); // (invalid)
- promptService.storePrompt('16', 'Ciao, {{{{name}}}}'); // (invalid)
- promptService.storePrompt('17', 'Hi, {{name}}! {{{name}}}'); // Mixed valid patterns
+ promptService.storePromptTemplate({ id: '12', template: 'Hi, {{name}}}' }); // (invalid)
+ promptService.storePromptTemplate({ id: '13', template: 'Hello, {{{name}}' }); // (invalid)
+ promptService.storePromptTemplate({ id: '14', template: 'Greetings, {{{name}}}}' }); // (invalid)
+ promptService.storePromptTemplate({ id: '15', template: 'Bye, {{{{name}}}' }); // (invalid)
+ promptService.storePromptTemplate({ id: '16', template: 'Ciao, {{{{name}}}}' }); // (invalid)
+ promptService.storePromptTemplate({ id: '17', template: 'Hi, {{name}}! {{{name}}}' }); // Mixed valid patterns
const prompt12 = await promptService.getPrompt('12', { name: 'John' });
expect(prompt12?.text).to.equal('Hi, {{name}}}');
@@ -161,87 +159,143 @@ describe('PromptService', () => {
});
it('should strip single-line comments at the start of the template', () => {
- promptService.storePrompt('comment-basic', '{{!-- Comment --}}Hello, {{name}}!');
+ promptService.storePromptTemplate({ id: 'comment-basic', template: '{{!-- Comment --}}Hello, {{name}}!' });
const prompt = promptService.getUnresolvedPrompt('comment-basic');
expect(prompt?.template).to.equal('Hello, {{name}}!');
});
it('should remove line break after first-line comment', () => {
- promptService.storePrompt('comment-line-break', '{{!-- Comment --}}\nHello, {{name}}!');
+ promptService.storePromptTemplate({ id: 'comment-line-break', template: '{{!-- Comment --}}\nHello, {{name}}!' });
const prompt = promptService.getUnresolvedPrompt('comment-line-break');
expect(prompt?.template).to.equal('Hello, {{name}}!');
});
it('should strip multiline comments at the start of the template', () => {
- promptService.storePrompt('comment-multiline', '{{!--\nMultiline comment\n--}}\nGoodbye, {{name}}!');
+ promptService.storePromptTemplate({ id: 'comment-multiline', template: '{{!--\nMultiline comment\n--}}\nGoodbye, {{name}}!' });
const prompt = promptService.getUnresolvedPrompt('comment-multiline');
expect(prompt?.template).to.equal('Goodbye, {{name}}!');
});
it('should not strip comments not in the first line', () => {
- promptService.storePrompt('comment-second-line', 'Hello, {{name}}!\n{{!-- Comment --}}');
+ promptService.storePromptTemplate({ id: 'comment-second-line', template: 'Hello, {{name}}!\n{{!-- Comment --}}' });
const prompt = promptService.getUnresolvedPrompt('comment-second-line');
expect(prompt?.template).to.equal('Hello, {{name}}!\n{{!-- Comment --}}');
});
it('should treat unclosed comments as regular text', () => {
- promptService.storePrompt('comment-unclosed', '{{!-- Unclosed comment');
+ promptService.storePromptTemplate({ id: 'comment-unclosed', template: '{{!-- Unclosed comment' });
const prompt = promptService.getUnresolvedPrompt('comment-unclosed');
expect(prompt?.template).to.equal('{{!-- Unclosed comment');
});
it('should treat standalone closing delimiters as regular text', () => {
- promptService.storePrompt('comment-standalone', '--}} Hello, {{name}}!');
+ promptService.storePromptTemplate({ id: 'comment-standalone', template: '--}} Hello, {{name}}!' });
const prompt = promptService.getUnresolvedPrompt('comment-standalone');
expect(prompt?.template).to.equal('--}} Hello, {{name}}!');
});
it('should handle nested comments and stop at the first closing tag', () => {
- promptService.storePrompt('nested-comment', '{{!-- {{!-- Nested comment --}} --}}text');
+ promptService.storePromptTemplate({ id: 'nested-comment', template: '{{!-- {{!-- Nested comment --}} --}}text' });
const prompt = promptService.getUnresolvedPrompt('nested-comment');
expect(prompt?.template).to.equal('--}}text');
});
it('should handle templates with only comments', () => {
- promptService.storePrompt('comment-only', '{{!-- Only comments --}}');
+ promptService.storePromptTemplate({ id: 'comment-only', template: '{{!-- Only comments --}}' });
const prompt = promptService.getUnresolvedPrompt('comment-only');
expect(prompt?.template).to.equal('');
});
it('should handle mixed delimiters on the same line', () => {
- promptService.storePrompt('comment-mixed', '{{!-- Unclosed comment --}}');
+ promptService.storePromptTemplate({ id: 'comment-mixed', template: '{{!-- Unclosed comment --}}' });
const prompt = promptService.getUnresolvedPrompt('comment-mixed');
expect(prompt?.template).to.equal('');
});
it('should resolve variables after stripping single-line comments', async () => {
- promptService.storePrompt('comment-resolve', '{{!-- Comment --}}Hello, {{name}}!');
+ promptService.storePromptTemplate({ id: 'comment-resolve', template: '{{!-- Comment --}}Hello, {{name}}!' });
const prompt = await promptService.getPrompt('comment-resolve', { name: 'John' });
expect(prompt?.text).to.equal('Hello, John!');
});
it('should resolve variables in multiline templates with comments', async () => {
- promptService.storePrompt('comment-multiline-vars', '{{!--\nMultiline comment\n--}}\nHello, {{name}}!');
+ promptService.storePromptTemplate({ id: 'comment-multiline-vars', template: '{{!--\nMultiline comment\n--}}\nHello, {{name}}!' });
const prompt = await promptService.getPrompt('comment-multiline-vars', { name: 'John' });
expect(prompt?.text).to.equal('Hello, John!');
});
it('should resolve variables with standalone closing delimiters', async () => {
- promptService.storePrompt('comment-standalone-vars', '--}} Hello, {{name}}!');
+ promptService.storePromptTemplate({ id: 'comment-standalone-vars', template: '--}} Hello, {{name}}!' });
const prompt = await promptService.getPrompt('comment-standalone-vars', { name: 'John' });
expect(prompt?.text).to.equal('--}} Hello, John!');
});
it('should treat unclosed comments as text and resolve variables', async () => {
- promptService.storePrompt('comment-unclosed-vars', '{{!-- Unclosed comment\nHello, {{name}}!');
+ promptService.storePromptTemplate({ id: 'comment-unclosed-vars', template: '{{!-- Unclosed comment\nHello, {{name}}!' });
const prompt = await promptService.getPrompt('comment-unclosed-vars', { name: 'John' });
expect(prompt?.text).to.equal('{{!-- Unclosed comment\nHello, John!');
});
it('should handle templates with mixed comments and variables', async () => {
- promptService.storePrompt('comment-mixed-vars', '{{!-- Comment --}}Hi, {{name}}! {{!-- Another comment --}}');
+ promptService.storePromptTemplate({ id: 'comment-mixed-vars', template: '{{!-- Comment --}}Hi, {{name}}! {{!-- Another comment --}}' });
const prompt = await promptService.getPrompt('comment-mixed-vars', { name: 'John' });
expect(prompt?.text).to.equal('Hi, John! {{!-- Another comment --}}');
});
+ it('should return all variant IDs of a given prompt', () => {
+ promptService.storePromptTemplate({ id: 'main', template: 'Main template' });
+
+ promptService.storePromptTemplate({
+ id: 'variant1',
+ template: 'Variant 1',
+ variantOf: 'main'
+ });
+ promptService.storePromptTemplate({
+ id: 'variant2',
+ template: 'Variant 2',
+ variantOf: 'main'
+ });
+ promptService.storePromptTemplate({
+ id: 'variant3',
+ template: 'Variant 3',
+ variantOf: 'main'
+ });
+
+ const variantIds = promptService.getVariantIds('main');
+ expect(variantIds).to.deep.equal(['variant1', 'variant2', 'variant3']);
+ });
+
+ it('should return an empty array if no variants exist for a given prompt', () => {
+ promptService.storePromptTemplate({ id: 'main', template: 'Main template' });
+
+ const variantIds = promptService.getVariantIds('main');
+ expect(variantIds).to.deep.equal([]);
+ });
+
+ it('should return an empty array if the main prompt ID does not exist', () => {
+ const variantIds = promptService.getVariantIds('nonExistent');
+ expect(variantIds).to.deep.equal([]);
+ });
+
+ it('should not influence prompts without variants when other prompts have variants', () => {
+ promptService.storePromptTemplate({ id: 'mainWithVariants', template: 'Main template with variants' });
+ promptService.storePromptTemplate({ id: 'mainWithoutVariants', template: 'Main template without variants' });
+
+ promptService.storePromptTemplate({
+ id: 'variant1',
+ template: 'Variant 1',
+ variantOf: 'mainWithVariants'
+ });
+ promptService.storePromptTemplate({
+ id: 'variant2',
+ template: 'Variant 2',
+ variantOf: 'mainWithVariants'
+ });
+
+ const variantsForMainWithVariants = promptService.getVariantIds('mainWithVariants');
+ const variantsForMainWithoutVariants = promptService.getVariantIds('mainWithoutVariants');
+
+ expect(variantsForMainWithVariants).to.deep.equal(['variant1', 'variant2']);
+ expect(variantsForMainWithoutVariants).to.deep.equal([]);
+ });
});
diff --git a/packages/ai-core/src/common/prompt-service.ts b/packages/ai-core/src/common/prompt-service.ts
index d4bc9aaea0ce5..aef16da8fdc50 100644
--- a/packages/ai-core/src/common/prompt-service.ts
+++ b/packages/ai-core/src/common/prompt-service.ts
@@ -21,10 +21,16 @@ import { ToolInvocationRegistry } from './tool-invocation-registry';
import { toolRequestToPromptText } from './language-model-util';
import { ToolRequest } from './language-model';
import { matchFunctionsRegEx, matchVariablesRegEx } from './prompt-service-util';
+import { AISettingsService } from './settings-service';
export interface PromptTemplate {
id: string;
template: string;
+ /**
+ * (Optional) The ID of the main template for which this template is a variant.
+ * If present, this indicates that the current template represents an alternative version of the specified main template.
+ */
+ variantOf?: string;
}
export interface PromptMap { [id: string]: PromptTemplate }
@@ -63,11 +69,10 @@ export interface PromptService {
*/
getPrompt(id: string, args?: { [key: string]: unknown }): Promise;
/**
- * Adds a prompt to the list of prompts.
- * @param id the id of the prompt
- * @param prompt the prompt template to store
+ * Adds a {@link PromptTemplate} to the list of prompts.
+ * @param promptTemplate the prompt template to store
*/
- storePrompt(id: string, prompt: string): void;
+ storePromptTemplate(promptTemplate: PromptTemplate): void;
/**
* Removes a prompt from the list of prompts.
* @param id the id of the prompt
@@ -77,6 +82,20 @@ export interface PromptService {
* Return all known prompts as a {@link PromptMap map}.
*/
getAllPrompts(): PromptMap;
+ /**
+ * Retrieve all variant IDs of a given {@link PromptTemplate}.
+ * @param id the id of the main {@link PromptTemplate}
+ * @returns an array of string IDs representing the variants of the given template
+ */
+ getVariantIds(id: string): string[];
+ /**
+ * Retrieve the currently selected variant ID for a given main prompt ID.
+ * If a variant is selected for the main prompt, it will be returned.
+ * Otherwise, the main prompt ID will be returned.
+ * @param id the id of the main prompt
+ * @returns the variant ID if one is selected, or the main prompt ID otherwise
+ */
+ getVariantId(id: string): Promise;
}
export interface CustomAgentDescription {
@@ -163,6 +182,9 @@ export interface PromptCustomizationService {
@injectable()
export class PromptServiceImpl implements PromptService {
+ @inject(AISettingsService) @optional()
+ protected readonly settingsService: AISettingsService | undefined;
+
@inject(PromptCustomizationService) @optional()
protected readonly customizationService: PromptCustomizationService | undefined;
@@ -203,8 +225,22 @@ export class PromptServiceImpl implements PromptService {
return commentRegex.test(template) ? template.replace(commentRegex, '').trimStart() : template;
}
+ async getVariantId(id: string): Promise {
+ if (this.settingsService !== undefined) {
+ const agentSettingsMap = await this.settingsService.getSettings();
+
+ for (const agentSettings of Object.values(agentSettingsMap)) {
+ if (agentSettings.selectedVariants && agentSettings.selectedVariants[id]) {
+ return agentSettings.selectedVariants[id];
+ }
+ }
+ }
+ return id;
+ }
+
async getPrompt(id: string, args?: { [key: string]: unknown }): Promise {
- const prompt = this.getUnresolvedPrompt(id);
+ const variantId = await this.getVariantId(id);
+ const prompt = this.getUnresolvedPrompt(variantId);
if (prompt === undefined) {
return undefined;
}
@@ -274,10 +310,15 @@ export class PromptServiceImpl implements PromptService {
return { ...this._prompts };
}
}
- storePrompt(id: string, prompt: string): void {
- this._prompts[id] = { id, template: prompt };
- }
removePrompt(id: string): void {
delete this._prompts[id];
}
+ getVariantIds(id: string): string[] {
+ return Object.values(this._prompts)
+ .filter(prompt => prompt.variantOf === id)
+ .map(variant => variant.id);
+ }
+ storePromptTemplate(promptTemplate: PromptTemplate): void {
+ this._prompts[promptTemplate.id] = promptTemplate;
+ }
}
diff --git a/packages/ai-core/src/common/settings-service.ts b/packages/ai-core/src/common/settings-service.ts
index 007daec366250..8610a36b92ea4 100644
--- a/packages/ai-core/src/common/settings-service.ts
+++ b/packages/ai-core/src/common/settings-service.ts
@@ -30,4 +30,9 @@ export type AISettings = Record;
export interface AgentSettings {
languageModelRequirements?: LanguageModelRequirement[];
enable?: boolean;
+ /**
+ * A mapping of main template IDs to their selected variant IDs.
+ * If a main template is not present in this mapping, it means the main template is used.
+ */
+ selectedVariants?: Record;
}