@theia/ai-chat 1.62.0-next.3 → 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/custom-agent-frontend-application-contribution.d.ts +2 -2
- package/lib/browser/custom-agent-frontend-application-contribution.d.ts.map +1 -1
- package/lib/browser/custom-agent-frontend-application-contribution.js +2 -1
- package/lib/browser/custom-agent-frontend-application-contribution.js.map +1 -1
- package/lib/browser/task-context-service.js +1 -1
- package/lib/browser/task-context-service.js.map +1 -1
- package/lib/common/chat-agents.d.ts +3 -4
- package/lib/common/chat-agents.d.ts.map +1 -1
- package/lib/common/chat-agents.js +12 -23
- package/lib/common/chat-agents.js.map +1 -1
- package/lib/common/chat-model.d.ts +13 -0
- package/lib/common/chat-model.d.ts.map +1 -1
- package/lib/common/chat-model.js +19 -0
- package/lib/common/chat-model.js.map +1 -1
- package/lib/common/chat-session-naming-service.d.ts +3 -3
- package/lib/common/chat-session-naming-service.d.ts.map +1 -1
- package/lib/common/chat-session-naming-service.js +20 -24
- package/lib/common/chat-session-naming-service.js.map +1 -1
- package/lib/common/chat-session-summary-agent-prompt.d.ts +4 -1
- package/lib/common/chat-session-summary-agent-prompt.d.ts.map +1 -1
- package/lib/common/chat-session-summary-agent-prompt.js +17 -14
- package/lib/common/chat-session-summary-agent-prompt.js.map +1 -1
- package/lib/common/chat-session-summary-agent.d.ts +2 -2
- package/lib/common/chat-session-summary-agent.d.ts.map +1 -1
- package/lib/common/chat-session-summary-agent.js +1 -1
- package/lib/common/chat-session-summary-agent.js.map +1 -1
- package/lib/common/chat-tool-request-service.d.ts +2 -1
- package/lib/common/chat-tool-request-service.d.ts.map +1 -1
- package/lib/common/chat-tool-request-service.js.map +1 -1
- package/lib/common/custom-chat-agent.js +1 -1
- package/lib/common/custom-chat-agent.js.map +1 -1
- package/package.json +10 -11
- package/src/browser/custom-agent-frontend-application-contribution.ts +4 -4
- package/src/browser/task-context-service.ts +1 -1
- package/src/common/chat-agents.ts +14 -28
- package/src/common/chat-model.ts +27 -0
- package/src/common/chat-session-naming-service.ts +24 -31
- package/src/common/chat-session-summary-agent-prompt.ts +17 -14
- package/src/common/chat-session-summary-agent.ts +2 -2
- package/src/common/chat-tool-request-service.ts +2 -4
- package/src/common/custom-chat-agent.ts +1 -1
|
@@ -23,8 +23,8 @@ import {
|
|
|
23
23
|
AgentSpecificVariables,
|
|
24
24
|
AIVariableContext,
|
|
25
25
|
AIVariableResolutionRequest,
|
|
26
|
-
CommunicationRecordingService,
|
|
27
26
|
getTextOfResponse,
|
|
27
|
+
isLanguageModelStreamResponsePart,
|
|
28
28
|
isTextResponsePart,
|
|
29
29
|
isThinkingResponsePart,
|
|
30
30
|
isToolCallResponsePart,
|
|
@@ -36,8 +36,8 @@ import {
|
|
|
36
36
|
LanguageModelService,
|
|
37
37
|
LanguageModelStreamResponse,
|
|
38
38
|
PromptService,
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
ResolvedPromptFragment,
|
|
40
|
+
PromptVariantSet,
|
|
41
41
|
TextMessage,
|
|
42
42
|
ToolCall,
|
|
43
43
|
ToolRequest,
|
|
@@ -75,7 +75,7 @@ export interface SystemMessageDescription {
|
|
|
75
75
|
functionDescriptions?: Map<string, ToolRequest>;
|
|
76
76
|
}
|
|
77
77
|
export namespace SystemMessageDescription {
|
|
78
|
-
export function
|
|
78
|
+
export function fromResolvedPromptFragment(resolvedPrompt: ResolvedPromptFragment): SystemMessageDescription {
|
|
79
79
|
return {
|
|
80
80
|
text: resolvedPrompt.text,
|
|
81
81
|
functionDescriptions: resolvedPrompt.functionDescriptions
|
|
@@ -147,9 +147,6 @@ export abstract class AbstractChatAgent implements ChatAgent {
|
|
|
147
147
|
@inject(DefaultResponseContentFactory)
|
|
148
148
|
protected defaultContentFactory: DefaultResponseContentFactory;
|
|
149
149
|
|
|
150
|
-
@inject(CommunicationRecordingService)
|
|
151
|
-
protected recordingService: CommunicationRecordingService;
|
|
152
|
-
|
|
153
150
|
readonly abstract id: string;
|
|
154
151
|
readonly abstract name: string;
|
|
155
152
|
readonly abstract languageModelRequirements: LanguageModelRequirement[];
|
|
@@ -158,7 +155,7 @@ export abstract class AbstractChatAgent implements ChatAgent {
|
|
|
158
155
|
tags: string[] = ['Chat'];
|
|
159
156
|
description: string = '';
|
|
160
157
|
variables: string[] = [];
|
|
161
|
-
|
|
158
|
+
prompts: PromptVariantSet[] = [];
|
|
162
159
|
agentSpecificVariables: AgentSpecificVariables[] = [];
|
|
163
160
|
functions: string[] = [];
|
|
164
161
|
protected readonly abstract defaultLanguageModelPurpose: string;
|
|
@@ -245,8 +242,8 @@ export abstract class AbstractChatAgent implements ChatAgent {
|
|
|
245
242
|
if (this.systemPromptId === undefined) {
|
|
246
243
|
return undefined;
|
|
247
244
|
}
|
|
248
|
-
const resolvedPrompt = await this.promptService.
|
|
249
|
-
return resolvedPrompt ? SystemMessageDescription.
|
|
245
|
+
const resolvedPrompt = await this.promptService.getResolvedPromptFragment(this.systemPromptId, undefined, context);
|
|
246
|
+
return resolvedPrompt ? SystemMessageDescription.fromResolvedPromptFragment(resolvedPrompt) : undefined;
|
|
250
247
|
}
|
|
251
248
|
|
|
252
249
|
protected async getMessages(
|
|
@@ -289,12 +286,6 @@ export abstract class AbstractChatAgent implements ChatAgent {
|
|
|
289
286
|
const agentSettings = this.getLlmSettings();
|
|
290
287
|
const settings = { ...agentSettings, ...request.session.settings };
|
|
291
288
|
const tools = toolRequests.length > 0 ? toolRequests : undefined;
|
|
292
|
-
this.recordingService.recordRequest({
|
|
293
|
-
agentId: this.id,
|
|
294
|
-
sessionId: request.session.id,
|
|
295
|
-
requestId: request.id,
|
|
296
|
-
request: messages
|
|
297
|
-
});
|
|
298
289
|
return this.languageModelService.sendRequest(
|
|
299
290
|
languageModel,
|
|
300
291
|
{
|
|
@@ -323,15 +314,6 @@ export abstract class AbstractChatAgent implements ChatAgent {
|
|
|
323
314
|
* Subclasses may override this method to perform additional actions or keep the response open for processing further requests.
|
|
324
315
|
*/
|
|
325
316
|
protected async onResponseComplete(request: MutableChatRequestModel): Promise<void> {
|
|
326
|
-
this.recordingService.recordResponse(
|
|
327
|
-
{
|
|
328
|
-
agentId: this.id,
|
|
329
|
-
sessionId: request.session.id,
|
|
330
|
-
requestId: request.id,
|
|
331
|
-
response: request.response.response.content.flatMap(c =>
|
|
332
|
-
c.toLanguageModelMessage?.() ?? ({ type: 'text', actor: 'ai', text: c.asDisplayString?.() ?? c.asString?.() ?? JSON.stringify(c) }))
|
|
333
|
-
}
|
|
334
|
-
);
|
|
335
317
|
return request.response.complete();
|
|
336
318
|
}
|
|
337
319
|
|
|
@@ -399,9 +381,13 @@ export abstract class AbstractStreamParsingChatAgent extends AbstractChatAgent {
|
|
|
399
381
|
let startIndex = Math.max(0, request.response.response.content.length - 1);
|
|
400
382
|
|
|
401
383
|
for await (const token of languageModelResponse.stream) {
|
|
384
|
+
// Skip unknown tokens. For example OpenAI sends empty tokens around tool calls
|
|
385
|
+
if (!isLanguageModelStreamResponsePart(token)) {
|
|
386
|
+
console.debug(`Unknown token: '${JSON.stringify(token)}'. Skipping`);
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
402
389
|
const newContent = this.parse(token, request);
|
|
403
|
-
|
|
404
|
-
if (!(isTextResponsePart(token) && token.content)) {
|
|
390
|
+
if (!isTextResponsePart(token)) {
|
|
405
391
|
// For non-text tokens (like tool calls), add them directly
|
|
406
392
|
if (isArray(newContent)) {
|
|
407
393
|
request.response.response.addContents(newContent);
|
|
@@ -409,7 +395,7 @@ export abstract class AbstractStreamParsingChatAgent extends AbstractChatAgent {
|
|
|
409
395
|
request.response.response.addContent(newContent);
|
|
410
396
|
}
|
|
411
397
|
// And reset the marker index and the text buffer as we skip matching across non-text tokens
|
|
412
|
-
startIndex = request.response.response.content.length
|
|
398
|
+
startIndex = request.response.response.content.length;
|
|
413
399
|
completeTextBuffer = '';
|
|
414
400
|
} else {
|
|
415
401
|
// parse the entire text so far (since beginning of the stream or last non-text token)
|
package/src/common/chat-model.ts
CHANGED
|
@@ -205,6 +205,12 @@ export interface ChangeSet extends Disposable {
|
|
|
205
205
|
onDidChange: Event<ChangeSetChangeEvent>;
|
|
206
206
|
readonly title: string;
|
|
207
207
|
getElements(): ChangeSetElement[];
|
|
208
|
+
/**
|
|
209
|
+
* Find an element by URI.
|
|
210
|
+
* @param uri The URI to look for.
|
|
211
|
+
* @returns The element with the given URI, or undefined if not found.
|
|
212
|
+
*/
|
|
213
|
+
getElementByURI(uri: URI): ChangeSetElement | undefined;
|
|
208
214
|
dispose(): void;
|
|
209
215
|
}
|
|
210
216
|
|
|
@@ -1037,6 +1043,21 @@ export class ChangeSetImpl implements ChangeSet {
|
|
|
1037
1043
|
return this._elements;
|
|
1038
1044
|
}
|
|
1039
1045
|
|
|
1046
|
+
/**
|
|
1047
|
+
* Find an element by URI.
|
|
1048
|
+
* @param uri The URI to look for.
|
|
1049
|
+
* @returns The element with the given URI, or undefined if not found.
|
|
1050
|
+
*/
|
|
1051
|
+
getElementByURI(uri: URI): ChangeSetElement | undefined {
|
|
1052
|
+
const uriString = uri.toString();
|
|
1053
|
+
for (const element of this._elements) {
|
|
1054
|
+
if (element.uri.toString() === uriString) {
|
|
1055
|
+
return element;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
return undefined;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1040
1061
|
/** Will replace any element that is already present, using URI as identity criterion. */
|
|
1041
1062
|
addElements(...elements: ChangeSetElement[]): void {
|
|
1042
1063
|
const added: URI[] = [];
|
|
@@ -1190,6 +1211,10 @@ export class MutableChatRequestModel implements ChatRequestModel, EditableChatRe
|
|
|
1190
1211
|
return this._data[key] as T;
|
|
1191
1212
|
}
|
|
1192
1213
|
|
|
1214
|
+
removeData(key: string): void {
|
|
1215
|
+
delete this._data[key];
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1193
1218
|
get id(): string {
|
|
1194
1219
|
return this._id;
|
|
1195
1220
|
}
|
|
@@ -1516,6 +1541,8 @@ export class ToolCallChatResponseContentImpl implements ToolCallChatResponseCont
|
|
|
1516
1541
|
if (nextChatResponseContent.id === this.id) {
|
|
1517
1542
|
this._finished = nextChatResponseContent.finished;
|
|
1518
1543
|
this._result = nextChatResponseContent.result;
|
|
1544
|
+
const args = nextChatResponseContent.arguments;
|
|
1545
|
+
this._arguments = (args && args.length > 0) ? args : this._arguments;
|
|
1519
1546
|
return true;
|
|
1520
1547
|
}
|
|
1521
1548
|
if (nextChatResponseContent.name !== undefined) {
|
|
@@ -17,31 +17,33 @@
|
|
|
17
17
|
import {
|
|
18
18
|
Agent,
|
|
19
19
|
AgentService,
|
|
20
|
-
CommunicationRecordingService,
|
|
21
|
-
CommunicationRequestEntryParam,
|
|
22
20
|
getTextOfResponse,
|
|
23
21
|
LanguageModelRegistry,
|
|
24
22
|
LanguageModelRequirement,
|
|
23
|
+
LanguageModelService,
|
|
25
24
|
PromptService,
|
|
26
|
-
|
|
25
|
+
PromptVariantSet,
|
|
27
26
|
UserRequest
|
|
28
27
|
} from '@theia/ai-core';
|
|
29
28
|
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
30
29
|
import { ChatSession } from './chat-service';
|
|
31
30
|
import { generateUuid } from '@theia/core';
|
|
32
31
|
|
|
33
|
-
const CHAT_SESSION_NAMING_PROMPT = {
|
|
32
|
+
const CHAT_SESSION_NAMING_PROMPT: PromptVariantSet = {
|
|
34
33
|
id: 'chat-session-naming-prompt',
|
|
35
|
-
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
defaultVariant: {
|
|
35
|
+
id: 'chat-session-naming-prompt',
|
|
36
|
+
template: '{{!-- Made improvements or adaptations to this prompt template? We\'d love for you to share it with the community! Contribute back here: ' +
|
|
37
|
+
'https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-contribution --}}\n\n' +
|
|
38
|
+
'Provide a short and descriptive name for the given AI chat conversation of an AI-powered tool based on the conversation below.\n\n' +
|
|
39
|
+
'The purpose of the name is for users to recognize the chat conversation easily in a list of conversations. ' +
|
|
40
|
+
'Use the same language for the chat conversation name as used in the provided conversation, if in doubt default to English. ' +
|
|
41
|
+
'Start the chat conversation name with an upper-case letter. ' +
|
|
42
|
+
'Below we also provide the already existing other conversation names, make sure your suggestion for a name is unique with respect to the existing ones.\n\n' +
|
|
43
|
+
'IMPORTANT: Your answer MUST ONLY CONTAIN THE PROPOSED NAME and must not be preceded or followed by any other text.' +
|
|
44
|
+
'\n\nOther session names:\n{{listOfSessionNames}}' +
|
|
45
|
+
'\n\nConversation:\n{{conversation}}',
|
|
46
|
+
}
|
|
45
47
|
};
|
|
46
48
|
|
|
47
49
|
@injectable()
|
|
@@ -58,12 +60,12 @@ export class ChatSessionNamingService {
|
|
|
58
60
|
|
|
59
61
|
@injectable()
|
|
60
62
|
export class ChatSessionNamingAgent implements Agent {
|
|
61
|
-
static ID = '
|
|
63
|
+
static ID = 'Chat Session Naming';
|
|
62
64
|
id = ChatSessionNamingAgent.ID;
|
|
63
|
-
name =
|
|
65
|
+
name = ChatSessionNamingAgent.ID;
|
|
64
66
|
description = 'Agent for generating chat session names';
|
|
65
67
|
variables = [];
|
|
66
|
-
|
|
68
|
+
prompts = [CHAT_SESSION_NAMING_PROMPT];
|
|
67
69
|
languageModelRequirements: LanguageModelRequirement[] = [{
|
|
68
70
|
purpose: 'chat-session-naming',
|
|
69
71
|
identifier: 'openai/gpt-4o-mini',
|
|
@@ -77,8 +79,8 @@ export class ChatSessionNamingAgent implements Agent {
|
|
|
77
79
|
@inject(LanguageModelRegistry)
|
|
78
80
|
protected readonly lmRegistry: LanguageModelRegistry;
|
|
79
81
|
|
|
80
|
-
@inject(
|
|
81
|
-
protected
|
|
82
|
+
@inject(LanguageModelService)
|
|
83
|
+
protected readonly languageModelService: LanguageModelService;
|
|
82
84
|
|
|
83
85
|
@inject(PromptService)
|
|
84
86
|
protected promptService: PromptService;
|
|
@@ -98,7 +100,7 @@ export class ChatSessionNamingAgent implements Agent {
|
|
|
98
100
|
.join('\n\n');
|
|
99
101
|
const listOfSessionNames = otherNames.map(name => name).join(', ');
|
|
100
102
|
|
|
101
|
-
const prompt = await this.promptService.
|
|
103
|
+
const prompt = await this.promptService.getResolvedPromptFragment(CHAT_SESSION_NAMING_PROMPT.id, { conversation, listOfSessionNames });
|
|
102
104
|
const message = prompt?.text;
|
|
103
105
|
if (!message) {
|
|
104
106
|
throw new Error('Unable to create prompt message for generating chat session name');
|
|
@@ -106,7 +108,7 @@ export class ChatSessionNamingAgent implements Agent {
|
|
|
106
108
|
|
|
107
109
|
const sessionId = generateUuid();
|
|
108
110
|
const requestId = generateUuid();
|
|
109
|
-
const request: UserRequest = {
|
|
111
|
+
const request: UserRequest & { agentId: string } = {
|
|
110
112
|
messages: [{
|
|
111
113
|
actor: 'user',
|
|
112
114
|
text: message,
|
|
@@ -116,18 +118,9 @@ export class ChatSessionNamingAgent implements Agent {
|
|
|
116
118
|
sessionId,
|
|
117
119
|
agentId: this.id
|
|
118
120
|
};
|
|
119
|
-
this.
|
|
120
|
-
|
|
121
|
-
const result = await lm.request(request);
|
|
121
|
+
const result = await this.languageModelService.sendRequest(lm, request);
|
|
122
122
|
const response = await getTextOfResponse(result);
|
|
123
|
-
this.recordingService.recordResponse({
|
|
124
|
-
agentId: this.id,
|
|
125
|
-
sessionId,
|
|
126
|
-
requestId,
|
|
127
|
-
response: [{ actor: 'ai', text: response, type: 'text' }]
|
|
128
|
-
});
|
|
129
123
|
|
|
130
124
|
return response.replace(/\s+/g, ' ').substring(0, 100);
|
|
131
125
|
}
|
|
132
|
-
|
|
133
126
|
}
|
|
@@ -11,18 +11,21 @@
|
|
|
11
11
|
import { CHANGE_SET_SUMMARY_VARIABLE_ID } from './context-variables';
|
|
12
12
|
|
|
13
13
|
export const CHAT_SESSION_SUMMARY_PROMPT = {
|
|
14
|
-
id: 'chat-session-summary-prompt',
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
'https://
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
id: 'chat-session-summary-system-prompt',
|
|
15
|
+
defaultVariant: {
|
|
16
|
+
id: 'chat-session-summary-prompt',
|
|
17
|
+
template: '{{!-- !-- This prompt is licensed under the MIT License (https://opensource.org/license/mit).\n' +
|
|
18
|
+
'Made improvements or adaptations to this prompt template? We\'d love for you to share it with the community! Contribute back here: ' +
|
|
19
|
+
'https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-contribution --}}\n\n' +
|
|
20
|
+
'You are a chat agent for summarizing AI agent chat sessions for later use. ' +
|
|
21
|
+
'Review the conversation above and generate a concise summary that captures every crucial detail, ' +
|
|
22
|
+
'including all requirements, decisions, and pending tasks. ' +
|
|
23
|
+
'Ensure that the summary is sufficiently comprehensive to allow seamless continuation of the workflow. ' +
|
|
24
|
+
'The summary will primarily be used by other AI agents, so tailor your response for use by AI agents. ' +
|
|
25
|
+
'Also consider the system message. ' +
|
|
26
|
+
'Make sure you include all necessary context information and use unique references(such as URIs, file paths, etc.). ' +
|
|
27
|
+
'If the conversation was about a task, describe the state of the task, i.e.what has been completed and what is open. ' +
|
|
28
|
+
'If a changeset is open in the session, describe the state of the suggested changes. ' +
|
|
29
|
+
`\n\n{{${CHANGE_SET_SUMMARY_VARIABLE_ID}}}`,
|
|
30
|
+
}
|
|
28
31
|
};
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import {
|
|
18
18
|
LanguageModelRequirement,
|
|
19
|
-
|
|
19
|
+
PromptVariantSet
|
|
20
20
|
} from '@theia/ai-core';
|
|
21
21
|
import { injectable } from '@theia/core/shared/inversify';
|
|
22
22
|
import { AbstractStreamParsingChatAgent, ChatAgent } from './chat-agents';
|
|
@@ -29,7 +29,7 @@ export class ChatSessionSummaryAgent extends AbstractStreamParsingChatAgent impl
|
|
|
29
29
|
name = 'Chat Session Summary';
|
|
30
30
|
override description = 'Agent for generating chat session summaries.';
|
|
31
31
|
override variables = [];
|
|
32
|
-
override
|
|
32
|
+
override prompts: PromptVariantSet[] = [CHAT_SESSION_SUMMARY_PROMPT];
|
|
33
33
|
protected readonly defaultLanguageModelPurpose = 'chat-session-summary';
|
|
34
34
|
languageModelRequirements: LanguageModelRequirement[] = [{
|
|
35
35
|
purpose: 'chat-session-summary',
|
|
@@ -19,10 +19,8 @@ import { injectable } from '@theia/core/shared/inversify';
|
|
|
19
19
|
import { MutableChatRequestModel } from './chat-model';
|
|
20
20
|
|
|
21
21
|
export interface ChatToolRequest extends ToolRequest {
|
|
22
|
-
handler:
|
|
23
|
-
|
|
24
|
-
context: MutableChatRequestModel,
|
|
25
|
-
) => Promise<unknown>;
|
|
22
|
+
handler(arg_string: string, context: MutableChatRequestModel): Promise<unknown>;
|
|
23
|
+
handler(arg_string: string, ctx?: unknown): Promise<unknown>;
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
/**
|
|
@@ -28,6 +28,6 @@ export class CustomChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
28
28
|
set prompt(prompt: string) {
|
|
29
29
|
// the name is dynamic, so we set the propmptId here
|
|
30
30
|
this.systemPromptId = `${this.name}_prompt`;
|
|
31
|
-
this.
|
|
31
|
+
this.prompts.push({ id: this.systemPromptId, defaultVariant: { id: `${this.name}_prompt`, template: prompt } });
|
|
32
32
|
}
|
|
33
33
|
}
|