@theia/ai-chat-ui 1.68.0-next.8 → 1.68.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 +33 -0
- package/lib/browser/ai-chat-ui-contribution.d.ts +2 -1
- package/lib/browser/ai-chat-ui-contribution.d.ts.map +1 -1
- package/lib/browser/ai-chat-ui-contribution.js +41 -32
- package/lib/browser/ai-chat-ui-contribution.js.map +1 -1
- package/lib/browser/ai-chat-ui-frontend-module.d.ts.map +1 -1
- package/lib/browser/ai-chat-ui-frontend-module.js +15 -6
- package/lib/browser/ai-chat-ui-frontend-module.js.map +1 -1
- package/lib/browser/change-set-actions/change-set-accept-action.d.ts +0 -1
- package/lib/browser/change-set-actions/change-set-accept-action.d.ts.map +1 -1
- package/lib/browser/change-set-actions/change-set-action-service.d.ts +0 -1
- package/lib/browser/change-set-actions/change-set-action-service.d.ts.map +1 -1
- package/lib/browser/change-set-actions/change-set-action-service.js +2 -2
- package/lib/browser/change-set-actions/change-set-action-service.js.map +1 -1
- package/lib/browser/chat-focus-contribution.d.ts +14 -0
- package/lib/browser/chat-focus-contribution.d.ts.map +1 -0
- package/lib/browser/chat-focus-contribution.js +102 -0
- package/lib/browser/chat-focus-contribution.js.map +1 -0
- package/lib/browser/chat-input-agent-suggestions.d.ts +0 -1
- package/lib/browser/chat-input-agent-suggestions.d.ts.map +1 -1
- package/lib/browser/chat-input-agent-suggestions.js +1 -1
- package/lib/browser/chat-input-agent-suggestions.js.map +1 -1
- package/lib/browser/chat-input-history-contribution.js +6 -10
- package/lib/browser/chat-input-history-contribution.js.map +1 -1
- package/lib/browser/chat-input-mode-contribution.js +1 -2
- package/lib/browser/chat-input-mode-contribution.js.map +1 -1
- package/lib/browser/chat-input-widget.d.ts +0 -1
- package/lib/browser/chat-input-widget.d.ts.map +1 -1
- package/lib/browser/chat-input-widget.js +106 -96
- package/lib/browser/chat-input-widget.js.map +1 -1
- package/lib/browser/chat-progress-message.d.ts +0 -1
- package/lib/browser/chat-progress-message.d.ts.map +1 -1
- package/lib/browser/chat-response-part-renderer.d.ts +0 -1
- package/lib/browser/chat-response-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/ai-selection-resolver.js +4 -5
- package/lib/browser/chat-response-renderer/ai-selection-resolver.js.map +1 -1
- package/lib/browser/chat-response-renderer/code-part-renderer.d.ts +0 -1
- package/lib/browser/chat-response-renderer/code-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/code-part-renderer.js +6 -9
- package/lib/browser/chat-response-renderer/code-part-renderer.js.map +1 -1
- package/lib/browser/chat-response-renderer/command-part-renderer.d.ts +0 -1
- package/lib/browser/chat-response-renderer/command-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/command-part-renderer.js +7 -4
- package/lib/browser/chat-response-renderer/command-part-renderer.js.map +1 -1
- package/lib/browser/chat-response-renderer/delegation-response-renderer.d.ts +0 -1
- package/lib/browser/chat-response-renderer/delegation-response-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/delegation-response-renderer.js +3 -4
- package/lib/browser/chat-response-renderer/delegation-response-renderer.js.map +1 -1
- package/lib/browser/chat-response-renderer/error-part-renderer.d.ts +0 -1
- package/lib/browser/chat-response-renderer/error-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/horizontal-layout-part-renderer.d.ts +0 -1
- package/lib/browser/chat-response-renderer/horizontal-layout-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/index.d.ts +1 -0
- package/lib/browser/chat-response-renderer/index.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/index.js +1 -0
- package/lib/browser/chat-response-renderer/index.js.map +1 -1
- package/lib/browser/chat-response-renderer/markdown-part-renderer.d.ts +0 -1
- package/lib/browser/chat-response-renderer/markdown-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/markdown-part-renderer.js +7 -9
- package/lib/browser/chat-response-renderer/markdown-part-renderer.js.map +1 -1
- package/lib/browser/chat-response-renderer/not-available-toolcall-renderer.d.ts +17 -0
- package/lib/browser/chat-response-renderer/not-available-toolcall-renderer.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/not-available-toolcall-renderer.js +56 -0
- package/lib/browser/chat-response-renderer/not-available-toolcall-renderer.js.map +1 -0
- package/lib/browser/chat-response-renderer/progress-part-renderer.d.ts +0 -1
- package/lib/browser/chat-response-renderer/progress-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/question-part-renderer.d.ts +0 -1
- package/lib/browser/chat-response-renderer/question-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/question-part-renderer.js +6 -9
- package/lib/browser/chat-response-renderer/question-part-renderer.js.map +1 -1
- package/lib/browser/chat-response-renderer/text-part-renderer.d.ts +0 -1
- package/lib/browser/chat-response-renderer/text-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/thinking-part-renderer.d.ts +0 -1
- package/lib/browser/chat-response-renderer/thinking-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/tool-confirmation.d.ts +29 -10
- package/lib/browser/chat-response-renderer/tool-confirmation.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/tool-confirmation.js +219 -65
- package/lib/browser/chat-response-renderer/tool-confirmation.js.map +1 -1
- package/lib/browser/chat-response-renderer/tool-confirmation.spec.d.ts +2 -0
- package/lib/browser/chat-response-renderer/tool-confirmation.spec.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/tool-confirmation.spec.js +100 -0
- package/lib/browser/chat-response-renderer/tool-confirmation.spec.js.map +1 -0
- package/lib/browser/chat-response-renderer/toolcall-part-renderer.d.ts +5 -3
- package/lib/browser/chat-response-renderer/toolcall-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/toolcall-part-renderer.js +21 -11
- package/lib/browser/chat-response-renderer/toolcall-part-renderer.js.map +1 -1
- package/lib/browser/chat-response-renderer/unknown-part-renderer.d.ts +0 -1
- package/lib/browser/chat-response-renderer/unknown-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/unknown-part-renderer.js +1 -2
- package/lib/browser/chat-response-renderer/unknown-part-renderer.js.map +1 -1
- package/lib/browser/chat-tree-view/chat-view-tree-container.js +1 -2
- package/lib/browser/chat-tree-view/chat-view-tree-container.js.map +1 -1
- package/lib/browser/chat-tree-view/chat-view-tree-input-widget.js +2 -3
- package/lib/browser/chat-tree-view/chat-view-tree-input-widget.js.map +1 -1
- package/lib/browser/chat-tree-view/chat-view-tree-widget.d.ts +3 -1
- package/lib/browser/chat-tree-view/chat-view-tree-widget.d.ts.map +1 -1
- package/lib/browser/chat-tree-view/chat-view-tree-widget.js +49 -42
- package/lib/browser/chat-tree-view/chat-view-tree-widget.js.map +1 -1
- package/lib/browser/chat-tree-view/prompt-variant-badge.d.ts +0 -1
- package/lib/browser/chat-tree-view/prompt-variant-badge.d.ts.map +1 -1
- package/lib/browser/chat-tree-view/sub-chat-widget.d.ts +0 -1
- package/lib/browser/chat-tree-view/sub-chat-widget.d.ts.map +1 -1
- package/lib/browser/chat-view-commands.d.ts.map +1 -1
- package/lib/browser/chat-view-commands.js +2 -2
- package/lib/browser/chat-view-commands.js.map +1 -1
- package/lib/browser/chat-view-contribution.js +7 -7
- package/lib/browser/chat-view-contribution.js.map +1 -1
- package/lib/browser/chat-view-language-contribution.js +3 -4
- package/lib/browser/chat-view-language-contribution.js.map +1 -1
- package/lib/browser/chat-view-widget.js +9 -10
- package/lib/browser/chat-view-widget.js.map +1 -1
- package/lib/browser/context-variable-picker.js +9 -13
- package/lib/browser/context-variable-picker.js.map +1 -1
- package/lib/browser/session-storage-preference-renderer.d.ts +127 -0
- package/lib/browser/session-storage-preference-renderer.d.ts.map +1 -0
- package/lib/browser/session-storage-preference-renderer.js +490 -0
- package/lib/browser/session-storage-preference-renderer.js.map +1 -0
- package/package.json +12 -11
- package/src/browser/ai-chat-ui-contribution.ts +19 -7
- package/src/browser/ai-chat-ui-frontend-module.ts +13 -0
- package/src/browser/chat-focus-contribution.ts +102 -0
- package/src/browser/chat-input-widget.tsx +99 -27
- package/src/browser/chat-response-renderer/index.ts +1 -0
- package/src/browser/chat-response-renderer/not-available-toolcall-renderer.tsx +57 -0
- package/src/browser/chat-response-renderer/tool-confirmation.spec.ts +108 -0
- package/src/browser/chat-response-renderer/tool-confirmation.tsx +379 -95
- package/src/browser/chat-response-renderer/toolcall-part-renderer.tsx +27 -13
- package/src/browser/chat-tree-view/chat-view-tree-widget.tsx +33 -5
- package/src/browser/chat-view-commands.ts +2 -2
- package/src/browser/session-storage-preference-renderer.ts +657 -0
- package/src/browser/style/index.css +73 -26
- package/src/browser/style/session-storage-preference.css +134 -0
|
@@ -38,7 +38,7 @@ const task_context_variable_1 = require("@theia/ai-chat/lib/browser/task-context
|
|
|
38
38
|
const chat_input_history_1 = require("./chat-input-history");
|
|
39
39
|
const context_file_validation_service_1 = require("@theia/ai-chat/lib/browser/context-file-validation-service");
|
|
40
40
|
exports.AIChatInputConfiguration = Symbol('AIChatInputConfiguration');
|
|
41
|
-
let AIChatInputWidget =
|
|
41
|
+
let AIChatInputWidget = class AIChatInputWidget extends browser_2.ReactWidget {
|
|
42
42
|
constructor() {
|
|
43
43
|
super(...arguments);
|
|
44
44
|
this.fileValidationState = new Map();
|
|
@@ -56,6 +56,9 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
|
|
|
56
56
|
this.onDidResizeEmitter = new core_1.Emitter();
|
|
57
57
|
this.onDidResize = this.onDidResizeEmitter.event;
|
|
58
58
|
}
|
|
59
|
+
static { AIChatInputWidget_1 = this; }
|
|
60
|
+
static { this.ID = 'chat-input-widget'; }
|
|
61
|
+
static { this.CONTEXT_MENU = ['chat-input-context-menu']; }
|
|
59
62
|
get editor() {
|
|
60
63
|
return this.editorRef;
|
|
61
64
|
}
|
|
@@ -94,8 +97,7 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
|
|
|
94
97
|
}
|
|
95
98
|
set onQuery(query) {
|
|
96
99
|
this._onQuery = (prompt, mode) => {
|
|
97
|
-
|
|
98
|
-
if (((_a = this.configuration) === null || _a === void 0 ? void 0 : _a.enablePromptHistory) !== false && prompt.trim()) {
|
|
100
|
+
if (this.configuration?.enablePromptHistory !== false && prompt.trim()) {
|
|
99
101
|
this.historyService.addToHistory(prompt);
|
|
100
102
|
this.navigationState.stopNavigation();
|
|
101
103
|
}
|
|
@@ -219,7 +221,6 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
|
|
|
219
221
|
}, 200);
|
|
220
222
|
}
|
|
221
223
|
async updateReceivingAgent() {
|
|
222
|
-
var _a, _b, _c;
|
|
223
224
|
if (!this.editorRef || !this._chatModel) {
|
|
224
225
|
if (this.receivingAgent !== undefined) {
|
|
225
226
|
this.chatInputReceivingAgentKey.set('');
|
|
@@ -237,15 +238,18 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
|
|
|
237
238
|
const session = this.chatService.getSessions().find(s => s.model.id === this._chatModel.id);
|
|
238
239
|
if (session) {
|
|
239
240
|
const agent = this.chatService.getAgent(parsedRequest, session);
|
|
240
|
-
const agentId =
|
|
241
|
-
const previousAgentId =
|
|
241
|
+
const agentId = agent?.id ?? '';
|
|
242
|
+
const previousAgentId = this.receivingAgent?.agentId;
|
|
242
243
|
this.chatInputReceivingAgentKey.set(agentId);
|
|
243
244
|
// Only update and re-render when the agent changes
|
|
244
245
|
if (agent && agentId !== previousAgentId) {
|
|
245
|
-
const modes =
|
|
246
|
+
const modes = agent.modes ?? [];
|
|
247
|
+
const defaultMode = modes.find(m => m.isDefault);
|
|
248
|
+
const initialModeId = defaultMode?.id;
|
|
246
249
|
this.receivingAgent = {
|
|
247
250
|
agentId: agentId,
|
|
248
|
-
modes
|
|
251
|
+
modes,
|
|
252
|
+
currentModeId: initialModeId
|
|
249
253
|
};
|
|
250
254
|
this.chatInputHasModesKey.set(modes.length > 1);
|
|
251
255
|
this.update();
|
|
@@ -326,13 +330,12 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
|
|
|
326
330
|
return new core_1.URI(`ai-chat:/input.${chat_view_language_contribution_1.CHAT_VIEW_LANGUAGE_EXTENSION}`);
|
|
327
331
|
}
|
|
328
332
|
render() {
|
|
329
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
330
333
|
const branch = this._branch;
|
|
331
334
|
const chatModel = this._chatModel;
|
|
332
335
|
// State of the input widget's action buttons depends on the state of the currently active or last processed
|
|
333
336
|
// request, if there is one. If the chat model has branched, then the current request is the last on the
|
|
334
337
|
// branch. Otherwise, it's the last request in the chat model.
|
|
335
|
-
const currentRequest =
|
|
338
|
+
const currentRequest = branch?.items?.at(-1)?.element ?? chatModel.getRequests().at(-1);
|
|
336
339
|
const isEditing = !!(currentRequest && (ai_chat_1.EditableChatRequestModel.isEditing(currentRequest)));
|
|
337
340
|
const isPending = () => !!(currentRequest && !isEditing && ai_chat_1.ChatRequestModel.isInProgress(currentRequest));
|
|
338
341
|
const pending = isPending();
|
|
@@ -340,22 +343,22 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
|
|
|
340
343
|
this.editorRef = editor;
|
|
341
344
|
this.setupEditorEventListeners();
|
|
342
345
|
this.editorReady.resolve();
|
|
343
|
-
|
|
346
|
+
this.scheduleUpdateReceivingAgent();
|
|
347
|
+
}, showContext: this.configuration?.showContext, showPinnedAgent: this.configuration?.showPinnedAgent, showChangeSet: this.configuration?.showChangeSet, showSuggestions: this.configuration?.showSuggestions, hasPromptHistory: this.configuration?.enablePromptHistory, labelProvider: this.labelProvider, actionService: this.changeSetActionService, decoratorService: this.changeSetDecoratorService, initialValue: this._initialValue, openerService: this.openerService, suggestions: this._chatModel.suggestions, currentRequest: currentRequest, isEditing: isEditing, pending: pending, heightInLines: this.heightInLines, onResponseChanged: () => {
|
|
344
348
|
if (isPending() !== pending) {
|
|
345
349
|
this.update();
|
|
346
350
|
}
|
|
347
351
|
}, onResize: () => this.onDidResizeEmitter.fire(), modeSelectorProps: {
|
|
348
|
-
receivingAgentModes:
|
|
349
|
-
currentMode:
|
|
352
|
+
receivingAgentModes: this.receivingAgent?.modes,
|
|
353
|
+
currentMode: this.receivingAgent?.currentModeId,
|
|
350
354
|
onModeChange: this.handleModeChange,
|
|
351
355
|
} }));
|
|
352
356
|
}
|
|
353
357
|
onDragOver(event) {
|
|
354
|
-
var _a;
|
|
355
358
|
event.preventDefault();
|
|
356
359
|
event.stopPropagation();
|
|
357
360
|
this.node.classList.add('drag-over');
|
|
358
|
-
if (
|
|
361
|
+
if (event.dataTransfer?.types.includes('text/plain')) {
|
|
359
362
|
event.dataTransfer.dropEffect = 'copy';
|
|
360
363
|
}
|
|
361
364
|
else {
|
|
@@ -363,18 +366,16 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
|
|
|
363
366
|
}
|
|
364
367
|
}
|
|
365
368
|
onDrop(event) {
|
|
366
|
-
var _a, _b, _c;
|
|
367
369
|
event.preventDefault();
|
|
368
370
|
event.stopPropagation();
|
|
369
371
|
this.node.classList.remove('drag-over');
|
|
370
|
-
const dataTransferText =
|
|
371
|
-
const position =
|
|
372
|
+
const dataTransferText = event.dataTransfer?.getData('text/plain');
|
|
373
|
+
const position = this.editorRef?.getControl().getTargetAtClientPoint(event.clientX, event.clientY)?.position;
|
|
372
374
|
this.variableService.getDropResult(event.nativeEvent, { type: 'ai-chat-input-widget' }).then(result => {
|
|
373
|
-
var _a, _b;
|
|
374
375
|
result.variables.forEach(variable => this.addContext(variable));
|
|
375
|
-
const text =
|
|
376
|
+
const text = result.text ?? dataTransferText;
|
|
376
377
|
if (position && text) {
|
|
377
|
-
|
|
378
|
+
this.editorRef?.getControl().executeEdits('drag-and-drop', [{
|
|
378
379
|
range: {
|
|
379
380
|
startLineNumber: position.lineNumber,
|
|
380
381
|
startColumn: position.column,
|
|
@@ -388,12 +389,11 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
|
|
|
388
389
|
}
|
|
389
390
|
onPaste(event) {
|
|
390
391
|
this.variableService.getPasteResult(event, { type: 'ai-chat-input-widget' }).then(result => {
|
|
391
|
-
var _a, _b;
|
|
392
392
|
result.variables.forEach(variable => this.addContext(variable));
|
|
393
393
|
if (result.text) {
|
|
394
|
-
const position =
|
|
394
|
+
const position = this.editorRef?.getControl().getPosition();
|
|
395
395
|
if (position && result.text) {
|
|
396
|
-
|
|
396
|
+
this.editorRef?.getControl().executeEdits('paste', [{
|
|
397
397
|
range: {
|
|
398
398
|
startLineNumber: position.lineNumber,
|
|
399
399
|
startColumn: position.column,
|
|
@@ -407,8 +407,7 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
|
|
|
407
407
|
});
|
|
408
408
|
}
|
|
409
409
|
onEscape() {
|
|
410
|
-
|
|
411
|
-
const currentRequest = (_d = (_c = (_b = (_a = this._branch) === null || _a === void 0 ? void 0 : _a.items) === null || _b === void 0 ? void 0 : _b.at(-1)) === null || _c === void 0 ? void 0 : _c.element) !== null && _d !== void 0 ? _d : this._chatModel.getRequests().at(-1);
|
|
410
|
+
const currentRequest = this._branch?.items?.at(-1)?.element ?? this._chatModel.getRequests().at(-1);
|
|
412
411
|
if (currentRequest && !ai_chat_1.EditableChatRequestModel.isEditing(currentRequest) && ai_chat_1.ChatRequestModel.isInProgress(currentRequest)) {
|
|
413
412
|
this._onCancel(currentRequest);
|
|
414
413
|
}
|
|
@@ -458,8 +457,6 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
|
|
|
458
457
|
}
|
|
459
458
|
};
|
|
460
459
|
exports.AIChatInputWidget = AIChatInputWidget;
|
|
461
|
-
AIChatInputWidget.ID = 'chat-input-widget';
|
|
462
|
-
AIChatInputWidget.CONTEXT_MENU = ['chat-input-context-menu'];
|
|
463
460
|
tslib_1.__decorate([
|
|
464
461
|
(0, inversify_1.inject)(monaco_editor_provider_1.MonacoEditorProvider),
|
|
465
462
|
tslib_1.__metadata("design:type", monaco_editor_provider_1.MonacoEditorProvider)
|
|
@@ -540,9 +537,8 @@ exports.AIChatInputWidget = AIChatInputWidget = AIChatInputWidget_1 = tslib_1.__
|
|
|
540
537
|
(0, inversify_1.injectable)()
|
|
541
538
|
], AIChatInputWidget);
|
|
542
539
|
// Utility to check if we have task context in the chat model
|
|
543
|
-
const hasTaskContext = (chatModel) => chatModel.context.getVariables().some(variable =>
|
|
540
|
+
const hasTaskContext = (chatModel) => chatModel.context.getVariables().some(variable => variable.variable?.id === task_context_variable_1.TASK_CONTEXT_VARIABLE.id);
|
|
544
541
|
const ChatInput = (props) => {
|
|
545
|
-
var _a, _b;
|
|
546
542
|
const onDeleteChangeSet = () => props.onDeleteChangeSet(props.chatModel.id);
|
|
547
543
|
const onDeleteChangeSetElement = (uri) => props.onDeleteChangeSetElement(props.chatModel.id, uri);
|
|
548
544
|
const [isInputEmpty, setIsInputEmpty] = React.useState(true);
|
|
@@ -589,10 +585,9 @@ const ChatInput = (props) => {
|
|
|
589
585
|
React.useEffect(() => {
|
|
590
586
|
const uri = props.uri;
|
|
591
587
|
const createInputElement = async () => {
|
|
592
|
-
var _a, _b;
|
|
593
588
|
const paddingTop = 6;
|
|
594
589
|
const lineHeight = 20;
|
|
595
|
-
const maxHeightPx = (
|
|
590
|
+
const maxHeightPx = (props.heightInLines ?? 12) * lineHeight;
|
|
596
591
|
const editor = await props.editorProvider.createSimpleInline(uri, editorContainerRef.current, {
|
|
597
592
|
language: chat_view_language_contribution_1.CHAT_VIEW_LANGUAGE_EXTENSION,
|
|
598
593
|
// Disable code lens, inlay hints and hover support to avoid console errors from other contributions
|
|
@@ -622,6 +617,7 @@ const ChatInput = (props) => {
|
|
|
622
617
|
bracketPairColorization: { enabled: false },
|
|
623
618
|
wrappingStrategy: 'advanced',
|
|
624
619
|
stickyScroll: { enabled: false },
|
|
620
|
+
ariaLabel: core_1.nls.localize('theia/ai/chat-ui/chatInputAriaLabel', 'Type your message here'),
|
|
625
621
|
});
|
|
626
622
|
if (editorContainerRef.current) {
|
|
627
623
|
editorContainerRef.current.style.overflowY = 'auto'; // ensure vertical scrollbar
|
|
@@ -669,18 +665,17 @@ const ChatInput = (props) => {
|
|
|
669
665
|
}
|
|
670
666
|
});
|
|
671
667
|
}
|
|
672
|
-
const lineNumbers = model.getAllDecorations().filter(predicate =>
|
|
668
|
+
const lineNumbers = model.getAllDecorations().filter(predicate => predicate.options.description?.startsWith('line-number-'));
|
|
673
669
|
editor.getControl().removeDecorations(lineNumbers.map(d => d.id));
|
|
674
670
|
editor.getControl().createDecorationsCollection(decorations);
|
|
675
671
|
};
|
|
676
|
-
|
|
672
|
+
editor.getControl().getModel()?.onDidChangeContent(() => {
|
|
677
673
|
updateLineCounts();
|
|
678
674
|
});
|
|
679
675
|
editor.getControl().onDidChangeCursorPosition(e => {
|
|
680
|
-
var _a;
|
|
681
676
|
const lineNumber = e.position.lineNumber;
|
|
682
|
-
const line =
|
|
683
|
-
line
|
|
677
|
+
const line = editor.getControl().getDomNode()?.querySelector(`.line-number-${lineNumber}`);
|
|
678
|
+
line?.scrollIntoView({ behavior: 'instant', block: 'nearest' });
|
|
684
679
|
});
|
|
685
680
|
editorRef.current = editor;
|
|
686
681
|
props.setEditorRef(editor);
|
|
@@ -748,17 +743,17 @@ const ChatInput = (props) => {
|
|
|
748
743
|
setValue('');
|
|
749
744
|
if (editorRef.current && !editorRef.current.document.textEditorModel.isDisposed()) {
|
|
750
745
|
editorRef.current.document.textEditorModel.setValue('');
|
|
746
|
+
editorRef.current.focus();
|
|
751
747
|
}
|
|
752
748
|
}, [props.context, props.onQuery, props.modeSelectorProps.currentMode, setValue, shouldUseTaskPlaceholder, taskPlaceholder]);
|
|
753
749
|
const onKeyDown = React.useCallback((event) => {
|
|
754
|
-
var _a;
|
|
755
750
|
if (!props.isEnabled) {
|
|
756
751
|
return;
|
|
757
752
|
}
|
|
758
753
|
if (event.key === 'Enter' && !event.shiftKey) {
|
|
759
754
|
event.preventDefault();
|
|
760
755
|
// On Enter, read input and submit (handles task context)
|
|
761
|
-
const currentValue =
|
|
756
|
+
const currentValue = editorRef.current?.document.textEditorModel.getValue() || '';
|
|
762
757
|
submit(currentValue);
|
|
763
758
|
}
|
|
764
759
|
else if (event.key === 'Escape') {
|
|
@@ -779,22 +774,19 @@ const ChatInput = (props) => {
|
|
|
779
774
|
showPlaceholderIfEditorEmpty();
|
|
780
775
|
};
|
|
781
776
|
const showPlaceholderIfEditorEmpty = () => {
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
(_b = placeholderRef.current) === null || _b === void 0 ? void 0 : _b.classList.remove('hidden');
|
|
777
|
+
if (!editorRef.current?.getControl().getValue()) {
|
|
778
|
+
placeholderRef.current?.classList.remove('hidden');
|
|
785
779
|
}
|
|
786
780
|
};
|
|
787
781
|
const hidePlaceholderIfEditorFilled = () => {
|
|
788
|
-
|
|
789
|
-
const value = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.getControl().getValue();
|
|
782
|
+
const value = editorRef.current?.getControl().getValue();
|
|
790
783
|
if (value && value.length > 0) {
|
|
791
|
-
|
|
784
|
+
placeholderRef.current?.classList.add('hidden');
|
|
792
785
|
}
|
|
793
786
|
};
|
|
794
787
|
const handlePin = () => {
|
|
795
|
-
var _a, _b;
|
|
796
788
|
if (editorRef.current) {
|
|
797
|
-
|
|
789
|
+
editorRef.current.getControl().getModel()?.applyEdits([{
|
|
798
790
|
range: {
|
|
799
791
|
startLineNumber: 1,
|
|
800
792
|
startColumn: 1,
|
|
@@ -804,7 +796,7 @@ const ChatInput = (props) => {
|
|
|
804
796
|
text: '@',
|
|
805
797
|
}]);
|
|
806
798
|
editorRef.current.getControl().setPosition({ lineNumber: 1, column: 2 });
|
|
807
|
-
|
|
799
|
+
editorRef.current.getControl().getAction('editor.action.triggerSuggest')?.run();
|
|
808
800
|
}
|
|
809
801
|
};
|
|
810
802
|
const leftOptions = [
|
|
@@ -842,9 +834,8 @@ const ChatInput = (props) => {
|
|
|
842
834
|
rightOptions = [{
|
|
843
835
|
title: core_1.nls.localize('theia/ai/chat-ui/send', 'Send (Enter)'),
|
|
844
836
|
handler: () => {
|
|
845
|
-
var _a;
|
|
846
837
|
if (props.isEnabled) {
|
|
847
|
-
submit(
|
|
838
|
+
submit(editorRef.current?.document.textEditorModel.getValue() || '');
|
|
848
839
|
}
|
|
849
840
|
},
|
|
850
841
|
className: 'codicon-send',
|
|
@@ -866,9 +857,8 @@ const ChatInput = (props) => {
|
|
|
866
857
|
rightOptions = [{
|
|
867
858
|
title: core_1.nls.localize('theia/ai/chat-ui/send', 'Send (Enter)'),
|
|
868
859
|
handler: () => {
|
|
869
|
-
var _a;
|
|
870
860
|
if (props.isEnabled) {
|
|
871
|
-
submit(
|
|
861
|
+
submit(editorRef.current?.document.textEditorModel.getValue() || '');
|
|
872
862
|
}
|
|
873
863
|
},
|
|
874
864
|
className: 'codicon-send',
|
|
@@ -877,10 +867,10 @@ const ChatInput = (props) => {
|
|
|
877
867
|
}
|
|
878
868
|
const contextUI = buildContextUI(props.context, props.labelProvider, props.onDeleteContextElement, props.onOpenContextElement, props.fileValidationState);
|
|
879
869
|
// Show mode selector if agent has multiple modes
|
|
880
|
-
const showModeSelector = (
|
|
870
|
+
const showModeSelector = (props.modeSelectorProps.receivingAgentModes?.length ?? 0) > 1;
|
|
881
871
|
return (React.createElement("div", { className: 'theia-ChatInput', "data-ai-disabled": !props.isEnabled, onDragOver: props.onDragOver, onDrop: props.onDrop, ref: containerRef },
|
|
882
872
|
props.showSuggestions !== false && React.createElement(chat_input_agent_suggestions_1.ChatInputAgentSuggestions, { suggestions: props.suggestions, opener: props.openerService }),
|
|
883
|
-
props.showChangeSet &&
|
|
873
|
+
props.showChangeSet && changeSetUI?.elements &&
|
|
884
874
|
React.createElement(ChangeSetBox, { changeSet: changeSetUI }),
|
|
885
875
|
React.createElement("div", { className: 'theia-ChatInput-Editor-Box' },
|
|
886
876
|
React.createElement("div", { className: 'theia-ChatInput-Editor', ref: editorContainerRef, onKeyDown: onKeyDown, onFocus: handleInputFocus, onBlur: handleInputBlur },
|
|
@@ -894,25 +884,29 @@ const ChatInput = (props) => {
|
|
|
894
884
|
onModeChange: props.modeSelectorProps.onModeChange,
|
|
895
885
|
} }))));
|
|
896
886
|
};
|
|
897
|
-
const ChatInputOptions = ({ leftOptions, rightOptions, isEnabled, modeSelectorProps }) => (
|
|
887
|
+
const ChatInputOptions = ({ leftOptions, rightOptions, isEnabled, modeSelectorProps }) => (
|
|
888
|
+
// Right options are rendered first in DOM for tab order (send button first when enabled)
|
|
889
|
+
// CSS order property positions them visually (left on left, right on right)
|
|
890
|
+
React.createElement("div", { className: "theia-ChatInputOptions" },
|
|
891
|
+
React.createElement("div", { className: "theia-ChatInputOptions-right" }, rightOptions.map((option, index) => (React.createElement("span", { key: index, className: `option${option.disabled ? ' disabled' : ''}${option.text?.align === 'right' ? ' reverse' : ''}`, title: option.title, "aria-label": option.title, role: 'button', tabIndex: option.disabled ? -1 : 0, onClick: option.handler, onKeyDown: e => {
|
|
892
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
893
|
+
e.preventDefault();
|
|
894
|
+
option.handler();
|
|
895
|
+
}
|
|
896
|
+
} },
|
|
897
|
+
React.createElement("span", null, option.text?.content),
|
|
898
|
+
React.createElement("span", { className: `codicon ${option.className}` }))))),
|
|
898
899
|
React.createElement("div", { className: "theia-ChatInputOptions-left" },
|
|
899
|
-
leftOptions.map((option, index) => {
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
React.createElement("span", null, (_b = option.text) === null || _b === void 0 ? void 0 : _b.content),
|
|
910
|
-
React.createElement("span", { className: `codicon ${option.className}` })));
|
|
911
|
-
}))));
|
|
912
|
-
const ChatModeSelector = React.memo(({ modes, currentMode, onModeChange, disabled }) => {
|
|
913
|
-
var _a, _b, _c;
|
|
914
|
-
return (React.createElement("select", { className: "theia-ChatInput-ModeSelector", value: (_b = currentMode !== null && currentMode !== void 0 ? currentMode : (_a = modes[0]) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : '', onChange: e => onModeChange(e.target.value), disabled: disabled, title: (_c = modes.find(m => { var _a; return m.id === (currentMode !== null && currentMode !== void 0 ? currentMode : (_a = modes[0]) === null || _a === void 0 ? void 0 : _a.id); })) === null || _c === void 0 ? void 0 : _c.name }, modes.map(mode => (React.createElement("option", { key: mode.id, value: mode.id, title: mode.name }, mode.name)))));
|
|
915
|
-
});
|
|
900
|
+
leftOptions.map((option, index) => (React.createElement("span", { key: index, className: `option${option.disabled ? ' disabled' : ''}${option.text?.align === 'right' ? ' reverse' : ''}`, title: option.title, "aria-label": option.title, role: 'button', tabIndex: option.disabled ? -1 : 0, onClick: option.handler, onKeyDown: e => {
|
|
901
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
902
|
+
e.preventDefault();
|
|
903
|
+
option.handler();
|
|
904
|
+
}
|
|
905
|
+
} },
|
|
906
|
+
React.createElement("span", null, option.text?.content),
|
|
907
|
+
React.createElement("span", { className: `codicon ${option.className}` })))),
|
|
908
|
+
modeSelectorProps.show && modeSelectorProps.modes && (React.createElement(ChatModeSelector, { modes: modeSelectorProps.modes, currentMode: modeSelectorProps.currentMode, onModeChange: modeSelectorProps.onModeChange, disabled: !isEnabled })))));
|
|
909
|
+
const ChatModeSelector = React.memo(({ modes, currentMode, onModeChange, disabled }) => (React.createElement("select", { className: "theia-ChatInput-ModeSelector", value: currentMode ?? modes[0]?.id ?? '', onChange: e => onModeChange(e.target.value), disabled: disabled, title: modes.find(m => m.id === (currentMode ?? modes[0]?.id))?.name }, modes.map(mode => (React.createElement("option", { key: mode.id, value: mode.id, title: mode.name }, mode.name))))));
|
|
916
910
|
const noPropagation = (handler) => (e) => {
|
|
917
911
|
handler();
|
|
918
912
|
e.stopPropagation();
|
|
@@ -928,31 +922,48 @@ const buildChangeSetUI = (changeSet, labelProvider, decoratorService, actions, o
|
|
|
928
922
|
}) : undefined;
|
|
929
923
|
};
|
|
930
924
|
/** Memo because the parent element rerenders on every key press in the chat widget. */
|
|
931
|
-
const ChangeSetBox = React.memo(({ changeSet: { changeSet, title, deleteChangeSet, elements, actions } }) =>
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
925
|
+
const ChangeSetBox = React.memo(({ changeSet: { changeSet, title, deleteChangeSet, elements, actions } }) => {
|
|
926
|
+
const [isCollapsed, setIsCollapsed] = React.useState(false);
|
|
927
|
+
const toggleCollapse = React.useCallback(() => {
|
|
928
|
+
setIsCollapsed(prev => !prev);
|
|
929
|
+
}, []);
|
|
930
|
+
const handleToggleKeyDown = React.useCallback((e) => {
|
|
931
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
932
|
+
e.preventDefault();
|
|
933
|
+
toggleCollapse();
|
|
934
|
+
}
|
|
935
|
+
}, [toggleCollapse]);
|
|
936
|
+
return (React.createElement("div", { className: 'theia-ChatInput-ChangeSet-Box' },
|
|
937
|
+
React.createElement("div", { className: 'theia-ChatInput-ChangeSet-Header' },
|
|
938
|
+
React.createElement("div", { className: 'theia-ChatInput-ChangeSet-Header-Title' },
|
|
939
|
+
React.createElement("span", { className: `codicon ${isCollapsed ? 'codicon-chevron-right' : 'codicon-chevron-down'} theia-ChatInput-ChangeSet-Toggle`, onClick: toggleCollapse, onKeyDown: handleToggleKeyDown, role: 'button', tabIndex: 0, "aria-expanded": !isCollapsed, "aria-label": isCollapsed
|
|
940
|
+
? core_1.nls.localize('theia/ai/chat-ui/expandChangeSet', 'Expand Change Set')
|
|
941
|
+
: core_1.nls.localize('theia/ai/chat-ui/collapseChangeSet', 'Collapse Change Set'), title: isCollapsed
|
|
942
|
+
? core_1.nls.localize('theia/ai/chat-ui/expandChangeSet', 'Expand Change Set')
|
|
943
|
+
: core_1.nls.localize('theia/ai/chat-ui/collapseChangeSet', 'Collapse Change Set') }),
|
|
944
|
+
React.createElement("h3", null, title)),
|
|
945
|
+
React.createElement("div", { className: 'theia-ChatInput-ChangeSet-Header-Actions' },
|
|
946
|
+
actions.map(action => (React.createElement("div", { key: action.id, className: 'theia-changeSet-Action' }, action.render(changeSet)))),
|
|
947
|
+
React.createElement("span", { className: 'codicon codicon-close action', title: core_1.nls.localize('theia/ai/chat-ui/deleteChangeSet', 'Delete Change Set'), onClick: () => deleteChangeSet() }))),
|
|
948
|
+
React.createElement("div", { className: `theia-ChatInput-ChangeSet-List ${isCollapsed ? 'collapsed' : 'expanded'}` },
|
|
949
|
+
React.createElement("ul", null, elements.map(element => ChangeSetElement(element))))));
|
|
950
|
+
});
|
|
939
951
|
function toUiElement(element, onDeleteChangeSetElement, labelProvider, decoratorService) {
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
open: (_a = element.open) === null || _a === void 0 ? void 0 : _a.bind(element),
|
|
952
|
+
return {
|
|
953
|
+
open: element.open?.bind(element),
|
|
943
954
|
uri: element.uri.toString(),
|
|
944
|
-
iconClass:
|
|
955
|
+
iconClass: element.icon ?? labelProvider.getIcon(element.uri) ?? labelProvider.fileIcon,
|
|
945
956
|
nameClass: `${element.type} ${element.state}`,
|
|
946
|
-
name:
|
|
947
|
-
additionalInfo:
|
|
957
|
+
name: element.name ?? labelProvider.getName(element.uri),
|
|
958
|
+
additionalInfo: element.additionalInfo ?? labelProvider.getDetails(element.uri),
|
|
948
959
|
additionalInfoSuffixIcon: decoratorService.getAdditionalInfoSuffixIcon(element),
|
|
949
|
-
openChange:
|
|
950
|
-
apply: element.state !== 'applied' ?
|
|
951
|
-
revert: element.state === 'applied' || element.state === 'stale' ?
|
|
960
|
+
openChange: element?.openChange?.bind(element),
|
|
961
|
+
apply: element.state !== 'applied' ? element?.apply?.bind(element) : undefined,
|
|
962
|
+
revert: element.state === 'applied' || element.state === 'stale' ? element?.revert?.bind(element) : undefined,
|
|
952
963
|
delete: () => onDeleteChangeSetElement(element.uri)
|
|
953
|
-
}
|
|
964
|
+
};
|
|
954
965
|
}
|
|
955
|
-
const ChangeSetElement = element => (React.createElement("li", { key: element.uri, title: core_1.nls.localize('theia/ai/chat-ui/openDiff', 'Open Diff'), onClick: () =>
|
|
966
|
+
const ChangeSetElement = element => (React.createElement("li", { key: element.uri, title: core_1.nls.localize('theia/ai/chat-ui/openDiff', 'Open Diff'), onClick: () => element.openChange?.() },
|
|
956
967
|
React.createElement("div", { className: `theia-ChatInput-ChangeSet-Icon ${element.iconClass}` }),
|
|
957
968
|
React.createElement("div", { className: 'theia-ChatInput-ChangeSet-labelParts' },
|
|
958
969
|
React.createElement("span", { className: `theia-ChatInput-ChangeSet-title ${element.nameClass}` }, element.name),
|
|
@@ -1005,14 +1016,13 @@ function buildContextUI(context, labelProvider, onDeleteContextElement, onOpen,
|
|
|
1005
1016
|
}
|
|
1006
1017
|
const ChatContext = ({ context }) => (React.createElement("div", { className: "theia-ChatInput-ChatContext" },
|
|
1007
1018
|
React.createElement("ul", null, context.map((element, index) => {
|
|
1008
|
-
var _a, _b, _c, _d;
|
|
1009
1019
|
if (image_context_variable_1.ImageContextVariable.isImageContextRequest(element.variable)) {
|
|
1010
1020
|
const variable = image_context_variable_1.ImageContextVariable.parseRequest(element.variable);
|
|
1011
|
-
return React.createElement("li", { key: index, className: "theia-ChatInput-ChatContext-Element theia-ChatInput-ImageContext-Element", title:
|
|
1021
|
+
return React.createElement("li", { key: index, className: "theia-ChatInput-ChatContext-Element theia-ChatInput-ImageContext-Element", title: variable.name ?? variable.wsRelativePath, onClick: () => element.open?.() },
|
|
1012
1022
|
React.createElement("div", { className: "theia-ChatInput-ChatContext-Row" },
|
|
1013
1023
|
React.createElement("div", { className: `theia-ChatInput-ChatContext-Icon ${element.iconClass}` }),
|
|
1014
1024
|
React.createElement("div", { className: "theia-ChatInput-ChatContext-labelParts" },
|
|
1015
|
-
React.createElement("span", { className: `theia-ChatInput-ChatContext-title ${element.nameClass}` },
|
|
1025
|
+
React.createElement("span", { className: `theia-ChatInput-ChatContext-title ${element.nameClass}` }, variable.name ?? variable.wsRelativePath?.split('/').pop()),
|
|
1016
1026
|
React.createElement("span", { className: 'theia-ChatInput-ChatContext-additionalInfo' }, element.additionalInfo)),
|
|
1017
1027
|
React.createElement("span", { className: "codicon codicon-close action", title: core_1.nls.localizeByDefault('Delete'), onClick: e => { e.stopPropagation(); element.delete(); } })),
|
|
1018
1028
|
React.createElement("div", { className: "theia-ChatInput-ChatContext-ImageRow" },
|
|
@@ -1021,8 +1031,8 @@ const ChatContext = ({ context }) => (React.createElement("div", { className: "t
|
|
|
1021
1031
|
}
|
|
1022
1032
|
const isWarning = element.className === 'warning-file';
|
|
1023
1033
|
const isInvalid = element.className === 'invalid-file';
|
|
1024
|
-
const tooltipTitle =
|
|
1025
|
-
return React.createElement("li", { key: index, className: `theia-ChatInput-ChatContext-Element ${element.className || ''}`, title: tooltipTitle, onClick: () =>
|
|
1034
|
+
const tooltipTitle = element.validationMessage ?? element.details;
|
|
1035
|
+
return React.createElement("li", { key: index, className: `theia-ChatInput-ChatContext-Element ${element.className || ''}`, title: tooltipTitle, onClick: () => element.open?.() },
|
|
1026
1036
|
React.createElement("div", { className: "theia-ChatInput-ChatContext-Row" },
|
|
1027
1037
|
isWarning && React.createElement("span", { className: "codicon codicon-warning warning-file-icon" }),
|
|
1028
1038
|
isInvalid && React.createElement("span", { className: "codicon codicon-error invalid-file-icon" }),
|