@theia/ai-core 1.55.0-next.4 → 1.55.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-configuration/agent-configuration-widget.d.ts +1 -0
- package/lib/browser/ai-configuration/agent-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/agent-configuration-widget.js +7 -1
- package/lib/browser/ai-configuration/agent-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/template-settings-renderer.js +1 -1
- package/lib/browser/ai-configuration/template-settings-renderer.js.map +1 -1
- package/lib/browser/ai-core-frontend-application-contribution.d.ts +3 -1
- package/lib/browser/ai-core-frontend-application-contribution.d.ts.map +1 -1
- package/lib/browser/ai-core-frontend-application-contribution.js +6 -6
- package/lib/browser/ai-core-frontend-application-contribution.js.map +1 -1
- package/lib/browser/frontend-prompt-customization-service.d.ts +6 -5
- package/lib/browser/frontend-prompt-customization-service.d.ts.map +1 -1
- package/lib/browser/frontend-prompt-customization-service.js +72 -35
- package/lib/browser/frontend-prompt-customization-service.js.map +1 -1
- package/lib/browser/prompttemplate-contribution.d.ts +1 -0
- package/lib/browser/prompttemplate-contribution.d.ts.map +1 -1
- package/lib/browser/prompttemplate-contribution.js +3 -2
- package/lib/browser/prompttemplate-contribution.js.map +1 -1
- package/lib/common/agent-service.d.ts +21 -3
- package/lib/common/agent-service.d.ts.map +1 -1
- package/lib/common/agent-service.js +17 -13
- package/lib/common/agent-service.js.map +1 -1
- package/lib/common/communication-recording-service.d.ts +3 -0
- package/lib/common/communication-recording-service.d.ts.map +1 -1
- package/lib/common/language-model-util.d.ts +11 -0
- package/lib/common/language-model-util.d.ts.map +1 -1
- package/lib/common/language-model-util.js +19 -2
- package/lib/common/language-model-util.js.map +1 -1
- package/lib/common/prompt-service.d.ts +33 -3
- package/lib/common/prompt-service.d.ts.map +1 -1
- package/lib/common/prompt-service.js +23 -1
- package/lib/common/prompt-service.js.map +1 -1
- package/package.json +12 -10
- package/src/browser/ai-configuration/agent-configuration-widget.tsx +8 -0
- package/src/browser/ai-configuration/template-settings-renderer.tsx +1 -1
- package/src/browser/ai-core-frontend-application-contribution.ts +7 -8
- package/src/browser/frontend-prompt-customization-service.ts +73 -35
- package/src/browser/prompttemplate-contribution.ts +3 -1
- package/src/browser/style/index.css +5 -0
- package/src/common/agent-service.ts +42 -13
- package/src/common/communication-recording-service.ts +5 -0
- package/src/common/language-model-util.ts +18 -1
- package/src/common/prompt-service.ts +51 -3
|
@@ -17,13 +17,22 @@
|
|
|
17
17
|
import { DisposableCollection, URI, Event, Emitter } from '@theia/core';
|
|
18
18
|
import { OpenerService } from '@theia/core/lib/browser';
|
|
19
19
|
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
20
|
-
import { PromptCustomizationService,
|
|
20
|
+
import { PromptCustomizationService, CustomAgentDescription } from '../common';
|
|
21
21
|
import { BinaryBuffer } from '@theia/core/lib/common/buffer';
|
|
22
22
|
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
|
23
23
|
import { FileChangesEvent } from '@theia/filesystem/lib/common/files';
|
|
24
24
|
import { AICorePreferences, PREFERENCE_NAME_PROMPT_TEMPLATES } from './ai-core-preferences';
|
|
25
|
-
import { AgentService } from '../common/agent-service';
|
|
26
25
|
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
|
|
26
|
+
import { load, dump } from 'js-yaml';
|
|
27
|
+
import { PROMPT_TEMPLATE_EXTENSION } from './prompttemplate-contribution';
|
|
28
|
+
|
|
29
|
+
const templateEntry = {
|
|
30
|
+
id: 'my_agent',
|
|
31
|
+
name: 'My Agent',
|
|
32
|
+
description: 'This is an example agent. Please adapt the properties to fit your needs.',
|
|
33
|
+
prompt: 'You are an example agent. Be nice and helpful to the user.',
|
|
34
|
+
defaultLLM: 'openai/gpt-4o'
|
|
35
|
+
};
|
|
27
36
|
|
|
28
37
|
@injectable()
|
|
29
38
|
export class FrontendPromptCustomizationServiceImpl implements PromptCustomizationService {
|
|
@@ -40,9 +49,6 @@ export class FrontendPromptCustomizationServiceImpl implements PromptCustomizati
|
|
|
40
49
|
@inject(OpenerService)
|
|
41
50
|
protected readonly openerService: OpenerService;
|
|
42
51
|
|
|
43
|
-
@inject(AgentService)
|
|
44
|
-
protected readonly agentService: AgentService;
|
|
45
|
-
|
|
46
52
|
protected readonly trackedTemplateURIs = new Set<string>();
|
|
47
53
|
protected templates = new Map<string, string>();
|
|
48
54
|
|
|
@@ -51,6 +57,9 @@ export class FrontendPromptCustomizationServiceImpl implements PromptCustomizati
|
|
|
51
57
|
private readonly onDidChangePromptEmitter = new Emitter<string>();
|
|
52
58
|
readonly onDidChangePrompt: Event<string> = this.onDidChangePromptEmitter.event;
|
|
53
59
|
|
|
60
|
+
private readonly onDidChangeCustomAgentsEmitter = new Emitter<void>();
|
|
61
|
+
readonly onDidChangeCustomAgents = this.onDidChangeCustomAgentsEmitter.event;
|
|
62
|
+
|
|
54
63
|
@postConstruct()
|
|
55
64
|
protected init(): void {
|
|
56
65
|
this.preferences.onPreferenceChanged(event => {
|
|
@@ -72,6 +81,9 @@ export class FrontendPromptCustomizationServiceImpl implements PromptCustomizati
|
|
|
72
81
|
|
|
73
82
|
this.toDispose.push(this.fileService.watch(templateURI, { recursive: true, excludes: [] }));
|
|
74
83
|
this.toDispose.push(this.fileService.onDidFilesChange(async (event: FileChangesEvent) => {
|
|
84
|
+
if (event.changes.some(change => change.resource.toString().endsWith('customAgents.yml'))) {
|
|
85
|
+
this.onDidChangeCustomAgentsEmitter.fire();
|
|
86
|
+
}
|
|
75
87
|
// check deleted templates
|
|
76
88
|
for (const deletedFile of event.getDeleted()) {
|
|
77
89
|
if (this.trackedTemplateURIs.has(deletedFile.resource.toString())) {
|
|
@@ -84,25 +96,26 @@ export class FrontendPromptCustomizationServiceImpl implements PromptCustomizati
|
|
|
84
96
|
// check updated templates
|
|
85
97
|
for (const updatedFile of event.getUpdated()) {
|
|
86
98
|
if (this.trackedTemplateURIs.has(updatedFile.resource.toString())) {
|
|
87
|
-
const
|
|
99
|
+
const fileContent = await this.fileService.read(updatedFile.resource);
|
|
88
100
|
const templateId = this.removePromptTemplateSuffix(updatedFile.resource.path.name);
|
|
89
|
-
_templates.set(templateId,
|
|
101
|
+
_templates.set(templateId, fileContent.value);
|
|
90
102
|
this.onDidChangePromptEmitter.fire(templateId);
|
|
91
103
|
}
|
|
92
104
|
}
|
|
93
105
|
// check new templates
|
|
94
106
|
for (const addedFile of event.getAdded()) {
|
|
95
|
-
if (addedFile.resource.parent.toString() === templateURI.toString() && addedFile.resource.path.ext ===
|
|
107
|
+
if (addedFile.resource.parent.toString() === templateURI.toString() && addedFile.resource.path.ext === PROMPT_TEMPLATE_EXTENSION) {
|
|
96
108
|
this.trackedTemplateURIs.add(addedFile.resource.toString());
|
|
97
|
-
const
|
|
109
|
+
const fileContent = await this.fileService.read(addedFile.resource);
|
|
98
110
|
const templateId = this.removePromptTemplateSuffix(addedFile.resource.path.name);
|
|
99
|
-
_templates.set(templateId,
|
|
111
|
+
_templates.set(templateId, fileContent.value);
|
|
100
112
|
this.onDidChangePromptEmitter.fire(templateId);
|
|
101
113
|
}
|
|
102
114
|
}
|
|
103
115
|
|
|
104
116
|
}));
|
|
105
117
|
|
|
118
|
+
this.onDidChangeCustomAgentsEmitter.fire();
|
|
106
119
|
const stat = await this.fileService.resolve(templateURI);
|
|
107
120
|
if (stat.children === undefined) {
|
|
108
121
|
return;
|
|
@@ -113,11 +126,11 @@ export class FrontendPromptCustomizationServiceImpl implements PromptCustomizati
|
|
|
113
126
|
continue;
|
|
114
127
|
}
|
|
115
128
|
const fileURI = file.resource;
|
|
116
|
-
if (fileURI.path.ext ===
|
|
129
|
+
if (fileURI.path.ext === PROMPT_TEMPLATE_EXTENSION) {
|
|
117
130
|
this.trackedTemplateURIs.add(fileURI.toString());
|
|
118
|
-
const
|
|
131
|
+
const fileContent = await this.fileService.read(fileURI);
|
|
119
132
|
const templateId = this.removePromptTemplateSuffix(file.name);
|
|
120
|
-
_templates.set(templateId,
|
|
133
|
+
_templates.set(templateId, fileContent.value);
|
|
121
134
|
this.onDidChangePromptEmitter.fire(templateId);
|
|
122
135
|
}
|
|
123
136
|
}
|
|
@@ -133,11 +146,11 @@ export class FrontendPromptCustomizationServiceImpl implements PromptCustomizati
|
|
|
133
146
|
}
|
|
134
147
|
|
|
135
148
|
protected async getTemplateURI(templateId: string): Promise<URI> {
|
|
136
|
-
return (await this.getTemplatesDirectoryURI()).resolve(`${templateId}
|
|
149
|
+
return (await this.getTemplatesDirectoryURI()).resolve(`${templateId}${PROMPT_TEMPLATE_EXTENSION}`);
|
|
137
150
|
}
|
|
138
151
|
|
|
139
152
|
protected removePromptTemplateSuffix(filename: string): string {
|
|
140
|
-
const suffix =
|
|
153
|
+
const suffix = PROMPT_TEMPLATE_EXTENSION;
|
|
141
154
|
if (filename.endsWith(suffix)) {
|
|
142
155
|
return filename.slice(0, -suffix.length);
|
|
143
156
|
}
|
|
@@ -152,17 +165,10 @@ export class FrontendPromptCustomizationServiceImpl implements PromptCustomizati
|
|
|
152
165
|
return this.templates.get(id);
|
|
153
166
|
}
|
|
154
167
|
|
|
155
|
-
async editTemplate(id: string,
|
|
156
|
-
const template = this.getOriginalTemplate(id);
|
|
157
|
-
if (template === undefined) {
|
|
158
|
-
throw new Error(`Unable to edit template ${id}: template not found.`);
|
|
159
|
-
}
|
|
168
|
+
async editTemplate(id: string, defaultContent?: string): Promise<void> {
|
|
160
169
|
const editorUri = await this.getTemplateURI(id);
|
|
161
170
|
if (! await this.fileService.exists(editorUri)) {
|
|
162
|
-
await this.fileService.createFile(editorUri, BinaryBuffer.fromString(
|
|
163
|
-
} else if (content) {
|
|
164
|
-
// Write content to the file before opening it
|
|
165
|
-
await this.fileService.writeFile(editorUri, BinaryBuffer.fromString(content));
|
|
171
|
+
await this.fileService.createFile(editorUri, BinaryBuffer.fromString(defaultContent ?? ''));
|
|
166
172
|
}
|
|
167
173
|
const openHandler = await this.openerService.getOpener(editorUri);
|
|
168
174
|
openHandler.open(editorUri);
|
|
@@ -175,17 +181,6 @@ export class FrontendPromptCustomizationServiceImpl implements PromptCustomizati
|
|
|
175
181
|
}
|
|
176
182
|
}
|
|
177
183
|
|
|
178
|
-
getOriginalTemplate(id: string): PromptTemplate | undefined {
|
|
179
|
-
for (const agent of this.agentService.getAllAgents()) {
|
|
180
|
-
for (const template of agent.promptTemplates) {
|
|
181
|
-
if (template.id === id) {
|
|
182
|
-
return template;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
return undefined;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
184
|
getTemplateIDFromURI(uri: URI): string | undefined {
|
|
190
185
|
const id = this.removePromptTemplateSuffix(uri.path.name);
|
|
191
186
|
if (this.templates.has(id)) {
|
|
@@ -194,4 +189,47 @@ export class FrontendPromptCustomizationServiceImpl implements PromptCustomizati
|
|
|
194
189
|
return undefined;
|
|
195
190
|
}
|
|
196
191
|
|
|
192
|
+
async getCustomAgents(): Promise<CustomAgentDescription[]> {
|
|
193
|
+
const customAgentYamlUri = (await this.getTemplatesDirectoryURI()).resolve('customAgents.yml');
|
|
194
|
+
const yamlExists = await this.fileService.exists(customAgentYamlUri);
|
|
195
|
+
if (!yamlExists) {
|
|
196
|
+
return [];
|
|
197
|
+
}
|
|
198
|
+
const fileContent = await this.fileService.read(customAgentYamlUri, { encoding: 'utf-8' });
|
|
199
|
+
try {
|
|
200
|
+
const doc = load(fileContent.value);
|
|
201
|
+
if (!Array.isArray(doc) || !doc.every(entry => CustomAgentDescription.is(entry))) {
|
|
202
|
+
console.debug('Invalid customAgents.yml file content');
|
|
203
|
+
return [];
|
|
204
|
+
}
|
|
205
|
+
const readAgents = doc as CustomAgentDescription[];
|
|
206
|
+
// make sure all agents are unique (id and name)
|
|
207
|
+
const uniqueAgentIds = new Set<string>();
|
|
208
|
+
const uniqueAgents: CustomAgentDescription[] = [];
|
|
209
|
+
readAgents.forEach(agent => {
|
|
210
|
+
if (uniqueAgentIds.has(agent.id)) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
uniqueAgentIds.add(agent.id);
|
|
214
|
+
uniqueAgents.push(agent);
|
|
215
|
+
});
|
|
216
|
+
return uniqueAgents;
|
|
217
|
+
} catch (e) {
|
|
218
|
+
console.debug(e.message, e);
|
|
219
|
+
return [];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async openCustomAgentYaml(): Promise<void> {
|
|
224
|
+
const customAgentYamlUri = (await this.getTemplatesDirectoryURI()).resolve('customAgents.yml');
|
|
225
|
+
const content = dump([templateEntry]);
|
|
226
|
+
if (! await this.fileService.exists(customAgentYamlUri)) {
|
|
227
|
+
await this.fileService.createFile(customAgentYamlUri, BinaryBuffer.fromString(content));
|
|
228
|
+
} else {
|
|
229
|
+
const fileContent = (await this.fileService.readFile(customAgentYamlUri)).value;
|
|
230
|
+
await this.fileService.writeFile(customAgentYamlUri, BinaryBuffer.concat([fileContent, BinaryBuffer.fromString(content)]));
|
|
231
|
+
}
|
|
232
|
+
const openHandler = await this.openerService.getOpener(customAgentYamlUri);
|
|
233
|
+
openHandler.open(customAgentYamlUri);
|
|
234
|
+
}
|
|
197
235
|
}
|
|
@@ -28,6 +28,8 @@ import { ProviderResult } from '@theia/monaco-editor-core/esm/vs/editor/common/l
|
|
|
28
28
|
const PROMPT_TEMPLATE_LANGUAGE_ID = 'theia-ai-prompt-template';
|
|
29
29
|
const PROMPT_TEMPLATE_TEXTMATE_SCOPE = 'source.prompttemplate';
|
|
30
30
|
|
|
31
|
+
export const PROMPT_TEMPLATE_EXTENSION = '.prompttemplate';
|
|
32
|
+
|
|
31
33
|
export const DISCARD_PROMPT_TEMPLATE_CUSTOMIZATIONS: Command = {
|
|
32
34
|
id: 'theia-ai-prompt-template:discard',
|
|
33
35
|
iconClass: codicon('discard'),
|
|
@@ -81,7 +83,7 @@ export class PromptTemplateContribution implements LanguageGrammarDefinitionCont
|
|
|
81
83
|
'Theia AI Prompt Templates'
|
|
82
84
|
],
|
|
83
85
|
'extensions': [
|
|
84
|
-
|
|
86
|
+
PROMPT_TEMPLATE_EXTENSION,
|
|
85
87
|
],
|
|
86
88
|
'filenames': []
|
|
87
89
|
});
|
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
//
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
|
-
import { inject, injectable,
|
|
17
|
-
import {
|
|
16
|
+
import { inject, injectable, optional, postConstruct } from '@theia/core/shared/inversify';
|
|
17
|
+
import { Emitter, Event } from '@theia/core';
|
|
18
18
|
import { Agent } from './agent';
|
|
19
19
|
import { AISettingsService } from './settings-service';
|
|
20
|
+
import { PromptService } from './prompt-service';
|
|
20
21
|
|
|
21
22
|
export const AgentService = Symbol('AgentService');
|
|
22
23
|
|
|
@@ -48,21 +49,42 @@ export interface AgentService {
|
|
|
48
49
|
* @return true if the agent is enabled, false otherwise.
|
|
49
50
|
*/
|
|
50
51
|
isEnabled(agentId: string): boolean;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Allows to register an agent programmatically.
|
|
55
|
+
* @param agent the agent to register
|
|
56
|
+
*/
|
|
57
|
+
registerAgent(agent: Agent): void;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Allows to unregister an agent programmatically.
|
|
61
|
+
* @param agentId the agent id to unregister
|
|
62
|
+
*/
|
|
63
|
+
unregisterAgent(agentId: string): void;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Emitted when the list of agents changes.
|
|
67
|
+
* This can be used to update the UI when agents are added or removed.
|
|
68
|
+
*/
|
|
69
|
+
onDidChangeAgents: Event<void>;
|
|
51
70
|
}
|
|
52
71
|
|
|
53
72
|
@injectable()
|
|
54
73
|
export class AgentServiceImpl implements AgentService {
|
|
55
74
|
|
|
56
|
-
@inject(ContributionProvider) @named(Agent)
|
|
57
|
-
protected readonly agentsProvider: ContributionProvider<Agent>;
|
|
58
|
-
|
|
59
75
|
@inject(AISettingsService) @optional()
|
|
60
76
|
protected readonly aiSettingsService: AISettingsService | undefined;
|
|
61
77
|
|
|
78
|
+
@inject(PromptService)
|
|
79
|
+
protected readonly promptService: PromptService;
|
|
80
|
+
|
|
62
81
|
protected disabledAgents = new Set<string>();
|
|
63
82
|
|
|
64
83
|
protected _agents: Agent[] = [];
|
|
65
84
|
|
|
85
|
+
private readonly onDidChangeAgentsEmitter = new Emitter<void>();
|
|
86
|
+
readonly onDidChangeAgents = this.onDidChangeAgentsEmitter.event;
|
|
87
|
+
|
|
66
88
|
@postConstruct()
|
|
67
89
|
protected init(): void {
|
|
68
90
|
this.aiSettingsService?.getSettings().then(settings => {
|
|
@@ -74,22 +96,29 @@ export class AgentServiceImpl implements AgentService {
|
|
|
74
96
|
});
|
|
75
97
|
}
|
|
76
98
|
|
|
77
|
-
private get agents(): Agent[] {
|
|
78
|
-
// We can't collect the contributions at @postConstruct because this will lead to a circular dependency
|
|
79
|
-
// with agents reusing the chat agent service (e.g. orchestrator) which in turn injects the agent service
|
|
80
|
-
return [...this.agentsProvider.getContributions(), ...this._agents];
|
|
81
|
-
}
|
|
82
|
-
|
|
83
99
|
registerAgent(agent: Agent): void {
|
|
84
100
|
this._agents.push(agent);
|
|
101
|
+
agent.promptTemplates.forEach(
|
|
102
|
+
template => this.promptService.storePrompt(template.id, template.template)
|
|
103
|
+
);
|
|
104
|
+
this.onDidChangeAgentsEmitter.fire();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
unregisterAgent(agentId: string): void {
|
|
108
|
+
const agent = this._agents.find(a => a.id === agentId);
|
|
109
|
+
this._agents = this._agents.filter(a => a.id !== agentId);
|
|
110
|
+
this.onDidChangeAgentsEmitter.fire();
|
|
111
|
+
agent?.promptTemplates.forEach(
|
|
112
|
+
template => this.promptService.removePrompt(template.id)
|
|
113
|
+
);
|
|
85
114
|
}
|
|
86
115
|
|
|
87
116
|
getAgents(): Agent[] {
|
|
88
|
-
return this.
|
|
117
|
+
return this._agents.filter(agent => this.isEnabled(agent.id));
|
|
89
118
|
}
|
|
90
119
|
|
|
91
120
|
getAllAgents(): Agent[] {
|
|
92
|
-
return this.
|
|
121
|
+
return this._agents;
|
|
93
122
|
}
|
|
94
123
|
|
|
95
124
|
enableAgent(agentId: string): void {
|
|
@@ -41,4 +41,9 @@ export interface CommunicationRecordingService {
|
|
|
41
41
|
readonly onDidRecordResponse: Event<CommunicationResponseEntry>;
|
|
42
42
|
|
|
43
43
|
getHistory(agentId: string): CommunicationHistory;
|
|
44
|
+
|
|
45
|
+
getSessionHistory(sessionId: string): CommunicationHistory;
|
|
46
|
+
|
|
47
|
+
clearHistory(): void;
|
|
48
|
+
readonly onStructuralChange: Event<void>;
|
|
44
49
|
}
|
|
@@ -14,8 +14,18 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { isLanguageModelStreamResponse, isLanguageModelTextResponse, LanguageModelResponse, ToolRequest } from './language-model';
|
|
17
|
+
import { isLanguageModelParsedResponse, isLanguageModelStreamResponse, isLanguageModelTextResponse, LanguageModelResponse, ToolRequest } from './language-model';
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Retrieves the text content from a `LanguageModelResponse` object.
|
|
21
|
+
*
|
|
22
|
+
* **Important:** For stream responses, the stream can only be consumed once. Calling this function multiple times on the same stream response will return an empty string (`''`)
|
|
23
|
+
* on subsequent calls, as the stream will have already been consumed.
|
|
24
|
+
*
|
|
25
|
+
* @param {LanguageModelResponse} response - The response object, which may contain a text, stream, or parsed response.
|
|
26
|
+
* @returns {Promise<string>} - A promise that resolves to the text content of the response.
|
|
27
|
+
* @throws {Error} - Throws an error if the response type is not supported or does not contain valid text content.
|
|
28
|
+
*/
|
|
19
29
|
export const getTextOfResponse = async (response: LanguageModelResponse): Promise<string> => {
|
|
20
30
|
if (isLanguageModelTextResponse(response)) {
|
|
21
31
|
return response.text;
|
|
@@ -25,12 +35,18 @@ export const getTextOfResponse = async (response: LanguageModelResponse): Promis
|
|
|
25
35
|
result += chunk.content ?? '';
|
|
26
36
|
}
|
|
27
37
|
return result;
|
|
38
|
+
} else if (isLanguageModelParsedResponse(response)) {
|
|
39
|
+
return response.content;
|
|
28
40
|
}
|
|
29
41
|
throw new Error(`Invalid response type ${response}`);
|
|
30
42
|
};
|
|
31
43
|
|
|
32
44
|
export const getJsonOfResponse = async (response: LanguageModelResponse): Promise<unknown> => {
|
|
33
45
|
const text = await getTextOfResponse(response);
|
|
46
|
+
return getJsonOfText(text);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const getJsonOfText = (text: string): unknown => {
|
|
34
50
|
if (text.startsWith('```json')) {
|
|
35
51
|
const regex = /```json\s*([\s\S]*?)\s*```/g;
|
|
36
52
|
let match;
|
|
@@ -47,6 +63,7 @@ export const getJsonOfResponse = async (response: LanguageModelResponse): Promis
|
|
|
47
63
|
}
|
|
48
64
|
throw new Error('Invalid response format');
|
|
49
65
|
};
|
|
66
|
+
|
|
50
67
|
export const toolRequestToPromptText = (toolRequest: ToolRequest): string => {
|
|
51
68
|
const parameters = toolRequest.parameters;
|
|
52
69
|
let paramsText = '';
|
|
@@ -58,17 +58,46 @@ export interface PromptService {
|
|
|
58
58
|
*/
|
|
59
59
|
getPrompt(id: string, args?: { [key: string]: unknown }): Promise<ResolvedPromptTemplate | undefined>;
|
|
60
60
|
/**
|
|
61
|
-
*
|
|
61
|
+
* Adds a prompt to the list of prompts.
|
|
62
62
|
* @param id the id of the prompt
|
|
63
63
|
* @param prompt the prompt template to store
|
|
64
64
|
*/
|
|
65
65
|
storePrompt(id: string, prompt: string): void;
|
|
66
|
+
/**
|
|
67
|
+
* Removes a prompt from the list of prompts.
|
|
68
|
+
* @param id the id of the prompt
|
|
69
|
+
*/
|
|
70
|
+
removePrompt(id: string): void;
|
|
66
71
|
/**
|
|
67
72
|
* Return all known prompts as a {@link PromptMap map}.
|
|
68
73
|
*/
|
|
69
74
|
getAllPrompts(): PromptMap;
|
|
70
75
|
}
|
|
71
76
|
|
|
77
|
+
export interface CustomAgentDescription {
|
|
78
|
+
id: string;
|
|
79
|
+
name: string;
|
|
80
|
+
description: string;
|
|
81
|
+
prompt: string;
|
|
82
|
+
defaultLLM: string;
|
|
83
|
+
}
|
|
84
|
+
export namespace CustomAgentDescription {
|
|
85
|
+
export function is(entry: unknown): entry is CustomAgentDescription {
|
|
86
|
+
// eslint-disable-next-line no-null/no-null
|
|
87
|
+
return typeof entry === 'object' && entry !== null
|
|
88
|
+
&& 'id' in entry && typeof entry.id === 'string'
|
|
89
|
+
&& 'name' in entry && typeof entry.name === 'string'
|
|
90
|
+
&& 'description' in entry && typeof entry.description === 'string'
|
|
91
|
+
&& 'prompt' in entry
|
|
92
|
+
&& typeof entry.prompt === 'string'
|
|
93
|
+
&& 'defaultLLM' in entry
|
|
94
|
+
&& typeof entry.defaultLLM === 'string';
|
|
95
|
+
}
|
|
96
|
+
export function equals(a: CustomAgentDescription, b: CustomAgentDescription): boolean {
|
|
97
|
+
return a.id === b.id && a.name === b.name && a.description === b.description && a.prompt === b.prompt && a.defaultLLM === b.defaultLLM;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
72
101
|
export const PromptCustomizationService = Symbol('PromptCustomizationService');
|
|
73
102
|
export interface PromptCustomizationService {
|
|
74
103
|
/**
|
|
@@ -89,9 +118,9 @@ export interface PromptCustomizationService {
|
|
|
89
118
|
* on the implementation. Implementation may for example decide to
|
|
90
119
|
* open an editor, or request more information from the user, ...
|
|
91
120
|
* @param id the template id.
|
|
92
|
-
* @param content optional content to
|
|
121
|
+
* @param content optional default content to initialize the template
|
|
93
122
|
*/
|
|
94
|
-
editTemplate(id: string,
|
|
123
|
+
editTemplate(id: string, defaultContent?: string): void;
|
|
95
124
|
|
|
96
125
|
/**
|
|
97
126
|
* Reset the template to its default value.
|
|
@@ -109,6 +138,22 @@ export interface PromptCustomizationService {
|
|
|
109
138
|
* Event which is fired when the prompt template is changed.
|
|
110
139
|
*/
|
|
111
140
|
readonly onDidChangePrompt: Event<string>;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Return all custom agents.
|
|
144
|
+
* @returns all custom agents
|
|
145
|
+
*/
|
|
146
|
+
getCustomAgents(): Promise<CustomAgentDescription[]>;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Event which is fired when custom agents are modified.
|
|
150
|
+
*/
|
|
151
|
+
readonly onDidChangeCustomAgents: Event<void>;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Open the custom agent yaml file.
|
|
155
|
+
*/
|
|
156
|
+
openCustomAgentYaml(): void;
|
|
112
157
|
}
|
|
113
158
|
|
|
114
159
|
@injectable()
|
|
@@ -210,4 +255,7 @@ export class PromptServiceImpl implements PromptService {
|
|
|
210
255
|
storePrompt(id: string, prompt: string): void {
|
|
211
256
|
this._prompts[id] = { id, template: prompt };
|
|
212
257
|
}
|
|
258
|
+
removePrompt(id: string): void {
|
|
259
|
+
delete this._prompts[id];
|
|
260
|
+
}
|
|
213
261
|
}
|