@theia/ai-chat-ui 1.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -0
- package/lib/browser/ai-chat-ui-contribution.d.ts +24 -0
- package/lib/browser/ai-chat-ui-contribution.d.ts.map +1 -0
- package/lib/browser/ai-chat-ui-contribution.js +161 -0
- package/lib/browser/ai-chat-ui-contribution.js.map +1 -0
- package/lib/browser/ai-chat-ui-frontend-module.d.ts +5 -0
- package/lib/browser/ai-chat-ui-frontend-module.d.ts.map +1 -0
- package/lib/browser/ai-chat-ui-frontend-module.js +83 -0
- package/lib/browser/ai-chat-ui-frontend-module.js.map +1 -0
- package/lib/browser/chat-input-widget.d.ts +32 -0
- package/lib/browser/chat-input-widget.d.ts.map +1 -0
- package/lib/browser/chat-input-widget.js +205 -0
- package/lib/browser/chat-input-widget.js.map +1 -0
- package/lib/browser/chat-node-toolbar-action-contribution.d.ts +47 -0
- package/lib/browser/chat-node-toolbar-action-contribution.d.ts.map +1 -0
- package/lib/browser/chat-node-toolbar-action-contribution.js +25 -0
- package/lib/browser/chat-node-toolbar-action-contribution.js.map +1 -0
- package/lib/browser/chat-response-part-renderer.d.ts +10 -0
- package/lib/browser/chat-response-part-renderer.d.ts.map +1 -0
- package/lib/browser/chat-response-part-renderer.js +20 -0
- package/lib/browser/chat-response-part-renderer.js.map +1 -0
- package/lib/browser/chat-response-renderer/ai-editor-manager.d.ts +36 -0
- package/lib/browser/chat-response-renderer/ai-editor-manager.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/ai-editor-manager.js +184 -0
- package/lib/browser/chat-response-renderer/ai-editor-manager.js.map +1 -0
- package/lib/browser/chat-response-renderer/code-part-renderer.d.ts +45 -0
- package/lib/browser/chat-response-renderer/code-part-renderer.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/code-part-renderer.js +186 -0
- package/lib/browser/chat-response-renderer/code-part-renderer.js.map +1 -0
- package/lib/browser/chat-response-renderer/command-part-renderer.d.ts +12 -0
- package/lib/browser/chat-response-renderer/command-part-renderer.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/command-part-renderer.js +70 -0
- package/lib/browser/chat-response-renderer/command-part-renderer.js.map +1 -0
- package/lib/browser/chat-response-renderer/error-part-renderer.d.ts +9 -0
- package/lib/browser/chat-response-renderer/error-part-renderer.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/error-part-renderer.js +40 -0
- package/lib/browser/chat-response-renderer/error-part-renderer.js.map +1 -0
- package/lib/browser/chat-response-renderer/horizontal-layout-part-renderer.d.ts +12 -0
- package/lib/browser/chat-response-renderer/horizontal-layout-part-renderer.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/horizontal-layout-part-renderer.js +54 -0
- package/lib/browser/chat-response-renderer/horizontal-layout-part-renderer.js.map +1 -0
- package/lib/browser/chat-response-renderer/index.d.ts +9 -0
- package/lib/browser/chat-response-renderer/index.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/index.js +27 -0
- package/lib/browser/chat-response-renderer/index.js.map +1 -0
- package/lib/browser/chat-response-renderer/markdown-part-renderer.d.ts +17 -0
- package/lib/browser/chat-response-renderer/markdown-part-renderer.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/markdown-part-renderer.js +70 -0
- package/lib/browser/chat-response-renderer/markdown-part-renderer.js.map +1 -0
- package/lib/browser/chat-response-renderer/text-part-renderer.d.ts +9 -0
- package/lib/browser/chat-response-renderer/text-part-renderer.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/text-part-renderer.js +41 -0
- package/lib/browser/chat-response-renderer/text-part-renderer.js.map +1 -0
- package/lib/browser/chat-response-renderer/text-part-renderer.spec.d.ts +2 -0
- package/lib/browser/chat-response-renderer/text-part-renderer.spec.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/text-part-renderer.spec.js +46 -0
- package/lib/browser/chat-response-renderer/text-part-renderer.spec.js.map +1 -0
- package/lib/browser/chat-response-renderer/toolcall-part-renderer.d.ts +9 -0
- package/lib/browser/chat-response-renderer/toolcall-part-renderer.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/toolcall-part-renderer.js +49 -0
- package/lib/browser/chat-response-renderer/toolcall-part-renderer.js.map +1 -0
- package/lib/browser/chat-tree-view/chat-view-tree-container.d.ts +4 -0
- package/lib/browser/chat-tree-view/chat-view-tree-container.d.ts.map +1 -0
- package/lib/browser/chat-tree-view/chat-view-tree-container.js +33 -0
- package/lib/browser/chat-tree-view/chat-view-tree-container.js.map +1 -0
- package/lib/browser/chat-tree-view/chat-view-tree-widget.d.ts +53 -0
- package/lib/browser/chat-tree-view/chat-view-tree-widget.d.ts.map +1 -0
- package/lib/browser/chat-tree-view/chat-view-tree-widget.js +324 -0
- package/lib/browser/chat-tree-view/chat-view-tree-widget.js.map +1 -0
- package/lib/browser/chat-tree-view/index.d.ts +3 -0
- package/lib/browser/chat-tree-view/index.d.ts.map +1 -0
- package/lib/browser/chat-tree-view/index.js +21 -0
- package/lib/browser/chat-tree-view/index.js.map +1 -0
- package/lib/browser/chat-view-commands.d.ts +8 -0
- package/lib/browser/chat-view-commands.d.ts.map +1 -0
- package/lib/browser/chat-view-commands.js +44 -0
- package/lib/browser/chat-view-commands.js.map +1 -0
- package/lib/browser/chat-view-contribution.d.ts +18 -0
- package/lib/browser/chat-view-contribution.d.ts.map +1 -0
- package/lib/browser/chat-view-contribution.js +153 -0
- package/lib/browser/chat-view-contribution.js.map +1 -0
- package/lib/browser/chat-view-language-contribution.d.ts +20 -0
- package/lib/browser/chat-view-language-contribution.d.ts.map +1 -0
- package/lib/browser/chat-view-language-contribution.js +98 -0
- package/lib/browser/chat-view-language-contribution.js.map +1 -0
- package/lib/browser/chat-view-widget-toolbar-contribution.d.ts +11 -0
- package/lib/browser/chat-view-widget-toolbar-contribution.d.ts.map +1 -0
- package/lib/browser/chat-view-widget-toolbar-contribution.js +65 -0
- package/lib/browser/chat-view-widget-toolbar-contribution.js.map +1 -0
- package/lib/browser/chat-view-widget.d.ts +41 -0
- package/lib/browser/chat-view-widget.d.ts.map +1 -0
- package/lib/browser/chat-view-widget.js +182 -0
- package/lib/browser/chat-view-widget.js.map +1 -0
- package/package.json +59 -0
- package/src/browser/ai-chat-ui-contribution.ts +171 -0
- package/src/browser/ai-chat-ui-frontend-module.ts +101 -0
- package/src/browser/chat-input-widget.tsx +247 -0
- package/src/browser/chat-node-toolbar-action-contribution.ts +63 -0
- package/src/browser/chat-response-part-renderer.ts +25 -0
- package/src/browser/chat-response-renderer/ai-editor-manager.ts +183 -0
- package/src/browser/chat-response-renderer/code-part-renderer.tsx +208 -0
- package/src/browser/chat-response-renderer/command-part-renderer.tsx +60 -0
- package/src/browser/chat-response-renderer/error-part-renderer.tsx +35 -0
- package/src/browser/chat-response-renderer/horizontal-layout-part-renderer.tsx +59 -0
- package/src/browser/chat-response-renderer/index.ts +23 -0
- package/src/browser/chat-response-renderer/markdown-part-renderer.tsx +71 -0
- package/src/browser/chat-response-renderer/text-part-renderer.spec.ts +50 -0
- package/src/browser/chat-response-renderer/text-part-renderer.tsx +35 -0
- package/src/browser/chat-response-renderer/toolcall-part-renderer.tsx +49 -0
- package/src/browser/chat-tree-view/chat-view-tree-container.ts +32 -0
- package/src/browser/chat-tree-view/chat-view-tree-widget.tsx +410 -0
- package/src/browser/chat-tree-view/index.ts +18 -0
- package/src/browser/chat-view-commands.ts +45 -0
- package/src/browser/chat-view-contribution.ts +154 -0
- package/src/browser/chat-view-language-contribution.ts +141 -0
- package/src/browser/chat-view-widget-toolbar-contribution.tsx +54 -0
- package/src/browser/chat-view-widget.tsx +194 -0
- package/src/browser/style/index.css +328 -0
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@theia/ai-chat-ui",
|
|
3
|
+
"version": "1.54.0",
|
|
4
|
+
"description": "Theia - AI Chat UI Extension",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"@theia/ai-chat": "1.54.0",
|
|
7
|
+
"@theia/ai-core": "1.54.0",
|
|
8
|
+
"@theia/core": "1.54.0",
|
|
9
|
+
"@theia/editor": "1.54.0",
|
|
10
|
+
"@theia/editor-preview": "1.54.0",
|
|
11
|
+
"@theia/filesystem": "1.54.0",
|
|
12
|
+
"@theia/monaco": "1.54.0",
|
|
13
|
+
"@theia/monaco-editor-core": "1.83.101",
|
|
14
|
+
"@theia/workspace": "1.54.0",
|
|
15
|
+
"minimatch": "^5.1.0",
|
|
16
|
+
"tslib": "^2.6.2",
|
|
17
|
+
"uuid": "^9.0.1"
|
|
18
|
+
},
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"theiaExtensions": [
|
|
23
|
+
{
|
|
24
|
+
"frontend": "lib/browser/ai-chat-ui-frontend-module",
|
|
25
|
+
"secondaryWindow": "lib/browser/ai-chat-ui-frontend-module"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"keywords": [
|
|
29
|
+
"theia-extension"
|
|
30
|
+
],
|
|
31
|
+
"license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/eclipse-theia/theia.git"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/eclipse-theia/theia/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/eclipse-theia/theia",
|
|
40
|
+
"files": [
|
|
41
|
+
"lib",
|
|
42
|
+
"src"
|
|
43
|
+
],
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "theiaext build",
|
|
46
|
+
"clean": "theiaext clean",
|
|
47
|
+
"compile": "theiaext compile",
|
|
48
|
+
"lint": "theiaext lint",
|
|
49
|
+
"test": "theiaext test",
|
|
50
|
+
"watch": "theiaext watch"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@theia/ext-scripts": "1.54.0"
|
|
54
|
+
},
|
|
55
|
+
"nyc": {
|
|
56
|
+
"extends": "../../configs/nyc.json"
|
|
57
|
+
},
|
|
58
|
+
"gitHead": "8fb36a237db744cff6e78eaff1481e1f36bb7a69"
|
|
59
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
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 { inject, injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import { CommandRegistry, QuickInputButton, QuickInputService, QuickPickItem } from '@theia/core';
|
|
19
|
+
import { Widget } from '@theia/core/lib/browser';
|
|
20
|
+
import { AI_CHAT_NEW_CHAT_WINDOW_COMMAND, AI_CHAT_SHOW_CHATS_COMMAND, ChatCommands } from './chat-view-commands';
|
|
21
|
+
import { ChatAgentLocation, ChatService } from '@theia/ai-chat';
|
|
22
|
+
import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution';
|
|
23
|
+
import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
|
24
|
+
import { ChatViewWidget } from './chat-view-widget';
|
|
25
|
+
import { Deferred } from '@theia/core/lib/common/promise-util';
|
|
26
|
+
import { SecondaryWindowHandler } from '@theia/core/lib/browser/secondary-window-handler';
|
|
27
|
+
|
|
28
|
+
export const AI_CHAT_TOGGLE_COMMAND_ID = 'aiChat:toggle';
|
|
29
|
+
|
|
30
|
+
@injectable()
|
|
31
|
+
export class AIChatContribution extends AbstractViewContribution<ChatViewWidget> implements TabBarToolbarContribution {
|
|
32
|
+
|
|
33
|
+
@inject(ChatService)
|
|
34
|
+
protected readonly chatService: ChatService;
|
|
35
|
+
@inject(QuickInputService)
|
|
36
|
+
protected readonly quickInputService: QuickInputService;
|
|
37
|
+
|
|
38
|
+
protected static readonly REMOVE_CHAT_BUTTON: QuickInputButton = {
|
|
39
|
+
iconClass: 'codicon-remove-close',
|
|
40
|
+
tooltip: 'Remove Chat',
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
@inject(SecondaryWindowHandler)
|
|
44
|
+
protected readonly secondaryWindowHandler: SecondaryWindowHandler;
|
|
45
|
+
|
|
46
|
+
constructor() {
|
|
47
|
+
super({
|
|
48
|
+
widgetId: ChatViewWidget.ID,
|
|
49
|
+
widgetName: ChatViewWidget.LABEL,
|
|
50
|
+
defaultWidgetOptions: {
|
|
51
|
+
area: 'left',
|
|
52
|
+
rank: 100
|
|
53
|
+
},
|
|
54
|
+
toggleCommandId: AI_CHAT_TOGGLE_COMMAND_ID,
|
|
55
|
+
toggleKeybinding: 'ctrlcmd+shift+e'
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
override registerCommands(registry: CommandRegistry): void {
|
|
60
|
+
super.registerCommands(registry);
|
|
61
|
+
registry.registerCommand(ChatCommands.SCROLL_LOCK_WIDGET, {
|
|
62
|
+
isEnabled: widget => this.withWidget(widget, chatWidget => !chatWidget.isLocked),
|
|
63
|
+
isVisible: widget => this.withWidget(widget, chatWidget => !chatWidget.isLocked),
|
|
64
|
+
execute: widget => this.withWidget(widget, chatWidget => {
|
|
65
|
+
chatWidget.lock();
|
|
66
|
+
return true;
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
registry.registerCommand(ChatCommands.SCROLL_UNLOCK_WIDGET, {
|
|
70
|
+
isEnabled: widget => this.withWidget(widget, chatWidget => chatWidget.isLocked),
|
|
71
|
+
isVisible: widget => this.withWidget(widget, chatWidget => chatWidget.isLocked),
|
|
72
|
+
execute: widget => this.withWidget(widget, chatWidget => {
|
|
73
|
+
chatWidget.unlock();
|
|
74
|
+
return true;
|
|
75
|
+
})
|
|
76
|
+
});
|
|
77
|
+
registry.registerCommand(AI_CHAT_NEW_CHAT_WINDOW_COMMAND, {
|
|
78
|
+
execute: () => this.chatService.createSession(ChatAgentLocation.Panel, { focus: true }),
|
|
79
|
+
isEnabled: widget => this.withWidget(widget, () => true),
|
|
80
|
+
isVisible: widget => this.withWidget(widget, () => true),
|
|
81
|
+
});
|
|
82
|
+
registry.registerCommand(AI_CHAT_SHOW_CHATS_COMMAND, {
|
|
83
|
+
execute: () => this.selectChat(),
|
|
84
|
+
isEnabled: widget => this.withWidget(widget, () => true) && this.chatService.getSessions().length > 1,
|
|
85
|
+
isVisible: widget => this.withWidget(widget, () => true)
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
registerToolbarItems(registry: TabBarToolbarRegistry): void {
|
|
90
|
+
registry.registerItem({
|
|
91
|
+
id: AI_CHAT_NEW_CHAT_WINDOW_COMMAND.id,
|
|
92
|
+
command: AI_CHAT_NEW_CHAT_WINDOW_COMMAND.id,
|
|
93
|
+
tooltip: 'New Chat',
|
|
94
|
+
isVisible: widget => this.isChatViewWidget(widget)
|
|
95
|
+
});
|
|
96
|
+
registry.registerItem({
|
|
97
|
+
id: AI_CHAT_SHOW_CHATS_COMMAND.id,
|
|
98
|
+
command: AI_CHAT_SHOW_CHATS_COMMAND.id,
|
|
99
|
+
tooltip: 'Show Chats...',
|
|
100
|
+
isVisible: widget => this.isChatViewWidget(widget),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
protected isChatViewWidget(widget?: Widget): boolean {
|
|
105
|
+
return !!widget && ChatViewWidget.ID === widget.id;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
protected async selectChat(sessionId?: string): Promise<void> {
|
|
109
|
+
let activeSessionId = sessionId;
|
|
110
|
+
|
|
111
|
+
if (!activeSessionId) {
|
|
112
|
+
const item = await this.askForChatSession();
|
|
113
|
+
if (item === undefined) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
activeSessionId = item.id;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
this.chatService.setActiveSession(activeSessionId!, { focus: true });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
protected askForChatSession(): Promise<QuickPickItem | undefined> {
|
|
123
|
+
const getItems = () =>
|
|
124
|
+
this.chatService.getSessions().filter(session => !session.isActive).map(session => <QuickPickItem>({
|
|
125
|
+
label: session.title ?? 'New Chat',
|
|
126
|
+
id: session.id,
|
|
127
|
+
buttons: [AIChatContribution.REMOVE_CHAT_BUTTON]
|
|
128
|
+
})).reverse();
|
|
129
|
+
|
|
130
|
+
const defer = new Deferred<QuickPickItem | undefined>();
|
|
131
|
+
const quickPick = this.quickInputService.createQuickPick();
|
|
132
|
+
quickPick.placeholder = 'Select chat';
|
|
133
|
+
quickPick.canSelectMany = false;
|
|
134
|
+
quickPick.items = getItems();
|
|
135
|
+
|
|
136
|
+
quickPick.onDidTriggerItemButton(async context => {
|
|
137
|
+
this.chatService.deleteSession(context.item.id!);
|
|
138
|
+
quickPick.items = getItems();
|
|
139
|
+
if (this.chatService.getSessions().length <= 1) {
|
|
140
|
+
quickPick.hide();
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
quickPick.onDidAccept(() => {
|
|
145
|
+
const selectedItem = quickPick.selectedItems[0];
|
|
146
|
+
defer.resolve(selectedItem);
|
|
147
|
+
quickPick.hide();
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
quickPick.onDidHide(() => defer.resolve(undefined));
|
|
151
|
+
|
|
152
|
+
quickPick.show();
|
|
153
|
+
|
|
154
|
+
return defer.promise;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
protected withWidget(
|
|
158
|
+
widget: Widget | undefined = this.tryGetWidget(),
|
|
159
|
+
predicate: (output: ChatViewWidget) => boolean = () => true
|
|
160
|
+
): boolean | false {
|
|
161
|
+
return widget instanceof ChatViewWidget ? predicate(widget) : false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
protected extractChatView(chatView: ChatViewWidget): void {
|
|
165
|
+
this.secondaryWindowHandler.moveWidgetToSecondaryWindow(chatView);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
canExtractChatView(chatView: ChatViewWidget): boolean {
|
|
169
|
+
return !chatView.secondaryWindow;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
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 { bindContributionProvider, CommandContribution, MenuContribution } from '@theia/core';
|
|
18
|
+
import { bindViewContribution, FrontendApplicationContribution, WidgetFactory } from '@theia/core/lib/browser';
|
|
19
|
+
import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
|
20
|
+
import { ContainerModule, interfaces } from '@theia/core/shared/inversify';
|
|
21
|
+
import { EditorManager } from '@theia/editor/lib/browser';
|
|
22
|
+
import '../../src/browser/style/index.css';
|
|
23
|
+
import { AIChatContribution } from './ai-chat-ui-contribution';
|
|
24
|
+
import { AIChatInputWidget } from './chat-input-widget';
|
|
25
|
+
import { ChatNodeToolbarActionContribution } from './chat-node-toolbar-action-contribution';
|
|
26
|
+
import { ChatResponsePartRenderer } from './chat-response-part-renderer';
|
|
27
|
+
import { CodePartRenderer, CommandPartRenderer, ErrorPartRenderer, HorizontalLayoutPartRenderer, MarkdownPartRenderer, ToolCallPartRenderer } from './chat-response-renderer';
|
|
28
|
+
import {
|
|
29
|
+
AIEditorManager, AIEditorSelectionResolver,
|
|
30
|
+
GitHubSelectionResolver, TextFragmentSelectionResolver, TypeDocSymbolSelectionResolver
|
|
31
|
+
} from './chat-response-renderer/ai-editor-manager';
|
|
32
|
+
import { createChatViewTreeWidget } from './chat-tree-view';
|
|
33
|
+
import { ChatViewTreeWidget } from './chat-tree-view/chat-view-tree-widget';
|
|
34
|
+
import { ChatViewMenuContribution } from './chat-view-contribution';
|
|
35
|
+
import { ChatViewLanguageContribution } from './chat-view-language-contribution';
|
|
36
|
+
import { ChatViewWidget } from './chat-view-widget';
|
|
37
|
+
import { ChatViewWidgetToolbarContribution } from './chat-view-widget-toolbar-contribution';
|
|
38
|
+
|
|
39
|
+
export default new ContainerModule((bind, _unbind, _isBound, rebind) => {
|
|
40
|
+
bindViewContribution(bind, AIChatContribution);
|
|
41
|
+
bind(TabBarToolbarContribution).toService(AIChatContribution);
|
|
42
|
+
|
|
43
|
+
bindContributionProvider(bind, ChatResponsePartRenderer);
|
|
44
|
+
|
|
45
|
+
bindChatViewWidget(bind);
|
|
46
|
+
|
|
47
|
+
bind(AIChatInputWidget).toSelf();
|
|
48
|
+
bind(WidgetFactory).toDynamicValue(({ container }) => ({
|
|
49
|
+
id: AIChatInputWidget.ID,
|
|
50
|
+
createWidget: () => container.get(AIChatInputWidget)
|
|
51
|
+
})).inSingletonScope();
|
|
52
|
+
|
|
53
|
+
bind(ChatViewTreeWidget).toDynamicValue(ctx =>
|
|
54
|
+
createChatViewTreeWidget(ctx.container)
|
|
55
|
+
);
|
|
56
|
+
bind(WidgetFactory).toDynamicValue(({ container }) => ({
|
|
57
|
+
id: ChatViewTreeWidget.ID,
|
|
58
|
+
createWidget: () => container.get(ChatViewTreeWidget)
|
|
59
|
+
})).inSingletonScope();
|
|
60
|
+
|
|
61
|
+
bind(ChatResponsePartRenderer).to(HorizontalLayoutPartRenderer).inSingletonScope();
|
|
62
|
+
bind(ChatResponsePartRenderer).to(ErrorPartRenderer).inSingletonScope();
|
|
63
|
+
bind(ChatResponsePartRenderer).to(MarkdownPartRenderer).inSingletonScope();
|
|
64
|
+
bind(ChatResponsePartRenderer).to(CodePartRenderer).inSingletonScope();
|
|
65
|
+
bind(ChatResponsePartRenderer).to(CommandPartRenderer).inSingletonScope();
|
|
66
|
+
bind(ChatResponsePartRenderer).to(ToolCallPartRenderer).inSingletonScope();
|
|
67
|
+
bind(ChatResponsePartRenderer).to(ErrorPartRenderer).inSingletonScope();
|
|
68
|
+
[CommandContribution, MenuContribution].forEach(serviceIdentifier =>
|
|
69
|
+
bind(serviceIdentifier).to(ChatViewMenuContribution).inSingletonScope()
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
bind(AIEditorManager).toSelf().inSingletonScope();
|
|
73
|
+
rebind(EditorManager).toService(AIEditorManager);
|
|
74
|
+
|
|
75
|
+
bindContributionProvider(bind, AIEditorSelectionResolver);
|
|
76
|
+
bind(AIEditorSelectionResolver).to(GitHubSelectionResolver).inSingletonScope();
|
|
77
|
+
bind(AIEditorSelectionResolver).to(TypeDocSymbolSelectionResolver).inSingletonScope();
|
|
78
|
+
bind(AIEditorSelectionResolver).to(TextFragmentSelectionResolver).inSingletonScope();
|
|
79
|
+
|
|
80
|
+
bind(ChatViewWidgetToolbarContribution).toSelf().inSingletonScope();
|
|
81
|
+
bind(TabBarToolbarContribution).toService(ChatViewWidgetToolbarContribution);
|
|
82
|
+
|
|
83
|
+
bind(FrontendApplicationContribution).to(ChatViewLanguageContribution).inSingletonScope();
|
|
84
|
+
|
|
85
|
+
bindContributionProvider(bind, ChatNodeToolbarActionContribution);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
function bindChatViewWidget(bind: interfaces.Bind): void {
|
|
89
|
+
let chatViewWidget: ChatViewWidget | undefined;
|
|
90
|
+
bind(ChatViewWidget).toSelf();
|
|
91
|
+
|
|
92
|
+
bind(WidgetFactory).toDynamicValue(context => ({
|
|
93
|
+
id: ChatViewWidget.ID,
|
|
94
|
+
createWidget: () => {
|
|
95
|
+
if (chatViewWidget?.isDisposed !== false) {
|
|
96
|
+
chatViewWidget = context.container.get<ChatViewWidget>(ChatViewWidget);
|
|
97
|
+
}
|
|
98
|
+
return chatViewWidget;
|
|
99
|
+
}
|
|
100
|
+
})).inSingletonScope();
|
|
101
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
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
|
+
import { ChatAgent, ChatAgentService, ChatModel, ChatRequestModel } from '@theia/ai-chat';
|
|
17
|
+
import { UntitledResourceResolver } from '@theia/core';
|
|
18
|
+
import { ContextMenuRenderer, Message, ReactWidget } from '@theia/core/lib/browser';
|
|
19
|
+
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
20
|
+
import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
|
|
21
|
+
import * as React from '@theia/core/shared/react';
|
|
22
|
+
import { MonacoEditorProvider } from '@theia/monaco/lib/browser/monaco-editor-provider';
|
|
23
|
+
import { CHAT_VIEW_LANGUAGE_EXTENSION } from './chat-view-language-contribution';
|
|
24
|
+
import { IMouseEvent } from '@theia/monaco-editor-core';
|
|
25
|
+
|
|
26
|
+
type Query = (query: string) => Promise<void>;
|
|
27
|
+
type Cancel = (requestModel: ChatRequestModel) => void;
|
|
28
|
+
|
|
29
|
+
@injectable()
|
|
30
|
+
export class AIChatInputWidget extends ReactWidget {
|
|
31
|
+
public static ID = 'chat-input-widget';
|
|
32
|
+
static readonly CONTEXT_MENU = ['chat-input-context-menu'];
|
|
33
|
+
|
|
34
|
+
@inject(ChatAgentService)
|
|
35
|
+
protected readonly agentService: ChatAgentService;
|
|
36
|
+
|
|
37
|
+
@inject(MonacoEditorProvider)
|
|
38
|
+
protected readonly editorProvider: MonacoEditorProvider;
|
|
39
|
+
|
|
40
|
+
@inject(UntitledResourceResolver)
|
|
41
|
+
protected readonly untitledResourceResolver: UntitledResourceResolver;
|
|
42
|
+
|
|
43
|
+
@inject(ContextMenuRenderer)
|
|
44
|
+
protected readonly contextMenuRenderer: ContextMenuRenderer;
|
|
45
|
+
|
|
46
|
+
protected isEnabled = false;
|
|
47
|
+
|
|
48
|
+
private _onQuery: Query;
|
|
49
|
+
set onQuery(query: Query) {
|
|
50
|
+
this._onQuery = query;
|
|
51
|
+
}
|
|
52
|
+
private _onCancel: Cancel;
|
|
53
|
+
set onCancel(cancel: Cancel) {
|
|
54
|
+
this._onCancel = cancel;
|
|
55
|
+
}
|
|
56
|
+
private _chatModel: ChatModel;
|
|
57
|
+
set chatModel(chatModel: ChatModel) {
|
|
58
|
+
this._chatModel = chatModel;
|
|
59
|
+
this.update();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@postConstruct()
|
|
63
|
+
protected init(): void {
|
|
64
|
+
this.id = AIChatInputWidget.ID;
|
|
65
|
+
this.title.closable = false;
|
|
66
|
+
this.update();
|
|
67
|
+
}
|
|
68
|
+
protected override onActivateRequest(msg: Message): void {
|
|
69
|
+
super.onActivateRequest(msg);
|
|
70
|
+
this.node.focus({ preventScroll: true });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
protected getChatAgents(): ChatAgent[] {
|
|
74
|
+
return this.agentService.getAgents();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
protected render(): React.ReactNode {
|
|
78
|
+
return (
|
|
79
|
+
<ChatInput
|
|
80
|
+
onQuery={this._onQuery.bind(this)}
|
|
81
|
+
onCancel={this._onCancel.bind(this)}
|
|
82
|
+
chatModel={this._chatModel}
|
|
83
|
+
getChatAgents={this.getChatAgents.bind(this)}
|
|
84
|
+
editorProvider={this.editorProvider}
|
|
85
|
+
untitledResourceResolver={this.untitledResourceResolver}
|
|
86
|
+
contextMenuCallback={this.handleContextMenu.bind(this)}
|
|
87
|
+
isEnabled={this.isEnabled}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public setEnabled(enabled: boolean): void {
|
|
93
|
+
this.isEnabled = enabled;
|
|
94
|
+
this.update();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
protected handleContextMenu(event: IMouseEvent): void {
|
|
98
|
+
this.contextMenuRenderer.render({
|
|
99
|
+
menuPath: AIChatInputWidget.CONTEXT_MENU,
|
|
100
|
+
anchor: { x: event.posx, y: event.posy },
|
|
101
|
+
});
|
|
102
|
+
event.preventDefault();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
interface ChatInputProperties {
|
|
108
|
+
onCancel: (requestModel: ChatRequestModel) => void;
|
|
109
|
+
onQuery: (query: string) => void;
|
|
110
|
+
isEnabled?: boolean;
|
|
111
|
+
chatModel: ChatModel;
|
|
112
|
+
getChatAgents: () => ChatAgent[];
|
|
113
|
+
editorProvider: MonacoEditorProvider;
|
|
114
|
+
untitledResourceResolver: UntitledResourceResolver;
|
|
115
|
+
contextMenuCallback: (event: IMouseEvent) => void;
|
|
116
|
+
}
|
|
117
|
+
const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInputProperties) => {
|
|
118
|
+
|
|
119
|
+
const [inProgress, setInProgress] = React.useState(false);
|
|
120
|
+
// eslint-disable-next-line no-null/no-null
|
|
121
|
+
const editorContainerRef = React.useRef<HTMLDivElement | null>(null);
|
|
122
|
+
// eslint-disable-next-line no-null/no-null
|
|
123
|
+
const placeholderRef = React.useRef<HTMLDivElement | null>(null);
|
|
124
|
+
const editorRef = React.useRef<MonacoEditor | undefined>(undefined);
|
|
125
|
+
const allRequests = props.chatModel.getRequests();
|
|
126
|
+
const lastRequest = allRequests.length === 0 ? undefined : allRequests[allRequests.length - 1];
|
|
127
|
+
|
|
128
|
+
const createInputElement = async () => {
|
|
129
|
+
const resource = await props.untitledResourceResolver.createUntitledResource('', CHAT_VIEW_LANGUAGE_EXTENSION);
|
|
130
|
+
const editor = await props.editorProvider.createInline(resource.uri, editorContainerRef.current!, {
|
|
131
|
+
language: CHAT_VIEW_LANGUAGE_EXTENSION,
|
|
132
|
+
// Disable code lens, inlay hints and hover support to avoid console errors from other contributions
|
|
133
|
+
codeLens: false,
|
|
134
|
+
inlayHints: { enabled: 'off' },
|
|
135
|
+
hover: { enabled: false },
|
|
136
|
+
autoSizing: true,
|
|
137
|
+
scrollBeyondLastLine: false,
|
|
138
|
+
scrollBeyondLastColumn: 0,
|
|
139
|
+
minHeight: 1,
|
|
140
|
+
fontFamily: 'var(--theia-ui-font-family)',
|
|
141
|
+
fontSize: 13,
|
|
142
|
+
cursorWidth: 1,
|
|
143
|
+
maxHeight: -1,
|
|
144
|
+
scrollbar: { horizontal: 'hidden' },
|
|
145
|
+
automaticLayout: true,
|
|
146
|
+
lineNumbers: 'off',
|
|
147
|
+
lineHeight: 20,
|
|
148
|
+
padding: { top: 8 },
|
|
149
|
+
suggest: {
|
|
150
|
+
showIcons: true,
|
|
151
|
+
showSnippets: false,
|
|
152
|
+
showWords: false,
|
|
153
|
+
showStatusBar: false,
|
|
154
|
+
insertMode: 'replace',
|
|
155
|
+
},
|
|
156
|
+
bracketPairColorization: { enabled: false },
|
|
157
|
+
wrappingStrategy: 'advanced',
|
|
158
|
+
stickyScroll: { enabled: false },
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
editor.getControl().onDidChangeModelContent(() => {
|
|
162
|
+
layout();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
editor.getControl().onContextMenu(e =>
|
|
166
|
+
props.contextMenuCallback(e.event)
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
editorRef.current = editor;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
React.useEffect(() => {
|
|
173
|
+
createInputElement();
|
|
174
|
+
return () => {
|
|
175
|
+
if (editorRef.current) {
|
|
176
|
+
editorRef.current.dispose();
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}, []);
|
|
180
|
+
|
|
181
|
+
React.useEffect(() => {
|
|
182
|
+
const listener = lastRequest?.response.onDidChange(() => {
|
|
183
|
+
if (lastRequest.response.isCanceled || lastRequest.response.isComplete || lastRequest.response.isError) {
|
|
184
|
+
setInProgress(false);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
return () => listener?.dispose();
|
|
188
|
+
}, [lastRequest]);
|
|
189
|
+
|
|
190
|
+
function submit(value: string): void {
|
|
191
|
+
setInProgress(true);
|
|
192
|
+
props.onQuery(value);
|
|
193
|
+
if (editorRef.current) {
|
|
194
|
+
editorRef.current.document.textEditorModel.setValue('');
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
function layout(): void {
|
|
199
|
+
if (editorRef.current === undefined) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const hiddenClass = 'hidden';
|
|
203
|
+
const editor = editorRef.current;
|
|
204
|
+
if (editor.document.textEditorModel.getValue().length > 0) {
|
|
205
|
+
placeholderRef.current?.classList.add(hiddenClass);
|
|
206
|
+
} else {
|
|
207
|
+
placeholderRef.current?.classList.remove(hiddenClass);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const onKeyDown = React.useCallback((event: React.KeyboardEvent) => {
|
|
212
|
+
if (!props.isEnabled) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (event.key === 'Enter' && !event.shiftKey) {
|
|
216
|
+
event.preventDefault();
|
|
217
|
+
submit(editorRef.current?.document.textEditorModel.getValue() || '');
|
|
218
|
+
}
|
|
219
|
+
}, [props.isEnabled]);
|
|
220
|
+
|
|
221
|
+
return <div className='theia-ChatInput'>
|
|
222
|
+
<div className='theia-ChatInput-Editor-Box'>
|
|
223
|
+
<div className='theia-ChatInput-Editor' ref={editorContainerRef} onKeyDown={onKeyDown}>
|
|
224
|
+
<div ref={placeholderRef} className='theia-ChatInput-Editor-Placeholder'>Enter your question</div>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
<div className="theia-ChatInputOptions">
|
|
228
|
+
{
|
|
229
|
+
inProgress ? <span
|
|
230
|
+
className="codicon codicon-stop-circle option"
|
|
231
|
+
title="Cancel (Esc)"
|
|
232
|
+
onClick={() => {
|
|
233
|
+
if (lastRequest) {
|
|
234
|
+
props.onCancel(lastRequest);
|
|
235
|
+
}
|
|
236
|
+
setInProgress(false);
|
|
237
|
+
}} /> :
|
|
238
|
+
<span
|
|
239
|
+
className="codicon codicon-send option"
|
|
240
|
+
title="Send (Enter)"
|
|
241
|
+
onClick={!props.isEnabled ? undefined : () => submit(editorRef.current?.document.textEditorModel.getValue() || '')}
|
|
242
|
+
style={{ cursor: !props.isEnabled ? 'default' : 'pointer', opacity: !props.isEnabled ? 0.5 : 1 }}
|
|
243
|
+
/>
|
|
244
|
+
}
|
|
245
|
+
</div>
|
|
246
|
+
</div>;
|
|
247
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
import { RequestNode, ResponseNode } from './chat-tree-view';
|
|
17
|
+
|
|
18
|
+
export interface ChatNodeToolbarAction {
|
|
19
|
+
/**
|
|
20
|
+
* The command to execute when the item is selected. The handler will receive the `RequestNode` or `ResponseNode` as first argument.
|
|
21
|
+
*/
|
|
22
|
+
commandId: string;
|
|
23
|
+
/**
|
|
24
|
+
* Icon class name(s) for the item (e.g. 'codicon codicon-feedback').
|
|
25
|
+
*/
|
|
26
|
+
icon: string;
|
|
27
|
+
/**
|
|
28
|
+
* Priority among the items. Can be negative. The smaller the number the left-most the item will be placed in the toolbar. It is `0` by default.
|
|
29
|
+
*/
|
|
30
|
+
priority?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Optional tooltip for the item.
|
|
33
|
+
*/
|
|
34
|
+
tooltip?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Clients implement this interface if they want to contribute to the toolbar of chat nodes.
|
|
39
|
+
*
|
|
40
|
+
* ### Example
|
|
41
|
+
* ```ts
|
|
42
|
+
* bind(ChatNodeToolbarActionContribution).toDynamicValue(context => ({
|
|
43
|
+
* getToolbarActions: (args: RequestNode | ResponseNode) => {
|
|
44
|
+
* if (isResponseNode(args)) {
|
|
45
|
+
* return [{
|
|
46
|
+
* commandId: 'core.about',
|
|
47
|
+
* icon: 'codicon codicon-feedback',
|
|
48
|
+
* tooltip: 'Show about dialog on response nodes'
|
|
49
|
+
* }];
|
|
50
|
+
* } else {
|
|
51
|
+
* return [];
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
* }));
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export const ChatNodeToolbarActionContribution = Symbol('ChatNodeToolbarActionContribution');
|
|
58
|
+
export interface ChatNodeToolbarActionContribution {
|
|
59
|
+
/**
|
|
60
|
+
* Returns the toolbar actions for the given node.
|
|
61
|
+
*/
|
|
62
|
+
getToolbarActions(node: RequestNode | ResponseNode): ChatNodeToolbarAction[];
|
|
63
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
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 { ChatResponseContent } from '@theia/ai-chat/lib/common';
|
|
18
|
+
import { ReactNode } from '@theia/core/shared/react';
|
|
19
|
+
import { ResponseNode } from './chat-tree-view/chat-view-tree-widget';
|
|
20
|
+
|
|
21
|
+
export const ChatResponsePartRenderer = Symbol('ChatResponsePartRenderer');
|
|
22
|
+
export interface ChatResponsePartRenderer<T extends ChatResponseContent> {
|
|
23
|
+
canHandle(response: ChatResponseContent): number;
|
|
24
|
+
render(response: T, parentNode: ResponseNode): ReactNode;
|
|
25
|
+
}
|