@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
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
16
|
// *****************************************************************************
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.
|
|
18
|
+
exports.DefaultPromptFragmentCustomizationService = exports.getCustomizationSourceString = exports.CustomizationSource = void 0;
|
|
19
19
|
const tslib_1 = require("tslib");
|
|
20
20
|
const core_1 = require("@theia/core");
|
|
21
21
|
const browser_1 = require("@theia/core/lib/browser");
|
|
@@ -27,39 +27,67 @@ const ai_core_preferences_1 = require("./ai-core-preferences");
|
|
|
27
27
|
const env_variables_1 = require("@theia/core/lib/common/env-variables");
|
|
28
28
|
const js_yaml_1 = require("js-yaml");
|
|
29
29
|
const prompttemplate_contribution_1 = require("./prompttemplate-contribution");
|
|
30
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Default template entry for creating custom agents
|
|
32
|
+
*/
|
|
33
|
+
const newCustomAgentEntry = {
|
|
31
34
|
id: 'my_agent',
|
|
32
35
|
name: 'My Agent',
|
|
33
36
|
description: 'This is an example agent. Please adapt the properties to fit your needs.',
|
|
34
|
-
prompt:
|
|
37
|
+
prompt: `{{!-- Note: The context section below will resolve all context elements (e.g. files) to their full content
|
|
38
|
+
in the system prompt. Context elements can be added by the user in the default chat view (e.g. via DnD or the "+" button).
|
|
39
|
+
If you want a more fine-grained, on demand resolvement of context elements, you can also resolve files to their paths only
|
|
40
|
+
and equip the agent with functions so that the LLM can retrieve files on demand. See the Coder Agent prompt for an example.--}}
|
|
41
|
+
|
|
42
|
+
# Role
|
|
43
|
+
You are an example agent. Be nice and helpful to the user.
|
|
44
|
+
|
|
45
|
+
## Current Context
|
|
46
|
+
Some files and other pieces of data may have been added by the user to the context of the chat. If any have, the details can be found below.
|
|
47
|
+
{{contextDetails}}`,
|
|
35
48
|
defaultLLM: 'openai/gpt-4o'
|
|
36
49
|
};
|
|
37
|
-
|
|
50
|
+
var CustomizationSource;
|
|
51
|
+
(function (CustomizationSource) {
|
|
52
|
+
CustomizationSource[CustomizationSource["CUSTOMIZED"] = 1] = "CUSTOMIZED";
|
|
53
|
+
CustomizationSource[CustomizationSource["FOLDER"] = 2] = "FOLDER";
|
|
54
|
+
CustomizationSource[CustomizationSource["FILE"] = 3] = "FILE";
|
|
55
|
+
})(CustomizationSource || (exports.CustomizationSource = CustomizationSource = {}));
|
|
56
|
+
function getCustomizationSourceString(origin) {
|
|
57
|
+
switch (origin) {
|
|
58
|
+
case CustomizationSource.FILE:
|
|
59
|
+
return 'Workspace Template Files';
|
|
60
|
+
case CustomizationSource.FOLDER:
|
|
61
|
+
return 'Workspace Template Directories';
|
|
62
|
+
default:
|
|
63
|
+
return 'Prompt Templates Folder';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.getCustomizationSourceString = getCustomizationSourceString;
|
|
67
|
+
let DefaultPromptFragmentCustomizationService = class DefaultPromptFragmentCustomizationService {
|
|
38
68
|
constructor() {
|
|
39
69
|
/** Stores URI strings of template files from directories currently being monitored for changes. */
|
|
40
70
|
this.trackedTemplateURIs = new Set();
|
|
41
|
-
/** Contains the currently active
|
|
42
|
-
this.
|
|
43
|
-
/** Tracks all loaded
|
|
44
|
-
this.
|
|
71
|
+
/** Contains the currently active customization, mapped by prompt fragment ID. */
|
|
72
|
+
this.activeCustomizations = new Map();
|
|
73
|
+
/** Tracks all loaded customizations, including overridden ones, mapped by source URI. */
|
|
74
|
+
this.allCustomizations = new Map();
|
|
45
75
|
/** Stores additional directory paths for loading template files. */
|
|
46
76
|
this.additionalTemplateDirs = new Set();
|
|
47
77
|
/** Contains file extensions that identify prompt template files. */
|
|
48
78
|
this.templateExtensions = new Set([prompttemplate_contribution_1.PROMPT_TEMPLATE_EXTENSION]);
|
|
49
|
-
/** Stores specific file paths that should be treated as templates. */
|
|
50
|
-
this.
|
|
79
|
+
/** Stores specific file paths, provided by the settings, that should be treated as templates. */
|
|
80
|
+
this.workspaceTemplateFiles = new Set();
|
|
51
81
|
/** Maps URI strings to WatchedFileInfo objects for individually watched template files. */
|
|
52
82
|
this.watchedFiles = new Map();
|
|
53
83
|
/** Collection of disposable resources for cleanup when the service updates or is disposed. */
|
|
54
84
|
this.toDispose = new core_1.DisposableCollection();
|
|
55
|
-
this.
|
|
56
|
-
this.
|
|
85
|
+
this.onDidChangePromptFragmentCustomizationEmitter = new core_1.Emitter();
|
|
86
|
+
this.onDidChangePromptFragmentCustomization = this.onDidChangePromptFragmentCustomizationEmitter.event;
|
|
57
87
|
this.onDidChangeCustomAgentsEmitter = new core_1.Emitter();
|
|
58
88
|
this.onDidChangeCustomAgents = this.onDidChangeCustomAgentsEmitter.event;
|
|
59
89
|
}
|
|
60
90
|
init() {
|
|
61
|
-
// Ensure PROMPT_TEMPLATE_EXTENSION is always included in templateExtensions as a default
|
|
62
|
-
this.templateExtensions.add(prompttemplate_contribution_1.PROMPT_TEMPLATE_EXTENSION);
|
|
63
91
|
this.preferences.onPreferenceChanged(event => {
|
|
64
92
|
if (event.preferenceName === ai_core_preferences_1.PREFERENCE_NAME_PROMPT_TEMPLATES) {
|
|
65
93
|
this.update();
|
|
@@ -67,123 +95,175 @@ let FrontendPromptCustomizationServiceImpl = class FrontendPromptCustomizationSe
|
|
|
67
95
|
});
|
|
68
96
|
this.update();
|
|
69
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Updates the service by reloading all template files and watching for changes
|
|
100
|
+
*/
|
|
70
101
|
async update() {
|
|
71
102
|
this.toDispose.dispose();
|
|
72
103
|
// we need to assign local variables, so that updates running in parallel don't interfere with each other
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
const
|
|
104
|
+
const activeCustomizationsCopy = new Map();
|
|
105
|
+
const trackedTemplateURIsCopy = new Set();
|
|
106
|
+
const allCustomizationsCopy = new Map();
|
|
107
|
+
const watchedFilesCopy = new Map();
|
|
77
108
|
// Process in order of priority (lowest to highest)
|
|
78
|
-
// First process the main
|
|
79
|
-
const
|
|
80
|
-
await this.processTemplateDirectory(
|
|
109
|
+
// First process the main templates directory (lowest priority)
|
|
110
|
+
const templatesURI = await this.getTemplatesDirectoryURI();
|
|
111
|
+
await this.processTemplateDirectory(activeCustomizationsCopy, trackedTemplateURIsCopy, allCustomizationsCopy, templatesURI, 1, CustomizationSource.CUSTOMIZED); // Priority 1 for customized fragments
|
|
81
112
|
// Process additional template directories (medium priority)
|
|
82
113
|
for (const dirPath of this.additionalTemplateDirs) {
|
|
83
114
|
const dirURI = core_1.URI.fromFilePath(dirPath);
|
|
84
|
-
await this.processTemplateDirectory(
|
|
115
|
+
await this.processTemplateDirectory(activeCustomizationsCopy, trackedTemplateURIsCopy, allCustomizationsCopy, dirURI, 2, CustomizationSource.FOLDER); // Priority 2 for folder fragments
|
|
85
116
|
}
|
|
86
117
|
// Process specific template files (highest priority)
|
|
87
|
-
await this.processTemplateFiles(
|
|
88
|
-
this.
|
|
89
|
-
this.trackedTemplateURIs =
|
|
90
|
-
this.
|
|
91
|
-
this.watchedFiles =
|
|
118
|
+
await this.processTemplateFiles(activeCustomizationsCopy, trackedTemplateURIsCopy, allCustomizationsCopy, watchedFilesCopy);
|
|
119
|
+
this.activeCustomizations = activeCustomizationsCopy;
|
|
120
|
+
this.trackedTemplateURIs = trackedTemplateURIsCopy;
|
|
121
|
+
this.allCustomizations = allCustomizationsCopy;
|
|
122
|
+
this.watchedFiles = watchedFilesCopy;
|
|
92
123
|
this.onDidChangeCustomAgentsEmitter.fire();
|
|
93
124
|
}
|
|
94
125
|
/**
|
|
95
|
-
* Adds a template to the
|
|
96
|
-
* @param
|
|
97
|
-
* @param id The
|
|
98
|
-
* @param
|
|
99
|
-
* @param priority The template priority
|
|
126
|
+
* Adds a template to the customizations map, handling conflicts based on priority
|
|
127
|
+
* @param activeCustomizationsCopy The map to add the customization to
|
|
128
|
+
* @param id The fragment ID
|
|
129
|
+
* @param template The template content
|
|
100
130
|
* @param sourceUri The URI of the source file (used to distinguish updates from conflicts)
|
|
101
|
-
* @param
|
|
131
|
+
* @param allCustomizationsCopy The map to track all loaded customizations
|
|
132
|
+
* @param priority The customization priority
|
|
133
|
+
* @param origin The source type of the customization
|
|
102
134
|
*/
|
|
103
|
-
addTemplate(
|
|
104
|
-
//
|
|
135
|
+
addTemplate(activeCustomizationsCopy, id, template, sourceUri, allCustomizationsCopy, priority, origin) {
|
|
136
|
+
// Generate a unique customization ID based on source URI and priority
|
|
137
|
+
const customizationId = this.generateCustomizationId(id, sourceUri);
|
|
138
|
+
// Always add to allCustomizationsCopy to keep track of all customizations including overridden ones
|
|
105
139
|
if (sourceUri) {
|
|
106
|
-
|
|
140
|
+
allCustomizationsCopy.set(sourceUri, { id, template, sourceUri, priority, customizationId, origin });
|
|
107
141
|
}
|
|
108
|
-
const existingEntry =
|
|
142
|
+
const existingEntry = activeCustomizationsCopy.get(id);
|
|
109
143
|
if (existingEntry) {
|
|
110
144
|
// If this is an update to the same file (same source URI)
|
|
111
145
|
if (sourceUri && existingEntry.sourceUri === sourceUri) {
|
|
112
146
|
// Update the content while keeping the same priority and source
|
|
113
|
-
|
|
147
|
+
activeCustomizationsCopy.set(id, { id, template, sourceUri, priority, customizationId, origin });
|
|
114
148
|
return;
|
|
115
149
|
}
|
|
116
|
-
// If the new
|
|
150
|
+
// If the new customization has higher priority, replace the existing one
|
|
117
151
|
if (priority > existingEntry.priority) {
|
|
118
|
-
|
|
152
|
+
activeCustomizationsCopy.set(id, { id, template, sourceUri, priority, customizationId, origin });
|
|
119
153
|
return;
|
|
120
154
|
}
|
|
121
155
|
else if (priority === existingEntry.priority) {
|
|
122
|
-
// There is a conflict with the same priority, we ignore the new
|
|
156
|
+
// There is a conflict with the same priority, we ignore the new customization
|
|
123
157
|
const conflictSourceUri = existingEntry.sourceUri ? ` (Existing source: ${existingEntry.sourceUri}, New source: ${sourceUri})` : '';
|
|
124
|
-
console.warn(`
|
|
158
|
+
console.warn(`Fragment conflict detected for ID '${id}' with equal priority.${conflictSourceUri}`);
|
|
125
159
|
}
|
|
126
160
|
return;
|
|
127
161
|
}
|
|
128
|
-
// No conflict at all, add the
|
|
129
|
-
|
|
162
|
+
// No conflict at all, add the customization
|
|
163
|
+
activeCustomizationsCopy.set(id, { id, template, sourceUri, priority, customizationId, origin });
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Generates a unique customization ID based on the fragment ID, source URI, and priority
|
|
167
|
+
* @param id The fragment ID
|
|
168
|
+
* @param sourceUri The source URI of the template
|
|
169
|
+
* @returns A unique customization ID
|
|
170
|
+
*/
|
|
171
|
+
generateCustomizationId(id, sourceUri) {
|
|
172
|
+
// Create a customization ID that contains information about the source and priority
|
|
173
|
+
// This ensures uniqueness across different customization sources
|
|
174
|
+
const sourceHash = this.hashString(sourceUri);
|
|
175
|
+
return `${id}_${sourceHash}`;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Simple hash function to generate a short identifier from a string
|
|
179
|
+
* @param str The string to hash
|
|
180
|
+
* @returns A string hash
|
|
181
|
+
*/
|
|
182
|
+
hashString(str) {
|
|
183
|
+
let hash = 0;
|
|
184
|
+
for (let i = 0; i < str.length; i++) {
|
|
185
|
+
const char = str.charCodeAt(i);
|
|
186
|
+
hash = ((hash << 5) - hash) + char;
|
|
187
|
+
hash = hash & hash; // Convert to 32bit integer
|
|
188
|
+
}
|
|
189
|
+
return Math.abs(hash).toString(36).substring(0, 8);
|
|
130
190
|
}
|
|
131
191
|
/**
|
|
132
|
-
* Removes a
|
|
133
|
-
* Also checks for any lower-priority
|
|
192
|
+
* Removes a customization from customizations maps based on the source URI.
|
|
193
|
+
* Also checks for any lower-priority customizations with the same ID that might need to be loaded.
|
|
134
194
|
* @param sourceUri The URI of the source file being removed
|
|
135
|
-
* @param
|
|
195
|
+
* @param allCustomizationsCopy The map of all loaded customizations
|
|
196
|
+
* @param activeCustomizationsCopy The map of active customizations
|
|
197
|
+
* @param trackedTemplateURIsCopy Optional set of tracked URIs to update
|
|
198
|
+
* @returns The fragment ID that was removed, or undefined if no customization was found
|
|
136
199
|
*/
|
|
137
|
-
|
|
138
|
-
// Get the
|
|
139
|
-
const
|
|
140
|
-
if (!
|
|
141
|
-
return;
|
|
200
|
+
removeCustomizationFromMaps(sourceUri, allCustomizationsCopy, activeCustomizationsCopy, trackedTemplateURIsCopy) {
|
|
201
|
+
// Get the customization entry from allCustomizationsCopy
|
|
202
|
+
const removedCustomization = allCustomizationsCopy.get(sourceUri);
|
|
203
|
+
if (!removedCustomization) {
|
|
204
|
+
return undefined;
|
|
142
205
|
}
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
206
|
+
const fragmentId = removedCustomization.id;
|
|
207
|
+
allCustomizationsCopy.delete(sourceUri);
|
|
208
|
+
trackedTemplateURIsCopy.delete(sourceUri);
|
|
209
|
+
// If the customization is in the active customizations map, we check if there is another customization previously conflicting with it
|
|
210
|
+
const activeCustomization = activeCustomizationsCopy.get(fragmentId);
|
|
211
|
+
if (activeCustomization && activeCustomization.sourceUri === sourceUri) {
|
|
212
|
+
activeCustomizationsCopy.delete(fragmentId);
|
|
213
|
+
// Find any lower-priority customizations with the same ID that were previously ignored
|
|
214
|
+
const lowerPriorityCustomizations = Array.from(allCustomizationsCopy.values())
|
|
215
|
+
.filter(t => t.id === fragmentId)
|
|
152
216
|
.sort((a, b) => b.priority - a.priority); // Sort by priority (highest first)
|
|
153
|
-
// If there are any lower-priority
|
|
154
|
-
if (
|
|
155
|
-
const
|
|
156
|
-
|
|
217
|
+
// If there are any lower-priority customizations, add the highest priority one
|
|
218
|
+
if (lowerPriorityCustomizations.length > 0) {
|
|
219
|
+
const highestRemainingCustomization = lowerPriorityCustomizations[0];
|
|
220
|
+
activeCustomizationsCopy.set(fragmentId, highestRemainingCustomization);
|
|
157
221
|
}
|
|
158
|
-
this.onDidChangePromptEmitter.fire(templateId);
|
|
159
222
|
}
|
|
223
|
+
return fragmentId;
|
|
160
224
|
}
|
|
161
225
|
/**
|
|
162
226
|
* Process the template files specified by path, watching for changes
|
|
163
|
-
* and loading their content into the
|
|
227
|
+
* and loading their content into the customizations map
|
|
228
|
+
* @param activeCustomizationsCopy Map to store active customizations
|
|
229
|
+
* @param trackedTemplateURIsCopy Set to track URIs being monitored
|
|
230
|
+
* @param allCustomizationsCopy Map to store all loaded customizations
|
|
231
|
+
* @param watchedFilesCopy Map to store file watch information
|
|
164
232
|
*/
|
|
165
|
-
async processTemplateFiles(
|
|
166
|
-
|
|
233
|
+
async processTemplateFiles(activeCustomizationsCopy, trackedTemplateURIsCopy, allCustomizationsCopy, watchedFilesCopy) {
|
|
234
|
+
const priority = 3; // Highest priority for specific files
|
|
235
|
+
const parsedPromptFragments = new Set();
|
|
236
|
+
for (const filePath of this.workspaceTemplateFiles) {
|
|
167
237
|
const fileURI = core_1.URI.fromFilePath(filePath);
|
|
168
|
-
const
|
|
238
|
+
const fragmentId = this.getFragmentIdFromFilePath(filePath);
|
|
169
239
|
const uriString = fileURI.toString();
|
|
170
|
-
|
|
240
|
+
const customizationId = this.generateCustomizationId(fragmentId, uriString);
|
|
241
|
+
watchedFilesCopy.set(uriString, { uri: fileURI, fragmentId, customizationId });
|
|
171
242
|
this.toDispose.push(this.fileService.watch(fileURI, { recursive: false, excludes: [] }));
|
|
172
243
|
if (await this.fileService.exists(fileURI)) {
|
|
173
|
-
|
|
244
|
+
trackedTemplateURIsCopy.add(uriString);
|
|
174
245
|
const fileContent = await this.fileService.read(fileURI);
|
|
175
|
-
this.addTemplate(
|
|
246
|
+
this.addTemplate(activeCustomizationsCopy, fragmentId, fileContent.value, uriString, allCustomizationsCopy, priority, CustomizationSource.FILE);
|
|
247
|
+
parsedPromptFragments.add(fragmentId);
|
|
176
248
|
}
|
|
177
249
|
}
|
|
250
|
+
this.onDidChangePromptFragmentCustomizationEmitter.fire(Array.from(parsedPromptFragments));
|
|
178
251
|
this.toDispose.push(this.fileService.onDidFilesChange(async (event) => {
|
|
252
|
+
// Only watch for changes that are in the watchedFiles map
|
|
253
|
+
if (!event.changes.some(change => this.watchedFiles.get(change.resource.toString()))) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
// Track changes for batched notification
|
|
257
|
+
const changedFragmentIds = new Set();
|
|
179
258
|
// Handle deleted files
|
|
180
259
|
for (const deletedFile of event.getDeleted()) {
|
|
181
260
|
const fileUriString = deletedFile.resource.toString();
|
|
182
261
|
const fileInfo = this.watchedFiles.get(fileUriString);
|
|
183
262
|
if (fileInfo) {
|
|
184
|
-
this.
|
|
185
|
-
|
|
186
|
-
|
|
263
|
+
const removedFragmentId = this.removeCustomizationFromMaps(fileUriString, allCustomizationsCopy, activeCustomizationsCopy, trackedTemplateURIsCopy);
|
|
264
|
+
if (removedFragmentId) {
|
|
265
|
+
changedFragmentIds.add(removedFragmentId);
|
|
266
|
+
}
|
|
187
267
|
}
|
|
188
268
|
}
|
|
189
269
|
// Handle updated files
|
|
@@ -192,8 +272,8 @@ let FrontendPromptCustomizationServiceImpl = class FrontendPromptCustomizationSe
|
|
|
192
272
|
const fileInfo = this.watchedFiles.get(fileUriString);
|
|
193
273
|
if (fileInfo) {
|
|
194
274
|
const fileContent = await this.fileService.read(fileInfo.uri);
|
|
195
|
-
this.addTemplate(this.
|
|
196
|
-
|
|
275
|
+
this.addTemplate(this.activeCustomizations, fileInfo.fragmentId, fileContent.value, fileUriString, this.allCustomizations, priority, CustomizationSource.FILE);
|
|
276
|
+
changedFragmentIds.add(fileInfo.fragmentId);
|
|
197
277
|
}
|
|
198
278
|
}
|
|
199
279
|
// Handle newly created files
|
|
@@ -202,79 +282,110 @@ let FrontendPromptCustomizationServiceImpl = class FrontendPromptCustomizationSe
|
|
|
202
282
|
const fileInfo = this.watchedFiles.get(fileUriString);
|
|
203
283
|
if (fileInfo) {
|
|
204
284
|
const fileContent = await this.fileService.read(fileInfo.uri);
|
|
205
|
-
this.addTemplate(this.
|
|
285
|
+
this.addTemplate(this.activeCustomizations, fileInfo.fragmentId, fileContent.value, fileUriString, this.allCustomizations, priority, CustomizationSource.FILE);
|
|
206
286
|
this.trackedTemplateURIs.add(fileUriString);
|
|
207
|
-
|
|
287
|
+
changedFragmentIds.add(fileInfo.fragmentId);
|
|
208
288
|
}
|
|
209
289
|
}
|
|
290
|
+
const changedFragmentIdsArray = Array.from(changedFragmentIds);
|
|
291
|
+
if (changedFragmentIdsArray.length > 0) {
|
|
292
|
+
this.onDidChangePromptFragmentCustomizationEmitter.fire(changedFragmentIdsArray);
|
|
293
|
+
}
|
|
294
|
+
;
|
|
210
295
|
}));
|
|
211
296
|
}
|
|
212
297
|
/**
|
|
213
|
-
* Extract a
|
|
298
|
+
* Extract a fragment ID from a file path
|
|
214
299
|
* @param filePath The path to the template file
|
|
215
|
-
* @returns A
|
|
300
|
+
* @returns A fragment ID derived from the file name
|
|
216
301
|
*/
|
|
217
|
-
|
|
302
|
+
getFragmentIdFromFilePath(filePath) {
|
|
218
303
|
const uri = core_1.URI.fromFilePath(filePath);
|
|
219
304
|
return this.removePromptTemplateSuffix(uri.path.name);
|
|
220
305
|
}
|
|
221
|
-
|
|
306
|
+
/**
|
|
307
|
+
* Processes a directory for template files, adding them to the customizations map
|
|
308
|
+
* and setting up file watching
|
|
309
|
+
* @param activeCustomizationsCopy Map to store active customizations
|
|
310
|
+
* @param trackedTemplateURIsCopy Set to track URIs being monitored
|
|
311
|
+
* @param allCustomizationsCopy Map to store all loaded customizations
|
|
312
|
+
* @param dirURI URI of the directory to process
|
|
313
|
+
* @param priority Priority level for customizations in this directory
|
|
314
|
+
* @param customizationSource Source type of the customization
|
|
315
|
+
*/
|
|
316
|
+
async processTemplateDirectory(activeCustomizationsCopy, trackedTemplateURIsCopy, allCustomizationsCopy, dirURI, priority, customizationSource) {
|
|
317
|
+
if (!(await this.fileService.exists(dirURI))) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const stat = await this.fileService.resolve(dirURI);
|
|
321
|
+
if (stat.children === undefined) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
const parsedPromptFragments = new Set();
|
|
325
|
+
for (const file of stat.children) {
|
|
326
|
+
if (!file.isFile) {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
const fileURI = file.resource;
|
|
330
|
+
if (this.isPromptTemplateExtension(fileURI.path.ext)) {
|
|
331
|
+
trackedTemplateURIsCopy.add(fileURI.toString());
|
|
332
|
+
const fileContent = await this.fileService.read(fileURI);
|
|
333
|
+
const fragmentId = this.removePromptTemplateSuffix(file.name);
|
|
334
|
+
this.addTemplate(activeCustomizationsCopy, fragmentId, fileContent.value, fileURI.toString(), allCustomizationsCopy, priority, customizationSource);
|
|
335
|
+
parsedPromptFragments.add(fragmentId);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
this.onDidChangePromptFragmentCustomizationEmitter.fire(Array.from(parsedPromptFragments));
|
|
339
|
+
this.onDidChangeCustomAgentsEmitter.fire();
|
|
222
340
|
this.toDispose.push(this.fileService.watch(dirURI, { recursive: true, excludes: [] }));
|
|
223
341
|
this.toDispose.push(this.fileService.onDidFilesChange(async (event) => {
|
|
342
|
+
// Only watch for changes within provided dir
|
|
343
|
+
if (!event.changes.some(change => change.resource.toString().startsWith(dirURI.toString()))) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
224
346
|
if (event.changes.some(change => change.resource.toString().endsWith('customAgents.yml'))) {
|
|
225
347
|
this.onDidChangeCustomAgentsEmitter.fire();
|
|
226
348
|
}
|
|
349
|
+
// Track changes for batched notification
|
|
350
|
+
const changedFragmentIds = new Set();
|
|
227
351
|
// check deleted templates
|
|
228
352
|
for (const deletedFile of event.getDeleted()) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
353
|
+
const uriString = deletedFile.resource.toString();
|
|
354
|
+
if (this.trackedTemplateURIs.has(uriString)) {
|
|
355
|
+
const removedFragmentId = this.removeCustomizationFromMaps(uriString, this.allCustomizations, this.activeCustomizations, this.trackedTemplateURIs);
|
|
356
|
+
if (removedFragmentId) {
|
|
357
|
+
changedFragmentIds.add(removedFragmentId);
|
|
358
|
+
}
|
|
234
359
|
}
|
|
235
360
|
}
|
|
236
361
|
// check updated templates
|
|
237
362
|
for (const updatedFile of event.getUpdated()) {
|
|
238
|
-
|
|
363
|
+
const uriString = updatedFile.resource.toString();
|
|
364
|
+
if (this.trackedTemplateURIs.has(uriString)) {
|
|
239
365
|
const fileContent = await this.fileService.read(updatedFile.resource);
|
|
240
|
-
const
|
|
241
|
-
this.addTemplate(this.
|
|
242
|
-
|
|
366
|
+
const fragmentId = this.removePromptTemplateSuffix(updatedFile.resource.path.name);
|
|
367
|
+
this.addTemplate(this.activeCustomizations, fragmentId, fileContent.value, uriString, this.allCustomizations, priority, customizationSource);
|
|
368
|
+
changedFragmentIds.add(fragmentId);
|
|
243
369
|
}
|
|
244
370
|
}
|
|
245
371
|
// check new templates
|
|
246
372
|
for (const addedFile of event.getAdded()) {
|
|
247
373
|
if (addedFile.resource.parent.toString() === dirURI.toString() &&
|
|
248
374
|
this.isPromptTemplateExtension(addedFile.resource.path.ext)) {
|
|
249
|
-
|
|
375
|
+
const uriString = addedFile.resource.toString();
|
|
376
|
+
this.trackedTemplateURIs.add(uriString);
|
|
250
377
|
const fileContent = await this.fileService.read(addedFile.resource);
|
|
251
|
-
const
|
|
252
|
-
this.addTemplate(this.
|
|
253
|
-
|
|
378
|
+
const fragmentId = this.removePromptTemplateSuffix(addedFile.resource.path.name);
|
|
379
|
+
this.addTemplate(this.activeCustomizations, fragmentId, fileContent.value, uriString, this.allCustomizations, priority, customizationSource);
|
|
380
|
+
changedFragmentIds.add(fragmentId);
|
|
254
381
|
}
|
|
255
382
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
const stat = await this.fileService.resolve(dirURI);
|
|
261
|
-
if (stat.children === undefined) {
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
for (const file of stat.children) {
|
|
265
|
-
if (!file.isFile) {
|
|
266
|
-
continue;
|
|
383
|
+
const changedFragmentIdsArray = Array.from(changedFragmentIds);
|
|
384
|
+
if (changedFragmentIdsArray.length > 0) {
|
|
385
|
+
this.onDidChangePromptFragmentCustomizationEmitter.fire(changedFragmentIdsArray);
|
|
267
386
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
trackedURIs.add(fileURI.toString());
|
|
271
|
-
const fileContent = await this.fileService.read(fileURI);
|
|
272
|
-
const templateId = this.removePromptTemplateSuffix(file.name);
|
|
273
|
-
this.addTemplate(templatesMap, templateId, fileContent.value, priority, fileURI.toString(), loadedTemplates);
|
|
274
|
-
this.onDidChangePromptEmitter.fire(templateId);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
this.onDidChangeCustomAgentsEmitter.fire();
|
|
387
|
+
;
|
|
388
|
+
}));
|
|
278
389
|
}
|
|
279
390
|
/**
|
|
280
391
|
* Checks if the given file extension is registered as a prompt template extension
|
|
@@ -303,11 +414,10 @@ let FrontendPromptCustomizationServiceImpl = class FrontendPromptCustomizationSe
|
|
|
303
414
|
* @returns Array of file paths
|
|
304
415
|
*/
|
|
305
416
|
getTemplateFiles() {
|
|
306
|
-
return Array.from(this.
|
|
417
|
+
return Array.from(this.workspaceTemplateFiles);
|
|
307
418
|
}
|
|
308
419
|
/**
|
|
309
420
|
* Updates multiple configuration properties at once, triggering only a single update process.
|
|
310
|
-
*
|
|
311
421
|
* @param properties An object containing the properties to update
|
|
312
422
|
* @returns Promise that resolves when the update is complete
|
|
313
423
|
*/
|
|
@@ -327,14 +437,18 @@ let FrontendPromptCustomizationServiceImpl = class FrontendPromptCustomizationSe
|
|
|
327
437
|
this.templateExtensions.add(prompttemplate_contribution_1.PROMPT_TEMPLATE_EXTENSION);
|
|
328
438
|
}
|
|
329
439
|
if (properties.filePaths !== undefined) {
|
|
330
|
-
this.
|
|
440
|
+
this.workspaceTemplateFiles.clear();
|
|
331
441
|
for (const path of properties.filePaths) {
|
|
332
|
-
this.
|
|
442
|
+
this.workspaceTemplateFiles.add(path);
|
|
333
443
|
}
|
|
334
444
|
}
|
|
335
445
|
// Only run the update process once, no matter how many properties were changed
|
|
336
446
|
await this.update();
|
|
337
447
|
}
|
|
448
|
+
/**
|
|
449
|
+
* Gets the URI of the templates directory
|
|
450
|
+
* @returns URI of the templates directory
|
|
451
|
+
*/
|
|
338
452
|
async getTemplatesDirectoryURI() {
|
|
339
453
|
const templatesFolder = this.preferences[ai_core_preferences_1.PREFERENCE_NAME_PROMPT_TEMPLATES];
|
|
340
454
|
if (templatesFolder && templatesFolder.trim().length > 0) {
|
|
@@ -343,9 +457,19 @@ let FrontendPromptCustomizationServiceImpl = class FrontendPromptCustomizationSe
|
|
|
343
457
|
const theiaConfigDir = await this.envVariablesServer.getConfigDirUri();
|
|
344
458
|
return new core_1.URI(theiaConfigDir).resolve('prompt-templates');
|
|
345
459
|
}
|
|
346
|
-
|
|
347
|
-
|
|
460
|
+
/**
|
|
461
|
+
* Gets the URI for a specific template file
|
|
462
|
+
* @param fragmentId The fragment ID
|
|
463
|
+
* @returns URI for the template file
|
|
464
|
+
*/
|
|
465
|
+
async getTemplateURI(fragmentId) {
|
|
466
|
+
return (await this.getTemplatesDirectoryURI()).resolve(`${fragmentId}${prompttemplate_contribution_1.PROMPT_TEMPLATE_EXTENSION}`);
|
|
348
467
|
}
|
|
468
|
+
/**
|
|
469
|
+
* Removes the prompt template extension from a filename
|
|
470
|
+
* @param filename The filename with extension
|
|
471
|
+
* @returns The filename without the extension
|
|
472
|
+
*/
|
|
349
473
|
removePromptTemplateSuffix(filename) {
|
|
350
474
|
for (const ext of this.templateExtensions) {
|
|
351
475
|
if (filename.endsWith(ext)) {
|
|
@@ -354,37 +478,212 @@ let FrontendPromptCustomizationServiceImpl = class FrontendPromptCustomizationSe
|
|
|
354
478
|
}
|
|
355
479
|
return filename;
|
|
356
480
|
}
|
|
357
|
-
|
|
358
|
-
|
|
481
|
+
// PromptFragmentCustomizationService interface implementation
|
|
482
|
+
isPromptFragmentCustomized(id) {
|
|
483
|
+
return this.activeCustomizations.has(id);
|
|
484
|
+
}
|
|
485
|
+
getActivePromptFragmentCustomization(id) {
|
|
486
|
+
const entry = this.activeCustomizations.get(id);
|
|
487
|
+
if (!entry) {
|
|
488
|
+
return undefined;
|
|
489
|
+
}
|
|
490
|
+
return {
|
|
491
|
+
id: entry.id,
|
|
492
|
+
template: entry.template,
|
|
493
|
+
customizationId: entry.customizationId,
|
|
494
|
+
priority: entry.priority
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
getAllCustomizations(id) {
|
|
498
|
+
const fragments = [];
|
|
499
|
+
// Collect all customizations with matching ID
|
|
500
|
+
this.allCustomizations.forEach(value => {
|
|
501
|
+
if (value.id === id) {
|
|
502
|
+
fragments.push({
|
|
503
|
+
id: value.id,
|
|
504
|
+
template: value.template,
|
|
505
|
+
customizationId: value.customizationId,
|
|
506
|
+
priority: value.priority
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
// Sort by priority (highest first)
|
|
511
|
+
return fragments.sort((a, b) => b.priority - a.priority);
|
|
359
512
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
return entry ? entry.content : undefined;
|
|
513
|
+
getCustomizedPromptFragmentIds() {
|
|
514
|
+
return Array.from(this.activeCustomizations.keys());
|
|
363
515
|
}
|
|
364
|
-
|
|
365
|
-
|
|
516
|
+
async createPromptFragmentCustomization(id, defaultContent) {
|
|
517
|
+
await this.editTemplate(id, defaultContent);
|
|
366
518
|
}
|
|
519
|
+
async createBuiltInPromptFragmentCustomization(id, defaultContent) {
|
|
520
|
+
await this.createPromptFragmentCustomization(id, defaultContent);
|
|
521
|
+
}
|
|
522
|
+
async editPromptFragmentCustomization(id, customizationId) {
|
|
523
|
+
// Find the customization with the given customization ID
|
|
524
|
+
const customization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.customizationId === customizationId);
|
|
525
|
+
if (customization) {
|
|
526
|
+
const uri = new core_1.URI(customization.sourceUri);
|
|
527
|
+
const openHandler = await this.openerService.getOpener(uri);
|
|
528
|
+
openHandler.open(uri);
|
|
529
|
+
}
|
|
530
|
+
else {
|
|
531
|
+
// Fall back to editing by fragment ID if customization ID not found
|
|
532
|
+
await this.editTemplate(id);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Edits a template by opening it in the editor, creating it if it doesn't exist
|
|
537
|
+
* @param id The fragment ID
|
|
538
|
+
* @param defaultContent Optional default content for new templates
|
|
539
|
+
*/
|
|
367
540
|
async editTemplate(id, defaultContent) {
|
|
368
541
|
const editorUri = await this.getTemplateURI(id);
|
|
369
|
-
if (!await this.fileService.exists(editorUri)) {
|
|
542
|
+
if (!(await this.fileService.exists(editorUri))) {
|
|
370
543
|
await this.fileService.createFile(editorUri, buffer_1.BinaryBuffer.fromString(defaultContent !== null && defaultContent !== void 0 ? defaultContent : ''));
|
|
371
544
|
}
|
|
372
545
|
const openHandler = await this.openerService.getOpener(editorUri);
|
|
373
546
|
openHandler.open(editorUri);
|
|
374
547
|
}
|
|
375
|
-
async
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
548
|
+
async removePromptFragmentCustomization(id, customizationId) {
|
|
549
|
+
// Find the customization with the given customization ID
|
|
550
|
+
const customization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.customizationId === customizationId);
|
|
551
|
+
if (customization) {
|
|
552
|
+
const sourceUri = customization.sourceUri;
|
|
553
|
+
// Delete the file if it exists
|
|
554
|
+
const uri = new core_1.URI(sourceUri);
|
|
555
|
+
if (await this.fileService.exists(uri)) {
|
|
556
|
+
await this.fileService.delete(uri);
|
|
557
|
+
}
|
|
379
558
|
}
|
|
380
559
|
}
|
|
381
|
-
|
|
560
|
+
async removeAllPromptFragmentCustomizations(id) {
|
|
561
|
+
// Get all customizations for this fragment ID
|
|
562
|
+
const customizations = this.getAllCustomizations(id);
|
|
563
|
+
if (customizations.length === 0) {
|
|
564
|
+
return; // Nothing to reset
|
|
565
|
+
}
|
|
566
|
+
// Find and delete all customization files
|
|
567
|
+
for (const customization of customizations) {
|
|
568
|
+
const fragment = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.customizationId === customization.customizationId);
|
|
569
|
+
if (fragment) {
|
|
570
|
+
const sourceUri = fragment.sourceUri;
|
|
571
|
+
// Delete the file if it exists
|
|
572
|
+
const uri = new core_1.URI(sourceUri);
|
|
573
|
+
if (await this.fileService.exists(uri)) {
|
|
574
|
+
await this.fileService.delete(uri);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
async resetToCustomization(id, customizationId) {
|
|
580
|
+
const customization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.customizationId === customizationId);
|
|
581
|
+
if (customization) {
|
|
582
|
+
// Get all customizations for this fragment ID
|
|
583
|
+
const customizations = this.getAllCustomizations(id);
|
|
584
|
+
if (customizations.length === 0) {
|
|
585
|
+
return; // Nothing to reset
|
|
586
|
+
}
|
|
587
|
+
// Find the target customization
|
|
588
|
+
const targetCustomization = customizations.find(c => c.customizationId === customizationId);
|
|
589
|
+
if (!targetCustomization) {
|
|
590
|
+
return; // Target customization not found
|
|
591
|
+
}
|
|
592
|
+
// Find and delete all higher-priority customization files
|
|
593
|
+
for (const cust of customizations) {
|
|
594
|
+
if (cust.priority > targetCustomization.priority) {
|
|
595
|
+
const fragmentToDelete = Array.from(this.allCustomizations.values()).find(t => t.id === cust.id && t.customizationId === cust.customizationId);
|
|
596
|
+
if (fragmentToDelete) {
|
|
597
|
+
const sourceUri = fragmentToDelete.sourceUri;
|
|
598
|
+
// Delete the file if it exists
|
|
599
|
+
const uri = new core_1.URI(sourceUri);
|
|
600
|
+
if (await this.fileService.exists(uri)) {
|
|
601
|
+
await this.fileService.delete(uri);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
async getPromptFragmentCustomizationDescription(id, customizationId) {
|
|
609
|
+
// Find the customization with the given customization ID
|
|
610
|
+
const customization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.customizationId === customizationId);
|
|
611
|
+
if (customization) {
|
|
612
|
+
return customization.sourceUri;
|
|
613
|
+
}
|
|
614
|
+
return undefined;
|
|
615
|
+
}
|
|
616
|
+
async getPromptFragmentCustomizationType(id, customizationId) {
|
|
617
|
+
// Find the customization with the given customization ID
|
|
618
|
+
const customization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.customizationId === customizationId);
|
|
619
|
+
if (customization) {
|
|
620
|
+
return getCustomizationSourceString(customization.origin);
|
|
621
|
+
}
|
|
622
|
+
return undefined;
|
|
623
|
+
}
|
|
624
|
+
async editBuiltIn(id, defaultContent = '') {
|
|
625
|
+
// Find an existing built-in customization (those with priority 1)
|
|
626
|
+
const builtInCustomization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.priority === 1);
|
|
627
|
+
if (builtInCustomization) {
|
|
628
|
+
// Edit the existing built-in customization
|
|
629
|
+
const uri = new core_1.URI(builtInCustomization.sourceUri);
|
|
630
|
+
const openHandler = await this.openerService.getOpener(uri);
|
|
631
|
+
openHandler.open(uri);
|
|
632
|
+
}
|
|
633
|
+
else {
|
|
634
|
+
// Create a new built-in customization
|
|
635
|
+
// Get the template URI in the main templates directory (priority 1)
|
|
636
|
+
const templateUri = await this.getTemplateURI(id);
|
|
637
|
+
// If template doesn't exist, create it with default content
|
|
638
|
+
if (!(await this.fileService.exists(templateUri))) {
|
|
639
|
+
await this.fileService.createFile(templateUri, buffer_1.BinaryBuffer.fromString(defaultContent));
|
|
640
|
+
}
|
|
641
|
+
// Open the template in the editor
|
|
642
|
+
const openHandler = await this.openerService.getOpener(templateUri);
|
|
643
|
+
openHandler.open(templateUri);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
async resetBuiltInCustomization(id) {
|
|
647
|
+
// Find a built-in customization (those with priority 1)
|
|
648
|
+
const builtInCustomization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.priority === 1);
|
|
649
|
+
if (!builtInCustomization) {
|
|
650
|
+
return; // No built-in customization found
|
|
651
|
+
}
|
|
652
|
+
const sourceUri = builtInCustomization.sourceUri;
|
|
653
|
+
// Delete the file if it exists
|
|
654
|
+
const uri = new core_1.URI(sourceUri);
|
|
655
|
+
if (await this.fileService.exists(uri)) {
|
|
656
|
+
await this.fileService.delete(uri);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
async editBuiltInPromptFragmentCustomization(id, defaultContent) {
|
|
660
|
+
return this.editBuiltIn(id, defaultContent);
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Gets the fragment ID from a URI
|
|
664
|
+
* @param uri URI to check
|
|
665
|
+
* @returns Fragment ID or undefined if not found
|
|
666
|
+
*/
|
|
667
|
+
getFragmentIDFromURI(uri) {
|
|
382
668
|
const id = this.removePromptTemplateSuffix(uri.path.name);
|
|
383
|
-
if (this.
|
|
669
|
+
if (this.activeCustomizations.has(id)) {
|
|
384
670
|
return id;
|
|
385
671
|
}
|
|
386
672
|
return undefined;
|
|
387
673
|
}
|
|
674
|
+
/**
|
|
675
|
+
* Implementation of the generic getPromptFragmentIDFromResource method in the interface
|
|
676
|
+
* Accepts any resource identifier but only processes URIs
|
|
677
|
+
* @param resourceId Resource to check
|
|
678
|
+
* @returns Fragment ID or undefined if not found
|
|
679
|
+
*/
|
|
680
|
+
getPromptFragmentIDFromResource(resourceId) {
|
|
681
|
+
// Check if the resource is a URI
|
|
682
|
+
if (resourceId instanceof core_1.URI) {
|
|
683
|
+
return this.getFragmentIDFromURI(resourceId);
|
|
684
|
+
}
|
|
685
|
+
return undefined;
|
|
686
|
+
}
|
|
388
687
|
async getCustomAgents() {
|
|
389
688
|
const agentsById = new Map();
|
|
390
689
|
// First, process additional (workspace) template directories to give them precedence
|
|
@@ -392,9 +691,9 @@ let FrontendPromptCustomizationServiceImpl = class FrontendPromptCustomizationSe
|
|
|
392
691
|
const dirURI = core_1.URI.fromFilePath(dirPath);
|
|
393
692
|
await this.loadCustomAgentsFromDirectory(dirURI, agentsById);
|
|
394
693
|
}
|
|
395
|
-
// Then process global
|
|
396
|
-
const
|
|
397
|
-
await this.loadCustomAgentsFromDirectory(
|
|
694
|
+
// Then process global templates directory (only adding agents that don't conflict)
|
|
695
|
+
const globalTemplatesDir = await this.getTemplatesDirectoryURI();
|
|
696
|
+
await this.loadCustomAgentsFromDirectory(globalTemplatesDir, agentsById);
|
|
398
697
|
// Return the merged list of agents
|
|
399
698
|
return Array.from(agentsById.values());
|
|
400
699
|
}
|
|
@@ -436,9 +735,9 @@ let FrontendPromptCustomizationServiceImpl = class FrontendPromptCustomizationSe
|
|
|
436
735
|
*/
|
|
437
736
|
async getCustomAgentsLocations() {
|
|
438
737
|
const locations = [];
|
|
439
|
-
// Check global
|
|
440
|
-
const
|
|
441
|
-
const globalAgentsUri =
|
|
738
|
+
// Check global templates directory
|
|
739
|
+
const globalTemplatesDir = await this.getTemplatesDirectoryURI();
|
|
740
|
+
const globalAgentsUri = globalTemplatesDir.resolve('customAgents.yml');
|
|
442
741
|
const globalExists = await this.fileService.exists(globalAgentsUri);
|
|
443
742
|
locations.push({ uri: globalAgentsUri, exists: globalExists });
|
|
444
743
|
// Check additional (workspace) template directories
|
|
@@ -456,7 +755,7 @@ let FrontendPromptCustomizationServiceImpl = class FrontendPromptCustomizationSe
|
|
|
456
755
|
* @param uri The URI of the customAgents.yml file to open or create
|
|
457
756
|
*/
|
|
458
757
|
async openCustomAgentYaml(uri) {
|
|
459
|
-
const content = (0, js_yaml_1.dump)([
|
|
758
|
+
const content = (0, js_yaml_1.dump)([newCustomAgentEntry]);
|
|
460
759
|
if (!await this.fileService.exists(uri)) {
|
|
461
760
|
await this.fileService.createFile(uri, buffer_1.BinaryBuffer.fromString(content));
|
|
462
761
|
}
|
|
@@ -468,30 +767,30 @@ let FrontendPromptCustomizationServiceImpl = class FrontendPromptCustomizationSe
|
|
|
468
767
|
openHandler.open(uri);
|
|
469
768
|
}
|
|
470
769
|
};
|
|
471
|
-
exports.
|
|
770
|
+
exports.DefaultPromptFragmentCustomizationService = DefaultPromptFragmentCustomizationService;
|
|
472
771
|
tslib_1.__decorate([
|
|
473
772
|
(0, inversify_1.inject)(env_variables_1.EnvVariablesServer),
|
|
474
773
|
tslib_1.__metadata("design:type", Object)
|
|
475
|
-
],
|
|
774
|
+
], DefaultPromptFragmentCustomizationService.prototype, "envVariablesServer", void 0);
|
|
476
775
|
tslib_1.__decorate([
|
|
477
776
|
(0, inversify_1.inject)(ai_core_preferences_1.AICorePreferences),
|
|
478
777
|
tslib_1.__metadata("design:type", Object)
|
|
479
|
-
],
|
|
778
|
+
], DefaultPromptFragmentCustomizationService.prototype, "preferences", void 0);
|
|
480
779
|
tslib_1.__decorate([
|
|
481
780
|
(0, inversify_1.inject)(file_service_1.FileService),
|
|
482
781
|
tslib_1.__metadata("design:type", file_service_1.FileService)
|
|
483
|
-
],
|
|
782
|
+
], DefaultPromptFragmentCustomizationService.prototype, "fileService", void 0);
|
|
484
783
|
tslib_1.__decorate([
|
|
485
784
|
(0, inversify_1.inject)(browser_1.OpenerService),
|
|
486
785
|
tslib_1.__metadata("design:type", Object)
|
|
487
|
-
],
|
|
786
|
+
], DefaultPromptFragmentCustomizationService.prototype, "openerService", void 0);
|
|
488
787
|
tslib_1.__decorate([
|
|
489
788
|
(0, inversify_1.postConstruct)(),
|
|
490
789
|
tslib_1.__metadata("design:type", Function),
|
|
491
790
|
tslib_1.__metadata("design:paramtypes", []),
|
|
492
791
|
tslib_1.__metadata("design:returntype", void 0)
|
|
493
|
-
],
|
|
494
|
-
exports.
|
|
792
|
+
], DefaultPromptFragmentCustomizationService.prototype, "init", null);
|
|
793
|
+
exports.DefaultPromptFragmentCustomizationService = DefaultPromptFragmentCustomizationService = tslib_1.__decorate([
|
|
495
794
|
(0, inversify_1.injectable)()
|
|
496
|
-
],
|
|
795
|
+
], DefaultPromptFragmentCustomizationService);
|
|
497
796
|
//# sourceMappingURL=frontend-prompt-customization-service.js.map
|