@gitlab/duo-ui 13.2.0 → 13.4.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.
Files changed (22) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/components/chat/components/duo_chat_header/duo_chat_header.js +4 -2
  3. package/dist/components/chat/components/duo_chat_header/duo_chat_header_agent_item/duo_chat_header_agent_item.js +62 -0
  4. package/dist/components/chat/components/duo_chat_header/web_duo_chat_header.js +4 -2
  5. package/dist/components/chat/components/duo_chat_message/message_types/message_tool.js +1 -1
  6. package/dist/components/chat/components/duo_chat_message_tool_approval/components/issuable_tool_params.js +69 -11
  7. package/dist/components/chat/components/duo_chat_message_tool_approval/components/pre_block.js +1 -1
  8. package/dist/components/chat/components/duo_chat_message_tool_approval/message_tool_approval.js +10 -0
  9. package/dist/components/chat/constants.js +5 -0
  10. package/dist/components/chat/mock_data.js +86 -1
  11. package/package.json +1 -1
  12. package/src/components/chat/components/duo_chat_header/duo_chat_header.vue +3 -6
  13. package/src/components/chat/components/duo_chat_header/duo_chat_header_agent_item/duo_chat_header_agent_item.vue +43 -0
  14. package/src/components/chat/components/duo_chat_header/web_duo_chat_header.md +1 -0
  15. package/src/components/chat/components/duo_chat_header/web_duo_chat_header.vue +3 -6
  16. package/src/components/chat/components/duo_chat_message/message_types/message_tool.vue +1 -11
  17. package/src/components/chat/components/duo_chat_message_tool_approval/components/issuable_tool_params.vue +94 -14
  18. package/src/components/chat/components/duo_chat_message_tool_approval/components/pre_block.vue +1 -1
  19. package/src/components/chat/components/duo_chat_message_tool_approval/message_tool_approval.vue +25 -0
  20. package/src/components/chat/constants.js +5 -0
  21. package/src/components/chat/mock_data.js +92 -0
  22. package/translations.js +18 -2
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [13.4.0](https://gitlab.com/gitlab-org/duo-ui/compare/v13.3.0...v13.4.0) (2025-10-30)
2
+
3
+
4
+ ### Features
5
+
6
+ * Improve support for work items and notes ([7c0c5e3](https://gitlab.com/gitlab-org/duo-ui/commit/7c0c5e3b3da6a5ee11fde57344348228f50c1362))
7
+
8
+ # [13.3.0](https://gitlab.com/gitlab-org/duo-ui/compare/v13.2.0...v13.3.0) (2025-10-29)
9
+
10
+
11
+ ### Features
12
+
13
+ * **DuoChatHeader:** adds visual tip for foundational agents ([9524a88](https://gitlab.com/gitlab-org/duo-ui/commit/9524a88b72d37db64a25a742cfaf76812c30db9f))
14
+
1
15
  # [13.2.0](https://gitlab.com/gitlab-org/duo-ui/compare/v13.1.0...v13.2.0) (2025-10-28)
2
16
 
3
17
 
@@ -2,6 +2,7 @@ import Vue from 'vue';
2
2
  import { GlToast, GlAlert, GlButton, GlExperimentBadge, GlDisclosureDropdown, GlSafeHtmlDirective, GlTooltipDirective } from '@gitlab/ui';
3
3
  import { translate, sprintf } from '../../../../utils/i18n';
4
4
  import { VIEW_TYPES } from './constants';
5
+ import DuoChatHeaderAgentItem from './duo_chat_header_agent_item/duo_chat_header_agent_item';
5
6
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
6
7
 
7
8
  const i18n = {
@@ -24,7 +25,8 @@ var script = {
24
25
  GlAlert,
25
26
  GlButton,
26
27
  GlExperimentBadge,
27
- GlDisclosureDropdown
28
+ GlDisclosureDropdown,
29
+ DuoChatHeaderAgentItem
28
30
  },
29
31
  directives: {
30
32
  SafeHtml: GlSafeHtmlDirective,
@@ -149,7 +151,7 @@ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=
149
151
  _vm.isMultithreaded && (_vm.activeThreadId || _vm.currentView === _vm.VIEW_TYPES.LIST || _vm.hasManyAgents)
150
152
  )?[(_vm.hasManyAgents)?_c('gl-disclosure-dropdown',{attrs:{"title":_vm.$options.i18n.CHAT_NEW_TOOLTIP,"toggle-text":_vm.$options.i18n.CHAT_NEW_TOOLTIP,"items":_vm.agents,"data-testid":"chat-new-button","variant":"confirm","category":"tertiary","size":"small","icon":"duo-chat-new","text-sr-only":"","aria-label":_vm.$options.i18n.CHAT_NEW_LABEL,"no-caret":""},on:{"action":_vm.startNewChat},scopedSlots:_vm._u([{key:"list-item",fn:function(ref){
151
153
  var item = ref.item;
152
- return [_c('span',{staticClass:"gl-flex gl-flex-col"},[_c('span',{attrs:{"clas":"gl-block"}},[_vm._v(_vm._s(item.name))]),_vm._v(" "),_c('span',{staticClass:"gl-overflow-hidden gl-text-ellipsis gl-whitespace-nowrap gl-text-sm"},[_vm._v(_vm._s(item.description))])])]}}],null,false,117082970)}):_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.CHAT_NEW_TOOLTIP,"data-testid":"chat-new-button","variant":"confirm","category":"tertiary","size":"small","icon":"duo-chat-new","aria-label":_vm.$options.i18n.CHAT_NEW_LABEL},on:{"click":_vm.startNewChat}})]:_vm._e(),_vm._v(" "),(_vm.isMultithreaded && _vm.currentView === _vm.VIEW_TYPES.CHAT)?_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.CHAT_HISTORY_TOOLTIP,"data-testid":"go-back-to-list-button","category":"tertiary","size":"small","icon":"history","aria-label":_vm.$options.i18n.CHAT_BACK_LABEL},on:{"click":function($event){return _vm.$emit('go-back')}}}):_vm._e(),_vm._v(" "),(_vm.isMultithreaded && _vm.activeThreadId && _vm.currentView === _vm.VIEW_TYPES.LIST)?_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.CHAT_BACK_TO_CHAT_TOOLTIP,"data-testid":"go-back-to-chat-button","category":"tertiary","size":"small","icon":"go-back","aria-label":_vm.$options.i18n.CHAT_BACK_TO_CHAT_TOOLTIP},on:{"click":function($event){return _vm.$emit('go-back-to-chat')}}}):_vm._e(),_vm._v(" "),(_vm.sessionId)?_c('gl-disclosure-dropdown',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip",value:(_vm.showSessionDropdownTooltip),expression:"showSessionDropdownTooltip"}],attrs:{"icon":"ellipsis_v","category":"tertiary","text-sr-only":"","size":"small","toggle-text":_vm.$options.i18n.CHAT_DROPDOWN_MORE_OPTIONS,"items":_vm.sessionIdItems,"no-caret":""},on:{"shown":_vm.showSessionDropdown,"hidden":_vm.hideSessionDropdown}}):_vm._e(),_vm._v(" "),_c('gl-button',{staticClass:"gl-ml-auto",attrs:{"category":"tertiary","variant":"default","icon":"close","size":"small","data-testid":"chat-close-button","aria-label":_vm.$options.i18n.CHAT_CLOSE_LABEL},on:{"click":function($event){return _vm.$emit('close')}}})],2)]),_vm._v(" "),_vm._t("subheader"),_vm._v(" "),(_vm.error)?_c('gl-alert',{key:"error",staticClass:"!gl-pl-9",attrs:{"dismissible":false,"variant":"danger","role":"alert","data-testid":"chat-error"}},[_c('span',{directives:[{name:"safe-html",rawName:"v-safe-html",value:(_vm.error),expression:"error"}]})]):_vm._e()],2)};
154
+ return [_c('duo-chat-header-agent-item',{attrs:{"agent":item}})]}}],null,false,1406306174)}):_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.CHAT_NEW_TOOLTIP,"data-testid":"chat-new-button","variant":"confirm","category":"tertiary","size":"small","icon":"duo-chat-new","aria-label":_vm.$options.i18n.CHAT_NEW_LABEL},on:{"click":_vm.startNewChat}})]:_vm._e(),_vm._v(" "),(_vm.isMultithreaded && _vm.currentView === _vm.VIEW_TYPES.CHAT)?_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.CHAT_HISTORY_TOOLTIP,"data-testid":"go-back-to-list-button","category":"tertiary","size":"small","icon":"history","aria-label":_vm.$options.i18n.CHAT_BACK_LABEL},on:{"click":function($event){return _vm.$emit('go-back')}}}):_vm._e(),_vm._v(" "),(_vm.isMultithreaded && _vm.activeThreadId && _vm.currentView === _vm.VIEW_TYPES.LIST)?_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.CHAT_BACK_TO_CHAT_TOOLTIP,"data-testid":"go-back-to-chat-button","category":"tertiary","size":"small","icon":"go-back","aria-label":_vm.$options.i18n.CHAT_BACK_TO_CHAT_TOOLTIP},on:{"click":function($event){return _vm.$emit('go-back-to-chat')}}}):_vm._e(),_vm._v(" "),(_vm.sessionId)?_c('gl-disclosure-dropdown',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip",value:(_vm.showSessionDropdownTooltip),expression:"showSessionDropdownTooltip"}],attrs:{"icon":"ellipsis_v","category":"tertiary","text-sr-only":"","size":"small","toggle-text":_vm.$options.i18n.CHAT_DROPDOWN_MORE_OPTIONS,"items":_vm.sessionIdItems,"no-caret":""},on:{"shown":_vm.showSessionDropdown,"hidden":_vm.hideSessionDropdown}}):_vm._e(),_vm._v(" "),_c('gl-button',{staticClass:"gl-ml-auto",attrs:{"category":"tertiary","variant":"default","icon":"close","size":"small","data-testid":"chat-close-button","aria-label":_vm.$options.i18n.CHAT_CLOSE_LABEL},on:{"click":function($event){return _vm.$emit('close')}}})],2)]),_vm._v(" "),_vm._t("subheader"),_vm._v(" "),(_vm.error)?_c('gl-alert',{key:"error",staticClass:"!gl-pl-9",attrs:{"dismissible":false,"variant":"danger","role":"alert","data-testid":"chat-error"}},[_c('span',{directives:[{name:"safe-html",rawName:"v-safe-html",value:(_vm.error),expression:"error"}]})]):_vm._e()],2)};
153
155
  var __vue_staticRenderFns__ = [];
154
156
 
155
157
  /* style */
@@ -0,0 +1,62 @@
1
+ import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
2
+ import { translate } from '@gitlab/ui/dist/utils/i18n';
3
+ import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
4
+
5
+ const i18n = {
6
+ CHAT_VERIFIED_AGENT: translate('DuoChat.verifiedAgent', 'Created and maintained by GitLab')
7
+ };
8
+ var script = {
9
+ name: 'ChatAgentItem',
10
+ components: {
11
+ GlIcon
12
+ },
13
+ directives: {
14
+ GlTooltip: GlTooltipDirective
15
+ },
16
+ props: {
17
+ agent: {
18
+ type: Object,
19
+ required: true
20
+ }
21
+ },
22
+ i18n
23
+ };
24
+
25
+ /* script */
26
+ const __vue_script__ = script;
27
+
28
+ /* template */
29
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('span',{staticClass:"gl-flex gl-flex-col"},[_c('span',{staticClass:"gl-mb-1 gl-inline-block gl-text-lg gl-font-bold gl-text-strong"},[_vm._v("\n "+_vm._s(_vm.agent.name)+"\n "),(_vm.agent.foundational)?_c('gl-icon',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"name":"tanuki-verified","variant":"subtle","title":_vm.$options.i18n.CHAT_VERIFIED_AGENT}}):_vm._e()],1),_vm._v(" "),_c('span',{staticClass:"gl-overflow-hidden gl-text-ellipsis gl-whitespace-nowrap gl-text-sm"},[_vm._v("\n "+_vm._s(_vm.agent.description)+"\n ")])])};
30
+ var __vue_staticRenderFns__ = [];
31
+
32
+ /* style */
33
+ const __vue_inject_styles__ = undefined;
34
+ /* scoped */
35
+ const __vue_scope_id__ = undefined;
36
+ /* module identifier */
37
+ const __vue_module_identifier__ = undefined;
38
+ /* functional template */
39
+ const __vue_is_functional_template__ = false;
40
+ /* style inject */
41
+
42
+ /* style inject SSR */
43
+
44
+ /* style inject shadow dom */
45
+
46
+
47
+
48
+ const __vue_component__ = __vue_normalize__(
49
+ { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
50
+ __vue_inject_styles__,
51
+ __vue_script__,
52
+ __vue_scope_id__,
53
+ __vue_is_functional_template__,
54
+ __vue_module_identifier__,
55
+ false,
56
+ undefined,
57
+ undefined,
58
+ undefined
59
+ );
60
+
61
+ export default __vue_component__;
62
+ export { i18n };
@@ -1,6 +1,7 @@
1
1
  import Vue from 'vue';
2
2
  import { GlToast, GlAlert, GlAvatar, GlButton, GlDisclosureDropdown, GlSafeHtmlDirective, GlTooltipDirective } from '@gitlab/ui';
3
3
  import { translate, sprintf } from '../../../../utils/i18n';
4
+ import DuoChatHeaderAgentItem from './duo_chat_header_agent_item/duo_chat_header_agent_item';
4
5
  import { VIEW_TYPES } from './constants';
5
6
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
6
7
 
@@ -24,7 +25,8 @@ var script = {
24
25
  GlAlert,
25
26
  GlAvatar,
26
27
  GlButton,
27
- GlDisclosureDropdown
28
+ GlDisclosureDropdown,
29
+ DuoChatHeaderAgentItem
28
30
  },
29
31
  directives: {
30
32
  SafeHtml: GlSafeHtmlDirective,
@@ -154,7 +156,7 @@ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=
154
156
  _vm.isMultithreaded && (_vm.activeThreadId || _vm.currentView === _vm.VIEW_TYPES.LIST || _vm.hasManyAgents)
155
157
  )?[(_vm.hasManyAgents)?_c('gl-disclosure-dropdown',{attrs:{"title":_vm.$options.i18n.CHAT_NEW_TOOLTIP,"toggle-text":_vm.$options.i18n.CHAT_NEW_TOOLTIP,"items":_vm.agents,"data-testid":"chat-new-button","variant":"confirm","category":"tertiary","size":"small","icon":"duo-chat-new","text-sr-only":"","aria-label":_vm.$options.i18n.CHAT_NEW_LABEL,"no-caret":""},on:{"action":_vm.startNewChat},scopedSlots:_vm._u([{key:"list-item",fn:function(ref){
156
158
  var item = ref.item;
157
- return [_c('span',{staticClass:"gl-flex gl-flex-col"},[_c('span',{staticClass:"gl-block"},[_vm._v(_vm._s(item.name))]),_vm._v(" "),_c('span',{staticClass:"gl-overflow-hidden gl-text-ellipsis gl-whitespace-nowrap gl-text-sm"},[_vm._v(_vm._s(item.description))])])]}}],null,false,2800000557)}):_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.CHAT_NEW_TOOLTIP,"data-testid":"chat-new-button","variant":"confirm","category":"tertiary","size":"small","icon":"duo-chat-new","aria-label":_vm.$options.i18n.CHAT_NEW_LABEL},on:{"click":_vm.startNewChat}})]:_vm._e(),_vm._v(" "),(!_vm.showStudioHeader && _vm.isMultithreaded && _vm.currentView === _vm.VIEW_TYPES.CHAT)?_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.CHAT_HISTORY_TOOLTIP,"data-testid":"go-back-to-list-button","category":"tertiary","size":"small","icon":"history","aria-label":_vm.$options.i18n.CHAT_BACK_LABEL},on:{"click":function($event){return _vm.$emit('go-back')}}}):_vm._e(),_vm._v(" "),(_vm.isMultithreaded && _vm.activeThreadId && _vm.currentView === _vm.VIEW_TYPES.LIST)?_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.CHAT_BACK_TO_CHAT_TOOLTIP,"data-testid":"go-back-to-chat-button","category":"tertiary","size":"small","icon":"go-back","aria-label":_vm.$options.i18n.CHAT_BACK_TO_CHAT_TOOLTIP},on:{"click":function($event){return _vm.$emit('go-back-to-chat')}}}):_vm._e(),_vm._v(" "),(_vm.sessionId)?_c('gl-disclosure-dropdown',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip",value:(_vm.showSessionDropdownTooltip),expression:"showSessionDropdownTooltip"}],attrs:{"icon":"ellipsis_v","category":"tertiary","text-sr-only":"","size":"small","toggle-text":_vm.$options.i18n.CHAT_DROPDOWN_MORE_OPTIONS,"items":_vm.sessionIdItems,"no-caret":""},on:{"shown":_vm.showSessionDropdown,"hidden":_vm.hideSessionDropdown}}):_vm._e()],2)]),_vm._v(" "),_vm._t("subheader"),_vm._v(" "),(_vm.error)?_c('gl-alert',{key:"error",staticClass:"!gl-pl-9",attrs:{"dismissible":false,"variant":"danger","role":"alert","data-testid":"chat-error"}},[_c('span',{directives:[{name:"safe-html",rawName:"v-safe-html",value:(_vm.error),expression:"error"}]})]):_vm._e()],2)};
159
+ return [_c('duo-chat-header-agent-item',{attrs:{"agent":item}})]}}],null,false,1406306174)}):_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.CHAT_NEW_TOOLTIP,"data-testid":"chat-new-button","variant":"confirm","category":"tertiary","size":"small","icon":"duo-chat-new","aria-label":_vm.$options.i18n.CHAT_NEW_LABEL},on:{"click":_vm.startNewChat}})]:_vm._e(),_vm._v(" "),(!_vm.showStudioHeader && _vm.isMultithreaded && _vm.currentView === _vm.VIEW_TYPES.CHAT)?_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.CHAT_HISTORY_TOOLTIP,"data-testid":"go-back-to-list-button","category":"tertiary","size":"small","icon":"history","aria-label":_vm.$options.i18n.CHAT_BACK_LABEL},on:{"click":function($event){return _vm.$emit('go-back')}}}):_vm._e(),_vm._v(" "),(_vm.isMultithreaded && _vm.activeThreadId && _vm.currentView === _vm.VIEW_TYPES.LIST)?_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.CHAT_BACK_TO_CHAT_TOOLTIP,"data-testid":"go-back-to-chat-button","category":"tertiary","size":"small","icon":"go-back","aria-label":_vm.$options.i18n.CHAT_BACK_TO_CHAT_TOOLTIP},on:{"click":function($event){return _vm.$emit('go-back-to-chat')}}}):_vm._e(),_vm._v(" "),(_vm.sessionId)?_c('gl-disclosure-dropdown',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip",value:(_vm.showSessionDropdownTooltip),expression:"showSessionDropdownTooltip"}],attrs:{"icon":"ellipsis_v","category":"tertiary","text-sr-only":"","size":"small","toggle-text":_vm.$options.i18n.CHAT_DROPDOWN_MORE_OPTIONS,"items":_vm.sessionIdItems,"no-caret":""},on:{"shown":_vm.showSessionDropdown,"hidden":_vm.hideSessionDropdown}}):_vm._e()],2)]),_vm._v(" "),_vm._t("subheader"),_vm._v(" "),(_vm.error)?_c('gl-alert',{key:"error",staticClass:"!gl-pl-9",attrs:{"dismissible":false,"variant":"danger","role":"alert","data-testid":"chat-error"}},[_c('span',{directives:[{name:"safe-html",rawName:"v-safe-html",value:(_vm.error),expression:"error"}]})]):_vm._e()],2)};
158
160
  var __vue_staticRenderFns__ = [];
159
161
 
160
162
  /* style */
@@ -120,7 +120,7 @@ var script = {
120
120
  return this.isDetailsOpen ? 'chevron-down' : 'chevron-right';
121
121
  },
122
122
  requiresApproval() {
123
- return [APPROVAL_TOOL_NAMES.runCommand, APPROVAL_TOOL_NAMES.runGitCommand, APPROVAL_TOOL_NAMES.createIssue, APPROVAL_TOOL_NAMES.updateIssue, APPROVAL_TOOL_NAMES.createMergeRequest, APPROVAL_TOOL_NAMES.updateMergeRequest, APPROVAL_TOOL_NAMES.createEpic, APPROVAL_TOOL_NAMES.updateEpic, APPROVAL_TOOL_NAMES.createCommit].includes(this.toolName);
123
+ return Object.values(APPROVAL_TOOL_NAMES).includes(this.toolName);
124
124
  },
125
125
  shouldShowDetails() {
126
126
  var _this$message;
@@ -1,8 +1,9 @@
1
- import { sprintf, translate } from '../../../../../utils/i18n';
1
+ import { translate, sprintf } from '../../../../../utils/i18n';
2
2
  import { APPROVAL_TOOL_NAMES } from '../../../constants';
3
3
  import BaseToolParams from './base_tool_params';
4
4
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
5
5
 
6
+ const NOTE_MESSAGE = translate('IssuableToolParams.NOTE_MESSAGE', 'Post a note on %{noteParentLabel} <code>%{noteParentIid}</code> that belongs to %{workItemParentType} <code>%{workItemParentId}</code>.');
6
7
  var script = {
7
8
  name: 'IssuableToolParams',
8
9
  components: {
@@ -12,7 +13,7 @@ var script = {
12
13
  toolName: {
13
14
  type: String,
14
15
  required: true,
15
- validator: toolName => [APPROVAL_TOOL_NAMES.createIssue, APPROVAL_TOOL_NAMES.updateIssue, APPROVAL_TOOL_NAMES.createEpic, APPROVAL_TOOL_NAMES.updateEpic, APPROVAL_TOOL_NAMES.createMergeRequest, APPROVAL_TOOL_NAMES.updateMergeRequest].includes(toolName)
16
+ validator: toolName => Object.values(APPROVAL_TOOL_NAMES).includes(toolName)
16
17
  },
17
18
  toolParams: {
18
19
  type: Object,
@@ -33,21 +34,59 @@ var script = {
33
34
  return (_this$toolParams4 = this.toolParams) === null || _this$toolParams4 === void 0 ? void 0 : _this$toolParams4.labels;
34
35
  },
35
36
  description() {
36
- var _this$toolParams5;
37
- return (_this$toolParams5 = this.toolParams) === null || _this$toolParams5 === void 0 ? void 0 : _this$toolParams5.description;
37
+ var _this$toolParams5, _this$toolParams6;
38
+ return ((_this$toolParams5 = this.toolParams) === null || _this$toolParams5 === void 0 ? void 0 : _this$toolParams5.description) || ((_this$toolParams6 = this.toolParams) === null || _this$toolParams6 === void 0 ? void 0 : _this$toolParams6.body);
38
39
  },
39
40
  sourceBranch() {
40
- var _this$toolParams6;
41
- return (_this$toolParams6 = this.toolParams) === null || _this$toolParams6 === void 0 ? void 0 : _this$toolParams6.sourceBranch;
41
+ var _this$toolParams7;
42
+ return (_this$toolParams7 = this.toolParams) === null || _this$toolParams7 === void 0 ? void 0 : _this$toolParams7.sourceBranch;
42
43
  },
43
44
  targetBranch() {
44
- var _this$toolParams7;
45
- return (_this$toolParams7 = this.toolParams) === null || _this$toolParams7 === void 0 ? void 0 : _this$toolParams7.targetBranch;
45
+ var _this$toolParams8;
46
+ return (_this$toolParams8 = this.toolParams) === null || _this$toolParams8 === void 0 ? void 0 : _this$toolParams8.targetBranch;
47
+ },
48
+ confidential() {
49
+ var _this$toolParams9;
50
+ return (_this$toolParams9 = this.toolParams) === null || _this$toolParams9 === void 0 ? void 0 : _this$toolParams9.confidential;
51
+ },
52
+ workItemParentType() {
53
+ var _this$toolParams0, _this$toolParams1;
54
+ if ((_this$toolParams0 = this.toolParams) !== null && _this$toolParams0 !== void 0 && _this$toolParams0.projectId) {
55
+ return 'project';
56
+ }
57
+ if ((_this$toolParams1 = this.toolParams) !== null && _this$toolParams1 !== void 0 && _this$toolParams1.groupId) {
58
+ return 'group';
59
+ }
60
+ return 'resource';
61
+ },
62
+ workItemParentId() {
63
+ var _this$toolParams10, _this$toolParams11, _this$toolParams12;
64
+ return ((_this$toolParams10 = this.toolParams) === null || _this$toolParams10 === void 0 ? void 0 : _this$toolParams10.url) || ((_this$toolParams11 = this.toolParams) === null || _this$toolParams11 === void 0 ? void 0 : _this$toolParams11.groupId) || ((_this$toolParams12 = this.toolParams) === null || _this$toolParams12 === void 0 ? void 0 : _this$toolParams12.projectId);
65
+ },
66
+ noteParentIid() {
67
+ var _this$toolParams13, _this$toolParams14, _this$toolParams15;
68
+ return ((_this$toolParams13 = this.toolParams) === null || _this$toolParams13 === void 0 ? void 0 : _this$toolParams13.issueIid) || ((_this$toolParams14 = this.toolParams) === null || _this$toolParams14 === void 0 ? void 0 : _this$toolParams14.mergeRequestIid) || ((_this$toolParams15 = this.toolParams) === null || _this$toolParams15 === void 0 ? void 0 : _this$toolParams15.workItemIid);
69
+ },
70
+ noteParentLabel() {
71
+ switch (this.toolName) {
72
+ case APPROVAL_TOOL_NAMES.createMergeRequestNote:
73
+ return this.$options.i18n.MERGE_REQUEST_LABEL;
74
+ case APPROVAL_TOOL_NAMES.createWorkItemNote:
75
+ return this.$options.i18n.WORK_ITEM_LABEL;
76
+ case APPROVAL_TOOL_NAMES.createIssueNote:
77
+ return this.$options.i18n.ISSUE_LABEL;
78
+ default:
79
+ return '';
80
+ }
81
+ },
82
+ isNote() {
83
+ return [APPROVAL_TOOL_NAMES.createMergeRequestNote, APPROVAL_TOOL_NAMES.createWorkItemNote, APPROVAL_TOOL_NAMES.createIssueNote].includes(this.toolName);
46
84
  },
47
85
  message() {
48
86
  let message = this.$options.i18n[this.toolName] || '';
49
87
  const labelsMessage = this.$options.i18n.ASSIGN_LABELS_MESSAGE;
50
88
  const branchMessage = this.$options.i18n.BRANCH_MESSAGE;
89
+ const confidentialMessage = this.$options.i18n.CONFIDENTIAL_MESSAGE;
51
90
  if (this.title) {
52
91
  message = `${message} ${this.$options.i18n.TITLE_MESSAGE}`;
53
92
  }
@@ -57,10 +96,20 @@ var script = {
57
96
  if (this.labels) {
58
97
  message = `${message} ${labelsMessage}`;
59
98
  }
99
+ if (this.confidential) {
100
+ message = `${message} ${confidentialMessage}`;
101
+ }
60
102
  return sprintf(message, {
61
103
  project: this.project,
104
+ workItemParentType: this.workItemParentType,
105
+ workItemParentId: this.workItemParentId,
106
+ noteParentLabel: this.noteParentLabel,
107
+ noteParentIid: this.noteParentIid,
62
108
  ...this.toolParams
63
109
  });
110
+ },
111
+ accordionTitle() {
112
+ return this.isNote ? this.$options.i18n.NOTE_ACCORDION_TITLE : '';
64
113
  }
65
114
  },
66
115
  i18n: {
@@ -68,12 +117,21 @@ var script = {
68
117
  [APPROVAL_TOOL_NAMES.updateIssue]: translate('IssuableToolParams.UPDATE_ISSUE', 'Update issue <code>%{issueIid}</code> in project <code>%{project}</code>.'),
69
118
  [APPROVAL_TOOL_NAMES.createEpic]: translate('IssuableToolParams.CREATE_EPIC', 'Create an epic in group <code>%{groupId}</code>.'),
70
119
  [APPROVAL_TOOL_NAMES.updateEpic]: translate('IssuableToolParams.UPDATE_EPIC', 'Update epic <code>%{epicId}</code> in group <code>%{groupId}</code>.'),
120
+ [APPROVAL_TOOL_NAMES.createWorkItem]: translate('IssuableToolParams.CREATE_WORK_ITEM', 'Create a work item with type <em>"%{typeName}"</em> in %{workItemParentType} <code>%{workItemParentId}</code>.'),
121
+ [APPROVAL_TOOL_NAMES.updateWorkItem]: translate('IssuableToolParams.UPDATE_WORK_ITEM', 'Update work item <code>%{workItemIid}</code> in %{workItemParentType} <code>%{workItemParentId}</code>.'),
71
122
  [APPROVAL_TOOL_NAMES.createMergeRequest]: translate('IssuableToolParams.CREATE_MERGE_REQUEST', 'Open a merge request in project <code>%{project}</code>.'),
72
123
  [APPROVAL_TOOL_NAMES.updateMergeRequest]: translate('IssuableToolParams.UPDATE_MERGE_REQUEST', 'Update merge request <code>%{mergeRequestIid}</code> in project <code>%{project}</code>.'),
124
+ [APPROVAL_TOOL_NAMES.createMergeRequestNote]: NOTE_MESSAGE,
125
+ [APPROVAL_TOOL_NAMES.createWorkItemNote]: NOTE_MESSAGE,
126
+ [APPROVAL_TOOL_NAMES.createIssueNote]: NOTE_MESSAGE,
73
127
  TITLE_MESSAGE: translate('IssuableToolParams.TITLE_MESSAGE', 'Set the title "<em>%{title}</em>".'),
74
128
  BRANCH_MESSAGE: translate('IssuableToolParams.BRANCH_MESSAGE', 'From branch <code>%{sourceBranch}</code> to branch <code>%{targetBranch}</code>.'),
75
- ASSIGN_LABELS_MESSAGE: translate('CreateIssueToolParams.ASSIGN_LABELS_MESSAGE', 'Assign the labels <code>%{labels}</code>.'),
76
- ACCORDION_TITLE: translate('CreateIssueToolParams.ACCORDION_TITLE', 'Read description')
129
+ ASSIGN_LABELS_MESSAGE: translate('IssuableToolParams.ASSIGN_LABELS_MESSAGE', 'Assign the labels <code>%{labels}</code>.'),
130
+ CONFIDENTIAL_MESSAGE: translate('IssuableToolParams.CONFIDENTIAL_MESSAGE', 'Set as confidential.'),
131
+ MERGE_REQUEST_LABEL: translate('IssuableToolParams.MERGE_REQUEST_LABEL', 'merge request'),
132
+ ISSUE_LABEL: translate('IssuableToolParams.ISSUE_LABEL', 'issue'),
133
+ WORK_ITEM_LABEL: translate('IssuableToolParams.WORK_ITEM_LABEL', 'work item'),
134
+ NOTE_ACCORDION_TITLE: translate('IssuableToolParams.NOTE_ACCORDION_TITLE', "Read note's content")
77
135
  }
78
136
  };
79
137
 
@@ -81,7 +139,7 @@ var script = {
81
139
  const __vue_script__ = script;
82
140
 
83
141
  /* template */
84
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('base-tool-params',{attrs:{"message":_vm.message,"description":_vm.description}})};
142
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('base-tool-params',{attrs:{"message":_vm.message,"description":_vm.description,"custom-accordion-title":_vm.accordionTitle}})};
85
143
  var __vue_staticRenderFns__ = [];
86
144
 
87
145
  /* style */
@@ -3,7 +3,7 @@ import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
3
3
  /* script */
4
4
 
5
5
  /* template */
6
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('pre',{staticClass:"gl-border gl-grid gl-text-pretty gl-rounded-lg gl-border-strong gl-bg-strong gl-p-5 gl-font-monospace"},[_c('code',[_vm._t("default")],2)])};
6
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('pre',{staticClass:"js-syntax-highlight gl-border gl-grid gl-text-pretty gl-rounded-lg gl-border-strong gl-bg-strong gl-p-5 gl-font-monospace"},[_c('code',[_vm._t("default")],2)])};
7
7
  var __vue_staticRenderFns__ = [];
8
8
 
9
9
  /* style */
@@ -38,7 +38,12 @@ const i18n = {
38
38
  [APPROVAL_TOOL_NAMES.updateIssue]: translate('MessageToolApproval.updateIssue', 'Duo wants to update an issue.'),
39
39
  [APPROVAL_TOOL_NAMES.createEpic]: translate('MessageToolApproval.createEpic', 'Duo wants to create an epic.'),
40
40
  [APPROVAL_TOOL_NAMES.updateEpic]: translate('MessageToolApproval.updateEpic', 'Duo wants to update an epic.'),
41
+ [APPROVAL_TOOL_NAMES.createWorkItem]: translate('MessageToolApproval.createWorkItem', 'Duo wants to create a work item.'),
42
+ [APPROVAL_TOOL_NAMES.updateWorkItem]: translate('MessageToolApproval.updateWorkItem', 'Duo wants to update a work item.'),
41
43
  [APPROVAL_TOOL_NAMES.createMergeRequest]: translate('MessageToolApproval.createMergeRequest', 'Duo wants to create a merge request.'),
44
+ [APPROVAL_TOOL_NAMES.createIssueNote]: translate('MessageToolApproval.createIssueNote', 'Duo wants to post a note on an issue.'),
45
+ [APPROVAL_TOOL_NAMES.createMergeRequestNote]: translate('MessageToolApproval.createMergeRequestNote', 'Duo wants to post a note on a merge request.'),
46
+ [APPROVAL_TOOL_NAMES.createWorkItemNote]: translate('MessageToolApproval.createWorkItemNote', 'Duo wants to post a note on a work item.'),
42
47
  [APPROVAL_TOOL_NAMES.runCommand]: translate('MessageToolApproval.runCommand', 'Duo wants to run a command.'),
43
48
  [APPROVAL_TOOL_NAMES.runGitCommand]: translate('MessageToolApproval.runGitCommand', 'Duo wants to run a git command.')
44
49
  },
@@ -55,6 +60,11 @@ const TOOL_PARAMS_VIEW_COMPONENTS = {
55
60
  [APPROVAL_TOOL_NAMES.updateEpic]: 'IssuableToolParams',
56
61
  [APPROVAL_TOOL_NAMES.createMergeRequest]: 'IssuableToolParams',
57
62
  [APPROVAL_TOOL_NAMES.updateMergeRequest]: 'IssuableToolParams',
63
+ [APPROVAL_TOOL_NAMES.createWorkItem]: 'IssuableToolParams',
64
+ [APPROVAL_TOOL_NAMES.updateWorkItem]: 'IssuableToolParams',
65
+ [APPROVAL_TOOL_NAMES.createMergeRequestNote]: 'IssuableToolParams',
66
+ [APPROVAL_TOOL_NAMES.createWorkItemNote]: 'IssuableToolParams',
67
+ [APPROVAL_TOOL_NAMES.createIssueNote]: 'IssuableToolParams',
58
68
  [APPROVAL_TOOL_NAMES.runCommand]: 'RunCommandToolParams',
59
69
  [APPROVAL_TOOL_NAMES.runGitCommand]: 'RunCommandToolParams'
60
70
  };
@@ -48,8 +48,13 @@ const APPROVAL_TOOL_NAMES = {
48
48
  updateIssue: 'update_issue',
49
49
  createEpic: 'create_epic',
50
50
  updateEpic: 'update_epic',
51
+ createWorkItem: 'create_work_item',
52
+ updateWorkItem: 'update_work_item',
51
53
  createMergeRequest: 'create_merge_request',
52
54
  updateMergeRequest: 'update_merge_request',
55
+ createMergeRequestNote: 'create_merge_request_note',
56
+ createWorkItemNote: 'create_work_item_note',
57
+ createIssueNote: 'create_issue_note',
53
58
  runCommand: 'run_command',
54
59
  runGitCommand: 'run_git_command'
55
60
  };
@@ -344,6 +344,91 @@ const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_COMMIT_AUTO_BRANCH = {
344
344
  status: 'success',
345
345
  role: 'request'
346
346
  };
347
+ const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_WORK_ITEM = {
348
+ id: '127',
349
+ content: 'Tool create_work_item requires approval. Please confirm if you want to proceed.',
350
+ message_type: MESSAGE_MODEL_ROLES.request,
351
+ tool_info: {
352
+ name: 'create_work_item',
353
+ args: {
354
+ project_id: 'gitlab-org/duo-ui',
355
+ title: 'Implement dark mode toggle for chat interface',
356
+ type_name: 'Issue',
357
+ description: '## Overview\n\nUsers have requested the ability to toggle between light and dark modes in the chat interface to improve usability in different lighting conditions.\n\n## Requirements\n\n- [ ] Add a toggle button in the chat header\n- [ ] Implement theme switching logic\n- [ ] Persist user preference in localStorage\n- [ ] Ensure all chat components support both themes\n- [ ] Update existing CSS variables for dark mode\n\n## Acceptance Criteria\n\n- Toggle button is visible and accessible\n- Theme changes are applied immediately\n- User preference is remembered across sessions\n- All text remains readable in both modes\n- Icons and UI elements adapt to the selected theme',
358
+ labels: ['enhancement', 'ui', 'accessibility'],
359
+ assignee_ids: [123]
360
+ }
361
+ },
362
+ timestamp: '2025-06-25T19:22:21.290791+00:00',
363
+ status: 'success',
364
+ role: 'request'
365
+ };
366
+ const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_UPDATE_WORK_ITEM = {
367
+ id: '128',
368
+ content: 'Tool update_work_item requires approval. Please confirm if you want to proceed.',
369
+ message_type: MESSAGE_MODEL_ROLES.request,
370
+ tool_info: {
371
+ name: 'update_work_item',
372
+ args: {
373
+ group_id: 'gitlab-org',
374
+ work_item_iid: 42,
375
+ title: 'Implement dark mode toggle for chat interface - Updated',
376
+ state: 'opened',
377
+ add_label_ids: ['bug', 'priority::high']
378
+ }
379
+ },
380
+ timestamp: '2025-06-25T19:22:21.290791+00:00',
381
+ status: 'success',
382
+ role: 'request'
383
+ };
384
+ const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_MERGE_REQUEST_NOTE = {
385
+ id: '129',
386
+ content: 'Tool create_merge_request_note requires approval. Please confirm if you want to proceed.',
387
+ message_type: MESSAGE_MODEL_ROLES.request,
388
+ tool_info: {
389
+ name: 'create_merge_request_note',
390
+ args: {
391
+ project_id: 'gitlab-org/duo-ui',
392
+ merge_request_iid: 156,
393
+ body: "Great work on implementing the dark mode feature! šŸŽ‰\n\nI've reviewed the changes and they look solid. A few observations:\n\n- The CSS variables approach is clean and maintainable\n- The localStorage persistence works perfectly\n- All components adapt well to both themes\n\nThis will definitely improve the user experience. Ready to merge once the pipeline passes!"
394
+ }
395
+ },
396
+ timestamp: '2025-06-25T19:22:21.290791+00:00',
397
+ status: 'success',
398
+ role: 'request'
399
+ };
400
+ const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_WORK_ITEM_NOTE = {
401
+ id: '130',
402
+ content: 'Tool create_work_item_note requires approval. Please confirm if you want to proceed.',
403
+ message_type: MESSAGE_MODEL_ROLES.request,
404
+ tool_info: {
405
+ name: 'create_work_item_note',
406
+ args: {
407
+ project_id: 'gitlab-org/duo-ui',
408
+ work_item_iid: 42,
409
+ body: "I've started working on this work item and made good progress on the initial implementation.\n\n## Progress Update\n\nāœ… **Completed:**\n- Added toggle button component\n- Implemented basic theme switching logic\n- Created CSS variables for dark mode\n\nšŸ”„ **In Progress:**\n- Testing theme persistence across sessions\n- Ensuring all components support both themes\n\nšŸ“‹ **Next Steps:**\n- Update remaining UI components\n- Add accessibility improvements\n- Write comprehensive tests\n\nExpected completion by end of week. Will update with any blockers."
410
+ }
411
+ },
412
+ timestamp: '2025-06-25T19:22:21.290791+00:00',
413
+ status: 'success',
414
+ role: 'request'
415
+ };
416
+ const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_ISSUE_NOTE = {
417
+ id: '131',
418
+ content: 'Tool create_issue_note requires approval. Please confirm if you want to proceed.',
419
+ message_type: MESSAGE_MODEL_ROLES.request,
420
+ tool_info: {
421
+ name: 'create_issue_note',
422
+ args: {
423
+ project_id: 'gitlab-org/duo-ui',
424
+ issue_iid: 89,
425
+ body: "Thanks for reporting this issue! šŸ‘\n\nI can reproduce the problem on my local environment. It seems like the CSP headers are indeed blocking the external web views.\n\n## Investigation Results\n\nAfter analyzing the VSCode Fork implementation, I found that:\n\n1. The CSP directive `frame-src` is too restrictive\n2. We need to allowlist specific domains for external web views\n3. The current policy blocks all external iframe content\n\n## Proposed Solution\n\nI'll create a merge request to:\n- Update the CSP configuration\n- Add necessary domain allowlisting\n- Ensure security is maintained while fixing the functionality\n\nAssigning this to myself and will have a fix ready soon."
426
+ }
427
+ },
428
+ timestamp: '2025-06-25T19:22:21.290791+00:00',
429
+ status: 'success',
430
+ role: 'request'
431
+ };
347
432
  const MOCK_WORKFLOW_END_MESSAGE = {
348
433
  id: '123',
349
434
  content: "Search for 'duo.*chat.*message' in directory",
@@ -656,4 +741,4 @@ const AGENTIC_THREADLIST = [{
656
741
  }
657
742
  }];
658
743
 
659
- export { AGENTIC_THREADLIST, INCLUDE_SLASH_COMMAND, MOCK_AGENT_MESSAGE, MOCK_REQUEST_MESSAGE, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_COMMIT, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_COMMIT_AUTO_BRANCH, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_COMMIT_OLD_NEW_CONTENT, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_EPIC, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_ISSUE, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_MERGE_REQUEST, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_PARAMS, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_RUN_COMMAND, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_RUN_COMMAND_WITH_RESPONSE, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_RUN_GIT_COMMAND, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_UPDATE_ISSUE, MOCK_RESPONSE_MESSAGE, MOCK_RESPONSE_MESSAGE_FOR_STREAMING, MOCK_TOOL_MESSAGE, MOCK_TOOL_MESSAGE_WITH_LINK, MOCK_USER_PROMPT_MESSAGE, MOCK_WORKFLOW_END_MESSAGE, SLASH_COMMANDS, THREADLIST, generateMockResponseChunks, generateSeparateChunks, renderGFM, renderMarkdown };
744
+ export { AGENTIC_THREADLIST, INCLUDE_SLASH_COMMAND, MOCK_AGENT_MESSAGE, MOCK_REQUEST_MESSAGE, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_COMMIT, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_COMMIT_AUTO_BRANCH, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_COMMIT_OLD_NEW_CONTENT, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_EPIC, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_ISSUE, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_ISSUE_NOTE, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_MERGE_REQUEST, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_MERGE_REQUEST_NOTE, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_WORK_ITEM, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_WORK_ITEM_NOTE, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_PARAMS, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_RUN_COMMAND, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_RUN_COMMAND_WITH_RESPONSE, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_RUN_GIT_COMMAND, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_UPDATE_ISSUE, MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_UPDATE_WORK_ITEM, MOCK_RESPONSE_MESSAGE, MOCK_RESPONSE_MESSAGE_FOR_STREAMING, MOCK_TOOL_MESSAGE, MOCK_TOOL_MESSAGE_WITH_LINK, MOCK_USER_PROMPT_MESSAGE, MOCK_WORKFLOW_END_MESSAGE, SLASH_COMMANDS, THREADLIST, generateMockResponseChunks, generateSeparateChunks, renderGFM, renderMarkdown };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/duo-ui",
3
- "version": "13.2.0",
3
+ "version": "13.4.0",
4
4
  "description": "Duo UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -11,6 +11,7 @@ import {
11
11
  } from '@gitlab/ui';
12
12
  import { sprintf, translate } from '../../../../utils/i18n';
13
13
  import { VIEW_TYPES } from './constants';
14
+ import DuoChatHeaderAgentItem from './duo_chat_header_agent_item/duo_chat_header_agent_item.vue';
14
15
 
15
16
  export const i18n = {
16
17
  CHAT_BACK_LABEL: translate('DuoChat.chatBackLabel', 'Back to history'),
@@ -42,6 +43,7 @@ export default {
42
43
  GlButton,
43
44
  GlExperimentBadge,
44
45
  GlDisclosureDropdown,
46
+ DuoChatHeaderAgentItem,
45
47
  },
46
48
  directives: {
47
49
  SafeHtml,
@@ -198,12 +200,7 @@ export default {
198
200
  @action="startNewChat"
199
201
  >
200
202
  <template #list-item="{ item }">
201
- <span class="gl-flex gl-flex-col">
202
- <span clas="gl-block">{{ item.name }}</span>
203
- <span class="gl-overflow-hidden gl-text-ellipsis gl-whitespace-nowrap gl-text-sm">{{
204
- item.description
205
- }}</span>
206
- </span>
203
+ <duo-chat-header-agent-item :agent="item" />
207
204
  </template>
208
205
  </gl-disclosure-dropdown>
209
206
  <gl-button
@@ -0,0 +1,43 @@
1
+ <script>
2
+ import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
3
+ import { translate } from '@gitlab/ui/dist/utils/i18n';
4
+
5
+ export const i18n = {
6
+ CHAT_VERIFIED_AGENT: translate('DuoChat.verifiedAgent', 'Created and maintained by GitLab'),
7
+ };
8
+
9
+ export default {
10
+ name: 'ChatAgentItem',
11
+ components: {
12
+ GlIcon,
13
+ },
14
+ directives: {
15
+ GlTooltip: GlTooltipDirective,
16
+ },
17
+ props: {
18
+ agent: {
19
+ type: Object,
20
+ required: true,
21
+ },
22
+ },
23
+ i18n,
24
+ };
25
+ </script>
26
+
27
+ <template>
28
+ <span class="gl-flex gl-flex-col">
29
+ <span class="gl-mb-1 gl-inline-block gl-text-lg gl-font-bold gl-text-strong">
30
+ {{ agent.name }}
31
+ <gl-icon
32
+ v-if="agent.foundational"
33
+ v-gl-tooltip
34
+ name="tanuki-verified"
35
+ variant="subtle"
36
+ :title="$options.i18n.CHAT_VERIFIED_AGENT"
37
+ />
38
+ </span>
39
+ <span class="gl-overflow-hidden gl-text-ellipsis gl-whitespace-nowrap gl-text-sm">
40
+ {{ agent.description }}
41
+ </span>
42
+ </span>
43
+ </template>
@@ -0,0 +1 @@
1
+ A component that handles the header of the chat, including agent selection
@@ -10,6 +10,7 @@ import {
10
10
  GlDisclosureDropdown,
11
11
  } from '@gitlab/ui';
12
12
  import { sprintf, translate } from '../../../../utils/i18n';
13
+ import DuoChatHeaderAgentItem from './duo_chat_header_agent_item/duo_chat_header_agent_item.vue';
13
14
  import { VIEW_TYPES } from './constants';
14
15
 
15
16
  export const i18n = {
@@ -42,6 +43,7 @@ export default {
42
43
  GlAvatar,
43
44
  GlButton,
44
45
  GlDisclosureDropdown,
46
+ DuoChatHeaderAgentItem,
45
47
  },
46
48
  directives: {
47
49
  SafeHtml,
@@ -222,12 +224,7 @@ export default {
222
224
  @action="startNewChat"
223
225
  >
224
226
  <template #list-item="{ item }">
225
- <span class="gl-flex gl-flex-col">
226
- <span class="gl-block">{{ item.name }}</span>
227
- <span class="gl-overflow-hidden gl-text-ellipsis gl-whitespace-nowrap gl-text-sm">{{
228
- item.description
229
- }}</span>
230
- </span>
227
+ <duo-chat-header-agent-item :agent="item" />
231
228
  </template>
232
229
  </gl-disclosure-dropdown>
233
230
  <gl-button
@@ -115,17 +115,7 @@ export default {
115
115
  return this.isDetailsOpen ? 'chevron-down' : 'chevron-right';
116
116
  },
117
117
  requiresApproval() {
118
- return [
119
- APPROVAL_TOOL_NAMES.runCommand,
120
- APPROVAL_TOOL_NAMES.runGitCommand,
121
- APPROVAL_TOOL_NAMES.createIssue,
122
- APPROVAL_TOOL_NAMES.updateIssue,
123
- APPROVAL_TOOL_NAMES.createMergeRequest,
124
- APPROVAL_TOOL_NAMES.updateMergeRequest,
125
- APPROVAL_TOOL_NAMES.createEpic,
126
- APPROVAL_TOOL_NAMES.updateEpic,
127
- APPROVAL_TOOL_NAMES.createCommit,
128
- ].includes(this.toolName);
118
+ return Object.values(APPROVAL_TOOL_NAMES).includes(this.toolName);
129
119
  },
130
120
  shouldShowDetails() {
131
121
  return (
@@ -3,6 +3,11 @@ import { sprintf, translate } from '../../../../../utils/i18n';
3
3
  import { APPROVAL_TOOL_NAMES } from '../../../constants';
4
4
  import BaseToolParams from './base_tool_params.vue';
5
5
 
6
+ const NOTE_MESSAGE = translate(
7
+ 'IssuableToolParams.NOTE_MESSAGE',
8
+ 'Post a note on %{noteParentLabel} <code>%{noteParentIid}</code> that belongs to %{workItemParentType} <code>%{workItemParentId}</code>.'
9
+ );
10
+
6
11
  export default {
7
12
  name: 'IssuableToolParams',
8
13
  components: {
@@ -12,15 +17,7 @@ export default {
12
17
  toolName: {
13
18
  type: String,
14
19
  required: true,
15
- validator: (toolName) =>
16
- [
17
- APPROVAL_TOOL_NAMES.createIssue,
18
- APPROVAL_TOOL_NAMES.updateIssue,
19
- APPROVAL_TOOL_NAMES.createEpic,
20
- APPROVAL_TOOL_NAMES.updateEpic,
21
- APPROVAL_TOOL_NAMES.createMergeRequest,
22
- APPROVAL_TOOL_NAMES.updateMergeRequest,
23
- ].includes(toolName),
20
+ validator: (toolName) => Object.values(APPROVAL_TOOL_NAMES).includes(toolName),
24
21
  },
25
22
  toolParams: {
26
23
  type: Object,
@@ -38,7 +35,7 @@ export default {
38
35
  return this.toolParams?.labels;
39
36
  },
40
37
  description() {
41
- return this.toolParams?.description;
38
+ return this.toolParams?.description || this.toolParams?.body;
42
39
  },
43
40
  sourceBranch() {
44
41
  return this.toolParams?.sourceBranch;
@@ -46,10 +43,54 @@ export default {
46
43
  targetBranch() {
47
44
  return this.toolParams?.targetBranch;
48
45
  },
46
+ confidential() {
47
+ return this.toolParams?.confidential;
48
+ },
49
+ workItemParentType() {
50
+ if (this.toolParams?.projectId) {
51
+ return 'project';
52
+ }
53
+
54
+ if (this.toolParams?.groupId) {
55
+ return 'group';
56
+ }
57
+
58
+ return 'resource';
59
+ },
60
+ workItemParentId() {
61
+ return this.toolParams?.url || this.toolParams?.groupId || this.toolParams?.projectId;
62
+ },
63
+ noteParentIid() {
64
+ return (
65
+ this.toolParams?.issueIid ||
66
+ this.toolParams?.mergeRequestIid ||
67
+ this.toolParams?.workItemIid
68
+ );
69
+ },
70
+ noteParentLabel() {
71
+ switch (this.toolName) {
72
+ case APPROVAL_TOOL_NAMES.createMergeRequestNote:
73
+ return this.$options.i18n.MERGE_REQUEST_LABEL;
74
+ case APPROVAL_TOOL_NAMES.createWorkItemNote:
75
+ return this.$options.i18n.WORK_ITEM_LABEL;
76
+ case APPROVAL_TOOL_NAMES.createIssueNote:
77
+ return this.$options.i18n.ISSUE_LABEL;
78
+ default:
79
+ return '';
80
+ }
81
+ },
82
+ isNote() {
83
+ return [
84
+ APPROVAL_TOOL_NAMES.createMergeRequestNote,
85
+ APPROVAL_TOOL_NAMES.createWorkItemNote,
86
+ APPROVAL_TOOL_NAMES.createIssueNote,
87
+ ].includes(this.toolName);
88
+ },
49
89
  message() {
50
90
  let message = this.$options.i18n[this.toolName] || '';
51
91
  const labelsMessage = this.$options.i18n.ASSIGN_LABELS_MESSAGE;
52
92
  const branchMessage = this.$options.i18n.BRANCH_MESSAGE;
93
+ const confidentialMessage = this.$options.i18n.CONFIDENTIAL_MESSAGE;
53
94
 
54
95
  if (this.title) {
55
96
  message = `${message} ${this.$options.i18n.TITLE_MESSAGE}`;
@@ -63,7 +104,21 @@ export default {
63
104
  message = `${message} ${labelsMessage}`;
64
105
  }
65
106
 
66
- return sprintf(message, { project: this.project, ...this.toolParams });
107
+ if (this.confidential) {
108
+ message = `${message} ${confidentialMessage}`;
109
+ }
110
+
111
+ return sprintf(message, {
112
+ project: this.project,
113
+ workItemParentType: this.workItemParentType,
114
+ workItemParentId: this.workItemParentId,
115
+ noteParentLabel: this.noteParentLabel,
116
+ noteParentIid: this.noteParentIid,
117
+ ...this.toolParams,
118
+ });
119
+ },
120
+ accordionTitle() {
121
+ return this.isNote ? this.$options.i18n.NOTE_ACCORDION_TITLE : '';
67
122
  },
68
123
  },
69
124
  i18n: {
@@ -83,6 +138,14 @@ export default {
83
138
  'IssuableToolParams.UPDATE_EPIC',
84
139
  'Update epic <code>%{epicId}</code> in group <code>%{groupId}</code>.'
85
140
  ),
141
+ [APPROVAL_TOOL_NAMES.createWorkItem]: translate(
142
+ 'IssuableToolParams.CREATE_WORK_ITEM',
143
+ 'Create a work item with type <em>"%{typeName}"</em> in %{workItemParentType} <code>%{workItemParentId}</code>.'
144
+ ),
145
+ [APPROVAL_TOOL_NAMES.updateWorkItem]: translate(
146
+ 'IssuableToolParams.UPDATE_WORK_ITEM',
147
+ 'Update work item <code>%{workItemIid}</code> in %{workItemParentType} <code>%{workItemParentId}</code>.'
148
+ ),
86
149
  [APPROVAL_TOOL_NAMES.createMergeRequest]: translate(
87
150
  'IssuableToolParams.CREATE_MERGE_REQUEST',
88
151
  'Open a merge request in project <code>%{project}</code>.'
@@ -91,6 +154,9 @@ export default {
91
154
  'IssuableToolParams.UPDATE_MERGE_REQUEST',
92
155
  'Update merge request <code>%{mergeRequestIid}</code> in project <code>%{project}</code>.'
93
156
  ),
157
+ [APPROVAL_TOOL_NAMES.createMergeRequestNote]: NOTE_MESSAGE,
158
+ [APPROVAL_TOOL_NAMES.createWorkItemNote]: NOTE_MESSAGE,
159
+ [APPROVAL_TOOL_NAMES.createIssueNote]: NOTE_MESSAGE,
94
160
  TITLE_MESSAGE: translate(
95
161
  'IssuableToolParams.TITLE_MESSAGE',
96
162
  'Set the title "<em>%{title}</em>".'
@@ -100,13 +166,27 @@ export default {
100
166
  'From branch <code>%{sourceBranch}</code> to branch <code>%{targetBranch}</code>.'
101
167
  ),
102
168
  ASSIGN_LABELS_MESSAGE: translate(
103
- 'CreateIssueToolParams.ASSIGN_LABELS_MESSAGE',
169
+ 'IssuableToolParams.ASSIGN_LABELS_MESSAGE',
104
170
  'Assign the labels <code>%{labels}</code>.'
105
171
  ),
106
- ACCORDION_TITLE: translate('CreateIssueToolParams.ACCORDION_TITLE', 'Read description'),
172
+ CONFIDENTIAL_MESSAGE: translate(
173
+ 'IssuableToolParams.CONFIDENTIAL_MESSAGE',
174
+ 'Set as confidential.'
175
+ ),
176
+ MERGE_REQUEST_LABEL: translate('IssuableToolParams.MERGE_REQUEST_LABEL', 'merge request'),
177
+ ISSUE_LABEL: translate('IssuableToolParams.ISSUE_LABEL', 'issue'),
178
+ WORK_ITEM_LABEL: translate('IssuableToolParams.WORK_ITEM_LABEL', 'work item'),
179
+ NOTE_ACCORDION_TITLE: translate(
180
+ 'IssuableToolParams.NOTE_ACCORDION_TITLE',
181
+ "Read note's content"
182
+ ),
107
183
  },
108
184
  };
109
185
  </script>
110
186
  <template>
111
- <base-tool-params :message="message" :description="description" />
187
+ <base-tool-params
188
+ :message="message"
189
+ :description="description"
190
+ :custom-accordion-title="accordionTitle"
191
+ />
112
192
  </template>
@@ -1,5 +1,5 @@
1
1
  <template>
2
2
  <pre
3
- class="gl-border gl-grid gl-text-pretty gl-rounded-lg gl-border-strong gl-bg-strong gl-p-5 gl-font-monospace"
3
+ class="js-syntax-highlight gl-border gl-grid gl-text-pretty gl-rounded-lg gl-border-strong gl-bg-strong gl-p-5 gl-font-monospace"
4
4
  ><code><slot></slot></code></pre>
5
5
  </template>
@@ -72,10 +72,30 @@ export const i18n = {
72
72
  'MessageToolApproval.updateEpic',
73
73
  'Duo wants to update an epic.'
74
74
  ),
75
+ [APPROVAL_TOOL_NAMES.createWorkItem]: translate(
76
+ 'MessageToolApproval.createWorkItem',
77
+ 'Duo wants to create a work item.'
78
+ ),
79
+ [APPROVAL_TOOL_NAMES.updateWorkItem]: translate(
80
+ 'MessageToolApproval.updateWorkItem',
81
+ 'Duo wants to update a work item.'
82
+ ),
75
83
  [APPROVAL_TOOL_NAMES.createMergeRequest]: translate(
76
84
  'MessageToolApproval.createMergeRequest',
77
85
  'Duo wants to create a merge request.'
78
86
  ),
87
+ [APPROVAL_TOOL_NAMES.createIssueNote]: translate(
88
+ 'MessageToolApproval.createIssueNote',
89
+ 'Duo wants to post a note on an issue.'
90
+ ),
91
+ [APPROVAL_TOOL_NAMES.createMergeRequestNote]: translate(
92
+ 'MessageToolApproval.createMergeRequestNote',
93
+ 'Duo wants to post a note on a merge request.'
94
+ ),
95
+ [APPROVAL_TOOL_NAMES.createWorkItemNote]: translate(
96
+ 'MessageToolApproval.createWorkItemNote',
97
+ 'Duo wants to post a note on a work item.'
98
+ ),
79
99
  [APPROVAL_TOOL_NAMES.runCommand]: translate(
80
100
  'MessageToolApproval.runCommand',
81
101
  'Duo wants to run a command.'
@@ -105,6 +125,11 @@ const TOOL_PARAMS_VIEW_COMPONENTS = {
105
125
  [APPROVAL_TOOL_NAMES.updateEpic]: 'IssuableToolParams',
106
126
  [APPROVAL_TOOL_NAMES.createMergeRequest]: 'IssuableToolParams',
107
127
  [APPROVAL_TOOL_NAMES.updateMergeRequest]: 'IssuableToolParams',
128
+ [APPROVAL_TOOL_NAMES.createWorkItem]: 'IssuableToolParams',
129
+ [APPROVAL_TOOL_NAMES.updateWorkItem]: 'IssuableToolParams',
130
+ [APPROVAL_TOOL_NAMES.createMergeRequestNote]: 'IssuableToolParams',
131
+ [APPROVAL_TOOL_NAMES.createWorkItemNote]: 'IssuableToolParams',
132
+ [APPROVAL_TOOL_NAMES.createIssueNote]: 'IssuableToolParams',
108
133
  [APPROVAL_TOOL_NAMES.runCommand]: 'RunCommandToolParams',
109
134
  [APPROVAL_TOOL_NAMES.runGitCommand]: 'RunCommandToolParams',
110
135
  };
@@ -56,8 +56,13 @@ export const APPROVAL_TOOL_NAMES = {
56
56
  updateIssue: 'update_issue',
57
57
  createEpic: 'create_epic',
58
58
  updateEpic: 'update_epic',
59
+ createWorkItem: 'create_work_item',
60
+ updateWorkItem: 'update_work_item',
59
61
  createMergeRequest: 'create_merge_request',
60
62
  updateMergeRequest: 'update_merge_request',
63
+ createMergeRequestNote: 'create_merge_request_note',
64
+ createWorkItemNote: 'create_work_item_note',
65
+ createIssueNote: 'create_issue_note',
61
66
  runCommand: 'run_command',
62
67
  runGitCommand: 'run_git_command',
63
68
  };
@@ -391,6 +391,98 @@ export const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_COMMIT_AUTO_BRANCH =
391
391
  role: 'request',
392
392
  };
393
393
 
394
+ export const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_WORK_ITEM = {
395
+ id: '127',
396
+ content: 'Tool create_work_item requires approval. Please confirm if you want to proceed.',
397
+ message_type: MESSAGE_MODEL_ROLES.request,
398
+ tool_info: {
399
+ name: 'create_work_item',
400
+ args: {
401
+ project_id: 'gitlab-org/duo-ui',
402
+ title: 'Implement dark mode toggle for chat interface',
403
+ type_name: 'Issue',
404
+ description:
405
+ '## Overview\n\nUsers have requested the ability to toggle between light and dark modes in the chat interface to improve usability in different lighting conditions.\n\n## Requirements\n\n- [ ] Add a toggle button in the chat header\n- [ ] Implement theme switching logic\n- [ ] Persist user preference in localStorage\n- [ ] Ensure all chat components support both themes\n- [ ] Update existing CSS variables for dark mode\n\n## Acceptance Criteria\n\n- Toggle button is visible and accessible\n- Theme changes are applied immediately\n- User preference is remembered across sessions\n- All text remains readable in both modes\n- Icons and UI elements adapt to the selected theme',
406
+ labels: ['enhancement', 'ui', 'accessibility'],
407
+ assignee_ids: [123],
408
+ },
409
+ },
410
+ timestamp: '2025-06-25T19:22:21.290791+00:00',
411
+ status: 'success',
412
+ role: 'request',
413
+ };
414
+
415
+ export const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_UPDATE_WORK_ITEM = {
416
+ id: '128',
417
+ content: 'Tool update_work_item requires approval. Please confirm if you want to proceed.',
418
+ message_type: MESSAGE_MODEL_ROLES.request,
419
+ tool_info: {
420
+ name: 'update_work_item',
421
+ args: {
422
+ group_id: 'gitlab-org',
423
+ work_item_iid: 42,
424
+ title: 'Implement dark mode toggle for chat interface - Updated',
425
+ state: 'opened',
426
+ add_label_ids: ['bug', 'priority::high'],
427
+ },
428
+ },
429
+ timestamp: '2025-06-25T19:22:21.290791+00:00',
430
+ status: 'success',
431
+ role: 'request',
432
+ };
433
+
434
+ export const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_MERGE_REQUEST_NOTE = {
435
+ id: '129',
436
+ content:
437
+ 'Tool create_merge_request_note requires approval. Please confirm if you want to proceed.',
438
+ message_type: MESSAGE_MODEL_ROLES.request,
439
+ tool_info: {
440
+ name: 'create_merge_request_note',
441
+ args: {
442
+ project_id: 'gitlab-org/duo-ui',
443
+ merge_request_iid: 156,
444
+ body: "Great work on implementing the dark mode feature! šŸŽ‰\n\nI've reviewed the changes and they look solid. A few observations:\n\n- The CSS variables approach is clean and maintainable\n- The localStorage persistence works perfectly\n- All components adapt well to both themes\n\nThis will definitely improve the user experience. Ready to merge once the pipeline passes!",
445
+ },
446
+ },
447
+ timestamp: '2025-06-25T19:22:21.290791+00:00',
448
+ status: 'success',
449
+ role: 'request',
450
+ };
451
+
452
+ export const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_WORK_ITEM_NOTE = {
453
+ id: '130',
454
+ content: 'Tool create_work_item_note requires approval. Please confirm if you want to proceed.',
455
+ message_type: MESSAGE_MODEL_ROLES.request,
456
+ tool_info: {
457
+ name: 'create_work_item_note',
458
+ args: {
459
+ project_id: 'gitlab-org/duo-ui',
460
+ work_item_iid: 42,
461
+ body: "I've started working on this work item and made good progress on the initial implementation.\n\n## Progress Update\n\nāœ… **Completed:**\n- Added toggle button component\n- Implemented basic theme switching logic\n- Created CSS variables for dark mode\n\nšŸ”„ **In Progress:**\n- Testing theme persistence across sessions\n- Ensuring all components support both themes\n\nšŸ“‹ **Next Steps:**\n- Update remaining UI components\n- Add accessibility improvements\n- Write comprehensive tests\n\nExpected completion by end of week. Will update with any blockers.",
462
+ },
463
+ },
464
+ timestamp: '2025-06-25T19:22:21.290791+00:00',
465
+ status: 'success',
466
+ role: 'request',
467
+ };
468
+
469
+ export const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_ISSUE_NOTE = {
470
+ id: '131',
471
+ content: 'Tool create_issue_note requires approval. Please confirm if you want to proceed.',
472
+ message_type: MESSAGE_MODEL_ROLES.request,
473
+ tool_info: {
474
+ name: 'create_issue_note',
475
+ args: {
476
+ project_id: 'gitlab-org/duo-ui',
477
+ issue_iid: 89,
478
+ body: "Thanks for reporting this issue! šŸ‘\n\nI can reproduce the problem on my local environment. It seems like the CSP headers are indeed blocking the external web views.\n\n## Investigation Results\n\nAfter analyzing the VSCode Fork implementation, I found that:\n\n1. The CSP directive `frame-src` is too restrictive\n2. We need to allowlist specific domains for external web views\n3. The current policy blocks all external iframe content\n\n## Proposed Solution\n\nI'll create a merge request to:\n- Update the CSP configuration\n- Add necessary domain allowlisting\n- Ensure security is maintained while fixing the functionality\n\nAssigning this to myself and will have a fix ready soon.",
479
+ },
480
+ },
481
+ timestamp: '2025-06-25T19:22:21.290791+00:00',
482
+ status: 'success',
483
+ role: 'request',
484
+ };
485
+
394
486
  export const MOCK_WORKFLOW_END_MESSAGE = {
395
487
  id: '123',
396
488
  content: "Search for 'duo.*chat.*message' in directory",
package/translations.js CHANGED
@@ -50,8 +50,6 @@ export default {
50
50
  'CreateCommitToolParams.readCommitMessage': 'Read commit message',
51
51
  'CreateCommitToolParams.unknownFileActionLabel': 'Modify file %{filePath}',
52
52
  'CreateCommitToolParams.updateFileActionLabel': 'Update file %{filePath}',
53
- 'CreateIssueToolParams.ACCORDION_TITLE': 'Read description',
54
- 'CreateIssueToolParams.ASSIGN_LABELS_MESSAGE': 'Assign the labels <code>%{labels}</code>.',
55
53
  'DuoChat.chatBackLabel': 'Back to history',
56
54
  'DuoChat.chatBackToChatToolTip': 'Back to chat',
57
55
  'DuoChat.chatCancelLabel': 'Cancel',
@@ -81,6 +79,7 @@ export default {
81
79
  'DuoChat.emptyHistoryTitle': 'See your chat history',
82
80
  'DuoChat.openChatLabel': 'Open chat: %{title}',
83
81
  'DuoChat.threadDeleteLabel': 'Delete this chat',
82
+ 'DuoChat.verifiedAgent': 'Created and maintained by GitLab',
84
83
  'DuoChatContextItemDetailsModal.contentErrorMessage': 'Item content could not be displayed.',
85
84
  'DuoChatContextItemDetailsModal.title': 'Preview',
86
85
  'DuoChatContextItemMenu.emptyStateMessage': 'No results found',
@@ -121,12 +120,21 @@ export default {
121
120
  'DuoRecentCollapsable.viewAllText': 'View All',
122
121
  'GlDuoChat.chatDisclamer': 'Responses may be inaccurate. Verify before use.',
123
122
  'GlDuoChat.chatHistoryTitle': 'Chat history',
123
+ 'IssuableToolParams.ASSIGN_LABELS_MESSAGE': 'Assign the labels <code>%{labels}</code>.',
124
124
  'IssuableToolParams.BRANCH_MESSAGE':
125
125
  'From branch <code>%{sourceBranch}</code> to branch <code>%{targetBranch}</code>.',
126
+ 'IssuableToolParams.CONFIDENTIAL_MESSAGE': 'Set as confidential.',
126
127
  'IssuableToolParams.CREATE_EPIC': 'Create an epic in group <code>%{groupId}</code>.',
127
128
  'IssuableToolParams.CREATE_ISSUE': 'Open an issue in project <code>%{project}</code>.',
128
129
  'IssuableToolParams.CREATE_MERGE_REQUEST':
129
130
  'Open a merge request in project <code>%{project}</code>.',
131
+ 'IssuableToolParams.CREATE_WORK_ITEM':
132
+ 'Create a work item with type <em>"%{typeName}"</em> in %{workItemParentType} <code>%{workItemParentId}</code>.',
133
+ 'IssuableToolParams.ISSUE_LABEL': 'issue',
134
+ 'IssuableToolParams.MERGE_REQUEST_LABEL': 'merge request',
135
+ 'IssuableToolParams.NOTE_ACCORDION_TITLE': "Read note's content",
136
+ 'IssuableToolParams.NOTE_MESSAGE':
137
+ 'Post a note on %{noteParentLabel} <code>%{noteParentIid}</code> that belongs to %{workItemParentType} <code>%{workItemParentId}</code>.',
130
138
  'IssuableToolParams.TITLE_MESSAGE': 'Set the title "<em>%{title}</em>".',
131
139
  'IssuableToolParams.UPDATE_EPIC':
132
140
  'Update epic <code>%{epicId}</code> in group <code>%{groupId}</code>.',
@@ -134,6 +142,9 @@ export default {
134
142
  'Update issue <code>%{issueIid}</code> in project <code>%{project}</code>.',
135
143
  'IssuableToolParams.UPDATE_MERGE_REQUEST':
136
144
  'Update merge request <code>%{mergeRequestIid}</code> in project <code>%{project}</code>.',
145
+ 'IssuableToolParams.UPDATE_WORK_ITEM':
146
+ 'Update work item <code>%{workItemIid}</code> in %{workItemParentType} <code>%{workItemParentId}</code>.',
147
+ 'IssuableToolParams.WORK_ITEM_LABEL': 'work item',
137
148
  'MessageToolApproval.approveAllText': 'Always approve this tool',
138
149
  'MessageToolApproval.approveSessionText': 'Approve for session',
139
150
  'MessageToolApproval.approveText': 'Approve',
@@ -144,7 +155,11 @@ export default {
144
155
  'MessageToolApproval.createCommit': 'Duo wants to push a commit.',
145
156
  'MessageToolApproval.createEpic': 'Duo wants to create an epic.',
146
157
  'MessageToolApproval.createIssue': 'Duo wants to open an issue.',
158
+ 'MessageToolApproval.createIssueNote': 'Duo wants to post a note on an issue.',
147
159
  'MessageToolApproval.createMergeRequest': 'Duo wants to create a merge request.',
160
+ 'MessageToolApproval.createMergeRequestNote': 'Duo wants to post a note on a merge request.',
161
+ 'MessageToolApproval.createWorkItem': 'Duo wants to create a work item.',
162
+ 'MessageToolApproval.createWorkItemNote': 'Duo wants to post a note on a work item.',
148
163
  'MessageToolApproval.denialReasonLabel': 'Rejection reason',
149
164
  'MessageToolApproval.denialReasonPlaceholder':
150
165
  "Tell Duo why you're rejecting this tool execution...",
@@ -162,6 +177,7 @@ export default {
162
177
  'MessageToolApproval.toolUnknown': 'Unknown',
163
178
  'MessageToolApproval.updateEpic': 'Duo wants to update an epic.',
164
179
  'MessageToolApproval.updateIssue': 'Duo wants to update an issue.',
180
+ 'MessageToolApproval.updateWorkItem': 'Duo wants to update a work item.',
165
181
  'RunCommandToolParams.ACCORDION_TITLE': 'Expand command output',
166
182
  'WebAgenticDuoChat.chatCancelLabel': 'Cancel',
167
183
  'WebAgenticDuoChat.chatDefaultPredefinedPromptsChangePassword':