@theia/ai-core 1.67.0-next.13 → 1.67.0-next.56
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/README.md +1 -0
- package/data/prompttemplate.tmLanguage.json +3 -0
- package/package.json +9 -9
- package/src/browser/frontend-language-model-alias-registry.ts +11 -11
- package/src/common/agent-service.ts +6 -6
- package/src/common/prompt-service.ts +6 -2
- package/lib/browser/agent-completion-notification-service.d.ts +0 -69
- package/lib/browser/agent-completion-notification-service.d.ts.map +0 -1
- package/lib/browser/agent-completion-notification-service.js +0 -187
- package/lib/browser/agent-completion-notification-service.js.map +0 -1
- package/lib/browser/ai-activation-service.d.ts +0 -31
- package/lib/browser/ai-activation-service.d.ts.map +0 -1
- package/lib/browser/ai-activation-service.js +0 -56
- package/lib/browser/ai-activation-service.js.map +0 -1
- package/lib/browser/ai-command-handler-factory.d.ts +0 -4
- package/lib/browser/ai-command-handler-factory.d.ts.map +0 -1
- package/lib/browser/ai-command-handler-factory.js +0 -20
- package/lib/browser/ai-command-handler-factory.js.map +0 -1
- package/lib/browser/ai-core-command-contribution.d.ts +0 -8
- package/lib/browser/ai-core-command-contribution.d.ts.map +0 -1
- package/lib/browser/ai-core-command-contribution.js +0 -44
- package/lib/browser/ai-core-command-contribution.js.map +0 -1
- package/lib/browser/ai-core-frontend-application-contribution.d.ts +0 -10
- package/lib/browser/ai-core-frontend-application-contribution.d.ts.map +0 -1
- package/lib/browser/ai-core-frontend-application-contribution.js +0 -46
- package/lib/browser/ai-core-frontend-application-contribution.js.map +0 -1
- package/lib/browser/ai-core-frontend-module.d.ts +0 -4
- package/lib/browser/ai-core-frontend-module.d.ts.map +0 -1
- package/lib/browser/ai-core-frontend-module.js +0 -137
- package/lib/browser/ai-core-frontend-module.js.map +0 -1
- package/lib/browser/ai-settings-service.d.ts +0 -16
- package/lib/browser/ai-settings-service.d.ts.map +0 -1
- package/lib/browser/ai-settings-service.js +0 -78
- package/lib/browser/ai-settings-service.js.map +0 -1
- package/lib/browser/ai-variable-uri-label-provider.d.ts +0 -17
- package/lib/browser/ai-variable-uri-label-provider.d.ts.map +0 -1
- package/lib/browser/ai-variable-uri-label-provider.js +0 -85
- package/lib/browser/ai-variable-uri-label-provider.js.map +0 -1
- package/lib/browser/ai-view-contribution.d.ts +0 -14
- package/lib/browser/ai-view-contribution.d.ts.map +0 -1
- package/lib/browser/ai-view-contribution.js +0 -87
- package/lib/browser/ai-view-contribution.js.map +0 -1
- package/lib/browser/file-variable-contribution.d.ts +0 -23
- package/lib/browser/file-variable-contribution.d.ts.map +0 -1
- package/lib/browser/file-variable-contribution.js +0 -114
- package/lib/browser/file-variable-contribution.js.map +0 -1
- package/lib/browser/frontend-language-model-alias-registry.d.ts +0 -31
- package/lib/browser/frontend-language-model-alias-registry.d.ts.map +0 -1
- package/lib/browser/frontend-language-model-alias-registry.js +0 -170
- package/lib/browser/frontend-language-model-alias-registry.js.map +0 -1
- package/lib/browser/frontend-language-model-registry.d.ts +0 -49
- package/lib/browser/frontend-language-model-registry.d.ts.map +0 -1
- package/lib/browser/frontend-language-model-registry.js +0 -387
- package/lib/browser/frontend-language-model-registry.js.map +0 -1
- package/lib/browser/frontend-language-model-registry.spec.d.ts +0 -2
- package/lib/browser/frontend-language-model-registry.spec.d.ts.map +0 -1
- package/lib/browser/frontend-language-model-registry.spec.js +0 -248
- package/lib/browser/frontend-language-model-registry.spec.js.map +0 -1
- package/lib/browser/frontend-language-model-service.d.ts +0 -10
- package/lib/browser/frontend-language-model-service.d.ts.map +0 -1
- package/lib/browser/frontend-language-model-service.js +0 -66
- package/lib/browser/frontend-language-model-service.js.map +0 -1
- package/lib/browser/frontend-prompt-customization-service.d.ts +0 -271
- package/lib/browser/frontend-prompt-customization-service.d.ts.map +0 -1
- package/lib/browser/frontend-prompt-customization-service.js +0 -869
- package/lib/browser/frontend-prompt-customization-service.js.map +0 -1
- package/lib/browser/frontend-prompt-customization-service.spec.d.ts +0 -2
- package/lib/browser/frontend-prompt-customization-service.spec.d.ts.map +0 -1
- package/lib/browser/frontend-prompt-customization-service.spec.js +0 -127
- package/lib/browser/frontend-prompt-customization-service.spec.js.map +0 -1
- package/lib/browser/frontend-variable-service.d.ts +0 -61
- package/lib/browser/frontend-variable-service.d.ts.map +0 -1
- package/lib/browser/frontend-variable-service.js +0 -165
- package/lib/browser/frontend-variable-service.js.map +0 -1
- package/lib/browser/index.d.ts +0 -20
- package/lib/browser/index.d.ts.map +0 -1
- package/lib/browser/index.js +0 -38
- package/lib/browser/index.js.map +0 -1
- package/lib/browser/open-editors-variable-contribution.d.ts +0 -17
- package/lib/browser/open-editors-variable-contribution.d.ts.map +0 -1
- package/lib/browser/open-editors-variable-contribution.js +0 -84
- package/lib/browser/open-editors-variable-contribution.js.map +0 -1
- package/lib/browser/os-notification-service.d.ts +0 -96
- package/lib/browser/os-notification-service.d.ts.map +0 -1
- package/lib/browser/os-notification-service.js +0 -222
- package/lib/browser/os-notification-service.js.map +0 -1
- package/lib/browser/prompttemplate-contribution.d.ts +0 -29
- package/lib/browser/prompttemplate-contribution.d.ts.map +0 -1
- package/lib/browser/prompttemplate-contribution.js +0 -243
- package/lib/browser/prompttemplate-contribution.js.map +0 -1
- package/lib/browser/prompttemplate-parser.d.ts +0 -36
- package/lib/browser/prompttemplate-parser.d.ts.map +0 -1
- package/lib/browser/prompttemplate-parser.js +0 -94
- package/lib/browser/prompttemplate-parser.js.map +0 -1
- package/lib/browser/theia-variable-contribution.d.ts +0 -26
- package/lib/browser/theia-variable-contribution.d.ts.map +0 -1
- package/lib/browser/theia-variable-contribution.js +0 -146
- package/lib/browser/theia-variable-contribution.js.map +0 -1
- package/lib/browser/token-usage-frontend-service-impl.d.ts +0 -25
- package/lib/browser/token-usage-frontend-service-impl.d.ts.map +0 -1
- package/lib/browser/token-usage-frontend-service-impl.js +0 -138
- package/lib/browser/token-usage-frontend-service-impl.js.map +0 -1
- package/lib/browser/token-usage-frontend-service.d.ts +0 -33
- package/lib/browser/token-usage-frontend-service.d.ts.map +0 -1
- package/lib/browser/token-usage-frontend-service.js +0 -23
- package/lib/browser/token-usage-frontend-service.js.map +0 -1
- package/lib/browser/window-blink-service.d.ts +0 -41
- package/lib/browser/window-blink-service.d.ts.map +0 -1
- package/lib/browser/window-blink-service.js +0 -174
- package/lib/browser/window-blink-service.js.map +0 -1
- package/lib/common/agent-preferences.d.ts +0 -4
- package/lib/common/agent-preferences.d.ts.map +0 -1
- package/lib/common/agent-preferences.js +0 -84
- package/lib/common/agent-preferences.js.map +0 -1
- package/lib/common/agent-service.d.ts +0 -66
- package/lib/common/agent-service.d.ts.map +0 -1
- package/lib/common/agent-service.js +0 -104
- package/lib/common/agent-service.js.map +0 -1
- package/lib/common/agent.d.ts +0 -72
- package/lib/common/agent.d.ts.map +0 -1
- package/lib/common/agent.js +0 -20
- package/lib/common/agent.js.map +0 -1
- package/lib/common/agents-variable-contribution.d.ts +0 -19
- package/lib/common/agents-variable-contribution.d.ts.map +0 -1
- package/lib/common/agents-variable-contribution.js +0 -57
- package/lib/common/agents-variable-contribution.js.map +0 -1
- package/lib/common/ai-core-preferences.d.ts +0 -48
- package/lib/common/ai-core-preferences.d.ts.map +0 -1
- package/lib/common/ai-core-preferences.js +0 -204
- package/lib/common/ai-core-preferences.js.map +0 -1
- package/lib/common/ai-variable-resource.d.ts +0 -18
- package/lib/common/ai-variable-resource.d.ts.map +0 -1
- package/lib/common/ai-variable-resource.js +0 -103
- package/lib/common/ai-variable-resource.js.map +0 -1
- package/lib/common/configurable-in-memory-resources.d.ts +0 -47
- package/lib/common/configurable-in-memory-resources.d.ts.map +0 -1
- package/lib/common/configurable-in-memory-resources.js +0 -154
- package/lib/common/configurable-in-memory-resources.js.map +0 -1
- package/lib/common/index.d.ts +0 -22
- package/lib/common/index.d.ts.map +0 -1
- package/lib/common/index.js +0 -40
- package/lib/common/index.js.map +0 -1
- package/lib/common/language-model-alias.d.ts +0 -58
- package/lib/common/language-model-alias.d.ts.map +0 -1
- package/lib/common/language-model-alias.js +0 -20
- package/lib/common/language-model-alias.js.map +0 -1
- package/lib/common/language-model-delegate.d.ts +0 -25
- package/lib/common/language-model-delegate.d.ts.map +0 -1
- package/lib/common/language-model-delegate.js +0 -26
- package/lib/common/language-model-delegate.js.map +0 -1
- package/lib/common/language-model-interaction-model.d.ts +0 -74
- package/lib/common/language-model-interaction-model.d.ts.map +0 -1
- package/lib/common/language-model-interaction-model.js +0 -3
- package/lib/common/language-model-interaction-model.js.map +0 -1
- package/lib/common/language-model-service.d.ts +0 -38
- package/lib/common/language-model-service.d.ts.map +0 -1
- package/lib/common/language-model-service.js +0 -128
- package/lib/common/language-model-service.js.map +0 -1
- package/lib/common/language-model-util.d.ts +0 -17
- package/lib/common/language-model-util.d.ts.map +0 -1
- package/lib/common/language-model-util.js +0 -82
- package/lib/common/language-model-util.js.map +0 -1
- package/lib/common/language-model.d.ts +0 -285
- package/lib/common/language-model.d.ts.map +0 -1
- package/lib/common/language-model.js +0 -248
- package/lib/common/language-model.js.map +0 -1
- package/lib/common/language-model.spec.d.ts +0 -2
- package/lib/common/language-model.spec.d.ts.map +0 -1
- package/lib/common/language-model.spec.js +0 -62
- package/lib/common/language-model.spec.js.map +0 -1
- package/lib/common/notification-types.d.ts +0 -7
- package/lib/common/notification-types.d.ts.map +0 -1
- package/lib/common/notification-types.js +0 -29
- package/lib/common/notification-types.js.map +0 -1
- package/lib/common/prompt-service-util.d.ts +0 -8
- package/lib/common/prompt-service-util.d.ts.map +0 -1
- package/lib/common/prompt-service-util.js +0 -34
- package/lib/common/prompt-service-util.js.map +0 -1
- package/lib/common/prompt-service.d.ts +0 -466
- package/lib/common/prompt-service.d.ts.map +0 -1
- package/lib/common/prompt-service.js +0 -653
- package/lib/common/prompt-service.js.map +0 -1
- package/lib/common/prompt-service.spec.d.ts +0 -2
- package/lib/common/prompt-service.spec.d.ts.map +0 -1
- package/lib/common/prompt-service.spec.js +0 -431
- package/lib/common/prompt-service.spec.js.map +0 -1
- package/lib/common/prompt-text.d.ts +0 -8
- package/lib/common/prompt-text.d.ts.map +0 -1
- package/lib/common/prompt-text.js +0 -27
- package/lib/common/prompt-text.js.map +0 -1
- package/lib/common/prompt-variable-contribution.d.ts +0 -18
- package/lib/common/prompt-variable-contribution.d.ts.map +0 -1
- package/lib/common/prompt-variable-contribution.js +0 -207
- package/lib/common/prompt-variable-contribution.js.map +0 -1
- package/lib/common/prompt-variable-contribution.spec.d.ts +0 -2
- package/lib/common/prompt-variable-contribution.spec.d.ts.map +0 -1
- package/lib/common/prompt-variable-contribution.spec.js +0 -163
- package/lib/common/prompt-variable-contribution.spec.js.map +0 -1
- package/lib/common/protocol.d.ts +0 -25
- package/lib/common/protocol.d.ts.map +0 -1
- package/lib/common/protocol.js +0 -22
- package/lib/common/protocol.js.map +0 -1
- package/lib/common/settings-service.d.ts +0 -29
- package/lib/common/settings-service.d.ts.map +0 -1
- package/lib/common/settings-service.js +0 -5
- package/lib/common/settings-service.js.map +0 -1
- package/lib/common/today-variable-contribution.d.ts +0 -17
- package/lib/common/today-variable-contribution.d.ts.map +0 -1
- package/lib/common/today-variable-contribution.js +0 -68
- package/lib/common/today-variable-contribution.js.map +0 -1
- package/lib/common/token-usage-service.d.ts +0 -43
- package/lib/common/token-usage-service.d.ts.map +0 -1
- package/lib/common/token-usage-service.js +0 -20
- package/lib/common/token-usage-service.js.map +0 -1
- package/lib/common/tool-invocation-registry.d.ts +0 -66
- package/lib/common/tool-invocation-registry.d.ts.map +0 -1
- package/lib/common/tool-invocation-registry.js +0 -101
- package/lib/common/tool-invocation-registry.js.map +0 -1
- package/lib/common/variable-service.d.ts +0 -172
- package/lib/common/variable-service.d.ts.map +0 -1
- package/lib/common/variable-service.js +0 -287
- package/lib/common/variable-service.js.map +0 -1
- package/lib/common/variable-service.spec.d.ts +0 -2
- package/lib/common/variable-service.spec.d.ts.map +0 -1
- package/lib/common/variable-service.spec.js +0 -237
- package/lib/common/variable-service.spec.js.map +0 -1
- package/lib/node/ai-core-backend-module.d.ts +0 -4
- package/lib/node/ai-core-backend-module.d.ts.map +0 -1
- package/lib/node/ai-core-backend-module.js +0 -65
- package/lib/node/ai-core-backend-module.js.map +0 -1
- package/lib/node/backend-language-model-registry.d.ts +0 -13
- package/lib/node/backend-language-model-registry.d.ts.map +0 -1
- package/lib/node/backend-language-model-registry.js +0 -68
- package/lib/node/backend-language-model-registry.js.map +0 -1
- package/lib/node/language-model-frontend-delegate.d.ts +0 -18
- package/lib/node/language-model-frontend-delegate.d.ts.map +0 -1
- package/lib/node/language-model-frontend-delegate.js +0 -109
- package/lib/node/language-model-frontend-delegate.js.map +0 -1
- package/lib/node/token-usage-service-impl.d.ts +0 -23
- package/lib/node/token-usage-service-impl.d.ts.map +0 -1
- package/lib/node/token-usage-service-impl.js +0 -78
- package/lib/node/token-usage-service-impl.js.map +0 -1
- package/lib/node/tool-request-parameters.spec.d.ts +0 -2
- package/lib/node/tool-request-parameters.spec.d.ts.map +0 -1
- package/lib/node/tool-request-parameters.spec.js +0 -116
- package/lib/node/tool-request-parameters.spec.js.map +0 -1
|
@@ -1,869 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// *****************************************************************************
|
|
3
|
-
// Copyright (C) 2024 EclipseSource GmbH.
|
|
4
|
-
//
|
|
5
|
-
// This program and the accompanying materials are made available under the
|
|
6
|
-
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
-
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
-
//
|
|
9
|
-
// This Source Code may also be made available under the following Secondary
|
|
10
|
-
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
-
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
-
// with the GNU Classpath Exception which is available at
|
|
13
|
-
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
-
//
|
|
15
|
-
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
|
-
// *****************************************************************************
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.DefaultPromptFragmentCustomizationService = exports.getCustomizationSourceString = exports.CustomizationSource = void 0;
|
|
19
|
-
const tslib_1 = require("tslib");
|
|
20
|
-
const core_1 = require("@theia/core");
|
|
21
|
-
const browser_1 = require("@theia/core/lib/browser");
|
|
22
|
-
const inversify_1 = require("@theia/core/shared/inversify");
|
|
23
|
-
const common_1 = require("../common");
|
|
24
|
-
const buffer_1 = require("@theia/core/lib/common/buffer");
|
|
25
|
-
const file_service_1 = require("@theia/filesystem/lib/browser/file-service");
|
|
26
|
-
const ai_core_preferences_1 = require("../common/ai-core-preferences");
|
|
27
|
-
const env_variables_1 = require("@theia/core/lib/common/env-variables");
|
|
28
|
-
const js_yaml_1 = require("js-yaml");
|
|
29
|
-
const prompttemplate_contribution_1 = require("./prompttemplate-contribution");
|
|
30
|
-
const prompttemplate_parser_1 = require("./prompttemplate-parser");
|
|
31
|
-
/**
|
|
32
|
-
* Default template entry for creating custom agents
|
|
33
|
-
*/
|
|
34
|
-
const newCustomAgentEntry = {
|
|
35
|
-
id: 'my_agent',
|
|
36
|
-
name: 'My Agent',
|
|
37
|
-
description: core_1.nls.localize('theia/ai/core/customAgentTemplate/description', 'This is an example agent. Please adapt the properties to fit your needs.'),
|
|
38
|
-
prompt: `{{!-- Note: The context section below will resolve all context elements (e.g. files) to their full content
|
|
39
|
-
in the system prompt. Context elements can be added by the user in the default chat view (e.g. via DnD or the "+" button).
|
|
40
|
-
If you want a more fine-grained, on demand resolvement of context elements, you can also resolve files to their paths only
|
|
41
|
-
and equip the agent with functions so that the LLM can retrieve files on demand. See the Coder Agent prompt for an example.--}}
|
|
42
|
-
|
|
43
|
-
# Role
|
|
44
|
-
You are an example agent. Be nice and helpful to the user.
|
|
45
|
-
|
|
46
|
-
## Current Context
|
|
47
|
-
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.
|
|
48
|
-
{{contextDetails}}`,
|
|
49
|
-
defaultLLM: 'openai/gpt-4o'
|
|
50
|
-
};
|
|
51
|
-
var CustomizationSource;
|
|
52
|
-
(function (CustomizationSource) {
|
|
53
|
-
CustomizationSource[CustomizationSource["CUSTOMIZED"] = 1] = "CUSTOMIZED";
|
|
54
|
-
CustomizationSource[CustomizationSource["FOLDER"] = 2] = "FOLDER";
|
|
55
|
-
CustomizationSource[CustomizationSource["FILE"] = 3] = "FILE";
|
|
56
|
-
})(CustomizationSource || (exports.CustomizationSource = CustomizationSource = {}));
|
|
57
|
-
function getCustomizationSourceString(origin) {
|
|
58
|
-
switch (origin) {
|
|
59
|
-
case CustomizationSource.FILE:
|
|
60
|
-
return 'Workspace Template Files';
|
|
61
|
-
case CustomizationSource.FOLDER:
|
|
62
|
-
return 'Workspace Template Directories';
|
|
63
|
-
default:
|
|
64
|
-
return 'Prompt Templates Folder';
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
exports.getCustomizationSourceString = getCustomizationSourceString;
|
|
68
|
-
let DefaultPromptFragmentCustomizationService = class DefaultPromptFragmentCustomizationService {
|
|
69
|
-
constructor() {
|
|
70
|
-
/** Stores URI strings of template files from directories currently being monitored for changes. */
|
|
71
|
-
this.trackedTemplateURIs = new Set();
|
|
72
|
-
/** Contains the currently active customization, mapped by prompt fragment ID. */
|
|
73
|
-
this.activeCustomizations = new Map();
|
|
74
|
-
/** Tracks all loaded customizations, including overridden ones, mapped by source URI. */
|
|
75
|
-
this.allCustomizations = new Map();
|
|
76
|
-
/** Stores additional directory paths for loading template files. */
|
|
77
|
-
this.additionalTemplateDirs = new Set();
|
|
78
|
-
/** Contains file extensions that identify prompt template files. */
|
|
79
|
-
this.templateExtensions = new Set([prompttemplate_contribution_1.PROMPT_TEMPLATE_EXTENSION]);
|
|
80
|
-
/** Stores specific file paths, provided by the settings, that should be treated as templates. */
|
|
81
|
-
this.workspaceTemplateFiles = new Set();
|
|
82
|
-
/** Maps URI strings to WatchedFileInfo objects for individually watched template files. */
|
|
83
|
-
this.watchedFiles = new Map();
|
|
84
|
-
/** Collection of disposable resources for cleanup when the service updates or is disposed. */
|
|
85
|
-
this.toDispose = new core_1.DisposableCollection();
|
|
86
|
-
this.onDidChangePromptFragmentCustomizationEmitter = new core_1.Emitter();
|
|
87
|
-
this.onDidChangePromptFragmentCustomization = this.onDidChangePromptFragmentCustomizationEmitter.event;
|
|
88
|
-
this.onDidChangeCustomAgentsEmitter = new core_1.Emitter();
|
|
89
|
-
this.onDidChangeCustomAgents = this.onDidChangeCustomAgentsEmitter.event;
|
|
90
|
-
}
|
|
91
|
-
init() {
|
|
92
|
-
this.preferences.onPreferenceChanged(event => {
|
|
93
|
-
if (event.preferenceName === ai_core_preferences_1.PREFERENCE_NAME_PROMPT_TEMPLATES) {
|
|
94
|
-
this.update();
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
this.update();
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Updates the service by reloading all template files and watching for changes
|
|
101
|
-
*/
|
|
102
|
-
async update() {
|
|
103
|
-
this.toDispose.dispose();
|
|
104
|
-
// we need to assign local variables, so that updates running in parallel don't interfere with each other
|
|
105
|
-
const activeCustomizationsCopy = new Map();
|
|
106
|
-
const trackedTemplateURIsCopy = new Set();
|
|
107
|
-
const allCustomizationsCopy = new Map();
|
|
108
|
-
const watchedFilesCopy = new Map();
|
|
109
|
-
// Process in order of priority (lowest to highest)
|
|
110
|
-
// First process the main templates directory (lowest priority)
|
|
111
|
-
const templatesURI = await this.getTemplatesDirectoryURI();
|
|
112
|
-
await this.processTemplateDirectory(activeCustomizationsCopy, trackedTemplateURIsCopy, allCustomizationsCopy, templatesURI, 1, CustomizationSource.CUSTOMIZED); // Priority 1 for customized fragments
|
|
113
|
-
// Process additional template directories (medium priority)
|
|
114
|
-
for (const dirPath of this.additionalTemplateDirs) {
|
|
115
|
-
const dirURI = core_1.URI.fromFilePath(dirPath);
|
|
116
|
-
await this.processTemplateDirectory(activeCustomizationsCopy, trackedTemplateURIsCopy, allCustomizationsCopy, dirURI, 2, CustomizationSource.FOLDER); // Priority 2 for folder fragments
|
|
117
|
-
}
|
|
118
|
-
// Process specific template files (highest priority)
|
|
119
|
-
await this.processTemplateFiles(activeCustomizationsCopy, trackedTemplateURIsCopy, allCustomizationsCopy, watchedFilesCopy);
|
|
120
|
-
this.activeCustomizations = activeCustomizationsCopy;
|
|
121
|
-
this.trackedTemplateURIs = trackedTemplateURIsCopy;
|
|
122
|
-
this.allCustomizations = allCustomizationsCopy;
|
|
123
|
-
this.watchedFiles = watchedFilesCopy;
|
|
124
|
-
this.onDidChangeCustomAgentsEmitter.fire();
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Adds a template to the customizations map, handling conflicts based on priority
|
|
128
|
-
* @param activeCustomizationsCopy The map to add the customization to
|
|
129
|
-
* @param id The fragment ID
|
|
130
|
-
* @param template The template content
|
|
131
|
-
* @param sourceUri The URI of the source file (used to distinguish updates from conflicts)
|
|
132
|
-
* @param allCustomizationsCopy The map to track all loaded customizations
|
|
133
|
-
* @param priority The customization priority
|
|
134
|
-
* @param origin The source type of the customization
|
|
135
|
-
* @param metadata Optional command metadata
|
|
136
|
-
*/
|
|
137
|
-
addTemplate(activeCustomizationsCopy, id, template, sourceUri, allCustomizationsCopy, priority, origin, metadata) {
|
|
138
|
-
// Generate a unique customization ID based on source URI and priority
|
|
139
|
-
const customizationId = this.generateCustomizationId(id, sourceUri);
|
|
140
|
-
// Create customization object with metadata
|
|
141
|
-
const customization = {
|
|
142
|
-
id,
|
|
143
|
-
template,
|
|
144
|
-
sourceUri,
|
|
145
|
-
priority,
|
|
146
|
-
customizationId,
|
|
147
|
-
origin,
|
|
148
|
-
...(metadata && {
|
|
149
|
-
isCommand: metadata.isCommand,
|
|
150
|
-
commandName: metadata.commandName,
|
|
151
|
-
commandDescription: metadata.commandDescription,
|
|
152
|
-
commandArgumentHint: metadata.commandArgumentHint,
|
|
153
|
-
commandAgents: metadata.commandAgents,
|
|
154
|
-
})
|
|
155
|
-
};
|
|
156
|
-
// Always add to allCustomizationsCopy to keep track of all customizations including overridden ones
|
|
157
|
-
if (sourceUri) {
|
|
158
|
-
allCustomizationsCopy.set(sourceUri, customization);
|
|
159
|
-
}
|
|
160
|
-
const existingEntry = activeCustomizationsCopy.get(id);
|
|
161
|
-
if (existingEntry) {
|
|
162
|
-
// If this is an update to the same file (same source URI)
|
|
163
|
-
if (sourceUri && existingEntry.sourceUri === sourceUri) {
|
|
164
|
-
// Update the content while keeping the same priority and source
|
|
165
|
-
activeCustomizationsCopy.set(id, customization);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
// If the new customization has higher priority, replace the existing one
|
|
169
|
-
if (priority > existingEntry.priority) {
|
|
170
|
-
activeCustomizationsCopy.set(id, customization);
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
else if (priority === existingEntry.priority) {
|
|
174
|
-
// There is a conflict with the same priority, we ignore the new customization
|
|
175
|
-
const conflictSourceUri = existingEntry.sourceUri ? ` (Existing source: ${existingEntry.sourceUri}, New source: ${sourceUri})` : '';
|
|
176
|
-
console.warn(`Fragment conflict detected for ID '${id}' with equal priority.${conflictSourceUri}`);
|
|
177
|
-
}
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
// No conflict at all, add the customization
|
|
181
|
-
activeCustomizationsCopy.set(id, customization);
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Generates a unique customization ID based on the fragment ID, source URI, and priority
|
|
185
|
-
* @param id The fragment ID
|
|
186
|
-
* @param sourceUri The source URI of the template
|
|
187
|
-
* @returns A unique customization ID
|
|
188
|
-
*/
|
|
189
|
-
generateCustomizationId(id, sourceUri) {
|
|
190
|
-
// Create a customization ID that contains information about the source and priority
|
|
191
|
-
// This ensures uniqueness across different customization sources
|
|
192
|
-
const sourceHash = this.hashString(sourceUri);
|
|
193
|
-
return `${id}_${sourceHash}`;
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Simple hash function to generate a short identifier from a string
|
|
197
|
-
* @param str The string to hash
|
|
198
|
-
* @returns A string hash
|
|
199
|
-
*/
|
|
200
|
-
hashString(str) {
|
|
201
|
-
let hash = 0;
|
|
202
|
-
for (let i = 0; i < str.length; i++) {
|
|
203
|
-
const char = str.charCodeAt(i);
|
|
204
|
-
hash = ((hash << 5) - hash) + char;
|
|
205
|
-
hash = hash & hash; // Convert to 32bit integer
|
|
206
|
-
}
|
|
207
|
-
return Math.abs(hash).toString(36).substring(0, 8);
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Parses a template file that may contain YAML front matter
|
|
211
|
-
* @param fileContent The raw file content
|
|
212
|
-
* @returns Parsed metadata and template content
|
|
213
|
-
*/
|
|
214
|
-
parseTemplateWithMetadata(fileContent) {
|
|
215
|
-
return (0, prompttemplate_parser_1.parseTemplateWithMetadata)(fileContent);
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Removes a customization from customizations maps based on the source URI.
|
|
219
|
-
* Also checks for any lower-priority customizations with the same ID that might need to be loaded.
|
|
220
|
-
* @param sourceUri The URI of the source file being removed
|
|
221
|
-
* @param allCustomizationsCopy The map of all loaded customizations
|
|
222
|
-
* @param activeCustomizationsCopy The map of active customizations
|
|
223
|
-
* @param trackedTemplateURIsCopy Optional set of tracked URIs to update
|
|
224
|
-
* @returns The fragment ID that was removed, or undefined if no customization was found
|
|
225
|
-
*/
|
|
226
|
-
removeCustomizationFromMaps(sourceUri, allCustomizationsCopy, activeCustomizationsCopy, trackedTemplateURIsCopy) {
|
|
227
|
-
// Get the customization entry from allCustomizationsCopy
|
|
228
|
-
const removedCustomization = allCustomizationsCopy.get(sourceUri);
|
|
229
|
-
if (!removedCustomization) {
|
|
230
|
-
return undefined;
|
|
231
|
-
}
|
|
232
|
-
const fragmentId = removedCustomization.id;
|
|
233
|
-
allCustomizationsCopy.delete(sourceUri);
|
|
234
|
-
trackedTemplateURIsCopy.delete(sourceUri);
|
|
235
|
-
// If the customization is in the active customizations map, we check if there is another customization previously conflicting with it
|
|
236
|
-
const activeCustomization = activeCustomizationsCopy.get(fragmentId);
|
|
237
|
-
if (activeCustomization && activeCustomization.sourceUri === sourceUri) {
|
|
238
|
-
activeCustomizationsCopy.delete(fragmentId);
|
|
239
|
-
// Find any lower-priority customizations with the same ID that were previously ignored
|
|
240
|
-
const lowerPriorityCustomizations = Array.from(allCustomizationsCopy.values())
|
|
241
|
-
.filter(t => t.id === fragmentId)
|
|
242
|
-
.sort((a, b) => b.priority - a.priority); // Sort by priority (highest first)
|
|
243
|
-
// If there are any lower-priority customizations, add the highest priority one
|
|
244
|
-
if (lowerPriorityCustomizations.length > 0) {
|
|
245
|
-
const highestRemainingCustomization = lowerPriorityCustomizations[0];
|
|
246
|
-
activeCustomizationsCopy.set(fragmentId, highestRemainingCustomization);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
return fragmentId;
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Process the template files specified by path, watching for changes
|
|
253
|
-
* and loading their content into the customizations map
|
|
254
|
-
* @param activeCustomizationsCopy Map to store active customizations
|
|
255
|
-
* @param trackedTemplateURIsCopy Set to track URIs being monitored
|
|
256
|
-
* @param allCustomizationsCopy Map to store all loaded customizations
|
|
257
|
-
* @param watchedFilesCopy Map to store file watch information
|
|
258
|
-
*/
|
|
259
|
-
async processTemplateFiles(activeCustomizationsCopy, trackedTemplateURIsCopy, allCustomizationsCopy, watchedFilesCopy) {
|
|
260
|
-
const priority = 3; // Highest priority for specific files
|
|
261
|
-
const parsedPromptFragments = new Set();
|
|
262
|
-
for (const filePath of this.workspaceTemplateFiles) {
|
|
263
|
-
const fileURI = core_1.URI.fromFilePath(filePath);
|
|
264
|
-
const fragmentId = this.getFragmentIdFromFilePath(filePath);
|
|
265
|
-
const uriString = fileURI.toString();
|
|
266
|
-
const customizationId = this.generateCustomizationId(fragmentId, uriString);
|
|
267
|
-
watchedFilesCopy.set(uriString, { uri: fileURI, fragmentId, customizationId });
|
|
268
|
-
this.toDispose.push(this.fileService.watch(fileURI, { recursive: false, excludes: [] }));
|
|
269
|
-
if (await this.fileService.exists(fileURI)) {
|
|
270
|
-
trackedTemplateURIsCopy.add(uriString);
|
|
271
|
-
const fileContent = await this.fileService.read(fileURI);
|
|
272
|
-
const parsed = this.parseTemplateWithMetadata(fileContent.value);
|
|
273
|
-
this.addTemplate(activeCustomizationsCopy, fragmentId, parsed.template, uriString, allCustomizationsCopy, priority, CustomizationSource.FILE, parsed.metadata);
|
|
274
|
-
parsedPromptFragments.add(fragmentId);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
this.onDidChangePromptFragmentCustomizationEmitter.fire(Array.from(parsedPromptFragments));
|
|
278
|
-
this.toDispose.push(this.fileService.onDidFilesChange(async (event) => {
|
|
279
|
-
// Only watch for changes that are in the watchedFiles map
|
|
280
|
-
if (!event.changes.some(change => this.watchedFiles.get(change.resource.toString()))) {
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
// Track changes for batched notification
|
|
284
|
-
const changedFragmentIds = new Set();
|
|
285
|
-
// Handle deleted files
|
|
286
|
-
for (const deletedFile of event.getDeleted()) {
|
|
287
|
-
const fileUriString = deletedFile.resource.toString();
|
|
288
|
-
const fileInfo = this.watchedFiles.get(fileUriString);
|
|
289
|
-
if (fileInfo) {
|
|
290
|
-
const removedFragmentId = this.removeCustomizationFromMaps(fileUriString, allCustomizationsCopy, activeCustomizationsCopy, trackedTemplateURIsCopy);
|
|
291
|
-
if (removedFragmentId) {
|
|
292
|
-
changedFragmentIds.add(removedFragmentId);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
// Handle updated files
|
|
297
|
-
for (const updatedFile of event.getUpdated()) {
|
|
298
|
-
const fileUriString = updatedFile.resource.toString();
|
|
299
|
-
const fileInfo = this.watchedFiles.get(fileUriString);
|
|
300
|
-
if (fileInfo) {
|
|
301
|
-
const fileContent = await this.fileService.read(fileInfo.uri);
|
|
302
|
-
const parsed = this.parseTemplateWithMetadata(fileContent.value);
|
|
303
|
-
this.addTemplate(this.activeCustomizations, fileInfo.fragmentId, parsed.template, fileUriString, this.allCustomizations, priority, CustomizationSource.FILE, parsed.metadata);
|
|
304
|
-
changedFragmentIds.add(fileInfo.fragmentId);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
// Handle newly created files
|
|
308
|
-
for (const addedFile of event.getAdded()) {
|
|
309
|
-
const fileUriString = addedFile.resource.toString();
|
|
310
|
-
const fileInfo = this.watchedFiles.get(fileUriString);
|
|
311
|
-
if (fileInfo) {
|
|
312
|
-
const fileContent = await this.fileService.read(fileInfo.uri);
|
|
313
|
-
const parsed = this.parseTemplateWithMetadata(fileContent.value);
|
|
314
|
-
this.addTemplate(this.activeCustomizations, fileInfo.fragmentId, parsed.template, fileUriString, this.allCustomizations, priority, CustomizationSource.FILE, parsed.metadata);
|
|
315
|
-
this.trackedTemplateURIs.add(fileUriString);
|
|
316
|
-
changedFragmentIds.add(fileInfo.fragmentId);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
const changedFragmentIdsArray = Array.from(changedFragmentIds);
|
|
320
|
-
if (changedFragmentIdsArray.length > 0) {
|
|
321
|
-
this.onDidChangePromptFragmentCustomizationEmitter.fire(changedFragmentIdsArray);
|
|
322
|
-
}
|
|
323
|
-
;
|
|
324
|
-
}));
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Extract a fragment ID from a file path
|
|
328
|
-
* @param filePath The path to the template file
|
|
329
|
-
* @returns A fragment ID derived from the file name
|
|
330
|
-
*/
|
|
331
|
-
getFragmentIdFromFilePath(filePath) {
|
|
332
|
-
const uri = core_1.URI.fromFilePath(filePath);
|
|
333
|
-
return this.removePromptTemplateSuffix(uri.path.name);
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Processes a directory for template files, adding them to the customizations map
|
|
337
|
-
* and setting up file watching
|
|
338
|
-
* @param activeCustomizationsCopy Map to store active customizations
|
|
339
|
-
* @param trackedTemplateURIsCopy Set to track URIs being monitored
|
|
340
|
-
* @param allCustomizationsCopy Map to store all loaded customizations
|
|
341
|
-
* @param dirURI URI of the directory to process
|
|
342
|
-
* @param priority Priority level for customizations in this directory
|
|
343
|
-
* @param customizationSource Source type of the customization
|
|
344
|
-
*/
|
|
345
|
-
async processTemplateDirectory(activeCustomizationsCopy, trackedTemplateURIsCopy, allCustomizationsCopy, dirURI, priority, customizationSource) {
|
|
346
|
-
const dirExists = await this.fileService.exists(dirURI);
|
|
347
|
-
// Process existing files if directory exists
|
|
348
|
-
if (dirExists) {
|
|
349
|
-
await this.processExistingTemplateDirectory(activeCustomizationsCopy, trackedTemplateURIsCopy, allCustomizationsCopy, dirURI, priority, customizationSource);
|
|
350
|
-
}
|
|
351
|
-
// Set up file watching for the directory (works for both existing and non-existing directories)
|
|
352
|
-
this.setupDirectoryWatcher(dirURI, priority, customizationSource);
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
* Processes an existing directory for template files
|
|
356
|
-
* @param activeCustomizationsCopy Map to store active customizations
|
|
357
|
-
* @param trackedTemplateURIsCopy Set to track URIs being monitored
|
|
358
|
-
* @param allCustomizationsCopy Map to store all loaded customizations
|
|
359
|
-
* @param dirURI URI of the directory to process
|
|
360
|
-
* @param priority Priority level for customizations in this directory
|
|
361
|
-
* @param customizationSource Source type of the customization
|
|
362
|
-
*/
|
|
363
|
-
async processExistingTemplateDirectory(activeCustomizationsCopy, trackedTemplateURIsCopy, allCustomizationsCopy, dirURI, priority, customizationSource) {
|
|
364
|
-
const stat = await this.fileService.resolve(dirURI);
|
|
365
|
-
if (stat.children === undefined) {
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
const parsedPromptFragments = new Set();
|
|
369
|
-
for (const file of stat.children) {
|
|
370
|
-
if (!file.isFile) {
|
|
371
|
-
continue;
|
|
372
|
-
}
|
|
373
|
-
const fileURI = file.resource;
|
|
374
|
-
if (this.isPromptTemplateExtension(fileURI.path.ext)) {
|
|
375
|
-
trackedTemplateURIsCopy.add(fileURI.toString());
|
|
376
|
-
const fileContent = await this.fileService.read(fileURI);
|
|
377
|
-
const parsed = this.parseTemplateWithMetadata(fileContent.value);
|
|
378
|
-
const fragmentId = this.removePromptTemplateSuffix(file.name);
|
|
379
|
-
this.addTemplate(activeCustomizationsCopy, fragmentId, parsed.template, fileURI.toString(), allCustomizationsCopy, priority, customizationSource, parsed.metadata);
|
|
380
|
-
parsedPromptFragments.add(fragmentId);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
this.onDidChangePromptFragmentCustomizationEmitter.fire(Array.from(parsedPromptFragments));
|
|
384
|
-
this.onDidChangeCustomAgentsEmitter.fire();
|
|
385
|
-
}
|
|
386
|
-
/**
|
|
387
|
-
* Sets up file watching for a template directory (works for both existing and non-existing directories)
|
|
388
|
-
* @param dirURI URI of the directory to watch
|
|
389
|
-
* @param priority Priority level for customizations in this directory
|
|
390
|
-
* @param customizationSource Source type of the customization
|
|
391
|
-
*/
|
|
392
|
-
setupDirectoryWatcher(dirURI, priority, customizationSource) {
|
|
393
|
-
this.toDispose.push(this.fileService.watch(dirURI, { recursive: true, excludes: [] }));
|
|
394
|
-
this.toDispose.push(this.fileService.onDidFilesChange(async (event) => {
|
|
395
|
-
// Filter for changes within the watched directory
|
|
396
|
-
if (!event.changes.some(change => change.resource.toString().startsWith(dirURI.toString()))) {
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
// Handle directory creation or deletion (when watching a previously non-existent directory)
|
|
400
|
-
if (event.getAdded().some(addedFile => addedFile.resource.toString() === dirURI.toString()) ||
|
|
401
|
-
event.getDeleted().some(deletedFile => deletedFile.resource.toString() === dirURI.toString())) {
|
|
402
|
-
// Directory was created or deleted, restart the update process to handle the change
|
|
403
|
-
await this.update();
|
|
404
|
-
return;
|
|
405
|
-
}
|
|
406
|
-
if (event.changes.some(change => change.resource.toString().endsWith('customAgents.yml'))) {
|
|
407
|
-
this.onDidChangeCustomAgentsEmitter.fire();
|
|
408
|
-
}
|
|
409
|
-
// Track changes for batched notification
|
|
410
|
-
const changedFragmentIds = new Set();
|
|
411
|
-
// Handle deleted templates
|
|
412
|
-
for (const deletedFile of event.getDeleted()) {
|
|
413
|
-
const uriString = deletedFile.resource.toString();
|
|
414
|
-
if (this.trackedTemplateURIs.has(uriString)) {
|
|
415
|
-
const removedFragmentId = this.removeCustomizationFromMaps(uriString, this.allCustomizations, this.activeCustomizations, this.trackedTemplateURIs);
|
|
416
|
-
if (removedFragmentId) {
|
|
417
|
-
changedFragmentIds.add(removedFragmentId);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
// Handle updated templates
|
|
422
|
-
for (const updatedFile of event.getUpdated()) {
|
|
423
|
-
const uriString = updatedFile.resource.toString();
|
|
424
|
-
if (this.trackedTemplateURIs.has(uriString)) {
|
|
425
|
-
const fileContent = await this.fileService.read(updatedFile.resource);
|
|
426
|
-
const parsed = this.parseTemplateWithMetadata(fileContent.value);
|
|
427
|
-
const fragmentId = this.removePromptTemplateSuffix(updatedFile.resource.path.name);
|
|
428
|
-
this.addTemplate(this.activeCustomizations, fragmentId, parsed.template, uriString, this.allCustomizations, priority, customizationSource, parsed.metadata);
|
|
429
|
-
changedFragmentIds.add(fragmentId);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
// Handle new templates
|
|
433
|
-
for (const addedFile of event.getAdded()) {
|
|
434
|
-
if (addedFile.resource.parent.toString() === dirURI.toString() &&
|
|
435
|
-
this.isPromptTemplateExtension(addedFile.resource.path.ext)) {
|
|
436
|
-
const uriString = addedFile.resource.toString();
|
|
437
|
-
this.trackedTemplateURIs.add(uriString);
|
|
438
|
-
const fileContent = await this.fileService.read(addedFile.resource);
|
|
439
|
-
const parsed = this.parseTemplateWithMetadata(fileContent.value);
|
|
440
|
-
const fragmentId = this.removePromptTemplateSuffix(addedFile.resource.path.name);
|
|
441
|
-
this.addTemplate(this.activeCustomizations, fragmentId, parsed.template, uriString, this.allCustomizations, priority, customizationSource, parsed.metadata);
|
|
442
|
-
changedFragmentIds.add(fragmentId);
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
const changedFragmentIdsArray = Array.from(changedFragmentIds);
|
|
446
|
-
if (changedFragmentIdsArray.length > 0) {
|
|
447
|
-
this.onDidChangePromptFragmentCustomizationEmitter.fire(changedFragmentIdsArray);
|
|
448
|
-
}
|
|
449
|
-
}));
|
|
450
|
-
}
|
|
451
|
-
/**
|
|
452
|
-
* Checks if the given file extension is registered as a prompt template extension
|
|
453
|
-
* @param extension The file extension including the leading dot (e.g., '.prompttemplate')
|
|
454
|
-
* @returns True if the extension is registered as a prompt template extension
|
|
455
|
-
*/
|
|
456
|
-
isPromptTemplateExtension(extension) {
|
|
457
|
-
return this.templateExtensions.has(extension);
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* Gets the list of additional template directories that are being watched.
|
|
461
|
-
* @returns Array of directory paths
|
|
462
|
-
*/
|
|
463
|
-
getAdditionalTemplateDirectories() {
|
|
464
|
-
return Array.from(this.additionalTemplateDirs);
|
|
465
|
-
}
|
|
466
|
-
/**
|
|
467
|
-
* Gets the list of file extensions that are considered prompt templates.
|
|
468
|
-
* @returns Array of file extensions including the leading dot (e.g., '.prompttemplate')
|
|
469
|
-
*/
|
|
470
|
-
getTemplateFileExtensions() {
|
|
471
|
-
return Array.from(this.templateExtensions);
|
|
472
|
-
}
|
|
473
|
-
/**
|
|
474
|
-
* Gets the list of specific template files that are being watched.
|
|
475
|
-
* @returns Array of file paths
|
|
476
|
-
*/
|
|
477
|
-
getTemplateFiles() {
|
|
478
|
-
return Array.from(this.workspaceTemplateFiles);
|
|
479
|
-
}
|
|
480
|
-
/**
|
|
481
|
-
* Updates multiple configuration properties at once, triggering only a single update process.
|
|
482
|
-
* @param properties An object containing the properties to update
|
|
483
|
-
* @returns Promise that resolves when the update is complete
|
|
484
|
-
*/
|
|
485
|
-
async updateConfiguration(properties) {
|
|
486
|
-
if (properties.directoryPaths !== undefined) {
|
|
487
|
-
this.additionalTemplateDirs.clear();
|
|
488
|
-
for (const path of properties.directoryPaths) {
|
|
489
|
-
this.additionalTemplateDirs.add(path);
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
if (properties.extensions !== undefined) {
|
|
493
|
-
this.templateExtensions.clear();
|
|
494
|
-
for (const ext of properties.extensions) {
|
|
495
|
-
this.templateExtensions.add(ext);
|
|
496
|
-
}
|
|
497
|
-
// Always include the default PROMPT_TEMPLATE_EXTENSION
|
|
498
|
-
this.templateExtensions.add(prompttemplate_contribution_1.PROMPT_TEMPLATE_EXTENSION);
|
|
499
|
-
}
|
|
500
|
-
if (properties.filePaths !== undefined) {
|
|
501
|
-
this.workspaceTemplateFiles.clear();
|
|
502
|
-
for (const path of properties.filePaths) {
|
|
503
|
-
this.workspaceTemplateFiles.add(path);
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
// Only run the update process once, no matter how many properties were changed
|
|
507
|
-
await this.update();
|
|
508
|
-
}
|
|
509
|
-
/**
|
|
510
|
-
* Gets the URI of the templates directory
|
|
511
|
-
* @returns URI of the templates directory
|
|
512
|
-
*/
|
|
513
|
-
async getTemplatesDirectoryURI() {
|
|
514
|
-
const templatesFolder = this.preferences[ai_core_preferences_1.PREFERENCE_NAME_PROMPT_TEMPLATES];
|
|
515
|
-
if (templatesFolder && templatesFolder.trim().length > 0) {
|
|
516
|
-
return core_1.URI.fromFilePath(templatesFolder);
|
|
517
|
-
}
|
|
518
|
-
const theiaConfigDir = await this.envVariablesServer.getConfigDirUri();
|
|
519
|
-
return new core_1.URI(theiaConfigDir).resolve('prompt-templates');
|
|
520
|
-
}
|
|
521
|
-
/**
|
|
522
|
-
* Gets the URI for a specific template file
|
|
523
|
-
* @param fragmentId The fragment ID
|
|
524
|
-
* @returns URI for the template file
|
|
525
|
-
*/
|
|
526
|
-
async getTemplateURI(fragmentId) {
|
|
527
|
-
return (await this.getTemplatesDirectoryURI()).resolve(`${fragmentId}${prompttemplate_contribution_1.PROMPT_TEMPLATE_EXTENSION}`);
|
|
528
|
-
}
|
|
529
|
-
/**
|
|
530
|
-
* Removes the prompt template extension from a filename
|
|
531
|
-
* @param filename The filename with extension
|
|
532
|
-
* @returns The filename without the extension
|
|
533
|
-
*/
|
|
534
|
-
removePromptTemplateSuffix(filename) {
|
|
535
|
-
for (const ext of this.templateExtensions) {
|
|
536
|
-
if (filename.endsWith(ext)) {
|
|
537
|
-
return filename.slice(0, -ext.length);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
return filename;
|
|
541
|
-
}
|
|
542
|
-
// PromptFragmentCustomizationService interface implementation
|
|
543
|
-
isPromptFragmentCustomized(id) {
|
|
544
|
-
return this.activeCustomizations.has(id);
|
|
545
|
-
}
|
|
546
|
-
getActivePromptFragmentCustomization(id) {
|
|
547
|
-
const entry = this.activeCustomizations.get(id);
|
|
548
|
-
if (!entry) {
|
|
549
|
-
return undefined;
|
|
550
|
-
}
|
|
551
|
-
return {
|
|
552
|
-
id: entry.id,
|
|
553
|
-
template: entry.template,
|
|
554
|
-
customizationId: entry.customizationId,
|
|
555
|
-
priority: entry.priority,
|
|
556
|
-
// Pass through command metadata
|
|
557
|
-
isCommand: entry.isCommand,
|
|
558
|
-
commandName: entry.commandName,
|
|
559
|
-
commandDescription: entry.commandDescription,
|
|
560
|
-
commandArgumentHint: entry.commandArgumentHint,
|
|
561
|
-
commandAgents: entry.commandAgents,
|
|
562
|
-
};
|
|
563
|
-
}
|
|
564
|
-
getAllCustomizations(id) {
|
|
565
|
-
const fragments = [];
|
|
566
|
-
// Collect all customizations with matching ID
|
|
567
|
-
this.allCustomizations.forEach(value => {
|
|
568
|
-
if (value.id === id) {
|
|
569
|
-
fragments.push({
|
|
570
|
-
id: value.id,
|
|
571
|
-
template: value.template,
|
|
572
|
-
customizationId: value.customizationId,
|
|
573
|
-
priority: value.priority,
|
|
574
|
-
// Pass through command metadata
|
|
575
|
-
isCommand: value.isCommand,
|
|
576
|
-
commandName: value.commandName,
|
|
577
|
-
commandDescription: value.commandDescription,
|
|
578
|
-
commandArgumentHint: value.commandArgumentHint,
|
|
579
|
-
commandAgents: value.commandAgents,
|
|
580
|
-
});
|
|
581
|
-
}
|
|
582
|
-
});
|
|
583
|
-
// Sort by priority (highest first)
|
|
584
|
-
return fragments.sort((a, b) => b.priority - a.priority);
|
|
585
|
-
}
|
|
586
|
-
getCustomizedPromptFragmentIds() {
|
|
587
|
-
return Array.from(this.activeCustomizations.keys());
|
|
588
|
-
}
|
|
589
|
-
async createPromptFragmentCustomization(id, defaultContent) {
|
|
590
|
-
await this.editTemplate(id, defaultContent);
|
|
591
|
-
}
|
|
592
|
-
async createBuiltInPromptFragmentCustomization(id, defaultContent) {
|
|
593
|
-
await this.createPromptFragmentCustomization(id, defaultContent);
|
|
594
|
-
}
|
|
595
|
-
async editPromptFragmentCustomization(id, customizationId) {
|
|
596
|
-
// Find the customization with the given customization ID
|
|
597
|
-
const customization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.customizationId === customizationId);
|
|
598
|
-
if (customization) {
|
|
599
|
-
const uri = new core_1.URI(customization.sourceUri);
|
|
600
|
-
const openHandler = await this.openerService.getOpener(uri);
|
|
601
|
-
openHandler.open(uri);
|
|
602
|
-
}
|
|
603
|
-
else {
|
|
604
|
-
// Fall back to editing by fragment ID if customization ID not found
|
|
605
|
-
await this.editTemplate(id);
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
/**
|
|
609
|
-
* Edits a template by opening it in the editor, creating it if it doesn't exist
|
|
610
|
-
* @param id The fragment ID
|
|
611
|
-
* @param defaultContent Optional default content for new templates
|
|
612
|
-
*/
|
|
613
|
-
async editTemplate(id, defaultContent) {
|
|
614
|
-
const editorUri = await this.getTemplateURI(id);
|
|
615
|
-
if (!(await this.fileService.exists(editorUri))) {
|
|
616
|
-
await this.fileService.createFile(editorUri, buffer_1.BinaryBuffer.fromString(defaultContent !== null && defaultContent !== void 0 ? defaultContent : ''));
|
|
617
|
-
}
|
|
618
|
-
const openHandler = await this.openerService.getOpener(editorUri);
|
|
619
|
-
openHandler.open(editorUri);
|
|
620
|
-
}
|
|
621
|
-
async removePromptFragmentCustomization(id, customizationId) {
|
|
622
|
-
// Find the customization with the given customization ID
|
|
623
|
-
const customization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.customizationId === customizationId);
|
|
624
|
-
if (customization) {
|
|
625
|
-
const sourceUri = customization.sourceUri;
|
|
626
|
-
// Delete the file if it exists
|
|
627
|
-
const uri = new core_1.URI(sourceUri);
|
|
628
|
-
if (await this.fileService.exists(uri)) {
|
|
629
|
-
await this.fileService.delete(uri);
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
async removeAllPromptFragmentCustomizations(id) {
|
|
634
|
-
// Get all customizations for this fragment ID
|
|
635
|
-
const customizations = this.getAllCustomizations(id);
|
|
636
|
-
if (customizations.length === 0) {
|
|
637
|
-
return; // Nothing to reset
|
|
638
|
-
}
|
|
639
|
-
// Find and delete all customization files
|
|
640
|
-
for (const customization of customizations) {
|
|
641
|
-
const fragment = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.customizationId === customization.customizationId);
|
|
642
|
-
if (fragment) {
|
|
643
|
-
const sourceUri = fragment.sourceUri;
|
|
644
|
-
// Delete the file if it exists
|
|
645
|
-
const uri = new core_1.URI(sourceUri);
|
|
646
|
-
if (await this.fileService.exists(uri)) {
|
|
647
|
-
await this.fileService.delete(uri);
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
async resetToCustomization(id, customizationId) {
|
|
653
|
-
const customization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.customizationId === customizationId);
|
|
654
|
-
if (customization) {
|
|
655
|
-
// Get all customizations for this fragment ID
|
|
656
|
-
const customizations = this.getAllCustomizations(id);
|
|
657
|
-
if (customizations.length === 0) {
|
|
658
|
-
return; // Nothing to reset
|
|
659
|
-
}
|
|
660
|
-
// Find the target customization
|
|
661
|
-
const targetCustomization = customizations.find(c => c.customizationId === customizationId);
|
|
662
|
-
if (!targetCustomization) {
|
|
663
|
-
return; // Target customization not found
|
|
664
|
-
}
|
|
665
|
-
// Find and delete all higher-priority customization files
|
|
666
|
-
for (const cust of customizations) {
|
|
667
|
-
if (cust.priority > targetCustomization.priority) {
|
|
668
|
-
const fragmentToDelete = Array.from(this.allCustomizations.values()).find(t => t.id === cust.id && t.customizationId === cust.customizationId);
|
|
669
|
-
if (fragmentToDelete) {
|
|
670
|
-
const sourceUri = fragmentToDelete.sourceUri;
|
|
671
|
-
// Delete the file if it exists
|
|
672
|
-
const uri = new core_1.URI(sourceUri);
|
|
673
|
-
if (await this.fileService.exists(uri)) {
|
|
674
|
-
await this.fileService.delete(uri);
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
async getPromptFragmentCustomizationDescription(id, customizationId) {
|
|
682
|
-
// Find the customization with the given customization ID
|
|
683
|
-
const customization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.customizationId === customizationId);
|
|
684
|
-
if (customization) {
|
|
685
|
-
return customization.sourceUri;
|
|
686
|
-
}
|
|
687
|
-
return undefined;
|
|
688
|
-
}
|
|
689
|
-
async getPromptFragmentCustomizationType(id, customizationId) {
|
|
690
|
-
// Find the customization with the given customization ID
|
|
691
|
-
const customization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.customizationId === customizationId);
|
|
692
|
-
if (customization) {
|
|
693
|
-
return getCustomizationSourceString(customization.origin);
|
|
694
|
-
}
|
|
695
|
-
return undefined;
|
|
696
|
-
}
|
|
697
|
-
async editBuiltIn(id, defaultContent = '') {
|
|
698
|
-
// Find an existing built-in customization (those with priority 1)
|
|
699
|
-
const builtInCustomization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.priority === 1);
|
|
700
|
-
if (builtInCustomization) {
|
|
701
|
-
// Edit the existing built-in customization
|
|
702
|
-
const uri = new core_1.URI(builtInCustomization.sourceUri);
|
|
703
|
-
const openHandler = await this.openerService.getOpener(uri);
|
|
704
|
-
openHandler.open(uri);
|
|
705
|
-
}
|
|
706
|
-
else {
|
|
707
|
-
// Create a new built-in customization
|
|
708
|
-
// Get the template URI in the main templates directory (priority 1)
|
|
709
|
-
const templateUri = await this.getTemplateURI(id);
|
|
710
|
-
// If template doesn't exist, create it with default content
|
|
711
|
-
if (!(await this.fileService.exists(templateUri))) {
|
|
712
|
-
await this.fileService.createFile(templateUri, buffer_1.BinaryBuffer.fromString(defaultContent));
|
|
713
|
-
}
|
|
714
|
-
// Open the template in the editor
|
|
715
|
-
const openHandler = await this.openerService.getOpener(templateUri);
|
|
716
|
-
openHandler.open(templateUri);
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
async resetBuiltInCustomization(id) {
|
|
720
|
-
// Find a built-in customization (those with priority 1)
|
|
721
|
-
const builtInCustomization = Array.from(this.allCustomizations.values()).find(t => t.id === id && t.priority === 1);
|
|
722
|
-
if (!builtInCustomization) {
|
|
723
|
-
return; // No built-in customization found
|
|
724
|
-
}
|
|
725
|
-
const sourceUri = builtInCustomization.sourceUri;
|
|
726
|
-
// Delete the file if it exists
|
|
727
|
-
const uri = new core_1.URI(sourceUri);
|
|
728
|
-
if (await this.fileService.exists(uri)) {
|
|
729
|
-
await this.fileService.delete(uri);
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
async editBuiltInPromptFragmentCustomization(id, defaultContent) {
|
|
733
|
-
return this.editBuiltIn(id, defaultContent);
|
|
734
|
-
}
|
|
735
|
-
/**
|
|
736
|
-
* Gets the fragment ID from a URI
|
|
737
|
-
* @param uri URI to check
|
|
738
|
-
* @returns Fragment ID or undefined if not found
|
|
739
|
-
*/
|
|
740
|
-
getFragmentIDFromURI(uri) {
|
|
741
|
-
const id = this.removePromptTemplateSuffix(uri.path.name);
|
|
742
|
-
if (this.activeCustomizations.has(id)) {
|
|
743
|
-
return id;
|
|
744
|
-
}
|
|
745
|
-
return undefined;
|
|
746
|
-
}
|
|
747
|
-
/**
|
|
748
|
-
* Implementation of the generic getPromptFragmentIDFromResource method in the interface
|
|
749
|
-
* Accepts any resource identifier but only processes URIs
|
|
750
|
-
* @param resourceId Resource to check
|
|
751
|
-
* @returns Fragment ID or undefined if not found
|
|
752
|
-
*/
|
|
753
|
-
getPromptFragmentIDFromResource(resourceId) {
|
|
754
|
-
// Check if the resource is a URI
|
|
755
|
-
if (resourceId instanceof core_1.URI) {
|
|
756
|
-
return this.getFragmentIDFromURI(resourceId);
|
|
757
|
-
}
|
|
758
|
-
return undefined;
|
|
759
|
-
}
|
|
760
|
-
async getCustomAgents() {
|
|
761
|
-
const agentsById = new Map();
|
|
762
|
-
// First, process additional (workspace) template directories to give them precedence
|
|
763
|
-
for (const dirPath of this.additionalTemplateDirs) {
|
|
764
|
-
const dirURI = core_1.URI.fromFilePath(dirPath);
|
|
765
|
-
await this.loadCustomAgentsFromDirectory(dirURI, agentsById);
|
|
766
|
-
}
|
|
767
|
-
// Then process global templates directory (only adding agents that don't conflict)
|
|
768
|
-
const globalTemplatesDir = await this.getTemplatesDirectoryURI();
|
|
769
|
-
await this.loadCustomAgentsFromDirectory(globalTemplatesDir, agentsById);
|
|
770
|
-
// Return the merged list of agents
|
|
771
|
-
return Array.from(agentsById.values());
|
|
772
|
-
}
|
|
773
|
-
/**
|
|
774
|
-
* Load custom agents from a specific directory
|
|
775
|
-
* @param directoryURI The URI of the directory to load from
|
|
776
|
-
* @param agentsById Map to store the loaded agents by ID
|
|
777
|
-
*/
|
|
778
|
-
async loadCustomAgentsFromDirectory(directoryURI, agentsById) {
|
|
779
|
-
const customAgentYamlUri = directoryURI.resolve('customAgents.yml');
|
|
780
|
-
const yamlExists = await this.fileService.exists(customAgentYamlUri);
|
|
781
|
-
if (!yamlExists) {
|
|
782
|
-
return;
|
|
783
|
-
}
|
|
784
|
-
try {
|
|
785
|
-
const fileContent = await this.fileService.read(customAgentYamlUri, { encoding: 'utf-8' });
|
|
786
|
-
const doc = (0, js_yaml_1.load)(fileContent.value);
|
|
787
|
-
if (!Array.isArray(doc) || !doc.every(entry => common_1.CustomAgentDescription.is(entry))) {
|
|
788
|
-
console.debug(`Invalid customAgents.yml file content in ${directoryURI.toString()}`);
|
|
789
|
-
return;
|
|
790
|
-
}
|
|
791
|
-
const readAgents = doc;
|
|
792
|
-
// Add agents to the map if they don't already exist
|
|
793
|
-
for (const agent of readAgents) {
|
|
794
|
-
if (!agentsById.has(agent.id)) {
|
|
795
|
-
agentsById.set(agent.id, agent);
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
catch (e) {
|
|
800
|
-
console.debug(`Error loading customAgents.yml from ${directoryURI.toString()}: ${e.message}`, e);
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
/**
|
|
804
|
-
* Returns all locations of existing customAgents.yml files and potential locations where
|
|
805
|
-
* new customAgents.yml files could be created.
|
|
806
|
-
*
|
|
807
|
-
* @returns An array of objects containing the URI and whether the file exists
|
|
808
|
-
*/
|
|
809
|
-
async getCustomAgentsLocations() {
|
|
810
|
-
const locations = [];
|
|
811
|
-
// Check global templates directory
|
|
812
|
-
const globalTemplatesDir = await this.getTemplatesDirectoryURI();
|
|
813
|
-
const globalAgentsUri = globalTemplatesDir.resolve('customAgents.yml');
|
|
814
|
-
const globalExists = await this.fileService.exists(globalAgentsUri);
|
|
815
|
-
locations.push({ uri: globalAgentsUri, exists: globalExists });
|
|
816
|
-
// Check additional (workspace) template directories
|
|
817
|
-
for (const dirPath of this.additionalTemplateDirs) {
|
|
818
|
-
const dirURI = core_1.URI.fromFilePath(dirPath);
|
|
819
|
-
const agentsUri = dirURI.resolve('customAgents.yml');
|
|
820
|
-
const exists = await this.fileService.exists(agentsUri);
|
|
821
|
-
locations.push({ uri: agentsUri, exists: exists });
|
|
822
|
-
}
|
|
823
|
-
return locations;
|
|
824
|
-
}
|
|
825
|
-
/**
|
|
826
|
-
* Opens an existing customAgents.yml file at the given URI, or creates a new one if it doesn't exist.
|
|
827
|
-
*
|
|
828
|
-
* @param uri The URI of the customAgents.yml file to open or create
|
|
829
|
-
*/
|
|
830
|
-
async openCustomAgentYaml(uri) {
|
|
831
|
-
const content = (0, js_yaml_1.dump)([newCustomAgentEntry]);
|
|
832
|
-
if (!await this.fileService.exists(uri)) {
|
|
833
|
-
await this.fileService.createFile(uri, buffer_1.BinaryBuffer.fromString(content));
|
|
834
|
-
}
|
|
835
|
-
else {
|
|
836
|
-
const fileContent = (await this.fileService.readFile(uri)).value;
|
|
837
|
-
await this.fileService.writeFile(uri, buffer_1.BinaryBuffer.concat([fileContent, buffer_1.BinaryBuffer.fromString(content)]));
|
|
838
|
-
}
|
|
839
|
-
const openHandler = await this.openerService.getOpener(uri);
|
|
840
|
-
openHandler.open(uri);
|
|
841
|
-
}
|
|
842
|
-
};
|
|
843
|
-
exports.DefaultPromptFragmentCustomizationService = DefaultPromptFragmentCustomizationService;
|
|
844
|
-
tslib_1.__decorate([
|
|
845
|
-
(0, inversify_1.inject)(env_variables_1.EnvVariablesServer),
|
|
846
|
-
tslib_1.__metadata("design:type", Object)
|
|
847
|
-
], DefaultPromptFragmentCustomizationService.prototype, "envVariablesServer", void 0);
|
|
848
|
-
tslib_1.__decorate([
|
|
849
|
-
(0, inversify_1.inject)(ai_core_preferences_1.AICorePreferences),
|
|
850
|
-
tslib_1.__metadata("design:type", Object)
|
|
851
|
-
], DefaultPromptFragmentCustomizationService.prototype, "preferences", void 0);
|
|
852
|
-
tslib_1.__decorate([
|
|
853
|
-
(0, inversify_1.inject)(file_service_1.FileService),
|
|
854
|
-
tslib_1.__metadata("design:type", file_service_1.FileService)
|
|
855
|
-
], DefaultPromptFragmentCustomizationService.prototype, "fileService", void 0);
|
|
856
|
-
tslib_1.__decorate([
|
|
857
|
-
(0, inversify_1.inject)(browser_1.OpenerService),
|
|
858
|
-
tslib_1.__metadata("design:type", Object)
|
|
859
|
-
], DefaultPromptFragmentCustomizationService.prototype, "openerService", void 0);
|
|
860
|
-
tslib_1.__decorate([
|
|
861
|
-
(0, inversify_1.postConstruct)(),
|
|
862
|
-
tslib_1.__metadata("design:type", Function),
|
|
863
|
-
tslib_1.__metadata("design:paramtypes", []),
|
|
864
|
-
tslib_1.__metadata("design:returntype", void 0)
|
|
865
|
-
], DefaultPromptFragmentCustomizationService.prototype, "init", null);
|
|
866
|
-
exports.DefaultPromptFragmentCustomizationService = DefaultPromptFragmentCustomizationService = tslib_1.__decorate([
|
|
867
|
-
(0, inversify_1.injectable)()
|
|
868
|
-
], DefaultPromptFragmentCustomizationService);
|
|
869
|
-
//# sourceMappingURL=frontend-prompt-customization-service.js.map
|