@theia/ai-chat 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.
Files changed (52) hide show
  1. package/lib/browser/ai-chat-frontend-module.d.ts.map +1 -1
  2. package/lib/browser/ai-chat-frontend-module.js +25 -2
  3. package/lib/browser/ai-chat-frontend-module.js.map +1 -1
  4. package/lib/browser/custom-agent-factory.d.ts +4 -0
  5. package/lib/browser/custom-agent-factory.d.ts.map +1 -0
  6. package/lib/browser/custom-agent-factory.js +20 -0
  7. package/lib/browser/custom-agent-factory.js.map +1 -0
  8. package/lib/browser/custom-agent-frontend-application-contribution.d.ts +13 -0
  9. package/lib/browser/custom-agent-frontend-application-contribution.d.ts.map +1 -0
  10. package/lib/browser/custom-agent-frontend-application-contribution.js +82 -0
  11. package/lib/browser/custom-agent-frontend-application-contribution.js.map +1 -0
  12. package/lib/common/chat-agent-service.d.ts +11 -0
  13. package/lib/common/chat-agent-service.d.ts.map +1 -1
  14. package/lib/common/chat-agent-service.js +3 -0
  15. package/lib/common/chat-agent-service.js.map +1 -1
  16. package/lib/common/chat-agents-variable-contribution.d.ts +1 -1
  17. package/lib/common/chat-agents-variable-contribution.d.ts.map +1 -1
  18. package/lib/common/chat-agents.d.ts +8 -1
  19. package/lib/common/chat-agents.d.ts.map +1 -1
  20. package/lib/common/chat-agents.js +48 -31
  21. package/lib/common/chat-agents.js.map +1 -1
  22. package/lib/common/chat-model.d.ts +14 -1
  23. package/lib/common/chat-model.d.ts.map +1 -1
  24. package/lib/common/chat-model.js +11 -1
  25. package/lib/common/chat-model.js.map +1 -1
  26. package/lib/common/custom-chat-agent.d.ts +14 -0
  27. package/lib/common/custom-chat-agent.d.ts.map +1 -0
  28. package/lib/common/custom-chat-agent.js +43 -0
  29. package/lib/common/custom-chat-agent.js.map +1 -0
  30. package/lib/common/index.d.ts +4 -3
  31. package/lib/common/index.d.ts.map +1 -1
  32. package/lib/common/index.js +4 -3
  33. package/lib/common/index.js.map +1 -1
  34. package/lib/common/o1-chat-agent.d.ts +13 -0
  35. package/lib/common/o1-chat-agent.d.ts.map +1 -0
  36. package/lib/common/o1-chat-agent.js +45 -0
  37. package/lib/common/o1-chat-agent.js.map +1 -0
  38. package/lib/common/orchestrator-chat-agent.d.ts.map +1 -1
  39. package/lib/common/orchestrator-chat-agent.js +28 -3
  40. package/lib/common/orchestrator-chat-agent.js.map +1 -1
  41. package/package.json +8 -8
  42. package/src/browser/ai-chat-frontend-module.ts +30 -4
  43. package/src/browser/custom-agent-factory.ts +20 -0
  44. package/src/browser/custom-agent-frontend-application-contribution.ts +73 -0
  45. package/src/common/chat-agent-service.ts +15 -0
  46. package/src/common/chat-agents-variable-contribution.ts +1 -1
  47. package/src/common/chat-agents.ts +49 -30
  48. package/src/common/chat-model.ts +17 -1
  49. package/src/common/custom-chat-agent.ts +44 -0
  50. package/src/common/index.ts +4 -3
  51. package/src/common/o1-chat-agent.ts +51 -0
  52. package/src/common/orchestrator-chat-agent.ts +29 -4
@@ -137,7 +137,8 @@ export abstract class AbstractChatAgent {
137
137
  protected defaultLanguageModelPurpose: string,
138
138
  public iconClass: string = 'codicon codicon-copilot',
139
139
  public locations: ChatAgentLocation[] = ChatAgentLocation.ALL,
140
- public tags: String[] = ['Chat']) {
140
+ public tags: String[] = ['Chat'],
141
+ public defaultLogging: boolean = true) {
141
142
  }
142
143
 
143
144
  @postConstruct()
@@ -152,14 +153,16 @@ export abstract class AbstractChatAgent {
152
153
  throw new Error('Couldn\'t find a matching language model. Please check your setup!');
153
154
  }
154
155
  const messages = await this.getMessages(request.session);
155
- this.recordingService.recordRequest({
156
- agentId: this.id,
157
- sessionId: request.session.id,
158
- timestamp: Date.now(),
159
- requestId: request.id,
160
- request: request.request.text,
161
- messages
162
- });
156
+ if (this.defaultLogging) {
157
+ this.recordingService.recordRequest({
158
+ agentId: this.id,
159
+ sessionId: request.session.id,
160
+ timestamp: Date.now(),
161
+ requestId: request.id,
162
+ request: request.request.text,
163
+ messages
164
+ });
165
+ }
163
166
 
164
167
  const systemMessageDescription = await this.getSystemMessageDescription();
165
168
  const tools: Map<string, ToolRequest> = new Map();
@@ -192,13 +195,15 @@ export abstract class AbstractChatAgent {
192
195
  );
193
196
  await this.addContentsToResponse(languageModelResponse, request);
194
197
  request.response.complete();
195
- this.recordingService.recordResponse({
196
- agentId: this.id,
197
- sessionId: request.session.id,
198
- timestamp: Date.now(),
199
- requestId: request.response.requestId,
200
- response: request.response.response.asString()
201
- });
198
+ if (this.defaultLogging) {
199
+ this.recordingService.recordResponse({
200
+ agentId: this.id,
201
+ sessionId: request.session.id,
202
+ timestamp: Date.now(),
203
+ requestId: request.response.requestId,
204
+ response: request.response.response.asString()
205
+ });
206
+ }
202
207
  } catch (e) {
203
208
  this.handleError(request, e);
204
209
  }
@@ -274,13 +279,22 @@ export abstract class AbstractChatAgent {
274
279
  tools: ToolRequest[] | undefined,
275
280
  token: CancellationToken
276
281
  ): Promise<LanguageModelResponse> {
282
+ const settings = this.getLlmSettings();
277
283
  const languageModelResponse = languageModel.request({
278
284
  messages,
279
285
  tools,
286
+ settings,
280
287
  }, token);
281
288
  return languageModelResponse;
282
289
  }
283
290
 
291
+ /**
292
+ * @returns the settings, such as `temperature`, to be used in all language model requests. Returns `undefined` by default.
293
+ */
294
+ protected getLlmSettings(): { [key: string]: unknown; } | undefined {
295
+ return undefined;
296
+ }
297
+
284
298
  protected abstract addContentsToResponse(languageModelResponse: LanguageModelResponse, request: ChatRequestModelImpl): Promise<void>;
285
299
  }
286
300
 
@@ -307,25 +321,30 @@ export abstract class AbstractStreamParsingChatAgent extends AbstractChatAgent {
307
321
  const contents = this.parseContents(languageModelResponse.text);
308
322
  request.response.response.addContents(contents);
309
323
  request.response.complete();
310
- this.recordingService.recordResponse({
311
- agentId: this.id,
312
- sessionId: request.session.id,
313
- timestamp: Date.now(),
314
- requestId: request.response.requestId,
315
- response: request.response.response.asString()
316
- });
324
+ if (this.defaultLogging) {
325
+ this.recordingService.recordResponse({
326
+ agentId: this.id,
327
+ sessionId: request.session.id,
328
+ timestamp: Date.now(),
329
+ requestId: request.response.requestId,
330
+ response: request.response.response.asString()
331
+
332
+ });
333
+ }
317
334
  return;
318
335
  }
319
336
  if (isLanguageModelStreamResponse(languageModelResponse)) {
320
337
  await this.addStreamResponse(languageModelResponse, request);
321
338
  request.response.complete();
322
- this.recordingService.recordResponse({
323
- agentId: this.id,
324
- sessionId: request.session.id,
325
- timestamp: Date.now(),
326
- requestId: request.response.requestId,
327
- response: request.response.response.asString()
328
- });
339
+ if (this.defaultLogging) {
340
+ this.recordingService.recordResponse({
341
+ agentId: this.id,
342
+ sessionId: request.session.id,
343
+ timestamp: Date.now(),
344
+ requestId: request.response.requestId,
345
+ response: request.response.response.asString()
346
+ });
347
+ }
329
348
  return;
330
349
  }
331
350
  this.logger.error(
@@ -73,6 +73,7 @@ export interface ChatRequestModel {
73
73
  readonly response: ChatResponseModel;
74
74
  readonly message: ParsedChatRequest;
75
75
  readonly agentId?: string;
76
+ readonly data?: { [key: string]: unknown };
76
77
  }
77
78
 
78
79
  export interface ChatProgressMessage {
@@ -342,14 +343,29 @@ export class ChatRequestModelImpl implements ChatRequestModel {
342
343
  protected _request: ChatRequest;
343
344
  protected _response: ChatResponseModelImpl;
344
345
  protected _agentId?: string;
346
+ protected _data: { [key: string]: unknown };
345
347
 
346
- constructor(session: ChatModel, public readonly message: ParsedChatRequest, agentId?: string) {
348
+ constructor(session: ChatModel, public readonly message: ParsedChatRequest, agentId?: string,
349
+ data: { [key: string]: unknown } = {}) {
347
350
  // TODO accept serialized data as a parameter to restore a previously saved ChatRequestModel
348
351
  this._request = message.request;
349
352
  this._id = generateUuid();
350
353
  this._session = session;
351
354
  this._response = new ChatResponseModelImpl(this._id, agentId);
352
355
  this._agentId = agentId;
356
+ this._data = data;
357
+ }
358
+
359
+ get data(): { [key: string]: unknown } | undefined {
360
+ return this._data;
361
+ }
362
+
363
+ addData(key: string, value: unknown): void {
364
+ this._data[key] = value;
365
+ }
366
+
367
+ getDataByKey(key: string): unknown {
368
+ return this._data[key];
353
369
  }
354
370
 
355
371
  get id(): string {
@@ -0,0 +1,44 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { AgentSpecificVariables, PromptTemplate } from '@theia/ai-core';
18
+ import { AbstractStreamParsingChatAgent, ChatAgent, SystemMessageDescription } from './chat-agents';
19
+ import { injectable } from '@theia/core/shared/inversify';
20
+
21
+ @injectable()
22
+ export class CustomChatAgent
23
+ extends AbstractStreamParsingChatAgent
24
+ implements ChatAgent {
25
+ name: string;
26
+ description: string;
27
+ readonly variables: string[] = [];
28
+ readonly functions: string[] = [];
29
+ readonly promptTemplates: PromptTemplate[] = [];
30
+ readonly agentSpecificVariables: AgentSpecificVariables[] = [];
31
+
32
+ constructor(
33
+ ) {
34
+ super('CustomChatAgent', [{ purpose: 'chat' }], 'chat');
35
+ }
36
+ protected override async getSystemMessageDescription(): Promise<SystemMessageDescription | undefined> {
37
+ const resolvedPrompt = await this.promptService.getPrompt(`${this.name}_prompt`);
38
+ return resolvedPrompt ? SystemMessageDescription.fromResolvedPromptTemplate(resolvedPrompt) : undefined;
39
+ }
40
+
41
+ set prompt(prompt: string) {
42
+ this.promptTemplates.push({ id: `${this.name}_prompt`, template: prompt });
43
+ }
44
+ }
@@ -13,12 +13,13 @@
13
13
  //
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
- export * from './chat-agent-service';
17
16
  export * from './chat-agents';
17
+ export * from './chat-agent-service';
18
18
  export * from './chat-model';
19
- export * from './parsed-chat-request';
20
19
  export * from './chat-request-parser';
21
20
  export * from './chat-service';
22
21
  export * from './command-chat-agents';
23
- export * from './universal-chat-agent';
22
+ export * from './custom-chat-agent';
23
+ export * from './parsed-chat-request';
24
24
  export * from './orchestrator-chat-agent';
25
+ export * from './universal-chat-agent';
@@ -0,0 +1,51 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import {
18
+ ChatAgent,
19
+ AbstractStreamParsingChatAgent,
20
+ SystemMessageDescription
21
+ } from './chat-agents';
22
+
23
+ import { injectable } from '@theia/core/shared/inversify';
24
+ import { AgentSpecificVariables, PromptTemplate } from '@theia/ai-core';
25
+
26
+ @injectable()
27
+ export class O1ChatAgent extends AbstractStreamParsingChatAgent implements ChatAgent {
28
+
29
+ public name = 'O1-Preview';
30
+ public description = 'An agent for interacting with ChatGPT o1-preview';
31
+ public promptTemplates: PromptTemplate[] = [];
32
+ readonly agentSpecificVariables: AgentSpecificVariables[] = [];
33
+ readonly variables: string[] = [];
34
+ readonly functions: string[] = [];
35
+
36
+ constructor() {
37
+ super(
38
+ 'o1-preview',
39
+ [{
40
+ purpose: 'chat',
41
+ identifier: 'openai/o1-preview',
42
+ }],
43
+ 'chat'
44
+ );
45
+ }
46
+
47
+ protected async getSystemMessageDescription(): Promise<SystemMessageDescription | undefined> {
48
+ // O1 currently does not support system prompts
49
+ return undefined;
50
+ }
51
+ }
@@ -14,7 +14,7 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { AgentSpecificVariables, getJsonOfResponse, LanguageModelResponse } from '@theia/ai-core';
17
+ import { AgentSpecificVariables, getJsonOfText, getTextOfResponse, LanguageModelResponse } from '@theia/ai-core';
18
18
  import {
19
19
  PromptTemplate
20
20
  } from '@theia/ai-core/lib/common';
@@ -22,6 +22,7 @@ import { inject, injectable } from '@theia/core/shared/inversify';
22
22
  import { ChatAgentService } from './chat-agent-service';
23
23
  import { AbstractStreamParsingChatAgent, ChatAgent, SystemMessageDescription } from './chat-agents';
24
24
  import { ChatRequestModelImpl, InformationalChatResponseContentImpl } from './chat-model';
25
+ import { generateUuid } from '@theia/core';
25
26
 
26
27
  export const orchestratorTemplate: PromptTemplate = {
27
28
  id: 'orchestrator-system',
@@ -59,6 +60,7 @@ You must only use the \`id\` attribute of the agent, never the name.
59
60
  `};
60
61
 
61
62
  export const OrchestratorChatAgentId = 'Orchestrator';
63
+ const OrchestatorRequestIdKey = 'orchestatorRequestIdKey';
62
64
 
63
65
  @injectable()
64
66
  export class OrchestratorChatAgent extends AbstractStreamParsingChatAgent implements ChatAgent {
@@ -74,7 +76,7 @@ export class OrchestratorChatAgent extends AbstractStreamParsingChatAgent implem
74
76
  super(OrchestratorChatAgentId, [{
75
77
  purpose: 'agent-selection',
76
78
  identifier: 'openai/gpt-4o',
77
- }], 'agent-selection', 'codicon codicon-symbol-boolean');
79
+ }], 'agent-selection', 'codicon codicon-symbol-boolean', undefined, undefined, false);
78
80
  this.name = OrchestratorChatAgentId;
79
81
  this.description = 'This agent analyzes the user request against the description of all available chat agents and selects the best fitting agent to answer the request \
80
82
  (by using AI).The user\'s request will be directly delegated to the selected agent without further confirmation.';
@@ -88,8 +90,19 @@ export class OrchestratorChatAgent extends AbstractStreamParsingChatAgent implem
88
90
  @inject(ChatAgentService)
89
91
  protected chatAgentService: ChatAgentService;
90
92
 
91
- override invoke(request: ChatRequestModelImpl): Promise<void> {
93
+ override async invoke(request: ChatRequestModelImpl): Promise<void> {
92
94
  request.response.addProgressMessage({ content: 'Determining the most appropriate agent', status: 'inProgress' });
95
+ // We generate a dedicated ID for recording the orchestrator request/response, as we will forward the original request to another agent
96
+ const orchestartorRequestId = generateUuid();
97
+ request.addData(OrchestatorRequestIdKey, orchestartorRequestId);
98
+ const userPrompt = request.request.text;
99
+ this.recordingService.recordRequest({
100
+ agentId: this.id,
101
+ sessionId: request.session.id,
102
+ timestamp: Date.now(),
103
+ requestId: orchestartorRequestId,
104
+ request: userPrompt,
105
+ });
93
106
  return super.invoke(request);
94
107
  }
95
108
 
@@ -100,8 +113,20 @@ export class OrchestratorChatAgent extends AbstractStreamParsingChatAgent implem
100
113
 
101
114
  protected override async addContentsToResponse(response: LanguageModelResponse, request: ChatRequestModelImpl): Promise<void> {
102
115
  let agentIds: string[] = [];
116
+ const responseText = await getTextOfResponse(response);
117
+ // We use the previously generated, dedicated ID to log the orchestrator response before we forward the original request
118
+ const orchestratorRequestId = request.getDataByKey(OrchestatorRequestIdKey);
119
+ if (typeof orchestratorRequestId === 'string') {
120
+ this.recordingService.recordResponse({
121
+ agentId: this.id,
122
+ sessionId: request.session.id,
123
+ timestamp: Date.now(),
124
+ requestId: orchestratorRequestId,
125
+ response: responseText,
126
+ });
127
+ }
103
128
  try {
104
- const jsonResponse = await getJsonOfResponse(response);
129
+ const jsonResponse = await getJsonOfText(responseText);
105
130
  if (Array.isArray(jsonResponse)) {
106
131
  agentIds = jsonResponse.filter((id: string) => id !== this.id);
107
132
  }