Skip to content

Commit 7df16e0

Browse files
ndoschekxai
andcommitted
GH-40 Initial Agent View and Communication History
Co-authored-by: Olaf Lessenich <[email protected]>
1 parent 565954e commit 7df16e0

28 files changed

+614
-2
lines changed

examples/browser-only/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
"@theia/ai-chat": "1.49.0",
1919
"@theia/ai-chat-ui": "1.49.0",
2020
"@theia/ai-core": "1.49.0",
21+
"@theia/ai-history": "1.49.0",
22+
"@theia/ai-history-ui": "1.49.0",
2123
"@theia/ai-openai": "1.49.0",
2224
"@theia/api-samples": "1.49.0",
2325
"@theia/bulk-edit": "1.49.0",

examples/browser-only/tsconfig.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
{
1818
"path": "../../packages/ai-core"
1919
},
20+
{
21+
"path": "../../packages/ai-history"
22+
},
23+
{
24+
"path": "../../packages/ai-history-ui"
25+
},
2026
{
2127
"path": "../../packages/ai-openai"
2228
},

examples/browser/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
"@theia/ai-chat": "1.49.0",
2424
"@theia/ai-chat-ui": "1.49.0",
2525
"@theia/ai-core": "1.49.0",
26+
"@theia/ai-history": "1.49.0",
27+
"@theia/ai-history-ui": "1.49.0",
2628
"@theia/ai-openai": "1.49.0",
2729
"@theia/api-provider-sample": "1.49.0",
2830
"@theia/api-samples": "1.49.0",

examples/browser/tsconfig.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
{
1818
"path": "../../packages/ai-core"
1919
},
20+
{
21+
"path": "../../packages/ai-history"
22+
},
23+
{
24+
"path": "../../packages/ai-history-ui"
25+
},
2026
{
2127
"path": "../../packages/ai-openai"
2228
},

examples/electron/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
"@theia/ai-chat": "1.49.0",
3030
"@theia/ai-chat-ui": "1.49.0",
3131
"@theia/ai-core": "1.49.0",
32+
"@theia/ai-history": "1.49.0",
33+
"@theia/ai-history-ui": "1.49.0",
3234
"@theia/ai-openai": "1.49.0",
3335
"@theia/api-provider-sample": "1.49.0",
3436
"@theia/api-samples": "1.49.0",

examples/electron/tsconfig.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
{
2121
"path": "../../packages/ai-core"
2222
},
23+
{
24+
"path": "../../packages/ai-history"
25+
},
26+
{
27+
"path": "../../packages/ai-history-ui"
28+
},
2329
{
2430
"path": "../../packages/ai-openai"
2531
},

packages/ai-chat/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"description": "Theia - AI Chat Extension",
55
"dependencies": {
66
"@theia/ai-core": "1.49.0",
7+
"@theia/ai-history": "1.49.0",
78
"@theia/core": "1.49.0",
89
"@theia/filesystem": "1.49.0",
910
"@theia/workspace": "1.49.0",

packages/ai-chat/src/browser/agent-frontend-module.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// *****************************************************************************
1616

1717
import { Agent } from '@theia/ai-core/lib/common';
18-
import { bindContributionProvider } from '@theia/core';
18+
import { bindContributionProvider, CommandContribution } from '@theia/core';
1919
import { ContainerModule } from '@theia/core/shared/inversify';
2020
import {
2121
ChatAgent,
@@ -27,8 +27,10 @@ import {
2727
ChatServiceImpl,
2828
ChatVariablesService,
2929
DefaultChatAgent,
30+
DummyChatAgent,
3031
DummyChatVariablesService
3132
} from '../common';
33+
import { DummyCommandContribution } from './dummy-command-contribution';
3234

3335
export default new ContainerModule(bind => {
3436
bindContributionProvider(bind, Agent);
@@ -49,4 +51,10 @@ export default new ContainerModule(bind => {
4951
bind(DefaultChatAgent).toSelf().inSingletonScope();
5052
bind(Agent).toService(DefaultChatAgent);
5153
bind(ChatAgent).toService(DefaultChatAgent);
54+
55+
bind(DummyChatAgent).toSelf().inSingletonScope();
56+
bind(Agent).toService(DummyChatAgent);
57+
bind(ChatAgent).toService(DummyChatAgent);
58+
59+
bind(CommandContribution).to(DummyCommandContribution);
5260
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// *****************************************************************************
2+
// Copyright (C) 2024 EclipseSource GmbH.
3+
//
4+
// This program and the accompanying materials are made available under the
5+
// terms of the Eclipse Public License v. 2.0 which is available at
6+
// http://www.eclipse.org/legal/epl-2.0.
7+
//
8+
// This Source Code may also be made available under the following Secondary
9+
// Licenses when the conditions for such availability set forth in the Eclipse
10+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
11+
// with the GNU Classpath Exception which is available at
12+
// https://www.gnu.org/software/classpath/license.html.
13+
//
14+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15+
// *****************************************************************************
16+
17+
import { CommandContribution, CommandRegistry } from '@theia/core';
18+
import { inject, injectable } from '@theia/core/shared/inversify';
19+
import { ChatAgentService, DummyChatAgent } from '../common';
20+
21+
export const TRIGGER_DUMMY_AGENT = ({
22+
id: 'trigger.dummy.agent',
23+
label: 'Trigger Dummy Agent',
24+
});
25+
26+
@injectable()
27+
export class DummyCommandContribution implements CommandContribution {
28+
@inject(ChatAgentService) agentService: ChatAgentService;
29+
30+
registerCommands(registry: CommandRegistry): void {
31+
registry.registerCommand(TRIGGER_DUMMY_AGENT, {
32+
execute: () => {
33+
(this.agentService.getAgentsByName('Dummy Chat Agent')[0] as DummyChatAgent).invoke();
34+
}
35+
});
36+
}
37+
}

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

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*--------------------------------------------------------------------------------------------*/
2020
// Partially copied from https://github.com/microsoft/vscode/blob/a2cab7255c0df424027be05d58e1b7b941f4ea60/src/vs/workbench/contrib/chat/common/chatAgents.ts
2121

22+
import { CommunicationRecordingService } from '@theia/ai-core';
2223
import {
2324
Agent,
2425
isLanguageModelStreamResponse,
@@ -28,7 +29,7 @@ import {
2829
LanguageModelStreamResponsePart,
2930
PromptTemplate
3031
} from '@theia/ai-core/lib/common';
31-
import { ILogger, isArray } from '@theia/core';
32+
import { generateUuid, ILogger, isArray } from '@theia/core';
3233
import { inject, injectable } from '@theia/core/shared/inversify';
3334
import { ChatRequestModelImpl, ChatResponseContent, MarkdownChatResponseContentImpl } from './chat-model';
3435
import { getMessages } from './chat-util';
@@ -67,6 +68,9 @@ export class DefaultChatAgent implements ChatAgent {
6768
@inject(ILogger)
6869
protected logger: ILogger;
6970

71+
@inject(CommunicationRecordingService)
72+
protected recordingService: CommunicationRecordingService;
73+
7074
id: string = 'DefaultChatAgent';
7175
name: string = 'Default Chat Agent';
7276
description: string = 'The default chat agent provided by Theia.';
@@ -95,6 +99,13 @@ export class DefaultChatAgent implements ChatAgent {
9599
locations: ChatAgentLocation[] = [];
96100

97101
async invoke(request: ChatRequestModelImpl): Promise<void> {
102+
this.recordingService.recordRequest({
103+
agentId: this.id,
104+
sessionId: request.session.id,
105+
timestamp: Date.now(),
106+
requestId: request.id,
107+
request: request.request.text
108+
});
98109
const selector = this.languageModelRequirements.find(req => req.purpose === 'chat')!;
99110
const languageModels = await this.languageModelRegistry.selectLanguageModels({ agent: this.id, ...selector });
100111
if (languageModels.length === 0) {
@@ -106,6 +117,13 @@ export class DefaultChatAgent implements ChatAgent {
106117
new MarkdownChatResponseContentImpl(languageModelResponse.text)
107118
);
108119
request.response.complete();
120+
this.recordingService.recordResponse({
121+
agentId: this.id,
122+
sessionId: request.session.id,
123+
timestamp: Date.now(),
124+
requestId: request.response.requestId,
125+
response: request.response.response.asString()
126+
});
109127
return;
110128
}
111129
if (isLanguageModelStreamResponse(languageModelResponse)) {
@@ -118,6 +136,13 @@ export class DefaultChatAgent implements ChatAgent {
118136
}
119137
}
120138
request.response.complete();
139+
this.recordingService.recordResponse({
140+
agentId: this.id,
141+
sessionId: request.session.id,
142+
timestamp: Date.now(),
143+
requestId: request.response.requestId,
144+
response: request.response.response.asString()
145+
});
121146
return;
122147
}
123148
this.logger.error(
@@ -129,6 +154,13 @@ export class DefaultChatAgent implements ChatAgent {
129154
)
130155
);
131156
request.response.complete();
157+
this.recordingService.recordResponse({
158+
agentId: this.id,
159+
sessionId: request.session.id,
160+
timestamp: Date.now(),
161+
requestId: request.response.requestId,
162+
response: request.response.response.asString()
163+
});
132164
}
133165

134166
private parse(token: LanguageModelStreamResponsePart, previousContent: ChatResponseContent[]): ChatResponseContent | ChatResponseContent[] {
@@ -141,3 +173,37 @@ export class DefaultChatAgent implements ChatAgent {
141173
return new MarkdownChatResponseContentImpl(token.content ?? '');
142174
}
143175
}
176+
177+
@injectable()
178+
export class DummyChatAgent implements ChatAgent {
179+
180+
@inject(CommunicationRecordingService)
181+
protected recordingService: CommunicationRecordingService;
182+
183+
id: string = 'DummyChatAgent';
184+
name: string = 'Dummy Chat Agent';
185+
description: string = 'The dummy chat agent provided by ES.';
186+
variables: string[] = [];
187+
promptTemplates: PromptTemplate[] = [];
188+
languageModelRequirements: Omit<LanguageModelSelector, 'agentId'>[] = [];
189+
locations: ChatAgentLocation[] = [];
190+
191+
async invoke(request?: ChatRequestModelImpl): Promise<void> {
192+
const requestUuid = generateUuid();
193+
const sessionId = 'dummy-session';
194+
this.recordingService.recordRequest({
195+
agentId: this.id,
196+
sessionId: sessionId,
197+
timestamp: Date.now(),
198+
requestId: requestUuid,
199+
request: 'Dummy request'
200+
});
201+
this.recordingService.recordResponse({
202+
agentId: this.id,
203+
sessionId: sessionId,
204+
timestamp: Date.now(),
205+
requestId: requestUuid,
206+
response: 'Dummy response'
207+
});
208+
}
209+
}

0 commit comments

Comments
 (0)