@theia/ai-chat-ui 1.65.0-next.55 → 1.65.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/lib/browser/ai-chat-ui-contribution.js +2 -2
- package/lib/browser/ai-chat-ui-contribution.js.map +1 -1
- package/lib/browser/chat-input-history-contribution.d.ts +1 -0
- package/lib/browser/chat-input-history-contribution.d.ts.map +1 -1
- package/lib/browser/chat-input-history-contribution.js +22 -8
- package/lib/browser/chat-input-history-contribution.js.map +1 -1
- package/lib/browser/chat-input-widget.d.ts +6 -1
- package/lib/browser/chat-input-widget.d.ts.map +1 -1
- package/lib/browser/chat-input-widget.js +75 -11
- package/lib/browser/chat-input-widget.js.map +1 -1
- package/lib/browser/chat-view-commands.d.ts +2 -0
- package/lib/browser/chat-view-commands.d.ts.map +1 -1
- package/lib/browser/chat-view-commands.js +30 -23
- package/lib/browser/chat-view-commands.js.map +1 -1
- package/package.json +11 -12
- package/src/browser/ai-chat-ui-contribution.ts +2 -2
- package/src/browser/chat-input-history-contribution.ts +26 -10
- package/src/browser/chat-input-widget.tsx +85 -13
- package/src/browser/chat-view-commands.ts +24 -17
- package/src/browser/style/index.css +22 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-view-commands.d.ts","sourceRoot":"","sources":["../../src/browser/chat-view-commands.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,OAAO,EAAO,MAAM,aAAa,CAAC;AAG3C,yBAAiB,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"chat-view-commands.d.ts","sourceRoot":"","sources":["../../src/browser/chat-view-commands.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,OAAO,EAAO,MAAM,aAAa,CAAC;AAG3C,yBAAiB,YAAY,CAAC;IACnB,MAAM,aAAa,SAAS,CAAC;IAC7B,MAAM,iBAAiB,QAAmC,CAAC;IAE3D,MAAM,kBAAkB,SAKsB,CAAC;IAE/C,MAAM,oBAAoB,SAKsB,CAAC;IAEjD,MAAM,qBAAqB,SAKwB,CAAC;IAEpD,MAAM,6BAA6B,EAAE,OAE3C,CAAC;IAEK,MAAM,0CAA0C,SAIgB,CAAC;IAEjE,MAAM,iCAAiC,SAKqB,CAAC;IAE7D,MAAM,wCAAwC,SAKiB,CAAC;CAC1E;AAED,eAAO,MAAM,+BAA+B,SAK1C,CAAC;AAEH,eAAO,MAAM,0BAA0B,SAKrC,CAAC"}
|
|
@@ -20,50 +20,57 @@ const core_1 = require("@theia/core");
|
|
|
20
20
|
const browser_1 = require("@theia/core/lib/browser");
|
|
21
21
|
var ChatCommands;
|
|
22
22
|
(function (ChatCommands) {
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
ChatCommands.CHAT_CATEGORY = 'Chat';
|
|
24
|
+
ChatCommands.CHAT_CATEGORY_KEY = core_1.nls.getDefaultKey(ChatCommands.CHAT_CATEGORY);
|
|
25
25
|
ChatCommands.SCROLL_LOCK_WIDGET = core_1.Command.toLocalizedCommand({
|
|
26
26
|
id: 'chat:widget:lock',
|
|
27
|
-
category: CHAT_CATEGORY,
|
|
28
|
-
iconClass: (0, browser_1.codicon)('unlock')
|
|
29
|
-
|
|
27
|
+
category: ChatCommands.CHAT_CATEGORY,
|
|
28
|
+
iconClass: (0, browser_1.codicon)('unlock'),
|
|
29
|
+
label: 'Lock Scroll'
|
|
30
|
+
}, 'theia/ai-chat-ui/scroll-lock', ChatCommands.CHAT_CATEGORY_KEY);
|
|
30
31
|
ChatCommands.SCROLL_UNLOCK_WIDGET = core_1.Command.toLocalizedCommand({
|
|
31
32
|
id: 'chat:widget:unlock',
|
|
32
|
-
category: CHAT_CATEGORY,
|
|
33
|
-
iconClass: (0, browser_1.codicon)('lock')
|
|
34
|
-
|
|
33
|
+
category: ChatCommands.CHAT_CATEGORY,
|
|
34
|
+
iconClass: (0, browser_1.codicon)('lock'),
|
|
35
|
+
label: 'Unlock Scroll'
|
|
36
|
+
}, 'theia/ai-chat-ui/scroll-unlock', ChatCommands.CHAT_CATEGORY_KEY);
|
|
35
37
|
ChatCommands.EDIT_SESSION_SETTINGS = core_1.Command.toLocalizedCommand({
|
|
36
38
|
id: 'chat:widget:session-settings',
|
|
37
|
-
category: CHAT_CATEGORY,
|
|
38
|
-
iconClass: (0, browser_1.codicon)('bracket')
|
|
39
|
-
|
|
39
|
+
category: ChatCommands.CHAT_CATEGORY,
|
|
40
|
+
iconClass: (0, browser_1.codicon)('bracket'),
|
|
41
|
+
label: 'Set Session Settings'
|
|
42
|
+
}, 'theia/ai-chat-ui/session-settings', ChatCommands.CHAT_CATEGORY_KEY);
|
|
40
43
|
ChatCommands.AI_CHAT_NEW_WITH_TASK_CONTEXT = {
|
|
41
44
|
id: 'ai-chat.new-with-task-context',
|
|
42
45
|
};
|
|
43
46
|
ChatCommands.AI_CHAT_INITIATE_SESSION_WITH_TASK_CONTEXT = core_1.Command.toLocalizedCommand({
|
|
44
47
|
id: 'ai-chat.initiate-session-with-task-context',
|
|
45
48
|
label: 'Task Context: Initiate Session',
|
|
46
|
-
category: CHAT_CATEGORY
|
|
47
|
-
},
|
|
49
|
+
category: ChatCommands.CHAT_CATEGORY
|
|
50
|
+
}, 'theia/ai-chat-ui/initiate-session-task-context', ChatCommands.CHAT_CATEGORY_KEY);
|
|
48
51
|
ChatCommands.AI_CHAT_SUMMARIZE_CURRENT_SESSION = core_1.Command.toLocalizedCommand({
|
|
49
52
|
id: 'ai-chat-summary-current-session',
|
|
50
53
|
iconClass: (0, browser_1.codicon)('go-to-editing-session'),
|
|
51
54
|
label: 'Summarize Current Session',
|
|
52
|
-
category: CHAT_CATEGORY
|
|
53
|
-
},
|
|
55
|
+
category: ChatCommands.CHAT_CATEGORY
|
|
56
|
+
}, 'theia/ai-chat-ui/summarize-current-session', ChatCommands.CHAT_CATEGORY_KEY);
|
|
54
57
|
ChatCommands.AI_CHAT_OPEN_SUMMARY_FOR_CURRENT_SESSION = core_1.Command.toLocalizedCommand({
|
|
55
58
|
id: 'ai-chat-open-current-session-summary',
|
|
56
59
|
iconClass: (0, browser_1.codicon)('note'),
|
|
57
60
|
label: 'Open Current Session Summary',
|
|
58
|
-
category: CHAT_CATEGORY
|
|
59
|
-
},
|
|
61
|
+
category: ChatCommands.CHAT_CATEGORY
|
|
62
|
+
}, 'theia/ai-chat-ui/open-current-session-summary', ChatCommands.CHAT_CATEGORY_KEY);
|
|
60
63
|
})(ChatCommands || (exports.ChatCommands = ChatCommands = {}));
|
|
61
|
-
exports.AI_CHAT_NEW_CHAT_WINDOW_COMMAND = {
|
|
64
|
+
exports.AI_CHAT_NEW_CHAT_WINDOW_COMMAND = core_1.Command.toDefaultLocalizedCommand({
|
|
62
65
|
id: 'ai-chat-ui.new-chat',
|
|
63
|
-
iconClass: (0, browser_1.codicon)('add')
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
iconClass: (0, browser_1.codicon)('add'),
|
|
67
|
+
category: ChatCommands.CHAT_CATEGORY,
|
|
68
|
+
label: 'New Chat'
|
|
69
|
+
});
|
|
70
|
+
exports.AI_CHAT_SHOW_CHATS_COMMAND = core_1.Command.toDefaultLocalizedCommand({
|
|
66
71
|
id: 'ai-chat-ui.show-chats',
|
|
67
|
-
iconClass: (0, browser_1.codicon)('history')
|
|
68
|
-
|
|
72
|
+
iconClass: (0, browser_1.codicon)('history'),
|
|
73
|
+
category: ChatCommands.CHAT_CATEGORY,
|
|
74
|
+
label: 'Show Chats...'
|
|
75
|
+
});
|
|
69
76
|
//# sourceMappingURL=chat-view-commands.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-view-commands.js","sourceRoot":"","sources":["../../src/browser/chat-view-commands.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;AAEhF,sCAA2C;AAC3C,qDAAkD;AAElD,IAAiB,YAAY,
|
|
1
|
+
{"version":3,"file":"chat-view-commands.js","sourceRoot":"","sources":["../../src/browser/chat-view-commands.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;AAEhF,sCAA2C;AAC3C,qDAAkD;AAElD,IAAiB,YAAY,CAgD5B;AAhDD,WAAiB,YAAY;IACZ,0BAAa,GAAG,MAAM,CAAC;IACvB,8BAAiB,GAAG,UAAG,CAAC,aAAa,CAAC,aAAA,aAAa,CAAC,CAAC;IAErD,+BAAkB,GAAG,cAAO,CAAC,kBAAkB,CAAC;QACzD,EAAE,EAAE,kBAAkB;QACtB,QAAQ,EAAE,aAAA,aAAa;QACvB,SAAS,EAAE,IAAA,iBAAO,EAAC,QAAQ,CAAC;QAC5B,KAAK,EAAE,aAAa;KACvB,EAAE,8BAA8B,EAAE,aAAA,iBAAiB,CAAC,CAAC;IAEzC,iCAAoB,GAAG,cAAO,CAAC,kBAAkB,CAAC;QAC3D,EAAE,EAAE,oBAAoB;QACxB,QAAQ,EAAE,aAAA,aAAa;QACvB,SAAS,EAAE,IAAA,iBAAO,EAAC,MAAM,CAAC;QAC1B,KAAK,EAAE,eAAe;KACzB,EAAE,gCAAgC,EAAE,aAAA,iBAAiB,CAAC,CAAC;IAE3C,kCAAqB,GAAG,cAAO,CAAC,kBAAkB,CAAC;QAC5D,EAAE,EAAE,8BAA8B;QAClC,QAAQ,EAAE,aAAA,aAAa;QACvB,SAAS,EAAE,IAAA,iBAAO,EAAC,SAAS,CAAC;QAC7B,KAAK,EAAE,sBAAsB;KAChC,EAAE,mCAAmC,EAAE,aAAA,iBAAiB,CAAC,CAAC;IAE9C,0CAA6B,GAAY;QAClD,EAAE,EAAE,+BAA+B;KACtC,CAAC;IAEW,uDAA0C,GAAG,cAAO,CAAC,kBAAkB,CAAC;QACjF,EAAE,EAAE,4CAA4C;QAChD,KAAK,EAAE,gCAAgC;QACvC,QAAQ,EAAE,aAAA,aAAa;KAC1B,EAAE,gDAAgD,EAAE,aAAA,iBAAiB,CAAC,CAAC;IAE3D,8CAAiC,GAAG,cAAO,CAAC,kBAAkB,CAAC;QACxE,EAAE,EAAE,iCAAiC;QACrC,SAAS,EAAE,IAAA,iBAAO,EAAC,uBAAuB,CAAC;QAC3C,KAAK,EAAE,2BAA2B;QAClC,QAAQ,EAAE,aAAA,aAAa;KAC1B,EAAE,4CAA4C,EAAE,aAAA,iBAAiB,CAAC,CAAC;IAEvD,qDAAwC,GAAG,cAAO,CAAC,kBAAkB,CAAC;QAC/E,EAAE,EAAE,sCAAsC;QAC1C,SAAS,EAAE,IAAA,iBAAO,EAAC,MAAM,CAAC;QAC1B,KAAK,EAAE,8BAA8B;QACrC,QAAQ,EAAE,aAAA,aAAa;KAC1B,EAAE,+CAA+C,EAAE,aAAA,iBAAiB,CAAC,CAAC;AAC3E,CAAC,EAhDgB,YAAY,4BAAZ,YAAY,QAgD5B;AAEY,QAAA,+BAA+B,GAAG,cAAO,CAAC,yBAAyB,CAAC;IAC7E,EAAE,EAAE,qBAAqB;IACzB,SAAS,EAAE,IAAA,iBAAO,EAAC,KAAK,CAAC;IACzB,QAAQ,EAAE,YAAY,CAAC,aAAa;IACpC,KAAK,EAAE,UAAU;CACpB,CAAC,CAAC;AAEU,QAAA,0BAA0B,GAAG,cAAO,CAAC,yBAAyB,CAAC;IACxE,EAAE,EAAE,uBAAuB;IAC3B,SAAS,EAAE,IAAA,iBAAO,EAAC,SAAS,CAAC;IAC7B,QAAQ,EAAE,YAAY,CAAC,aAAa;IACpC,KAAK,EAAE,eAAe;CACzB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theia/ai-chat-ui",
|
|
3
|
-
"version": "1.65.0
|
|
3
|
+
"version": "1.65.0",
|
|
4
4
|
"description": "Theia - AI Chat UI Extension",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@theia/ai-chat": "1.65.0
|
|
7
|
-
"@theia/ai-core": "1.65.0
|
|
8
|
-
"@theia/core": "1.65.0
|
|
9
|
-
"@theia/editor": "1.65.0
|
|
10
|
-
"@theia/editor-preview": "1.65.0
|
|
11
|
-
"@theia/filesystem": "1.65.0
|
|
12
|
-
"@theia/monaco": "1.65.0
|
|
6
|
+
"@theia/ai-chat": "1.65.0",
|
|
7
|
+
"@theia/ai-core": "1.65.0",
|
|
8
|
+
"@theia/core": "1.65.0",
|
|
9
|
+
"@theia/editor": "1.65.0",
|
|
10
|
+
"@theia/editor-preview": "1.65.0",
|
|
11
|
+
"@theia/filesystem": "1.65.0",
|
|
12
|
+
"@theia/monaco": "1.65.0",
|
|
13
13
|
"@theia/monaco-editor-core": "1.96.302",
|
|
14
|
-
"@theia/workspace": "1.65.0
|
|
14
|
+
"@theia/workspace": "1.65.0",
|
|
15
15
|
"date-fns": "^4.1.0",
|
|
16
|
-
"minimatch": "^5.1.0",
|
|
17
16
|
"tslib": "^2.6.2",
|
|
18
17
|
"uuid": "^9.0.1"
|
|
19
18
|
},
|
|
@@ -51,10 +50,10 @@
|
|
|
51
50
|
"watch": "theiaext watch"
|
|
52
51
|
},
|
|
53
52
|
"devDependencies": {
|
|
54
|
-
"@theia/ext-scripts": "1.
|
|
53
|
+
"@theia/ext-scripts": "1.65.0"
|
|
55
54
|
},
|
|
56
55
|
"nyc": {
|
|
57
56
|
"extends": "../../configs/nyc.json"
|
|
58
57
|
},
|
|
59
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "500dfc80cee94fd2a623b5fb59b22d5a575247c2"
|
|
60
59
|
}
|
|
@@ -229,14 +229,14 @@ export class AIChatContribution extends AbstractViewContribution<ChatViewWidget>
|
|
|
229
229
|
registry.registerItem({
|
|
230
230
|
id: AI_CHAT_NEW_CHAT_WINDOW_COMMAND.id,
|
|
231
231
|
command: AI_CHAT_NEW_CHAT_WINDOW_COMMAND.id,
|
|
232
|
-
tooltip:
|
|
232
|
+
tooltip: AI_CHAT_NEW_CHAT_WINDOW_COMMAND.label,
|
|
233
233
|
isVisible: widget => this.activationService.isActive && this.withWidget(widget),
|
|
234
234
|
when: ENABLE_AI_CONTEXT_KEY
|
|
235
235
|
});
|
|
236
236
|
registry.registerItem({
|
|
237
237
|
id: AI_CHAT_SHOW_CHATS_COMMAND.id,
|
|
238
238
|
command: AI_CHAT_SHOW_CHATS_COMMAND.id,
|
|
239
|
-
tooltip:
|
|
239
|
+
tooltip: AI_CHAT_SHOW_CHATS_COMMAND.label,
|
|
240
240
|
isVisible: widget => this.activationService.isActive && this.withWidget(widget),
|
|
241
241
|
when: ENABLE_AI_CONTEXT_KEY
|
|
242
242
|
});
|
|
@@ -82,12 +82,18 @@ export class ChatInputHistoryContribution implements CommandContribution, Keybin
|
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
const position = chatInputWidget.editor.getControl().getPosition();
|
|
86
|
+
const isCursorAtBeginning = position && (position.lineNumber > 1 || position.column > 1);
|
|
87
|
+
if (isCursorAtBeginning) {
|
|
88
|
+
this.positionCursorAtBeginning(chatInputWidget);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
85
92
|
const currentInput = chatInputWidget.editor.getControl().getValue();
|
|
86
93
|
const previousPrompt = chatInputWidget.getPreviousPrompt(currentInput);
|
|
87
|
-
|
|
88
94
|
if (previousPrompt !== undefined) {
|
|
89
95
|
chatInputWidget.editor.getControl().setValue(previousPrompt);
|
|
90
|
-
this.
|
|
96
|
+
this.positionCursorAtBeginning(chatInputWidget);
|
|
91
97
|
}
|
|
92
98
|
}
|
|
93
99
|
|
|
@@ -97,14 +103,31 @@ export class ChatInputHistoryContribution implements CommandContribution, Keybin
|
|
|
97
103
|
return;
|
|
98
104
|
}
|
|
99
105
|
|
|
100
|
-
const
|
|
106
|
+
const position = chatInputWidget.editor.getControl().getPosition();
|
|
107
|
+
const model = chatInputWidget.editor.getControl().getModel();
|
|
108
|
+
const isCursorAtEnd = position && model && (
|
|
109
|
+
position.lineNumber < model.getLineCount() || position.column < model.getLineMaxColumn(position.lineNumber)
|
|
110
|
+
);
|
|
111
|
+
if (isCursorAtEnd) {
|
|
112
|
+
this.positionCursorAtEnd(chatInputWidget);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
101
115
|
|
|
116
|
+
const nextPrompt = chatInputWidget.getNextPrompt();
|
|
102
117
|
if (nextPrompt !== undefined) {
|
|
103
118
|
chatInputWidget.editor.getControl().setValue(nextPrompt);
|
|
104
119
|
this.positionCursorAtEnd(chatInputWidget);
|
|
105
120
|
}
|
|
106
121
|
}
|
|
107
122
|
|
|
123
|
+
protected positionCursorAtBeginning(widget: AIChatInputWidget): void {
|
|
124
|
+
const editor = widget.editor?.getControl();
|
|
125
|
+
if (editor) {
|
|
126
|
+
editor.setPosition({ lineNumber: 1, column: 1 });
|
|
127
|
+
editor.focus();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
108
131
|
protected positionCursorAtEnd(widget: AIChatInputWidget): void {
|
|
109
132
|
const editor = widget.editor?.getControl();
|
|
110
133
|
const model = editor?.getModel();
|
|
@@ -114,13 +137,6 @@ export class ChatInputHistoryContribution implements CommandContribution, Keybin
|
|
|
114
137
|
const lastColumn = model.getLineContent(lastLine).length + 1;
|
|
115
138
|
editor.setPosition({ lineNumber: lastLine, column: lastColumn });
|
|
116
139
|
editor.focus();
|
|
117
|
-
|
|
118
|
-
setTimeout(() => {
|
|
119
|
-
// Trigger cursor position update after setting value
|
|
120
|
-
if (widget.editor?.getControl().hasWidgetFocus()) {
|
|
121
|
-
widget.updateCursorPositionKeys();
|
|
122
|
-
}
|
|
123
|
-
}, 0);
|
|
124
140
|
}
|
|
125
141
|
}
|
|
126
142
|
|
|
@@ -15,13 +15,14 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
import {
|
|
17
17
|
ChangeSet, ChangeSetElement, ChatAgent, ChatChangeEvent, ChatHierarchyBranch,
|
|
18
|
-
ChatModel, ChatRequestModel, ChatService, ChatSuggestion, EditableChatRequestModel
|
|
18
|
+
ChatModel, ChatRequestModel, ChatService, ChatSuggestion, EditableChatRequestModel,
|
|
19
|
+
ChatRequestParser
|
|
19
20
|
} from '@theia/ai-chat';
|
|
20
21
|
import { ChangeSetDecoratorService } from '@theia/ai-chat/lib/browser/change-set-decorator-service';
|
|
21
22
|
import { ImageContextVariable } from '@theia/ai-chat/lib/common/image-context-variable';
|
|
22
23
|
import { AIVariableResolutionRequest } from '@theia/ai-core';
|
|
23
24
|
import { AgentCompletionNotificationService, FrontendVariableService, AIActivationService } from '@theia/ai-core/lib/browser';
|
|
24
|
-
import { DisposableCollection, Emitter, InMemoryResources, URI, nls } from '@theia/core';
|
|
25
|
+
import { DisposableCollection, Emitter, InMemoryResources, URI, nls, Disposable } from '@theia/core';
|
|
25
26
|
import { ContextMenuRenderer, LabelProvider, Message, OpenerService, ReactWidget } from '@theia/core/lib/browser';
|
|
26
27
|
import { ContextKey, ContextKeyService } from '@theia/core/lib/browser/context-key-service';
|
|
27
28
|
import { Deferred } from '@theia/core/lib/common/promise-util';
|
|
@@ -36,6 +37,7 @@ import { CHAT_VIEW_LANGUAGE_EXTENSION } from './chat-view-language-contribution'
|
|
|
36
37
|
import { ContextVariablePicker } from './context-variable-picker';
|
|
37
38
|
import { TASK_CONTEXT_VARIABLE } from '@theia/ai-chat/lib/browser/task-context-variable';
|
|
38
39
|
import { IModelDeltaDecoration } from '@theia/monaco-editor-core/esm/vs/editor/common/model';
|
|
40
|
+
import { EditorOption } from '@theia/monaco-editor-core/esm/vs/editor/common/config/editorOptions';
|
|
39
41
|
import { ChatInputHistoryService, ChatInputNavigationState } from './chat-input-history';
|
|
40
42
|
|
|
41
43
|
type Query = (query: string) => Promise<void>;
|
|
@@ -101,6 +103,9 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
101
103
|
@inject(ChatInputHistoryService)
|
|
102
104
|
protected readonly historyService: ChatInputHistoryService;
|
|
103
105
|
|
|
106
|
+
@inject(ChatRequestParser)
|
|
107
|
+
protected readonly chatRequestParser: ChatRequestParser;
|
|
108
|
+
|
|
104
109
|
protected navigationState: ChatInputNavigationState;
|
|
105
110
|
|
|
106
111
|
@inject(ContextKeyService)
|
|
@@ -134,10 +139,13 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
134
139
|
protected chatInputFocusKey: ContextKey<boolean>;
|
|
135
140
|
protected chatInputFirstLineKey: ContextKey<boolean>;
|
|
136
141
|
protected chatInputLastLineKey: ContextKey<boolean>;
|
|
142
|
+
protected chatInputReceivingAgentKey: ContextKey<string>;
|
|
137
143
|
|
|
138
144
|
protected isEnabled = false;
|
|
139
145
|
protected heightInLines = 12;
|
|
140
146
|
|
|
147
|
+
protected updateReceivingAgentTimeout: number | undefined;
|
|
148
|
+
|
|
141
149
|
protected _branch?: ChatHierarchyBranch;
|
|
142
150
|
set branch(branch: ChatHierarchyBranch | undefined) {
|
|
143
151
|
if (this._branch !== branch) {
|
|
@@ -189,11 +197,13 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
189
197
|
}
|
|
190
198
|
}));
|
|
191
199
|
this._chatModel = chatModel;
|
|
200
|
+
this.scheduleUpdateReceivingAgent();
|
|
192
201
|
this.update();
|
|
193
202
|
}
|
|
194
203
|
protected _pinnedAgent: ChatAgent | undefined;
|
|
195
204
|
set pinnedAgent(pinnedAgent: ChatAgent | undefined) {
|
|
196
205
|
this._pinnedAgent = pinnedAgent;
|
|
206
|
+
this.scheduleUpdateReceivingAgent();
|
|
197
207
|
this.update();
|
|
198
208
|
}
|
|
199
209
|
|
|
@@ -209,6 +219,12 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
209
219
|
this.setEnabled(this.aiActivationService.isActive);
|
|
210
220
|
}));
|
|
211
221
|
this.toDispose.push(this.onDidResizeEmitter);
|
|
222
|
+
this.toDispose.push(Disposable.create(() => {
|
|
223
|
+
if (this.updateReceivingAgentTimeout !== undefined) {
|
|
224
|
+
clearTimeout(this.updateReceivingAgentTimeout);
|
|
225
|
+
this.updateReceivingAgentTimeout = undefined;
|
|
226
|
+
}
|
|
227
|
+
}));
|
|
212
228
|
this.setEnabled(this.aiActivationService.isActive);
|
|
213
229
|
this.historyService.init().then(() => {
|
|
214
230
|
this.navigationState = new ChatInputNavigationState(this.historyService);
|
|
@@ -221,6 +237,7 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
221
237
|
this.chatInputFocusKey = this.contextKeyService.createKey<boolean>('chatInputFocus', false);
|
|
222
238
|
this.chatInputFirstLineKey = this.contextKeyService.createKey<boolean>('chatInputFirstLine', false);
|
|
223
239
|
this.chatInputLastLineKey = this.contextKeyService.createKey<boolean>('chatInputLastLine', false);
|
|
240
|
+
this.chatInputReceivingAgentKey = this.contextKeyService.createKey<string>('chatInputReceivingAgent', '');
|
|
224
241
|
}
|
|
225
242
|
|
|
226
243
|
updateCursorPositionKeys(): void {
|
|
@@ -240,11 +257,57 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
240
257
|
return;
|
|
241
258
|
}
|
|
242
259
|
|
|
243
|
-
const
|
|
244
|
-
const
|
|
260
|
+
const line = position.lineNumber;
|
|
261
|
+
const col = position.column;
|
|
262
|
+
|
|
263
|
+
const topAtPos = editor.getTopForPosition(line, col);
|
|
264
|
+
const topAtLineStart = editor.getTopForLineNumber(line);
|
|
265
|
+
const topAtLineEnd = editor.getTopForPosition(line, model.getLineMaxColumn(line));
|
|
266
|
+
const lineHeight = editor.getOption(EditorOption.lineHeight);
|
|
267
|
+
const toleranceValue = 0.5;
|
|
268
|
+
|
|
269
|
+
const isFirstVisualOfThisLine = Math.abs(topAtPos - topAtLineStart) < toleranceValue;
|
|
270
|
+
const isLastVisualOfThisLine = Math.abs(topAtPos - topAtLineEnd) < toleranceValue || (topAtPos > topAtLineEnd - lineHeight + toleranceValue);
|
|
271
|
+
const isFirstVisualOverall = line === 1 && isFirstVisualOfThisLine;
|
|
245
272
|
|
|
246
|
-
|
|
247
|
-
|
|
273
|
+
const isLastVisualOverall = line === model.getLineCount() && isLastVisualOfThisLine;
|
|
274
|
+
|
|
275
|
+
this.chatInputFirstLineKey.set(isFirstVisualOverall);
|
|
276
|
+
this.chatInputLastLineKey.set(isLastVisualOverall);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
protected scheduleUpdateReceivingAgent(): void {
|
|
280
|
+
if (this.updateReceivingAgentTimeout !== undefined) {
|
|
281
|
+
clearTimeout(this.updateReceivingAgentTimeout);
|
|
282
|
+
}
|
|
283
|
+
this.updateReceivingAgentTimeout = window.setTimeout(() => {
|
|
284
|
+
this.updateReceivingAgent();
|
|
285
|
+
this.updateReceivingAgentTimeout = undefined;
|
|
286
|
+
}, 200);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
protected async updateReceivingAgent(): Promise<void> {
|
|
290
|
+
if (!this.editorRef || !this._chatModel) {
|
|
291
|
+
this.chatInputReceivingAgentKey.set('');
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
try {
|
|
296
|
+
const inputText = this.editorRef.getControl().getValue();
|
|
297
|
+
const request = { text: inputText };
|
|
298
|
+
const resolvedContext = { variables: [] };
|
|
299
|
+
const parsedRequest = await this.chatRequestParser.parseChatRequest(request, this._chatModel.location, resolvedContext);
|
|
300
|
+
const session = this.chatService.getSessions().find(s => s.model.id === this._chatModel.id);
|
|
301
|
+
if (session) {
|
|
302
|
+
const agent = this.chatService.getAgent(parsedRequest, session);
|
|
303
|
+
this.chatInputReceivingAgentKey.set(agent?.id ?? '');
|
|
304
|
+
} else {
|
|
305
|
+
this.chatInputReceivingAgentKey.set('');
|
|
306
|
+
}
|
|
307
|
+
} catch (error) {
|
|
308
|
+
console.warn('Failed to determine receiving agent:', error);
|
|
309
|
+
this.chatInputReceivingAgentKey.set('');
|
|
310
|
+
}
|
|
248
311
|
}
|
|
249
312
|
|
|
250
313
|
protected setupEditorEventListeners(): void {
|
|
@@ -275,6 +338,7 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
275
338
|
if (editor.hasWidgetFocus()) {
|
|
276
339
|
this.updateCursorPositionKeys();
|
|
277
340
|
}
|
|
341
|
+
this.scheduleUpdateReceivingAgent();
|
|
278
342
|
}));
|
|
279
343
|
|
|
280
344
|
if (editor.hasWidgetFocus()) {
|
|
@@ -319,7 +383,6 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
319
383
|
const isEditing = !!(currentRequest && (EditableChatRequestModel.isEditing(currentRequest)));
|
|
320
384
|
const isPending = () => !!(currentRequest && !isEditing && ChatRequestModel.isInProgress(currentRequest));
|
|
321
385
|
const pending = isPending();
|
|
322
|
-
const hasPromptHistory = this.configuration?.enablePromptHistory && this.historyService.getPrompts().length > 0;
|
|
323
386
|
|
|
324
387
|
return (
|
|
325
388
|
<ChatInput
|
|
@@ -353,7 +416,7 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
353
416
|
showPinnedAgent={this.configuration?.showPinnedAgent}
|
|
354
417
|
showChangeSet={this.configuration?.showChangeSet}
|
|
355
418
|
showSuggestions={this.configuration?.showSuggestions}
|
|
356
|
-
hasPromptHistory={
|
|
419
|
+
hasPromptHistory={this.configuration?.enablePromptHistory}
|
|
357
420
|
labelProvider={this.labelProvider}
|
|
358
421
|
actionService={this.changeSetActionService}
|
|
359
422
|
decoratorService={this.changeSetDecoratorService}
|
|
@@ -529,6 +592,8 @@ const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInpu
|
|
|
529
592
|
const onDeleteChangeSetElement = (uri: URI) => props.onDeleteChangeSetElement(props.chatModel.id, uri);
|
|
530
593
|
|
|
531
594
|
const [isInputEmpty, setIsInputEmpty] = React.useState(true);
|
|
595
|
+
const [isInputFocused, setIsInputFocused] = React.useState(false);
|
|
596
|
+
const [placeholderText, setPlaceholderText] = React.useState('');
|
|
532
597
|
const [changeSetUI, setChangeSetUI] = React.useState(
|
|
533
598
|
() => buildChangeSetUI(
|
|
534
599
|
props.chatModel.changeSet,
|
|
@@ -552,11 +617,16 @@ const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInpu
|
|
|
552
617
|
const isFirstRequest = props.chatModel.getRequests().length === 0;
|
|
553
618
|
const shouldUseTaskPlaceholder = isFirstRequest && props.pinnedAgent && hasTaskContext(props.chatModel);
|
|
554
619
|
const taskPlaceholder = nls.localize('theia/ai/chat-ui/performThisTask', 'Perform this task.');
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
620
|
+
|
|
621
|
+
// Update placeholder text when focus state or other dependencies change
|
|
622
|
+
React.useEffect(() => {
|
|
623
|
+
const newPlaceholderText = !props.isEnabled
|
|
624
|
+
? nls.localize('theia/ai/chat-ui/aiDisabled', 'AI features are disabled')
|
|
625
|
+
: shouldUseTaskPlaceholder
|
|
626
|
+
? taskPlaceholder
|
|
627
|
+
: nls.localizeByDefault('Ask a question') + (props.hasPromptHistory && isInputFocused ? nls.localizeByDefault(' ({0} for history)', '⇅') : '');
|
|
628
|
+
setPlaceholderText(newPlaceholderText);
|
|
629
|
+
}, [props.isEnabled, shouldUseTaskPlaceholder, taskPlaceholder, props.hasPromptHistory, isInputFocused]);
|
|
560
630
|
|
|
561
631
|
// Handle paste events on the container
|
|
562
632
|
const handlePaste = React.useCallback((event: ClipboardEvent) => {
|
|
@@ -797,6 +867,7 @@ const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInpu
|
|
|
797
867
|
}, [props.isEnabled, submit]);
|
|
798
868
|
|
|
799
869
|
const handleInputFocus = () => {
|
|
870
|
+
setIsInputFocused(true);
|
|
800
871
|
hidePlaceholderIfEditorFilled();
|
|
801
872
|
};
|
|
802
873
|
|
|
@@ -806,6 +877,7 @@ const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInpu
|
|
|
806
877
|
};
|
|
807
878
|
|
|
808
879
|
const handleInputBlur = () => {
|
|
880
|
+
setIsInputFocused(false);
|
|
809
881
|
showPlaceholderIfEditorEmpty();
|
|
810
882
|
};
|
|
811
883
|
|
|
@@ -18,26 +18,29 @@ import { Command, nls } from '@theia/core';
|
|
|
18
18
|
import { codicon } from '@theia/core/lib/browser';
|
|
19
19
|
|
|
20
20
|
export namespace ChatCommands {
|
|
21
|
-
const CHAT_CATEGORY = 'Chat';
|
|
22
|
-
const CHAT_CATEGORY_KEY = nls.getDefaultKey(CHAT_CATEGORY);
|
|
21
|
+
export const CHAT_CATEGORY = 'Chat';
|
|
22
|
+
export const CHAT_CATEGORY_KEY = nls.getDefaultKey(CHAT_CATEGORY);
|
|
23
23
|
|
|
24
24
|
export const SCROLL_LOCK_WIDGET = Command.toLocalizedCommand({
|
|
25
25
|
id: 'chat:widget:lock',
|
|
26
26
|
category: CHAT_CATEGORY,
|
|
27
|
-
iconClass: codicon('unlock')
|
|
28
|
-
|
|
27
|
+
iconClass: codicon('unlock'),
|
|
28
|
+
label: 'Lock Scroll'
|
|
29
|
+
}, 'theia/ai-chat-ui/scroll-lock', CHAT_CATEGORY_KEY);
|
|
29
30
|
|
|
30
31
|
export const SCROLL_UNLOCK_WIDGET = Command.toLocalizedCommand({
|
|
31
32
|
id: 'chat:widget:unlock',
|
|
32
33
|
category: CHAT_CATEGORY,
|
|
33
|
-
iconClass: codicon('lock')
|
|
34
|
-
|
|
34
|
+
iconClass: codicon('lock'),
|
|
35
|
+
label: 'Unlock Scroll'
|
|
36
|
+
}, 'theia/ai-chat-ui/scroll-unlock', CHAT_CATEGORY_KEY);
|
|
35
37
|
|
|
36
38
|
export const EDIT_SESSION_SETTINGS = Command.toLocalizedCommand({
|
|
37
39
|
id: 'chat:widget:session-settings',
|
|
38
40
|
category: CHAT_CATEGORY,
|
|
39
|
-
iconClass: codicon('bracket')
|
|
40
|
-
|
|
41
|
+
iconClass: codicon('bracket'),
|
|
42
|
+
label: 'Set Session Settings'
|
|
43
|
+
}, 'theia/ai-chat-ui/session-settings', CHAT_CATEGORY_KEY);
|
|
41
44
|
|
|
42
45
|
export const AI_CHAT_NEW_WITH_TASK_CONTEXT: Command = {
|
|
43
46
|
id: 'ai-chat.new-with-task-context',
|
|
@@ -47,29 +50,33 @@ export namespace ChatCommands {
|
|
|
47
50
|
id: 'ai-chat.initiate-session-with-task-context',
|
|
48
51
|
label: 'Task Context: Initiate Session',
|
|
49
52
|
category: CHAT_CATEGORY
|
|
50
|
-
},
|
|
53
|
+
}, 'theia/ai-chat-ui/initiate-session-task-context', CHAT_CATEGORY_KEY);
|
|
51
54
|
|
|
52
55
|
export const AI_CHAT_SUMMARIZE_CURRENT_SESSION = Command.toLocalizedCommand({
|
|
53
56
|
id: 'ai-chat-summary-current-session',
|
|
54
57
|
iconClass: codicon('go-to-editing-session'),
|
|
55
58
|
label: 'Summarize Current Session',
|
|
56
59
|
category: CHAT_CATEGORY
|
|
57
|
-
},
|
|
60
|
+
}, 'theia/ai-chat-ui/summarize-current-session', CHAT_CATEGORY_KEY);
|
|
58
61
|
|
|
59
62
|
export const AI_CHAT_OPEN_SUMMARY_FOR_CURRENT_SESSION = Command.toLocalizedCommand({
|
|
60
63
|
id: 'ai-chat-open-current-session-summary',
|
|
61
64
|
iconClass: codicon('note'),
|
|
62
65
|
label: 'Open Current Session Summary',
|
|
63
66
|
category: CHAT_CATEGORY
|
|
64
|
-
},
|
|
67
|
+
}, 'theia/ai-chat-ui/open-current-session-summary', CHAT_CATEGORY_KEY);
|
|
65
68
|
}
|
|
66
69
|
|
|
67
|
-
export const AI_CHAT_NEW_CHAT_WINDOW_COMMAND
|
|
70
|
+
export const AI_CHAT_NEW_CHAT_WINDOW_COMMAND = Command.toDefaultLocalizedCommand({
|
|
68
71
|
id: 'ai-chat-ui.new-chat',
|
|
69
|
-
iconClass: codicon('add')
|
|
70
|
-
|
|
72
|
+
iconClass: codicon('add'),
|
|
73
|
+
category: ChatCommands.CHAT_CATEGORY,
|
|
74
|
+
label: 'New Chat'
|
|
75
|
+
});
|
|
71
76
|
|
|
72
|
-
export const AI_CHAT_SHOW_CHATS_COMMAND
|
|
77
|
+
export const AI_CHAT_SHOW_CHATS_COMMAND = Command.toDefaultLocalizedCommand({
|
|
73
78
|
id: 'ai-chat-ui.show-chats',
|
|
74
|
-
iconClass: codicon('history')
|
|
75
|
-
|
|
79
|
+
iconClass: codicon('history'),
|
|
80
|
+
category: ChatCommands.CHAT_CATEGORY,
|
|
81
|
+
label: 'Show Chats...'
|
|
82
|
+
});
|