@theia/ai-chat 1.61.0-next.8 → 1.61.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 (98) hide show
  1. package/lib/browser/ai-chat-frontend-contribution.d.ts +11 -0
  2. package/lib/browser/ai-chat-frontend-contribution.d.ts.map +1 -0
  3. package/lib/browser/ai-chat-frontend-contribution.js +56 -0
  4. package/lib/browser/ai-chat-frontend-contribution.js.map +1 -0
  5. package/lib/browser/ai-chat-frontend-module.d.ts.map +1 -1
  6. package/lib/browser/ai-chat-frontend-module.js +21 -3
  7. package/lib/browser/ai-chat-frontend-module.js.map +1 -1
  8. package/lib/browser/change-set-decorator-service.d.ts +24 -0
  9. package/lib/browser/change-set-decorator-service.d.ts.map +1 -0
  10. package/lib/browser/change-set-decorator-service.js +66 -0
  11. package/lib/browser/change-set-decorator-service.js.map +1 -0
  12. package/lib/browser/change-set-file-element.d.ts +7 -4
  13. package/lib/browser/change-set-file-element.d.ts.map +1 -1
  14. package/lib/browser/change-set-file-element.js +20 -12
  15. package/lib/browser/change-set-file-element.js.map +1 -1
  16. package/lib/browser/change-set-file-resource.d.ts +1 -42
  17. package/lib/browser/change-set-file-resource.d.ts.map +1 -1
  18. package/lib/browser/change-set-file-resource.js +1 -136
  19. package/lib/browser/change-set-file-resource.js.map +1 -1
  20. package/lib/browser/change-set-variable.d.ts.map +1 -1
  21. package/lib/browser/change-set-variable.js +13 -4
  22. package/lib/browser/change-set-variable.js.map +1 -1
  23. package/lib/browser/context-file-variable-label-provider.js +1 -1
  24. package/lib/browser/context-file-variable-label-provider.js.map +1 -1
  25. package/lib/browser/file-chat-variable-contribution.d.ts.map +1 -1
  26. package/lib/browser/file-chat-variable-contribution.js +29 -27
  27. package/lib/browser/file-chat-variable-contribution.js.map +1 -1
  28. package/lib/browser/task-context-service.d.ts +40 -0
  29. package/lib/browser/task-context-service.d.ts.map +1 -0
  30. package/lib/browser/task-context-service.js +148 -0
  31. package/lib/browser/task-context-service.js.map +1 -0
  32. package/lib/browser/task-context-storage-service.d.ts +18 -0
  33. package/lib/browser/task-context-storage-service.d.ts.map +1 -0
  34. package/lib/browser/task-context-storage-service.js +77 -0
  35. package/lib/browser/task-context-storage-service.js.map +1 -0
  36. package/lib/browser/task-context-variable-contribution.d.ts +20 -0
  37. package/lib/browser/task-context-variable-contribution.d.ts.map +1 -0
  38. package/lib/browser/task-context-variable-contribution.js +101 -0
  39. package/lib/browser/task-context-variable-contribution.js.map +1 -0
  40. package/lib/browser/task-context-variable-label-provider.d.ts +21 -0
  41. package/lib/browser/task-context-variable-label-provider.d.ts.map +1 -0
  42. package/lib/browser/task-context-variable-label-provider.js +83 -0
  43. package/lib/browser/task-context-variable-label-provider.js.map +1 -0
  44. package/lib/browser/task-context-variable.d.ts +3 -0
  45. package/lib/browser/task-context-variable.d.ts.map +1 -0
  46. package/lib/browser/task-context-variable.js +29 -0
  47. package/lib/browser/task-context-variable.js.map +1 -0
  48. package/lib/common/chat-agents.d.ts +2 -1
  49. package/lib/common/chat-agents.d.ts.map +1 -1
  50. package/lib/common/chat-agents.js +5 -0
  51. package/lib/common/chat-agents.js.map +1 -1
  52. package/lib/common/chat-model.d.ts +173 -8
  53. package/lib/common/chat-model.d.ts.map +1 -1
  54. package/lib/common/chat-model.js +329 -17
  55. package/lib/common/chat-model.js.map +1 -1
  56. package/lib/common/chat-request-parser.d.ts +1 -1
  57. package/lib/common/chat-request-parser.d.ts.map +1 -1
  58. package/lib/common/chat-request-parser.js +1 -1
  59. package/lib/common/chat-request-parser.js.map +1 -1
  60. package/lib/common/chat-service.d.ts +2 -0
  61. package/lib/common/chat-service.d.ts.map +1 -1
  62. package/lib/common/chat-service.js +18 -25
  63. package/lib/common/chat-service.js.map +1 -1
  64. package/lib/common/chat-session-naming-service.d.ts.map +1 -1
  65. package/lib/common/chat-session-naming-service.js +3 -3
  66. package/lib/common/chat-session-naming-service.js.map +1 -1
  67. package/lib/common/chat-session-summary-agent-prompt.d.ts +5 -0
  68. package/lib/common/chat-session-summary-agent-prompt.d.ts.map +1 -0
  69. package/lib/common/chat-session-summary-agent-prompt.js +30 -0
  70. package/lib/common/chat-session-summary-agent-prompt.js.map +1 -0
  71. package/lib/common/chat-session-summary-agent.d.ts +17 -0
  72. package/lib/common/chat-session-summary-agent.d.ts.map +1 -0
  73. package/lib/common/chat-session-summary-agent.js +48 -0
  74. package/lib/common/chat-session-summary-agent.js.map +1 -0
  75. package/lib/common/context-summary-variable.js +1 -1
  76. package/lib/common/context-summary-variable.js.map +1 -1
  77. package/package.json +11 -11
  78. package/src/browser/ai-chat-frontend-contribution.ts +49 -0
  79. package/src/browser/ai-chat-frontend-module.ts +25 -4
  80. package/src/browser/change-set-decorator-service.ts +72 -0
  81. package/src/browser/change-set-file-element.ts +18 -13
  82. package/src/browser/change-set-file-resource.ts +1 -138
  83. package/src/browser/change-set-variable.ts +14 -6
  84. package/src/browser/context-file-variable-label-provider.ts +1 -1
  85. package/src/browser/file-chat-variable-contribution.ts +26 -29
  86. package/src/browser/task-context-service.ts +144 -0
  87. package/src/browser/task-context-storage-service.ts +75 -0
  88. package/src/browser/task-context-variable-contribution.ts +93 -0
  89. package/src/browser/task-context-variable-label-provider.ts +67 -0
  90. package/src/browser/task-context-variable.ts +28 -0
  91. package/src/common/chat-agents.ts +6 -1
  92. package/src/common/chat-model.ts +507 -18
  93. package/src/common/chat-request-parser.ts +2 -2
  94. package/src/common/chat-service.ts +17 -26
  95. package/src/common/chat-session-naming-service.ts +4 -3
  96. package/src/common/chat-session-summary-agent-prompt.ts +28 -0
  97. package/src/common/chat-session-summary-agent.ts +42 -0
  98. package/src/common/context-summary-variable.ts +1 -1
@@ -55,7 +55,7 @@ function offsetRange(start: number, endExclusive: number): OffsetRange {
55
55
  return { start, endExclusive };
56
56
  }
57
57
  @injectable()
58
- export class ChatRequestParserImpl {
58
+ export class ChatRequestParserImpl implements ChatRequestParser {
59
59
  constructor(
60
60
  @inject(ChatAgentService) private readonly agentService: ChatAgentService,
61
61
  @inject(AIVariableService) private readonly variableService: AIVariableService,
@@ -90,7 +90,7 @@ export class ChatRequestParserImpl {
90
90
  }
91
91
 
92
92
  // Get resolved variables from variable cache after all variables have been resolved.
93
- // We want to return all recursilvely resolved variables, thus use the whole cache.
93
+ // We want to return all recursively resolved variables, thus use the whole cache.
94
94
  const resolvedVariables = await getAllResolvedAIVariables(variableCache);
95
95
 
96
96
  return { request, parts, toolRequests, variables: resolvedVariables };
@@ -38,6 +38,7 @@ import {
38
38
  import { ChatRequestParser } from './chat-request-parser';
39
39
  import { ParsedChatRequest, ParsedChatRequestAgentPart } from './parsed-chat-request';
40
40
  import { ChatSessionNamingService } from './chat-session-naming-service';
41
+ import { Deferred } from '@theia/core/lib/common/promise-util';
41
42
 
42
43
  export interface ChatRequestInvocation {
43
44
  /**
@@ -125,6 +126,7 @@ export interface ChatService {
125
126
  getSessions(): ChatSession[];
126
127
  createSession(location?: ChatAgentLocation, options?: SessionOptions, pinnedAgent?: ChatAgent): ChatSession;
127
128
  deleteSession(sessionId: string): void;
129
+ getActiveSession(): ChatSession | undefined;
128
130
  setActiveSession(sessionId: string, options?: SessionOptions): void;
129
131
 
130
132
  sendRequest(
@@ -208,6 +210,12 @@ export class ChatServiceImpl implements ChatService {
208
210
  this.onSessionEventEmitter.fire({ type: 'deleted', sessionId: sessionId });
209
211
  }
210
212
 
213
+ getActiveSession(): ChatSession | undefined {
214
+ const activeSessions = this._sessions.filter(candidate => candidate.isActive);
215
+ if (activeSessions.length > 1) { throw new Error('More than one session marked as active. This indicates an error in ChatService.'); }
216
+ return activeSessions.at(0);
217
+ }
218
+
211
219
  setActiveSession(sessionId: string | undefined, options?: SessionOptions): void {
212
220
  this._sessions.forEach(session => {
213
221
  session.isActive = session.id === sessionId;
@@ -225,7 +233,7 @@ export class ChatServiceImpl implements ChatService {
225
233
  }
226
234
 
227
235
  const resolutionContext: ChatSessionContext = { model: session.model };
228
- const resolvedContext = await this.resolveChatContext(session.model.context.getVariables(), resolutionContext);
236
+ const resolvedContext = await this.resolveChatContext(request.variables ?? session.model.context.getVariables(), resolutionContext);
229
237
  const parsedRequest = await this.chatRequestParser.parseChatRequest(request, session.model.location, resolvedContext);
230
238
  const agent = this.getAgent(parsedRequest, session);
231
239
 
@@ -244,33 +252,23 @@ export class ChatServiceImpl implements ChatService {
244
252
  this.updateSessionMetadata(session, requestModel);
245
253
  resolutionContext.request = requestModel;
246
254
 
247
- let resolveResponseCreated: (responseModel: ChatResponseModel) => void;
248
- let resolveResponseCompleted: (responseModel: ChatResponseModel) => void;
255
+ const responseCompletionDeferred = new Deferred<ChatResponseModel>();
249
256
  const invocation: ChatRequestInvocation = {
250
257
  requestCompleted: Promise.resolve(requestModel),
251
- responseCreated: new Promise(resolve => {
252
- resolveResponseCreated = resolve;
253
- }),
254
- responseCompleted: new Promise(resolve => {
255
- resolveResponseCompleted = resolve;
256
- }),
258
+ responseCreated: Promise.resolve(requestModel.response),
259
+ responseCompleted: responseCompletionDeferred.promise,
257
260
  };
258
261
 
259
- resolveResponseCreated!(requestModel.response);
260
262
  requestModel.response.onDidChange(() => {
261
263
  if (requestModel.response.isComplete) {
262
- resolveResponseCompleted!(requestModel.response);
264
+ responseCompletionDeferred.resolve(requestModel.response);
263
265
  }
264
266
  if (requestModel.response.isError) {
265
- resolveResponseCompleted!(requestModel.response);
267
+ responseCompletionDeferred.resolve(requestModel.response);
266
268
  }
267
269
  });
268
270
 
269
- if (agent) {
270
- agent.invoke(requestModel).catch(error => requestModel.response.error(error));
271
- } else {
272
- this.logger.error('No ChatAgents available to handle request!', requestModel);
273
- }
271
+ agent.invoke(requestModel).catch(error => requestModel.response.error(error));
274
272
 
275
273
  return invocation;
276
274
  }
@@ -304,15 +302,8 @@ export class ChatServiceImpl implements ChatService {
304
302
  context: ChatSessionContext,
305
303
  ): Promise<ChatContext> {
306
304
  // TODO use a common cache to resolve variables and return recursively resolved variables?
307
- const resolvedVariables = await Promise.all(
308
- resolutionRequests.map(async contextVariable => {
309
- const resolvedVariable = await this.variableService.resolveVariable(contextVariable, context);
310
- if (ResolvedAIContextVariable.is(resolvedVariable)) {
311
- return resolvedVariable;
312
- }
313
- return undefined;
314
- })
315
- ).then(results => results.filter((result): result is ResolvedAIContextVariable => result !== undefined));
305
+ const resolvedVariables = await Promise.all(resolutionRequests.map(async contextVariable => this.variableService.resolveVariable(contextVariable, context)))
306
+ .then(results => results.filter(ResolvedAIContextVariable.is));
316
307
  return { variables: resolvedVariables };
317
308
  }
318
309
 
@@ -18,6 +18,7 @@ import {
18
18
  Agent,
19
19
  AgentService,
20
20
  CommunicationRecordingService,
21
+ CommunicationRequestEntryParam,
21
22
  getTextOfResponse,
22
23
  LanguageModelRegistry,
23
24
  LanguageModelRequirement,
@@ -38,7 +39,7 @@ const CHAT_SESSION_NAMING_PROMPT = {
38
39
  'Use the same language for the chat conversation name as used in the provided conversation, if in doubt default to English. ' +
39
40
  'Start the chat conversation name with an upper-case letter. ' +
40
41
  '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' +
41
- 'IMPORTANT: Your answer MUST ONLY CONTAIN THE PROPOSED NAME and must not be preceded or succeeded with any other text.' +
42
+ 'IMPORTANT: Your answer MUST ONLY CONTAIN THE PROPOSED NAME and must not be preceded or followed by any other text.' +
42
43
  '\n\nOther session names:\n{{listOfSessionNames}}' +
43
44
  '\n\nConversation:\n{{conversation}}',
44
45
  };
@@ -92,7 +93,7 @@ export class ChatSessionNamingAgent implements Agent {
92
93
  }
93
94
 
94
95
  const conversation = chatSession.model.getRequests()
95
- .map(req => `<user>${req.request.text}</user>` +
96
+ .map(req => `<user>${req.message.parts.map(chunk => chunk.promptText).join('')}</user>` +
96
97
  (req.response.response ? `<assistant>${req.response.response.asString()}</assistant>` : ''))
97
98
  .join('\n\n');
98
99
  const listOfSessionNames = otherNames.map(name => name).join(', ');
@@ -115,7 +116,7 @@ export class ChatSessionNamingAgent implements Agent {
115
116
  sessionId,
116
117
  agentId: this.id
117
118
  };
118
- this.recordingService.recordRequest(request);
119
+ this.recordingService.recordRequest({ ...request, request: request.messages } satisfies CommunicationRequestEntryParam);
119
120
 
120
121
  const result = await lm.request(request);
121
122
  const response = await getTextOfResponse(result);
@@ -0,0 +1,28 @@
1
+ /* eslint-disable @typescript-eslint/tslint/config */
2
+ // *****************************************************************************
3
+ // Copyright (C) 2025 EclipseSource GmbH and others.
4
+ //
5
+ // This file is licensed under the MIT License.
6
+ // See LICENSE-MIT.txt in the project root for license information.
7
+ // https://opensource.org/license/mit.
8
+ //
9
+ // SPDX-License-Identifier: MIT
10
+
11
+ import { CHANGE_SET_SUMMARY_VARIABLE_ID } from './context-variables';
12
+
13
+ export const CHAT_SESSION_SUMMARY_PROMPT = {
14
+ id: 'chat-session-summary-prompt',
15
+ template: `{{!-- !-- This prompt is licensed under the MIT License (https://opensource.org/license/mit).
16
+ Made improvements or adaptations to this prompt template? We\'d love for you to share it with the community! Contribute back here: ' +
17
+ 'https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-contribution --}}\n\n' +
18
+ 'You are a chat agent for summarizing AI agent chat sessions for later use. \
19
+ Review the conversation above and generate a concise summary that captures every crucial detail, \
20
+ including all requirements, decisions, and pending tasks. \
21
+ Ensure that the summary is sufficiently comprehensive to allow seamless continuation of the workflow. The summary will primarily be used by other AI agents, so tailor your \
22
+ response for use by AI agents. \
23
+ Also consider the system message.
24
+ Make sure you include all necessary context information and use unique references (such as URIs, file paths, etc.).
25
+ If the conversation was about a task, describe the state of the task, i.e. what has been completed and what is open.
26
+ If a changeset is open in the session, describe the state of the suggested changes.
27
+ {{${CHANGE_SET_SUMMARY_VARIABLE_ID}}}`,
28
+ };
@@ -0,0 +1,42 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 EclipseSource GmbH and others.
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
+ LanguageModelRequirement,
19
+ PromptTemplate
20
+ } from '@theia/ai-core';
21
+ import { injectable } from '@theia/core/shared/inversify';
22
+ import { AbstractStreamParsingChatAgent, ChatAgent } from './chat-agents';
23
+ import { CHAT_SESSION_SUMMARY_PROMPT } from './chat-session-summary-agent-prompt';
24
+
25
+ @injectable()
26
+ export class ChatSessionSummaryAgent extends AbstractStreamParsingChatAgent implements ChatAgent {
27
+ static ID = 'chat-session-summary-agent';
28
+ id = ChatSessionSummaryAgent.ID;
29
+ name = 'Chat Session Summary';
30
+ override description = 'Agent for generating chat session summaries.';
31
+ override variables = [];
32
+ override promptTemplates: PromptTemplate[] = [CHAT_SESSION_SUMMARY_PROMPT];
33
+ protected readonly defaultLanguageModelPurpose = 'chat-session-summary';
34
+ languageModelRequirements: LanguageModelRequirement[] = [{
35
+ purpose: 'chat-session-summary',
36
+ identifier: 'openai/gpt-4o-mini',
37
+ }];
38
+ override agentSpecificVariables = [];
39
+ override functions = [];
40
+ override locations = [];
41
+ override tags = [];
42
+ }
@@ -38,7 +38,7 @@ export class ContextSummaryVariableContribution implements AIVariableContributio
38
38
 
39
39
  async resolve(request: AIVariableResolutionRequest, context: AIVariableContext): Promise<ResolvedAIVariable | undefined> {
40
40
  if (!ChatSessionContext.is(context) || request.variable.name !== CONTEXT_SUMMARY_VARIABLE.name) { return undefined; }
41
- const data = context.model.context.getVariables().filter(variable => variable.variable.isContextVariable)
41
+ const data = ChatSessionContext.getVariables(context).filter(variable => variable.variable.isContextVariable)
42
42
  .map(variable => ({
43
43
  type: variable.variable.name,
44
44
  // eslint-disable-next-line no-null/no-null