@theia/ai-chat 1.58.3 → 1.59.0-next.72

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 (128) hide show
  1. package/lib/browser/ai-chat-frontend-module.d.ts.map +1 -1
  2. package/lib/browser/ai-chat-frontend-module.js +16 -13
  3. package/lib/browser/ai-chat-frontend-module.js.map +1 -1
  4. package/lib/browser/ai-chat-preferences.d.ts +1 -0
  5. package/lib/browser/ai-chat-preferences.d.ts.map +1 -1
  6. package/lib/browser/ai-chat-preferences.js +12 -3
  7. package/lib/browser/ai-chat-preferences.js.map +1 -1
  8. package/lib/browser/change-set-file-element.d.ts +31 -6
  9. package/lib/browser/change-set-file-element.d.ts.map +1 -1
  10. package/lib/browser/change-set-file-element.js +108 -15
  11. package/lib/browser/change-set-file-element.js.map +1 -1
  12. package/lib/browser/change-set-file-resource.d.ts +40 -8
  13. package/lib/browser/change-set-file-resource.d.ts.map +1 -1
  14. package/lib/browser/change-set-file-resource.js +123 -37
  15. package/lib/browser/change-set-file-resource.js.map +1 -1
  16. package/lib/browser/change-set-file-service.d.ts +9 -3
  17. package/lib/browser/change-set-file-service.d.ts.map +1 -1
  18. package/lib/browser/change-set-file-service.js +35 -13
  19. package/lib/browser/change-set-file-service.js.map +1 -1
  20. package/lib/browser/change-set-variable.d.ts +11 -0
  21. package/lib/browser/change-set-variable.d.ts.map +1 -0
  22. package/lib/browser/change-set-variable.js +56 -0
  23. package/lib/browser/change-set-variable.js.map +1 -0
  24. package/lib/browser/context-file-variable-label-provider.d.ts +14 -0
  25. package/lib/browser/context-file-variable-label-provider.d.ts.map +1 -0
  26. package/lib/browser/context-file-variable-label-provider.js +63 -0
  27. package/lib/browser/context-file-variable-label-provider.js.map +1 -0
  28. package/lib/browser/context-variable-label-provider.d.ts +9 -0
  29. package/lib/browser/context-variable-label-provider.d.ts.map +1 -0
  30. package/lib/browser/context-variable-label-provider.js +55 -0
  31. package/lib/browser/context-variable-label-provider.js.map +1 -0
  32. package/lib/browser/file-chat-variable-contribution.d.ts +18 -0
  33. package/lib/browser/file-chat-variable-contribution.d.ts.map +1 -0
  34. package/lib/browser/file-chat-variable-contribution.js +135 -0
  35. package/lib/browser/file-chat-variable-contribution.js.map +1 -0
  36. package/lib/browser/frontend-chat-service.d.ts +10 -3
  37. package/lib/browser/frontend-chat-service.d.ts.map +1 -1
  38. package/lib/browser/frontend-chat-service.js +39 -19
  39. package/lib/browser/frontend-chat-service.js.map +1 -1
  40. package/lib/common/chat-agents.d.ts +54 -24
  41. package/lib/common/chat-agents.d.ts.map +1 -1
  42. package/lib/common/chat-agents.js +58 -20
  43. package/lib/common/chat-agents.js.map +1 -1
  44. package/lib/common/chat-history-entry.js +1 -1
  45. package/lib/common/chat-history-entry.js.map +1 -1
  46. package/lib/common/chat-model.d.ts +84 -36
  47. package/lib/common/chat-model.d.ts.map +1 -1
  48. package/lib/common/chat-model.js +142 -51
  49. package/lib/common/chat-model.js.map +1 -1
  50. package/lib/common/chat-service.d.ts +27 -10
  51. package/lib/common/chat-service.d.ts.map +1 -1
  52. package/lib/common/chat-service.js +80 -20
  53. package/lib/common/chat-service.js.map +1 -1
  54. package/lib/common/chat-string-utils.d.ts +3 -0
  55. package/lib/common/chat-string-utils.d.ts.map +1 -0
  56. package/lib/common/chat-string-utils.js +27 -0
  57. package/lib/common/chat-string-utils.js.map +1 -0
  58. package/lib/common/chat-tool-request-service.d.ts +5 -5
  59. package/lib/common/chat-tool-request-service.d.ts.map +1 -1
  60. package/lib/common/chat-tool-request-service.js.map +1 -1
  61. package/lib/common/context-details-variable.d.ts +9 -0
  62. package/lib/common/context-details-variable.d.ts.map +1 -0
  63. package/lib/common/context-details-variable.js +57 -0
  64. package/lib/common/context-details-variable.js.map +1 -0
  65. package/lib/common/context-summary-variable.d.ts +9 -0
  66. package/lib/common/context-summary-variable.d.ts.map +1 -0
  67. package/lib/common/context-summary-variable.js +57 -0
  68. package/lib/common/context-summary-variable.js.map +1 -0
  69. package/lib/common/context-variables.d.ts +4 -0
  70. package/lib/common/context-variables.d.ts.map +1 -0
  71. package/lib/common/context-variables.js +22 -0
  72. package/lib/common/context-variables.js.map +1 -0
  73. package/lib/common/custom-chat-agent.d.ts +6 -10
  74. package/lib/common/custom-chat-agent.d.ts.map +1 -1
  75. package/lib/common/custom-chat-agent.js +8 -11
  76. package/lib/common/custom-chat-agent.js.map +1 -1
  77. package/lib/common/index.d.ts +1 -3
  78. package/lib/common/index.d.ts.map +1 -1
  79. package/lib/common/index.js +1 -3
  80. package/lib/common/index.js.map +1 -1
  81. package/lib/common/parse-contents.d.ts +2 -2
  82. package/lib/common/parse-contents.d.ts.map +1 -1
  83. package/lib/common/parse-contents.js.map +1 -1
  84. package/lib/common/parse-contents.spec.d.ts.map +1 -1
  85. package/lib/common/parse-contents.spec.js.map +1 -1
  86. package/lib/common/response-content-matcher.d.ts +3 -3
  87. package/lib/common/response-content-matcher.d.ts.map +1 -1
  88. package/lib/common/response-content-matcher.js.map +1 -1
  89. package/package.json +12 -10
  90. package/src/browser/ai-chat-frontend-module.ts +20 -18
  91. package/src/browser/ai-chat-preferences.ts +13 -2
  92. package/src/browser/change-set-file-element.ts +109 -20
  93. package/src/browser/change-set-file-resource.ts +125 -39
  94. package/src/browser/change-set-file-service.ts +38 -16
  95. package/src/browser/change-set-variable.ts +54 -0
  96. package/src/browser/context-file-variable-label-provider.ts +62 -0
  97. package/src/browser/context-variable-label-provider.ts +56 -0
  98. package/src/browser/file-chat-variable-contribution.ts +143 -0
  99. package/src/browser/frontend-chat-service.ts +40 -26
  100. package/src/common/chat-agents.ts +87 -30
  101. package/src/common/chat-history-entry.ts +1 -1
  102. package/src/common/chat-model.ts +204 -70
  103. package/src/common/chat-service.ts +92 -24
  104. package/src/common/chat-string-utils.ts +23 -0
  105. package/src/common/chat-tool-request-service.ts +5 -5
  106. package/src/common/context-details-variable.ts +53 -0
  107. package/src/common/context-summary-variable.ts +53 -0
  108. package/src/common/context-variables.ts +19 -0
  109. package/src/common/custom-chat-agent.ts +9 -20
  110. package/src/common/index.ts +1 -3
  111. package/src/common/parse-contents.spec.ts +2 -2
  112. package/src/common/parse-contents.ts +2 -2
  113. package/src/common/response-content-matcher.ts +3 -3
  114. package/lib/common/command-chat-agents.d.ts +0 -33
  115. package/lib/common/command-chat-agents.d.ts.map +0 -1
  116. package/lib/common/command-chat-agents.js +0 -329
  117. package/lib/common/command-chat-agents.js.map +0 -1
  118. package/lib/common/orchestrator-chat-agent.d.ts +0 -22
  119. package/lib/common/orchestrator-chat-agent.d.ts.map +0 -1
  120. package/lib/common/orchestrator-chat-agent.js +0 -167
  121. package/lib/common/orchestrator-chat-agent.js.map +0 -1
  122. package/lib/common/universal-chat-agent.d.ts +0 -16
  123. package/lib/common/universal-chat-agent.d.ts.map +0 -1
  124. package/lib/common/universal-chat-agent.js +0 -109
  125. package/lib/common/universal-chat-agent.js.map +0 -1
  126. package/src/common/command-chat-agents.ts +0 -354
  127. package/src/common/orchestrator-chat-agent.ts +0 -179
  128. package/src/common/universal-chat-agent.ts +0 -117
@@ -19,22 +19,23 @@
19
19
  *--------------------------------------------------------------------------------------------*/
20
20
  // Partially copied from https://github.com/microsoft/vscode/blob/a2cab7255c0df424027be05d58e1b7b941f4ea60/src/vs/workbench/contrib/chat/common/chatService.ts
21
21
 
22
+ import { AIVariableResolutionRequest, AIVariableService, ResolvedAIContextVariable } from '@theia/ai-core';
23
+ import { Emitter, ILogger, generateUuid } from '@theia/core';
22
24
  import { inject, injectable, optional } from '@theia/core/shared/inversify';
25
+ import { Event } from '@theia/core/shared/vscode-languageserver-protocol';
26
+ import { ChatAgentService } from './chat-agent-service';
27
+ import { ChatAgent, ChatAgentLocation, ChatSessionContext } from './chat-agents';
23
28
  import {
24
29
  ChatModel,
25
- ChatModelImpl,
30
+ MutableChatModel,
26
31
  ChatRequest,
27
32
  ChatRequestModel,
28
33
  ChatResponseModel,
29
- ErrorChatResponseModelImpl,
34
+ ErrorChatResponseModel,
35
+ ChatContext,
30
36
  } from './chat-model';
31
- import { ChatAgentService } from './chat-agent-service';
32
- import { Emitter, ILogger, generateUuid } from '@theia/core';
33
37
  import { ChatRequestParser } from './chat-request-parser';
34
- import { ChatAgent, ChatAgentLocation } from './chat-agents';
35
- import { ParsedChatRequestAgentPart, ParsedChatRequestVariablePart, ParsedChatRequest } from './parsed-chat-request';
36
- import { AIVariableService } from '@theia/ai-core';
37
- import { Event } from '@theia/core/shared/vscode-languageserver-protocol';
38
+ import { ParsedChatRequest, ParsedChatRequestAgentPart, ParsedChatRequestVariablePart } from './parsed-chat-request';
38
39
 
39
40
  export interface ChatRequestInvocation {
40
41
  /**
@@ -56,6 +57,7 @@ export interface ChatSession {
56
57
  title?: string;
57
58
  model: ChatModel;
58
59
  isActive: boolean;
60
+ pinnedAgent?: ChatAgent;
59
61
  }
60
62
 
61
63
  export interface ActiveSessionChangedEvent {
@@ -67,18 +69,32 @@ export interface SessionOptions {
67
69
  focus?: boolean;
68
70
  }
69
71
 
72
+ /**
73
+ * The default chat agent to invoke
74
+ */
70
75
  export const DefaultChatAgentId = Symbol('DefaultChatAgentId');
71
76
  export interface DefaultChatAgentId {
72
77
  id: string;
73
78
  }
74
79
 
80
+ /**
81
+ * In case no fitting chat agent is available, this one will be used (if it is itself available)
82
+ */
83
+ export const FallbackChatAgentId = Symbol('FallbackChatAgentId');
84
+ export interface FallbackChatAgentId {
85
+ id: string;
86
+ }
87
+
88
+ export const PinChatAgent = Symbol('PinChatAgent');
89
+ export type PinChatAgent = boolean;
90
+
75
91
  export const ChatService = Symbol('ChatService');
76
92
  export interface ChatService {
77
93
  onActiveSessionChanged: Event<ActiveSessionChangedEvent>
78
94
 
79
95
  getSession(id: string): ChatSession | undefined;
80
96
  getSessions(): ChatSession[];
81
- createSession(location?: ChatAgentLocation, options?: SessionOptions): ChatSession;
97
+ createSession(location?: ChatAgentLocation, options?: SessionOptions, pinnedAgent?: ChatAgent): ChatSession;
82
98
  deleteSession(sessionId: string): void;
83
99
  setActiveSession(sessionId: string, options?: SessionOptions): void;
84
100
 
@@ -94,7 +110,7 @@ export interface ChatService {
94
110
  }
95
111
 
96
112
  interface ChatSessionInternal extends ChatSession {
97
- model: ChatModelImpl;
113
+ model: MutableChatModel;
98
114
  }
99
115
 
100
116
  @injectable()
@@ -108,6 +124,12 @@ export class ChatServiceImpl implements ChatService {
108
124
  @inject(DefaultChatAgentId) @optional()
109
125
  protected defaultChatAgentId: DefaultChatAgentId | undefined;
110
126
 
127
+ @inject(FallbackChatAgentId) @optional()
128
+ protected fallbackChatAgentId: FallbackChatAgentId | undefined;
129
+
130
+ @inject(PinChatAgent) @optional()
131
+ protected pinChatAgent: boolean | undefined;
132
+
111
133
  @inject(ChatRequestParser)
112
134
  protected chatRequestParser: ChatRequestParser;
113
135
 
@@ -127,12 +149,13 @@ export class ChatServiceImpl implements ChatService {
127
149
  return this._sessions.find(session => session.id === id);
128
150
  }
129
151
 
130
- createSession(location = ChatAgentLocation.Panel, options?: SessionOptions): ChatSession {
131
- const model = new ChatModelImpl(location);
152
+ createSession(location = ChatAgentLocation.Panel, options?: SessionOptions, pinnedAgent?: ChatAgent): ChatSession {
153
+ const model = new MutableChatModel(location);
132
154
  const session: ChatSessionInternal = {
133
155
  id: model.id,
134
156
  model,
135
- isActive: true
157
+ isActive: true,
158
+ pinnedAgent
136
159
  };
137
160
  this._sessions.push(session);
138
161
  this.setActiveSession(session.id, options);
@@ -140,11 +163,15 @@ export class ChatServiceImpl implements ChatService {
140
163
  }
141
164
 
142
165
  deleteSession(sessionId: string): void {
166
+ const sessionIndex = this._sessions.findIndex(candidate => candidate.id === sessionId);
167
+ if (sessionIndex === -1) { return; }
168
+ const session = this._sessions[sessionIndex];
143
169
  // If the removed session is the active one, set the newest one as active
144
- if (this.getSession(sessionId)?.isActive) {
170
+ if (session.isActive) {
145
171
  this.setActiveSession(this._sessions[this._sessions.length - 1]?.id);
146
172
  }
147
- this._sessions = this._sessions.filter(item => item.id !== sessionId);
173
+ session.model.dispose();
174
+ this._sessions.splice(sessionIndex, 1);
148
175
  }
149
176
 
150
177
  setActiveSession(sessionId: string | undefined, options?: SessionOptions): void {
@@ -156,7 +183,7 @@ export class ChatServiceImpl implements ChatService {
156
183
 
157
184
  async sendRequest(
158
185
  sessionId: string,
159
- request: ChatRequest
186
+ request: ChatRequest,
160
187
  ): Promise<ChatRequestInvocation | undefined> {
161
188
  const session = this.getSession(sessionId);
162
189
  if (!session) {
@@ -165,25 +192,29 @@ export class ChatServiceImpl implements ChatService {
165
192
  session.title = request.text;
166
193
 
167
194
  const parsedRequest = this.chatRequestParser.parseChatRequest(request, session.model.location);
195
+ const agent = this.getAgent(parsedRequest, session);
168
196
 
169
- const agent = this.getAgent(parsedRequest);
170
197
  if (agent === undefined) {
171
198
  const error = 'No ChatAgents available to handle request!';
172
199
  this.logger.error(error);
173
- const chatResponseModel = new ErrorChatResponseModelImpl(generateUuid(), new Error(error));
200
+ const chatResponseModel = new ErrorChatResponseModel(generateUuid(), new Error(error));
174
201
  return {
175
202
  requestCompleted: Promise.reject(error),
176
203
  responseCreated: Promise.reject(error),
177
204
  responseCompleted: Promise.resolve(chatResponseModel),
178
205
  };
179
206
  }
180
- const requestModel = session.model.addRequest(parsedRequest, agent?.id);
207
+
208
+ const resolutionContext: ChatSessionContext = { model: session.model };
209
+ const resolvedContext = await this.resolveChatContext(session.model.context.getVariables(), resolutionContext);
210
+ const requestModel = session.model.addRequest(parsedRequest, agent?.id, resolvedContext);
211
+ resolutionContext.request = requestModel;
181
212
 
182
213
  for (const part of parsedRequest.parts) {
183
214
  if (part instanceof ParsedChatRequestVariablePart) {
184
215
  const resolvedVariable = await this.variableService.resolveVariable(
185
216
  { variable: part.variableName, arg: part.variableArg },
186
- { request, model: session }
217
+ resolutionContext
187
218
  );
188
219
  if (resolvedVariable) {
189
220
  part.resolution = resolvedVariable;
@@ -224,18 +255,55 @@ export class ChatServiceImpl implements ChatService {
224
255
  return invocation;
225
256
  }
226
257
 
258
+ protected async resolveChatContext(
259
+ resolutionRequests: readonly AIVariableResolutionRequest[],
260
+ context: ChatSessionContext,
261
+ ): Promise<ChatContext> {
262
+ const resolvedVariables = await Promise.all(
263
+ resolutionRequests.map(async contextVariable => {
264
+ const resolvedVariable = await this.variableService.resolveVariable(contextVariable, context);
265
+ if (ResolvedAIContextVariable.is(resolvedVariable)) {
266
+ return resolvedVariable;
267
+ }
268
+ return undefined;
269
+ })
270
+ ).then(results => results.filter((result): result is ResolvedAIContextVariable => result !== undefined));
271
+ return { variables: resolvedVariables };
272
+ }
273
+
227
274
  async cancelRequest(sessionId: string, requestId: string): Promise<void> {
228
275
  return this.getSession(sessionId)?.model.getRequest(requestId)?.response.cancel();
229
276
  }
230
277
 
231
- protected getAgent(parsedRequest: ParsedChatRequest): ChatAgent | undefined {
278
+ protected getAgent(parsedRequest: ParsedChatRequest, session: ChatSession): ChatAgent | undefined {
279
+ let agent = this.initialAgentSelection(parsedRequest);
280
+ if (this.pinChatAgent === false) {
281
+ return agent;
282
+ }
283
+ if (!session.pinnedAgent && agent && agent.id !== this.defaultChatAgentId?.id) {
284
+ session.pinnedAgent = agent;
285
+ } else if (session.pinnedAgent && this.getMentionedAgent(parsedRequest) === undefined) {
286
+ agent = session.pinnedAgent;
287
+ }
288
+ return agent;
289
+ }
290
+
291
+ protected initialAgentSelection(parsedRequest: ParsedChatRequest): ChatAgent | undefined {
232
292
  const agentPart = this.getMentionedAgent(parsedRequest);
233
293
  if (agentPart) {
234
294
  return this.chatAgentService.getAgent(agentPart.agentId);
235
295
  }
296
+ let chatAgent = undefined;
236
297
  if (this.defaultChatAgentId) {
237
- return this.chatAgentService.getAgent(this.defaultChatAgentId.id);
298
+ chatAgent = this.chatAgentService.getAgent(this.defaultChatAgentId.id);
299
+ }
300
+ if (!chatAgent && this.fallbackChatAgentId) {
301
+ chatAgent = this.chatAgentService.getAgent(this.fallbackChatAgentId.id);
302
+ }
303
+ if (chatAgent) {
304
+ return chatAgent;
238
305
  }
306
+ this.logger.warn('Neither the default chat agent nor the fallback chat agent are configured or available. Falling back to the first registered agent');
239
307
  return this.chatAgentService.getAgents()[0] ?? undefined;
240
308
  }
241
309
 
@@ -244,10 +312,10 @@ export class ChatServiceImpl implements ChatService {
244
312
  }
245
313
 
246
314
  deleteChangeSet(sessionId: string): void {
247
- this.getSession(sessionId)?.model.setChangeSet(undefined);
315
+ this.getSession(sessionId)?.model.removeChangeSet();
248
316
  }
249
317
 
250
318
  deleteChangeSetElement(sessionId: string, index: number): void {
251
- this.getSession(sessionId)?.model.changeSet?.removeElement(index);
319
+ this.getSession(sessionId)?.model.changeSet?.removeElements(index);
252
320
  }
253
321
  }
@@ -0,0 +1,23 @@
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
+ export function stringJsonCodeBlock(input: string): string {
18
+ return `\`\`\`json\n${input}\n\`\`\``;
19
+ }
20
+
21
+ export function dataToJsonCodeBlock(input: unknown): string {
22
+ return stringJsonCodeBlock(JSON.stringify(input, undefined, 2));
23
+ }
@@ -16,12 +16,12 @@
16
16
 
17
17
  import { ToolRequest } from '@theia/ai-core';
18
18
  import { injectable } from '@theia/core/shared/inversify';
19
- import { ChatRequestModelImpl } from './chat-model';
19
+ import { MutableChatRequestModel } from './chat-model';
20
20
 
21
21
  export interface ChatToolRequest extends ToolRequest {
22
22
  handler: (
23
23
  arg_string: string,
24
- context: ChatRequestModelImpl,
24
+ context: MutableChatRequestModel,
25
25
  ) => Promise<unknown>;
26
26
  }
27
27
 
@@ -34,7 +34,7 @@ export interface ChatToolRequest extends ToolRequest {
34
34
  @injectable()
35
35
  export class ChatToolRequestService {
36
36
 
37
- getChatToolRequests(request: ChatRequestModelImpl): ChatToolRequest[] {
37
+ getChatToolRequests(request: MutableChatRequestModel): ChatToolRequest[] {
38
38
  const toolRequests = request.message.toolRequests.size > 0 ? [...request.message.toolRequests.values()] : undefined;
39
39
  if (!toolRequests) {
40
40
  return [];
@@ -42,14 +42,14 @@ export class ChatToolRequestService {
42
42
  return this.toChatToolRequests(toolRequests, request);
43
43
  }
44
44
 
45
- toChatToolRequests(toolRequests: ToolRequest[] | undefined, request: ChatRequestModelImpl): ChatToolRequest[] {
45
+ toChatToolRequests(toolRequests: ToolRequest[] | undefined, request: MutableChatRequestModel): ChatToolRequest[] {
46
46
  if (!toolRequests) {
47
47
  return [];
48
48
  }
49
49
  return toolRequests.map(toolRequest => this.toChatToolRequest(toolRequest, request));
50
50
  }
51
51
 
52
- protected toChatToolRequest(toolRequest: ToolRequest, request: ChatRequestModelImpl): ChatToolRequest {
52
+ protected toChatToolRequest(toolRequest: ToolRequest, request: MutableChatRequestModel): ChatToolRequest {
53
53
  return {
54
54
  ...toolRequest,
55
55
  handler: async (arg_string: string) => toolRequest.handler(arg_string, request)
@@ -0,0 +1,53 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 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 { MaybePromise, nls } from '@theia/core';
18
+ import { injectable } from '@theia/core/shared/inversify';
19
+ import { AIVariable, ResolvedAIVariable, AIVariableContribution, AIVariableResolver, AIVariableService, AIVariableResolutionRequest, AIVariableContext } from '@theia/ai-core';
20
+ import { dataToJsonCodeBlock } from './chat-string-utils';
21
+ import { ChatSessionContext } from './chat-agents';
22
+ import { CHAT_CONTEXT_DETAILS_VARIABLE_ID } from './context-variables';
23
+
24
+ export const CONTEXT_DETAILS_VARIABLE: AIVariable = {
25
+ id: CHAT_CONTEXT_DETAILS_VARIABLE_ID,
26
+ description: nls.localize('theia/ai/core/contextDetailsVariable/description', 'Provides full text values and descriptions for all context elements.'),
27
+ name: CHAT_CONTEXT_DETAILS_VARIABLE_ID,
28
+ };
29
+
30
+ @injectable()
31
+ export class ContextDetailsVariableContribution implements AIVariableContribution, AIVariableResolver {
32
+ registerVariables(service: AIVariableService): void {
33
+ service.registerResolver(CONTEXT_DETAILS_VARIABLE, this);
34
+ }
35
+
36
+ canResolve(request: AIVariableResolutionRequest, context: AIVariableContext): MaybePromise<number> {
37
+ return request.variable.name === CONTEXT_DETAILS_VARIABLE.name ? 50 : 0;
38
+ }
39
+
40
+ async resolve(request: AIVariableResolutionRequest, context: AIVariableContext): Promise<ResolvedAIVariable | undefined> {
41
+ /** By expecting context.request, we're assuming that this variable will not be resolved until the context has been resolved. */
42
+ if (!ChatSessionContext.is(context) || request.variable.name !== CONTEXT_DETAILS_VARIABLE.name || !context.request) { return undefined; }
43
+ const data = context.request.context.variables.map(variable => ({
44
+ type: variable.variable.name,
45
+ ref: variable.value,
46
+ content: variable.contextValue
47
+ }));
48
+ return {
49
+ variable: CONTEXT_DETAILS_VARIABLE,
50
+ value: dataToJsonCodeBlock(data)
51
+ };
52
+ }
53
+ }
@@ -0,0 +1,53 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 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 { MaybePromise, nls } from '@theia/core';
18
+ import { injectable } from '@theia/core/shared/inversify';
19
+ import { AIVariable, ResolvedAIVariable, AIVariableContribution, AIVariableResolver, AIVariableService, AIVariableResolutionRequest, AIVariableContext } from '@theia/ai-core';
20
+ import { dataToJsonCodeBlock } from './chat-string-utils';
21
+ import { ChatSessionContext } from './chat-agents';
22
+
23
+ export const CONTEXT_SUMMARY_VARIABLE: AIVariable = {
24
+ id: 'contextSummary',
25
+ description: nls.localize('theia/ai/core/contextSummaryVariable/description', 'Describes files in the context for a given session.'),
26
+ name: 'contextSummary',
27
+ };
28
+
29
+ @injectable()
30
+ export class ContextSummaryVariableContribution implements AIVariableContribution, AIVariableResolver {
31
+ registerVariables(service: AIVariableService): void {
32
+ service.registerResolver(CONTEXT_SUMMARY_VARIABLE, this);
33
+ }
34
+
35
+ canResolve(request: AIVariableResolutionRequest, context: AIVariableContext): MaybePromise<number> {
36
+ return request.variable.name === CONTEXT_SUMMARY_VARIABLE.name ? 50 : 0;
37
+ }
38
+
39
+ async resolve(request: AIVariableResolutionRequest, context: AIVariableContext): Promise<ResolvedAIVariable | undefined> {
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)
42
+ .map(variable => ({
43
+ type: variable.variable.name,
44
+ // eslint-disable-next-line no-null/no-null
45
+ instanceData: variable.arg || null,
46
+ contextElementId: variable.variable.id + variable.arg
47
+ }));
48
+ return {
49
+ variable: CONTEXT_SUMMARY_VARIABLE,
50
+ value: dataToJsonCodeBlock(data)
51
+ };
52
+ }
53
+ }
@@ -0,0 +1,19 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 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
+ export const CHAT_CONTEXT_VARIABLE_ID = 'contextSummary';
18
+ export const CHAT_CONTEXT_DETAILS_VARIABLE_ID = 'contextDetails';
19
+ export const CHANGE_SET_SUMMARY_VARIABLE_ID = 'changeSetSummary';
@@ -14,31 +14,20 @@
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, PromptTemplate } from '@theia/ai-core';
18
- import { AbstractStreamParsingChatAgent, ChatAgent, SystemMessageDescription } from './chat-agents';
17
+ import { LanguageModelRequirement } from '@theia/ai-core';
18
+ import { AbstractStreamParsingChatAgent } from './chat-agents';
19
19
  import { injectable } from '@theia/core/shared/inversify';
20
20
 
21
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
- }
22
+ export class CustomChatAgent extends AbstractStreamParsingChatAgent {
23
+ id: string = 'CustomChatAgent';
24
+ name: string = 'CustomChatAgent';
25
+ languageModelRequirements: LanguageModelRequirement[] = [{ purpose: 'chat' }];
26
+ protected defaultLanguageModelPurpose: string = 'chat';
40
27
 
41
28
  set prompt(prompt: string) {
29
+ // the name is dynamic, so we set the propmptId here
30
+ this.systemPromptId = `${this.name}_prompt`;
42
31
  this.promptTemplates.push({ id: `${this.name}_prompt`, template: prompt });
43
32
  }
44
33
  }
@@ -19,8 +19,6 @@ export * from './chat-model';
19
19
  export * from './chat-model-util';
20
20
  export * from './chat-request-parser';
21
21
  export * from './chat-service';
22
- export * from './command-chat-agents';
23
22
  export * from './custom-chat-agent';
24
23
  export * from './parsed-chat-request';
25
- export * from './orchestrator-chat-agent';
26
- export * from './universal-chat-agent';
24
+ export * from './context-variables';
@@ -15,7 +15,7 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { expect } from 'chai';
18
- import { ChatRequestModelImpl, ChatResponseContent, CodeChatResponseContentImpl, MarkdownChatResponseContentImpl } from './chat-model';
18
+ import { MutableChatRequestModel, ChatResponseContent, CodeChatResponseContentImpl, MarkdownChatResponseContentImpl } from './chat-model';
19
19
  import { parseContents } from './parse-contents';
20
20
  import { CodeContentMatcher, ResponseContentMatcher } from './response-content-matcher';
21
21
 
@@ -33,7 +33,7 @@ export const CommandContentMatcher: ResponseContentMatcher = {
33
33
  }
34
34
  };
35
35
 
36
- const fakeRequest = {} as ChatRequestModelImpl;
36
+ const fakeRequest = {} as MutableChatRequestModel;
37
37
 
38
38
  describe('parseContents', () => {
39
39
  it('should parse code content', () => {
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  */
16
- import { ChatRequestModelImpl, ChatResponseContent } from './chat-model';
16
+ import { MutableChatRequestModel, ChatResponseContent } from './chat-model';
17
17
  import { CodeContentMatcher, MarkdownContentFactory, ResponseContentFactory, ResponseContentMatcher } from './response-content-matcher';
18
18
 
19
19
  interface Match {
@@ -24,7 +24,7 @@ interface Match {
24
24
 
25
25
  export function parseContents(
26
26
  text: string,
27
- request: ChatRequestModelImpl,
27
+ request: MutableChatRequestModel,
28
28
  contentMatchers: ResponseContentMatcher[] = [CodeContentMatcher],
29
29
  defaultContentFactory: ResponseContentFactory = MarkdownContentFactory
30
30
  ): ChatResponseContent[] {
@@ -14,14 +14,14 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  */
16
16
  import {
17
- ChatRequestModelImpl,
17
+ MutableChatRequestModel,
18
18
  ChatResponseContent,
19
19
  CodeChatResponseContentImpl,
20
20
  MarkdownChatResponseContentImpl
21
21
  } from './chat-model';
22
22
  import { injectable } from '@theia/core/shared/inversify';
23
23
 
24
- export type ResponseContentFactory = (content: string, request: ChatRequestModelImpl) => ChatResponseContent;
24
+ export type ResponseContentFactory = (content: string, request: MutableChatRequestModel) => ChatResponseContent;
25
25
 
26
26
  export const MarkdownContentFactory: ResponseContentFactory = (content: string) =>
27
27
  new MarkdownChatResponseContentImpl(content);
@@ -34,7 +34,7 @@ export const MarkdownContentFactory: ResponseContentFactory = (content: string)
34
34
  */
35
35
  @injectable()
36
36
  export class DefaultResponseContentFactory {
37
- create(content: string, request: ChatRequestModelImpl): ChatResponseContent {
37
+ create(content: string, request: MutableChatRequestModel): ChatResponseContent {
38
38
  return MarkdownContentFactory(content, request);
39
39
  }
40
40
  }
@@ -1,33 +0,0 @@
1
- import { AbstractTextToModelParsingChatAgent, ChatAgent, SystemMessageDescription } from './chat-agents';
2
- import { PromptTemplate, AgentSpecificVariables } from '@theia/ai-core';
3
- import { ChatRequestModelImpl, ChatResponseContent } from './chat-model';
4
- import { CommandRegistry, MessageService } from '@theia/core';
5
- export declare const commandTemplate: PromptTemplate;
6
- interface ParsedCommand {
7
- type: 'theia-command' | 'custom-handler' | 'no-command';
8
- commandId: string;
9
- arguments?: string[];
10
- message?: string;
11
- }
12
- export declare class CommandChatAgent extends AbstractTextToModelParsingChatAgent<ParsedCommand> implements ChatAgent {
13
- protected commandRegistry: CommandRegistry;
14
- protected messageService: MessageService;
15
- readonly name: string;
16
- readonly description: string;
17
- readonly variables: string[];
18
- readonly promptTemplates: PromptTemplate[];
19
- readonly functions: string[];
20
- readonly agentSpecificVariables: AgentSpecificVariables[];
21
- constructor();
22
- protected getSystemMessageDescription(): Promise<SystemMessageDescription | undefined>;
23
- /**
24
- * @param text the text received from the language model
25
- * @returns the parsed command if the text contained a valid command.
26
- * If there was no json in the text, return a no-command response.
27
- */
28
- protected parseTextResponse(text: string): Promise<ParsedCommand>;
29
- protected createResponseContent(parsedCommand: ParsedCommand, request: ChatRequestModelImpl): ChatResponseContent;
30
- protected commandCallback(...commandArgs: unknown[]): Promise<void>;
31
- }
32
- export {};
33
- //# sourceMappingURL=command-chat-agents.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"command-chat-agents.d.ts","sourceRoot":"","sources":["../../src/common/command-chat-agents.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,mCAAmC,EAAE,SAAS,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EACH,cAAc,EACd,sBAAsB,EACzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACH,oBAAoB,EACpB,mBAAmB,EAKtB,MAAM,cAAc,CAAC;AACtB,OAAO,EACH,eAAe,EACf,cAAc,EAEjB,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,eAAe,EAAE,cA8M5B,CAAC;AAEH,UAAU,aAAa;IACnB,IAAI,EAAE,eAAe,GAAG,gBAAgB,GAAG,YAAY,CAAA;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBACa,gBAAiB,SAAQ,mCAAmC,CAAC,aAAa,CAAE,YAAW,SAAS;IAEzG,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAE3C,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,CAAC,eAAe,EAAE,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB,EAAE,CAAC;;cAqB1C,2BAA2B,IAAI,OAAO,CAAC,wBAAwB,GAAG,SAAS,CAAC;IAc5F;;;;OAIG;cACa,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAUvE,SAAS,CAAC,qBAAqB,CAAC,aAAa,EAAE,aAAa,EAAE,OAAO,EAAE,oBAAoB,GAAG,mBAAmB;cAqCjG,eAAe,CAAC,GAAG,WAAW,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAI5E"}