@theia/ai-chat 1.66.0-next.44 → 1.66.0-next.73
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/agent-delegation-tool.d.ts.map +1 -1
- package/lib/browser/agent-delegation-tool.js +4 -2
- package/lib/browser/agent-delegation-tool.js.map +1 -1
- package/lib/browser/ai-chat-frontend-module.d.ts.map +1 -1
- package/lib/browser/ai-chat-frontend-module.js +15 -0
- package/lib/browser/ai-chat-frontend-module.js.map +1 -1
- package/lib/browser/change-set-file-element-deserializer.d.ts +7 -0
- package/lib/browser/change-set-file-element-deserializer.d.ts.map +1 -0
- package/lib/browser/change-set-file-element-deserializer.js +61 -0
- package/lib/browser/change-set-file-element-deserializer.js.map +1 -0
- package/lib/browser/change-set-file-element.d.ts +3 -1
- package/lib/browser/change-set-file-element.d.ts.map +1 -1
- package/lib/browser/change-set-file-element.js +23 -2
- package/lib/browser/change-set-file-element.js.map +1 -1
- package/lib/browser/change-set-file-service.d.ts.map +1 -1
- package/lib/browser/change-set-file-service.js +2 -2
- package/lib/browser/change-set-file-service.js.map +1 -1
- package/lib/browser/chat-session-store-impl.d.ts +36 -0
- package/lib/browser/chat-session-store-impl.d.ts.map +1 -0
- package/lib/browser/chat-session-store-impl.js +287 -0
- package/lib/browser/chat-session-store-impl.js.map +1 -0
- package/lib/browser/file-chat-variable-contribution.d.ts.map +1 -1
- package/lib/browser/file-chat-variable-contribution.js +1 -1
- package/lib/browser/file-chat-variable-contribution.js.map +1 -1
- package/lib/browser/image-context-variable-contribution.js +1 -1
- package/lib/browser/image-context-variable-contribution.js.map +1 -1
- package/lib/browser/task-context-service.d.ts.map +1 -1
- package/lib/browser/task-context-service.js +8 -2
- package/lib/browser/task-context-service.js.map +1 -1
- package/lib/browser/task-context-variable.d.ts.map +1 -1
- package/lib/browser/task-context-variable.js +7 -3
- package/lib/browser/task-context-variable.js.map +1 -1
- package/lib/common/change-set-element-deserializer.d.ts +30 -0
- package/lib/common/change-set-element-deserializer.d.ts.map +1 -0
- package/lib/common/change-set-element-deserializer.js +81 -0
- package/lib/common/change-set-element-deserializer.js.map +1 -0
- package/lib/common/change-set.d.ts +7 -0
- package/lib/common/change-set.d.ts.map +1 -1
- package/lib/common/change-set.js +1 -1
- package/lib/common/change-set.js.map +1 -1
- package/lib/common/chat-agents-variable-contribution.d.ts.map +1 -1
- package/lib/common/chat-agents-variable-contribution.js +17 -1
- package/lib/common/chat-agents-variable-contribution.js.map +1 -1
- package/lib/common/chat-agents.d.ts.map +1 -1
- package/lib/common/chat-agents.js +3 -3
- package/lib/common/chat-agents.js.map +1 -1
- package/lib/common/chat-auto-save.spec.d.ts +2 -0
- package/lib/common/chat-auto-save.spec.d.ts.map +1 -0
- package/lib/common/chat-auto-save.spec.js +304 -0
- package/lib/common/chat-auto-save.spec.js.map +1 -0
- package/lib/common/chat-content-deserializer.d.ts +161 -0
- package/lib/common/chat-content-deserializer.d.ts.map +1 -0
- package/lib/common/chat-content-deserializer.js +166 -0
- package/lib/common/chat-content-deserializer.js.map +1 -0
- package/lib/common/chat-content-deserializer.spec.d.ts +2 -0
- package/lib/common/chat-content-deserializer.spec.d.ts.map +1 -0
- package/lib/common/chat-content-deserializer.spec.js +307 -0
- package/lib/common/chat-content-deserializer.spec.js.map +1 -0
- package/lib/common/chat-model-serialization.d.ts +110 -0
- package/lib/common/chat-model-serialization.d.ts.map +1 -0
- package/lib/common/chat-model-serialization.js +20 -0
- package/lib/common/chat-model-serialization.js.map +1 -0
- package/lib/common/chat-model-serialization.spec.d.ts +2 -0
- package/lib/common/chat-model-serialization.spec.d.ts.map +1 -0
- package/lib/common/chat-model-serialization.spec.js +278 -0
- package/lib/common/chat-model-serialization.spec.js.map +1 -0
- package/lib/common/chat-model.d.ts +163 -14
- package/lib/common/chat-model.d.ts.map +1 -1
- package/lib/common/chat-model.js +444 -36
- package/lib/common/chat-model.js.map +1 -1
- package/lib/common/chat-request-parser.d.ts +8 -1
- package/lib/common/chat-request-parser.d.ts.map +1 -1
- package/lib/common/chat-request-parser.js +29 -1
- package/lib/common/chat-request-parser.js.map +1 -1
- package/lib/common/chat-request-parser.spec.js +51 -0
- package/lib/common/chat-request-parser.spec.js.map +1 -1
- package/lib/common/chat-service-deletion.spec.d.ts +2 -0
- package/lib/common/chat-service-deletion.spec.d.ts.map +1 -0
- package/lib/common/chat-service-deletion.spec.js +221 -0
- package/lib/common/chat-service-deletion.spec.js.map +1 -0
- package/lib/common/chat-service.d.ts +30 -2
- package/lib/common/chat-service.d.ts.map +1 -1
- package/lib/common/chat-service.js +182 -10
- package/lib/common/chat-service.js.map +1 -1
- package/lib/common/chat-session-naming-service.d.ts.map +1 -1
- package/lib/common/chat-session-naming-service.js +11 -3
- package/lib/common/chat-session-naming-service.js.map +1 -1
- package/lib/common/chat-session-store.d.ts +43 -0
- package/lib/common/chat-session-store.d.ts.map +1 -0
- package/lib/common/chat-session-store.js +20 -0
- package/lib/common/chat-session-store.js.map +1 -0
- package/lib/common/chat-session-summary-agent-prompt.js +1 -1
- package/lib/common/chat-session-summary-agent-prompt.js.map +1 -1
- package/lib/common/chat-session-summary-agent.d.ts.map +1 -1
- package/lib/common/chat-session-summary-agent.js +2 -1
- package/lib/common/chat-session-summary-agent.js.map +1 -1
- package/lib/common/chat-tool-preferences.js +1 -1
- package/lib/common/chat-tool-preferences.js.map +1 -1
- package/lib/common/image-context-variable.d.ts.map +1 -1
- package/lib/common/image-context-variable.js +21 -6
- package/lib/common/image-context-variable.js.map +1 -1
- package/lib/common/index.d.ts +3 -0
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +3 -0
- package/lib/common/index.js.map +1 -1
- package/package.json +9 -9
- package/src/browser/agent-delegation-tool.ts +4 -2
- package/src/browser/ai-chat-frontend-module.ts +27 -0
- package/src/browser/change-set-file-element-deserializer.ts +62 -0
- package/src/browser/change-set-file-element.ts +29 -4
- package/src/browser/change-set-file-service.ts +3 -3
- package/src/browser/chat-session-store-impl.ts +326 -0
- package/src/browser/file-chat-variable-contribution.ts +2 -2
- package/src/browser/image-context-variable-contribution.ts +1 -1
- package/src/browser/task-context-service.ts +9 -3
- package/src/browser/task-context-variable.ts +8 -3
- package/src/common/change-set-element-deserializer.ts +90 -0
- package/src/common/change-set.ts +10 -2
- package/src/common/chat-agents-variable-contribution.ts +2 -2
- package/src/common/chat-agents.ts +4 -4
- package/src/common/chat-auto-save.spec.ts +372 -0
- package/src/common/chat-content-deserializer.spec.ts +375 -0
- package/src/common/chat-content-deserializer.ts +327 -0
- package/src/common/chat-model-serialization.spec.ts +343 -0
- package/src/common/chat-model-serialization.ts +133 -0
- package/src/common/chat-model.ts +644 -41
- package/src/common/chat-request-parser.spec.ts +61 -0
- package/src/common/chat-request-parser.ts +40 -1
- package/src/common/chat-service-deletion.spec.ts +269 -0
- package/src/common/chat-service.ts +227 -10
- package/src/common/chat-session-naming-service.ts +12 -4
- package/src/common/chat-session-store.ts +63 -0
- package/src/common/chat-session-summary-agent-prompt.ts +1 -1
- package/src/common/chat-session-summary-agent.ts +2 -1
- package/src/common/chat-tool-preferences.ts +1 -2
- package/src/common/image-context-variable.ts +21 -6
- package/src/common/index.ts +3 -0
|
@@ -27,6 +27,8 @@ import { Event } from '@theia/core/shared/vscode-languageserver-protocol';
|
|
|
27
27
|
import { ChatAgentService } from './chat-agent-service';
|
|
28
28
|
import { ChatAgent, ChatAgentLocation, ChatSessionContext } from './chat-agents';
|
|
29
29
|
import {
|
|
30
|
+
ChangeSetElement,
|
|
31
|
+
ChangeSetImpl,
|
|
30
32
|
ChatContext,
|
|
31
33
|
ChatModel,
|
|
32
34
|
ChatRequest,
|
|
@@ -39,6 +41,11 @@ import {
|
|
|
39
41
|
import { ChatRequestParser } from './chat-request-parser';
|
|
40
42
|
import { ChatSessionNamingService } from './chat-session-naming-service';
|
|
41
43
|
import { ParsedChatRequest, ParsedChatRequestAgentPart } from './parsed-chat-request';
|
|
44
|
+
import { ChatSessionIndex, ChatSessionStore } from './chat-session-store';
|
|
45
|
+
import { ChatContentDeserializerRegistry } from './chat-content-deserializer';
|
|
46
|
+
import { ChangeSetDeserializationContext, ChangeSetElementDeserializerRegistry } from './change-set-element-deserializer';
|
|
47
|
+
import { SerializableChangeSetElement, SerializedChatModel } from './chat-model-serialization';
|
|
48
|
+
import debounce = require('@theia/core/shared/lodash.debounce');
|
|
42
49
|
|
|
43
50
|
export interface ChatRequestInvocation {
|
|
44
51
|
/**
|
|
@@ -126,7 +133,7 @@ export interface ChatService {
|
|
|
126
133
|
getSession(id: string): ChatSession | undefined;
|
|
127
134
|
getSessions(): ChatSession[];
|
|
128
135
|
createSession(location?: ChatAgentLocation, options?: SessionOptions, pinnedAgent?: ChatAgent): ChatSession;
|
|
129
|
-
deleteSession(sessionId: string): void
|
|
136
|
+
deleteSession(sessionId: string): Promise<void>;
|
|
130
137
|
getActiveSession(): ChatSession | undefined;
|
|
131
138
|
setActiveSession(sessionId: string, options?: SessionOptions): void;
|
|
132
139
|
|
|
@@ -141,6 +148,15 @@ export interface ChatService {
|
|
|
141
148
|
cancelRequest(sessionId: string, requestId: string): Promise<void>;
|
|
142
149
|
|
|
143
150
|
getAgent(parsedRequest: ParsedChatRequest, session: ChatSession): ChatAgent | undefined;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Get an existing session or restore from storage
|
|
154
|
+
*/
|
|
155
|
+
getOrRestoreSession(sessionId: string): Promise<ChatSession | undefined>;
|
|
156
|
+
/**
|
|
157
|
+
* Get all persisted session metadata
|
|
158
|
+
*/
|
|
159
|
+
getPersistedSessions(): Promise<ChatSessionIndex>;
|
|
144
160
|
}
|
|
145
161
|
|
|
146
162
|
interface ChatSessionInternal extends ChatSession {
|
|
@@ -176,6 +192,15 @@ export class ChatServiceImpl implements ChatService {
|
|
|
176
192
|
@inject(ILogger)
|
|
177
193
|
protected logger: ILogger;
|
|
178
194
|
|
|
195
|
+
@inject(ChatSessionStore) @optional()
|
|
196
|
+
protected sessionStore: ChatSessionStore | undefined;
|
|
197
|
+
|
|
198
|
+
@inject(ChatContentDeserializerRegistry)
|
|
199
|
+
protected deserializerRegistry: ChatContentDeserializerRegistry;
|
|
200
|
+
|
|
201
|
+
@inject(ChangeSetElementDeserializerRegistry)
|
|
202
|
+
protected changeSetElementDeserializerRegistry: ChangeSetElementDeserializerRegistry;
|
|
203
|
+
|
|
179
204
|
protected _sessions: ChatSessionInternal[] = [];
|
|
180
205
|
|
|
181
206
|
getSessions(): ChatSessionInternal[] {
|
|
@@ -190,27 +215,41 @@ export class ChatServiceImpl implements ChatService {
|
|
|
190
215
|
const model = new MutableChatModel(location);
|
|
191
216
|
const session: ChatSessionInternal = {
|
|
192
217
|
id: model.id,
|
|
218
|
+
lastInteraction: new Date(),
|
|
193
219
|
model,
|
|
194
220
|
isActive: true,
|
|
195
221
|
pinnedAgent
|
|
196
222
|
};
|
|
197
223
|
this._sessions.push(session);
|
|
224
|
+
this.setupAutoSaveForSession(session);
|
|
198
225
|
this.setActiveSession(session.id, options);
|
|
199
226
|
this.onSessionEventEmitter.fire({ type: 'created', sessionId: session.id });
|
|
200
227
|
return session;
|
|
201
228
|
}
|
|
202
229
|
|
|
203
|
-
deleteSession(sessionId: string): void {
|
|
230
|
+
async deleteSession(sessionId: string): Promise<void> {
|
|
204
231
|
const sessionIndex = this._sessions.findIndex(candidate => candidate.id === sessionId);
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
232
|
+
|
|
233
|
+
// If session is in memory, remove it
|
|
234
|
+
if (sessionIndex !== -1) {
|
|
235
|
+
const session = this._sessions[sessionIndex];
|
|
236
|
+
// If the removed session is the active one, set the newest one as active
|
|
237
|
+
if (session.isActive) {
|
|
238
|
+
this.setActiveSession(this._sessions[this._sessions.length - 1]?.id);
|
|
239
|
+
}
|
|
240
|
+
session.model.dispose();
|
|
241
|
+
this._sessions.splice(sessionIndex, 1);
|
|
242
|
+
this.onSessionEventEmitter.fire({ type: 'deleted', sessionId: sessionId });
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Always delete from persistent storage
|
|
246
|
+
if (this.sessionStore) {
|
|
247
|
+
try {
|
|
248
|
+
await this.sessionStore.deleteSession(sessionId);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
this.logger.error('Failed to delete session from storage', { sessionId, error });
|
|
251
|
+
}
|
|
210
252
|
}
|
|
211
|
-
session.model.dispose();
|
|
212
|
-
this._sessions.splice(sessionIndex, 1);
|
|
213
|
-
this.onSessionEventEmitter.fire({ type: 'deleted', sessionId: sessionId });
|
|
214
253
|
}
|
|
215
254
|
|
|
216
255
|
getActiveSession(): ChatSession | undefined {
|
|
@@ -303,6 +342,8 @@ export class ChatServiceImpl implements ChatService {
|
|
|
303
342
|
namingService.generateChatSessionName(session, otherSessionNames).then(name => {
|
|
304
343
|
if (name && session.title === requestText) {
|
|
305
344
|
session.title = name;
|
|
345
|
+
// Trigger persistence when title changes
|
|
346
|
+
this.saveSession(session.id);
|
|
306
347
|
}
|
|
307
348
|
didGenerateName = true;
|
|
308
349
|
}).catch(error => this.logger.error('Failed to generate chat session name', error));
|
|
@@ -392,4 +433,180 @@ export class ChatServiceImpl implements ChatService {
|
|
|
392
433
|
deleteChangeSetElement(sessionId: string, uri: URI): void {
|
|
393
434
|
this.getSession(sessionId)?.model.changeSet.removeElements(uri);
|
|
394
435
|
}
|
|
436
|
+
|
|
437
|
+
protected saveSession(sessionId: string): void {
|
|
438
|
+
if (!this.sessionStore) {
|
|
439
|
+
this.logger.debug('Session store not available, skipping save');
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const session = this.getSession(sessionId);
|
|
444
|
+
if (!session) {
|
|
445
|
+
this.logger.debug('Session not found, skipping save', { sessionId });
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Don't save empty sessions
|
|
450
|
+
if (session.model.isEmpty()) {
|
|
451
|
+
this.logger.debug('Session is empty, skipping save', { sessionId });
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Store session with title and pinned agent info
|
|
456
|
+
this.sessionStore.storeSessions(
|
|
457
|
+
{ model: session.model, title: session.title, pinnedAgentId: session.pinnedAgent?.id }
|
|
458
|
+
).catch(error => {
|
|
459
|
+
this.logger.error('Failed to store chat sessions', error);
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Set up auto-save for a session by listening to model changes.
|
|
465
|
+
*/
|
|
466
|
+
protected setupAutoSaveForSession(session: ChatSessionInternal): void {
|
|
467
|
+
const debouncedSave = debounce(() => this.saveSession(session.id), 500, { maxWait: 5000 });
|
|
468
|
+
session.model.onDidChange(_event => {
|
|
469
|
+
debouncedSave();
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
async getOrRestoreSession(sessionId: string): Promise<ChatSession | undefined> {
|
|
474
|
+
const existing = this.getSession(sessionId);
|
|
475
|
+
if (existing) {
|
|
476
|
+
this.logger.debug('Session already loaded', { sessionId });
|
|
477
|
+
return existing;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (!this.sessionStore) {
|
|
481
|
+
this.logger.debug('Session store not available, cannot restore', { sessionId });
|
|
482
|
+
return undefined;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
this.logger.debug('Restoring session from storage', { sessionId });
|
|
486
|
+
|
|
487
|
+
const serialized = await this.sessionStore.readSession(sessionId);
|
|
488
|
+
if (!serialized) {
|
|
489
|
+
this.logger.warn('Session not found in storage', { sessionId });
|
|
490
|
+
return undefined;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
this.logger.debug('Session loaded from storage', {
|
|
494
|
+
sessionId,
|
|
495
|
+
requestCount: serialized.model.requests.length,
|
|
496
|
+
responseCount: serialized.model.responses.length,
|
|
497
|
+
version: serialized.version
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
const model = new MutableChatModel(serialized.model);
|
|
501
|
+
await this.restoreSessionData(model, serialized.model);
|
|
502
|
+
|
|
503
|
+
// Determine pinned agent
|
|
504
|
+
const pinnedAgent = serialized.pinnedAgentId
|
|
505
|
+
? this.chatAgentService.getAgent(serialized.pinnedAgentId)
|
|
506
|
+
: undefined;
|
|
507
|
+
|
|
508
|
+
// Register as session
|
|
509
|
+
const session: ChatSessionInternal = {
|
|
510
|
+
id: sessionId,
|
|
511
|
+
title: serialized.title,
|
|
512
|
+
lastInteraction: new Date(serialized.saveDate),
|
|
513
|
+
model,
|
|
514
|
+
isActive: false,
|
|
515
|
+
pinnedAgent
|
|
516
|
+
};
|
|
517
|
+
this._sessions.push(session);
|
|
518
|
+
this.setupAutoSaveForSession(session);
|
|
519
|
+
this.onSessionEventEmitter.fire({ type: 'created', sessionId: session.id });
|
|
520
|
+
|
|
521
|
+
this.logger.debug('Session successfully restored and registered', { sessionId, title: session.title });
|
|
522
|
+
|
|
523
|
+
return session;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
async getPersistedSessions(): Promise<ChatSessionIndex> {
|
|
527
|
+
if (!this.sessionStore) {
|
|
528
|
+
return {};
|
|
529
|
+
}
|
|
530
|
+
return this.sessionStore.getSessionIndex();
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Deserialize response content and restore changesets.
|
|
535
|
+
* Called after basic chat model structure was created.
|
|
536
|
+
*/
|
|
537
|
+
protected async restoreSessionData(model: MutableChatModel, data: SerializedChatModel): Promise<void> {
|
|
538
|
+
this.logger.debug('Restoring dynamic session data', { sessionId: data.sessionId, requestCount: data.requests.length });
|
|
539
|
+
|
|
540
|
+
// Process each request for response content and changeset restoration
|
|
541
|
+
// IMPORTANT: Use getAllRequests() to include alternatives, not just active requests
|
|
542
|
+
const requests = model.getAllRequests();
|
|
543
|
+
for (let i = 0; i < requests.length; i++) {
|
|
544
|
+
const requestModel = requests[i];
|
|
545
|
+
|
|
546
|
+
this.logger.debug('Restore response content', { requestId: requestModel.id, index: i });
|
|
547
|
+
|
|
548
|
+
// Restore response content using deserializer registry
|
|
549
|
+
const respData = data.responses.find(r => r.requestId === requestModel.id);
|
|
550
|
+
if (respData && respData.content.length > 0) {
|
|
551
|
+
const restoredContent = await Promise.all(respData.content.map(contentData =>
|
|
552
|
+
this.deserializerRegistry.deserialize(contentData)
|
|
553
|
+
));
|
|
554
|
+
restoredContent.forEach(content => requestModel.response.response.addContent(content));
|
|
555
|
+
this.logger.debug('Restored response content', {
|
|
556
|
+
requestId: requestModel.id,
|
|
557
|
+
contentCount: restoredContent.length
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// Restore changeset elements
|
|
562
|
+
const serializedChangeSet = data.requests.find(r => r.id === requestModel.id)?.changeSet;
|
|
563
|
+
if (serializedChangeSet && serializedChangeSet.elements && serializedChangeSet.elements.length > 0) {
|
|
564
|
+
// Create a changeset if one doesn't exist
|
|
565
|
+
if (!requestModel.changeSet) {
|
|
566
|
+
requestModel.changeSet = new ChangeSetImpl();
|
|
567
|
+
}
|
|
568
|
+
await this.restoreChangeSetElements(requestModel, serializedChangeSet.elements, data.sessionId);
|
|
569
|
+
|
|
570
|
+
// Restore changeset title
|
|
571
|
+
if (serializedChangeSet.title) {
|
|
572
|
+
requestModel.changeSet.setTitle(serializedChangeSet.title);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
this.logger.debug('Restored changeset', {
|
|
576
|
+
requestId: requestModel.id,
|
|
577
|
+
elementCount: serializedChangeSet.elements.length
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
this.logger.debug('Restoring dynamic session data complete', { sessionId: data.sessionId });
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
protected async restoreChangeSetElements(
|
|
586
|
+
requestModel: MutableChatRequestModel,
|
|
587
|
+
elements: SerializableChangeSetElement[],
|
|
588
|
+
sessionId: string
|
|
589
|
+
): Promise<void> {
|
|
590
|
+
this.logger.debug('Restoring changeset elements', { requestId: requestModel.id, elementCount: elements.length });
|
|
591
|
+
|
|
592
|
+
const context: ChangeSetDeserializationContext = {
|
|
593
|
+
chatSessionId: sessionId,
|
|
594
|
+
requestId: requestModel.id
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
const restoredElements: ChangeSetElement[] = [];
|
|
598
|
+
|
|
599
|
+
for (const elem of elements) {
|
|
600
|
+
const restoredElement = await this.changeSetElementDeserializerRegistry.deserialize(elem, context);
|
|
601
|
+
restoredElements.push(restoredElement);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Add elements to the request's changeset
|
|
605
|
+
if (requestModel.changeSet) {
|
|
606
|
+
requestModel.changeSet.addElements(...restoredElements);
|
|
607
|
+
this.logger.debug('Changeset elements restored', { requestId: requestModel.id, elementCount: restoredElements.length });
|
|
608
|
+
} else {
|
|
609
|
+
this.logger.warn('Request has no changeset, cannot restore elements', { requestId: requestModel.id });
|
|
610
|
+
}
|
|
611
|
+
}
|
|
395
612
|
}
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
} from '@theia/ai-core';
|
|
27
27
|
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
28
28
|
import { ChatSession } from './chat-service';
|
|
29
|
-
import { generateUuid } from '@theia/core';
|
|
29
|
+
import { generateUuid, nls } from '@theia/core';
|
|
30
30
|
|
|
31
31
|
import { CHAT_SESSION_NAMING_PROMPT } from './chat-session-naming-prompt-template';
|
|
32
32
|
|
|
@@ -47,7 +47,7 @@ export class ChatSessionNamingAgent implements Agent {
|
|
|
47
47
|
static ID = 'Chat Session Naming';
|
|
48
48
|
id = ChatSessionNamingAgent.ID;
|
|
49
49
|
name = ChatSessionNamingAgent.ID;
|
|
50
|
-
description = 'Agent for generating chat session names';
|
|
50
|
+
description = nls.localize('theia/ai/chat/chatSessionNamingAgent/description', 'Agent for generating chat session names');
|
|
51
51
|
variables = [];
|
|
52
52
|
prompts = [CHAT_SESSION_NAMING_PROMPT];
|
|
53
53
|
languageModelRequirements: LanguageModelRequirement[] = [{
|
|
@@ -55,8 +55,16 @@ export class ChatSessionNamingAgent implements Agent {
|
|
|
55
55
|
identifier: 'default/summarize',
|
|
56
56
|
}];
|
|
57
57
|
agentSpecificVariables = [
|
|
58
|
-
{
|
|
59
|
-
|
|
58
|
+
{
|
|
59
|
+
name: 'conversation',
|
|
60
|
+
usedInPrompt: true,
|
|
61
|
+
description: nls.localize('theia/ai/chat/chatSessionNamingAgent/vars/conversation/description', 'The content of the chat conversation.')
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'listOfSessionNames',
|
|
65
|
+
usedInPrompt: true,
|
|
66
|
+
description: nls.localize('theia/ai/chat/chatSessionNamingAgent/vars/listOfSessionNames/description', 'The list of existing session names.')
|
|
67
|
+
}
|
|
60
68
|
];
|
|
61
69
|
functions = [];
|
|
62
70
|
|
|
@@ -0,0 +1,63 @@
|
|
|
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 { ChatModel } from './chat-model';
|
|
18
|
+
import { SerializedChatData } from './chat-model-serialization';
|
|
19
|
+
import { ChatAgentLocation } from './chat-agents';
|
|
20
|
+
|
|
21
|
+
export const ChatSessionStore = Symbol('ChatSessionStore');
|
|
22
|
+
|
|
23
|
+
export interface ChatModelWithMetadata {
|
|
24
|
+
model: ChatModel;
|
|
25
|
+
title?: string;
|
|
26
|
+
pinnedAgentId?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ChatSessionStore {
|
|
30
|
+
/**
|
|
31
|
+
* Stores the handed over sessions.
|
|
32
|
+
*
|
|
33
|
+
* Might overwrite existing sessions when maximum storage capacity is exceeded.
|
|
34
|
+
*/
|
|
35
|
+
storeSessions(...sessions: Array<ChatModel | ChatModelWithMetadata>): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Read specified session
|
|
38
|
+
*/
|
|
39
|
+
readSession(sessionId: string): Promise<SerializedChatData | undefined>;
|
|
40
|
+
/**
|
|
41
|
+
* Delete specified session
|
|
42
|
+
*/
|
|
43
|
+
deleteSession(sessionId: string): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Deletes all sessions
|
|
46
|
+
*/
|
|
47
|
+
clearAllSessions(): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Get index of all stored sessions
|
|
50
|
+
*/
|
|
51
|
+
getSessionIndex(): Promise<ChatSessionIndex>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface ChatSessionIndex {
|
|
55
|
+
[sessionId: string]: ChatSessionMetadata;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ChatSessionMetadata {
|
|
59
|
+
sessionId: string;
|
|
60
|
+
title: string;
|
|
61
|
+
saveDate: number;
|
|
62
|
+
location: ChatAgentLocation;
|
|
63
|
+
}
|
|
@@ -24,7 +24,7 @@ export const CHAT_SESSION_SUMMARY_PROMPT = {
|
|
|
24
24
|
'The summary will primarily be used by other AI agents, so tailor your response for use by AI agents. ' +
|
|
25
25
|
'Also consider the system message. ' +
|
|
26
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. ' +
|
|
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
28
|
'If a changeset is open in the session, describe the state of the suggested changes. ' +
|
|
29
29
|
`\n\n{{${CHANGE_SET_SUMMARY_VARIABLE_ID}}}`,
|
|
30
30
|
}
|
|
@@ -21,13 +21,14 @@ import {
|
|
|
21
21
|
import { injectable } from '@theia/core/shared/inversify';
|
|
22
22
|
import { AbstractStreamParsingChatAgent, ChatAgent } from './chat-agents';
|
|
23
23
|
import { CHAT_SESSION_SUMMARY_PROMPT } from './chat-session-summary-agent-prompt';
|
|
24
|
+
import { nls } from '@theia/core';
|
|
24
25
|
|
|
25
26
|
@injectable()
|
|
26
27
|
export class ChatSessionSummaryAgent extends AbstractStreamParsingChatAgent implements ChatAgent {
|
|
27
28
|
static ID = 'chat-session-summary-agent';
|
|
28
29
|
id = ChatSessionSummaryAgent.ID;
|
|
29
30
|
name = 'Chat Session Summary';
|
|
30
|
-
override description = 'Agent for generating chat session summaries.';
|
|
31
|
+
override description = nls.localize('theia/ai/chat/chatSessionSummaryAgent/description', 'Agent for generating chat session summaries.');
|
|
31
32
|
override prompts: PromptVariantSet[] = [CHAT_SESSION_SUMMARY_PROMPT];
|
|
32
33
|
protected readonly defaultLanguageModelPurpose = 'chat-session-summary';
|
|
33
34
|
languageModelRequirements: LanguageModelRequirement[] = [{
|
|
@@ -70,7 +70,7 @@ export const chatToolPreferences: PreferenceSchema = {
|
|
|
70
70
|
},
|
|
71
71
|
default: {},
|
|
72
72
|
description: nls.localize('theia/ai/chat/toolConfirmation/description',
|
|
73
|
-
'Configure confirmation behavior for different tools. Key is the tool ID, value is the confirmation mode.' +
|
|
73
|
+
'Configure confirmation behavior for different tools. Key is the tool ID, value is the confirmation mode. ' +
|
|
74
74
|
'Use "*" as the key to set a global default for all tools.'),
|
|
75
75
|
title: AI_CORE_PREFERENCES_TITLE,
|
|
76
76
|
}
|
|
@@ -80,4 +80,3 @@ export const chatToolPreferences: PreferenceSchema = {
|
|
|
80
80
|
export interface ChatToolConfiguration {
|
|
81
81
|
[TOOL_CONFIRMATION_PREFERENCE]: { [toolId: string]: ToolConfirmationMode };
|
|
82
82
|
}
|
|
83
|
-
|
|
@@ -19,19 +19,34 @@ import {
|
|
|
19
19
|
AIVariableResolutionRequest,
|
|
20
20
|
ResolvedAIContextVariable
|
|
21
21
|
} from '@theia/ai-core';
|
|
22
|
+
import { nls } from '@theia/core';
|
|
22
23
|
|
|
23
24
|
export const IMAGE_CONTEXT_VARIABLE: AIVariable = {
|
|
24
25
|
id: 'imageContext',
|
|
25
|
-
description: 'Provides context information for an image',
|
|
26
|
+
description: nls.localize('theia/ai/chat/imageContextVariable/description', 'Provides context information for an image'),
|
|
26
27
|
name: 'imageContext',
|
|
27
|
-
label: 'Image File',
|
|
28
|
+
label: nls.localize('theia/ai/chat/imageContextVariable/label', 'Image File'),
|
|
28
29
|
iconClasses: ['codicon', 'codicon-file-media'],
|
|
29
30
|
isContextVariable: true,
|
|
30
31
|
args: [
|
|
31
|
-
{
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
{
|
|
33
|
+
name: 'name',
|
|
34
|
+
description: nls.localize('theia/ai/chat/imageContextVariable/args/name/description', 'The name of the image file if available.'),
|
|
35
|
+
isOptional: true
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'wsRelativePath',
|
|
39
|
+
description: nls.localize('theia/ai/chat/imageContextVariable/args/wsRelativePath/description', 'The workspace-relative path of the image file if available.'),
|
|
40
|
+
isOptional: true
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'data',
|
|
44
|
+
description: nls.localize('theia/ai/chat/imageContextVariable/args/data/description', 'The image data in base64.')
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'mimeType',
|
|
48
|
+
description: nls.localize('theia/ai/chat/imageContextVariable/args/mimeType/description', 'The mimetype of the image.')
|
|
49
|
+
}
|
|
35
50
|
]
|
|
36
51
|
};
|
|
37
52
|
|
package/src/common/index.ts
CHANGED
|
@@ -16,9 +16,12 @@
|
|
|
16
16
|
export * from './chat-agents';
|
|
17
17
|
export * from './chat-agent-service';
|
|
18
18
|
export * from './chat-model';
|
|
19
|
+
export * from './chat-model-serialization';
|
|
20
|
+
export * from './chat-content-deserializer';
|
|
19
21
|
export * from './chat-model-util';
|
|
20
22
|
export * from './chat-request-parser';
|
|
21
23
|
export * from './chat-service';
|
|
24
|
+
export * from './chat-session-store';
|
|
22
25
|
export * from './custom-chat-agent';
|
|
23
26
|
export * from './parsed-chat-request';
|
|
24
27
|
export * from './context-variables';
|