@vibe-forge/client 0.10.1 → 0.11.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 (133) hide show
  1. package/dist/assets/{arc-C1rWFTer.js → arc-CSepokz3.js} +1 -1
  2. package/dist/assets/{blockDiagram-c4efeb88-DlZ9x70F.js → blockDiagram-c4efeb88-D0ARcoNf.js} +1 -1
  3. package/dist/assets/{c4Diagram-c83219d4-BKKxi__y.js → c4Diagram-c83219d4-BysYF9kP.js} +1 -1
  4. package/dist/assets/channel-CeKPk6Nd.js +1 -0
  5. package/dist/assets/{classDiagram-beda092f-CVGPySZq.js → classDiagram-beda092f-BG1GhIOL.js} +1 -1
  6. package/dist/assets/{classDiagram-v2-2358418a-7kp8GVVj.js → classDiagram-v2-2358418a-Dd08uGSH.js} +1 -1
  7. package/dist/assets/clone-CrkD2PuD.js +1 -0
  8. package/dist/assets/{createText-1719965b-Dykv8kT9.js → createText-1719965b-CigPEIEn.js} +1 -1
  9. package/dist/assets/{cssMode-B59COYVW.js → cssMode-MjflyEfm.js} +1 -1
  10. package/dist/assets/{edges-96097737-CkZ1ZBro.js → edges-96097737-DuTBJJRv.js} +1 -1
  11. package/dist/assets/{erDiagram-0228fc6a-281ADcRp.js → erDiagram-0228fc6a-Cp1bL7Y7.js} +1 -1
  12. package/dist/assets/{flowDb-c6c81e3f-BQjX_flP.js → flowDb-c6c81e3f-BfKbhiq5.js} +1 -1
  13. package/dist/assets/{flowDiagram-50d868cf-DMHZTjES.js → flowDiagram-50d868cf-m7gGc3PK.js} +1 -1
  14. package/dist/assets/flowDiagram-v2-4f6560a1-4ZU4bdp1.js +1 -0
  15. package/dist/assets/{flowchart-elk-definition-6af322e1-CI3yz4z8.js → flowchart-elk-definition-6af322e1-EVeTDRRK.js} +1 -1
  16. package/dist/assets/{freemarker2-DWnWjibn.js → freemarker2-Bb3-QAIN.js} +1 -1
  17. package/dist/assets/{ganttDiagram-a2739b55-B3IING9L.js → ganttDiagram-a2739b55-DslB2U0R.js} +1 -1
  18. package/dist/assets/{gitGraphDiagram-82fe8481-CnArIr_T.js → gitGraphDiagram-82fe8481-C-KFWMXL.js} +1 -1
  19. package/dist/assets/{graph-BZ1F0Yve.js → graph-CukaUc0o.js} +1 -1
  20. package/dist/assets/{handlebars-C1QH9qTz.js → handlebars-C4le-2Y6.js} +1 -1
  21. package/dist/assets/{html-D1NkqHjC.js → html-CjNiRs5S.js} +1 -1
  22. package/dist/assets/{htmlMode-DAZCE_rA.js → htmlMode-B73_3-We.js} +1 -1
  23. package/dist/assets/{index-5325376f-Da9zSHjA.js → index-5325376f-CVISZFPw.js} +1 -1
  24. package/dist/assets/{index-C0vjF3D0.js → index-BZosmb5_.js} +336 -336
  25. package/dist/assets/index-C1oh0w9H.css +32 -0
  26. package/dist/assets/{infoDiagram-8eee0895-DYbFvRM7.js → infoDiagram-8eee0895-DoirLE1K.js} +1 -1
  27. package/dist/assets/{javascript-CoMjGRHa.js → javascript-BDjnqJFP.js} +1 -1
  28. package/dist/assets/{journeyDiagram-c64418c1-Boebox0b.js → journeyDiagram-c64418c1-Ckn-p2CM.js} +1 -1
  29. package/dist/assets/{jsonMode-D__gAvuz.js → jsonMode-C-ftOc5j.js} +1 -1
  30. package/dist/assets/{layout-CTcHNbHp.js → layout-Z7yUG7hB.js} +1 -1
  31. package/dist/assets/{line-4AwinCz2.js → line-DPG_cfAy.js} +1 -1
  32. package/dist/assets/{linear-CeSMLzJW.js → linear--GSeVfMi.js} +1 -1
  33. package/dist/assets/{liquid-DZF6egdE.js → liquid-COiLZ9py.js} +1 -1
  34. package/dist/assets/{lspLanguageFeatures-6K4lv5S2.js → lspLanguageFeatures-DGmhryFq.js} +1 -1
  35. package/dist/assets/{mdx-Cnt4ka6w.js → mdx-BpL87Gej.js} +1 -1
  36. package/dist/assets/{mermaid.core-B0yG5s4D.js → mermaid.core-Cg1CCDo6.js} +4 -4
  37. package/dist/assets/{mindmap-definition-8da855dc-KJEvXMKj.js → mindmap-definition-8da855dc-CKDof1lD.js} +1 -1
  38. package/dist/assets/{pieDiagram-a8764435-17nFAXPJ.js → pieDiagram-a8764435-DwvCaZVE.js} +1 -1
  39. package/dist/assets/{python-DA3TtjDv.js → python-63dBmWV_.js} +1 -1
  40. package/dist/assets/{quadrantDiagram-1e28029f-Dt4vubi-.js → quadrantDiagram-1e28029f-CkzYBQpy.js} +1 -1
  41. package/dist/assets/{razor-CWDJgvX_.js → razor-C50tBqEZ.js} +1 -1
  42. package/dist/assets/{requirementDiagram-08caed73-H6aDyDK-.js → requirementDiagram-08caed73-Brgdjqf4.js} +1 -1
  43. package/dist/assets/{sankeyDiagram-a04cb91d-DxsVtbjI.js → sankeyDiagram-a04cb91d-CGkYexrs.js} +1 -1
  44. package/dist/assets/{sequenceDiagram-c5b8d532-BHa148XJ.js → sequenceDiagram-c5b8d532-D0wE-_J8.js} +1 -1
  45. package/dist/assets/{stateDiagram-1ecb1508-DgwBm8LO.js → stateDiagram-1ecb1508-BYb3NCXZ.js} +1 -1
  46. package/dist/assets/{stateDiagram-v2-c2b004d7-BK7IQLVc.js → stateDiagram-v2-c2b004d7-DrPqi4Pt.js} +1 -1
  47. package/dist/assets/{styles-b4e223ce-DzW27Bc-.js → styles-b4e223ce-DD66TIO4.js} +1 -1
  48. package/dist/assets/{styles-ca3715f6-Dex2GiLT.js → styles-ca3715f6-iy02LHIV.js} +1 -1
  49. package/dist/assets/{styles-d45a18b0-B6fGtDKS.js → styles-d45a18b0-BgqAgJyW.js} +1 -1
  50. package/dist/assets/{svgDrawCommon-b86b1483-B4HYgfV5.js → svgDrawCommon-b86b1483-CDq7ugnw.js} +1 -1
  51. package/dist/assets/{timeline-definition-faaaa080--QSbWb25.js → timeline-definition-faaaa080-DzcLLjK0.js} +1 -1
  52. package/dist/assets/{tsMode-ZM7ocZCH.js → tsMode-BFRFI4ct.js} +1 -1
  53. package/dist/assets/{typescript-CKWDmBCc.js → typescript-CBZQRAPv.js} +1 -1
  54. package/dist/assets/{xml-DuEUAzPi.js → xml-BpWm6upt.js} +1 -1
  55. package/dist/assets/{xychartDiagram-f5964ef8-D09Zkv2K.js → xychartDiagram-f5964ef8-zBN8FmLQ.js} +1 -1
  56. package/dist/assets/{yaml-DL7QPRYk.js → yaml-CqbJPiIP.js} +1 -1
  57. package/dist/index.html +2 -2
  58. package/package.json +10 -10
  59. package/src/api/git.ts +78 -0
  60. package/src/api.ts +24 -0
  61. package/src/components/chat/ChatHeader.tsx +4 -0
  62. package/src/components/chat/ChatHistoryView.tsx +22 -13
  63. package/src/components/chat/git-controls/BranchSwitcherDropdown.tsx +157 -0
  64. package/src/components/chat/git-controls/ChatGitControls.scss +616 -0
  65. package/src/components/chat/git-controls/ChatGitControls.tsx +151 -0
  66. package/src/components/chat/git-controls/GitCommitModal.tsx +199 -0
  67. package/src/components/chat/git-controls/GitCommitModalParts.tsx +151 -0
  68. package/src/components/chat/git-controls/GitOperationsDropdown.tsx +123 -0
  69. package/src/components/chat/git-controls/GitPushModal.tsx +106 -0
  70. package/src/components/chat/git-controls/GitWorktreeDropdown.tsx +68 -0
  71. package/src/components/chat/git-controls/git-branch-utils.ts +88 -0
  72. package/src/components/chat/git-controls/git-commit-utils.ts +79 -0
  73. package/src/components/chat/git-controls/git-mutation-utils.ts +69 -0
  74. package/src/components/chat/git-controls/git-operation-utils.ts +98 -0
  75. package/src/components/chat/git-controls/git-worktree-utils.ts +49 -0
  76. package/src/components/chat/git-controls/use-chat-git-commit.ts +185 -0
  77. package/src/components/chat/git-controls/use-chat-git-controls.ts +200 -0
  78. package/src/components/chat/git-controls/use-chat-git-push-state.ts +19 -0
  79. package/src/components/chat/git-controls/use-chat-git-worktrees.ts +39 -0
  80. package/src/components/chat/messages/MessageStatusNotice.scss +163 -0
  81. package/src/components/chat/messages/MessageStatusNotice.tsx +48 -0
  82. package/src/components/chat/messages/build-chat-history-status-notices.ts +138 -0
  83. package/src/components/chat/sender/@components/sender-body/SenderBody.tsx +0 -24
  84. package/src/components/chat/sender/@core/build-sender-controller-result.ts +0 -6
  85. package/src/components/chat/sender/@hooks/use-sender-controller.ts +0 -2
  86. package/src/components/chat/sender/@types/sender-props.ts +0 -3
  87. package/src/components/chat/sender/Sender.scss +0 -58
  88. package/src/components/chat/sender/Sender.tsx +0 -2
  89. package/src/components/chat/tools/DefaultTool.tsx +84 -208
  90. package/src/components/chat/tools/adapter-claude/ClaudeEditDiff.tsx +30 -0
  91. package/src/components/chat/tools/adapter-claude/GenericClaudeTool.scss +128 -0
  92. package/src/components/chat/tools/adapter-claude/GenericClaudeTool.tsx +119 -0
  93. package/src/components/chat/tools/adapter-claude/claude-tool-edit-builders.ts +109 -0
  94. package/src/components/chat/tools/adapter-claude/claude-tool-field-sections.tsx +83 -0
  95. package/src/components/chat/tools/adapter-claude/claude-tool-operation-builders.ts +135 -0
  96. package/src/components/chat/tools/adapter-claude/claude-tool-presentation.ts +61 -0
  97. package/src/components/chat/tools/adapter-claude/claude-tool-shared.ts +185 -0
  98. package/src/components/chat/tools/adapter-claude/claude-tool-summary.ts +76 -0
  99. package/src/components/chat/tools/adapter-claude/claude-tool-system-builders.ts +125 -0
  100. package/src/components/chat/tools/adapter-claude/claude-tool-task-builders.ts +148 -0
  101. package/src/components/chat/tools/adapter-claude/index.ts +24 -15
  102. package/src/components/chat/tools/core/ToolCallBox.scss +362 -36
  103. package/src/components/chat/tools/core/ToolCallBox.tsx +35 -13
  104. package/src/components/chat/tools/core/ToolDiffViewer.scss +138 -0
  105. package/src/components/chat/tools/core/ToolDiffViewer.tsx +180 -0
  106. package/src/components/chat/tools/core/ToolGroup.scss +52 -74
  107. package/src/components/chat/tools/core/ToolGroup.tsx +25 -40
  108. package/src/components/chat/tools/core/ToolRenderer.tsx +3 -3
  109. package/src/components/chat/tools/core/ToolResultContent.tsx +66 -0
  110. package/src/components/chat/tools/core/ToolSummaryHeader.tsx +67 -0
  111. package/src/components/chat/tools/core/generic-tool-presentation.ts +661 -0
  112. package/src/components/chat/tools/core/tool-content-presence.ts +57 -0
  113. package/src/components/chat/tools/core/tool-display.ts +203 -0
  114. package/src/components/chat/tools/core/tool-field-sections.tsx +132 -0
  115. package/src/components/chat/tools/core/tool-result-content-utils.ts +171 -0
  116. package/src/components/chat/tools/core/tool-summary.ts +206 -0
  117. package/src/components/chat/tools/plugin-chrome-devtools/ChromeDevtoolsTool.tsx +59 -53
  118. package/src/components/chat/tools/task/GetTaskInfoTool.tsx +26 -9
  119. package/src/components/chat/tools/task/ListTasksTool.tsx +22 -9
  120. package/src/components/chat/tools/task/StartTasksTool.tsx +22 -9
  121. package/src/hooks/chat/interaction-state.ts +29 -9
  122. package/src/hooks/chat/session-view-cache.ts +80 -0
  123. package/src/hooks/chat/use-chat-scroll.ts +2 -2
  124. package/src/hooks/chat/use-chat-session-messages.ts +139 -39
  125. package/src/hooks/chat/use-chat-session.ts +2 -2
  126. package/src/resources/locales/en.json +149 -0
  127. package/src/resources/locales/zh.json +149 -0
  128. package/src/routes/ChatRoute.tsx +24 -27
  129. package/src/utils/strip-ansi.ts +26 -0
  130. package/dist/assets/channel-F1aqMANO.js +0 -1
  131. package/dist/assets/clone-B-GCuXNo.js +0 -1
  132. package/dist/assets/flowDiagram-v2-4f6560a1-C5FzdVl1.js +0 -1
  133. package/dist/assets/index-vzEbM21t.css +0 -32
@@ -3,17 +3,20 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'
3
3
  import { useTranslation } from 'react-i18next'
4
4
  import { useLocation } from 'react-router-dom'
5
5
 
6
- import type { ChatErrorBannerState } from '#~/hooks/chat/interaction-state'
6
+ import type { AskUserQuestionParams, ChatMessage, ChatMessageContent, Session } from '@vibe-forge/core'
7
+ import type { SessionInfo } from '@vibe-forge/types'
8
+
7
9
  import type { ChatEffort } from '#~/hooks/chat/use-chat-effort'
8
10
  import type { ModelSelectMenuGroup, ModelSelectOption } from '#~/hooks/chat/use-chat-model-adapter-selection'
9
11
  import type { PermissionMode } from '#~/hooks/chat/use-chat-permission-mode'
10
12
  import { useChatScroll } from '#~/hooks/chat/use-chat-scroll'
11
13
  import { useChatSessionActions } from '#~/hooks/chat/use-chat-session-actions'
12
- import type { AskUserQuestionParams, ChatMessage, ChatMessageContent, Session } from '@vibe-forge/core'
13
- import type { SessionInfo } from '@vibe-forge/types'
14
+
14
15
  import { CurrentTodoList } from './CurrentTodoList'
15
16
  import { NewSessionGuide } from './NewSessionGuide'
16
17
  import { MessageItem } from './messages/MessageItem'
18
+ import { MessageStatusNotice } from './messages/MessageStatusNotice'
19
+ import type { ChatHistoryStatusNotice } from './messages/build-chat-history-status-notices'
17
20
  import { buildMessageTurns } from './messages/message-turns'
18
21
  import { processMessages } from './messages/message-utils'
19
22
  import { Sender } from './sender/Sender'
@@ -26,7 +29,7 @@ export function ChatHistoryView({
26
29
  targetMessageId,
27
30
  targetToolUseId,
28
31
  sessionInfo,
29
- errorBanner,
32
+ historyStatusNotices,
30
33
  onRetryConnection,
31
34
  interactionRequest,
32
35
  onInteractionResponse,
@@ -60,7 +63,7 @@ export function ChatHistoryView({
60
63
  targetMessageId?: string
61
64
  targetToolUseId?: string
62
65
  sessionInfo: SessionInfo | null
63
- errorBanner?: ChatErrorBannerState | null
66
+ historyStatusNotices: ChatHistoryStatusNotice[]
64
67
  onRetryConnection: () => void
65
68
  interactionRequest: { id: string; payload: AskUserQuestionParams } | null
66
69
  onInteractionResponse: (id: string, data: string | string[]) => void
@@ -91,8 +94,9 @@ export function ChatHistoryView({
91
94
  const { t } = useTranslation()
92
95
  const { message } = App.useApp()
93
96
  const location = useLocation()
97
+ const historyRenderCount = messages.length + historyStatusNotices.length
94
98
  const { messagesEndRef, messagesContainerRef, messagesContentRef, showScrollBottom, scrollToBottom } = useChatScroll({
95
- messagesLength: messages.length
99
+ contentVersion: historyRenderCount
96
100
  })
97
101
  const {
98
102
  isCreating,
@@ -173,12 +177,12 @@ export function ChatHistoryView({
173
177
  scrollToBottom('auto')
174
178
  initialScrollDoneRef.current = true
175
179
  }
176
- }, [isReady, location.hash, messages.length, scrollToBottom])
180
+ }, [historyRenderCount, isReady, location.hash, scrollToBottom])
177
181
  useEffect(() => {
178
182
  if (location.hash === '' && !showScrollBottom) {
179
183
  scrollToBottom('auto')
180
184
  }
181
- }, [location.hash, messages.length, scrollToBottom, showScrollBottom])
185
+ }, [historyRenderCount, location.hash, scrollToBottom, showScrollBottom])
182
186
  const handleStartEditing = (messageId: string) => {
183
187
  let isBlocked = false
184
188
 
@@ -288,8 +292,8 @@ export function ChatHistoryView({
288
292
  const targetAttr = targetToolUseId != null && targetToolUseId !== ''
289
293
  ? { key: 'data-tool-use-id', value: targetToolUseId, targetKey: `tool:${targetToolUseId}` }
290
294
  : targetMessageId != null && targetMessageId !== ''
291
- ? { key: 'data-message-id', value: targetMessageId, targetKey: `message:${targetMessageId}` }
292
- : undefined
295
+ ? { key: 'data-message-id', value: targetMessageId, targetKey: `message:${targetMessageId}` }
296
+ : undefined
293
297
  if (targetAttr == null) {
294
298
  handledTargetScrollKeyRef.current = ''
295
299
  return
@@ -462,6 +466,13 @@ export function ChatHistoryView({
462
466
  </React.Fragment>
463
467
  )
464
468
  ))}
469
+ {historyStatusNotices.map(notice => (
470
+ <MessageStatusNotice
471
+ key={notice.id}
472
+ notice={notice}
473
+ onRetryConnection={onRetryConnection}
474
+ />
475
+ ))}
465
476
  <div ref={messagesEndRef} />
466
477
  </div>
467
478
 
@@ -472,7 +483,7 @@ export function ChatHistoryView({
472
483
  )}
473
484
  </div>
474
485
 
475
- {!session?.id && messages.length === 0 && (
486
+ {!session?.id && messages.length === 0 && historyStatusNotices.length === 0 && (
476
487
  <div className='new-session-guide-wrapper'>
477
488
  <NewSessionGuide />
478
489
  </div>
@@ -489,8 +500,6 @@ export function ChatHistoryView({
489
500
  onInterrupt={interrupt}
490
501
  onClear={clearMessages}
491
502
  sessionInfo={sessionInfo}
492
- errorBanner={errorBanner}
493
- onRetryConnection={onRetryConnection}
494
503
  interactionRequest={interactionRequest}
495
504
  onInteractionResponse={onInteractionResponse}
496
505
  placeholder={placeholder}
@@ -0,0 +1,157 @@
1
+ import { Button, Dropdown, Empty, Input, Spin } from 'antd'
2
+ import { useTranslation } from 'react-i18next'
3
+
4
+ import type { GitBranchSummary, GitRepositoryState } from '@vibe-forge/types'
5
+
6
+ export function BranchSwitcherDropdown({
7
+ availableLocalBranches,
8
+ currentBranchLabel,
9
+ isBusy,
10
+ isLoading,
11
+ open,
12
+ repoState,
13
+ branchQuery,
14
+ canCreateBranch,
15
+ hasBranchResults,
16
+ remoteBranches,
17
+ onCreateBranch,
18
+ onOpenChange,
19
+ onQueryChange,
20
+ onSwitchBranch
21
+ }: {
22
+ availableLocalBranches: GitBranchSummary[]
23
+ currentBranchLabel: string
24
+ isBusy: boolean
25
+ isLoading: boolean
26
+ open: boolean
27
+ repoState: GitRepositoryState
28
+ branchQuery: string
29
+ canCreateBranch: boolean
30
+ hasBranchResults: boolean
31
+ remoteBranches: GitBranchSummary[]
32
+ onCreateBranch: (name: string) => void
33
+ onOpenChange: (open: boolean) => void
34
+ onQueryChange: (value: string) => void
35
+ onSwitchBranch: (branch: GitBranchSummary) => void
36
+ }) {
37
+ const { t } = useTranslation()
38
+
39
+ const renderBranchSection = (title: string, branches: GitBranchSummary[]) => {
40
+ if (branches.length === 0) {
41
+ return null
42
+ }
43
+
44
+ return (
45
+ <div className='chat-header-git__section'>
46
+ <span className='chat-header-git__section-label'>{title}</span>
47
+ {branches.map(branch => {
48
+ return (
49
+ <button
50
+ key={`${branch.kind}:${branch.name}`}
51
+ type='button'
52
+ className='chat-header-git__branch-row'
53
+ disabled={isBusy}
54
+ title={branch.name}
55
+ onClick={() => onSwitchBranch(branch)}
56
+ >
57
+ <div className='chat-header-git__branch-row-main'>
58
+ <span className='chat-header-git__row-icon material-symbols-rounded'>
59
+ {branch.kind === 'local' ? 'call_split' : 'cloud_sync'}
60
+ </span>
61
+ <span className='chat-header-git__row-copy'>
62
+ <span className='chat-header-git__row-title'>{branch.name}</span>
63
+ </span>
64
+ </div>
65
+ {branch.isCurrent
66
+ ? (
67
+ <span className='chat-header-git__row-state material-symbols-rounded'>check</span>
68
+ )
69
+ : null}
70
+ </button>
71
+ )
72
+ })}
73
+ </div>
74
+ )
75
+ }
76
+
77
+ return (
78
+ <Dropdown
79
+ open={open}
80
+ placement='bottomLeft'
81
+ trigger={['click']}
82
+ onOpenChange={onOpenChange}
83
+ dropdownRender={() => (
84
+ <div className='chat-header-git__overlay chat-header-git__overlay--branches'>
85
+ <Input
86
+ allowClear
87
+ autoFocus
88
+ className='chat-header-git__search'
89
+ placeholder={t('chat.gitSearchBranches')}
90
+ prefix={<span className='material-symbols-rounded'>search</span>}
91
+ value={branchQuery}
92
+ onChange={(event) => onQueryChange(event.target.value)}
93
+ onPressEnter={() => {
94
+ if (canCreateBranch) {
95
+ onCreateBranch(branchQuery)
96
+ }
97
+ }}
98
+ />
99
+
100
+ {canCreateBranch && (
101
+ <button
102
+ type='button'
103
+ className='chat-header-git__create-row'
104
+ disabled={isBusy}
105
+ onClick={() => onCreateBranch(branchQuery)}
106
+ >
107
+ <div className='chat-header-git__branch-row-main'>
108
+ <span className='chat-header-git__row-icon material-symbols-rounded'>add</span>
109
+ <span className='chat-header-git__row-title'>
110
+ {t('chat.gitCreateBranchWithName', { branch: branchQuery.trim() })}
111
+ </span>
112
+ </div>
113
+ </button>
114
+ )}
115
+
116
+ {isLoading &&
117
+ availableLocalBranches.length === 0 &&
118
+ remoteBranches.length === 0
119
+ ? (
120
+ <div className='chat-header-git__loading'>
121
+ <Spin size='small' />
122
+ </div>
123
+ )
124
+ : hasBranchResults
125
+ ? (
126
+ <div className='chat-header-git__sections'>
127
+ {renderBranchSection(t('chat.gitBranchesLocal'), availableLocalBranches)}
128
+ {renderBranchSection(t('chat.gitBranchesRemote'), remoteBranches)}
129
+ </div>
130
+ )
131
+ : (
132
+ <div className='chat-header-git__empty'>
133
+ <Empty
134
+ image={Empty.PRESENTED_IMAGE_SIMPLE}
135
+ description={t('chat.gitNoBranches')}
136
+ />
137
+ </div>
138
+ )}
139
+ </div>
140
+ )}
141
+ >
142
+ <Button
143
+ type='text'
144
+ className={`chat-header-git__trigger ${open ? 'is-open' : ''} ${isBusy ? 'is-disabled' : ''}`}
145
+ title={t('chat.gitBranchSwitcher')}
146
+ aria-label={t('chat.gitBranchSwitcher')}
147
+ >
148
+ <span className='chat-header-git__trigger-main'>
149
+ <span className='material-symbols-rounded'>call_split</span>
150
+ <span className='chat-header-git__trigger-label'>{currentBranchLabel}</span>
151
+ {repoState.hasChanges && <span className='chat-header-git__dirty-dot' />}
152
+ </span>
153
+ <span className='chat-header-git__trigger-chevron material-symbols-rounded'>expand_more</span>
154
+ </Button>
155
+ </Dropdown>
156
+ )
157
+ }