@gitlab/duo-ui 15.8.3 → 15.10.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.
@@ -1,48 +1,175 @@
1
- import { GlButton, GlIcon, GlTooltipDirective } from '@gitlab/ui';
1
+ import { nextTick } from 'vue';
2
+ import { GlButton, GlIcon, GlFormTextarea, GlForm, GlTooltipDirective } from '@gitlab/ui';
2
3
  import { translate } from '@gitlab/ui/dist/utils/i18n';
3
4
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
4
5
 
5
6
  const i18n = {
6
7
  THANKS: translate('AgenticBinaryFeedback.thanks', 'Thanks for the feedback!'),
7
8
  THUMBS_UP: translate('AgenticBinaryFeedback.thumbsUp', 'Helpful'),
8
- THUMBS_DOWN: translate('AgenticBinaryFeedback.thumbsDown', 'Not helpful')
9
+ THUMBS_DOWN: translate('AgenticBinaryFeedback.thumbsDown', 'Not helpful'),
10
+ TELL_US_MORE: translate('AgenticBinaryFeedback.tellUsMore', 'Tell us more'),
11
+ SUBMIT: translate('AgenticBinaryFeedback.submit', 'Submit'),
12
+ BACK: translate('AgenticBinaryFeedback.back', 'Back'),
13
+ CLOSE: translate('AgenticBinaryFeedback.close', 'Close'),
14
+ FEEDBACK_PLACEHOLDER: translate('AgenticBinaryFeedback.placeholder', 'Share your feedback...'),
15
+ THUMBS_UP_HEADER: translate('AgenticBinaryFeedback.thumbsUpHeader', 'What made this helpful?'),
16
+ THUMBS_DOWN_HEADER: translate('AgenticBinaryFeedback.thumbsDownHeader', 'What would have been more helpful?'),
17
+ TOO_GENERIC: translate('AgenticBinaryFeedback.tooGeneric', 'Too generic'),
18
+ MISSING_STEPS: translate('AgenticBinaryFeedback.missingSteps', 'Missing steps'),
19
+ WRONG_CONTEXT: translate('AgenticBinaryFeedback.wrongContext', 'Wrong context'),
20
+ OUTDATED_INCORRECT: translate('AgenticBinaryFeedback.outdatedIncorrect', 'Outdated/incorrect'),
21
+ SOLVED_PROBLEM: translate('AgenticBinaryFeedback.solvedProblem', 'Solved my problem'),
22
+ SAVED_TIME: translate('AgenticBinaryFeedback.savedTime', 'Saved me time'),
23
+ GOOD_EXAMPLES: translate('AgenticBinaryFeedback.goodExamples', 'Good examples'),
24
+ ACCURATE_INFO: translate('AgenticBinaryFeedback.accurateInfo', 'Accurate information')
25
+ };
26
+ const thumbsDownReasons = [{
27
+ key: 'too_generic',
28
+ label: i18n.TOO_GENERIC
29
+ }, {
30
+ key: 'missing_steps',
31
+ label: i18n.MISSING_STEPS
32
+ }, {
33
+ key: 'wrong_context',
34
+ label: i18n.WRONG_CONTEXT
35
+ }, {
36
+ key: 'outdated_incorrect',
37
+ label: i18n.OUTDATED_INCORRECT
38
+ }, {
39
+ key: 'tell_us_more',
40
+ label: i18n.TELL_US_MORE,
41
+ isCustom: true
42
+ }];
43
+ const thumbsUpReasons = [{
44
+ key: 'solved_problem',
45
+ label: i18n.SOLVED_PROBLEM
46
+ }, {
47
+ key: 'saved_time',
48
+ label: i18n.SAVED_TIME
49
+ }, {
50
+ key: 'good_examples',
51
+ label: i18n.GOOD_EXAMPLES
52
+ }, {
53
+ key: 'accurate_info',
54
+ label: i18n.ACCURATE_INFO
55
+ }, {
56
+ key: 'tell_us_more',
57
+ label: i18n.TELL_US_MORE,
58
+ isCustom: true
59
+ }];
60
+ const FEEDBACK_VIEW = {
61
+ CLOSED: 'closed',
62
+ REASON_LIST: 'reason_list',
63
+ TELL_US_MORE: 'tell_us_more'
9
64
  };
10
65
  var script = {
11
66
  name: 'AgenticBinaryFeedback',
12
67
  i18n,
68
+ thumbsUpReasons,
69
+ thumbsDownReasons,
13
70
  components: {
14
71
  GlButton,
15
- GlIcon
72
+ GlIcon,
73
+ GlFormTextarea,
74
+ GlForm
16
75
  },
17
76
  directives: {
18
77
  GlTooltip: GlTooltipDirective
19
78
  },
20
79
  data() {
21
80
  return {
22
- feedbackType: null
81
+ feedbackType: null,
82
+ feedbackView: FEEDBACK_VIEW.CLOSED,
83
+ customFeedback: '',
84
+ feedbackSubmitted: false
23
85
  };
24
86
  },
25
87
  computed: {
26
- feedbackGiven() {
27
- return this.feedbackType !== null;
28
- },
29
88
  isThumbsUp() {
30
89
  return this.feedbackType === 'thumbs_up';
31
90
  },
32
91
  isThumbsDown() {
33
92
  return this.feedbackType === 'thumbs_down';
93
+ },
94
+ reasonOptions() {
95
+ return this.isThumbsUp ? this.$options.thumbsUpReasons : this.$options.thumbsDownReasons;
96
+ },
97
+ reasonHeader() {
98
+ return this.isThumbsUp ? this.$options.i18n.THUMBS_UP_HEADER : this.$options.i18n.THUMBS_DOWN_HEADER;
99
+ },
100
+ isOverCharacterLimit() {
101
+ return this.customFeedback.length > 140;
102
+ },
103
+ trimmedFeedback() {
104
+ return this.customFeedback.trim();
105
+ },
106
+ isTextareaValid() {
107
+ return this.trimmedFeedback.length === 0 ? null : !this.isOverCharacterLimit;
108
+ },
109
+ canSubmitCustomFeedback() {
110
+ return this.trimmedFeedback.length > 0 && !this.isOverCharacterLimit;
111
+ },
112
+ characterCountText() {
113
+ const remaining = 140 - this.customFeedback.length;
114
+ if (remaining >= 0) {
115
+ return remaining === 1 ? `${remaining} character remaining` : `${remaining} characters remaining`;
116
+ }
117
+ const over = Math.abs(remaining);
118
+ return over === 1 ? `${over} character over limit` : `${over} characters over limit`;
119
+ },
120
+ isDropdownOpen() {
121
+ return this.feedbackView !== FEEDBACK_VIEW.CLOSED;
122
+ },
123
+ isReasonListVisible() {
124
+ return this.feedbackView === FEEDBACK_VIEW.REASON_LIST;
125
+ },
126
+ isTellUsMoreVisible() {
127
+ return this.feedbackView === FEEDBACK_VIEW.TELL_US_MORE;
34
128
  }
35
129
  },
36
130
  methods: {
37
- submitFeedback(type) {
38
- /**
39
- * Notify listeners about the feedback submission.
40
- * @param {string} type The feedback type ('thumbs_up' or 'thumbs_down').
41
- */
131
+ selectFeedbackType(type) {
132
+ this.feedbackType = type;
133
+ this.feedbackView = FEEDBACK_VIEW.REASON_LIST;
134
+ this.customFeedback = '';
135
+ this.scrollToDropdown();
136
+ },
137
+ scrollToDropdown() {
138
+ nextTick(() => {
139
+ var _this$$refs$dropdown, _el$scrollIntoView;
140
+ const el = ((_this$$refs$dropdown = this.$refs.dropdown) === null || _this$$refs$dropdown === void 0 ? void 0 : _this$$refs$dropdown.$el) || this.$refs.dropdown;
141
+ el === null || el === void 0 ? void 0 : (_el$scrollIntoView = el.scrollIntoView) === null || _el$scrollIntoView === void 0 ? void 0 : _el$scrollIntoView.call(el, {
142
+ behavior: 'smooth',
143
+ block: 'nearest'
144
+ });
145
+ });
146
+ },
147
+ selectReason(reason) {
148
+ if (reason.isCustom) {
149
+ this.feedbackView = FEEDBACK_VIEW.TELL_US_MORE;
150
+ return;
151
+ }
152
+ this.submitFeedback(reason.key);
153
+ },
154
+ submitCustomFeedback() {
155
+ this.submitFeedback(`custom_${this.customFeedback.trim()}`);
156
+ },
157
+ submitFeedback(feedbackReason) {
42
158
  this.$emit('feedback', {
43
- feedbackType: type
159
+ feedbackType: this.feedbackType,
160
+ feedbackReason
44
161
  });
45
- this.feedbackType = type;
162
+ this.feedbackView = FEEDBACK_VIEW.CLOSED;
163
+ this.feedbackSubmitted = true;
164
+ },
165
+ goBackToReasons() {
166
+ this.feedbackView = FEEDBACK_VIEW.REASON_LIST;
167
+ this.customFeedback = '';
168
+ },
169
+ closeDropdown() {
170
+ this.feedbackView = FEEDBACK_VIEW.CLOSED;
171
+ this.customFeedback = '';
172
+ this.feedbackType = null;
46
173
  }
47
174
  }
48
175
  };
@@ -51,7 +178,7 @@ var script = {
51
178
  const __vue_script__ = script;
52
179
 
53
180
  /* template */
54
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"agentic-binary-feedback gl-flex gl-items-center gl-gap-2"},[(!_vm.feedbackGiven)?[_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.THUMBS_UP,"aria-label":_vm.$options.i18n.THUMBS_UP,"icon":"thumb-up","category":"tertiary","size":"small","data-testid":"thumb-up-button"},on:{"click":function($event){return _vm.submitFeedback('thumbs_up')}}}),_vm._v(" "),_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.THUMBS_DOWN,"aria-label":_vm.$options.i18n.THUMBS_DOWN,"icon":"thumb-down","category":"tertiary","size":"small","data-testid":"thumb-down-button"},on:{"click":function($event){return _vm.submitFeedback('thumbs_down')}}})]:_c('div',{staticClass:"gl-relative gl-flex gl-items-center gl-gap-2",attrs:{"data-testid":"feedback-given"}},[_c('div',{staticClass:"feedback-colored-icon",attrs:{"data-testid":"feedback-colored-icon"}},[(_vm.isThumbsUp)?_c('gl-icon',{staticClass:"gl-text-success",attrs:{"name":"thumb-up","size":16,"data-testid":"thumb-up-icon-success"}}):(_vm.isThumbsDown)?_c('gl-icon',{staticClass:"gl-text-danger",attrs:{"name":"thumb-down","size":16,"data-testid":"thumb-down-icon-danger"}}):_vm._e()],1),_vm._v(" "),_c('div',{staticClass:"feedback-thanks gl-m-l-0 gl-w-0 gl-overflow-hidden gl-whitespace-nowrap gl-opacity-0",attrs:{"data-testid":"feedback-thanks"}},[_c('gl-icon',{staticClass:"gl-text-success",attrs:{"name":"check-xs","size":16,"data-testid":"check-icon"}}),_vm._v(" "),_c('span',{staticClass:"gl-text-sm gl-text-subtle"},[_vm._v(_vm._s(_vm.$options.i18n.THANKS))])],1)])],2)};
181
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"agentic-binary-feedback gl-flex gl-items-center gl-gap-2",class:{ 'gl-relative': !_vm.isDropdownOpen }},[(!_vm.feedbackSubmitted && !_vm.isDropdownOpen)?[_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.THUMBS_UP,"aria-label":_vm.$options.i18n.THUMBS_UP,"icon":"thumb-up","category":"tertiary","size":"small","data-testid":"thumb-up-button"},on:{"click":function($event){return _vm.selectFeedbackType('thumbs_up')}}}),_vm._v(" "),_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"title":_vm.$options.i18n.THUMBS_DOWN,"aria-label":_vm.$options.i18n.THUMBS_DOWN,"icon":"thumb-down","category":"tertiary","size":"small","data-testid":"thumb-down-button"},on:{"click":function($event){return _vm.selectFeedbackType('thumbs_down')}}})]:(_vm.isDropdownOpen)?[_c('div',{staticClass:"gl-flex gl-h-6 gl-items-center"},[_c('gl-icon',{class:_vm.isThumbsUp ? 'gl-text-success' : 'gl-text-danger',attrs:{"name":_vm.isThumbsUp ? 'thumb-up' : 'thumb-down',"size":16,"data-testid":"selected-thumb-icon"}})],1),_vm._v(" "),_c('div',{ref:"dropdown",staticClass:"feedback-reason-dropdown gl-l-0 gl-r-0 gl-border gl-absolute gl-top-full gl-mb-4 gl-mt-4 gl-w-full gl-rounded-lg gl-border-default gl-bg-subtle gl-p-3",attrs:{"data-testid":"feedback-reason-dropdown"}},[_c('div',{staticClass:"gl-mb-3 gl-flex gl-items-center gl-justify-between gl-gap-2"},[_c('p',{staticClass:"gl-m-0 gl-text-sm gl-font-bold",attrs:{"data-testid":"reason-header"}},[_vm._v("\n "+_vm._s(_vm.reasonHeader)+"\n ")]),_vm._v(" "),_c('div',{staticClass:"gl-flex gl-shrink-0 gl-items-center gl-gap-1"},[(_vm.isTellUsMoreVisible)?_c('gl-button',{attrs:{"icon":"go-back","category":"tertiary","size":"small","aria-label":_vm.$options.i18n.BACK,"data-testid":"back-button"},on:{"click":_vm.goBackToReasons}}):_vm._e(),_vm._v(" "),_c('gl-button',{staticClass:"gl-mr-[-5px]",attrs:{"icon":"close","category":"tertiary","size":"small","aria-label":_vm.$options.i18n.CLOSE,"data-testid":"close-dropdown-button"},on:{"click":_vm.closeDropdown}})],1)]),_vm._v(" "),(_vm.isReasonListVisible)?_c('div',{staticClass:"gl-flex gl-flex-wrap gl-gap-2",attrs:{"data-testid":"reason-buttons"}},_vm._l((_vm.reasonOptions),function(reason){return _c('gl-button',{key:reason.key,staticClass:"gl-rounded-full",attrs:{"category":"secondary","size":"small","icon":reason.isCustom ? 'pencil' : undefined,"data-testid":("reason-" + (reason.key))},on:{"click":function($event){return _vm.selectReason(reason)}}},[_vm._v("\n "+_vm._s(reason.label)+"\n ")])}),1):_vm._e(),_vm._v(" "),(_vm.isTellUsMoreVisible)?_c('div',{staticClass:"gl-flex gl-w-full gl-flex-col gl-gap-3",attrs:{"data-testid":"tell-us-more-view"}},[_c('gl-form',{staticClass:"gl-flex gl-w-full gl-flex-col gl-gap-3",on:{"submit":function($event){$event.preventDefault();_vm.canSubmitCustomFeedback ? _vm.submitCustomFeedback() : null;}}},[_c('gl-form-textarea',{attrs:{"state":_vm.isTextareaValid,"placeholder":_vm.$options.i18n.FEEDBACK_PLACEHOLDER,"rows":3,"max-rows":5,"data-testid":"custom-feedback-textarea"},model:{value:(_vm.customFeedback),callback:function ($$v) {_vm.customFeedback=$$v;},expression:"customFeedback"}}),_vm._v(" "),_c('div',{staticClass:"gl-flex gl-items-center gl-justify-between"},[_c('gl-button',{attrs:{"variant":"confirm","size":"small","type":"submit","data-testid":"submit-custom-feedback-button"}},[_vm._v("\n "+_vm._s(_vm.$options.i18n.SUBMIT)+"\n ")]),_vm._v(" "),_c('span',{staticClass:"gl-text-sm",class:_vm.isOverCharacterLimit ? 'gl-text-danger' : 'gl-text-subtle',attrs:{"data-testid":"character-count"}},[_vm._v("\n "+_vm._s(_vm.characterCountText)+"\n ")])],1)],1)],1):_vm._e()])]:_c('div',{staticClass:"gl-relative gl-flex gl-items-center gl-gap-2",attrs:{"data-testid":"feedback-given"}},[_c('div',{staticClass:"feedback-colored-icon",attrs:{"data-testid":"feedback-colored-icon"}},[(_vm.isThumbsUp)?_c('gl-icon',{staticClass:"gl-text-success",attrs:{"name":"thumb-up","size":16,"data-testid":"thumb-up-icon-success"}}):(_vm.isThumbsDown)?_c('gl-icon',{staticClass:"gl-text-danger",attrs:{"name":"thumb-down","size":16,"data-testid":"thumb-down-icon-danger"}}):_vm._e()],1),_vm._v(" "),_c('div',{staticClass:"feedback-thanks gl-m-l-0 gl-w-0 gl-overflow-hidden gl-whitespace-nowrap gl-opacity-0",attrs:{"data-testid":"feedback-thanks"}},[_c('gl-icon',{staticClass:"gl-text-success",attrs:{"name":"check-xs","size":16,"data-testid":"check-icon"}}),_vm._v(" "),_c('span',{staticClass:"gl-text-sm gl-text-subtle"},[_vm._v(_vm._s(_vm.$options.i18n.THANKS))])],1)])],2)};
55
182
  var __vue_staticRenderFns__ = [];
56
183
 
57
184
  /* style */
@@ -84,4 +211,4 @@ var __vue_staticRenderFns__ = [];
84
211
  );
85
212
 
86
213
  export default __vue_component__;
87
- export { i18n };
214
+ export { FEEDBACK_VIEW, i18n, thumbsDownReasons, thumbsUpReasons };
@@ -319,7 +319,7 @@ var script = {
319
319
  const __vue_script__ = script;
320
320
 
321
321
  /* template */
322
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:"content-wrapper",staticClass:"duo-chat-message-container gl-group gl-flex gl-flex-col gl-gap-4 gl-text-base gl-break-anywhere",class:{
322
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:"content-wrapper",staticClass:"duo-chat-message-container gl-group gl-relative gl-flex gl-flex-col gl-gap-4 gl-text-base gl-break-anywhere",class:{
323
323
  'gl-pr-7': _vm.isAssistantMessage,
324
324
  'gl-justify-end gl-pl-7': _vm.isUserMessage,
325
325
  'duo-chat-message-complete': _vm.isDoneStreaming,
@@ -1,6 +1,8 @@
1
- import { GlButton, GlAvatar } from '@gitlab/ui';
1
+ import { GlButton, GlAvatar, GlSearchBoxByType } from '@gitlab/ui';
2
+ import debounce from 'lodash/debounce';
2
3
  import { translate, sprintf } from '../../../../utils/i18n';
3
4
  import { formatLocalizedDate } from '../../../../utils/date';
5
+ import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '../../constants';
4
6
  import DuoChatThreadsEmpty from './duo_chat_threads_empty';
5
7
  import DuoChatThreadsSkeleton from './duo_chat_threads_skeleton_loader';
6
8
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
@@ -9,13 +11,17 @@ const i18n = {
9
11
  CHAT_HISTORY_INFO: translate('DuoChat.chatHistoryInfo', 'Inactive chats are deleted after 30 days.'),
10
12
  THREAD_DELETE_LABEL: translate('DuoChat.threadDeleteLabel', 'Delete this chat'),
11
13
  OPEN_CHAT_LABEL: translate('DuoChat.openChatLabel', 'Open chat: %{title}'),
12
- UNTITLED_CHAT_TITLE: translate('DuoChat.untitledChatTitle', 'Untitled Chat')
14
+ UNTITLED_CHAT_TITLE: translate('DuoChat.untitledChatTitle', 'Untitled Chat'),
15
+ SEARCH_PLACEHOLDER: translate('DuoChat.searchPlaceholder', 'Search chats...'),
16
+ NO_RESULTS: translate('DuoChat.noSearchResults', 'No results found'),
17
+ CHAT_HISTORY_SEARCH: translate('DuoChat.chatHistorySearch', 'Search chat history')
13
18
  };
14
19
  var script = {
15
20
  name: 'DuoChatHistory',
16
21
  components: {
17
22
  GlButton,
18
23
  GlAvatar,
24
+ GlSearchBoxByType,
19
25
  DuoChatThreadsEmpty,
20
26
  DuoChatThreadsSkeleton
21
27
  },
@@ -34,12 +40,32 @@ var script = {
34
40
  default: false
35
41
  }
36
42
  },
43
+ data() {
44
+ return {
45
+ searchQuery: '',
46
+ debouncedSearchQuery: ''
47
+ };
48
+ },
37
49
  computed: {
50
+ filteredThreads() {
51
+ if (!this.debouncedSearchQuery.trim()) {
52
+ return this.threads;
53
+ }
54
+ const query = this.debouncedSearchQuery.trim();
55
+ return this.threads.filter(thread => {
56
+ const {
57
+ title = '',
58
+ goal = '',
59
+ agentName = ''
60
+ } = thread;
61
+ return title.includes(query) || goal.includes(query) || agentName.includes(query);
62
+ });
63
+ },
38
64
  groupedThreads() {
39
- if (!this.hasThreads) {
65
+ if (!this.hasFilteredThreads) {
40
66
  return {};
41
67
  }
42
- return this.threads.slice().sort((a, b) => this.compareThreadDates(b.updatedAt, a.updatedAt)).sort((a, b) => this.compareThreadDates(b.lastUpdatedAt, a.lastUpdatedAt)).reduce((grouped, thread) => {
68
+ return this.filteredThreads.slice().sort((a, b) => this.compareThreadDates(b.updatedAt, a.updatedAt)).sort((a, b) => this.compareThreadDates(b.lastUpdatedAt, a.lastUpdatedAt)).reduce((grouped, thread) => {
43
69
  const dateField = thread.updatedAt || thread.lastUpdatedAt;
44
70
  const dateKey = this.getDateKey(dateField);
45
71
  return {
@@ -50,8 +76,21 @@ var script = {
50
76
  },
51
77
  hasThreads() {
52
78
  return this.threads.length > 0;
79
+ },
80
+ hasFilteredThreads() {
81
+ return this.filteredThreads.length > 0;
53
82
  }
54
83
  },
84
+ watch: {
85
+ searchQuery(newValue) {
86
+ this.updateDebouncedSearchQuery(newValue);
87
+ }
88
+ },
89
+ created() {
90
+ this.updateDebouncedSearchQuery = debounce(value => {
91
+ this.debouncedSearchQuery = value;
92
+ }, DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
93
+ },
55
94
  methods: {
56
95
  threadLabel(thread) {
57
96
  return thread.title || thread.goal || i18n.UNTITLED_CHAT_TITLE;
@@ -88,9 +127,9 @@ var script = {
88
127
  const __vue_script__ = script;
89
128
 
90
129
  /* template */
91
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-flex gl-flex-col gl-overflow-hidden"},[(_vm.loading)?_c('duo-chat-threads-skeleton'):(_vm.hasThreads)?[_c('div',{staticClass:"gl-grow gl-overflow-y-scroll gl-px-4 gl-py-5"},_vm._l((_vm.groupedThreads),function(threadsForDate,date){return _c('div',{key:date,staticClass:"gl-mb-3"},[_c('div',{staticClass:"gl-mb-3 gl-text-base gl-font-bold gl-text-default",attrs:{"data-testid":"chat-threads-date-header"}},[_vm._v("\n "+_vm._s(_vm.formattedLocalDate(date))+"\n ")]),_vm._v(" "),_vm._l((threadsForDate),function(thread){return _c('div',{key:thread.id,staticClass:"history-item gl-w-full gl-text-base"},[_c('gl-button',{staticClass:"history-item-name gl-w-full gl-text-base",attrs:{"data-testid":"chat-threads-thread-box","aria-label":_vm.sprintf(_vm.$options.i18n.OPEN_CHAT_LABEL, {
130
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-flex gl-flex-col gl-overflow-hidden"},[(_vm.loading)?_c('duo-chat-threads-skeleton'):(_vm.hasThreads)?[_c('div',{staticClass:"gl-px-4 gl-pt-4"},[_c('span',{staticClass:"gl-sr-only"},[_vm._v(_vm._s(_vm.$options.i18n.CHAT_HISTORY_SEARCH))]),_vm._v(" "),_c('gl-search-box-by-type',{attrs:{"data-testid":"chat-threads-search-input","placeholder":_vm.$options.i18n.SEARCH_PLACEHOLDER},model:{value:(_vm.searchQuery),callback:function ($$v) {_vm.searchQuery=$$v;},expression:"searchQuery"}})],1),_vm._v(" "),_c('div',{staticClass:"gl-grow gl-overflow-y-scroll gl-px-4 gl-py-5"},[(!_vm.hasFilteredThreads)?_c('p',{staticClass:"gl-mb-0 gl-text-center gl-text-subtle",attrs:{"data-testid":"chat-threads-no-results"}},[_vm._v("\n "+_vm._s(_vm.$options.i18n.NO_RESULTS)+"\n ")]):_vm._e(),_vm._v(" "),_vm._l((_vm.groupedThreads),function(threadsForDate,date){return _c('div',{key:date,staticClass:"gl-mb-3"},[_c('div',{staticClass:"gl-mb-3 gl-text-base gl-font-bold gl-text-default",attrs:{"data-testid":"chat-threads-date-header"}},[_vm._v("\n "+_vm._s(_vm.formattedLocalDate(date))+"\n ")]),_vm._v(" "),_vm._l((threadsForDate),function(thread){return _c('div',{key:thread.id,staticClass:"history-item gl-w-full gl-text-base"},[_c('gl-button',{staticClass:"history-item-name gl-w-full gl-text-base",attrs:{"data-testid":"chat-threads-thread-box","aria-label":_vm.sprintf(_vm.$options.i18n.OPEN_CHAT_LABEL, {
92
131
  title: _vm.threadLabel(thread),
93
- })},on:{"click":function($event){return _vm.onSelectThread(thread)}}},[_c('gl-avatar',{staticClass:"gl-shrink-0",attrs:{"size":32,"entity-name":_vm.threadLabel(thread),"shape":"circle"}}),_vm._v(" "),_c('div',{staticClass:"gl-grow gl-whitespace-normal gl-break-all"},[(!thread.title && !thread.goal)?_c('span',{staticClass:"gl-line-clamp-1 gl-text-default"},[_vm._v(_vm._s(_vm.$options.i18n.UNTITLED_CHAT_TITLE))]):[(thread.title)?_c('span',{staticClass:"gl-line-clamp-1 gl-text-default"},[_vm._v(_vm._s(thread.title))]):_vm._e(),_vm._v(" "),(thread.goal)?_c('span',{staticClass:"gl-line-clamp-1 gl-text-subtle"},[_vm._v(_vm._s(thread.goal))]):_vm._e()],_vm._v(" "),(thread.agentName)?_c('span',{staticClass:"gl-line-clamp-1 gl-text-sm gl-text-subtle"},[_vm._v("\n "+_vm._s(thread.agentName)+"\n ")]):_vm._e()],2)],1),_vm._v(" "),_c('gl-button',{staticClass:"history-remove-button",attrs:{"data-testid":"chat-threads-delete-thread-button","icon":"remove","category":"tertiary","title":_vm.$options.i18n.THREAD_DELETE_LABEL,"aria-label":_vm.$options.i18n.THREAD_DELETE_LABEL},on:{"click":function($event){return _vm.$emit('delete-thread', thread.id)}}})],1)})],2)}),0),_vm._v(" "),_c('p',{staticClass:"gl-m-0 gl-p-5 gl-text-center gl-text-base gl-text-subtle",attrs:{"data-testid":"chat-threads-info-banner"}},[_vm._v("\n "+_vm._s(_vm.$options.i18n.CHAT_HISTORY_INFO)+"\n ")])]:_c('duo-chat-threads-empty')],2)};
132
+ })},on:{"click":function($event){return _vm.onSelectThread(thread)}}},[_c('gl-avatar',{staticClass:"gl-shrink-0",attrs:{"size":32,"entity-name":_vm.threadLabel(thread),"shape":"circle"}}),_vm._v(" "),_c('div',{staticClass:"gl-grow gl-whitespace-normal gl-break-all"},[(!thread.title && !thread.goal)?_c('span',{staticClass:"gl-line-clamp-1 gl-text-default"},[_vm._v(_vm._s(_vm.$options.i18n.UNTITLED_CHAT_TITLE))]):[(thread.title)?_c('span',{staticClass:"gl-line-clamp-1 gl-text-default"},[_vm._v(_vm._s(thread.title))]):_vm._e(),_vm._v(" "),(thread.goal)?_c('span',{staticClass:"gl-line-clamp-1 gl-text-subtle"},[_vm._v(_vm._s(thread.goal))]):_vm._e()],_vm._v(" "),(thread.agentName)?_c('span',{staticClass:"gl-line-clamp-1 gl-text-sm gl-text-subtle"},[_vm._v("\n "+_vm._s(thread.agentName)+"\n ")]):_vm._e()],2)],1),_vm._v(" "),_c('gl-button',{staticClass:"history-remove-button",attrs:{"data-testid":"chat-threads-delete-thread-button","icon":"remove","category":"tertiary","title":_vm.$options.i18n.THREAD_DELETE_LABEL,"aria-label":_vm.$options.i18n.THREAD_DELETE_LABEL},on:{"click":function($event){return _vm.$emit('delete-thread', thread.id)}}})],1)})],2)})],2),_vm._v(" "),_c('p',{staticClass:"gl-m-0 gl-p-5 gl-text-center gl-text-base gl-text-subtle",attrs:{"data-testid":"chat-threads-info-banner"}},[_vm._v("\n "+_vm._s(_vm.$options.i18n.CHAT_HISTORY_INFO)+"\n ")])]:_c('duo-chat-threads-empty')],2)};
94
133
  var __vue_staticRenderFns__ = [];
95
134
 
96
135
  /* style */
@@ -4,6 +4,7 @@ const CHAT_NEW_MESSAGE = '/new';
4
4
  const CHAT_INCLUDE_MESSAGE = '/include';
5
5
  const CHAT_BASE_COMMANDS = [CHAT_RESET_MESSAGE, CHAT_CLEAR_MESSAGE, CHAT_NEW_MESSAGE];
6
6
  const LOADING_TRANSITION_DURATION = 7500;
7
+ const DEFAULT_DEBOUNCE_AND_THROTTLE_MS = 250;
7
8
  const DOCUMENTATION_SOURCE_TYPES = {
8
9
  HANDBOOK: {
9
10
  value: 'handbook'
@@ -59,4 +60,4 @@ const APPROVAL_TOOL_NAMES = {
59
60
  runGitCommand: 'run_git_command'
60
61
  };
61
62
 
62
- export { APPROVAL_TOOL_NAMES, CHAT_BASE_COMMANDS, CHAT_CLEAR_MESSAGE, CHAT_INCLUDE_MESSAGE, CHAT_NEW_MESSAGE, CHAT_RESET_MESSAGE, DOCUMENTATION_SOURCE_TYPES, LOADING_TRANSITION_DURATION, MAX_PROMPT_LENGTH, MESSAGE_MODEL_ROLES, PROMPT_LENGTH_WARNING, SELECTED_CONTEXT_ITEMS_DEFAULT_COLLAPSED, acceptedApproveToolPayloads, badgeTypeValidator, badgeTypes };
63
+ export { APPROVAL_TOOL_NAMES, CHAT_BASE_COMMANDS, CHAT_CLEAR_MESSAGE, CHAT_INCLUDE_MESSAGE, CHAT_NEW_MESSAGE, CHAT_RESET_MESSAGE, DEFAULT_DEBOUNCE_AND_THROTTLE_MS, DOCUMENTATION_SOURCE_TYPES, LOADING_TRANSITION_DURATION, MAX_PROMPT_LENGTH, MESSAGE_MODEL_ROLES, PROMPT_LENGTH_WARNING, SELECTED_CONTEXT_ITEMS_DEFAULT_COLLAPSED, acceptedApproveToolPayloads, badgeTypeValidator, badgeTypes };
@@ -717,115 +717,75 @@ const THREADLIST = [{
717
717
  title: 'Before the Configuration Committee'
718
718
  }];
719
719
  const AGENTIC_THREADLIST = [{
720
- id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1031434',
721
- projectId: 'gid://gitlab/Project/62039593',
722
- humanStatus: 'input required',
723
- updatedAt: '2025-01-24T19:27:15Z',
724
- goal: 'Help me migrate the legacy duo_chat_component to the modern tech stack of the current project. If there are ways to simplify it (remove unnecessary CSS, functionality, etc) and rely more on the default shadcn-ui components, please suggest those simplifications. If you need to install any shadcn-ui component, feel free to do so',
725
- stalled: false,
726
- archived: false,
727
- firstCheckpoint: {
728
- checkpoint: '{"v":3,"id":"1f0659ae-d2f8-6230-bfff-fea961e0365f","ts":"2025-07-20T18:54:12.716786+00:00","pending_sends":[],"versions_seen":{"__input__":{}},"channel_values":{"__start__":{"plan":{"steps":[]},"status":"Not Started","project":{"id":62039593,"name":"Duo UI","web_url":"https://gitlab.com/gitlab-org/duo-ui","languages":[{"name":"JavaScript","share":72.16},{"name":"Vue","share":22.06},{"name":"SCSS","share":2.68},{"name":"Ruby","share":1.54},{"name":"TypeScript","share":0.6}],"description":"","http_url_to_repo":"https://gitlab.com/gitlab-org/duo-ui.git"},"approval":null,"ui_chat_log":[{"status":"success","content":"Help me migrate the legacy duo_chat_component to the modern tech stack of the current project. If there are ways to simplify it (remove unnecessary CSS, functionality, etc) and rely more on the default shadcn-ui components, please suggest those simplifications. If you need to install any shadcn-ui component, feel free to do so","timestamp":"2025-07-20T18:54:12.429236+00:00","tool_info":null,"message_type":"user","correlation_id":null,"message_sub_type":null,"additional_context":[{"id":"1","type":"AdditionalContext","content":"The user wants you to adhere to these rules:\\nThe project is built with Vue 3, Typescript, Tailwind, shadcn-vue and other modern technologies.\\n\\nFor some transient time, this project is used to migrate legacy Vue 2 + JS + gitlab-ui components to the new tech stack. While migrating components all of the gitlab-ui components should be replaced with the shadcn-ui analogues or explicitly agreed with the user. If you see any better analogue in shadcn-ui or better way to implement functionality, speak up and ask for user\'s confirmation on what path to take.\\n\\nEvery component should have a story and a test spec alongside itself.","category":"user_rule","metadata":{"icon":"user","title":"User instruction","enabled":true,"subType":"user_rule","subTypeLabel":"User instruction","secondaryText":"chat-rules.md"}}]}],"last_human_input":null,"conversation_history":{"Chat Agent":[{"id":null,"name":null,"type":"HumanMessage","content":"Help me migrate the legacy duo_chat_component to the modern tech stack of the current project. If there are ways to simplify it (remove unnecessary CSS, functionality, etc) and rely more on the default shadcn-ui components, please suggest those simplifications. If you need to install any shadcn-ui component, feel free to do so","example":false,"additional_kwargs":{"additional_context":[{"id":"1","content":"The user wants you to adhere to these rules:\\nThe project is built with Vue 3, Typescript, Tailwind, shadcn-vue and other modern technologies.\\n\\nFor some transient time, this project is used to migrate legacy Vue 2 + JS + gitlab-ui components to the new tech stack. While migrating components all of the gitlab-ui components should be replaced with the shadcn-ui analogues or explicitly agreed with the user. If you see any better analogue in shadcn-ui or better way to implement functionality, speak up and ask for user\'s confirmation on what path to take.\\n\\nEvery component should have a story and a test spec alongside itself.","category":"user_rule","metadata":{"icon":"user","title":"User instruction","enabled":true,"subType":"user_rule","subTypeLabel":"User instruction","secondaryText":"chat-rules.md"}}]},"response_metadata":{}}]}}},"channel_versions":{"__start__":1}}'
729
- }
720
+ __typename: 'DuoWorkflow',
721
+ id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1801035',
722
+ lastUpdatedAt: '2025-01-31T13:45:20Z',
723
+ title: 'Help me refactor this authentication module',
724
+ aiCatalogItemVersionId: null,
725
+ agentName: 'GitLab Duo'
730
726
  }, {
731
- id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1031775',
732
- projectId: 'gid://gitlab/Project/278964',
733
- humanStatus: 'input required',
734
- updatedAt: '2025-01-31T12:20:31Z',
735
- goal: 'I have the following data structure: "edges": [\n {\n "node": {\n "id": "gid://gitlab/Ai::DuoWorkflows::Workflow/1031434",\n "projectId": "gid://gitlab/Project/62039593",\n "humanStatus": "input required",\n "updatedAt": "2025-07-20T19:27:15Z",\n "createdAt": "2025-07-20T18:51:44Z",\n "goal": "Hel",\n "stalled": false,\n "archived": false\n }\n },\n {\n "node": {\n "id": "gid://gitlab/Ai::DuoWorkflows::Workflow/1031206",\n "projectId": "gid://gitlab/Project/62039593",\n "humanStatus": "input required",\n "updatedAt": "2025-07-19T12:20:31Z",\n "createdAt": "2025-07-19T12:15:49Z",\n "goal": "Hel",\n "stalled": false,\n "archived": false\n }\n },]\n\nHow can I "unwrap" nodes so that, let\'s say a constant `nodes` would contain an array of nodes like: [\n {\n "id": "gid://gitlab/Ai::DuoWorkflows::Workflow/1031434",\n "projectId": "gid://gitlab/Project/62039593",\n "humanStatus": "input required",\n "updatedAt": "2025-07-20T19:27:15Z",\n "createdAt": "2025-07-20T18:51:44Z",\n "goal": "Hel",\n "stalled": false,\n "archived": false\n },\n {\n "id": "gid://gitlab/Ai::DuoWorkflows::Workflow/1031206",\n "projectId": "gid://gitlab/Project/62039593",\n "humanStatus": "input required",\n "updatedAt": "2025-07-19T12:20:31Z",\n "createdAt": "2025-07-19T12:15:49Z",\n "goal": "Hel",\n "stalled": false,\n "archived": false\n },]?',
736
- stalled: false,
737
- archived: false,
738
- firstCheckpoint: {
739
- checkpoint: '{"v":3,"id":"1f0660ac-f31d-611f-bfff-989cc966f3d3","ts":"2025-07-21T08:15:06.033987+00:00","pending_sends":[],"versions_seen":{"__input__":{}},"channel_values":{"__start__":{"plan":{"steps":[]},"status":"Not Started","project":{"id":278964,"name":"GitLab","web_url":"https://gitlab.com/gitlab-org/gitlab","languages":[{"name":"Ruby","share":68.37},{"name":"JavaScript","share":19.23},{"name":"Vue","share":8.04},{"name":"PLpgSQL","share":1.86},{"name":"Haml","share":1.22}],"description":"GitLab is an open source end-to-end software development platform with built-in version control, issue tracking, code review, CI/CD, and more. Self-host GitLab on your own servers, in a container, or on a cloud provider.","http_url_to_repo":"https://gitlab.com/gitlab-org/gitlab.git"},"approval":null,"ui_chat_log":[{"status":"success","content":"I have the following data structure: \\"edges\\": [\\n {\\n \\"node\\": {\\n \\"id\\": \\"gid://gitlab/Ai::DuoWorkflows::Workflow/1031434\\",\\n \\"projectId\\": \\"gid://gitlab/Project/62039593\\",\\n \\"humanStatus\\": \\"input required\\",\\n \\"updatedAt\\": \\"2025-07-20T19:27:15Z\\",\\n \\"createdAt\\": \\"2025-07-20T18:51:44Z\\",\\n \\"goal\\": \\"Hel\\",\\n \\"stalled\\": false,\\n \\"archived\\": false\\n }\\n },\\n {\\n \\"node\\": {\\n \\"id\\": \\"gid://gitlab/Ai::DuoWorkflows::Workflow/1031206\\",\\n \\"projectId\\": \\"gid://gitlab/Project/62039593\\",\\n \\"humanStatus\\": \\"input required\\",\\n \\"updatedAt\\": \\"2025-07-19T12:20:31Z\\",\\n \\"createdAt\\": \\"2025-07-19T12:15:49Z\\",\\n \\"goal\\": \\"Hel\\",\\n \\"stalled\\": false,\\n \\"archived\\": false\\n }\\n },]\\n\\nHow can I \\"unwrap\\" nodes so that, let\'s say a constant `nodes` would contain an array of nodes like: [\\n {\\n \\"id\\": \\"gid://gitlab/Ai::DuoWorkflows::Workflow/1031434\\",\\n \\"projectId\\": \\"gid://gitlab/Project/62039593\\",\\n \\"humanStatus\\": \\"input required\\",\\n \\"updatedAt\\": \\"2025-07-20T19:27:15Z\\",\\n \\"createdAt\\": \\"2025-07-20T18:51:44Z\\",\\n \\"goal\\": \\"Hel\\",\\n \\"stalled\\": false,\\n \\"archived\\": false\\n },\\n {\\n \\"id\\": \\"gid://gitlab/Ai::DuoWorkflows::Workflow/1031206\\",\\n \\"projectId\\": \\"gid://gitlab/Project/62039593\\",\\n \\"humanStatus\\": \\"input required\\",\\n \\"updatedAt\\": \\"2025-07-19T12:20:31Z\\",\\n \\"createdAt\\": \\"2025-07-19T12:15:49Z\\",\\n \\"goal\\": \\"Hel\\",\\n \\"stalled\\": false,\\n \\"archived\\": false\\n },]?","timestamp":"2025-07-21T08:15:05.647932+00:00","tool_info":null,"message_type":"user","correlation_id":null,"message_sub_type":null,"additional_context":null}],"last_human_input":null,"conversation_history":{"Chat Agent":[{"id":null,"name":null,"type":"HumanMessage","content":"I have the following data structure: \\"edges\\": [\\n {\\n \\"node\\": {\\n \\"id\\": \\"gid://gitlab/Ai::DuoWorkflows::Workflow/1031434\\",\\n \\"projectId\\": \\"gid://gitlab/Project/62039593\\",\\n \\"humanStatus\\": \\"input required\\",\\n \\"updatedAt\\": \\"2025-07-20T19:27:15Z\\",\\n \\"createdAt\\": \\"2025-07-20T18:51:44Z\\",\\n \\"goal\\": \\"Hel\\",\\n \\"stalled\\": false,\\n \\"archived\\": false\\n }\\n },\\n {\\n \\"node\\": {\\n \\"id\\": \\"gid://gitlab/Ai::DuoWorkflows::Workflow/1031206\\",\\n \\"projectId\\": \\"gid://gitlab/Project/62039593\\",\\n \\"humanStatus\\": \\"input required\\",\\n \\"updatedAt\\": \\"2025-07-19T12:20:31Z\\",\\n \\"createdAt\\": \\"2025-07-19T12:15:49Z\\",\\n \\"goal\\": \\"Hel\\",\\n \\"stalled\\": false,\\n \\"archived\\": false\\n }\\n },]\\n\\nHow can I \\"unwrap\\" nodes so that, let\'s say a constant `nodes` would contain an array of nodes like: [\\n {\\n \\"id\\": \\"gid://gitlab/Ai::DuoWorkflows::Workflow/1031434\\",\\n \\"projectId\\": \\"gid://gitlab/Project/62039593\\",\\n \\"humanStatus\\": \\"input required\\",\\n \\"updatedAt\\": \\"2025-07-20T19:27:15Z\\",\\n \\"createdAt\\": \\"2025-07-20T18:51:44Z\\",\\n \\"goal\\": \\"Hel\\",\\n \\"stalled\\": false,\\n \\"archived\\": false\\n },\\n {\\n \\"id\\": \\"gid://gitlab/Ai::DuoWorkflows::Workflow/1031206\\",\\n \\"projectId\\": \\"gid://gitlab/Project/62039593\\",\\n \\"humanStatus\\": \\"input required\\",\\n \\"updatedAt\\": \\"2025-07-19T12:20:31Z\\",\\n \\"createdAt\\": \\"2025-07-19T12:15:49Z\\",\\n \\"goal\\": \\"Hel\\",\\n \\"stalled\\": false,\\n \\"archived\\": false\\n },]?","example":false,"additional_kwargs":{"additional_context":null},"response_metadata":{}}]}}},"channel_versions":{"__start__":1}}'
740
- }
727
+ __typename: 'DuoWorkflow',
728
+ id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1796032',
729
+ lastUpdatedAt: '2025-01-31T17:40:02Z',
730
+ title: 'Analyze repository activity for the past week',
731
+ aiCatalogItemVersionId: null,
732
+ agentName: 'Data Analyst'
741
733
  }, {
742
- id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1031206',
743
- projectId: 'gid://gitlab/Project/62039593',
744
- humanStatus: 'input required',
745
- updatedAt: '2025-01-31T08:15:32Z',
746
- goal: 'Help me introduce translation support for the selected string using the Vue-18n dependency',
747
- stalled: false,
748
- archived: false,
749
- firstCheckpoint: {
750
- checkpoint: '{"v":3,"id":"1f0649a2-cee3-6c86-bfff-b35ddd3c4901","ts":"2025-07-19T12:16:19.003703+00:00","pending_sends":[],"versions_seen":{"__input__":{}},"channel_values":{"__start__":{"plan":{"steps":[]},"status":"Not Started","project":{"id":62039593,"name":"Duo UI","web_url":"https://gitlab.com/gitlab-org/duo-ui","languages":[{"name":"JavaScript","share":72.16},{"name":"Vue","share":22.06},{"name":"SCSS","share":2.68},{"name":"Ruby","share":1.54},{"name":"TypeScript","share":0.6}],"description":"","http_url_to_repo":"https://gitlab.com/gitlab-org/duo-ui.git"},"approval":null,"ui_chat_log":[{"status":"success","content":"Help me introduce translation support for the selected string using the Vue-18n dependency","timestamp":"2025-07-19T12:16:18.708768+00:00","tool_info":null,"message_type":"user","correlation_id":null,"message_sub_type":null,"additional_context":[{"id":"editor_selection:src/components/custom/duo_chat_message_sources/duo_chat_message_sources.vue_893edb37-6d20-4f81-83eb-2f5fbb290609","type":"AdditionalContext","content":" return count === 1 ? \'Source\' : \'Sources\';","category":"snippet","metadata":{"icon":"selection","title":"Selected text in src/components/custom/duo_chat_message_sources/duo_chat_message_sources.vue","enabled":true,"subType":"snippet","fileName":"src/components/custom/duo_chat_message_sources/duo_chat_message_sources.vue","subTypeLabel":"Editor Selection","secondaryText":"src/components/custom/duo_chat_message_sources/duo_chat_message_sources.vue"}},{"id":"1","type":"AdditionalContext","content":"The user wants you to adhere to these rules:\\nThe project is built with Vue 3, Typescript, Tailwind, shadcn-vue and other modern technologies.\\n\\nFor some transient time, this project is used to migrate legacy Vue 2 + JS + gitlab-ui components to the new tech stack. While migrating components all of the gitlab-ui components should be replaced with the shadcn-ui analogues or explicitly agreed with the user. If you see any better analogue in shadcn-ui or better way to implement functionality, speak up and ask for user\'s confirmation on what path to take.\\n\\nEvery string that is meant to be output in the UI, should be translated. The package is using Vue-18 dependency for translations.\\n\\nEvery component should have a story and a test spec alongside itself.","category":"user_rule","metadata":{"icon":"user","title":"User instruction","enabled":true,"subType":"user_rule","subTypeLabel":"User instruction","secondaryText":"chat-rules.md"}}]}],"last_human_input":null,"conversation_history":{"Chat Agent":[{"id":null,"name":null,"type":"HumanMessage","content":"Help me introduce translation support for the selected string using the Vue-18n dependency","example":false,"additional_kwargs":{"additional_context":[{"id":"editor_selection:src/components/custom/duo_chat_message_sources/duo_chat_message_sources.vue_893edb37-6d20-4f81-83eb-2f5fbb290609","content":" return count === 1 ? \'Source\' : \'Sources\';","category":"snippet","metadata":{"icon":"selection","title":"Selected text in src/components/custom/duo_chat_message_sources/duo_chat_message_sources.vue","enabled":true,"subType":"snippet","fileName":"src/components/custom/duo_chat_message_sources/duo_chat_message_sources.vue","subTypeLabel":"Editor Selection","secondaryText":"src/components/custom/duo_chat_message_sources/duo_chat_message_sources.vue"}},{"id":"1","content":"The user wants you to adhere to these rules:\\nThe project is built with Vue 3, Typescript, Tailwind, shadcn-vue and other modern technologies.\\n\\nFor some transient time, this project is used to migrate legacy Vue 2 + JS + gitlab-ui components to the new tech stack. While migrating components all of the gitlab-ui components should be replaced with the shadcn-ui analogues or explicitly agreed with the user. If you see any better analogue in shadcn-ui or better way to implement functionality, speak up and ask for user\'s confirmation on what path to take.\\n\\nEvery string that is meant to be output in the UI, should be translated. The package is using Vue-18 dependency for translations.\\n\\nEvery component should have a story and a test spec alongside itself.","category":"user_rule","metadata":{"icon":"user","title":"User instruction","enabled":true,"subType":"user_rule","subTypeLabel":"User instruction","secondaryText":"chat-rules.md"}}]},"response_metadata":{}}]}}},"channel_versions":{"__start__":1}}'
751
- }
734
+ __typename: 'DuoWorkflow',
735
+ id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1795886',
736
+ lastUpdatedAt: '2025-01-31T17:17:44Z',
737
+ title: 'Create a new Vue component for the dashboard',
738
+ aiCatalogItemVersionId: null,
739
+ agentName: 'GitLab Duo'
752
740
  }, {
753
- id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1031041',
754
- projectId: 'gid://gitlab/Project/62039593',
755
- humanStatus: 'failed',
756
- updatedAt: '2025-01-15T20:35:23Z',
757
- goal: 'I need your help migrating the src/components/custom/duo_chat_message_sources folder (component, story, and the test), that were copied over from a legacy project to the tech stack used in this project. Can you help?',
758
- stalled: false,
759
- archived: false,
760
- firstCheckpoint: {
761
- checkpoint: '{"v":3,"id":"1f064155-71df-6f90-bfff-eaa94aa27ec1","ts":"2025-07-18T20:25:26.715981+00:00","pending_sends":[],"versions_seen":{"__input__":{}},"channel_values":{"__start__":{"plan":{"steps":[]},"status":"Not Started","project":{"id":62039593,"name":"Duo UI","web_url":"https://gitlab.com/gitlab-org/duo-ui","languages":[{"name":"JavaScript","share":72.16},{"name":"Vue","share":22.06},{"name":"SCSS","share":2.68},{"name":"Ruby","share":1.54},{"name":"TypeScript","share":0.6}],"description":"","http_url_to_repo":"https://gitlab.com/gitlab-org/duo-ui.git"},"approval":null,"ui_chat_log":[{"status":"success","content":"I need your help migrating the src/components/custom/duo_chat_message_sources folder (component, story, and the test), that were copied over from a legacy project to the tech stack used in this project. Can you help?","timestamp":"2025-07-18T20:25:26.401616+00:00","tool_info":null,"message_type":"user","correlation_id":null,"message_sub_type":null,"additional_context":null}],"last_human_input":null,"conversation_history":{"Chat Agent":[{"id":null,"name":null,"type":"HumanMessage","content":"I need your help migrating the src/components/custom/duo_chat_message_sources folder (component, story, and the test), that were copied over from a legacy project to the tech stack used in this project. Can you help?","example":false,"additional_kwargs":{"additional_context":null},"response_metadata":{}}]}}},"channel_versions":{"__start__":1}}'
762
- }
741
+ __typename: 'DuoWorkflow',
742
+ id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1780932',
743
+ lastUpdatedAt: '2025-01-24T15:38:40Z',
744
+ title: 'How do I configure the CI/CD pipeline for deployment?',
745
+ aiCatalogItemVersionId: null,
746
+ agentName: 'GitLab Duo'
763
747
  }, {
764
- id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1030377',
765
- projectId: 'gid://gitlab/Project/46519181',
766
- humanStatus: 'input required',
767
- updatedAt: '2025-01-15T12:03:06Z',
768
- goal: "How should I update the CSP derectives to allow images from `https://secure.gravatar.com/avatar/`? I've tried with the selected update, but it doesn't work - I get the \"The source list for the Content Security Policy directive 'img-src' contains an invalid source: ''secure.gravatar.com''. It will be ignored.\" error. Can you help me fix this and allow images from that domain?",
769
- stalled: false,
770
- archived: false,
771
- firstCheckpoint: {
772
- checkpoint: '{"v":3,"id":"1f063cf2-1522-60d4-bfff-b222b997066b","ts":"2025-07-18T12:02:51.689588+00:00","pending_sends":[],"versions_seen":{"__input__":{}},"channel_values":{"__start__":{"plan":{"steps":[]},"status":"Not Started","project":{"id":46519181,"name":"GitLab Language Server","web_url":"https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp","languages":[{"name":"TypeScript","share":79.66},{"name":"JavaScript","share":12.25},{"name":"Vue","share":5.62},{"name":"SCSS","share":2.01},{"name":"Shell","share":0.38}],"description":"","http_url_to_repo":"https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp.git"},"approval":null,"ui_chat_log":[{"status":"success","content":"How should I update the CSP derectives to allow images from `https://secure.gravatar.com/avatar/`? I\'ve tried with the selected update, but it doesn\'t work - I get the \\"The source list for the Content Security Policy directive \'img-src\' contains an invalid source: \'\'secure.gravatar.com\'\'. It will be ignored.\\" error. Can you help me fix this and allow images from that domain?","timestamp":"2025-07-18T12:02:51.347774+00:00","tool_info":null,"message_type":"user","correlation_id":null,"message_sub_type":null,"additional_context":[{"id":"editor_selection:src/common/webview/html/utils/csp_builder.ts_cd5c7d74-f642-4b6f-ac74-5aacff408dd6","type":"AdditionalContext","content":" \'img-src\': [\\"\'self\'\\", \\"\'secure.gravatar.com\'\\"],","category":"snippet","metadata":{"icon":"selection","title":"Selected text in src/common/webview/html/utils/csp_builder.ts","enabled":true,"subType":"snippet","fileName":"src/common/webview/html/utils/csp_builder.ts","subTypeLabel":"Editor Selection","secondaryText":"src/common/webview/html/utils/csp_builder.ts"}}]}],"last_human_input":null,"conversation_history":{"Chat Agent":[{"id":null,"name":null,"type":"HumanMessage","content":"How should I update the CSP derectives to allow images from `https://secure.gravatar.com/avatar/`? I\'ve tried with the selected update, but it doesn\'t work - I get the \\"The source list for the Content Security Policy directive \'img-src\' contains an invalid source: \'\'secure.gravatar.com\'\'. It will be ignored.\\" error. Can you help me fix this and allow images from that domain?","example":false,"additional_kwargs":{"additional_context":[{"id":"editor_selection:src/common/webview/html/utils/csp_builder.ts_cd5c7d74-f642-4b6f-ac74-5aacff408dd6","content":" \'img-src\': [\\"\'self\'\\", \\"\'secure.gravatar.com\'\\"],","category":"snippet","metadata":{"icon":"selection","title":"Selected text in src/common/webview/html/utils/csp_builder.ts","enabled":true,"subType":"snippet","fileName":"src/common/webview/html/utils/csp_builder.ts","subTypeLabel":"Editor Selection","secondaryText":"src/common/webview/html/utils/csp_builder.ts"}}]},"response_metadata":{}}]}}},"channel_versions":{"__start__":1}}'
773
- }
748
+ __typename: 'DuoWorkflow',
749
+ id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1774141',
750
+ lastUpdatedAt: '2025-01-24T20:24:45Z',
751
+ title: 'Show me merge request statistics for the team',
752
+ aiCatalogItemVersionId: null,
753
+ agentName: 'Data Analyst'
774
754
  }, {
775
- id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1029369',
776
- projectId: 'gid://gitlab/Project/7071551',
777
- humanStatus: 'input required',
778
- updatedAt: '2025-01-08T15:55:58Z',
779
- goal: 'explain this to me',
780
- stalled: false,
781
- archived: false,
782
- firstCheckpoint: {
783
- checkpoint: '{"v":3,"id":"1f063217-75c6-6ace-bfff-9c250f04abb6","ts":"2025-07-17T15:19:43.610124+00:00","pending_sends":[],"versions_seen":{"__input__":{}},"channel_values":{"__start__":{"plan":{"steps":[]},"status":"Not Started","project":{"id":7071551,"name":"gitlab-ui","web_url":"https://gitlab.com/gitlab-org/gitlab-ui","languages":[{"name":"JavaScript","share":56.13},{"name":"Vue","share":19.71},{"name":"SCSS","share":15.81},{"name":"CSS","share":7.21},{"name":"Ruby","share":0.39}],"description":"Development of this project has moved to https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com.\\r\\n\\r\\nSee https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/issues/2035 for more information.","http_url_to_repo":"https://gitlab.com/gitlab-org/gitlab-ui.git"},"approval":null,"ui_chat_log":[{"status":"success","content":"foo bar","timestamp":"2025-07-17T15:19:43.272681+00:00","tool_info":null,"message_type":"user","correlation_id":null,"message_sub_type":null,"additional_context":null}],"last_human_input":null,"conversation_history":{"Chat Agent":[{"id":null,"name":null,"type":"HumanMessage","content":"foo bar","example":false,"additional_kwargs":{"additional_context":null},"response_metadata":{}}]}}},"channel_versions":{"__start__":1}}'
784
- }
755
+ __typename: 'DuoWorkflow',
756
+ id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1759516',
757
+ lastUpdatedAt: '2025-01-15T16:57:52Z',
758
+ title: 'Find documentation about API rate limiting',
759
+ aiCatalogItemVersionId: null,
760
+ agentName: 'GitLab Duo'
785
761
  }, {
786
- id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1029334',
787
- projectId: 'gid://gitlab/Project/7071551',
788
- humanStatus: 'input required',
789
- updatedAt: '2025-01-08T15:19:49Z',
790
- goal: 'foo bar',
791
- stalled: false,
792
- archived: false,
793
- firstCheckpoint: {
794
- checkpoint: '{"v":3,"id":"1f063217-75c6-6ace-bfff-9c250f04abb6","ts":"2025-07-17T15:19:43.610124+00:00","pending_sends":[],"versions_seen":{"__input__":{}},"channel_values":{"__start__":{"plan":{"steps":[]},"status":"Not Started","project":{"id":7071551,"name":"gitlab-ui","web_url":"https://gitlab.com/gitlab-org/gitlab-ui","languages":[{"name":"JavaScript","share":56.13},{"name":"Vue","share":19.71},{"name":"SCSS","share":15.81},{"name":"CSS","share":7.21},{"name":"Ruby","share":0.39}],"description":"Development of this project has moved to https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com.\\r\\n\\r\\nSee https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/issues/2035 for more information.","http_url_to_repo":"https://gitlab.com/gitlab-org/gitlab-ui.git"},"approval":null,"ui_chat_log":[{"status":"success","content":"foo bar","timestamp":"2025-07-17T15:19:43.272681+00:00","tool_info":null,"message_type":"user","correlation_id":null,"message_sub_type":null,"additional_context":null}],"last_human_input":null,"conversation_history":{"Chat Agent":[{"id":null,"name":null,"type":"HumanMessage","content":"foo bar","example":false,"additional_kwargs":{"additional_context":null},"response_metadata":{}}]}}},"channel_versions":{"__start__":1}}'
795
- }
762
+ __typename: 'DuoWorkflow',
763
+ id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1743262',
764
+ lastUpdatedAt: '2025-01-15T17:14:49Z',
765
+ title: 'Troubleshoot this broken pipeline',
766
+ aiCatalogItemVersionId: null,
767
+ agentName: 'GitLab Duo'
796
768
  }, {
797
- id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1029330',
798
- projectId: 'gid://gitlab/Project/7071551',
799
- humanStatus: 'input required',
800
- updatedAt: '2025-01-08T15:17:28Z',
801
- goal: 'test me',
802
- stalled: false,
803
- archived: false,
804
- firstCheckpoint: {
805
- checkpoint: '{"v":3,"id":"1f063212-2bac-68c0-bfff-fc55ae272eb1","ts":"2025-07-17T15:17:21.622232+00:00","pending_sends":[],"versions_seen":{"__input__":{}},"channel_values":{"__start__":{"plan":{"steps":[]},"status":"Not Started","project":{"id":7071551,"name":"gitlab-ui","web_url":"https://gitlab.com/gitlab-org/gitlab-ui","languages":[{"name":"JavaScript","share":56.13},{"name":"Vue","share":19.71},{"name":"SCSS","share":15.81},{"name":"CSS","share":7.21},{"name":"Ruby","share":0.39}],"description":"Development of this project has moved to https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com.\\r\\n\\r\\nSee https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/issues/2035 for more information.","http_url_to_repo":"https://gitlab.com/gitlab-org/gitlab-ui.git"},"approval":null,"ui_chat_log":[{"status":"success","content":"test me","timestamp":"2025-07-17T15:17:21.275711+00:00","tool_info":null,"message_type":"user","correlation_id":null,"message_sub_type":null,"additional_context":null}],"last_human_input":null,"conversation_history":{"Chat Agent":[{"id":null,"name":null,"type":"HumanMessage","content":"test me","example":false,"additional_kwargs":{"additional_context":null},"response_metadata":{}}]}}},"channel_versions":{"__start__":1}}'
806
- }
769
+ __typename: 'DuoWorkflow',
770
+ id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1685676',
771
+ lastUpdatedAt: '2025-01-08T14:24:16Z',
772
+ title: 'Explain the error handling patterns used in this codebase',
773
+ aiCatalogItemVersionId: null,
774
+ agentName: 'GitLab Duo'
807
775
  }, {
808
- id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1028684',
809
- projectId: 'gid://gitlab/Project/46519181',
810
- humanStatus: 'input required',
811
- updatedAt: '2025-01-08T22:16:28Z',
812
- goal: 'In the `packages/lib_webview_agentic_chat/src/app/common/chat.test.js` file, help me fill out the "provides avatarUrl to the underlying components" and the "provides renderGFM to the underlying components" test placeholders based on the implementation in `packages/lib_webview_agentic_chat/src/app/common/chat.vue`',
813
- stalled: false,
814
- archived: false,
815
- firstCheckpoint: {
816
- checkpoint: '{"v":3,"id":"1f062927-1357-6124-bfff-af05cc284fdb","ts":"2025-07-16T22:15:55.256032+00:00","pending_sends":[],"versions_seen":{"__input__":{}},"channel_values":{"__start__":{"plan":{"steps":[]},"status":"Not Started","project":{"id":46519181,"name":"GitLab Language Server","web_url":"https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp","languages":[{"name":"TypeScript","share":79.68},{"name":"JavaScript","share":12.26},{"name":"Vue","share":5.33},{"name":"SCSS","share":2.26},{"name":"Shell","share":0.38}],"description":"","http_url_to_repo":"https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp.git"},"approval":null,"ui_chat_log":[{"status":"success","content":"In the `packages/lib_webview_agentic_chat/src/app/common/chat.test.js` file, help me fill out the \\"provides avatarUrl to the underlying components\\" and the \\"provides renderGFM to the underlying components\\" test placeholders based on the implementation in `packages/lib_webview_agentic_chat/src/app/common/chat.vue`","timestamp":"2025-07-16T22:15:54.359309+00:00","tool_info":null,"message_type":"user","correlation_id":null,"message_sub_type":null,"additional_context":[{"id":"editor_selection:packages/lib_webview_agentic_chat/src/app/common/chat.test.js_b5815a3e-099c-466d-9ef0-f48536f69ddd","type":"AdditionalContext","content":"provides renderGFM to the underlying components","category":"snippet","metadata":{"icon":"selection","title":"Selected text in packages/lib_webview_agentic_chat/src/app/common/chat.test.js","enabled":true,"subType":"snippet","fileName":"packages/lib_webview_agentic_chat/src/app/common/chat.test.js","subTypeLabel":"Editor Selection","secondaryText":"packages/lib_webview_agentic_chat/src/app/common/chat.test.js"}}]}],"last_human_input":null,"conversation_history":{"Chat Agent":[{"id":null,"name":null,"type":"HumanMessage","content":"In the `packages/lib_webview_agentic_chat/src/app/common/chat.test.js` file, help me fill out the \\"provides avatarUrl to the underlying components\\" and the \\"provides renderGFM to the underlying components\\" test placeholders based on the implementation in `packages/lib_webview_agentic_chat/src/app/common/chat.vue`","example":false,"additional_kwargs":{"additional_context":[{"id":"editor_selection:packages/lib_webview_agentic_chat/src/app/common/chat.test.js_b5815a3e-099c-466d-9ef0-f48536f69ddd","content":"provides renderGFM to the underlying components","category":"snippet","metadata":{"icon":"selection","title":"Selected text in packages/lib_webview_agentic_chat/src/app/common/chat.test.js","enabled":true,"subType":"snippet","fileName":"packages/lib_webview_agentic_chat/src/app/common/chat.test.js","subTypeLabel":"Editor Selection","secondaryText":"packages/lib_webview_agentic_chat/src/app/common/chat.test.js"}}]},"response_metadata":{}}]}}},"channel_versions":{"__start__":1}}'
817
- }
776
+ __typename: 'DuoWorkflow',
777
+ id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1678431',
778
+ lastUpdatedAt: '2025-01-08T13:45:15Z',
779
+ title: 'Review the testing guidelines for frontend components',
780
+ aiCatalogItemVersionId: null,
781
+ agentName: 'GitLab Duo'
818
782
  }, {
819
- id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1028594',
820
- projectId: 'gid://gitlab/Project/46519181',
821
- humanStatus: 'tool call approval required',
822
- updatedAt: '2025-01-08T20:03:24Z',
823
- goal: "In the current project I need to ensure that a webview in packages/lib_webview_agentic_chat has information about `avatarUrl` of the currently logged in user. The GraphQl query to get that information is in user_service (src/common/core/services/user_service.ts). Can you help me connect that service to the webview somehow? I would need to get that information sent down to the webview as part of the `pluginToWebview` communication channel, I guess. But please analyze all the options and let's see how far we can get",
824
- stalled: false,
825
- archived: false,
826
- firstCheckpoint: {
827
- checkpoint: '{"v":3,"id":"1f0627f5-1510-677c-bfff-624b1a456de4","ts":"2025-07-16T19:59:01.311877+00:00","pending_sends":[],"versions_seen":{"__input__":{}},"channel_values":{"__start__":{"plan":{"steps":[]},"status":"Not Started","project":{"id":46519181,"name":"GitLab Language Server","web_url":"https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp","languages":[{"name":"TypeScript","share":79.68},{"name":"JavaScript","share":12.26},{"name":"Vue","share":5.33},{"name":"SCSS","share":2.26},{"name":"Shell","share":0.38}],"description":"","http_url_to_repo":"https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp.git"},"approval":null,"ui_chat_log":[{"status":"success","content":"In the current project I need to ensure that a webview in packages/lib_webview_agentic_chat has information about `avatarUrl` of the currently logged in user. The GraphQl query to get that information is in user_service (src/common/core/services/user_service.ts). Can you help me connect that service to the webview somehow? I would need to get that information sent down to the webview as part of the `pluginToWebview` communication channel, I guess. But please analyze all the options and let\'s see how far we can get","timestamp":"2025-07-16T19:59:00.775754+00:00","tool_info":null,"message_type":"user","correlation_id":null,"message_sub_type":null,"additional_context":[{"id":"editor_selection:src/common/core/services/user_service.ts_22d20969-dfd7-4b78-9dac-c63de2f559ea","type":"AdditionalContext","content":"DefaultUserService","category":"snippet","metadata":{"icon":"selection","title":"Selected text in src/common/core/services/user_service.ts","enabled":true,"subType":"snippet","fileName":"src/common/core/services/user_service.ts","subTypeLabel":"Editor Selection","secondaryText":"src/common/core/services/user_service.ts"}}]}],"last_human_input":null,"conversation_history":{"Chat Agent":[{"id":null,"name":null,"type":"HumanMessage","content":"In the current project I need to ensure that a webview in packages/lib_webview_agentic_chat has information about `avatarUrl` of the currently logged in user. The GraphQl query to get that information is in user_service (src/common/core/services/user_service.ts). Can you help me connect that service to the webview somehow? I would need to get that information sent down to the webview as part of the `pluginToWebview` communication channel, I guess. But please analyze all the options and let\'s see how far we can get","example":false,"additional_kwargs":{"additional_context":[{"id":"editor_selection:src/common/core/services/user_service.ts_22d20969-dfd7-4b78-9dac-c63de2f559ea","content":"DefaultUserService","category":"snippet","metadata":{"icon":"selection","title":"Selected text in src/common/core/services/user_service.ts","enabled":true,"subType":"snippet","fileName":"src/common/core/services/user_service.ts","subTypeLabel":"Editor Selection","secondaryText":"src/common/core/services/user_service.ts"}}]},"response_metadata":{}}]}}},"channel_versions":{"__start__":1}}'
828
- }
783
+ __typename: 'DuoWorkflow',
784
+ id: 'gid://gitlab/Ai::DuoWorkflows::Workflow/1282107',
785
+ lastUpdatedAt: '2025-01-08T10:39:16Z',
786
+ title: 'Search for related issues and create a summary',
787
+ aiCatalogItemVersionId: 'gid://gitlab/Ai::Catalog::ItemVersion/656',
788
+ agentName: 'Issue Tracker Agent'
829
789
  }];
830
790
 
831
791
  export { AGENTIC_THREADLIST, INCLUDE_SLASH_COMMAND, MOCK_AGENT_MESSAGE, MOCK_AGENT_MESSAGE_WITH_LONG_CODE_BLOCK, MOCK_AGENT_MESSAGE_WITH_MARKDOWN, 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_MESSAGE_ONLY, 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_ERROR_RESPONSE, 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_MERGE_REQUEST, 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_TOOL_MESSAGE_WITH_REQUEST_AND_RESPONSE_DETAILS, MOCK_USER_PROMPT_MESSAGE, MOCK_WORKFLOW_END_MESSAGE, SLASH_COMMANDS, THREADLIST, generateMockResponseChunks, generateSeparateChunks, renderGFM, renderMarkdown };