@gitlab/duo-ui 8.13.2 → 8.14.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.
Files changed (30) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/components/agentic_chat/agentic_duo_chat.js +11 -12
  3. package/dist/components/chat/components/duo_chat_conversation/duo_chat_conversation.js +4 -1
  4. package/dist/components/chat/components/duo_chat_loader/duo_chat_loader.js +8 -6
  5. package/dist/components/chat/components/duo_chat_message/duo_chat_message.js +30 -10
  6. package/dist/components/chat/components/duo_chat_message/message_types/index.js +13 -0
  7. package/dist/components/chat/components/duo_chat_message/message_types/message_agent.js +61 -0
  8. package/dist/components/chat/components/duo_chat_message/message_types/message_base.js +103 -0
  9. package/dist/components/chat/components/duo_chat_message/message_types/message_input_requested.js +53 -0
  10. package/dist/components/chat/components/duo_chat_message/message_types/message_tool.js +77 -0
  11. package/dist/components/chat/components/duo_chat_message/message_types/message_workflow_end.js +59 -0
  12. package/dist/components/chat/constants.js +4 -1
  13. package/dist/components/chat/duo_chat.js +8 -1
  14. package/dist/components/chat/mock_data.js +26 -1
  15. package/dist/tailwind.css +1 -1
  16. package/dist/tailwind.css.map +1 -1
  17. package/package.json +2 -2
  18. package/src/components/agentic_chat/agentic_duo_chat.vue +12 -12
  19. package/src/components/chat/components/duo_chat_conversation/duo_chat_conversation.vue +4 -0
  20. package/src/components/chat/components/duo_chat_loader/duo_chat_loader.vue +5 -3
  21. package/src/components/chat/components/duo_chat_message/duo_chat_message.vue +129 -93
  22. package/src/components/chat/components/duo_chat_message/message_types/index.js +11 -0
  23. package/src/components/chat/components/duo_chat_message/message_types/message_agent.vue +34 -0
  24. package/src/components/chat/components/duo_chat_message/message_types/message_base.vue +84 -0
  25. package/src/components/chat/components/duo_chat_message/message_types/message_input_requested.vue +19 -0
  26. package/src/components/chat/components/duo_chat_message/message_types/message_tool.vue +52 -0
  27. package/src/components/chat/components/duo_chat_message/message_types/message_workflow_end.vue +32 -0
  28. package/src/components/chat/constants.js +3 -0
  29. package/src/components/chat/duo_chat.vue +8 -0
  30. package/src/components/chat/mock_data.js +30 -0
@@ -0,0 +1,34 @@
1
+ <script>
2
+ import BaseMessage from './message_base.vue';
3
+
4
+ export default {
5
+ name: 'DuoChatAgentMessage',
6
+ components: {
7
+ BaseMessage,
8
+ },
9
+ props: {
10
+ message: {
11
+ required: true,
12
+ type: Object,
13
+ },
14
+ },
15
+ computed: {
16
+ hasError() {
17
+ return Boolean(this.message?.errors?.length);
18
+ },
19
+ },
20
+ };
21
+ </script>
22
+ <template>
23
+ <base-message
24
+ :message="message"
25
+ class="gl-rounded-bl-none gl-border-1 gl-border-solid gl-text-gray-900 gl-p-4 gl-border-gray-50"
26
+ :class="{
27
+ 'gl-border-red-100': hasError,
28
+ }"
29
+ >
30
+ <template #message="slotProps">
31
+ <slot name="message" v-bind="slotProps"> </slot>
32
+ </template>
33
+ </base-message>
34
+ </template>
@@ -0,0 +1,84 @@
1
+ <script>
2
+ import { GlIcon, GlTooltipDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
3
+ // eslint-disable-next-line no-restricted-imports
4
+ import { renderDuoChatMarkdownPreview } from '../../../markdown_renderer';
5
+
6
+ export default {
7
+ name: 'DuoChatBaseMessage',
8
+ components: {
9
+ GlIcon,
10
+ },
11
+ directives: {
12
+ SafeHtml,
13
+ GlTooltip: GlTooltipDirective,
14
+ },
15
+ inject: {
16
+ // Note, we likely might move away from Provide/Inject for this
17
+ // and only ship the versions that are currently in the default
18
+ // See https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/3953#note_1762834219
19
+ // for more context.
20
+ renderGFM: {
21
+ from: 'renderGFM',
22
+ default: () => (element) => {
23
+ element.classList.add('gl-markdown', 'gl-compact-markdown', 'gl-text-sm');
24
+ },
25
+ },
26
+ renderMarkdown: {
27
+ from: 'renderMarkdown',
28
+ default: () => renderDuoChatMarkdownPreview,
29
+ },
30
+ },
31
+ props: {
32
+ /**
33
+ * A message object
34
+ */
35
+ message: {
36
+ type: Object,
37
+ required: true,
38
+ },
39
+ },
40
+ computed: {
41
+ messageContent() {
42
+ return this.renderMarkdown(this.message.content);
43
+ },
44
+ renderedError() {
45
+ return this.renderMarkdown(this.message.errors?.join('; ') || '');
46
+ },
47
+ hasError() {
48
+ return Boolean(this.message?.errors?.length);
49
+ },
50
+ },
51
+ mounted() {
52
+ this.hydrateContentWithGFM();
53
+ },
54
+ updated() {
55
+ this.hydrateContentWithGFM();
56
+ },
57
+ methods: {
58
+ hydrateContentWithGFM() {
59
+ if (this.$refs.content) {
60
+ this.$nextTick(this.renderGFM(this.$refs.content, this.message.role));
61
+ }
62
+ },
63
+ },
64
+ };
65
+ </script>
66
+ <template>
67
+ <div class="duo-chat-message gl-mb-4 gl-rounded-lg gl-leading-20 gl-break-anywhere">
68
+ <gl-icon
69
+ v-if="hasError"
70
+ name="status_warning_borderless"
71
+ :size="16"
72
+ class="error-icon gl-border gl-mr-3 gl-shrink-0 gl-rounded-full gl-border-red-500 gl-text-red-600"
73
+ data-testid="error"
74
+ />
75
+ <div ref="content-wrapper" :class="{ 'has-error': hasError }">
76
+ <div v-if="hasError" ref="error-message" v-safe-html="renderedError"></div>
77
+ <div v-else>
78
+ <slot name="message" v-bind="{ content: message.content, htmlContent: messageContent }">
79
+ <div ref="content" v-safe-html="messageContent"></div>
80
+ </slot>
81
+ </div>
82
+ </div>
83
+ </div>
84
+ </template>
@@ -0,0 +1,19 @@
1
+ <script>
2
+ import AgentMessage from './message_agent.vue';
3
+
4
+ export default {
5
+ name: 'DuoChatInputRequestedMessage',
6
+ components: {
7
+ AgentMessage,
8
+ },
9
+ props: {
10
+ message: {
11
+ required: true,
12
+ type: Object,
13
+ },
14
+ },
15
+ };
16
+ </script>
17
+ <template>
18
+ <agent-message :message="message" class="duo-highlight-message input-requested" />
19
+ </template>
@@ -0,0 +1,52 @@
1
+ <script>
2
+ import { GlLink } from '@gitlab/ui';
3
+ import BaseMessage from './message_base.vue';
4
+
5
+ export default {
6
+ name: 'DuoChatToolMessage',
7
+ components: {
8
+ BaseMessage,
9
+ GlLink,
10
+ },
11
+ provide: {
12
+ renderGFM: {
13
+ from: 'renderGFM',
14
+ default: () => (element) => {
15
+ element.classList.add('gl-markdown', 'gl-compact-markdown');
16
+ element.classList.add('duo-system-message', 'gl-text-sm');
17
+ },
18
+ },
19
+ },
20
+ props: {
21
+ message: {
22
+ required: true,
23
+ type: Object,
24
+ },
25
+ },
26
+ computed: {
27
+ messageFilePath() {
28
+ return this.message.tool_info?.args?.file_path;
29
+ },
30
+ },
31
+ methods: {
32
+ onOpenFilePath() {
33
+ this.$emit('open-file-path', this.messageFilePath);
34
+ },
35
+ },
36
+ };
37
+ </script>
38
+ <template>
39
+ <base-message :message="message">
40
+ <template #message="{ content }">
41
+ <span class="gl-text-sm">{{ content }}</span>
42
+ <gl-link
43
+ v-if="messageFilePath"
44
+ class="gl-markdown file-path-link gl-text-sm"
45
+ data-testid="file-path-link"
46
+ @click.prevent="onOpenFilePath"
47
+ >
48
+ <code>{{ messageFilePath }}</code>
49
+ </gl-link>
50
+ </template>
51
+ </base-message>
52
+ </template>
@@ -0,0 +1,32 @@
1
+ <script>
2
+ import { GlButton } from '@gitlab/ui';
3
+ import AgentMessage from './message_agent.vue';
4
+
5
+ export const WORKFLOW_NEW_APP = 'workflow-new';
6
+
7
+ export default {
8
+ name: 'DuoChatWorkflowEndMessage',
9
+ components: {
10
+ AgentMessage,
11
+ GlButton,
12
+ },
13
+ workflowEndMessage: {
14
+ content:
15
+ "Review the changes. To improve the implementation, create another workflow and describe the specific changes you'd like to see.",
16
+ },
17
+ newRoute: {
18
+ name: WORKFLOW_NEW_APP,
19
+ },
20
+ };
21
+ </script>
22
+ <template>
23
+ <agent-message :message="$options.workflowEndMessage">
24
+ <template #message="{ content }">
25
+ <p>
26
+ {{ content }}
27
+ </p>
28
+
29
+ <gl-button :to="$options.newRoute" class="gl-mt-4">New workflow</gl-button>
30
+ </template>
31
+ </agent-message>
32
+ </template>
@@ -24,6 +24,9 @@ export const MESSAGE_MODEL_ROLES = {
24
24
  user: 'user',
25
25
  system: 'system',
26
26
  assistant: 'assistant',
27
+ tool: 'tool',
28
+ request: 'request',
29
+ workflow_end: 'workflow_end',
27
30
  };
28
31
 
29
32
  export const SELECTED_CONTEXT_ITEMS_DEFAULT_COLLAPSED = true;
@@ -678,6 +678,13 @@ export default {
678
678
  */
679
679
  this.$emit('delete-thread', threadId);
680
680
  },
681
+ onOpenFilePath(filePath) {
682
+ /**
683
+ * Emitted when a file path link is clicked in a chat message.
684
+ * @param {String} filePath The file path to open
685
+ */
686
+ this.$emit('open-file-path', filePath);
687
+ },
681
688
  },
682
689
  i18n,
683
690
  };
@@ -767,6 +774,7 @@ export default {
767
774
  @copy-code-snippet="onCopyCodeSnippet"
768
775
  @copy-message="onCopyMessage"
769
776
  @get-context-item-content="onGetContextItemContent"
777
+ @open-file-path="onOpenFilePath"
770
778
  />
771
779
  <template v-if="!hasMessages && !isLoading">
772
780
  <div
@@ -44,6 +44,36 @@ export const MOCK_RESPONSE_MESSAGE = {
44
44
  timestamp: '2021-04-21T12:00:00.000Z',
45
45
  };
46
46
 
47
+ export const MOCK_TOOL_MESSAGE = {
48
+ id: '123',
49
+ content: "Search for 'duo.*chat.*message' in directory",
50
+ message_type: MESSAGE_MODEL_ROLES.tool,
51
+ };
52
+
53
+ export const MOCK_TOOL_MESSAGE_WITH_LINK = {
54
+ id: '123',
55
+ content: "Search for 'duo.*chat.*message' in directory",
56
+ message_type: MESSAGE_MODEL_ROLES.tool,
57
+ tool_info: {
58
+ args: {
59
+ file_path: '/path/to/file.js',
60
+ },
61
+ },
62
+ };
63
+
64
+ export const MOCK_REQUEST_MESSAGE = {
65
+ id: '123',
66
+ content:
67
+ 'On the left, review the proposed plan. Then ask questions or request changes. To execute the plan, select Approve plan.',
68
+ message_type: MESSAGE_MODEL_ROLES.request,
69
+ };
70
+
71
+ export const MOCK_WORKFLOW_END_MESSAGE = {
72
+ id: '123',
73
+ content: "Search for 'duo.*chat.*message' in directory",
74
+ message_type: MESSAGE_MODEL_ROLES.workflow_end,
75
+ };
76
+
47
77
  export const generateSeparateChunks = (n) => {
48
78
  const res = [];
49
79
  for (let i = 1; i <= n; i += 1) {