@vibe-forge/client 0.5.0 → 0.7.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 (134) hide show
  1. package/AGENTS.md +37 -0
  2. package/dist/assets/{arc-C4ymrcSQ.js → arc-DidNmF3v.js} +1 -1
  3. package/dist/assets/{blockDiagram-c4efeb88-CeB7-kgP.js → blockDiagram-c4efeb88-CDnN61xv.js} +1 -1
  4. package/dist/assets/{c4Diagram-c83219d4-C935Im8S.js → c4Diagram-c83219d4-B3k8deko.js} +1 -1
  5. package/dist/assets/channel-Cde3vJGp.js +1 -0
  6. package/dist/assets/{classDiagram-beda092f-B9IV13KI.js → classDiagram-beda092f-BdANZ7yV.js} +1 -1
  7. package/dist/assets/{classDiagram-v2-2358418a-CXF_K4fE.js → classDiagram-v2-2358418a-ow-iRMSq.js} +1 -1
  8. package/dist/assets/clone-LUH_zyxR.js +1 -0
  9. package/dist/assets/{createText-1719965b-DwX8iC5F.js → createText-1719965b-Wz6GZTHU.js} +1 -1
  10. package/dist/assets/{edges-96097737-9P1uH1RE.js → edges-96097737-D0RiugNT.js} +1 -1
  11. package/dist/assets/{erDiagram-0228fc6a-ixeGTFvg.js → erDiagram-0228fc6a-CthowAHZ.js} +1 -1
  12. package/dist/assets/{flowDb-c6c81e3f-G1gSTTBI.js → flowDb-c6c81e3f-C-joVb9m.js} +1 -1
  13. package/dist/assets/{flowDiagram-50d868cf-CzrG99nD.js → flowDiagram-50d868cf-Bx-hAyRl.js} +1 -1
  14. package/dist/assets/flowDiagram-v2-4f6560a1-CVxV-0Ew.js +1 -0
  15. package/dist/assets/{flowchart-elk-definition-6af322e1-sFCoysWa.js → flowchart-elk-definition-6af322e1-CpGiH0RQ.js} +1 -1
  16. package/dist/assets/{ganttDiagram-a2739b55-Ccsk_Lru.js → ganttDiagram-a2739b55-B2rBCB_P.js} +1 -1
  17. package/dist/assets/{gitGraphDiagram-82fe8481-CwathJ6H.js → gitGraphDiagram-82fe8481-BH6XyEeG.js} +1 -1
  18. package/dist/assets/{graph-DRCU-8Rz.js → graph-De4BWXYq.js} +1 -1
  19. package/dist/assets/{index-5325376f-Bq-fg2i_.js → index-5325376f-DciqDx2s.js} +1 -1
  20. package/dist/assets/index-IW7UIMcY.js +545 -0
  21. package/dist/assets/{index-CHMuZ5-1.css → index-fcJ9v94I.css} +1 -1
  22. package/dist/assets/{infoDiagram-8eee0895-JBcUkJ6T.js → infoDiagram-8eee0895-CiV1aI2C.js} +1 -1
  23. package/dist/assets/{journeyDiagram-c64418c1-DsdQU-R8.js → journeyDiagram-c64418c1-DeClao2V.js} +1 -1
  24. package/dist/assets/{layout-s0slG1OL.js → layout-B5GMBoJz.js} +1 -1
  25. package/dist/assets/{line-CymFqgW6.js → line-CgBpZ2AR.js} +1 -1
  26. package/dist/assets/{linear-lDQVZ6aQ.js → linear-Cd0IpBll.js} +1 -1
  27. package/dist/assets/{mermaid.core-Cmlqga_E.js → mermaid.core-CZnO8AvM.js} +4 -4
  28. package/dist/assets/{mindmap-definition-8da855dc-CqqTDJn_.js → mindmap-definition-8da855dc-0XmBTp3E.js} +1 -1
  29. package/dist/assets/{pieDiagram-a8764435-BL2Ajx7Z.js → pieDiagram-a8764435-BNAROg0P.js} +1 -1
  30. package/dist/assets/{quadrantDiagram-1e28029f-ClL_3ASt.js → quadrantDiagram-1e28029f-Df_gmUZ3.js} +1 -1
  31. package/dist/assets/{requirementDiagram-08caed73-CB1RgE3K.js → requirementDiagram-08caed73-CJucWU8H.js} +1 -1
  32. package/dist/assets/{sankeyDiagram-a04cb91d-tgleEYiD.js → sankeyDiagram-a04cb91d-CHiMn2x-.js} +1 -1
  33. package/dist/assets/{sequenceDiagram-c5b8d532-DlatQT5R.js → sequenceDiagram-c5b8d532-C9TpmcH3.js} +1 -1
  34. package/dist/assets/{stateDiagram-1ecb1508-B--MLqRs.js → stateDiagram-1ecb1508-Cvptb-Zj.js} +1 -1
  35. package/dist/assets/{stateDiagram-v2-c2b004d7-CRMZ6Dpx.js → stateDiagram-v2-c2b004d7-nRJ7hzpx.js} +1 -1
  36. package/dist/assets/{styles-b4e223ce-CPiYHfUz.js → styles-b4e223ce-iTClb1YD.js} +1 -1
  37. package/dist/assets/{styles-ca3715f6-B9UKPAzX.js → styles-ca3715f6-BstDoS6h.js} +1 -1
  38. package/dist/assets/{styles-d45a18b0-BC1Ak1So.js → styles-d45a18b0-Ci8lW61F.js} +1 -1
  39. package/dist/assets/{svgDrawCommon-b86b1483-DV8R0g-n.js → svgDrawCommon-b86b1483-DxM1HDTD.js} +1 -1
  40. package/dist/assets/{timeline-definition-faaaa080-CiqGS5DC.js → timeline-definition-faaaa080-bmNqY66u.js} +1 -1
  41. package/dist/assets/{xychartDiagram-f5964ef8-h6VSD3GE.js → xychartDiagram-f5964ef8-0OjuuJfh.js} +1 -1
  42. package/dist/index.html +2 -2
  43. package/package.json +10 -8
  44. package/src/App.tsx +20 -168
  45. package/src/api/base.ts +116 -7
  46. package/src/api.ts +3 -1
  47. package/src/components/ArchiveView.tsx +5 -5
  48. package/src/components/ConfigView.tsx +3 -3
  49. package/src/components/{AutomationView → automation-view}/index.tsx +10 -9
  50. package/src/components/{BenchmarkView → benchmark-view}/index.tsx +5 -4
  51. package/src/components/chat/ChatHeader.tsx +6 -6
  52. package/src/components/chat/ChatHistoryView.tsx +64 -16
  53. package/src/components/chat/ChatTimelineView.tsx +3 -3
  54. package/src/components/chat/CurrentTodoList.scss +56 -27
  55. package/src/components/chat/{Sender → sender}/Sender.scss +201 -71
  56. package/src/components/chat/{Sender → sender}/Sender.tsx +104 -42
  57. package/src/components/chat/tools/core/ToolGroup.tsx +1 -1
  58. package/src/components/config/ConfigSectionForm.tsx +1 -1
  59. package/src/components/layout/AppShell.scss +19 -0
  60. package/src/components/layout/AppShell.tsx +45 -0
  61. package/src/hooks/chat/model-selector.ts +150 -0
  62. package/src/hooks/chat/use-chat-adapter.ts +20 -8
  63. package/src/hooks/chat/use-chat-models.tsx +79 -74
  64. package/src/hooks/chat/use-chat-permission-mode.ts +14 -10
  65. package/src/hooks/chat/use-chat-session-actions.ts +19 -11
  66. package/src/hooks/chat/use-chat-session-messages.ts +46 -6
  67. package/src/hooks/chat/use-chat-session.ts +42 -1
  68. package/src/hooks/use-app-preferences.ts +41 -0
  69. package/src/hooks/use-session-subscription.ts +101 -0
  70. package/src/hooks/use-sidebar-navigation.ts +35 -0
  71. package/src/resources/locales/en.json +6 -0
  72. package/src/resources/locales/zh.json +6 -0
  73. package/src/routes/AppRoutes.tsx +22 -0
  74. package/src/routes/ArchiveRoute.tsx +5 -0
  75. package/src/routes/AutomationRoute.tsx +5 -0
  76. package/src/routes/BenchmarkRoute.tsx +5 -0
  77. package/src/{components/Chat.scss → routes/ChatRoute.scss} +35 -0
  78. package/src/{components/Chat.tsx → routes/ChatRoute.tsx} +54 -28
  79. package/src/routes/ConfigRoute.tsx +5 -0
  80. package/src/routes/KnowledgeRoute.tsx +5 -0
  81. package/dist/assets/channel-84s1ACzD.js +0 -1
  82. package/dist/assets/clone-B2E8tddE.js +0 -1
  83. package/dist/assets/flowDiagram-v2-4f6560a1-CJfJYbME.js +0 -1
  84. package/dist/assets/index-cGZvDhhU.js +0 -542
  85. /package/src/components/{AutomationView → automation-view}/RuleFormPanel.scss +0 -0
  86. /package/src/components/{AutomationView → automation-view}/RuleFormPanel.tsx +0 -0
  87. /package/src/components/{AutomationView → automation-view}/RuleSidebar.scss +0 -0
  88. /package/src/components/{AutomationView → automation-view}/RuleSidebar.tsx +0 -0
  89. /package/src/components/{AutomationView → automation-view}/RunHistoryPanel.scss +0 -0
  90. /package/src/components/{AutomationView → automation-view}/RunHistoryPanel.tsx +0 -0
  91. /package/src/components/{AutomationView → automation-view}/TaskList.scss +0 -0
  92. /package/src/components/{AutomationView → automation-view}/TaskList.tsx +0 -0
  93. /package/src/components/{AutomationView → automation-view}/TriggerList.scss +0 -0
  94. /package/src/components/{AutomationView → automation-view}/TriggerList.tsx +0 -0
  95. /package/src/components/{AutomationView/AutomationView.scss → automation-view/index.scss} +0 -0
  96. /package/src/components/{AutomationView → automation-view}/types.ts +0 -0
  97. /package/src/components/{BenchmarkView → benchmark-view}/BenchmarkCasePanel.scss +0 -0
  98. /package/src/components/{BenchmarkView → benchmark-view}/BenchmarkCasePanel.tsx +0 -0
  99. /package/src/components/{BenchmarkView → benchmark-view}/BenchmarkSidebar.scss +0 -0
  100. /package/src/components/{BenchmarkView → benchmark-view}/BenchmarkSidebar.tsx +0 -0
  101. /package/src/components/{BenchmarkView → benchmark-view}/BenchmarkView.scss +0 -0
  102. /package/src/components/{BenchmarkView → benchmark-view}/types.ts +0 -0
  103. /package/src/components/{BenchmarkView → benchmark-view}/utils.ts +0 -0
  104. /package/src/components/chat/{Messages → messages}/MessageFooter.tsx +0 -0
  105. /package/src/components/chat/{Messages → messages}/MessageItem.scss +0 -0
  106. /package/src/components/chat/{Messages → messages}/MessageItem.tsx +0 -0
  107. /package/src/components/chat/{Messages → messages}/message-utils.ts +0 -0
  108. /package/src/components/chat/{Sender → sender}/CompletionMenu.scss +0 -0
  109. /package/src/components/chat/{Sender → sender}/CompletionMenu.tsx +0 -0
  110. /package/src/components/chat/{Sender → sender}/ThinkingStatus.scss +0 -0
  111. /package/src/components/chat/{Sender → sender}/ThinkingStatus.tsx +0 -0
  112. /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/EventList.scss +0 -0
  113. /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/EventList.tsx +0 -0
  114. /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/gantt.ts +0 -0
  115. /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/git-graph.ts +0 -0
  116. /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/index.scss +0 -0
  117. /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/index.tsx +0 -0
  118. /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/mermaid.ts +0 -0
  119. /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/types.ts +0 -0
  120. /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/utils.ts +0 -0
  121. /package/src/components/config/{recordEditors → record-editors}/BooleanRecordEditor.scss +0 -0
  122. /package/src/components/config/{recordEditors → record-editors}/BooleanRecordEditor.tsx +0 -0
  123. /package/src/components/config/{recordEditors → record-editors}/ChannelRecordEditor.scss +0 -0
  124. /package/src/components/config/{recordEditors → record-editors}/ChannelRecordEditor.tsx +0 -0
  125. /package/src/components/config/{recordEditors → record-editors}/KeyValueEditor.scss +0 -0
  126. /package/src/components/config/{recordEditors → record-editors}/KeyValueEditor.tsx +0 -0
  127. /package/src/components/config/{recordEditors → record-editors}/McpServersRecordEditor.scss +0 -0
  128. /package/src/components/config/{recordEditors → record-editors}/McpServersRecordEditor.tsx +0 -0
  129. /package/src/components/config/{recordEditors → record-editors}/ModelServicesRecordEditor.scss +0 -0
  130. /package/src/components/config/{recordEditors → record-editors}/ModelServicesRecordEditor.tsx +0 -0
  131. /package/src/components/config/{recordEditors → record-editors}/RecordEditors.scss +0 -0
  132. /package/src/components/config/{recordEditors → record-editors}/RecordJsonEditor.scss +0 -0
  133. /package/src/components/config/{recordEditors → record-editors}/RecordJsonEditor.tsx +0 -0
  134. /package/src/components/config/{recordEditors → record-editors}/index.tsx +0 -0
@@ -1,20 +1,22 @@
1
1
  import React, { useEffect, useMemo, useRef } from 'react'
2
+ import { useTranslation } from 'react-i18next'
2
3
 
4
+ import type { PermissionMode } from '#~/hooks/chat/use-chat-permission-mode'
5
+ import { useChatScroll } from '#~/hooks/chat/use-chat-scroll'
6
+ import { useChatSessionActions } from '#~/hooks/chat/use-chat-session-actions'
3
7
  import type { AskUserQuestionParams, ChatMessage, ChatMessageContent, Session, SessionInfo } from '@vibe-forge/core'
4
8
  import { CurrentTodoList } from './CurrentTodoList'
5
- import { MessageItem } from './Messages/MessageItem'
9
+ import { MessageItem } from './messages/MessageItem'
10
+ import { processMessages } from './messages/message-utils'
6
11
  import { NewSessionGuide } from './NewSessionGuide'
7
- import { Sender } from './Sender/Sender'
12
+ import { Sender } from './sender/Sender'
8
13
  import { ToolGroup } from './tools/core/ToolGroup'
9
- import { processMessages } from './Messages/message-utils'
10
- import type { PermissionMode } from '#~/hooks/chat/use-chat-permission-mode'
11
- import { useChatScroll } from '#~/hooks/chat/use-chat-scroll'
12
- import { useChatSessionActions } from '#~/hooks/chat/use-chat-session-actions'
13
14
 
14
15
  interface ModelSelectOption {
15
16
  value: string
16
17
  label: React.ReactNode
17
18
  searchText: string
19
+ displayLabel: string
18
20
  }
19
21
 
20
22
  interface ModelSelectGroup {
@@ -27,11 +29,12 @@ export function ChatHistoryView({
27
29
  messages,
28
30
  session,
29
31
  sessionInfo,
32
+ connectionError,
33
+ onRetryConnection,
30
34
  interactionRequest,
31
35
  onInteractionResponse,
36
+ setMessages,
32
37
  onClearMessages,
33
- onSend,
34
- onSendContent,
35
38
  placeholder,
36
39
  modelOptions,
37
40
  selectedModel,
@@ -50,11 +53,12 @@ export function ChatHistoryView({
50
53
  messages: ChatMessage[]
51
54
  session?: Session
52
55
  sessionInfo: SessionInfo | null
56
+ connectionError?: string | null
57
+ onRetryConnection: () => void
53
58
  interactionRequest: { id: string; payload: AskUserQuestionParams } | null
54
59
  onInteractionResponse: (id: string, data: string | string[]) => void
60
+ setMessages: React.Dispatch<React.SetStateAction<ChatMessage[]>>
55
61
  onClearMessages: () => void
56
- onSend: (text: string) => void
57
- onSendContent: (content: ChatMessageContent[]) => void
58
62
  placeholder?: string
59
63
  modelOptions: ModelSelectGroup[]
60
64
  selectedModel?: string
@@ -69,6 +73,7 @@ export function ChatHistoryView({
69
73
  modelUnavailable: boolean
70
74
  hasAvailableModels: boolean
71
75
  }) {
76
+ const { t } = useTranslation()
72
77
  const { messagesEndRef, messagesContainerRef, messagesContentRef, showScrollBottom, scrollToBottom } = useChatScroll({
73
78
  messagesLength: messages.length
74
79
  })
@@ -81,15 +86,49 @@ export function ChatHistoryView({
81
86
  onClearMessages
82
87
  })
83
88
  const initialScrollDoneRef = useRef(false)
89
+ const buildUserMessage = (content: string | ChatMessageContent[]): ChatMessage => {
90
+ const id = globalThis.crypto?.randomUUID
91
+ ? globalThis.crypto.randomUUID()
92
+ : `local-${Date.now()}-${Math.random().toString(16).slice(2)}`
93
+ return {
94
+ id,
95
+ role: 'user' as const,
96
+ content,
97
+ createdAt: Date.now()
98
+ }
99
+ }
100
+
84
101
  const handleSend = async (text: string) => {
85
- await send(text)
86
- if (session?.id) {
87
- onSend(text)
102
+ if (!session?.id) {
103
+ const optimisticMessage = buildUserMessage(text)
104
+ setMessages((prev) => [...prev, optimisticMessage])
105
+ const didSend = await send(text)
106
+ if (!didSend) {
107
+ setMessages((prev) => prev.filter((message) => message.id !== optimisticMessage.id))
108
+ }
109
+ return
110
+ }
111
+
112
+ const didSend = await send(text)
113
+ if (didSend) {
114
+ setMessages((prev) => [...prev, buildUserMessage(text)])
88
115
  }
89
116
  }
90
117
  const handleSendContent = async (content: ChatMessageContent[]) => {
91
- await sendContent(content)
92
- onSendContent(content)
118
+ if (!session?.id) {
119
+ const optimisticMessage = buildUserMessage(content)
120
+ setMessages((prev) => [...prev, optimisticMessage])
121
+ const didSend = await sendContent(content)
122
+ if (!didSend) {
123
+ setMessages((prev) => prev.filter((message) => message.id !== optimisticMessage.id))
124
+ }
125
+ return
126
+ }
127
+
128
+ const didSend = await sendContent(content)
129
+ if (didSend) {
130
+ setMessages((prev) => [...prev, buildUserMessage(content)])
131
+ }
93
132
  }
94
133
  useEffect(() => {
95
134
  initialScrollDoneRef.current = false
@@ -111,6 +150,12 @@ export function ChatHistoryView({
111
150
  <>
112
151
  <div className={`chat-messages ${isReady ? 'ready' : ''}`} ref={messagesContainerRef}>
113
152
  <div className='chat-messages-content' ref={messagesContentRef}>
153
+ {!session?.id && isCreating && (
154
+ <div className='chat-pending-session-banner'>
155
+ <span className='material-symbols-rounded'>hourglass_top</span>
156
+ <span>{t('common.creatingChat')}</span>
157
+ </div>
158
+ )}
114
159
  {renderItems.map((item, index) => {
115
160
  if (item.type === 'message') {
116
161
  return (
@@ -141,7 +186,7 @@ export function ChatHistoryView({
141
186
  )}
142
187
  </div>
143
188
 
144
- {!session?.id && (
189
+ {!session?.id && messages.length === 0 && (
145
190
  <div className='new-session-guide-wrapper'>
146
191
  <NewSessionGuide />
147
192
  </div>
@@ -152,10 +197,13 @@ export function ChatHistoryView({
152
197
  <Sender
153
198
  onSend={handleSend}
154
199
  onSendContent={handleSendContent}
200
+ adapterLocked={session?.id != null}
155
201
  sessionStatus={isCreating ? 'running' : session?.status}
156
202
  onInterrupt={interrupt}
157
203
  onClear={clearMessages}
158
204
  sessionInfo={sessionInfo}
205
+ connectionError={connectionError}
206
+ onRetryConnection={onRetryConnection}
159
207
  interactionRequest={interactionRequest}
160
208
  onInteractionResponse={onInteractionResponse}
161
209
  placeholder={placeholder}
@@ -4,9 +4,9 @@ import React from 'react'
4
4
 
5
5
  import type { ChatMessage } from '@vibe-forge/core'
6
6
 
7
- import { SessionTimelinePanel } from './SessionTimelinePanel'
8
- import { SessionTimelineEventList } from './SessionTimelinePanel/EventList'
9
- import type { Task } from './SessionTimelinePanel/types'
7
+ import { SessionTimelinePanel } from './session-timeline-panel'
8
+ import { SessionTimelineEventList } from './session-timeline-panel/EventList'
9
+ import type { Task } from './session-timeline-panel/types'
10
10
 
11
11
  const mockTimelineTask: Task = {
12
12
  startTime: '09:40:00',
@@ -1,4 +1,22 @@
1
1
  .current-todo-container {
2
+ --todo-panel-bg: var(--bg-color);
3
+ --todo-panel-muted-bg: var(--tag-bg);
4
+ --todo-panel-border: var(--border-color);
5
+ --todo-panel-hover-border: var(--primary-color);
6
+ --todo-panel-shadow: 0 2px 4px -1px rgba(0, 0, 0, .06);
7
+ --todo-overlay-shadow: 0 4px 12px rgba(0, 0, 0, .15);
8
+ --todo-track-bg: var(--tag-hover-bg);
9
+ --todo-text: var(--text-color);
10
+ --todo-sub-text: var(--sub-text-color);
11
+ --todo-pending-icon: var(--placeholder-color);
12
+ --todo-hover-bg: var(--tag-bg);
13
+ --todo-priority-high-bg: #fee2e2;
14
+ --todo-priority-high-text: #ef4444;
15
+ --todo-priority-medium-bg: #fef3c7;
16
+ --todo-priority-medium-text: #d97706;
17
+ --todo-priority-low-bg: #d1fae5;
18
+ --todo-priority-low-text: #10b981;
19
+
2
20
  position: relative;
3
21
  margin: 12px 24px 0 24px;
4
22
  z-index: 10;
@@ -9,31 +27,31 @@
9
27
  opacity: .6;
10
28
  .todo-progress-bar {
11
29
  cursor: default;
12
- background: #f9fafb;
30
+ background: var(--todo-panel-muted-bg);
13
31
  box-shadow: none;
14
32
  &:hover {
15
- border-color: #e5e7eb;
33
+ border-color: var(--todo-panel-border);
16
34
  }
17
35
  .progress-info .material-symbols-rounded {
18
- color: #9ca3af;
36
+ color: var(--todo-pending-icon);
19
37
  }
20
38
  }
21
39
  }
22
40
 
23
41
  .todo-progress-bar {
24
- background: white;
25
- border: 1px solid #e5e7eb;
42
+ background: var(--todo-panel-bg);
43
+ border: 1px solid var(--todo-panel-border);
26
44
  border-radius: 8px;
27
45
  padding: 8px 16px;
28
46
  display: flex;
29
47
  align-items: center;
30
48
  gap: 12px;
31
- box-shadow: 0 2px 4px -1px rgba(0, 0, 0, .06);
49
+ box-shadow: var(--todo-panel-shadow);
32
50
  cursor: pointer;
33
51
  transition: all .2s ease;
34
52
 
35
53
  &:hover {
36
- border-color: #3b82f6;
54
+ border-color: var(--todo-panel-hover-border);
37
55
  }
38
56
 
39
57
  .progress-info {
@@ -44,26 +62,26 @@
44
62
 
45
63
  .material-symbols-rounded {
46
64
  font-size: 20px;
47
- color: #3b82f6;
65
+ color: var(--primary-color);
48
66
  }
49
67
 
50
68
  .text {
51
69
  font-size: 13px;
52
70
  font-weight: 500;
53
- color: #374151;
71
+ color: var(--todo-text);
54
72
  }
55
73
  }
56
74
 
57
75
  .progress-track {
58
76
  flex: 1;
59
77
  height: 6px;
60
- background: #f3f4f6;
78
+ background: var(--todo-track-bg);
61
79
  border-radius: 3px;
62
80
  overflow: hidden;
63
81
 
64
82
  .progress-fill {
65
83
  height: 100%;
66
- background: #3b82f6;
84
+ background: var(--primary-color);
67
85
  transition: width .3s ease;
68
86
  }
69
87
  }
@@ -73,12 +91,12 @@
73
91
  border: none;
74
92
  padding: 0;
75
93
  cursor: pointer;
76
- color: #9ca3af;
94
+ color: var(--todo-pending-icon);
77
95
  display: flex;
78
96
  align-items: center;
79
97
 
80
98
  &:hover {
81
- color: #374151;
99
+ color: var(--todo-text);
82
100
  }
83
101
  }
84
102
  }
@@ -88,10 +106,10 @@
88
106
  bottom: calc(100% + 8px);
89
107
  left: 0;
90
108
  right: 0;
91
- background: white;
92
- border: 1px solid #e5e7eb;
109
+ background: var(--todo-panel-bg);
110
+ border: 1px solid var(--todo-panel-border);
93
111
  border-radius: 8px;
94
- box-shadow: 0 4px 12px rgba(0, 0, 0, .15);
112
+ box-shadow: var(--todo-overlay-shadow);
95
113
  animation: slideUp .3s cubic-bezier(.4, 0, .2, 1);
96
114
  overflow: hidden;
97
115
  z-index: 100;
@@ -109,7 +127,7 @@
109
127
  transition: background-color .2s;
110
128
 
111
129
  &:hover {
112
- background-color: #f9fafb;
130
+ background-color: var(--todo-hover-bg);
113
131
  }
114
132
 
115
133
  .icon {
@@ -130,21 +148,21 @@
130
148
 
131
149
  &.status-in_progress {
132
150
  .icon {
133
- color: #3b82f6;
151
+ color: var(--primary-color);
134
152
  animation: spin 2s linear infinite;
135
153
  }
136
154
  .text {
137
- color: #111827;
155
+ color: var(--todo-text);
138
156
  font-weight: 500;
139
157
  }
140
158
  }
141
159
 
142
160
  &.status-pending {
143
161
  .icon {
144
- color: #9ca3af;
162
+ color: var(--todo-pending-icon);
145
163
  }
146
164
  .text {
147
- color: #4b5563;
165
+ color: var(--todo-sub-text);
148
166
  }
149
167
  }
150
168
 
@@ -167,16 +185,16 @@
167
185
  font-weight: 600;
168
186
 
169
187
  &.high {
170
- background: #fee2e2;
171
- color: #ef4444;
188
+ background: var(--todo-priority-high-bg);
189
+ color: var(--todo-priority-high-text);
172
190
  }
173
191
  &.medium {
174
- background: #fef3c7;
175
- color: #d97706;
192
+ background: var(--todo-priority-medium-bg);
193
+ color: var(--todo-priority-medium-text);
176
194
  }
177
195
  &.low {
178
- background: #d1fae5;
179
- color: #10b981;
196
+ background: var(--todo-priority-low-bg);
197
+ color: var(--todo-priority-low-text);
180
198
  }
181
199
  }
182
200
  }
@@ -185,6 +203,17 @@
185
203
  }
186
204
  }
187
205
 
206
+ html.dark .current-todo-container {
207
+ --todo-panel-shadow: 0 8px 24px rgba(0, 0, 0, .24);
208
+ --todo-overlay-shadow: 0 16px 36px rgba(0, 0, 0, .32);
209
+ --todo-priority-high-bg: rgba(248, 113, 113, .16);
210
+ --todo-priority-high-text: #fca5a5;
211
+ --todo-priority-medium-bg: rgba(245, 158, 11, .16);
212
+ --todo-priority-medium-text: #fcd34d;
213
+ --todo-priority-low-bg: rgba(45, 212, 191, .16);
214
+ --todo-priority-low-text: #5eead4;
215
+ }
216
+
188
217
  @keyframes slideDown {
189
218
  from {
190
219
  opacity: 0;
@@ -37,6 +37,54 @@
37
37
  color: var(--placeholder-color);
38
38
  font-size: 12px;
39
39
  }
40
+
41
+ .connection-error-banner {
42
+ display: flex;
43
+ align-items: center;
44
+ justify-content: space-between;
45
+ gap: 12px;
46
+ margin-bottom: 8px;
47
+ padding: 10px 12px;
48
+ border-radius: 10px;
49
+ border: 1px solid rgba(220, 38, 38, .2);
50
+ background: linear-gradient(
51
+ 135deg,
52
+ rgba(254, 242, 242, .95),
53
+ rgba(255, 255, 255, .92)
54
+ );
55
+ }
56
+
57
+ .connection-error-content {
58
+ display: flex;
59
+ align-items: flex-start;
60
+ gap: 10px;
61
+ min-width: 0;
62
+
63
+ .material-symbols-rounded {
64
+ color: #dc2626;
65
+ font-size: 18px;
66
+ line-height: 1;
67
+ margin-top: 1px;
68
+ }
69
+ }
70
+
71
+ .connection-error-copy {
72
+ min-width: 0;
73
+ }
74
+
75
+ .connection-error-title {
76
+ color: #991b1b;
77
+ font-size: 12px;
78
+ font-weight: 600;
79
+ }
80
+
81
+ .connection-error-message {
82
+ margin-top: 2px;
83
+ color: #7f1d1d;
84
+ font-size: 12px;
85
+ line-height: 1.4;
86
+ word-break: break-word;
87
+ }
40
88
  }
41
89
 
42
90
  .file-input-hidden {
@@ -103,27 +151,49 @@
103
151
  display: flex;
104
152
  align-items: center;
105
153
  gap: 4px;
106
- margin-left: 4px;
107
- padding-left: 8px;
108
- border-left: 2px solid var(--border-color);
154
+ margin-left: 6px;
155
+ padding-left: 10px;
156
+ border-left: 1px solid var(--border-color);
109
157
  border-radius: 1px;
110
158
  position: relative;
111
- height: 14px;
159
+ height: auto;
112
160
  align-self: center;
113
161
 
162
+ .ant-cascader {
163
+ display: block;
164
+ }
165
+
114
166
  .info-item {
115
167
  display: flex;
116
168
  align-items: center;
117
- gap: 4px;
118
- font-size: 13px;
169
+ gap: 8px;
170
+ min-height: 28px;
171
+ font-size: 12px;
119
172
  color: var(--sub-text-color, #9ca3af);
120
- background-color: transparent;
121
- padding: 2px 4px;
122
- border-radius: 4px;
173
+ background: linear-gradient(180deg, var(--bg-color), var(--tag-hover-bg, #f3f4f6));
174
+ border: 1px solid var(--border-color);
175
+ padding: 0 6px 0 8px;
176
+ border-radius: 10px;
123
177
  white-space: nowrap;
124
- max-width: 150px;
178
+ max-width: 170px;
125
179
  cursor: pointer;
126
- transition: all .2s;
180
+ transition: all .2s ease;
181
+
182
+ .info-item-leading {
183
+ width: 18px;
184
+ height: 18px;
185
+ border-radius: 6px;
186
+ background: rgba(99, 102, 241, .12);
187
+ color: var(--primary-color, #6366f1);
188
+ display: flex;
189
+ align-items: center;
190
+ justify-content: center;
191
+ flex-shrink: 0;
192
+
193
+ .material-symbols-rounded {
194
+ font-size: 14px;
195
+ }
196
+ }
127
197
 
128
198
  .material-symbols-rounded {
129
199
  font-size: 18px;
@@ -132,19 +202,24 @@
132
202
  .info-text {
133
203
  overflow: hidden;
134
204
  text-overflow: ellipsis;
135
- font-weight: 400;
205
+ font-weight: 600;
206
+ color: var(--text-color);
136
207
  }
137
208
 
138
209
  .arrow-icon {
139
- font-size: 16px;
210
+ font-size: 18px;
140
211
  color: var(--sub-text-color, #9ca3af);
212
+ background: var(--tag-hover-bg, #f3f4f6);
213
+ border-radius: 999px;
141
214
  transition: transform .2s;
142
215
  }
143
216
 
144
217
  &:hover, &.active {
145
- color: #3b82f6;
218
+ color: var(--primary-color, #6366f1);
219
+ border-color: rgba(99, 102, 241, .3);
220
+ box-shadow: 0 8px 18px rgba(15, 23, 42, .08);
146
221
  .arrow-icon {
147
- color: #3b82f6;
222
+ color: var(--primary-color, #6366f1);
148
223
  }
149
224
  }
150
225
 
@@ -153,60 +228,6 @@
153
228
  }
154
229
  }
155
230
 
156
- .tools-list-popup {
157
- position: absolute;
158
- bottom: calc(100% + 12px);
159
- left: 12px;
160
- background: var(--bg-color);
161
- border: 1px solid var(--border-color);
162
- border-radius: 12px;
163
- box-shadow: 0 4px 12px rgba(0, 0, 0, .15);
164
- min-width: 200px;
165
- max-height: 300px;
166
- overflow: hidden;
167
- display: flex;
168
- flex-direction: column;
169
- z-index: 100;
170
- animation: slideUp .2s ease-out;
171
-
172
- .popup-header {
173
- padding: 10px 12px;
174
- font-size: 12px;
175
- font-weight: 600;
176
- color: var(--sub-text-color, #9ca3af);
177
- border-bottom: 1px solid var(--border-color);
178
- background: var(--tag-bg, #f9fafb);
179
- }
180
-
181
- .popup-content {
182
- padding: 6px;
183
- overflow-y: auto;
184
-
185
- .tool-item {
186
- display: flex;
187
- align-items: center;
188
- gap: 8px;
189
- padding: 8px 10px;
190
- border-radius: 6px;
191
- color: var(--text-color);
192
- transition: all .2s;
193
-
194
- .material-symbols-rounded {
195
- font-size: 18px;
196
- color: #3b82f6;
197
- }
198
-
199
- .tool-name {
200
- font-size: 13px;
201
- }
202
-
203
- &:hover {
204
- background-color: var(--tag-hover-bg, #f3f4f6);
205
- color: var(--text-color);
206
- }
207
- }
208
- }
209
- }
210
231
  }
211
232
  }
212
233
 
@@ -267,6 +288,117 @@
267
288
  }
268
289
  }
269
290
 
291
+ .sender-tools-cascader-popup {
292
+ .ant-cascader-menus {
293
+ background: var(--bg-color);
294
+ border: 1px solid var(--border-color);
295
+ border-radius: 14px;
296
+ overflow: hidden;
297
+ box-shadow: 0 18px 40px rgba(15, 23, 42, .16);
298
+ }
299
+
300
+ .ant-cascader-menu {
301
+ min-width: 240px;
302
+ max-height: 320px;
303
+ padding: 8px;
304
+ background: var(--bg-color);
305
+ border-inline-end: 1px solid var(--border-color);
306
+ }
307
+
308
+ .ant-cascader-menu:first-child {
309
+ background: var(--sub-bg-color);
310
+ }
311
+
312
+ .ant-cascader-menu:last-child {
313
+ border-inline-end: none;
314
+ }
315
+
316
+ .ant-cascader-menu-item {
317
+ min-height: 40px;
318
+ padding: 8px 10px;
319
+ border-radius: 10px;
320
+ color: var(--text-color);
321
+ font-size: 13px;
322
+ transition: all .18s ease;
323
+ }
324
+
325
+ .ant-cascader-menu-item-content {
326
+ min-width: 0;
327
+ }
328
+
329
+ .ant-cascader-menu-item-expand-icon {
330
+ color: var(--sub-text-color);
331
+ }
332
+
333
+ .ant-cascader-menu-item:hover,
334
+ .ant-cascader-menu-item-active,
335
+ .ant-cascader-menu-item-expand {
336
+ background-color: var(--tag-hover-bg, #f3f4f6);
337
+ }
338
+
339
+ .sender-tool-group-option,
340
+ .sender-tool-option {
341
+ display: flex;
342
+ align-items: center;
343
+ gap: 10px;
344
+ min-width: 0;
345
+ width: 100%;
346
+ }
347
+
348
+ .sender-tool-group-option__icon {
349
+ width: 20px;
350
+ height: 20px;
351
+ border-radius: 7px;
352
+ display: inline-flex;
353
+ align-items: center;
354
+ justify-content: center;
355
+ background: rgba(99, 102, 241, .12);
356
+ color: var(--primary-color, #6366f1);
357
+ font-size: 14px;
358
+ flex-shrink: 0;
359
+ }
360
+
361
+ .sender-tool-group-option__text {
362
+ flex: 1;
363
+ min-width: 0;
364
+ font-weight: 600;
365
+ color: var(--text-color);
366
+ }
367
+
368
+ .sender-tool-group-option__count {
369
+ flex-shrink: 0;
370
+ min-width: 22px;
371
+ padding: 1px 6px;
372
+ border-radius: 999px;
373
+ background: var(--bg-color);
374
+ border: 1px solid var(--border-color);
375
+ color: var(--sub-text-color);
376
+ font-size: 11px;
377
+ line-height: 1.4;
378
+ text-align: center;
379
+ }
380
+
381
+ .sender-tool-option__dot {
382
+ width: 8px;
383
+ height: 8px;
384
+ border-radius: 999px;
385
+ background: var(--primary-color, #6366f1);
386
+ box-shadow: 0 0 0 4px rgba(99, 102, 241, .12);
387
+ flex-shrink: 0;
388
+ margin-left: 2px;
389
+ }
390
+
391
+ .sender-tool-option__text {
392
+ min-width: 0;
393
+ overflow: hidden;
394
+ text-overflow: ellipsis;
395
+ font-size: 12px;
396
+ font-family: ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
397
+ 'Courier New', monospace;
398
+ letter-spacing: .01em;
399
+ }
400
+ }
401
+
270
402
  .adapter-select,
271
403
  .model-select,
272
404
  .permission-mode-select {
@@ -315,7 +447,6 @@
315
447
 
316
448
  .model-select {
317
449
  min-width: 160px;
318
-
319
450
  }
320
451
 
321
452
  .permission-mode-select {
@@ -362,7 +493,6 @@
362
493
  min-height: 14px;
363
494
  line-height: 1;
364
495
  }
365
-
366
496
  }
367
497
 
368
498
  .adapter-option {