@gitlab/ui 92.0.0 → 92.1.1
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/CHANGELOG.md +14 -0
- package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu.js +5 -0
- package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_selections/duo_chat_context_item_selections.js +1 -1
- package/dist/components/experimental/duo/chat/constants.js +2 -1
- package/dist/components/experimental/duo/chat/duo_chat.js +72 -18
- package/dist/components/experimental/duo/chat/mock_data.js +6 -2
- package/dist/index.js +1 -0
- package/package.json +1 -1
- package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu.vue +5 -0
- package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_selections/duo_chat_context_item_selections.vue +1 -0
- package/src/components/experimental/duo/chat/constants.js +1 -0
- package/src/components/experimental/duo/chat/duo_chat.vue +103 -18
- package/src/components/experimental/duo/chat/mock_data.js +6 -0
- package/src/index.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [92.1.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v92.1.0...v92.1.1) (2024-09-11)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* ensure chat scrolls to bottom with new message ([3d048f8](https://gitlab.com/gitlab-org/gitlab-ui/commit/3d048f82c586cd3860a7cf5c86d0572ee44d0dc6))
|
|
7
|
+
|
|
8
|
+
# [92.1.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v92.0.0...v92.1.0) (2024-09-10)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **GlDuoChat:** add /include command, integrate context-item-menu ([3f664f8](https://gitlab.com/gitlab-org/gitlab-ui/commit/3f664f89a35aa426bb043f1563cd2bdb9722878c))
|
|
14
|
+
|
|
1
15
|
# [92.0.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v91.15.0...v92.0.0) (2024-09-10)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -82,7 +82,7 @@ var script = {
|
|
|
82
82
|
const __vue_script__ = script;
|
|
83
83
|
|
|
84
84
|
/* template */
|
|
85
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-mb-3 gl-flex gl-flex-col"},[_c('button',{staticClass:"gl-flex gl-w-full gl-items-center gl-border-0 gl-bg-transparent gl-p-0 gl-text-left gl-text-xs gl-lowercase gl-text-gray-500",attrs:{"data-testid":"chat-context-selections-title"},on:{"click":_vm.toggleCollapse}},[_c('gl-icon',{attrs:{"name":_vm.collapseIconName,"data-testid":"chat-context-collapse-icon"}}),_vm._v(" "+_vm._s(_vm.title)+"\n ")],1),_vm._v(" "),_c('div',{directives:[{name:"show",rawName:"v-show",value:(!_vm.isCollapsed),expression:"!isCollapsed"}],staticClass:"gl-mt-1 gl-flex gl-grow gl-flex-wrap",attrs:{"data-testid":"chat-context-tokens-wrapper"}},_vm._l((_vm.selections),function(contextItem){return _c('gl-token',{key:contextItem.id,staticClass:"gl-mb-2 gl-mr-2",attrs:{"view-only":!_vm.removable,"variant":"default"},on:{"close":function($event){return _vm.onRemoveItem(contextItem)}}},[_c('div',{staticClass:"gl-flex gl-items-center",attrs:{"id":("context-item-" + (contextItem.id) + "-" + _vm.selectionsId)}},[_c('gl-icon',{staticClass:"gl-mr-1",attrs:{"name":_vm.getIconName(contextItem.type),"size":12}}),_vm._v("\n "+_vm._s(contextItem.metadata.name)+"\n ")],1),_vm._v(" "),_c('gl-duo-chat-context-item-popover',{attrs:{"context-item":contextItem,"target":("context-item-" + (contextItem.id) + "-" + _vm.selectionsId),"placement":"bottom"}})],1)}),1)])};
|
|
85
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-mb-3 gl-flex gl-flex-col"},[_c('button',{staticClass:"gl-flex gl-w-full gl-items-center gl-border-0 gl-bg-transparent gl-p-0 gl-text-left gl-text-xs gl-lowercase gl-text-gray-500",attrs:{"data-testid":"chat-context-selections-title","type":"button"},on:{"click":_vm.toggleCollapse}},[_c('gl-icon',{attrs:{"name":_vm.collapseIconName,"data-testid":"chat-context-collapse-icon"}}),_vm._v(" "+_vm._s(_vm.title)+"\n ")],1),_vm._v(" "),_c('div',{directives:[{name:"show",rawName:"v-show",value:(!_vm.isCollapsed),expression:"!isCollapsed"}],staticClass:"gl-mt-1 gl-flex gl-grow gl-flex-wrap",attrs:{"data-testid":"chat-context-tokens-wrapper"}},_vm._l((_vm.selections),function(contextItem){return _c('gl-token',{key:contextItem.id,staticClass:"gl-mb-2 gl-mr-2",attrs:{"view-only":!_vm.removable,"variant":"default"},on:{"close":function($event){return _vm.onRemoveItem(contextItem)}}},[_c('div',{staticClass:"gl-flex gl-items-center",attrs:{"id":("context-item-" + (contextItem.id) + "-" + _vm.selectionsId)}},[_c('gl-icon',{staticClass:"gl-mr-1",attrs:{"name":_vm.getIconName(contextItem.type),"size":12}}),_vm._v("\n "+_vm._s(contextItem.metadata.name)+"\n ")],1),_vm._v(" "),_c('gl-duo-chat-context-item-popover',{attrs:{"context-item":contextItem,"target":("context-item-" + (contextItem.id) + "-" + _vm.selectionsId),"placement":"bottom"}})],1)}),1)])};
|
|
86
86
|
var __vue_staticRenderFns__ = [];
|
|
87
87
|
|
|
88
88
|
/* style */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const CHAT_RESET_MESSAGE = '/reset';
|
|
2
2
|
const CHAT_CLEAN_MESSAGE = '/clean';
|
|
3
3
|
const CHAT_CLEAR_MESSAGE = '/clear';
|
|
4
|
+
const CHAT_INCLUDE_MESSAGE = '/include';
|
|
4
5
|
const LOADING_TRANSITION_DURATION = 7500;
|
|
5
6
|
const DOCUMENTATION_SOURCE_TYPES = {
|
|
6
7
|
HANDBOOK: {
|
|
@@ -22,4 +23,4 @@ const MESSAGE_MODEL_ROLES = {
|
|
|
22
23
|
assistant: 'assistant'
|
|
23
24
|
};
|
|
24
25
|
|
|
25
|
-
export { CHAT_CLEAN_MESSAGE, CHAT_CLEAR_MESSAGE, CHAT_RESET_MESSAGE, DOCUMENTATION_SOURCE_TYPES, LOADING_TRANSITION_DURATION, MESSAGE_MODEL_ROLES };
|
|
26
|
+
export { CHAT_CLEAN_MESSAGE, CHAT_CLEAR_MESSAGE, CHAT_INCLUDE_MESSAGE, CHAT_RESET_MESSAGE, DOCUMENTATION_SOURCE_TYPES, LOADING_TRANSITION_DURATION, MESSAGE_MODEL_ROLES };
|
|
@@ -14,7 +14,8 @@ import { SafeHtmlDirective } from '../../../../directives/safe_html/safe_html';
|
|
|
14
14
|
import GlDuoChatLoader from './components/duo_chat_loader/duo_chat_loader';
|
|
15
15
|
import GlDuoChatPredefinedPrompts from './components/duo_chat_predefined_prompts/duo_chat_predefined_prompts';
|
|
16
16
|
import GlDuoChatConversation from './components/duo_chat_conversation/duo_chat_conversation';
|
|
17
|
-
import { CHAT_RESET_MESSAGE, CHAT_CLEAN_MESSAGE, CHAT_CLEAR_MESSAGE } from './constants';
|
|
17
|
+
import { CHAT_RESET_MESSAGE, CHAT_INCLUDE_MESSAGE, MESSAGE_MODEL_ROLES, CHAT_CLEAN_MESSAGE, CHAT_CLEAR_MESSAGE } from './constants';
|
|
18
|
+
import { INCLUDE_SLASH_COMMAND } from './mock_data';
|
|
18
19
|
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
19
20
|
|
|
20
21
|
const i18n = {
|
|
@@ -205,7 +206,9 @@ var script = {
|
|
|
205
206
|
scrolledToBottom: true,
|
|
206
207
|
activeCommandIndex: 0,
|
|
207
208
|
displaySubmitButton: true,
|
|
208
|
-
compositionJustEnded: false
|
|
209
|
+
compositionJustEnded: false,
|
|
210
|
+
contextItemsMenuIsOpen: false,
|
|
211
|
+
contextItemMenuRef: null
|
|
209
212
|
};
|
|
210
213
|
},
|
|
211
214
|
computed: {
|
|
@@ -231,6 +234,9 @@ var script = {
|
|
|
231
234
|
var _this$messages2;
|
|
232
235
|
return (_this$messages2 = this.messages) === null || _this$messages2 === void 0 ? void 0 : _this$messages2[this.messages.length - 1];
|
|
233
236
|
},
|
|
237
|
+
caseInsensitivePrompt() {
|
|
238
|
+
return this.prompt.toLowerCase().trim();
|
|
239
|
+
},
|
|
234
240
|
resetDisabled() {
|
|
235
241
|
var _this$lastMessage;
|
|
236
242
|
if (this.isLoading || !this.hasMessages) {
|
|
@@ -246,21 +252,38 @@ var script = {
|
|
|
246
252
|
return Boolean(((_this$lastMessage3 = this.lastMessage) === null || _this$lastMessage3 === void 0 ? void 0 : (_this$lastMessage3$ch = _this$lastMessage3.chunks) === null || _this$lastMessage3$ch === void 0 ? void 0 : _this$lastMessage3$ch.length) > 0 && !((_this$lastMessage4 = this.lastMessage) !== null && _this$lastMessage4 !== void 0 && _this$lastMessage4.content) || typeof ((_this$lastMessage5 = this.lastMessage) === null || _this$lastMessage5 === void 0 ? void 0 : _this$lastMessage5.chunkId) === 'number');
|
|
247
253
|
},
|
|
248
254
|
filteredSlashCommands() {
|
|
249
|
-
|
|
250
|
-
|
|
255
|
+
return this.slashCommands.filter(c => c.name.toLowerCase().startsWith(this.caseInsensitivePrompt)).filter(c => {
|
|
256
|
+
if (c.name === CHAT_INCLUDE_MESSAGE) {
|
|
257
|
+
return this.hasContextItemSelectionMenu;
|
|
258
|
+
}
|
|
259
|
+
return true;
|
|
260
|
+
});
|
|
251
261
|
},
|
|
252
262
|
shouldShowSlashCommands() {
|
|
253
|
-
if (!this.withSlashCommands) return false;
|
|
254
|
-
const
|
|
255
|
-
const
|
|
256
|
-
const startsWithSlashCommand = this.slashCommands.some(c => caseInsensitivePrompt.startsWith(c.name));
|
|
263
|
+
if (!this.withSlashCommands || this.contextItemsMenuIsOpen) return false;
|
|
264
|
+
const startsWithSlash = this.caseInsensitivePrompt.startsWith('/');
|
|
265
|
+
const startsWithSlashCommand = this.slashCommands.some(c => this.caseInsensitivePrompt.startsWith(c.name));
|
|
257
266
|
return startsWithSlash && this.filteredSlashCommands.length && !startsWithSlashCommand;
|
|
258
267
|
},
|
|
268
|
+
shouldShowContextItemSelectionMenu() {
|
|
269
|
+
if (!this.hasContextItemSelectionMenu) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
const isSlash = this.caseInsensitivePrompt === '/';
|
|
273
|
+
if (!this.caseInsensitivePrompt || isSlash) {
|
|
274
|
+
// if user has removed entire command (or whole command except for '/') we should close context item menu and allow slash command menu to show again
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
return INCLUDE_SLASH_COMMAND.name.startsWith(this.caseInsensitivePrompt);
|
|
278
|
+
},
|
|
259
279
|
inputPlaceholder() {
|
|
260
280
|
if (this.chatPromptPlaceholder) {
|
|
261
281
|
return this.chatPromptPlaceholder;
|
|
262
282
|
}
|
|
263
283
|
return this.withSlashCommands ? i18n.CHAT_PROMPT_PLACEHOLDER_WITH_COMMANDS : i18n.CHAT_PROMPT_PLACEHOLDER_DEFAULT;
|
|
284
|
+
},
|
|
285
|
+
hasContextItemSelectionMenu() {
|
|
286
|
+
return Boolean(this.contextItemMenuRef);
|
|
264
287
|
}
|
|
265
288
|
},
|
|
266
289
|
watch: {
|
|
@@ -269,12 +292,18 @@ var script = {
|
|
|
269
292
|
this.displaySubmitButton = true; // Re-enable submit button when loading stops
|
|
270
293
|
}
|
|
271
294
|
this.isHidden = false;
|
|
272
|
-
this.scrollToBottom();
|
|
273
295
|
},
|
|
274
296
|
isStreaming(newVal) {
|
|
275
297
|
if (!newVal && !this.isLoading) {
|
|
276
298
|
this.displaySubmitButton = true; // Re-enable submit button when streaming stops
|
|
277
299
|
}
|
|
300
|
+
},
|
|
301
|
+
lastMessage(newMessage) {
|
|
302
|
+
if (this.scrolledToBottom || newMessage.role.toLowerCase() === MESSAGE_MODEL_ROLES.user) {
|
|
303
|
+
// only scroll to bottom on new message if the user hasn't explicitly scrolled up to view an earlier message
|
|
304
|
+
// or if the user has just submitted a new message
|
|
305
|
+
this.scrollToBottom();
|
|
306
|
+
}
|
|
278
307
|
}
|
|
279
308
|
},
|
|
280
309
|
created() {
|
|
@@ -304,27 +333,32 @@ var script = {
|
|
|
304
333
|
this.setPromptAndFocus();
|
|
305
334
|
},
|
|
306
335
|
sendChatPrompt() {
|
|
307
|
-
if (!this.displaySubmitButton) {
|
|
336
|
+
if (!this.displaySubmitButton || this.contextItemsMenuIsOpen) {
|
|
308
337
|
return;
|
|
309
338
|
}
|
|
310
339
|
if (this.prompt) {
|
|
311
|
-
if (this.
|
|
340
|
+
if (this.caseInsensitivePrompt === CHAT_RESET_MESSAGE && this.resetDisabled) {
|
|
312
341
|
return;
|
|
313
342
|
}
|
|
343
|
+
if (this.caseInsensitivePrompt.startsWith(CHAT_INCLUDE_MESSAGE) && this.hasContextItemSelectionMenu) {
|
|
344
|
+
this.contextItemsMenuIsOpen = true;
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
if (![CHAT_RESET_MESSAGE, CHAT_CLEAN_MESSAGE, CHAT_CLEAR_MESSAGE].includes(this.caseInsensitivePrompt)) {
|
|
348
|
+
this.displaySubmitButton = false;
|
|
349
|
+
}
|
|
350
|
+
|
|
314
351
|
/**
|
|
315
352
|
* Emitted when a new user prompt should be sent out.
|
|
316
353
|
*
|
|
317
354
|
* @param {String} prompt The user prompt to send.
|
|
318
355
|
*/
|
|
319
|
-
|
|
320
|
-
if (![CHAT_RESET_MESSAGE, CHAT_CLEAN_MESSAGE, CHAT_CLEAR_MESSAGE].includes(this.prompt)) {
|
|
321
|
-
this.displaySubmitButton = false;
|
|
322
|
-
}
|
|
323
356
|
this.$emit('send-chat-prompt', this.prompt.trim());
|
|
324
357
|
this.setPromptAndFocus();
|
|
325
358
|
}
|
|
326
359
|
},
|
|
327
360
|
sendPredefinedPrompt(prompt) {
|
|
361
|
+
this.contextItemsMenuIsOpen = false;
|
|
328
362
|
this.prompt = prompt;
|
|
329
363
|
this.sendChatPrompt();
|
|
330
364
|
},
|
|
@@ -338,8 +372,6 @@ var script = {
|
|
|
338
372
|
},
|
|
339
373
|
async scrollToBottom() {
|
|
340
374
|
var _this$$refs$anchor, _this$$refs$anchor$sc;
|
|
341
|
-
// This method is also called directly by consumers of this component
|
|
342
|
-
// https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/3269f6200dc3821c62a3992b40c971dd9ee55d87/webviews/vue2/gitlab_duo_chat/src/App.vue#L97
|
|
343
375
|
await this.$nextTick();
|
|
344
376
|
(_this$$refs$anchor = this.$refs.anchor) === null || _this$$refs$anchor === void 0 ? void 0 : (_this$$refs$anchor$sc = _this$$refs$anchor.scrollIntoView) === null || _this$$refs$anchor$sc === void 0 ? void 0 : _this$$refs$anchor$sc.call(_this$$refs$anchor);
|
|
345
377
|
},
|
|
@@ -371,6 +403,18 @@ var script = {
|
|
|
371
403
|
const {
|
|
372
404
|
key
|
|
373
405
|
} = e;
|
|
406
|
+
if (this.contextItemsMenuIsOpen) {
|
|
407
|
+
var _this$contextItemMenu;
|
|
408
|
+
if (!this.shouldShowContextItemSelectionMenu) {
|
|
409
|
+
this.contextItemsMenuIsOpen = false;
|
|
410
|
+
}
|
|
411
|
+
(_this$contextItemMenu = this.contextItemMenuRef) === null || _this$contextItemMenu === void 0 ? void 0 : _this$contextItemMenu.handleKeyUp(e);
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
if (this.caseInsensitivePrompt === INCLUDE_SLASH_COMMAND.name) {
|
|
415
|
+
this.contextItemsMenuIsOpen = true;
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
374
418
|
if (this.shouldShowSlashCommands) {
|
|
375
419
|
e.preventDefault();
|
|
376
420
|
if (key === 'Enter') {
|
|
@@ -416,6 +460,9 @@ var script = {
|
|
|
416
460
|
this.sendChatPrompt();
|
|
417
461
|
} else {
|
|
418
462
|
this.setPromptAndFocus(`${command.name} `);
|
|
463
|
+
if (command.name === CHAT_INCLUDE_MESSAGE && this.hasContextItemSelectionMenu) {
|
|
464
|
+
this.contextItemsMenuIsOpen = true;
|
|
465
|
+
}
|
|
419
466
|
}
|
|
420
467
|
},
|
|
421
468
|
onInsertCodeSnippet(e) {
|
|
@@ -424,6 +471,13 @@ var script = {
|
|
|
424
471
|
* @param {*} event An event containing code string in the "detail.code" field.
|
|
425
472
|
*/
|
|
426
473
|
this.$emit('insert-code-snippet', e);
|
|
474
|
+
},
|
|
475
|
+
closeContextItemsMenuOpen() {
|
|
476
|
+
this.contextItemsMenuIsOpen = false;
|
|
477
|
+
this.setPromptAndFocus();
|
|
478
|
+
},
|
|
479
|
+
setContextItemsMenuRef(ref) {
|
|
480
|
+
this.contextItemMenuRef = ref;
|
|
427
481
|
}
|
|
428
482
|
},
|
|
429
483
|
i18n,
|
|
@@ -438,7 +492,7 @@ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=
|
|
|
438
492
|
{
|
|
439
493
|
'gl-h-full': !_vm.hasMessages,
|
|
440
494
|
'force-scroll-bar': _vm.hasMessages,
|
|
441
|
-
} ],attrs:{"tag":"section","name":"message"}},[_vm._l((_vm.conversations),function(conversation,index){return _c('gl-duo-chat-conversation',{key:("conversation-" + index),attrs:{"enable-code-insertion":_vm.enableCodeInsertion,"messages":conversation,"canceled-request-ids":_vm.canceledRequestIds,"show-delimiter":index > 0},on:{"track-feedback":_vm.onTrackFeedback,"insert-code-snippet":_vm.onInsertCodeSnippet}})}),_vm._v(" "),(!_vm.hasMessages && !_vm.isLoading)?[_c('gl-empty-state',{key:"empty-state",staticClass:"gl-flex-grow gl-justify-center",attrs:{"svg-path":_vm.$options.emptySvg,"svg-height":145,"title":_vm.emptyStateTitle},scopedSlots:_vm._u([{key:"description",fn:function(){return [_c('p',{staticClass:"gl-mb-3",attrs:{"data-testid":"gl-duo-chat-empty-state-description"}},[_vm._v("\n "+_vm._s(_vm.emptyStateDescription)+"\n ")]),_vm._v(" "),_c('p',{staticClass:"gl-mt-3 gl-text-sm gl-text-subtle",attrs:{"data-testid":"gl-duo-chat-empty-state-secondary-description"}},[_vm._v("\n "+_vm._s(_vm.emptyStateSecondaryDescription)+"\n ")])]},proxy:true}],null,false,460840487)}),_vm._v(" "),_c('gl-duo-chat-predefined-prompts',{key:"predefined-prompts",attrs:{"prompts":_vm.predefinedPrompts},on:{"click":_vm.sendPredefinedPrompt}})]:_vm._e(),_vm._v(" "),(_vm.isLoading)?_c('gl-duo-chat-loader',{key:"loader",attrs:{"tool-name":_vm.toolName}}):_vm._e(),_vm._v(" "),_c('div',{key:"anchor",ref:"anchor",staticClass:"scroll-anchor"})],2)],1),_vm._v(" "),(_vm.isChatAvailable)?_c('footer',{staticClass:"duo-chat-drawer-footer duo-chat-drawer-footer-sticky gl-border-t gl-bg-gray-10 gl-p-5",class:{ 'duo-chat-drawer-body-scrim-on-footer': !_vm.scrolledToBottom },attrs:{"data-testid":"chat-footer"}},[_c('gl-form',{attrs:{"data-testid":"chat-prompt-form"},on:{"submit":function($event){$event.stopPropagation();$event.preventDefault();return _vm.sendChatPrompt.apply(null, arguments)}}},[_c('gl-form-input-group',{scopedSlots:_vm._u([{key:"append",fn:function(){return [(_vm.displaySubmitButton)?_c('gl-button',{staticClass:"!gl-absolute gl-bottom-2 gl-right-2 !gl-rounded-base",attrs:{"icon":"paper-airplane","category":"primary","variant":"confirm","type":"submit","data-testid":"chat-prompt-submit-button","aria-label":_vm.$options.i18n.CHAT_SUBMIT_LABEL}}):_c('gl-button',{staticClass:"!gl-absolute gl-bottom-2 gl-right-2 !gl-rounded-base",attrs:{"icon":"stop","category":"primary","variant":"default","data-testid":"chat-prompt-cancel-button","aria-label":_vm.$options.i18n.CHAT_CANCEL_LABEL},on:{"click":_vm.cancelPrompt}})]},proxy:true}],null,false,677611116)},[_c('div',{staticClass:"duo-chat-input gl-min-h-8 gl-max-w-full gl-grow gl-rounded-base gl-bg-white gl-align-top gl-shadow-inner-1-gray-400",attrs:{"data-value":_vm.prompt}},[(_vm.shouldShowSlashCommands)?_c('gl-card',{ref:"commands",staticClass:"slash-commands !gl-absolute gl-w-full -gl-translate-y-full gl-list-none gl-pl-0 gl-shadow-md",attrs:{"body-class":"!gl-p-2"}},_vm._l((_vm.filteredSlashCommands),function(command,index){return _c('gl-dropdown-item',{key:command.name,class:{ 'active-command': index === _vm.activeCommandIndex },on:{"click":function($event){return _vm.selectSlashCommand(index)}},nativeOn:{"mouseenter":function($event){_vm.activeCommandIndex = index;}}},[_c('span',{staticClass:"gl-flex gl-justify-between"},[_c('span',{staticClass:"gl-block"},[_vm._v(_vm._s(command.name))]),_vm._v(" "),_c('small',{staticClass:"gl-pl-3 gl-text-right gl-italic gl-text-gray-500"},[_vm._v(_vm._s(command.description))])])])}),1):_vm._e(),_vm._v(" "),_c('gl-form-textarea',{ref:"prompt",staticClass:"gl-absolute !gl-h-full gl-rounded-br-none gl-rounded-tr-none !gl-bg-transparent !gl-py-4 !gl-shadow-none",class:{ 'gl-truncate': !_vm.prompt },attrs:{"data-testid":"chat-prompt-input","placeholder":_vm.inputPlaceholder,"autofocus":""},on:{"compositionend":_vm.compositionEnd},nativeOn:{"keydown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }if($event.ctrlKey||$event.shiftKey||$event.altKey||$event.metaKey){ return null; }$event.preventDefault();},"keyup":function($event){return _vm.onInputKeyup.apply(null, arguments)}},model:{value:(_vm.prompt),callback:function ($$v) {_vm.prompt=$$v;},expression:"prompt"}})],1)]),_vm._v(" "),_c('p',{staticClass:"gl-mb-0 gl-mt-3 gl-text-sm gl-leading-20 gl-text-subtle",attrs:{"data-testid":"chat-legal-disclaimer"}},[_vm._v("\n "+_vm._s(_vm.$options.i18n.CHAT_LEGAL_DISCLAIMER)+"\n ")])],1)],1):_vm._e()]):_vm._e()};
|
|
495
|
+
} ],attrs:{"tag":"section","name":"message"}},[_vm._l((_vm.conversations),function(conversation,index){return _c('gl-duo-chat-conversation',{key:("conversation-" + index),attrs:{"enable-code-insertion":_vm.enableCodeInsertion,"messages":conversation,"canceled-request-ids":_vm.canceledRequestIds,"show-delimiter":index > 0},on:{"track-feedback":_vm.onTrackFeedback,"insert-code-snippet":_vm.onInsertCodeSnippet}})}),_vm._v(" "),(!_vm.hasMessages && !_vm.isLoading)?[_c('gl-empty-state',{key:"empty-state",staticClass:"gl-flex-grow gl-justify-center",attrs:{"svg-path":_vm.$options.emptySvg,"svg-height":145,"title":_vm.emptyStateTitle},scopedSlots:_vm._u([{key:"description",fn:function(){return [_c('p',{staticClass:"gl-mb-3",attrs:{"data-testid":"gl-duo-chat-empty-state-description"}},[_vm._v("\n "+_vm._s(_vm.emptyStateDescription)+"\n ")]),_vm._v(" "),_c('p',{staticClass:"gl-mt-3 gl-text-sm gl-text-subtle",attrs:{"data-testid":"gl-duo-chat-empty-state-secondary-description"}},[_vm._v("\n "+_vm._s(_vm.emptyStateSecondaryDescription)+"\n ")])]},proxy:true}],null,false,460840487)}),_vm._v(" "),_c('gl-duo-chat-predefined-prompts',{key:"predefined-prompts",attrs:{"prompts":_vm.predefinedPrompts},on:{"click":_vm.sendPredefinedPrompt}})]:_vm._e(),_vm._v(" "),(_vm.isLoading)?_c('gl-duo-chat-loader',{key:"loader",attrs:{"tool-name":_vm.toolName}}):_vm._e(),_vm._v(" "),_c('div',{key:"anchor",ref:"anchor",staticClass:"scroll-anchor"})],2)],1),_vm._v(" "),(_vm.isChatAvailable)?_c('footer',{staticClass:"duo-chat-drawer-footer duo-chat-drawer-footer-sticky gl-border-t gl-bg-gray-10 gl-p-5",class:{ 'duo-chat-drawer-body-scrim-on-footer': !_vm.scrolledToBottom },attrs:{"data-testid":"chat-footer"}},[_c('gl-form',{attrs:{"data-testid":"chat-prompt-form"},on:{"submit":function($event){$event.stopPropagation();$event.preventDefault();return _vm.sendChatPrompt.apply(null, arguments)}}},[_c('div',{staticClass:"gl-relative gl-max-w-full"},[_vm._t("context-items-menu",null,{"isOpen":_vm.contextItemsMenuIsOpen,"onClose":_vm.closeContextItemsMenuOpen,"setRef":_vm.setContextItemsMenuRef,"focusPrompt":_vm.focusChatInput})],2),_vm._v(" "),_c('gl-form-input-group',{scopedSlots:_vm._u([{key:"append",fn:function(){return [(_vm.displaySubmitButton)?_c('gl-button',{staticClass:"!gl-absolute gl-bottom-2 gl-right-2 !gl-rounded-base",attrs:{"icon":"paper-airplane","category":"primary","variant":"confirm","type":"submit","data-testid":"chat-prompt-submit-button","aria-label":_vm.$options.i18n.CHAT_SUBMIT_LABEL}}):_c('gl-button',{staticClass:"!gl-absolute gl-bottom-2 gl-right-2 !gl-rounded-base",attrs:{"icon":"stop","category":"primary","variant":"default","data-testid":"chat-prompt-cancel-button","aria-label":_vm.$options.i18n.CHAT_CANCEL_LABEL},on:{"click":_vm.cancelPrompt}})]},proxy:true}],null,false,677611116)},[_c('div',{staticClass:"duo-chat-input gl-min-h-8 gl-max-w-full gl-grow gl-rounded-base gl-bg-white gl-align-top gl-shadow-inner-1-gray-400",attrs:{"data-value":_vm.prompt}},[(_vm.shouldShowSlashCommands)?_c('gl-card',{ref:"commands",staticClass:"slash-commands !gl-absolute gl-w-full -gl-translate-y-full gl-list-none gl-pl-0 gl-shadow-md",attrs:{"body-class":"!gl-p-2"}},_vm._l((_vm.filteredSlashCommands),function(command,index){return _c('gl-dropdown-item',{key:command.name,class:{ 'active-command': index === _vm.activeCommandIndex },on:{"click":function($event){return _vm.selectSlashCommand(index)}},nativeOn:{"mouseenter":function($event){_vm.activeCommandIndex = index;}}},[_c('span',{staticClass:"gl-flex gl-justify-between"},[_c('span',{staticClass:"gl-block"},[_vm._v(_vm._s(command.name))]),_vm._v(" "),_c('small',{staticClass:"gl-pl-3 gl-text-right gl-italic gl-text-gray-500"},[_vm._v(_vm._s(command.description))])])])}),1):_vm._e(),_vm._v(" "),_c('gl-form-textarea',{ref:"prompt",staticClass:"gl-absolute !gl-h-full gl-rounded-br-none gl-rounded-tr-none !gl-bg-transparent !gl-py-4 !gl-shadow-none",class:{ 'gl-truncate': !_vm.prompt },attrs:{"data-testid":"chat-prompt-input","placeholder":_vm.inputPlaceholder,"autofocus":""},on:{"compositionend":_vm.compositionEnd},nativeOn:{"keydown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }if($event.ctrlKey||$event.shiftKey||$event.altKey||$event.metaKey){ return null; }$event.preventDefault();},"keyup":function($event){return _vm.onInputKeyup.apply(null, arguments)}},model:{value:(_vm.prompt),callback:function ($$v) {_vm.prompt=$$v;},expression:"prompt"}})],1)]),_vm._v(" "),_c('p',{staticClass:"gl-mb-0 gl-mt-3 gl-text-sm gl-leading-20 gl-text-subtle",attrs:{"data-testid":"chat-legal-disclaimer"}},[_vm._v("\n "+_vm._s(_vm.$options.i18n.CHAT_LEGAL_DISCLAIMER)+"\n ")])],1)],1):_vm._e()]):_vm._e()};
|
|
442
496
|
var __vue_staticRenderFns__ = [];
|
|
443
497
|
|
|
444
498
|
/* style */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { setStoryTimeout } from '../../../../utils/test_utils';
|
|
2
|
-
import { DOCUMENTATION_SOURCE_TYPES, MESSAGE_MODEL_ROLES, CHAT_RESET_MESSAGE, CHAT_CLEAN_MESSAGE } from './constants';
|
|
2
|
+
import { DOCUMENTATION_SOURCE_TYPES, MESSAGE_MODEL_ROLES, CHAT_RESET_MESSAGE, CHAT_CLEAN_MESSAGE, CHAT_INCLUDE_MESSAGE } from './constants';
|
|
3
3
|
import { getMockContextItems } from './components/duo_chat_context/mock_context_data';
|
|
4
4
|
|
|
5
5
|
const MOCK_SOURCES = [{
|
|
@@ -154,5 +154,9 @@ const SLASH_COMMANDS = [{
|
|
|
154
154
|
name: '/explain',
|
|
155
155
|
description: 'Explain the selected snippet.'
|
|
156
156
|
}];
|
|
157
|
+
const INCLUDE_SLASH_COMMAND = {
|
|
158
|
+
name: CHAT_INCLUDE_MESSAGE,
|
|
159
|
+
description: 'Include additional context in the conversation.'
|
|
160
|
+
};
|
|
157
161
|
|
|
158
|
-
export { MOCK_RESPONSE_MESSAGE, MOCK_RESPONSE_MESSAGE_FOR_STREAMING, MOCK_USER_PROMPT_MESSAGE, SLASH_COMMANDS, generateMockResponseChunks, generateSeparateChunks, renderGFM, renderMarkdown };
|
|
162
|
+
export { INCLUDE_SLASH_COMMAND, MOCK_RESPONSE_MESSAGE, MOCK_RESPONSE_MESSAGE_FOR_STREAMING, MOCK_USER_PROMPT_MESSAGE, SLASH_COMMANDS, generateMockResponseChunks, generateSeparateChunks, renderGFM, renderMarkdown };
|
package/dist/index.js
CHANGED
|
@@ -89,6 +89,7 @@ export { default as GlAccordionItem } from './components/base/accordion/accordio
|
|
|
89
89
|
export { default as GlExperimentBadge } from './components/experimental/experiment_badge/experiment_badge';
|
|
90
90
|
export { default as GlDuoUserFeedback } from './components/experimental/duo/user_feedback/user_feedback';
|
|
91
91
|
export { default as GlDuoChat } from './components/experimental/duo/chat/duo_chat';
|
|
92
|
+
export { default as GlDuoChatContextItemMenu } from './components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu';
|
|
92
93
|
export { default as GlAnimatedNumber } from './components/utilities/animated_number/animated_number';
|
|
93
94
|
export { default as GlFriendlyWrap } from './components/utilities/friendly_wrap/friendly_wrap';
|
|
94
95
|
export { default as GlIntersperse } from './components/utilities/intersperse/intersperse';
|
package/package.json
CHANGED
|
@@ -88,6 +88,7 @@ export default {
|
|
|
88
88
|
<button
|
|
89
89
|
class="gl-flex gl-w-full gl-items-center gl-border-0 gl-bg-transparent gl-p-0 gl-text-left gl-text-xs gl-lowercase gl-text-gray-500"
|
|
90
90
|
data-testid="chat-context-selections-title"
|
|
91
|
+
type="button"
|
|
91
92
|
@click="toggleCollapse"
|
|
92
93
|
>
|
|
93
94
|
<gl-icon :name="collapseIconName" data-testid="chat-context-collapse-icon" /> {{ title }}
|
|
@@ -15,7 +15,14 @@ import { SafeHtmlDirective as SafeHtml } from '../../../../directives/safe_html/
|
|
|
15
15
|
import GlDuoChatLoader from './components/duo_chat_loader/duo_chat_loader.vue';
|
|
16
16
|
import GlDuoChatPredefinedPrompts from './components/duo_chat_predefined_prompts/duo_chat_predefined_prompts.vue';
|
|
17
17
|
import GlDuoChatConversation from './components/duo_chat_conversation/duo_chat_conversation.vue';
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
CHAT_CLEAN_MESSAGE,
|
|
20
|
+
CHAT_RESET_MESSAGE,
|
|
21
|
+
CHAT_CLEAR_MESSAGE,
|
|
22
|
+
CHAT_INCLUDE_MESSAGE,
|
|
23
|
+
MESSAGE_MODEL_ROLES,
|
|
24
|
+
} from './constants';
|
|
25
|
+
import { INCLUDE_SLASH_COMMAND } from './mock_data';
|
|
19
26
|
|
|
20
27
|
export const i18n = {
|
|
21
28
|
CHAT_DEFAULT_TITLE: 'GitLab Duo Chat',
|
|
@@ -214,6 +221,8 @@ export default {
|
|
|
214
221
|
activeCommandIndex: 0,
|
|
215
222
|
displaySubmitButton: true,
|
|
216
223
|
compositionJustEnded: false,
|
|
224
|
+
contextItemsMenuIsOpen: false,
|
|
225
|
+
contextItemMenuRef: null,
|
|
217
226
|
};
|
|
218
227
|
},
|
|
219
228
|
computed: {
|
|
@@ -241,6 +250,9 @@ export default {
|
|
|
241
250
|
lastMessage() {
|
|
242
251
|
return this.messages?.[this.messages.length - 1];
|
|
243
252
|
},
|
|
253
|
+
caseInsensitivePrompt() {
|
|
254
|
+
return this.prompt.toLowerCase().trim();
|
|
255
|
+
},
|
|
244
256
|
resetDisabled() {
|
|
245
257
|
if (this.isLoading || !this.hasMessages) {
|
|
246
258
|
return true;
|
|
@@ -257,20 +269,36 @@ export default {
|
|
|
257
269
|
);
|
|
258
270
|
},
|
|
259
271
|
filteredSlashCommands() {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
272
|
+
return this.slashCommands
|
|
273
|
+
.filter((c) => c.name.toLowerCase().startsWith(this.caseInsensitivePrompt))
|
|
274
|
+
.filter((c) => {
|
|
275
|
+
if (c.name === CHAT_INCLUDE_MESSAGE) {
|
|
276
|
+
return this.hasContextItemSelectionMenu;
|
|
277
|
+
}
|
|
278
|
+
return true;
|
|
279
|
+
});
|
|
264
280
|
},
|
|
265
281
|
shouldShowSlashCommands() {
|
|
266
|
-
if (!this.withSlashCommands) return false;
|
|
267
|
-
const
|
|
268
|
-
const startsWithSlash = caseInsensitivePrompt.startsWith('/');
|
|
282
|
+
if (!this.withSlashCommands || this.contextItemsMenuIsOpen) return false;
|
|
283
|
+
const startsWithSlash = this.caseInsensitivePrompt.startsWith('/');
|
|
269
284
|
const startsWithSlashCommand = this.slashCommands.some((c) =>
|
|
270
|
-
caseInsensitivePrompt.startsWith(c.name)
|
|
285
|
+
this.caseInsensitivePrompt.startsWith(c.name)
|
|
271
286
|
);
|
|
272
287
|
return startsWithSlash && this.filteredSlashCommands.length && !startsWithSlashCommand;
|
|
273
288
|
},
|
|
289
|
+
shouldShowContextItemSelectionMenu() {
|
|
290
|
+
if (!this.hasContextItemSelectionMenu) {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const isSlash = this.caseInsensitivePrompt === '/';
|
|
295
|
+
if (!this.caseInsensitivePrompt || isSlash) {
|
|
296
|
+
// if user has removed entire command (or whole command except for '/') we should close context item menu and allow slash command menu to show again
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return INCLUDE_SLASH_COMMAND.name.startsWith(this.caseInsensitivePrompt);
|
|
301
|
+
},
|
|
274
302
|
inputPlaceholder() {
|
|
275
303
|
if (this.chatPromptPlaceholder) {
|
|
276
304
|
return this.chatPromptPlaceholder;
|
|
@@ -280,6 +308,9 @@ export default {
|
|
|
280
308
|
? i18n.CHAT_PROMPT_PLACEHOLDER_WITH_COMMANDS
|
|
281
309
|
: i18n.CHAT_PROMPT_PLACEHOLDER_DEFAULT;
|
|
282
310
|
},
|
|
311
|
+
hasContextItemSelectionMenu() {
|
|
312
|
+
return Boolean(this.contextItemMenuRef);
|
|
313
|
+
},
|
|
283
314
|
},
|
|
284
315
|
watch: {
|
|
285
316
|
isLoading(newVal) {
|
|
@@ -287,13 +318,19 @@ export default {
|
|
|
287
318
|
this.displaySubmitButton = true; // Re-enable submit button when loading stops
|
|
288
319
|
}
|
|
289
320
|
this.isHidden = false;
|
|
290
|
-
this.scrollToBottom();
|
|
291
321
|
},
|
|
292
322
|
isStreaming(newVal) {
|
|
293
323
|
if (!newVal && !this.isLoading) {
|
|
294
324
|
this.displaySubmitButton = true; // Re-enable submit button when streaming stops
|
|
295
325
|
}
|
|
296
326
|
},
|
|
327
|
+
lastMessage(newMessage) {
|
|
328
|
+
if (this.scrolledToBottom || newMessage.role.toLowerCase() === MESSAGE_MODEL_ROLES.user) {
|
|
329
|
+
// only scroll to bottom on new message if the user hasn't explicitly scrolled up to view an earlier message
|
|
330
|
+
// or if the user has just submitted a new message
|
|
331
|
+
this.scrollToBottom();
|
|
332
|
+
}
|
|
333
|
+
},
|
|
297
334
|
},
|
|
298
335
|
created() {
|
|
299
336
|
this.handleScrollingTrottled = throttle(this.handleScrolling, 200); // Assume a 200ms throttle for example
|
|
@@ -322,28 +359,42 @@ export default {
|
|
|
322
359
|
this.setPromptAndFocus();
|
|
323
360
|
},
|
|
324
361
|
sendChatPrompt() {
|
|
325
|
-
if (!this.displaySubmitButton) {
|
|
362
|
+
if (!this.displaySubmitButton || this.contextItemsMenuIsOpen) {
|
|
326
363
|
return;
|
|
327
364
|
}
|
|
328
365
|
if (this.prompt) {
|
|
329
|
-
if (this.
|
|
366
|
+
if (this.caseInsensitivePrompt === CHAT_RESET_MESSAGE && this.resetDisabled) {
|
|
330
367
|
return;
|
|
331
368
|
}
|
|
369
|
+
|
|
370
|
+
if (
|
|
371
|
+
this.caseInsensitivePrompt.startsWith(CHAT_INCLUDE_MESSAGE) &&
|
|
372
|
+
this.hasContextItemSelectionMenu
|
|
373
|
+
) {
|
|
374
|
+
this.contextItemsMenuIsOpen = true;
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (
|
|
379
|
+
![CHAT_RESET_MESSAGE, CHAT_CLEAN_MESSAGE, CHAT_CLEAR_MESSAGE].includes(
|
|
380
|
+
this.caseInsensitivePrompt
|
|
381
|
+
)
|
|
382
|
+
) {
|
|
383
|
+
this.displaySubmitButton = false;
|
|
384
|
+
}
|
|
385
|
+
|
|
332
386
|
/**
|
|
333
387
|
* Emitted when a new user prompt should be sent out.
|
|
334
388
|
*
|
|
335
389
|
* @param {String} prompt The user prompt to send.
|
|
336
390
|
*/
|
|
337
|
-
|
|
338
|
-
if (![CHAT_RESET_MESSAGE, CHAT_CLEAN_MESSAGE, CHAT_CLEAR_MESSAGE].includes(this.prompt)) {
|
|
339
|
-
this.displaySubmitButton = false;
|
|
340
|
-
}
|
|
341
391
|
this.$emit('send-chat-prompt', this.prompt.trim());
|
|
342
392
|
|
|
343
393
|
this.setPromptAndFocus();
|
|
344
394
|
}
|
|
345
395
|
},
|
|
346
396
|
sendPredefinedPrompt(prompt) {
|
|
397
|
+
this.contextItemsMenuIsOpen = false;
|
|
347
398
|
this.prompt = prompt;
|
|
348
399
|
this.sendChatPrompt();
|
|
349
400
|
},
|
|
@@ -352,8 +403,6 @@ export default {
|
|
|
352
403
|
this.scrolledToBottom = scrollTop + offsetHeight >= scrollHeight;
|
|
353
404
|
},
|
|
354
405
|
async scrollToBottom() {
|
|
355
|
-
// This method is also called directly by consumers of this component
|
|
356
|
-
// https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/3269f6200dc3821c62a3992b40c971dd9ee55d87/webviews/vue2/gitlab_duo_chat/src/App.vue#L97
|
|
357
406
|
await this.$nextTick();
|
|
358
407
|
|
|
359
408
|
this.$refs.anchor?.scrollIntoView?.();
|
|
@@ -379,6 +428,18 @@ export default {
|
|
|
379
428
|
onInputKeyup(e) {
|
|
380
429
|
const { key } = e;
|
|
381
430
|
|
|
431
|
+
if (this.contextItemsMenuIsOpen) {
|
|
432
|
+
if (!this.shouldShowContextItemSelectionMenu) {
|
|
433
|
+
this.contextItemsMenuIsOpen = false;
|
|
434
|
+
}
|
|
435
|
+
this.contextItemMenuRef?.handleKeyUp(e);
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
if (this.caseInsensitivePrompt === INCLUDE_SLASH_COMMAND.name) {
|
|
439
|
+
this.contextItemsMenuIsOpen = true;
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
|
|
382
443
|
if (this.shouldShowSlashCommands) {
|
|
383
444
|
e.preventDefault();
|
|
384
445
|
|
|
@@ -426,6 +487,10 @@ export default {
|
|
|
426
487
|
this.sendChatPrompt();
|
|
427
488
|
} else {
|
|
428
489
|
this.setPromptAndFocus(`${command.name} `);
|
|
490
|
+
|
|
491
|
+
if (command.name === CHAT_INCLUDE_MESSAGE && this.hasContextItemSelectionMenu) {
|
|
492
|
+
this.contextItemsMenuIsOpen = true;
|
|
493
|
+
}
|
|
429
494
|
}
|
|
430
495
|
},
|
|
431
496
|
onInsertCodeSnippet(e) {
|
|
@@ -435,6 +500,13 @@ export default {
|
|
|
435
500
|
*/
|
|
436
501
|
this.$emit('insert-code-snippet', e);
|
|
437
502
|
},
|
|
503
|
+
closeContextItemsMenuOpen() {
|
|
504
|
+
this.contextItemsMenuIsOpen = false;
|
|
505
|
+
this.setPromptAndFocus();
|
|
506
|
+
},
|
|
507
|
+
setContextItemsMenuRef(ref) {
|
|
508
|
+
this.contextItemMenuRef = ref;
|
|
509
|
+
},
|
|
438
510
|
},
|
|
439
511
|
i18n,
|
|
440
512
|
emptySvg,
|
|
@@ -561,6 +633,19 @@ export default {
|
|
|
561
633
|
:class="{ 'duo-chat-drawer-body-scrim-on-footer': !scrolledToBottom }"
|
|
562
634
|
>
|
|
563
635
|
<gl-form data-testid="chat-prompt-form" @submit.stop.prevent="sendChatPrompt">
|
|
636
|
+
<div class="gl-relative gl-max-w-full">
|
|
637
|
+
<!--
|
|
638
|
+
@slot For integrating `<gl-context-items-menu>` component if pinned-context should be available. The following scopedSlot properties are provided: `isOpen`, `onClose`, `setRef`, `focusPrompt`, which should be passed to the `<gl-context-items-menu>` component when rendering, e.g. `<template #context-items-menu="{ isOpen, onClose, setRef, focusPrompt }">` `<gl-duo-chat-context-item-menu :ref="setRef" :open="isOpen" @close="onClose" @focus-prompt="focusPrompt" ...`
|
|
639
|
+
-->
|
|
640
|
+
<slot
|
|
641
|
+
name="context-items-menu"
|
|
642
|
+
:is-open="contextItemsMenuIsOpen"
|
|
643
|
+
:on-close="closeContextItemsMenuOpen"
|
|
644
|
+
:set-ref="setContextItemsMenuRef"
|
|
645
|
+
:focus-prompt="focusChatInput"
|
|
646
|
+
></slot>
|
|
647
|
+
</div>
|
|
648
|
+
|
|
564
649
|
<gl-form-input-group>
|
|
565
650
|
<div
|
|
566
651
|
class="duo-chat-input gl-min-h-8 gl-max-w-full gl-grow gl-rounded-base gl-bg-white gl-align-top gl-shadow-inner-1-gray-400"
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
MESSAGE_MODEL_ROLES,
|
|
5
5
|
CHAT_RESET_MESSAGE,
|
|
6
6
|
CHAT_CLEAN_MESSAGE,
|
|
7
|
+
CHAT_INCLUDE_MESSAGE,
|
|
7
8
|
} from './constants';
|
|
8
9
|
import { getMockContextItems } from './components/duo_chat_context/mock_context_data';
|
|
9
10
|
|
|
@@ -170,3 +171,8 @@ export const SLASH_COMMANDS = [
|
|
|
170
171
|
description: 'Explain the selected snippet.',
|
|
171
172
|
},
|
|
172
173
|
];
|
|
174
|
+
|
|
175
|
+
export const INCLUDE_SLASH_COMMAND = {
|
|
176
|
+
name: CHAT_INCLUDE_MESSAGE,
|
|
177
|
+
description: 'Include additional context in the conversation.',
|
|
178
|
+
};
|
package/src/index.js
CHANGED
|
@@ -100,6 +100,7 @@ export { default as GlAccordionItem } from './components/base/accordion/accordio
|
|
|
100
100
|
export { default as GlExperimentBadge } from './components/experimental/experiment_badge/experiment_badge.vue';
|
|
101
101
|
export { default as GlDuoUserFeedback } from './components/experimental/duo/user_feedback/user_feedback.vue';
|
|
102
102
|
export { default as GlDuoChat } from './components/experimental/duo/chat/duo_chat.vue';
|
|
103
|
+
export { default as GlDuoChatContextItemMenu } from './components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu.vue';
|
|
103
104
|
|
|
104
105
|
// Utilities
|
|
105
106
|
export { default as GlAnimatedNumber } from './components/utilities/animated_number/animated_number.vue';
|