@gitlab/duo-ui 11.1.2 → 11.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/components/agentic_chat/web_agentic_duo_chat.js +14 -4
- package/dist/components/chat/components/duo_chat_message/message_types/message_tool.js +8 -4
- package/dist/components/chat/components/duo_chat_message_tool_approval/components/base_tool_params.js +79 -0
- package/dist/components/chat/components/duo_chat_message_tool_approval/components/issuable_tool_params.js +116 -0
- package/dist/components/chat/components/duo_chat_message_tool_approval/components/run_command_tool_params.js +45 -5
- package/dist/components/chat/components/duo_chat_message_tool_approval/message_tool_approval.js +67 -20
- package/dist/components/chat/constants.js +12 -1
- package/dist/components/chat/mock_data.js +77 -1
- package/dist/components/chat/web_duo_chat.js +21 -7
- package/dist/components.css +1 -1
- package/dist/components.css.map +1 -1
- package/dist/tailwind.css +1 -1
- package/dist/tailwind.css.map +1 -1
- package/package.json +2 -2
- package/src/components/agentic_chat/web_agentic_duo_chat.vue +25 -9
- package/src/components/chat/components/duo_chat_message/message_types/message_tool.vue +23 -11
- package/src/components/chat/components/duo_chat_message_tool_approval/components/base_tool_params.vue +55 -0
- package/src/components/chat/components/duo_chat_message_tool_approval/components/issuable_tool_params.vue +112 -0
- package/src/components/chat/components/duo_chat_message_tool_approval/components/run_command_tool_params.vue +51 -6
- package/src/components/chat/components/duo_chat_message_tool_approval/message_tool_approval.vue +97 -22
- package/src/components/chat/constants.js +12 -0
- package/src/components/chat/mock_data.js +80 -0
- package/src/components/chat/web_duo_chat.scss +10 -0
- package/src/components/chat/web_duo_chat.vue +46 -12
- package/src/scss/components.scss +1 -0
- package/translations.js +26 -7
- package/dist/components/chat/components/duo_chat_message_tool_approval/components/create_issue_tool_params.js +0 -88
- package/dist/components/chat/components/duo_chat_message_tool_approval/components/create_merge_request_tool_params.js +0 -83
- package/src/components/chat/components/duo_chat_message_tool_approval/components/create_issue_tool_params.vue +0 -80
- package/src/components/chat/components/duo_chat_message_tool_approval/components/create_merge_request_tool_params.vue +0 -74
|
@@ -450,6 +450,13 @@ export default {
|
|
|
450
450
|
activeThreadTitleForView() {
|
|
451
451
|
return (this.currentView === VIEW_TYPES.CHAT && this.activeThreadTitle) || '';
|
|
452
452
|
},
|
|
453
|
+
hasFooterControls() {
|
|
454
|
+
return (
|
|
455
|
+
this.$scopedSlots?.['footer-controls'] &&
|
|
456
|
+
typeof this.$scopedSlots['footer-controls'] === 'function' &&
|
|
457
|
+
this.$scopedSlots['footer-controls']()
|
|
458
|
+
);
|
|
459
|
+
},
|
|
453
460
|
},
|
|
454
461
|
watch: {
|
|
455
462
|
multiThreadedView(newView) {
|
|
@@ -866,7 +873,7 @@ export default {
|
|
|
866
873
|
</div>
|
|
867
874
|
|
|
868
875
|
<div
|
|
869
|
-
class="duo-chat-input gl-min-h-8 gl-max-w-full gl-grow gl-flex-col gl-rounded-bl-[12px] gl-rounded-br-[18px] gl-rounded-tl-[12px] gl-rounded-tr-[12px] gl-align-top"
|
|
876
|
+
class="duo-chat-input web-only gl-relative gl-min-h-8 gl-max-w-full gl-grow gl-flex-col gl-rounded-bl-[12px] gl-rounded-br-[18px] gl-rounded-tl-[12px] gl-rounded-tr-[12px] gl-align-top"
|
|
870
877
|
>
|
|
871
878
|
<div
|
|
872
879
|
class="gl-flex gl-justify-between gl-border-0 gl-border-b-1 gl-border-solid gl-border-strong gl-px-4 gl-py-4"
|
|
@@ -874,7 +881,7 @@ export default {
|
|
|
874
881
|
<div>{{ $options.i18n.CHAT_MODEL_PLACEHOLDER }}</div>
|
|
875
882
|
<div><slot name="agentic-switch"></slot></div>
|
|
876
883
|
</div>
|
|
877
|
-
<div :data-value="prompt" class="gl-h-[
|
|
884
|
+
<div :data-value="prompt" class="gl-h-[80px] gl-grow">
|
|
878
885
|
<gl-card
|
|
879
886
|
v-if="shouldShowSlashCommands"
|
|
880
887
|
ref="commands"
|
|
@@ -929,25 +936,34 @@ export default {
|
|
|
929
936
|
<template #remaining-character-count-text="{ count }">
|
|
930
937
|
<span
|
|
931
938
|
v-if="count <= promptLengthWarningCount"
|
|
932
|
-
class="gl-absolute gl-
|
|
939
|
+
class="gl-absolute gl-right-px gl-mt-3 gl-pr-3 gl-text-sm"
|
|
940
|
+
:class="{
|
|
941
|
+
'gl-bottom-[-5rem]': hasFooterControls,
|
|
942
|
+
'gl-bottom-[-1.6rem]': !hasFooterControls,
|
|
943
|
+
}"
|
|
933
944
|
>
|
|
934
945
|
{{ remainingCharacterCountMessage(count) }}
|
|
935
946
|
</span>
|
|
936
947
|
</template>
|
|
937
948
|
<template #character-count-over-limit-text="{ count }">
|
|
938
|
-
<span
|
|
939
|
-
|
|
940
|
-
|
|
949
|
+
<span
|
|
950
|
+
class="gl-absolute gl-bottom-[-1.6rem] gl-right-0 gl-mt-3 gl-pr-3 gl-text-sm"
|
|
951
|
+
:class="{
|
|
952
|
+
'gl-bottom-[-5rem]': hasFooterControls,
|
|
953
|
+
'gl-bottom-[-1.6rem]': !hasFooterControls,
|
|
954
|
+
}"
|
|
955
|
+
>{{ overLimitCharacterCountMessage(count) }}</span
|
|
956
|
+
>
|
|
941
957
|
</template>
|
|
942
958
|
</gl-form-textarea>
|
|
943
959
|
</div>
|
|
944
|
-
<div class="gl-
|
|
960
|
+
<div class="gl-absolute gl-bottom-0 gl-right-0 gl-px-3 gl-pb-3">
|
|
945
961
|
<gl-button
|
|
946
962
|
v-if="canSubmit"
|
|
947
963
|
icon="paper-airplane"
|
|
948
964
|
category="primary"
|
|
949
965
|
variant="confirm"
|
|
950
|
-
class="
|
|
966
|
+
class="!gl-rounded-full"
|
|
951
967
|
type="submit"
|
|
952
968
|
:disabled="isPromptEmpty || !hasValidPrompt"
|
|
953
969
|
data-testid="chat-prompt-submit-button"
|
|
@@ -958,7 +974,7 @@ export default {
|
|
|
958
974
|
icon="stop"
|
|
959
975
|
category="primary"
|
|
960
976
|
variant="default"
|
|
961
|
-
class="
|
|
977
|
+
class="!gl-rounded-full"
|
|
962
978
|
data-testid="chat-prompt-cancel-button"
|
|
963
979
|
:aria-label="$options.i18n.CHAT_CANCEL_LABEL"
|
|
964
980
|
@click="cancelPrompt"
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { GlIcon, GlLink } from '@gitlab/ui';
|
|
3
3
|
import { translate } from '../../../../../utils/i18n';
|
|
4
|
-
import
|
|
4
|
+
import MessageToolApproval from '../../duo_chat_message_tool_approval/message_tool_approval.vue';
|
|
5
|
+
import { APPROVAL_TOOL_NAMES } from '../../../constants';
|
|
5
6
|
import BaseMessage from './message_base.vue';
|
|
6
7
|
|
|
7
8
|
export const i18n = {
|
|
@@ -19,7 +20,7 @@ export default {
|
|
|
19
20
|
name: 'DuoToolMessage',
|
|
20
21
|
components: {
|
|
21
22
|
BaseMessage,
|
|
22
|
-
|
|
23
|
+
MessageToolApproval,
|
|
23
24
|
GlIcon,
|
|
24
25
|
GlLink,
|
|
25
26
|
},
|
|
@@ -99,6 +100,18 @@ export default {
|
|
|
99
100
|
toolWorkingDirectory() {
|
|
100
101
|
return this.workingDirectory;
|
|
101
102
|
},
|
|
103
|
+
requiresApproval() {
|
|
104
|
+
return [
|
|
105
|
+
APPROVAL_TOOL_NAMES.runCommand,
|
|
106
|
+
APPROVAL_TOOL_NAMES.runGitCommand,
|
|
107
|
+
APPROVAL_TOOL_NAMES.createIssue,
|
|
108
|
+
APPROVAL_TOOL_NAMES.updateIssue,
|
|
109
|
+
APPROVAL_TOOL_NAMES.createMergeRequest,
|
|
110
|
+
APPROVAL_TOOL_NAMES.updateMergeRequest,
|
|
111
|
+
APPROVAL_TOOL_NAMES.createEpic,
|
|
112
|
+
APPROVAL_TOOL_NAMES.updateEpic,
|
|
113
|
+
].includes(this.toolName);
|
|
114
|
+
},
|
|
102
115
|
},
|
|
103
116
|
methods: {
|
|
104
117
|
onOpenFilePath(filePath) {
|
|
@@ -111,16 +124,15 @@ export default {
|
|
|
111
124
|
};
|
|
112
125
|
</script>
|
|
113
126
|
<template>
|
|
114
|
-
<
|
|
127
|
+
<message-tool-approval
|
|
128
|
+
v-if="requiresApproval"
|
|
129
|
+
:message="message"
|
|
130
|
+
:working-directory="workingDirectory"
|
|
131
|
+
approval-status="approved"
|
|
132
|
+
/>
|
|
133
|
+
<base-message v-else :message="message">
|
|
115
134
|
<template #message="{ content }">
|
|
116
|
-
<
|
|
117
|
-
v-if="hasCommandOutput"
|
|
118
|
-
:command-header="$options.i18n.RAN_TERMINAL_COMMAND"
|
|
119
|
-
:command-action="toolName"
|
|
120
|
-
:command-output="toolResponseContent"
|
|
121
|
-
:working-directory="toolWorkingDirectory"
|
|
122
|
-
/>
|
|
123
|
-
<div v-else class="gl-flex gl-items-baseline !gl-text-subtle">
|
|
135
|
+
<div class="gl-flex gl-items-baseline !gl-text-subtle">
|
|
124
136
|
<div class="gl-mr-3 gl-flex-shrink-0">
|
|
125
137
|
<gl-icon :name="iconName" />
|
|
126
138
|
</div>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { GlAccordion, GlAccordionItem, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
|
|
3
|
+
import { translate } from '../../../../../utils/i18n';
|
|
4
|
+
import PreBlock from './pre_block.vue';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
name: 'BaseToolParams',
|
|
8
|
+
components: {
|
|
9
|
+
GlAccordion,
|
|
10
|
+
GlAccordionItem,
|
|
11
|
+
PreBlock,
|
|
12
|
+
},
|
|
13
|
+
directives: {
|
|
14
|
+
SafeHtml,
|
|
15
|
+
},
|
|
16
|
+
props: {
|
|
17
|
+
message: {
|
|
18
|
+
type: String,
|
|
19
|
+
required: false,
|
|
20
|
+
default: '',
|
|
21
|
+
},
|
|
22
|
+
description: {
|
|
23
|
+
type: String,
|
|
24
|
+
required: false,
|
|
25
|
+
default: '',
|
|
26
|
+
},
|
|
27
|
+
customAccordionTitle: {
|
|
28
|
+
type: String,
|
|
29
|
+
required: false,
|
|
30
|
+
default: '',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
computed: {
|
|
34
|
+
accordionTitle() {
|
|
35
|
+
return this.customAccordionTitle || this.$options.i18n.ACCORDION_TITLE;
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
i18n: {
|
|
39
|
+
ACCORDION_TITLE: translate('BaseToolParams.ACCORDION_TITLE', 'Read description'),
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
</script>
|
|
43
|
+
<template>
|
|
44
|
+
<div class="gl-flex gl-flex-col">
|
|
45
|
+
<div v-if="message" v-safe-html="message"></div>
|
|
46
|
+
<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>
|
|
53
|
+
</gl-accordion>
|
|
54
|
+
</div>
|
|
55
|
+
</template>
|
|
@@ -0,0 +1,112 @@
|
|
|
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: 'IssuableToolParams',
|
|
8
|
+
components: {
|
|
9
|
+
BaseToolParams,
|
|
10
|
+
},
|
|
11
|
+
props: {
|
|
12
|
+
toolName: {
|
|
13
|
+
type: String,
|
|
14
|
+
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),
|
|
24
|
+
},
|
|
25
|
+
toolParams: {
|
|
26
|
+
type: Object,
|
|
27
|
+
required: true,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
computed: {
|
|
31
|
+
project() {
|
|
32
|
+
return this.toolParams?.projectPath || this.toolParams?.projectId;
|
|
33
|
+
},
|
|
34
|
+
title() {
|
|
35
|
+
return this.toolParams?.title;
|
|
36
|
+
},
|
|
37
|
+
labels() {
|
|
38
|
+
return this.toolParams?.labels;
|
|
39
|
+
},
|
|
40
|
+
description() {
|
|
41
|
+
return this.toolParams?.description;
|
|
42
|
+
},
|
|
43
|
+
sourceBranch() {
|
|
44
|
+
return this.toolParams?.sourceBranch;
|
|
45
|
+
},
|
|
46
|
+
targetBranch() {
|
|
47
|
+
return this.toolParams?.targetBranch;
|
|
48
|
+
},
|
|
49
|
+
message() {
|
|
50
|
+
let message = this.$options.i18n[this.toolName] || '';
|
|
51
|
+
const labelsMessage = this.$options.i18n.ASSIGN_LABELS_MESSAGE;
|
|
52
|
+
const branchMessage = this.$options.i18n.BRANCH_MESSAGE;
|
|
53
|
+
|
|
54
|
+
if (this.title) {
|
|
55
|
+
message = `${message} ${this.$options.i18n.TITLE_MESSAGE}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (this.sourceBranch && this.targetBranch) {
|
|
59
|
+
message = `${message} ${branchMessage}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (this.labels) {
|
|
63
|
+
message = `${message} ${labelsMessage}`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return sprintf(message, { project: this.project, ...this.toolParams });
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
i18n: {
|
|
70
|
+
[APPROVAL_TOOL_NAMES.createIssue]: translate(
|
|
71
|
+
'IssuableToolParams.CREATE_ISSUE',
|
|
72
|
+
'Open an issue in project <code>%{project}</code>.'
|
|
73
|
+
),
|
|
74
|
+
[APPROVAL_TOOL_NAMES.updateIssue]: translate(
|
|
75
|
+
'IssuableToolParams.UPDATE_ISSUE',
|
|
76
|
+
'Update issue <code>%{issueIid}</code> in project <code>%{project}</code>.'
|
|
77
|
+
),
|
|
78
|
+
[APPROVAL_TOOL_NAMES.createEpic]: translate(
|
|
79
|
+
'IssuableToolParams.CREATE_EPIC',
|
|
80
|
+
'Create an epic in group <code>%{groupId}</code>.'
|
|
81
|
+
),
|
|
82
|
+
[APPROVAL_TOOL_NAMES.updateEpic]: translate(
|
|
83
|
+
'IssuableToolParams.UPDATE_EPIC',
|
|
84
|
+
'Update epic <code>%{epicId}</code> in group <code>%{groupId}</code>.'
|
|
85
|
+
),
|
|
86
|
+
[APPROVAL_TOOL_NAMES.createMergeRequest]: translate(
|
|
87
|
+
'IssuableToolParams.CREATE_MERGE_REQUEST',
|
|
88
|
+
'Open a merge request in project <code>%{project}</code>.'
|
|
89
|
+
),
|
|
90
|
+
[APPROVAL_TOOL_NAMES.updateMergeRequest]: translate(
|
|
91
|
+
'IssuableToolParams.UPDATE_MERGE_REQUEST',
|
|
92
|
+
'Update merge request <code>%{mergeRequestIid}</code> in project <code>%{project}</code>.'
|
|
93
|
+
),
|
|
94
|
+
TITLE_MESSAGE: translate(
|
|
95
|
+
'IssuableToolParams.TITLE_MESSAGE',
|
|
96
|
+
'Set the title "<em>%{title}</em>".'
|
|
97
|
+
),
|
|
98
|
+
BRANCH_MESSAGE: translate(
|
|
99
|
+
'IssuableToolParams.BRANCH_MESSAGE',
|
|
100
|
+
'From branch <code>%{sourceBranch}</code> to branch <code>%{targetBranch}</code>.'
|
|
101
|
+
),
|
|
102
|
+
ASSIGN_LABELS_MESSAGE: translate(
|
|
103
|
+
'CreateIssueToolParams.ASSIGN_LABELS_MESSAGE',
|
|
104
|
+
'Assign the labels <code>%{labels}</code>.'
|
|
105
|
+
),
|
|
106
|
+
ACCORDION_TITLE: translate('CreateIssueToolParams.ACCORDION_TITLE', 'Read description'),
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
</script>
|
|
110
|
+
<template>
|
|
111
|
+
<base-tool-params :message="message" :description="description" />
|
|
112
|
+
</template>
|
|
@@ -1,30 +1,75 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { GlIcon } from '@gitlab/ui';
|
|
3
|
+
import { translate } from '../../../../../utils/i18n';
|
|
4
|
+
import { APPROVAL_TOOL_NAMES } from '../../../constants';
|
|
5
|
+
import BaseToolParams from './base_tool_params.vue';
|
|
3
6
|
|
|
4
7
|
export default {
|
|
5
8
|
name: 'RunCommandToolParams',
|
|
6
9
|
components: {
|
|
7
10
|
GlIcon,
|
|
11
|
+
BaseToolParams,
|
|
8
12
|
},
|
|
9
13
|
props: {
|
|
10
|
-
|
|
14
|
+
toolName: {
|
|
11
15
|
type: String,
|
|
12
16
|
required: true,
|
|
13
17
|
},
|
|
18
|
+
program: {
|
|
19
|
+
type: String,
|
|
20
|
+
required: false,
|
|
21
|
+
default: '',
|
|
22
|
+
},
|
|
14
23
|
args: {
|
|
15
24
|
type: String,
|
|
16
|
-
required:
|
|
25
|
+
required: false,
|
|
26
|
+
default: '',
|
|
27
|
+
},
|
|
28
|
+
command: {
|
|
29
|
+
type: String,
|
|
30
|
+
required: false,
|
|
31
|
+
default: '',
|
|
32
|
+
},
|
|
33
|
+
toolResponse: {
|
|
34
|
+
type: Object,
|
|
35
|
+
required: false,
|
|
36
|
+
default: null,
|
|
37
|
+
},
|
|
38
|
+
workingDirectory: {
|
|
39
|
+
type: String,
|
|
40
|
+
required: false,
|
|
41
|
+
default: '',
|
|
17
42
|
},
|
|
18
43
|
},
|
|
19
44
|
computed: {
|
|
20
45
|
formattedCommand() {
|
|
21
|
-
|
|
46
|
+
if (this.toolName === APPROVAL_TOOL_NAMES.runCommand) {
|
|
47
|
+
return this.command?.length ? this.command : `${this.program} ${this.args}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return `git ${this.command} ${this.args}`;
|
|
22
51
|
},
|
|
52
|
+
withWorkingDirectory() {
|
|
53
|
+
return this.workingDirectory?.length
|
|
54
|
+
? `${this.workingDirectory}> ${this.formattedCommand}`
|
|
55
|
+
: this.formattedCommand;
|
|
56
|
+
},
|
|
57
|
+
commandOutput() {
|
|
58
|
+
return this.toolResponse?.content;
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
i18n: {
|
|
62
|
+
SEE_COMMAND_OUTPUT: translate('RunCommandToolParams.ACCORDION_TITLE', 'Expand command output'),
|
|
23
63
|
},
|
|
24
64
|
};
|
|
25
65
|
</script>
|
|
26
66
|
<template>
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
67
|
+
<base-tool-params
|
|
68
|
+
:description="commandOutput"
|
|
69
|
+
:custom-accordion-title="$options.i18n.SEE_COMMAND_OUTPUT"
|
|
70
|
+
>
|
|
71
|
+
<div class="gl-flex gl-items-center gl-gap-3">
|
|
72
|
+
<gl-icon name="terminal" /> <code>{{ withWorkingDirectory }}</code>
|
|
73
|
+
</div>
|
|
74
|
+
</base-tool-params>
|
|
30
75
|
</template>
|
package/src/components/chat/components/duo_chat_message_tool_approval/message_tool_approval.vue
CHANGED
|
@@ -10,25 +10,22 @@ import {
|
|
|
10
10
|
} from '@gitlab/ui';
|
|
11
11
|
import { translate } from '../../../../utils/i18n';
|
|
12
12
|
import { convertKeysToCamelCase } from '../../../../utils/object';
|
|
13
|
-
import { acceptedApproveToolPayloads } from '../../constants';
|
|
13
|
+
import { acceptedApproveToolPayloads, APPROVAL_TOOL_NAMES } from '../../constants';
|
|
14
14
|
import CreateCommitToolParams from './components/create_commit_tool_params.vue';
|
|
15
|
-
import
|
|
16
|
-
import CreateMergeRequestToolParams from './components/create_merge_request_tool_params.vue';
|
|
15
|
+
import IssuableToolParams from './components/issuable_tool_params.vue';
|
|
17
16
|
import RunCommandToolParams from './components/run_command_tool_params.vue';
|
|
18
17
|
|
|
19
|
-
export const APPROVAL_TOOL_NAMES = {
|
|
20
|
-
createCommit: 'create_commit',
|
|
21
|
-
createIssue: 'create_issue',
|
|
22
|
-
createMergeRequest: 'create_merge_request',
|
|
23
|
-
runCommand: 'run_command',
|
|
24
|
-
};
|
|
25
|
-
|
|
26
18
|
export const PROCESSING_STATE = {
|
|
27
19
|
APPROVING: 'approving',
|
|
28
20
|
DENYING: 'denying',
|
|
29
21
|
NONE: null,
|
|
30
22
|
};
|
|
31
23
|
|
|
24
|
+
export const TOOL_STATUS = {
|
|
25
|
+
Pending: 'pending',
|
|
26
|
+
Approved: 'approved',
|
|
27
|
+
};
|
|
28
|
+
|
|
32
29
|
export const i18n = {
|
|
33
30
|
TOOL_APPROVAL_DESCRIPTION: translate(
|
|
34
31
|
'MessageToolApproval.toolApprovalDescription',
|
|
@@ -62,6 +59,18 @@ export const i18n = {
|
|
|
62
59
|
'MessageToolApproval.createIssue',
|
|
63
60
|
'Duo wants to open an issue.'
|
|
64
61
|
),
|
|
62
|
+
[APPROVAL_TOOL_NAMES.updateIssue]: translate(
|
|
63
|
+
'MessageToolApproval.updateIssue',
|
|
64
|
+
'Duo wants to update an issue.'
|
|
65
|
+
),
|
|
66
|
+
[APPROVAL_TOOL_NAMES.createEpic]: translate(
|
|
67
|
+
'MessageToolApproval.createEpic',
|
|
68
|
+
'Duo wants to create an epic.'
|
|
69
|
+
),
|
|
70
|
+
[APPROVAL_TOOL_NAMES.updateEpic]: translate(
|
|
71
|
+
'MessageToolApproval.updateEpic',
|
|
72
|
+
'Duo wants to update an epic.'
|
|
73
|
+
),
|
|
65
74
|
[APPROVAL_TOOL_NAMES.createMergeRequest]: translate(
|
|
66
75
|
'MessageToolApproval.createMergeRequest',
|
|
67
76
|
'Duo wants to create a merge request.'
|
|
@@ -70,15 +79,33 @@ export const i18n = {
|
|
|
70
79
|
'MessageToolApproval.runCommand',
|
|
71
80
|
'Duo wants to run a command.'
|
|
72
81
|
),
|
|
82
|
+
[APPROVAL_TOOL_NAMES.runGitCommand]: translate(
|
|
83
|
+
'MessageToolApproval.runGitCommand',
|
|
84
|
+
'Duo wants to run a git command.'
|
|
85
|
+
),
|
|
73
86
|
},
|
|
74
|
-
TOOL_STATUS: translate('MessageToolApproval.
|
|
87
|
+
[TOOL_STATUS.Pending]: translate('MessageToolApproval.toolStatusPending', 'Pending'),
|
|
88
|
+
[TOOL_STATUS.Approved]: translate('MessageToolApproval.toolStatusApproved', 'Approved'),
|
|
89
|
+
TOGGLE_PARAMS_BUTTON_EXPAND: translate(
|
|
90
|
+
'MessageToolApproval.collapseButtonCollapsed',
|
|
91
|
+
'Display tool details'
|
|
92
|
+
),
|
|
93
|
+
TOGGLE_PARAMS_BUTTON_COLLAPSE: translate(
|
|
94
|
+
'MessageToolApproval.collapseButtonExpanded',
|
|
95
|
+
'Hide tool details'
|
|
96
|
+
),
|
|
75
97
|
};
|
|
76
98
|
|
|
77
99
|
const TOOL_PARAMS_VIEW_COMPONENTS = {
|
|
78
100
|
[APPROVAL_TOOL_NAMES.createCommit]: 'CreateCommitToolParams',
|
|
79
|
-
[APPROVAL_TOOL_NAMES.createIssue]: '
|
|
80
|
-
[APPROVAL_TOOL_NAMES.
|
|
101
|
+
[APPROVAL_TOOL_NAMES.createIssue]: 'IssuableToolParams',
|
|
102
|
+
[APPROVAL_TOOL_NAMES.updateIssue]: 'IssuableToolParams',
|
|
103
|
+
[APPROVAL_TOOL_NAMES.createEpic]: 'IssuableToolParams',
|
|
104
|
+
[APPROVAL_TOOL_NAMES.updateEpic]: 'IssuableToolParams',
|
|
105
|
+
[APPROVAL_TOOL_NAMES.createMergeRequest]: 'IssuableToolParams',
|
|
106
|
+
[APPROVAL_TOOL_NAMES.updateMergeRequest]: 'IssuableToolParams',
|
|
81
107
|
[APPROVAL_TOOL_NAMES.runCommand]: 'RunCommandToolParams',
|
|
108
|
+
[APPROVAL_TOOL_NAMES.runGitCommand]: 'RunCommandToolParams',
|
|
82
109
|
};
|
|
83
110
|
|
|
84
111
|
export default {
|
|
@@ -92,8 +119,7 @@ export default {
|
|
|
92
119
|
GlDropdown,
|
|
93
120
|
GlDropdownItem,
|
|
94
121
|
CreateCommitToolParams,
|
|
95
|
-
|
|
96
|
-
CreateMergeRequestToolParams,
|
|
122
|
+
IssuableToolParams,
|
|
97
123
|
RunCommandToolParams,
|
|
98
124
|
},
|
|
99
125
|
props: {
|
|
@@ -101,11 +127,21 @@ export default {
|
|
|
101
127
|
required: true,
|
|
102
128
|
type: Object,
|
|
103
129
|
},
|
|
130
|
+
workingDirectory: {
|
|
131
|
+
type: String,
|
|
132
|
+
required: false,
|
|
133
|
+
default: '',
|
|
134
|
+
},
|
|
104
135
|
isProcessing: {
|
|
105
136
|
type: Boolean,
|
|
106
137
|
required: false,
|
|
107
138
|
default: false,
|
|
108
139
|
},
|
|
140
|
+
approvalStatus: {
|
|
141
|
+
type: String,
|
|
142
|
+
required: false,
|
|
143
|
+
default: TOOL_STATUS.Pending,
|
|
144
|
+
},
|
|
109
145
|
/**
|
|
110
146
|
* Array of approval options for multi-approval functionality
|
|
111
147
|
* @property {string} type - The approval type (approve-tool-once, approve-for-session, always-approve-tool)
|
|
@@ -137,6 +173,7 @@ export default {
|
|
|
137
173
|
showDenialReason: false,
|
|
138
174
|
denialReason: '',
|
|
139
175
|
localProcessingState: PROCESSING_STATE.NONE,
|
|
176
|
+
collapsed: this.approvalStatus === TOOL_STATUS.Approved,
|
|
140
177
|
};
|
|
141
178
|
},
|
|
142
179
|
computed: {
|
|
@@ -146,6 +183,9 @@ export default {
|
|
|
146
183
|
toolParameters() {
|
|
147
184
|
return this.message?.tool_info?.args || {};
|
|
148
185
|
},
|
|
186
|
+
toolResponse() {
|
|
187
|
+
return this.message?.tool_info?.tool_response;
|
|
188
|
+
},
|
|
149
189
|
camelCaseToolParameters() {
|
|
150
190
|
return convertKeysToCamelCase(this.toolParameters);
|
|
151
191
|
},
|
|
@@ -153,7 +193,27 @@ export default {
|
|
|
153
193
|
return Object.keys(this.toolParameters).length > 0;
|
|
154
194
|
},
|
|
155
195
|
toolApprovalTitle() {
|
|
156
|
-
return i18n.TOOL_APPROVAL_TITLES[this.toolName];
|
|
196
|
+
return i18n.TOOL_APPROVAL_TITLES[this.toolName] || this.toolName;
|
|
197
|
+
},
|
|
198
|
+
toolStatusLabel() {
|
|
199
|
+
return i18n[this.approvalStatus];
|
|
200
|
+
},
|
|
201
|
+
toolStatusVariant() {
|
|
202
|
+
return {
|
|
203
|
+
[TOOL_STATUS.Pending]: 'neutral',
|
|
204
|
+
[TOOL_STATUS.Approved]: 'info',
|
|
205
|
+
}[this.approvalStatus];
|
|
206
|
+
},
|
|
207
|
+
collapsible() {
|
|
208
|
+
return this.approvalStatus === TOOL_STATUS.Approved;
|
|
209
|
+
},
|
|
210
|
+
collapseButtonProps() {
|
|
211
|
+
return this.collapsed
|
|
212
|
+
? { icon: 'chevron-right', title: i18n.TOGGLE_PARAMS_BUTTON_EXPAND }
|
|
213
|
+
: { icon: 'chevron-down', title: i18n.TOGGLE_PARAMS_BUTTON_COLLAPSE };
|
|
214
|
+
},
|
|
215
|
+
isApproved() {
|
|
216
|
+
return this.approvalStatus === TOOL_STATUS.Approved;
|
|
157
217
|
},
|
|
158
218
|
isApproving() {
|
|
159
219
|
return this.isProcessing && this.localProcessingState === PROCESSING_STATE.APPROVING;
|
|
@@ -247,14 +307,25 @@ export default {
|
|
|
247
307
|
</script>
|
|
248
308
|
|
|
249
309
|
<template>
|
|
250
|
-
<gl-card>
|
|
310
|
+
<gl-card class="gl-w-full" :body-class="{ 'gl-hidden': collapsed }">
|
|
251
311
|
<template #header>
|
|
252
|
-
<div class="gl-flex gl-items-center gl-justify-between">
|
|
312
|
+
<div class="gl-flex gl-items-center gl-justify-between gl-gap-3">
|
|
253
313
|
<span>
|
|
254
|
-
|
|
314
|
+
<gl-button
|
|
315
|
+
v-if="collapsible"
|
|
316
|
+
variant="default"
|
|
317
|
+
category="tertiary"
|
|
318
|
+
size="small"
|
|
319
|
+
data-testid="toggle-details-button"
|
|
320
|
+
v-bind="collapseButtonProps"
|
|
321
|
+
@click="collapsed = !collapsed"
|
|
322
|
+
/>
|
|
323
|
+
<span>
|
|
324
|
+
{{ toolApprovalTitle }}
|
|
325
|
+
</span>
|
|
255
326
|
</span>
|
|
256
|
-
<gl-badge>
|
|
257
|
-
{{
|
|
327
|
+
<gl-badge :variant="toolStatusVariant">
|
|
328
|
+
{{ toolStatusLabel }}
|
|
258
329
|
</gl-badge>
|
|
259
330
|
</div>
|
|
260
331
|
</template>
|
|
@@ -262,6 +333,10 @@ export default {
|
|
|
262
333
|
:is="toolParamsViewComponent"
|
|
263
334
|
v-if="toolParamsViewComponent"
|
|
264
335
|
class="gl-leading-20"
|
|
336
|
+
:tool-name="toolName"
|
|
337
|
+
:tool-params="camelCaseToolParameters"
|
|
338
|
+
:tool-response="toolResponse"
|
|
339
|
+
:working-directory="workingDirectory"
|
|
265
340
|
v-bind="camelCaseToolParameters"
|
|
266
341
|
/>
|
|
267
342
|
<div
|
|
@@ -283,7 +358,7 @@ export default {
|
|
|
283
358
|
</span>
|
|
284
359
|
</div>
|
|
285
360
|
</div>
|
|
286
|
-
<template #footer>
|
|
361
|
+
<template v-if="!isApproved" #footer>
|
|
287
362
|
<div v-if="!showDenialReason" class="gl-flex gl-gap-2">
|
|
288
363
|
<!-- Split button when multiple approval options available -->
|
|
289
364
|
<gl-dropdown
|
|
@@ -49,3 +49,15 @@ export const acceptedApproveToolPayloads = {
|
|
|
49
49
|
APPROVE_SESSION,
|
|
50
50
|
APPROVE_ALL_TOOLS,
|
|
51
51
|
};
|
|
52
|
+
|
|
53
|
+
export const APPROVAL_TOOL_NAMES = {
|
|
54
|
+
createCommit: 'create_commit',
|
|
55
|
+
createIssue: 'create_issue',
|
|
56
|
+
updateIssue: 'update_issue',
|
|
57
|
+
createEpic: 'create_epic',
|
|
58
|
+
updateEpic: 'update_epic',
|
|
59
|
+
createMergeRequest: 'create_merge_request',
|
|
60
|
+
updateMergeRequest: 'update_merge_request',
|
|
61
|
+
runCommand: 'run_command',
|
|
62
|
+
runGitCommand: 'run_git_command',
|
|
63
|
+
};
|