@theia/ai-core 1.61.0 → 1.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/ai-core-frontend-module.js +2 -2
- package/lib/browser/ai-core-frontend-module.js.map +1 -1
- package/lib/browser/frontend-language-model-service.d.ts +1 -1
- package/lib/browser/frontend-language-model-service.d.ts.map +1 -1
- package/lib/browser/frontend-language-model-service.js.map +1 -1
- package/lib/browser/frontend-prompt-customization-service.d.ts +142 -48
- package/lib/browser/frontend-prompt-customization-service.d.ts.map +1 -1
- package/lib/browser/frontend-prompt-customization-service.js +452 -153
- package/lib/browser/frontend-prompt-customization-service.js.map +1 -1
- package/lib/browser/prompttemplate-contribution.d.ts +1 -2
- package/lib/browser/prompttemplate-contribution.d.ts.map +1 -1
- package/lib/browser/prompttemplate-contribution.js +5 -9
- package/lib/browser/prompttemplate-contribution.js.map +1 -1
- package/lib/common/agent-service.d.ts.map +1 -1
- package/lib/common/agent-service.js +14 -2
- package/lib/common/agent-service.js.map +1 -1
- package/lib/common/agent.d.ts +8 -3
- package/lib/common/agent.d.ts.map +1 -1
- package/lib/common/agent.js.map +1 -1
- package/lib/common/index.d.ts +0 -1
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +0 -1
- package/lib/common/index.js.map +1 -1
- package/lib/common/language-model-interaction-model.d.ts +74 -0
- package/lib/common/language-model-interaction-model.d.ts.map +1 -0
- package/lib/common/language-model-interaction-model.js +3 -0
- package/lib/common/language-model-interaction-model.js.map +1 -0
- package/lib/common/language-model-service.d.ts +26 -3
- package/lib/common/language-model-service.d.ts.map +1 -1
- package/lib/common/language-model-service.js +83 -6
- package/lib/common/language-model-service.js.map +1 -1
- package/lib/common/language-model-util.d.ts +3 -2
- package/lib/common/language-model-util.d.ts.map +1 -1
- package/lib/common/language-model-util.js +8 -0
- package/lib/common/language-model-util.js.map +1 -1
- package/lib/common/language-model.d.ts +25 -2
- package/lib/common/language-model.d.ts.map +1 -1
- package/lib/common/language-model.js +3 -1
- package/lib/common/language-model.js.map +1 -1
- package/lib/common/prompt-service.d.ts +332 -126
- package/lib/common/prompt-service.d.ts.map +1 -1
- package/lib/common/prompt-service.js +363 -102
- package/lib/common/prompt-service.js.map +1 -1
- package/lib/common/prompt-service.spec.js +104 -114
- package/lib/common/prompt-service.spec.js.map +1 -1
- package/lib/common/prompt-variable-contribution.d.ts +1 -2
- package/lib/common/prompt-variable-contribution.d.ts.map +1 -1
- package/lib/common/prompt-variable-contribution.js +17 -26
- package/lib/common/prompt-variable-contribution.js.map +1 -1
- package/package.json +10 -10
- package/src/browser/ai-core-frontend-module.ts +4 -4
- package/src/browser/frontend-language-model-service.ts +1 -1
- package/src/browser/frontend-prompt-customization-service.ts +574 -183
- package/src/browser/prompttemplate-contribution.ts +6 -9
- package/src/common/agent-service.ts +14 -4
- package/src/common/agent.ts +9 -3
- package/src/common/index.ts +0 -1
- package/src/common/language-model-interaction-model.ts +98 -0
- package/src/common/language-model-service.ts +115 -6
- package/src/common/language-model-util.ts +10 -2
- package/src/common/language-model.ts +28 -2
- package/src/common/prompt-service.spec.ts +108 -114
- package/src/common/prompt-service.ts +694 -221
- package/src/common/prompt-variable-contribution.ts +22 -27
- package/lib/common/communication-recording-service.d.ts +0 -30
- package/lib/common/communication-recording-service.d.ts.map +0 -1
- package/lib/common/communication-recording-service.js +0 -20
- package/lib/common/communication-recording-service.js.map +0 -1
- package/src/common/communication-recording-service.ts +0 -55
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import {
|
|
18
|
-
import { inject, injectable, optional } from '@theia/core/shared/inversify';
|
|
17
|
+
import { Event, Emitter, URI } from '@theia/core';
|
|
18
|
+
import { inject, injectable, optional, postConstruct } from '@theia/core/shared/inversify';
|
|
19
19
|
import { AIVariableArg, AIVariableContext, AIVariableService, createAIResolveVariableCache, ResolvedAIVariable } from './variable-service';
|
|
20
20
|
import { ToolInvocationRegistry } from './tool-invocation-registry';
|
|
21
21
|
import { toolRequestToPromptText } from './language-model-util';
|
|
@@ -23,189 +23,242 @@ import { ToolRequest } from './language-model';
|
|
|
23
23
|
import { matchFunctionsRegEx, matchVariablesRegEx } from './prompt-service-util';
|
|
24
24
|
import { AISettingsService } from './settings-service';
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Represents a basic prompt fragment with an ID and template content.
|
|
28
|
+
*/
|
|
29
|
+
export interface BasePromptFragment {
|
|
30
|
+
/** Unique identifier for this prompt fragment */
|
|
27
31
|
id: string;
|
|
32
|
+
|
|
33
|
+
/** The template content, which may contain variables and function references */
|
|
28
34
|
template: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Represents a customized prompt fragment with an assigned customization ID and priority.
|
|
39
|
+
*/
|
|
40
|
+
export interface CustomizedPromptFragment extends BasePromptFragment {
|
|
29
41
|
/**
|
|
30
|
-
*
|
|
31
|
-
* If present, this indicates that the current template represents an alternative version of the specified main template.
|
|
42
|
+
* Unique identifier for this customization
|
|
32
43
|
*/
|
|
33
|
-
|
|
44
|
+
customizationId: string;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The order/priority of this customization, higher values indicate higher priority
|
|
48
|
+
* when multiple customizations exist for the same fragment
|
|
49
|
+
*/
|
|
50
|
+
priority: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Union type representing either a built-in or customized prompt fragment
|
|
55
|
+
*/
|
|
56
|
+
export type PromptFragment = BasePromptFragment | CustomizedPromptFragment;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Type guard to check if a PromptFragment is a built-in fragment (not customized)
|
|
60
|
+
* @param fragment The fragment to check
|
|
61
|
+
* @returns True if the fragment is a basic BasePromptFragment (not customized)
|
|
62
|
+
*/
|
|
63
|
+
export function isBasePromptFragment(fragment: PromptFragment): fragment is BasePromptFragment {
|
|
64
|
+
return !('customizationId' in fragment && 'priority' in fragment);
|
|
34
65
|
}
|
|
35
66
|
|
|
36
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Type guard to check if a PromptFragment is a CustomizedPromptFragment
|
|
69
|
+
* @param fragment The fragment to check
|
|
70
|
+
* @returns True if the fragment is a CustomizedPromptFragment
|
|
71
|
+
*/
|
|
72
|
+
export function isCustomizedPromptFragment(fragment: PromptFragment): fragment is CustomizedPromptFragment {
|
|
73
|
+
return 'customizationId' in fragment && 'priority' in fragment;
|
|
74
|
+
}
|
|
37
75
|
|
|
38
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Map of prompt fragment IDs to prompt fragments
|
|
78
|
+
*/
|
|
79
|
+
export interface PromptMap { [id: string]: PromptFragment }
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Represents a prompt fragment with all variables and function references resolved
|
|
83
|
+
*/
|
|
84
|
+
export interface ResolvedPromptFragment {
|
|
85
|
+
/** The fragment ID */
|
|
39
86
|
id: string;
|
|
40
|
-
|
|
87
|
+
|
|
88
|
+
/** The resolved prompt text with variables and function requests being replaced */
|
|
41
89
|
text: string;
|
|
42
|
-
|
|
90
|
+
|
|
91
|
+
/** All functions referenced in the prompt fragment */
|
|
43
92
|
functionDescriptions?: Map<string, ToolRequest>;
|
|
44
|
-
|
|
93
|
+
|
|
94
|
+
/** All variables resolved in the prompt fragment */
|
|
45
95
|
variables?: ResolvedAIVariable[];
|
|
46
96
|
}
|
|
47
97
|
|
|
48
|
-
|
|
49
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Describes a custom agent with its properties
|
|
100
|
+
*/
|
|
101
|
+
export interface CustomAgentDescription {
|
|
102
|
+
/** Unique identifier for this agent */
|
|
103
|
+
id: string;
|
|
104
|
+
|
|
105
|
+
/** Display name for the agent */
|
|
106
|
+
name: string;
|
|
107
|
+
|
|
108
|
+
/** Description of the agent's purpose and capabilities */
|
|
109
|
+
description: string;
|
|
110
|
+
|
|
111
|
+
/** The prompt text for this agent */
|
|
112
|
+
prompt: string;
|
|
113
|
+
|
|
114
|
+
/** The default large language model to use with this agent */
|
|
115
|
+
defaultLLM: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export namespace CustomAgentDescription {
|
|
50
119
|
/**
|
|
51
|
-
*
|
|
52
|
-
* @param id the id of the {@link PromptTemplate}
|
|
120
|
+
* Type guard to check if an object is a CustomAgentDescription
|
|
53
121
|
*/
|
|
54
|
-
|
|
122
|
+
export function is(entry: unknown): entry is CustomAgentDescription {
|
|
123
|
+
// eslint-disable-next-line no-null/no-null
|
|
124
|
+
return typeof entry === 'object' && entry !== null
|
|
125
|
+
&& 'id' in entry && typeof entry.id === 'string'
|
|
126
|
+
&& 'name' in entry && typeof entry.name === 'string'
|
|
127
|
+
&& 'description' in entry && typeof entry.description === 'string'
|
|
128
|
+
&& 'prompt' in entry && typeof entry.prompt === 'string'
|
|
129
|
+
&& 'defaultLLM' in entry && typeof entry.defaultLLM === 'string';
|
|
130
|
+
}
|
|
131
|
+
|
|
55
132
|
/**
|
|
56
|
-
*
|
|
57
|
-
* @param id the id of the {@link PromptTemplate}
|
|
133
|
+
* Compares two CustomAgentDescription objects for equality
|
|
58
134
|
*/
|
|
59
|
-
|
|
135
|
+
export function equals(a: CustomAgentDescription, b: CustomAgentDescription): boolean {
|
|
136
|
+
return a.id === b.id && a.name === b.name && a.description === b.description && a.prompt === b.prompt && a.defaultLLM === b.defaultLLM;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Service responsible for customizing prompt fragments
|
|
142
|
+
*/
|
|
143
|
+
export const PromptFragmentCustomizationService = Symbol('PromptFragmentCustomizationService');
|
|
144
|
+
export interface PromptFragmentCustomizationService {
|
|
60
145
|
/**
|
|
61
|
-
*
|
|
62
|
-
* @param id the id of the {@link PromptTemplate}
|
|
146
|
+
* Event fired when a prompt fragment is changed
|
|
63
147
|
*/
|
|
64
|
-
|
|
148
|
+
readonly onDidChangePromptFragmentCustomization: Event<string[]>;
|
|
149
|
+
|
|
65
150
|
/**
|
|
66
|
-
*
|
|
67
|
-
* The placeholder is then searched inside the args object and replaced.
|
|
68
|
-
* Function references are also supported via format '~{functionId}'.
|
|
69
|
-
*
|
|
70
|
-
* All placeholders are replaced before function references are resolved.
|
|
71
|
-
* This allows to resolve function references contained in placeholders.
|
|
72
|
-
*
|
|
73
|
-
* @param id the id of the prompt
|
|
74
|
-
* @param args the object with placeholders, mapping the placeholder key to the value
|
|
151
|
+
* Event fired when custom agents are modified
|
|
75
152
|
*/
|
|
76
|
-
|
|
153
|
+
readonly onDidChangeCustomAgents: Event<void>;
|
|
77
154
|
|
|
78
155
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* In contrast to {@link getPrompt}, this method does not resolve function references but leaves them as is.
|
|
83
|
-
* This allows resolving them later as part of the prompt or chat message containing the fragment.
|
|
84
|
-
*
|
|
85
|
-
* @param id the id of the prompt
|
|
86
|
-
* @param args the object with placeholders, mapping the placeholder key to the value
|
|
87
|
-
* @param context the {@link AIVariableContext} to use during variable resolution
|
|
88
|
-
* @param resolveVariable the variable resolving method. Fall back to using the {@link AIVariableService} if not given.
|
|
156
|
+
* Checks if a prompt fragment has customizations
|
|
157
|
+
* @param fragmentId The prompt fragment ID
|
|
158
|
+
* @returns Whether the fragment has any customizations
|
|
89
159
|
*/
|
|
90
|
-
|
|
91
|
-
id: string,
|
|
92
|
-
args?: { [key: string]: unknown },
|
|
93
|
-
context?: AIVariableContext,
|
|
94
|
-
resolveVariable?: (variable: AIVariableArg) => Promise<ResolvedAIVariable | undefined>
|
|
95
|
-
): Promise<Omit<ResolvedPromptTemplate, 'functionDescriptions'> | undefined>;
|
|
160
|
+
isPromptFragmentCustomized(fragmentId: string): boolean;
|
|
96
161
|
|
|
97
162
|
/**
|
|
98
|
-
*
|
|
99
|
-
* @param
|
|
163
|
+
* Gets the active customized prompt fragment for a given ID
|
|
164
|
+
* @param fragmentId The prompt fragment ID
|
|
165
|
+
* @returns The active customized fragment or undefined if none exists
|
|
100
166
|
*/
|
|
101
|
-
|
|
167
|
+
getActivePromptFragmentCustomization(fragmentId: string): CustomizedPromptFragment | undefined;
|
|
168
|
+
|
|
102
169
|
/**
|
|
103
|
-
*
|
|
104
|
-
* @param
|
|
170
|
+
* Gets all customizations for a prompt fragment ordered by priority
|
|
171
|
+
* @param fragmentId The prompt fragment ID
|
|
172
|
+
* @returns Array of customized fragments ordered by priority (highest first)
|
|
105
173
|
*/
|
|
106
|
-
|
|
174
|
+
getAllCustomizations(fragmentId: string): CustomizedPromptFragment[];
|
|
175
|
+
|
|
107
176
|
/**
|
|
108
|
-
*
|
|
177
|
+
* Gets the IDs of all prompt fragments that have customizations
|
|
178
|
+
* @returns Array of prompt fragment IDs
|
|
109
179
|
*/
|
|
110
|
-
|
|
180
|
+
getCustomizedPromptFragmentIds(): string[];
|
|
181
|
+
|
|
111
182
|
/**
|
|
112
|
-
*
|
|
113
|
-
* @param
|
|
114
|
-
* @
|
|
183
|
+
* Creates a new customization for a prompt fragment
|
|
184
|
+
* @param fragmentId The fragment ID to customize
|
|
185
|
+
* @param defaultContent Optional default content for the customization
|
|
115
186
|
*/
|
|
116
|
-
|
|
187
|
+
createPromptFragmentCustomization(fragmentId: string, defaultContent?: string): Promise<void>;
|
|
188
|
+
|
|
117
189
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* @param id the id of the main prompt
|
|
122
|
-
* @returns the variant ID if one is selected, or the main prompt ID otherwise
|
|
190
|
+
* Creates a customization based on a built-in fragment
|
|
191
|
+
* @param fragmentId The ID of the built-in fragment to customize
|
|
192
|
+
* @param defaultContent Optional default content for the customization
|
|
123
193
|
*/
|
|
124
|
-
|
|
125
|
-
}
|
|
194
|
+
createBuiltInPromptFragmentCustomization(fragmentId: string, defaultContent?: string): Promise<void>;
|
|
126
195
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
export namespace CustomAgentDescription {
|
|
135
|
-
export function is(entry: unknown): entry is CustomAgentDescription {
|
|
136
|
-
// eslint-disable-next-line no-null/no-null
|
|
137
|
-
return typeof entry === 'object' && entry !== null
|
|
138
|
-
&& 'id' in entry && typeof entry.id === 'string'
|
|
139
|
-
&& 'name' in entry && typeof entry.name === 'string'
|
|
140
|
-
&& 'description' in entry && typeof entry.description === 'string'
|
|
141
|
-
&& 'prompt' in entry
|
|
142
|
-
&& typeof entry.prompt === 'string'
|
|
143
|
-
&& 'defaultLLM' in entry
|
|
144
|
-
&& typeof entry.defaultLLM === 'string';
|
|
145
|
-
}
|
|
146
|
-
export function equals(a: CustomAgentDescription, b: CustomAgentDescription): boolean {
|
|
147
|
-
return a.id === b.id && a.name === b.name && a.description === b.description && a.prompt === b.prompt && a.defaultLLM === b.defaultLLM;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
196
|
+
/**
|
|
197
|
+
* Edits a specific customization of a prompt fragment
|
|
198
|
+
* @param fragmentId The prompt fragment ID
|
|
199
|
+
* @param customizationId The customization ID to edit
|
|
200
|
+
*/
|
|
201
|
+
editPromptFragmentCustomization(fragmentId: string, customizationId: string): Promise<void>;
|
|
150
202
|
|
|
151
|
-
export const PromptCustomizationService = Symbol('PromptCustomizationService');
|
|
152
|
-
export interface PromptCustomizationService {
|
|
153
203
|
/**
|
|
154
|
-
*
|
|
155
|
-
* @param
|
|
204
|
+
* Edits the built-in customization of a prompt fragment
|
|
205
|
+
* @param fragmentId The prompt fragment ID to edit
|
|
206
|
+
* @param defaultContent Optional default content for the customization
|
|
156
207
|
*/
|
|
157
|
-
|
|
208
|
+
editBuiltInPromptFragmentCustomization(fragmentId: string, defaultContent?: string): Promise<void>;
|
|
158
209
|
|
|
159
210
|
/**
|
|
160
|
-
*
|
|
161
|
-
* @param
|
|
211
|
+
* Removes a specific customization of a prompt fragment
|
|
212
|
+
* @param fragmentId The prompt fragment ID
|
|
213
|
+
* @param customizationId The customization ID to remove
|
|
162
214
|
*/
|
|
163
|
-
|
|
215
|
+
removePromptFragmentCustomization(fragmentId: string, customizationId: string): Promise<void>;
|
|
164
216
|
|
|
165
|
-
getCustomPromptTemplateIDs(): string[];
|
|
166
217
|
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* on the implementation. Implementation may for example decide to
|
|
170
|
-
* open an editor, or request more information from the user, ...
|
|
171
|
-
* @param id the template id.
|
|
172
|
-
* @param content optional default content to initialize the template
|
|
218
|
+
* Resets a fragment to its built-in version by removing all customizations
|
|
219
|
+
* @param fragmentId The fragment ID to reset
|
|
173
220
|
*/
|
|
174
|
-
|
|
221
|
+
removeAllPromptFragmentCustomizations(fragmentId: string): Promise<void>;
|
|
175
222
|
|
|
176
223
|
/**
|
|
177
|
-
*
|
|
178
|
-
* @param
|
|
224
|
+
* Resets to a specific customization by removing higher-priority customizations
|
|
225
|
+
* @param fragmentId The fragment ID
|
|
226
|
+
* @param customizationId The customization ID to reset to
|
|
179
227
|
*/
|
|
180
|
-
|
|
228
|
+
resetToCustomization(fragmentId: string, customizationId: string): Promise<void>;
|
|
181
229
|
|
|
182
230
|
/**
|
|
183
|
-
*
|
|
184
|
-
* @param
|
|
231
|
+
* Gets information about the description of a customization
|
|
232
|
+
* @param fragmentId The fragment ID
|
|
233
|
+
* @param customizationId The customization ID
|
|
234
|
+
* @returns Description of the customization
|
|
185
235
|
*/
|
|
186
|
-
|
|
236
|
+
getPromptFragmentCustomizationDescription(fragmentId: string, customizationId: string): Promise<string | undefined>;
|
|
187
237
|
|
|
188
238
|
/**
|
|
189
|
-
*
|
|
239
|
+
* Gets information about the source/type of a customization
|
|
240
|
+
* @param fragmentId The fragment ID
|
|
241
|
+
* @param customizationId The customization ID
|
|
242
|
+
* @returns Type of the customization source
|
|
190
243
|
*/
|
|
191
|
-
|
|
244
|
+
getPromptFragmentCustomizationType(fragmentId: string, customizationId: string): Promise<string | undefined>;
|
|
192
245
|
|
|
193
246
|
/**
|
|
194
|
-
*
|
|
195
|
-
* @
|
|
247
|
+
* Gets the fragment ID from a resource identifier
|
|
248
|
+
* @param resourceId Resource identifier (implementation specific)
|
|
249
|
+
* @returns Fragment ID or undefined if not found
|
|
196
250
|
*/
|
|
197
|
-
|
|
251
|
+
getPromptFragmentIDFromResource(resourceId: unknown): string | undefined;
|
|
198
252
|
|
|
199
253
|
/**
|
|
200
|
-
*
|
|
254
|
+
* Gets all custom agent descriptions
|
|
255
|
+
* @returns Array of custom agent descriptions
|
|
201
256
|
*/
|
|
202
|
-
|
|
257
|
+
getCustomAgents(): Promise<CustomAgentDescription[]>;
|
|
203
258
|
|
|
204
259
|
/**
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
* @returns An array of objects containing the URI and whether the file exists
|
|
260
|
+
* Gets the locations of custom agent configuration files
|
|
261
|
+
* @returns Array of URIs and existence status
|
|
209
262
|
*/
|
|
210
263
|
getCustomAgentsLocations(): Promise<{ uri: URI, exists: boolean }[]>;
|
|
211
264
|
|
|
@@ -217,13 +270,149 @@ export interface PromptCustomizationService {
|
|
|
217
270
|
openCustomAgentYaml(uri: URI): Promise<void>;
|
|
218
271
|
}
|
|
219
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Service for managing and resolving prompt fragments
|
|
275
|
+
*/
|
|
276
|
+
export const PromptService = Symbol('PromptService');
|
|
277
|
+
export interface PromptService {
|
|
278
|
+
/**
|
|
279
|
+
* Event fired when the prompts change
|
|
280
|
+
*/
|
|
281
|
+
readonly onPromptsChange: Event<void>;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Event fired when the selected variant for a prompt variant set changes
|
|
285
|
+
*/
|
|
286
|
+
readonly onSelectedVariantChange: Event<{ promptVariantSetId: string, variantId: string }>;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Gets the raw prompt fragment with comments
|
|
290
|
+
* @param fragmentId The prompt fragment ID
|
|
291
|
+
* @returns The raw prompt fragment or undefined if not found
|
|
292
|
+
*/
|
|
293
|
+
getRawPromptFragment(fragmentId: string): PromptFragment | undefined;
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Gets the raw prompt fragment without comments
|
|
297
|
+
* @param fragmentId The prompt fragment ID
|
|
298
|
+
* @returns The raw prompt fragment or undefined if not found
|
|
299
|
+
*/
|
|
300
|
+
getPromptFragment(fragmentId: string): PromptFragment | undefined;
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Gets the built-in raw prompt fragment (before any customizations)
|
|
304
|
+
* @param fragmentId The prompt fragment ID
|
|
305
|
+
* @returns The built-in fragment or undefined if not found
|
|
306
|
+
*/
|
|
307
|
+
getBuiltInRawPrompt(fragmentId: string): PromptFragment | undefined;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Resolves a prompt fragment by replacing variables and function references
|
|
311
|
+
* @param fragmentId The prompt fragment ID
|
|
312
|
+
* @param args Optional object with values for variable replacement
|
|
313
|
+
* @param context Optional context for variable resolution
|
|
314
|
+
* @returns The resolved prompt fragment or undefined if not found
|
|
315
|
+
*/
|
|
316
|
+
getResolvedPromptFragment(fragmentId: string, args?: { [key: string]: unknown }, context?: AIVariableContext): Promise<ResolvedPromptFragment | undefined>;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Resolves a prompt fragment by replacing variables but preserving function references
|
|
320
|
+
* @param fragmentId The prompt fragment ID
|
|
321
|
+
* @param args Optional object with values for variable replacement
|
|
322
|
+
* @param context Optional context for variable resolution
|
|
323
|
+
* @param resolveVariable Optional custom variable resolution function
|
|
324
|
+
* @returns The partially resolved prompt fragment or undefined if not found
|
|
325
|
+
*/
|
|
326
|
+
getResolvedPromptFragmentWithoutFunctions(
|
|
327
|
+
fragmentId: string,
|
|
328
|
+
args?: { [key: string]: unknown },
|
|
329
|
+
context?: AIVariableContext,
|
|
330
|
+
resolveVariable?: (variable: AIVariableArg) => Promise<ResolvedAIVariable | undefined>
|
|
331
|
+
): Promise<Omit<ResolvedPromptFragment, 'functionDescriptions'> | undefined>;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Adds a prompt fragment to the service
|
|
335
|
+
* @param promptFragment The fragment to store
|
|
336
|
+
* @param promptVariantSetId Optional ID of the prompt variant set this is a variant of
|
|
337
|
+
*/
|
|
338
|
+
addBuiltInPromptFragment(promptFragment: BasePromptFragment, promptVariantSetId?: string, isDefault?: boolean): void;
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Removes a prompt fragment from the service
|
|
342
|
+
* @param fragmentId The fragment ID to remove
|
|
343
|
+
*/
|
|
344
|
+
removePromptFragment(fragmentId: string): void;
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Gets all known prompts, including variants and customizations
|
|
348
|
+
* @returns Map of fragment IDs to arrays of fragments
|
|
349
|
+
*/
|
|
350
|
+
getAllPromptFragments(): Map<string, PromptFragment[]>;
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Gets all active prompts (highest priority version of each fragment)
|
|
354
|
+
* @returns Array of active prompt fragments
|
|
355
|
+
*/
|
|
356
|
+
getActivePromptFragments(): PromptFragment[];
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Returns all IDs of all prompt fragments of the given set
|
|
360
|
+
* @param promptVariantSetId The prompt variant set id
|
|
361
|
+
* @returns Array of variant IDs
|
|
362
|
+
*/
|
|
363
|
+
getVariantIds(promptVariantSetId: string): string[];
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Gets the currently selected variant ID of the given set
|
|
367
|
+
* @param promptVariantSetId The prompt variant set id
|
|
368
|
+
* @returns The selected variant ID or the main ID if no variant is selected
|
|
369
|
+
*/
|
|
370
|
+
getSelectedVariantId(promptVariantSetId: string): Promise<string | undefined>;
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Gets the default variant ID of the given set
|
|
374
|
+
* @param promptVariantSetId The prompt variant set id
|
|
375
|
+
* @returns The default variant ID or undefined if no default is set
|
|
376
|
+
*/
|
|
377
|
+
getDefaultVariantId(promptVariantSetId: string): string | undefined;
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Updates the selected variant for a prompt variant set
|
|
381
|
+
* @param agentId The ID of the agent to update
|
|
382
|
+
* @param promptVariantSetId The prompt variant set ID
|
|
383
|
+
* @param newVariant The new variant ID to set as selected
|
|
384
|
+
*/
|
|
385
|
+
updateSelectedVariantId(agentId: string, promptVariantSetId: string, newVariant: string): Promise<void>;
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Gets all prompt variant sets and their variants
|
|
389
|
+
* @returns Map of prompt variant set IDs to arrays of variant IDs
|
|
390
|
+
*/
|
|
391
|
+
getPromptVariantSets(): Map<string, string[]>;
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* The following methods delegate to the PromptFragmentCustomizationService
|
|
395
|
+
*/
|
|
396
|
+
createCustomization(fragmentId: string): Promise<void>;
|
|
397
|
+
createBuiltInCustomization(fragmentId: string): Promise<void>;
|
|
398
|
+
editBuiltInCustomization(fragmentId: string): Promise<void>;
|
|
399
|
+
editCustomization(fragmentId: string, customizationId: string): Promise<void>;
|
|
400
|
+
removeCustomization(fragmentId: string, customizationId: string): Promise<void>;
|
|
401
|
+
resetAllToBuiltIn(): Promise<void>;
|
|
402
|
+
resetToBuiltIn(fragmentId: string): Promise<void>;
|
|
403
|
+
resetToCustomization(fragmentId: string, customizationId: string): Promise<void>;
|
|
404
|
+
getCustomizationDescription(fragmentId: string, customizationId: string): Promise<string | undefined>;
|
|
405
|
+
getCustomizationType(fragmentId: string, customizationId: string): Promise<string | undefined>;
|
|
406
|
+
getTemplateIDFromResource(resourceId: unknown): string | undefined;
|
|
407
|
+
}
|
|
408
|
+
|
|
220
409
|
@injectable()
|
|
221
410
|
export class PromptServiceImpl implements PromptService {
|
|
222
411
|
@inject(AISettingsService) @optional()
|
|
223
412
|
protected readonly settingsService: AISettingsService | undefined;
|
|
224
413
|
|
|
225
|
-
@inject(
|
|
226
|
-
protected readonly customizationService:
|
|
414
|
+
@inject(PromptFragmentCustomizationService) @optional()
|
|
415
|
+
protected readonly customizationService: PromptFragmentCustomizationService | undefined;
|
|
227
416
|
|
|
228
417
|
@inject(AIVariableService) @optional()
|
|
229
418
|
protected readonly variableService: AIVariableService | undefined;
|
|
@@ -231,199 +420,483 @@ export class PromptServiceImpl implements PromptService {
|
|
|
231
420
|
@inject(ToolInvocationRegistry) @optional()
|
|
232
421
|
protected readonly toolInvocationRegistry: ToolInvocationRegistry | undefined;
|
|
233
422
|
|
|
234
|
-
|
|
423
|
+
// Collection of built-in prompt fragments
|
|
424
|
+
protected _builtInFragments: BasePromptFragment[] = [];
|
|
425
|
+
|
|
426
|
+
// Map to store prompt variants sets (key: promptVariantSetId, value: array of variantIds)
|
|
427
|
+
protected _promptVariantSetsMap = new Map<string, string[]>();
|
|
428
|
+
|
|
429
|
+
// Map to store default variant for each prompt variant set (key: promptVariantSetId, value: variantId)
|
|
430
|
+
protected _defaultVariantsMap = new Map<string, string>();
|
|
431
|
+
|
|
432
|
+
// Event emitter for prompt changes
|
|
433
|
+
protected _onPromptsChangeEmitter = new Emitter<void>();
|
|
434
|
+
readonly onPromptsChange = this._onPromptsChangeEmitter.event;
|
|
435
|
+
|
|
436
|
+
// Event emitter for selected variant changes
|
|
437
|
+
protected _onSelectedVariantChangeEmitter = new Emitter<{ promptVariantSetId: string, variantId: string }>();
|
|
438
|
+
readonly onSelectedVariantChange = this._onSelectedVariantChangeEmitter.event;
|
|
439
|
+
|
|
440
|
+
@postConstruct()
|
|
441
|
+
protected init(): void {
|
|
442
|
+
if (this.customizationService) {
|
|
443
|
+
this.customizationService.onDidChangePromptFragmentCustomization(() => {
|
|
444
|
+
this._onPromptsChangeEmitter.fire();
|
|
445
|
+
});
|
|
446
|
+
this.customizationService.onDidChangeCustomAgents(() => {
|
|
447
|
+
this._onPromptsChangeEmitter.fire();
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// ===== Fragment Retrieval Methods =====
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Finds a built-in fragment by its ID
|
|
456
|
+
* @param fragmentId The ID of the fragment to find
|
|
457
|
+
* @returns The built-in fragment or undefined if not found
|
|
458
|
+
*/
|
|
459
|
+
protected findBuiltInFragmentById(fragmentId: string): BasePromptFragment | undefined {
|
|
460
|
+
return this._builtInFragments.find(fragment => fragment.id === fragmentId);
|
|
461
|
+
}
|
|
235
462
|
|
|
236
|
-
|
|
237
|
-
if (this.customizationService
|
|
238
|
-
const
|
|
239
|
-
if (
|
|
240
|
-
return
|
|
463
|
+
getRawPromptFragment(fragmentId: string): PromptFragment | undefined {
|
|
464
|
+
if (this.customizationService?.isPromptFragmentCustomized(fragmentId)) {
|
|
465
|
+
const customizedFragment = this.customizationService.getActivePromptFragmentCustomization(fragmentId);
|
|
466
|
+
if (customizedFragment !== undefined) {
|
|
467
|
+
return customizedFragment;
|
|
241
468
|
}
|
|
242
469
|
}
|
|
243
|
-
return this.
|
|
470
|
+
return this.getBuiltInRawPrompt(fragmentId);
|
|
244
471
|
}
|
|
245
|
-
|
|
246
|
-
|
|
472
|
+
|
|
473
|
+
getBuiltInRawPrompt(fragmentId: string): PromptFragment | undefined {
|
|
474
|
+
return this.findBuiltInFragmentById(fragmentId);
|
|
247
475
|
}
|
|
248
476
|
|
|
249
|
-
|
|
250
|
-
const
|
|
251
|
-
if (!
|
|
477
|
+
getPromptFragment(fragmentId: string): PromptFragment | undefined {
|
|
478
|
+
const rawFragment = this.getRawPromptFragment(fragmentId);
|
|
479
|
+
if (!rawFragment) {
|
|
252
480
|
return undefined;
|
|
253
481
|
}
|
|
254
482
|
return {
|
|
255
|
-
|
|
256
|
-
template: this.stripComments(
|
|
483
|
+
...rawFragment,
|
|
484
|
+
template: this.stripComments(rawFragment.template)
|
|
257
485
|
};
|
|
258
486
|
}
|
|
259
487
|
|
|
260
|
-
|
|
488
|
+
/**
|
|
489
|
+
* Strips comments from a template string
|
|
490
|
+
* @param templateText The template text to process
|
|
491
|
+
* @returns Template text with comments removed
|
|
492
|
+
*/
|
|
493
|
+
protected stripComments(templateText: string): string {
|
|
261
494
|
const commentRegex = /^\s*{{!--[\s\S]*?--}}\s*\n?/;
|
|
262
|
-
return commentRegex.test(
|
|
495
|
+
return commentRegex.test(templateText) ? templateText.replace(commentRegex, '').trimStart() : templateText;
|
|
263
496
|
}
|
|
264
497
|
|
|
265
|
-
async
|
|
266
|
-
if (this.settingsService
|
|
498
|
+
async getSelectedVariantId(fragmentId: string): Promise<string | undefined> {
|
|
499
|
+
if (this.settingsService) {
|
|
267
500
|
const agentSettingsMap = await this.settingsService.getSettings();
|
|
268
501
|
|
|
269
502
|
for (const agentSettings of Object.values(agentSettingsMap)) {
|
|
270
|
-
if (agentSettings.selectedVariants && agentSettings.selectedVariants[
|
|
271
|
-
return agentSettings.selectedVariants[
|
|
503
|
+
if (agentSettings.selectedVariants && agentSettings.selectedVariants[fragmentId]) {
|
|
504
|
+
return agentSettings.selectedVariants[fragmentId];
|
|
272
505
|
}
|
|
273
506
|
}
|
|
274
507
|
}
|
|
275
|
-
return
|
|
508
|
+
return this.getDefaultVariantId(fragmentId);
|
|
276
509
|
}
|
|
277
510
|
|
|
278
|
-
async
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
511
|
+
protected async resolvePotentialSystemPrompt(promptFragmentId: string): Promise<PromptFragment | undefined> {
|
|
512
|
+
if (this._promptVariantSetsMap.has(promptFragmentId)) {
|
|
513
|
+
// This is a systemPrompt find the selected variant
|
|
514
|
+
const selectedVariantId = await this.getSelectedVariantId(promptFragmentId);
|
|
515
|
+
if (selectedVariantId === undefined) {
|
|
516
|
+
return undefined;
|
|
517
|
+
}
|
|
518
|
+
return this.getPromptFragment(selectedVariantId);
|
|
519
|
+
}
|
|
520
|
+
return this.getPromptFragment(promptFragmentId);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// ===== Fragment Resolution Methods =====
|
|
524
|
+
|
|
525
|
+
async getResolvedPromptFragment(systemOrFragmentId: string, args?: { [key: string]: unknown }, context?: AIVariableContext): Promise<ResolvedPromptFragment | undefined> {
|
|
526
|
+
const promptFragment = await this.resolvePotentialSystemPrompt(systemOrFragmentId);
|
|
527
|
+
if (promptFragment === undefined) {
|
|
282
528
|
return undefined;
|
|
283
529
|
}
|
|
284
530
|
|
|
285
531
|
// First resolve variables and arguments
|
|
286
|
-
let resolvedTemplate =
|
|
287
|
-
const
|
|
288
|
-
|
|
532
|
+
let resolvedTemplate = promptFragment.template;
|
|
533
|
+
const variableAndArgResolutions = await this.resolveVariablesAndArgs(promptFragment.template, args, context);
|
|
534
|
+
variableAndArgResolutions.replacements.forEach(replacement =>
|
|
535
|
+
resolvedTemplate = resolvedTemplate.replace(replacement.placeholder, replacement.value));
|
|
289
536
|
|
|
290
537
|
// Then resolve function references with already resolved variables and arguments
|
|
291
538
|
// This allows to resolve function references contained in resolved variables (e.g. prompt fragments)
|
|
292
539
|
const functionMatches = matchFunctionsRegEx(resolvedTemplate);
|
|
293
|
-
const
|
|
540
|
+
const functionMap = new Map<string, ToolRequest>();
|
|
294
541
|
const functionReplacements = functionMatches.map(match => {
|
|
295
542
|
const completeText = match[0];
|
|
296
543
|
const functionId = match[1];
|
|
297
544
|
const toolRequest = this.toolInvocationRegistry?.getFunction(functionId);
|
|
298
545
|
if (toolRequest) {
|
|
299
|
-
|
|
546
|
+
functionMap.set(toolRequest.id, toolRequest);
|
|
300
547
|
}
|
|
301
548
|
return {
|
|
302
549
|
placeholder: completeText,
|
|
303
550
|
value: toolRequest ? toolRequestToPromptText(toolRequest) : completeText
|
|
304
551
|
};
|
|
305
552
|
});
|
|
306
|
-
functionReplacements.forEach(replacement =>
|
|
553
|
+
functionReplacements.forEach(replacement =>
|
|
554
|
+
resolvedTemplate = resolvedTemplate.replace(replacement.placeholder, replacement.value));
|
|
307
555
|
|
|
308
556
|
return {
|
|
309
|
-
id,
|
|
557
|
+
id: systemOrFragmentId,
|
|
310
558
|
text: resolvedTemplate,
|
|
311
|
-
functionDescriptions:
|
|
312
|
-
variables:
|
|
559
|
+
functionDescriptions: functionMap.size > 0 ? functionMap : undefined,
|
|
560
|
+
variables: variableAndArgResolutions.resolvedVariables
|
|
313
561
|
};
|
|
314
562
|
}
|
|
315
563
|
|
|
316
|
-
async
|
|
317
|
-
|
|
564
|
+
async getResolvedPromptFragmentWithoutFunctions(
|
|
565
|
+
systemOrFragmentId: string,
|
|
318
566
|
args?: { [key: string]: unknown },
|
|
319
567
|
context?: AIVariableContext,
|
|
320
568
|
resolveVariable?: (variable: AIVariableArg) => Promise<ResolvedAIVariable | undefined>
|
|
321
|
-
): Promise<Omit<
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
if (prompt === undefined) {
|
|
569
|
+
): Promise<Omit<ResolvedPromptFragment, 'functionDescriptions'> | undefined> {
|
|
570
|
+
const promptFragment = await this.resolvePotentialSystemPrompt(systemOrFragmentId);
|
|
571
|
+
if (promptFragment === undefined) {
|
|
325
572
|
return undefined;
|
|
326
573
|
}
|
|
327
574
|
|
|
328
|
-
const
|
|
329
|
-
let resolvedTemplate =
|
|
330
|
-
|
|
575
|
+
const resolutions = await this.resolveVariablesAndArgs(promptFragment.template, args, context, resolveVariable);
|
|
576
|
+
let resolvedTemplate = promptFragment.template;
|
|
577
|
+
resolutions.replacements.forEach(replacement =>
|
|
578
|
+
resolvedTemplate = resolvedTemplate.replace(replacement.placeholder, replacement.value));
|
|
331
579
|
|
|
332
580
|
return {
|
|
333
|
-
id,
|
|
581
|
+
id: systemOrFragmentId,
|
|
334
582
|
text: resolvedTemplate,
|
|
335
|
-
variables:
|
|
583
|
+
variables: resolutions.resolvedVariables
|
|
336
584
|
};
|
|
337
585
|
}
|
|
338
586
|
|
|
339
587
|
/**
|
|
340
588
|
* Calculates all variable and argument replacements for an unresolved template.
|
|
341
589
|
*
|
|
342
|
-
* @param
|
|
590
|
+
* @param templateText the unresolved template text
|
|
343
591
|
* @param args the object with placeholders, mapping the placeholder key to the value
|
|
344
592
|
* @param context the {@link AIVariableContext} to use during variable resolution
|
|
345
593
|
* @param resolveVariable the variable resolving method. Fall back to using the {@link AIVariableService} if not given.
|
|
594
|
+
* @returns Object containing replacements and resolved variables
|
|
346
595
|
*/
|
|
347
|
-
protected async
|
|
348
|
-
|
|
596
|
+
protected async resolveVariablesAndArgs(
|
|
597
|
+
templateText: string,
|
|
349
598
|
args?: { [key: string]: unknown },
|
|
350
599
|
context?: AIVariableContext,
|
|
351
600
|
resolveVariable?: (variable: AIVariableArg) => Promise<ResolvedAIVariable | undefined>
|
|
352
|
-
): Promise<{
|
|
353
|
-
|
|
601
|
+
): Promise<{
|
|
602
|
+
replacements: { placeholder: string; value: string }[],
|
|
603
|
+
resolvedVariables: ResolvedAIVariable[]
|
|
604
|
+
}> {
|
|
605
|
+
const variableMatches = matchVariablesRegEx(templateText);
|
|
354
606
|
const variableCache = createAIResolveVariableCache();
|
|
355
|
-
const
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
607
|
+
const replacementsList: { placeholder: string; value: string }[] = [];
|
|
608
|
+
const resolvedVariablesSet: Set<ResolvedAIVariable> = new Set();
|
|
609
|
+
|
|
610
|
+
for (const match of variableMatches) {
|
|
611
|
+
const placeholderText = match[0];
|
|
359
612
|
const variableAndArg = match[1];
|
|
360
613
|
let variableName = variableAndArg;
|
|
361
614
|
let argument: string | undefined;
|
|
615
|
+
|
|
362
616
|
const parts = variableAndArg.split(':', 2);
|
|
363
617
|
if (parts.length > 1) {
|
|
364
618
|
variableName = parts[0];
|
|
365
619
|
argument = parts[1];
|
|
366
620
|
}
|
|
367
|
-
|
|
621
|
+
|
|
622
|
+
let replacementValue: string;
|
|
368
623
|
if (args && args[variableAndArg] !== undefined) {
|
|
369
|
-
|
|
624
|
+
replacementValue = String(args[variableAndArg]);
|
|
370
625
|
} else {
|
|
371
|
-
const
|
|
372
|
-
const
|
|
373
|
-
? await resolveVariable(
|
|
374
|
-
: await this.variableService?.resolveVariable(
|
|
626
|
+
const variableToResolve = { variable: variableName, arg: argument };
|
|
627
|
+
const resolvedVariable = resolveVariable
|
|
628
|
+
? await resolveVariable(variableToResolve)
|
|
629
|
+
: await this.variableService?.resolveVariable(variableToResolve, context ?? {}, variableCache);
|
|
630
|
+
|
|
375
631
|
// Track resolved variable and its dependencies in all resolved variables
|
|
376
|
-
if (
|
|
377
|
-
|
|
378
|
-
|
|
632
|
+
if (resolvedVariable) {
|
|
633
|
+
resolvedVariablesSet.add(resolvedVariable);
|
|
634
|
+
resolvedVariable.allResolvedDependencies?.forEach(v => resolvedVariablesSet.add(v));
|
|
635
|
+
}
|
|
636
|
+
replacementValue = String(resolvedVariable?.value ?? placeholderText);
|
|
637
|
+
}
|
|
638
|
+
replacementsList.push({ placeholder: placeholderText, value: replacementValue });
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
return {
|
|
642
|
+
replacements: replacementsList,
|
|
643
|
+
resolvedVariables: Array.from(resolvedVariablesSet)
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// ===== Fragment Collection Management Methods =====
|
|
648
|
+
|
|
649
|
+
getAllPromptFragments(): Map<string, PromptFragment[]> {
|
|
650
|
+
const fragmentsMap = new Map<string, PromptFragment[]>();
|
|
651
|
+
|
|
652
|
+
if (this.customizationService) {
|
|
653
|
+
const customizationIds = this.customizationService.getCustomizedPromptFragmentIds();
|
|
654
|
+
customizationIds.forEach(fragmentId => {
|
|
655
|
+
const customizations = this.customizationService!.getAllCustomizations(fragmentId);
|
|
656
|
+
if (customizations.length > 0) {
|
|
657
|
+
fragmentsMap.set(fragmentId, customizations);
|
|
379
658
|
}
|
|
380
|
-
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// Add all built-in fragments
|
|
663
|
+
for (const fragment of this._builtInFragments) {
|
|
664
|
+
if (fragmentsMap.has(fragment.id)) {
|
|
665
|
+
fragmentsMap.get(fragment.id)!.push(fragment);
|
|
666
|
+
} else {
|
|
667
|
+
fragmentsMap.set(fragment.id, [fragment]);
|
|
381
668
|
}
|
|
382
|
-
variableAndArgReplacements.push({ placeholder: completeText, value });
|
|
383
669
|
}
|
|
384
670
|
|
|
385
|
-
return
|
|
671
|
+
return fragmentsMap;
|
|
386
672
|
}
|
|
387
673
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
674
|
+
getActivePromptFragments(): PromptFragment[] {
|
|
675
|
+
const activeFragments: PromptFragment[] = [...this._builtInFragments];
|
|
676
|
+
|
|
677
|
+
if (this.customizationService) {
|
|
678
|
+
// Fetch all customized fragment IDs once
|
|
679
|
+
const customizedIds = this.customizationService.getCustomizedPromptFragmentIds();
|
|
680
|
+
|
|
681
|
+
// For each customized ID, get the active customization
|
|
682
|
+
for (const fragmentId of customizedIds) {
|
|
683
|
+
const customFragment = this.customizationService?.getActivePromptFragmentCustomization(fragmentId);
|
|
684
|
+
if (customFragment) {
|
|
685
|
+
// Find and replace existing entry with the same ID instead of just adding
|
|
686
|
+
const existingIndex = activeFragments.findIndex(fragment => fragment.id === fragmentId);
|
|
687
|
+
if (existingIndex !== -1) {
|
|
688
|
+
// Replace existing fragment
|
|
689
|
+
activeFragments[existingIndex] = customFragment;
|
|
397
690
|
} else {
|
|
398
|
-
|
|
691
|
+
// Add new fragment if no existing one found
|
|
692
|
+
activeFragments.push(customFragment);
|
|
399
693
|
}
|
|
400
|
-
} else {
|
|
401
|
-
result[id] = { ...this._prompts[id] };
|
|
402
694
|
}
|
|
403
|
-
}
|
|
404
|
-
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
return activeFragments;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
removePromptFragment(fragmentId: string): void {
|
|
701
|
+
const index = this._builtInFragments.findIndex(fragment => fragment.id === fragmentId);
|
|
702
|
+
if (index !== -1) {
|
|
703
|
+
this._builtInFragments.splice(index, 1);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
// Remove any variant references
|
|
707
|
+
for (const [promptVariantSetId, variants] of this._promptVariantSetsMap.entries()) {
|
|
708
|
+
if (variants.includes(fragmentId)) {
|
|
709
|
+
this.removeFragmentVariant(promptVariantSetId, fragmentId);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// Clean up default variants map if needed
|
|
714
|
+
if (this._defaultVariantsMap.has(fragmentId)) {
|
|
715
|
+
this._defaultVariantsMap.delete(fragmentId);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Look for this fragmentId as a variant in default variants and remove if found
|
|
719
|
+
for (const [promptVariantSetId, defaultVariantId] of this._defaultVariantsMap.entries()) {
|
|
720
|
+
if (defaultVariantId === fragmentId) {
|
|
721
|
+
this._defaultVariantsMap.delete(promptVariantSetId);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
this._onPromptsChangeEmitter.fire();
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
getVariantIds(fragmentId: string): string[] {
|
|
729
|
+
return this._promptVariantSetsMap.get(fragmentId) || [];
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
getDefaultVariantId(promptVariantSetId: string): string | undefined {
|
|
733
|
+
return this._defaultVariantsMap.get(promptVariantSetId);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
getPromptVariantSets(): Map<string, string[]> {
|
|
737
|
+
return new Map(this._promptVariantSetsMap);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
addBuiltInPromptFragment(promptFragment: BasePromptFragment, promptVariantSetId?: string, isDefault: boolean = false): void {
|
|
741
|
+
const existingIndex = this._builtInFragments.findIndex(fragment => fragment.id === promptFragment.id);
|
|
742
|
+
if (existingIndex !== -1) {
|
|
743
|
+
// Replace existing fragment with the same ID
|
|
744
|
+
this._builtInFragments[existingIndex] = promptFragment;
|
|
405
745
|
} else {
|
|
406
|
-
|
|
746
|
+
// Add new fragment
|
|
747
|
+
this._builtInFragments.push(promptFragment);
|
|
407
748
|
}
|
|
749
|
+
|
|
750
|
+
// If this is a variant of a prompt variant set, record it in the variants map
|
|
751
|
+
if (promptVariantSetId) {
|
|
752
|
+
this.addFragmentVariant(promptVariantSetId, promptFragment.id, isDefault);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
this._onPromptsChangeEmitter.fire();
|
|
408
756
|
}
|
|
409
|
-
|
|
410
|
-
|
|
757
|
+
|
|
758
|
+
// ===== Variant Management Methods =====
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* Adds a variant ID to the fragment variants map
|
|
762
|
+
* @param promptVariantSetId The prompt variant set id
|
|
763
|
+
* @param variantId The variant ID to add
|
|
764
|
+
* @param isDefault Whether this variant should be the default for the prompt variant set (defaults to false)
|
|
765
|
+
*/
|
|
766
|
+
protected addFragmentVariant(promptVariantSetId: string, variantId: string, isDefault: boolean = false): void {
|
|
767
|
+
if (!this._promptVariantSetsMap.has(promptVariantSetId)) {
|
|
768
|
+
this._promptVariantSetsMap.set(promptVariantSetId, []);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
const variants = this._promptVariantSetsMap.get(promptVariantSetId)!;
|
|
772
|
+
if (!variants.includes(variantId)) {
|
|
773
|
+
variants.push(variantId);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
if (isDefault) {
|
|
777
|
+
this._defaultVariantsMap.set(promptVariantSetId, variantId);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* Removes a variant ID from the fragment variants map
|
|
783
|
+
* @param promptVariantSetId The prompt variant set id
|
|
784
|
+
* @param variantId The variant ID to remove
|
|
785
|
+
*/
|
|
786
|
+
protected removeFragmentVariant(promptVariantSetId: string, variantId: string): void {
|
|
787
|
+
if (!this._promptVariantSetsMap.has(promptVariantSetId)) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
const variants = this._promptVariantSetsMap.get(promptVariantSetId)!;
|
|
792
|
+
const index = variants.indexOf(variantId);
|
|
793
|
+
|
|
794
|
+
if (index !== -1) {
|
|
795
|
+
variants.splice(index, 1);
|
|
796
|
+
|
|
797
|
+
// Remove the key if no variants left
|
|
798
|
+
if (variants.length === 0) {
|
|
799
|
+
this._promptVariantSetsMap.delete(promptVariantSetId);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
411
802
|
}
|
|
412
|
-
getVariantIds(id: string): string[] {
|
|
413
|
-
const allCustomPromptTemplateIds = this.customizationService?.getCustomPromptTemplateIDs() || [];
|
|
414
|
-
const knownPromptIds = Object.keys(this._prompts);
|
|
415
803
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
804
|
+
async updateSelectedVariantId(agentId: string, promptVariantSetId: string, newVariant: string): Promise<void> {
|
|
805
|
+
if (!this.settingsService) {
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
const defaultVariantId = this.getDefaultVariantId(promptVariantSetId);
|
|
810
|
+
const agentSettings = await this.settingsService.getAgentSettings(agentId);
|
|
811
|
+
const selectedVariants = agentSettings?.selectedVariants || {};
|
|
423
812
|
|
|
424
|
-
|
|
813
|
+
const updatedVariants = { ...selectedVariants };
|
|
814
|
+
if (newVariant === defaultVariantId) {
|
|
815
|
+
delete updatedVariants[promptVariantSetId];
|
|
816
|
+
} else {
|
|
817
|
+
updatedVariants[promptVariantSetId] = newVariant;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
await this.settingsService.updateAgentSettings(agentId, {
|
|
821
|
+
selectedVariants: updatedVariants,
|
|
822
|
+
});
|
|
823
|
+
|
|
824
|
+
// Emit the selected variant change event
|
|
825
|
+
this._onSelectedVariantChangeEmitter.fire({ promptVariantSetId, variantId: newVariant });
|
|
425
826
|
}
|
|
426
|
-
|
|
427
|
-
|
|
827
|
+
|
|
828
|
+
// ===== Customization Service Delegation Methods =====
|
|
829
|
+
|
|
830
|
+
async createCustomization(fragmentId: string): Promise<void> {
|
|
831
|
+
if (this.customizationService) {
|
|
832
|
+
await this.customizationService.createPromptFragmentCustomization(fragmentId);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
async createBuiltInCustomization(fragmentId: string): Promise<void> {
|
|
837
|
+
if (this.customizationService) {
|
|
838
|
+
const builtInTemplate = this.findBuiltInFragmentById(fragmentId);
|
|
839
|
+
await this.customizationService.createBuiltInPromptFragmentCustomization(fragmentId, builtInTemplate?.template);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
async editCustomization(fragmentId: string, customizationId: string): Promise<void> {
|
|
844
|
+
if (this.customizationService) {
|
|
845
|
+
await this.customizationService.editPromptFragmentCustomization(fragmentId, customizationId);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
async removeCustomization(fragmentId: string, customizationId: string): Promise<void> {
|
|
850
|
+
if (this.customizationService) {
|
|
851
|
+
await this.customizationService.removePromptFragmentCustomization(fragmentId, customizationId);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
async resetAllToBuiltIn(): Promise<void> {
|
|
856
|
+
if (this.customizationService) {
|
|
857
|
+
for (const fragment of this._builtInFragments) {
|
|
858
|
+
await this.customizationService.removeAllPromptFragmentCustomizations(fragment.id);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
async resetToBuiltIn(fragmentId: string): Promise<void> {
|
|
864
|
+
if (this.customizationService) {
|
|
865
|
+
await this.customizationService.removeAllPromptFragmentCustomizations(fragmentId);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
async resetToCustomization(fragmentId: string, customizationId: string): Promise<void> {
|
|
870
|
+
if (this.customizationService) {
|
|
871
|
+
await this.customizationService.resetToCustomization(fragmentId, customizationId);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
async getCustomizationDescription(fragmentId: string, customizationId: string): Promise<string | undefined> {
|
|
876
|
+
if (!this.customizationService) {
|
|
877
|
+
return undefined;
|
|
878
|
+
}
|
|
879
|
+
return await this.customizationService.getPromptFragmentCustomizationDescription(fragmentId, customizationId);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
async getCustomizationType(fragmentId: string, customizationId: string): Promise<string | undefined> {
|
|
883
|
+
if (!this.customizationService) {
|
|
884
|
+
return undefined;
|
|
885
|
+
}
|
|
886
|
+
return await this.customizationService.getPromptFragmentCustomizationType(fragmentId, customizationId);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
getTemplateIDFromResource(resourceId: unknown): string | undefined {
|
|
890
|
+
if (this.customizationService) {
|
|
891
|
+
return this.customizationService.getPromptFragmentIDFromResource(resourceId);
|
|
892
|
+
}
|
|
893
|
+
return undefined;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
async editBuiltInCustomization(fragmentId: string): Promise<void> {
|
|
897
|
+
if (this.customizationService) {
|
|
898
|
+
const builtInTemplate = this.findBuiltInFragmentById(fragmentId);
|
|
899
|
+
await this.customizationService.editBuiltInPromptFragmentCustomization(fragmentId, builtInTemplate?.template);
|
|
900
|
+
}
|
|
428
901
|
}
|
|
429
902
|
}
|