Skip to content

Commit a36d0a3

Browse files
committed
refactor: use communication model in AI history view
Refactors the AI history view to use the new AI communication model as data input. Removes the now obsolete communication recording service. The history now supports two visual modes: "raw" and "compact" for easier inspection. Also added an option to toggle newline rendering. The ai-history package now depends on ai-chat-ui instead of the other way around. Therefore the AI history is now optional. Resolves #15539 Contributed on behalf of STMicroelectronics.
1 parent 6d1a4a1 commit a36d0a3

29 files changed

+633
-539
lines changed

package-lock.json

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/ai-chat-ui/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"dependencies": {
66
"@theia/ai-chat": "1.61.0",
77
"@theia/ai-core": "1.61.0",
8-
"@theia/ai-history": "1.61.0",
98
"@theia/core": "1.61.0",
109
"@theia/editor": "1.61.0",
1110
"@theia/editor-preview": "1.61.0",

packages/ai-chat-ui/src/browser/ai-chat-ui-contribution.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import { SecondaryWindowHandler } from '@theia/core/lib/browser/secondary-window
3131
import { formatDistance } from 'date-fns';
3232
import * as locales from 'date-fns/locale';
3333
import { AI_SHOW_SETTINGS_COMMAND } from '@theia/ai-core/lib/browser';
34-
import { OPEN_AI_HISTORY_VIEW } from '@theia/ai-history/lib/browser/ai-history-contribution';
3534
import { ChatNodeToolbarCommands } from './chat-node-toolbar-action-contribution';
3635
import { isEditableRequestNode, type EditableRequestNode } from './chat-tree-view';
3736
import { TASK_CONTEXT_VARIABLE } from '@theia/ai-chat/lib/browser/task-context-variable';
@@ -179,14 +178,6 @@ export class AIChatContribution extends AbstractViewContribution<ChatViewWidget>
179178
tooltip: nls.localize('theia/ai-chat-ui/open-settings-tooltip', 'Open AI settings...'),
180179
isVisible: widget => this.withWidget(widget),
181180
});
182-
registry.registerItem({
183-
id: 'chat-view.' + OPEN_AI_HISTORY_VIEW.id,
184-
command: OPEN_AI_HISTORY_VIEW.id,
185-
tooltip: nls.localize('theia/ai-chat-ui/open-history-tooltip', 'Open AI history...'),
186-
group: 'ai-settings',
187-
priority: 1,
188-
isVisible: widget => this.withWidget(widget),
189-
});
190181
const sessionSummarizibilityChangedEmitter = new Emitter<void>();
191182
this.taskContextService.onDidChange(() => sessionSummarizibilityChangedEmitter.fire());
192183
this.chatService.onSessionEvent(event => event.type === 'activeChange' && sessionSummarizibilityChangedEmitter.fire());

packages/ai-chat-ui/tsconfig.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
{
1616
"path": "../ai-core"
1717
},
18-
{
19-
"path": "../ai-history"
20-
},
2118
{
2219
"path": "../core"
2320
},

packages/ai-chat/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"description": "Theia - AI Chat Extension",
55
"dependencies": {
66
"@theia/ai-core": "1.61.0",
7-
"@theia/ai-history": "1.61.0",
87
"@theia/core": "1.61.0",
98
"@theia/editor": "1.61.0",
109
"@theia/file-search": "1.61.0",

packages/ai-chat/src/common/chat-agents.ts

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import {
2323
AgentSpecificVariables,
2424
AIVariableContext,
2525
AIVariableResolutionRequest,
26-
CommunicationRecordingService,
2726
getTextOfResponse,
2827
isTextResponsePart,
2928
isThinkingResponsePart,
@@ -147,9 +146,6 @@ export abstract class AbstractChatAgent implements ChatAgent {
147146
@inject(DefaultResponseContentFactory)
148147
protected defaultContentFactory: DefaultResponseContentFactory;
149148

150-
@inject(CommunicationRecordingService)
151-
protected recordingService: CommunicationRecordingService;
152-
153149
readonly abstract id: string;
154150
readonly abstract name: string;
155151
readonly abstract languageModelRequirements: LanguageModelRequirement[];
@@ -289,12 +285,6 @@ export abstract class AbstractChatAgent implements ChatAgent {
289285
const agentSettings = this.getLlmSettings();
290286
const settings = { ...agentSettings, ...request.session.settings };
291287
const tools = toolRequests.length > 0 ? toolRequests : undefined;
292-
this.recordingService.recordRequest({
293-
agentId: this.id,
294-
sessionId: request.session.id,
295-
requestId: request.id,
296-
request: messages
297-
});
298288
return this.languageModelService.sendRequest(
299289
languageModel,
300290
{
@@ -323,15 +313,6 @@ export abstract class AbstractChatAgent implements ChatAgent {
323313
* Subclasses may override this method to perform additional actions or keep the response open for processing further requests.
324314
*/
325315
protected async onResponseComplete(request: MutableChatRequestModel): Promise<void> {
326-
this.recordingService.recordResponse(
327-
{
328-
agentId: this.id,
329-
sessionId: request.session.id,
330-
requestId: request.id,
331-
response: request.response.response.content.flatMap(c =>
332-
c.toLanguageModelMessage?.() ?? ({ type: 'text', actor: 'ai', text: c.asDisplayString?.() ?? c.asString?.() ?? JSON.stringify(c) }))
333-
}
334-
);
335316
return request.response.complete();
336317
}
337318

packages/ai-chat/src/common/chat-model.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,6 +1190,10 @@ export class MutableChatRequestModel implements ChatRequestModel, EditableChatRe
11901190
return this._data[key] as T;
11911191
}
11921192

1193+
removeData(key: string): void {
1194+
delete this._data[key];
1195+
}
1196+
11931197
get id(): string {
11941198
return this._id;
11951199
}

packages/ai-chat/src/common/chat-session-naming-service.ts

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,10 @@
1717
import {
1818
Agent,
1919
AgentService,
20-
CommunicationRecordingService,
21-
CommunicationRequestEntryParam,
2220
getTextOfResponse,
2321
LanguageModelRegistry,
2422
LanguageModelRequirement,
23+
LanguageModelService,
2524
PromptService,
2625
PromptTemplate,
2726
UserRequest
@@ -58,9 +57,9 @@ export class ChatSessionNamingService {
5857

5958
@injectable()
6059
export class ChatSessionNamingAgent implements Agent {
61-
static ID = 'chat-session-naming-agent';
60+
static ID = 'Chat Session Naming';
6261
id = ChatSessionNamingAgent.ID;
63-
name = 'Chat Session Naming';
62+
name = ChatSessionNamingAgent.ID;
6463
description = 'Agent for generating chat session names';
6564
variables = [];
6665
promptTemplates: PromptTemplate[] = [CHAT_SESSION_NAMING_PROMPT];
@@ -77,8 +76,8 @@ export class ChatSessionNamingAgent implements Agent {
7776
@inject(LanguageModelRegistry)
7877
protected readonly lmRegistry: LanguageModelRegistry;
7978

80-
@inject(CommunicationRecordingService)
81-
protected recordingService: CommunicationRecordingService;
79+
@inject(LanguageModelService)
80+
protected readonly languageModelService: LanguageModelService;
8281

8382
@inject(PromptService)
8483
protected promptService: PromptService;
@@ -116,18 +115,9 @@ export class ChatSessionNamingAgent implements Agent {
116115
sessionId,
117116
agentId: this.id
118117
};
119-
this.recordingService.recordRequest({ ...request, request: request.messages } satisfies CommunicationRequestEntryParam);
120-
121-
const result = await lm.request(request);
118+
const result = await this.languageModelService.sendRequest(lm, request);
122119
const response = await getTextOfResponse(result);
123-
this.recordingService.recordResponse({
124-
agentId: this.id,
125-
sessionId,
126-
requestId,
127-
response: [{ actor: 'ai', text: response, type: 'text' }]
128-
});
129120

130121
return response.replace(/\s+/g, ' ').substring(0, 100);
131122
}
132-
133123
}

packages/ai-chat/tsconfig.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
{
1313
"path": "../ai-core"
1414
},
15-
{
16-
"path": "../ai-history"
17-
},
1815
{
1916
"path": "../core"
2017
},

packages/ai-code-completion/src/browser/code-completion-agent.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import { LanguageModelService } from '@theia/ai-core/lib/browser';
1818
import {
19-
Agent, AgentSpecificVariables, CommunicationRecordingService, getTextOfResponse,
19+
Agent, AgentSpecificVariables, getTextOfResponse,
2020
LanguageModelRegistry, LanguageModelRequirement, PromptService, PromptTemplate,
2121
UserRequest
2222
} from '@theia/ai-core/lib/common';
@@ -132,12 +132,6 @@ export class CodeCompletionAgentImpl implements CodeCompletionAgent {
132132
if (token.isCancellationRequested) {
133133
return undefined;
134134
}
135-
this.recordingService.recordRequest({
136-
agentId: this.id,
137-
sessionId,
138-
requestId,
139-
request: request.messages
140-
});
141135
const response = await this.languageModelService.sendRequest(languageModel, request);
142136
if (token.isCancellationRequested) {
143137
return undefined;
@@ -146,12 +140,6 @@ export class CodeCompletionAgentImpl implements CodeCompletionAgent {
146140
if (token.isCancellationRequested) {
147141
return undefined;
148142
}
149-
this.recordingService.recordResponse({
150-
agentId: this.id,
151-
sessionId,
152-
requestId,
153-
response: [{ actor: 'ai', text: completionText, type: 'text' }]
154-
});
155143

156144
const postProcessedCompletionText = this.postProcessor.postProcess(completionText);
157145

@@ -182,9 +170,6 @@ export class CodeCompletionAgentImpl implements CodeCompletionAgent {
182170
@inject(PromptService)
183171
protected promptService: PromptService;
184172

185-
@inject(CommunicationRecordingService)
186-
protected recordingService: CommunicationRecordingService;
187-
188173
@inject(ProgressService)
189174
protected progressService: ProgressService;
190175

packages/ai-core/src/common/communication-recording-service.ts

Lines changed: 0 additions & 55 deletions
This file was deleted.

packages/ai-core/src/common/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
export * from './agent-service';
1717
export * from './agent';
1818
export * from './agents-variable-contribution';
19-
export * from './communication-recording-service';
2019
export * from './tool-invocation-registry';
2120
export * from './language-model-delegate';
2221
export * from './language-model-util';

packages/ai-core/src/common/language-model-interaction-model.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
1515
// *****************************************************************************
1616
import {
17-
LanguageModelParsedResponse,
1817
LanguageModelRequest,
18+
LanguageModelResponse,
19+
LanguageModelStreamResponse,
1920
LanguageModelStreamResponsePart,
20-
LanguageModelTextResponse
2121
} from './language-model';
2222

2323
/**
@@ -62,6 +62,11 @@ export interface LanguageModelMonitoredStreamResponse {
6262
parts: LanguageModelStreamResponsePart[];
6363
}
6464

65+
/**
66+
* Alternative to the LanguageModelResponse, suited for inspection
67+
*/
68+
export type LanguageModelExchangeRequestResponse = Exclude<LanguageModelResponse, LanguageModelStreamResponse> | LanguageModelMonitoredStreamResponse;
69+
6570
/**
6671
* Represents a request to a language model within an exchange unit, capturing the request and its response.
6772
*/
@@ -89,5 +94,5 @@ export interface LanguageModelExchangeRequest {
8994
/**
9095
* The recorded response
9196
*/
92-
response: LanguageModelTextResponse | LanguageModelParsedResponse | LanguageModelMonitoredStreamResponse;
97+
response: LanguageModelExchangeRequestResponse;
9398
}

packages/ai-core/src/common/language-model-service.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ export interface ResponseCompletedEvent {
2727
type: 'responseCompleted',
2828
requestId: string;
2929
}
30-
export type SessionEvent = RequestAddedEvent | ResponseCompletedEvent;
30+
export interface SessionsClearedEvent {
31+
type: 'sessionsCleared'
32+
}
33+
export type SessionEvent = RequestAddedEvent | ResponseCompletedEvent | SessionsClearedEvent;
3134

3235
export const LanguageModelService = Symbol('LanguageModelService');
3336
export interface LanguageModelService {
@@ -49,7 +52,18 @@ export class LanguageModelServiceImpl implements LanguageModelService {
4952
@inject(LanguageModelRegistry)
5053
protected languageModelRegistry: LanguageModelRegistry;
5154

52-
sessions: LanguageModelSession[] = [];
55+
private _sessions: LanguageModelSession[] = [];
56+
57+
get sessions(): LanguageModelSession[] {
58+
return this._sessions;
59+
}
60+
61+
set sessions(newSessions: LanguageModelSession[]) {
62+
this._sessions = newSessions;
63+
if (newSessions.length === 0) {
64+
this.sessionChangedEmitter.fire({ type: 'sessionsCleared' });
65+
}
66+
}
5367

5468
protected sessionChangedEmitter = new Emitter<SessionEvent>();
5569
onSessionChanged = this.sessionChangedEmitter.event;
@@ -92,13 +106,13 @@ export class LanguageModelServiceImpl implements LanguageModelService {
92106

93107
protected storeRequest(languageModel: LanguageModel, languageModelRequest: UserRequest, response: LanguageModelExchangeRequest['response']): void {
94108
// Find or create the session for this request
95-
let session = this.sessions.find(s => s.id === languageModelRequest.sessionId);
109+
let session = this._sessions.find(s => s.id === languageModelRequest.sessionId);
96110
if (!session) {
97111
session = {
98112
id: languageModelRequest.sessionId,
99113
exchanges: []
100114
};
101-
this.sessions.push(session);
115+
this._sessions.push(session);
102116
}
103117

104118
// Find or create the exchange for this request

0 commit comments

Comments
 (0)