@gitlab/duo-ui 14.0.0 → 14.1.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 (17) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/components/chat/components/duo_chat_message_tool_approval/components/base_tool_params.js +167 -5
  3. package/dist/components/chat/components/duo_chat_message_tool_approval/components/create_commit_tool_params.js +12 -18
  4. package/dist/components/chat/components/duo_chat_message_tool_approval/components/default_tool_params.js +89 -0
  5. package/dist/components/chat/components/duo_chat_message_tool_approval/components/tool_params_json_view.js +63 -0
  6. package/dist/components/chat/components/duo_chat_message_tool_approval/message_tool_approval.js +8 -40
  7. package/dist/components/chat/mock_data.js +18 -2
  8. package/package.json +1 -1
  9. package/src/components/chat/components/duo_chat_message_tool_approval/components/base_tool_params.vue +138 -10
  10. package/src/components/chat/components/duo_chat_message_tool_approval/components/create_commit_tool_params.vue +14 -16
  11. package/src/components/chat/components/duo_chat_message_tool_approval/components/default_tool_params.vue +72 -0
  12. package/src/components/chat/components/duo_chat_message_tool_approval/components/tool_params_json_view.vue +42 -0
  13. package/src/components/chat/components/duo_chat_message_tool_approval/message_tool_approval.vue +7 -99
  14. package/src/components/chat/mock_data.js +18 -0
  15. package/translations.js +23 -40
  16. package/dist/components/chat/components/duo_chat_message_tool_approval/components/issuable_tool_params.js +0 -174
  17. package/src/components/chat/components/duo_chat_message_tool_approval/components/issuable_tool_params.vue +0 -193
@@ -1,14 +1,68 @@
1
1
  <script>
2
- import { GlAccordion, GlAccordionItem, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
2
+ import { GlAccordion, GlAccordionItem, GlBadge, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
3
3
  import { translate } from '../../../../../utils/i18n';
4
4
  import PreBlock from './pre_block.vue';
5
+ import ToolParamsJsonView from './tool_params_json_view.vue';
6
+
7
+ const projectLabel = translate('BaseToolParams.projectLabel', 'Project');
8
+ const groupLabel = translate('BaseToolParams.groupLabel', 'Group');
9
+ const issueLabel = translate('BaseToolParams.issueLabel', 'Issue');
10
+ const mergeRequestLabel = translate('BaseToolParams.mergeRequestLabel', 'Merge request');
11
+ const workItemLabel = translate('BaseToolParams.workItemLabel', 'Work item');
12
+ const epicLabel = translate('BaseToolParams.epicLabel', 'Epic');
13
+ const sourceBranchLabel = translate('BaseToolParams.sourceBranchLabel', 'Source branch');
14
+ const targetBranchLabel = translate('BaseToolParams.targetBranchLabel', 'Target branch');
15
+ const startDateLabel = translate('BaseToolParams.startDateLabel', 'Start date');
16
+ const dueDateLabel = translate('BaseToolParams.dueDateLabel', 'Due date');
17
+ const healthStatusLabel = translate('BaseToolParams.healthStatusLabel', 'Health status');
18
+ const labelsLabel = translate('BaseToolParams.labelsLabel', 'Labels');
19
+ const vulnerabilityLabel = translate('BaseToolParams.vulnerabilityLabel', 'Vulnerability');
20
+ const dismissalReasonLabel = translate('BaseToolParams.dismissalReasonLabel', 'Dismissal reason');
21
+ const stateLabel = translate('BaseToolParams.stateLabel', 'State');
22
+ const confidentialLabel = translate('BaseToolParams.confidentialLabel', 'Confidential');
23
+ const typeLabel = translate('BaseToolParams.typeLabel', 'Type');
24
+
25
+ const metadataProperties = {
26
+ projectId: {
27
+ icon: 'project',
28
+ label: projectLabel,
29
+ },
30
+ projectPath: { icon: 'project', label: projectLabel },
31
+ projectFullPath: { icon: 'project', label: projectLabel },
32
+ groupId: { icon: 'group', label: groupLabel },
33
+ groupPath: { icon: 'group', label: groupLabel },
34
+ issueId: { icon: 'issues', label: issueLabel },
35
+ issueIid: { icon: 'issues', label: issueLabel },
36
+ mergeRequestId: { icon: 'merge-request', label: mergeRequestLabel },
37
+ mergeRequestIid: { icon: 'merge-request', label: mergeRequestLabel },
38
+ workItemIid: { icon: 'work-items', label: workItemLabel },
39
+ epicIid: { icon: 'epics', label: epicLabel },
40
+ sourceBranch: { icon: 'branch', label: sourceBranchLabel },
41
+ targetBranch: { icon: 'branch', label: targetBranchLabel },
42
+ url: { icon: 'external-link', type: 'url' },
43
+ startDate: { icon: 'calendar', label: startDateLabel },
44
+ dueDate: { icon: 'calendar', label: dueDateLabel },
45
+ healthStatus: { icon: 'status-health', label: healthStatusLabel },
46
+ state: {
47
+ label: stateLabel,
48
+ icon: (value) => (value === 'opened' ? 'status_open' : 'status_closed'),
49
+ },
50
+ labels: { icon: 'labels', label: labelsLabel },
51
+ addLabelIds: { icon: 'labels', label: labelsLabel },
52
+ confidential: { icon: (value) => (value ? 'eye-slash' : 'eye'), label: confidentialLabel },
53
+ typeName: { icon: (value) => `work-item-${value.toLowerCase()}`, label: typeLabel },
54
+ vulnerabilityId: { label: vulnerabilityLabel },
55
+ dismissalReason: { icon: 'information', label: dismissalReasonLabel },
56
+ };
5
57
 
6
58
  export default {
7
59
  name: 'BaseToolParams',
8
60
  components: {
9
61
  GlAccordion,
10
62
  GlAccordionItem,
63
+ GlBadge,
11
64
  PreBlock,
65
+ ToolParamsJsonView,
12
66
  },
13
67
  directives: {
14
68
  SafeHtml,
@@ -24,32 +78,106 @@ export default {
24
78
  required: false,
25
79
  default: '',
26
80
  },
81
+ toolParams: {
82
+ type: Object,
83
+ required: false,
84
+ default: () => {},
85
+ },
27
86
  customAccordionTitle: {
28
87
  type: String,
29
88
  required: false,
30
89
  default: '',
31
90
  },
91
+ withJsonView: {
92
+ type: Boolean,
93
+ required: false,
94
+ default: false,
95
+ },
32
96
  },
33
97
  computed: {
34
98
  accordionTitle() {
35
- return this.customAccordionTitle || this.$options.i18n.ACCORDION_TITLE;
99
+ return this.customAccordionTitle || this.$options.i18n.DESCRIPTION_ACCORDION_TITLE;
100
+ },
101
+ metadataProperties() {
102
+ const toolParams = this.toolParams || {};
103
+
104
+ return Object.entries(metadataProperties)
105
+ .filter(([property]) => toolParams[property])
106
+ .map(([property, styles]) => ({
107
+ key: property,
108
+ value: toolParams[property],
109
+ ...styles,
110
+ }));
111
+ },
112
+ hasMetadataProperties() {
113
+ return this.metadataProperties.length > 0;
114
+ },
115
+ },
116
+ methods: {
117
+ formatPropertyValue(value) {
118
+ if (Array.isArray(value)) {
119
+ return value.join(', ');
120
+ }
121
+
122
+ if (typeof value === 'boolean') {
123
+ return value ? translate('Yes', 'Yes') : translate('No', 'No');
124
+ }
125
+
126
+ return value;
127
+ },
128
+ processPropertyIcon(icon, propertyValue) {
129
+ if (typeof icon === 'function') {
130
+ return icon(propertyValue);
131
+ }
132
+ return icon;
36
133
  },
37
134
  },
38
135
  i18n: {
39
- ACCORDION_TITLE: translate('BaseToolParams.ACCORDION_TITLE', 'Read description'),
136
+ DESCRIPTION_ACCORDION_TITLE: translate(
137
+ 'BaseToolParams.ExpandDescriptionTitle',
138
+ 'Read description'
139
+ ),
140
+ EXPAND_JSON_VIEW_TITLE: translate(
141
+ 'BaseToolParams.ExpandJsonViewTitle',
142
+ 'See request parameters as JSON'
143
+ ),
40
144
  },
41
145
  };
42
146
  </script>
43
147
  <template>
44
- <div class="gl-flex gl-flex-col">
148
+ <div class="gl-flex gl-flex-col gl-gap-3">
149
+ <div v-if="hasMetadataProperties" class="gl-flex gl-flex-wrap gl-gap-2">
150
+ <span v-for="property in metadataProperties" :key="property.key" class="gl-overflow-hidden">
151
+ <gl-badge
152
+ v-if="property.type == 'url'"
153
+ :icon="property.icon"
154
+ :href="property.value"
155
+ :title="property.value"
156
+ >
157
+ <span class="gl-truncate">
158
+ {{ property.value }}
159
+ </span>
160
+ </gl-badge>
161
+ <gl-badge v-else :icon="processPropertyIcon(property.icon, property.value)">
162
+ {{ property.label }}: {{ formatPropertyValue(property.value) }}
163
+ </gl-badge>
164
+ </span>
165
+ </div>
166
+
45
167
  <div v-if="message" v-safe-html="message"></div>
46
168
  <slot v-else></slot>
47
- <gl-accordion v-if="description" class="-gl-ml-2 gl-mt-3" :header-level="3">
48
- <slot name="params-description">
49
- <gl-accordion-item :title="accordionTitle">
50
- <pre-block>{{ description }}</pre-block>
51
- </gl-accordion-item>
52
- </slot>
169
+
170
+ <gl-accordion v-if="message || description" class="-gl-ml-2" :header-level="3">
171
+ <gl-accordion-item v-if="description" class="gl-mb-3" :title="accordionTitle">
172
+ <pre-block>{{ description }}</pre-block>
173
+ </gl-accordion-item>
174
+ <gl-accordion-item v-if="withJsonView" :title="$options.i18n.EXPAND_JSON_VIEW_TITLE">
175
+ <tool-params-json-view :tool-params="toolParams" />
176
+ </gl-accordion-item>
53
177
  </gl-accordion>
178
+ <tool-params-json-view
179
+ v-else-if="!message && !description && withJsonView"
180
+ :tool-params="toolParams"
181
+ />
54
182
  </div>
55
183
  </template>
@@ -2,6 +2,7 @@
2
2
  import { GlSprintf, GlAccordion, GlAccordionItem } from '@gitlab/ui';
3
3
  import { createPatch } from 'diff';
4
4
  import { translate, translatePlural, sprintf } from '../../../../../utils/i18n';
5
+ import BaseToolParams from './base_tool_params.vue';
5
6
  import PreBlock from './pre_block.vue';
6
7
 
7
8
  const NO_NEW_LINE_SIGNAL = '\';
@@ -12,6 +13,7 @@ export default {
12
13
  GlSprintf,
13
14
  GlAccordion,
14
15
  GlAccordionItem,
16
+ BaseToolParams,
15
17
  PreBlock,
16
18
  },
17
19
  props: {
@@ -21,15 +23,9 @@ export default {
21
23
  },
22
24
  },
23
25
  computed: {
24
- project() {
25
- return this.toolParams?.projectPath || this.toolParams?.projectId || '';
26
- },
27
26
  branch() {
28
27
  return this.toolParams?.branch;
29
28
  },
30
- startBranch() {
31
- return this.toolParams?.startBranch || '';
32
- },
33
29
  commitMessage() {
34
30
  return this.toolParams?.commitMessage;
35
31
  },
@@ -108,11 +104,11 @@ export default {
108
104
  i18n: {
109
105
  COMMIT_SUMMARY_MESSAGE: translate(
110
106
  'CreateCommitToolParams.commitSummaryMessage',
111
- 'Create a commit in the branch %{branch} and project %{project}.'
107
+ 'Create a commit in the branch %{branch}.'
112
108
  ),
113
109
  COMMIT_SUMMARY_AUTO_BRANCH_MESSAGE: translate(
114
110
  'CreateCommitToolParams.commitSummaryAutoBranchMessage',
115
- 'Create a commit in a new auto-created branch and project %{project}.'
111
+ 'Create a commit in a new auto-created branch.'
116
112
  ),
117
113
  READ_COMMIT_MESSAGE: translate(
118
114
  'CreateCommitToolParams.readCommitMessage',
@@ -151,7 +147,7 @@ export default {
151
147
  };
152
148
  </script>
153
149
  <template>
154
- <div class="gl-flex gl-flex-col">
150
+ <base-tool-params :tool-params="toolParams">
155
151
  <div>
156
152
  <gl-sprintf
157
153
  :message="
@@ -160,17 +156,18 @@ export default {
160
156
  : $options.i18n.COMMIT_SUMMARY_AUTO_BRANCH_MESSAGE
161
157
  "
162
158
  >
163
- <template #project>
164
- <code>{{ project }}</code>
165
- </template>
166
159
  <template v-if="branch" #branch>
167
160
  <code>{{ branch }}</code>
168
161
  </template>
169
162
  </gl-sprintf>
170
163
  {{ actionsCountMessage }}
171
164
  </div>
172
- <gl-accordion class="-gl-ml-2 gl-mt-3" :header-level="3">
173
- <gl-accordion-item :title="$options.i18n.READ_COMMIT_MESSAGE">
165
+ <gl-accordion class="-gl-ml-2" :header-level="3">
166
+ <gl-accordion-item
167
+ v-if="commitMessage"
168
+ class="gl-mb-3"
169
+ :title="$options.i18n.READ_COMMIT_MESSAGE"
170
+ >
174
171
  <pre-block>{{ commitMessage }}</pre-block>
175
172
  </gl-accordion-item>
176
173
  <gl-accordion-item v-if="actionsCount" :title="$options.i18n.EXPAND_CHANGES">
@@ -178,12 +175,13 @@ export default {
178
175
  <gl-accordion-item
179
176
  v-for="(action, index) in actions"
180
177
  :key="index"
178
+ class="gl-mb-3"
181
179
  :title="getActionTitle(action)"
182
180
  >
183
- <pre-block>{{ getActionContent(action) }}</pre-block>
181
+ <pre-block class="language-diff">{{ getActionContent(action) }}</pre-block>
184
182
  </gl-accordion-item>
185
183
  </gl-accordion>
186
184
  </gl-accordion-item>
187
185
  </gl-accordion>
188
- </div>
186
+ </base-tool-params>
189
187
  </template>
@@ -0,0 +1,72 @@
1
+ <script>
2
+ import { sprintf, translate } from '../../../../../utils/i18n';
3
+ import { APPROVAL_TOOL_NAMES } from '../../../constants';
4
+ import BaseToolParams from './base_tool_params.vue';
5
+
6
+ export default {
7
+ name: 'DefaultToolParams',
8
+ components: {
9
+ BaseToolParams,
10
+ },
11
+ props: {
12
+ toolName: {
13
+ type: String,
14
+ required: false,
15
+ default: '',
16
+ },
17
+ toolParams: {
18
+ type: Object,
19
+ required: true,
20
+ },
21
+ },
22
+ computed: {
23
+ title() {
24
+ return this.toolParams?.title;
25
+ },
26
+ description() {
27
+ return this.toolParams?.description || this.toolParams?.body || this.toolParams?.comment;
28
+ },
29
+ isNote() {
30
+ return [
31
+ APPROVAL_TOOL_NAMES.createMergeRequestNote,
32
+ APPROVAL_TOOL_NAMES.createWorkItemNote,
33
+ APPROVAL_TOOL_NAMES.createIssueNote,
34
+ ].includes(this.toolName);
35
+ },
36
+ message() {
37
+ const message = this.title ? this.$options.i18n.TITLE_MESSAGE : '';
38
+
39
+ return sprintf(message, {
40
+ ...this.toolParams,
41
+ });
42
+ },
43
+ accordionTitle() {
44
+ return this.isNote ? this.$options.i18n.NOTE_ACCORDION_TITLE : '';
45
+ },
46
+ displayRawOutput() {
47
+ return !this.message;
48
+ },
49
+ },
50
+ i18n: {
51
+ TITLE_MESSAGE: translate(
52
+ 'IssuableToolParams.TITLE_MESSAGE',
53
+ 'Set the title "<em>%{title}</em>".'
54
+ ),
55
+ NOTE_ACCORDION_TITLE: translate(
56
+ 'IssuableToolParams.NOTE_ACCORDION_TITLE',
57
+ "Read note's content"
58
+ ),
59
+ },
60
+ };
61
+ </script>
62
+ <template>
63
+ <div>
64
+ <base-tool-params
65
+ with-json-view
66
+ :tool-params="toolParams"
67
+ :message="message"
68
+ :description="description"
69
+ :custom-accordion-title="accordionTitle"
70
+ />
71
+ </div>
72
+ </template>
@@ -0,0 +1,42 @@
1
+ <script>
2
+ import { translate } from '../../../../../utils/i18n';
3
+ import PreBlock from './pre_block.vue';
4
+
5
+ export default {
6
+ name: 'ToolParamsJsonView',
7
+ components: {
8
+ PreBlock,
9
+ },
10
+ props: {
11
+ toolParams: {
12
+ type: Object,
13
+ required: true,
14
+ },
15
+ },
16
+ computed: {
17
+ hasToolParams() {
18
+ return Object.keys(this.toolParams || {}).length > 0;
19
+ },
20
+ },
21
+ i18n: {
22
+ REQUEST_TEXT: translate('MessageToolApproval.parametersText', 'Request parameters'),
23
+ NO_PARAMETERS_TEXT: translate(
24
+ 'MessageToolApproval.noParametersText',
25
+ 'No parameters will be sent with this request.'
26
+ ),
27
+ },
28
+ };
29
+ </script>
30
+ <template>
31
+ <figure class="gl-m-0 gl-flex gl-flex-col gl-gap-2">
32
+ <figcaption class="gl-text-subtle">
33
+ {{ $options.i18n.REQUEST_TEXT }}
34
+ </figcaption>
35
+ <pre-block v-if="hasToolParams" class="language-json" data-testid="tool-parameters">{{
36
+ JSON.stringify(toolParams, null, 2)
37
+ }}</pre-block>
38
+ <span v-else class="gl-text-sm gl-text-gray-500" data-testid="no-parameters-message">
39
+ {{ $options.i18n.NO_PARAMETERS_TEXT }}
40
+ </span>
41
+ </figure>
42
+ </template>
@@ -8,13 +8,14 @@ import {
8
8
  GlDropdown,
9
9
  GlDropdownItem,
10
10
  } from '@gitlab/ui';
11
+ import startCase from 'lodash/startCase';
12
+ import capitalize from 'lodash/capitalize';
11
13
  import { translate } from '../../../../utils/i18n';
12
14
  import { convertKeysToCamelCase } from '../../../../utils/object';
13
15
  import { acceptedApproveToolPayloads, APPROVAL_TOOL_NAMES } from '../../constants';
14
16
  import CreateCommitToolParams from './components/create_commit_tool_params.vue';
15
- import IssuableToolParams from './components/issuable_tool_params.vue';
17
+ import DefaultToolParams from './components/default_tool_params.vue';
16
18
  import RunCommandToolParams from './components/run_command_tool_params.vue';
17
- import PreBlock from './components/pre_block.vue';
18
19
 
19
20
  export const PROCESSING_STATE = {
20
21
  APPROVING: 'approving',
@@ -40,71 +41,12 @@ export const i18n = {
40
41
  APPROVING_TEXT: translate('MessageToolApproval.approvingText', 'Approving...'),
41
42
  DENY_TEXT: translate('MessageToolApproval.denyText', 'Deny'),
42
43
  DENYING_TEXT: translate('MessageToolApproval.denyingText', 'Denying...'),
43
- NO_PARAMETERS_TEXT: translate(
44
- 'MessageToolApproval.noParametersText',
45
- 'No parameters will be sent with this request.'
46
- ),
47
- REQUEST_TEXT: translate('MessageToolApproval.parametersText', 'Request parameters'),
48
44
  DENIAL_REASON_LABEL: translate('MessageToolApproval.denialReasonLabel', 'Rejection reason'),
49
45
  DENIAL_REASON_PLACEHOLDER: translate(
50
46
  'MessageToolApproval.denialReasonPlaceholder',
51
47
  "Tell Duo why you're rejecting this tool execution..."
52
48
  ),
53
49
  CANCEL_TEXT: translate('MessageToolApproval.cancelText', 'Cancel'),
54
- TOOL_APPROVAL_TITLES: {
55
- [APPROVAL_TOOL_NAMES.createCommit]: translate(
56
- 'MessageToolApproval.createCommit',
57
- 'Duo wants to push a commit.'
58
- ),
59
- [APPROVAL_TOOL_NAMES.createIssue]: translate(
60
- 'MessageToolApproval.createIssue',
61
- 'Duo wants to open an issue.'
62
- ),
63
- [APPROVAL_TOOL_NAMES.updateIssue]: translate(
64
- 'MessageToolApproval.updateIssue',
65
- 'Duo wants to update an issue.'
66
- ),
67
- [APPROVAL_TOOL_NAMES.createEpic]: translate(
68
- 'MessageToolApproval.createEpic',
69
- 'Duo wants to create an epic.'
70
- ),
71
- [APPROVAL_TOOL_NAMES.updateEpic]: translate(
72
- 'MessageToolApproval.updateEpic',
73
- 'Duo wants to update an epic.'
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
- ),
83
- [APPROVAL_TOOL_NAMES.createMergeRequest]: translate(
84
- 'MessageToolApproval.createMergeRequest',
85
- 'Duo wants to create a merge request.'
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
- ),
99
- [APPROVAL_TOOL_NAMES.runCommand]: translate(
100
- 'MessageToolApproval.runCommand',
101
- 'Duo wants to run a command.'
102
- ),
103
- [APPROVAL_TOOL_NAMES.runGitCommand]: translate(
104
- 'MessageToolApproval.runGitCommand',
105
- 'Duo wants to run a git command.'
106
- ),
107
- },
108
50
  [TOOL_STATUS.Pending]: translate('MessageToolApproval.toolStatusPending', 'Pending'),
109
51
  [TOOL_STATUS.Approved]: translate('MessageToolApproval.toolStatusApproved', 'Approved'),
110
52
  TOGGLE_PARAMS_BUTTON_EXPAND: translate(
@@ -123,17 +65,6 @@ export const i18n = {
123
65
 
124
66
  const TOOL_PARAMS_VIEW_COMPONENTS = {
125
67
  [APPROVAL_TOOL_NAMES.createCommit]: 'CreateCommitToolParams',
126
- [APPROVAL_TOOL_NAMES.createIssue]: 'IssuableToolParams',
127
- [APPROVAL_TOOL_NAMES.updateIssue]: 'IssuableToolParams',
128
- [APPROVAL_TOOL_NAMES.createEpic]: 'IssuableToolParams',
129
- [APPROVAL_TOOL_NAMES.updateEpic]: 'IssuableToolParams',
130
- [APPROVAL_TOOL_NAMES.createMergeRequest]: 'IssuableToolParams',
131
- [APPROVAL_TOOL_NAMES.updateMergeRequest]: 'IssuableToolParams',
132
- [APPROVAL_TOOL_NAMES.createWorkItem]: 'IssuableToolParams',
133
- [APPROVAL_TOOL_NAMES.updateWorkItem]: 'IssuableToolParams',
134
- [APPROVAL_TOOL_NAMES.createMergeRequestNote]: 'IssuableToolParams',
135
- [APPROVAL_TOOL_NAMES.createWorkItemNote]: 'IssuableToolParams',
136
- [APPROVAL_TOOL_NAMES.createIssueNote]: 'IssuableToolParams',
137
68
  [APPROVAL_TOOL_NAMES.runCommand]: 'RunCommandToolParams',
138
69
  [APPROVAL_TOOL_NAMES.runGitCommand]: 'RunCommandToolParams',
139
70
  };
@@ -149,9 +80,8 @@ export default {
149
80
  GlDropdown,
150
81
  GlDropdownItem,
151
82
  CreateCommitToolParams,
152
- IssuableToolParams,
83
+ DefaultToolParams,
153
84
  RunCommandToolParams,
154
- PreBlock,
155
85
  },
156
86
  props: {
157
87
  messages: {
@@ -236,7 +166,7 @@ export default {
236
166
  }
237
167
 
238
168
  // Single tool: show specific tool message
239
- return i18n.TOOL_APPROVAL_TITLES[this.toolName] || this.toolName;
169
+ return capitalize(startCase(this.toolName));
240
170
  },
241
171
  toolStatusLabel() {
242
172
  return i18n[this.approvalStatus];
@@ -347,7 +277,7 @@ export default {
347
277
  return convertKeysToCamelCase(obj);
348
278
  },
349
279
  getToolParamsComponent(toolName) {
350
- return TOOL_PARAMS_VIEW_COMPONENTS[toolName];
280
+ return TOOL_PARAMS_VIEW_COMPONENTS[toolName] || 'DefaultToolParams';
351
281
  },
352
282
  },
353
283
  i18n,
@@ -364,7 +294,7 @@ export default {
364
294
  >
365
295
  <template #header>
366
296
  <div class="gl-flex gl-items-center gl-justify-between gl-gap-3">
367
- <span>
297
+ <span class="gl-inline-flex gl-items-center gl-gap-2">
368
298
  <gl-button
369
299
  v-if="collapsible"
370
300
  variant="default"
@@ -386,7 +316,6 @@ export default {
386
316
  <div v-for="(toolMsg, index) in messages" :key="toolMsg.id || index">
387
317
  <component
388
318
  :is="getToolParamsComponent(toolMsg.tool_info && toolMsg.tool_info.name)"
389
- v-if="getToolParamsComponent(toolMsg.tool_info && toolMsg.tool_info.name)"
390
319
  :class="['gl-leading-20', { 'gl-border-t gl-mt-3 gl-border-gray-100 gl-pt-3': index > 0 }]"
391
320
  :tool-name="toolMsg.tool_info && toolMsg.tool_info.name"
392
321
  :tool-params="convertKeysToCamelCase((toolMsg.tool_info && toolMsg.tool_info.args) || {})"
@@ -394,27 +323,6 @@ export default {
394
323
  :tool-response="toolMsg.tool_info && toolMsg.tool_info.tool_response"
395
324
  :working-directory="workingDirectory"
396
325
  />
397
- <figure
398
- v-else
399
- class="gl-m-0 gl-flex gl-flex-col gl-gap-2"
400
- :class="{ 'gl-border-t gl-mt-3 gl-border-gray-100 gl-pt-3': index > 0 }"
401
- >
402
- <figcaption class="gl-text-subtle">
403
- {{ $options.i18n.REQUEST_TEXT }}
404
- </figcaption>
405
- <pre-block
406
- v-if="
407
- toolMsg.tool_info &&
408
- toolMsg.tool_info.args &&
409
- Object.keys(toolMsg.tool_info.args).length > 0
410
- "
411
- data-testid="tool-parameters"
412
- >{{ JSON.stringify(toolMsg.tool_info.args, null, 2) }}</pre-block
413
- >
414
- <span v-else class="gl-text-sm gl-text-gray-500" data-testid="no-parameters-message">
415
- {{ $options.i18n.NO_PARAMETERS_TEXT }}
416
- </span>
417
- </figure>
418
326
  </div>
419
327
  <template v-if="!isApproved" #footer>
420
328
  <div v-if="!showDenialReason" class="gl-flex gl-gap-2">
@@ -209,6 +209,23 @@ export const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_MERGE_REQUEST = {
209
209
  role: 'request',
210
210
  };
211
211
 
212
+ export const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_UPDATE_MERGE_REQUEST = {
213
+ id: '125',
214
+ content: 'Tool update_merge_request requires approval. Please confirm if you want to proceed.',
215
+ message_type: MESSAGE_MODEL_ROLES.request,
216
+ tool_info: {
217
+ name: 'update_merge_request',
218
+ args: {
219
+ url: 'https://gitlab.com/gitlab-org/editor-extensions/gitlab-language-server/-/merge_requests/123',
220
+ description:
221
+ '## What does this MR do?\n\nThis MR updates the `group` field in the `web_ide_language_server` beta feature flag configuration from `group::remote development` to `group:: editor extensions`.\n\n## Related issues\n\nThis change aligns the feature flag with the correct group ownership.\n\n## Changes made\n\n- Updated `config/feature_flags/beta/web_ide_language_server.yml`\n- Changed group field from `group::remote development` to `group:: editor extensions`\n\n## Checklist\n\n- [x] Feature flag configuration updated\n- [x] Group field correctly set to `group:: editor extensions`',
222
+ },
223
+ },
224
+ timestamp: '2025-06-25T19:22:21.290791+00:00',
225
+ status: 'success',
226
+ role: 'request',
227
+ };
228
+
212
229
  export const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_RUN_COMMAND = {
213
230
  id: '125',
214
231
  content: 'Tool run_command requires approval. Please confirm if you want to proceed.',
@@ -442,6 +459,7 @@ export const MOCK_REQUEST_MESSAGE_WITH_TOOL_APPROVAL_CREATE_WORK_ITEM = {
442
459
  '## 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',
443
460
  labels: ['enhancement', 'ui', 'accessibility'],
444
461
  assignee_ids: [123],
462
+ confidential: true,
445
463
  },
446
464
  },
447
465
  timestamp: '2025-06-25T19:22:21.290791+00:00',