@vibe-forge/client 0.2.0-alpha.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 (184) hide show
  1. package/LICENSE +21 -0
  2. package/cli.cjs +6 -0
  3. package/index.html +27 -0
  4. package/package.json +42 -0
  5. package/src/App.tsx +174 -0
  6. package/src/api.ts +241 -0
  7. package/src/components/ArchiveView.scss +168 -0
  8. package/src/components/ArchiveView.tsx +299 -0
  9. package/src/components/AutomationView/AutomationView.scss +26 -0
  10. package/src/components/AutomationView/RuleFormPanel.scss +129 -0
  11. package/src/components/AutomationView/RuleFormPanel.tsx +257 -0
  12. package/src/components/AutomationView/RuleSidebar.scss +219 -0
  13. package/src/components/AutomationView/RuleSidebar.tsx +258 -0
  14. package/src/components/AutomationView/RunHistoryPanel.scss +286 -0
  15. package/src/components/AutomationView/RunHistoryPanel.tsx +320 -0
  16. package/src/components/AutomationView/TaskList.scss +128 -0
  17. package/src/components/AutomationView/TaskList.tsx +79 -0
  18. package/src/components/AutomationView/TriggerList.scss +153 -0
  19. package/src/components/AutomationView/TriggerList.tsx +217 -0
  20. package/src/components/AutomationView/index.tsx +228 -0
  21. package/src/components/AutomationView/types.ts +21 -0
  22. package/src/components/Chat.scss +89 -0
  23. package/src/components/Chat.tsx +92 -0
  24. package/src/components/ConfigView.scss +185 -0
  25. package/src/components/ConfigView.tsx +258 -0
  26. package/src/components/NavRail.scss +71 -0
  27. package/src/components/NavRail.tsx +188 -0
  28. package/src/components/Sidebar.scss +112 -0
  29. package/src/components/Sidebar.tsx +291 -0
  30. package/src/components/chat/ChatHeader.scss +401 -0
  31. package/src/components/chat/ChatHeader.tsx +342 -0
  32. package/src/components/chat/ChatHistoryView.tsx +122 -0
  33. package/src/components/chat/ChatSettingsView.tsx +22 -0
  34. package/src/components/chat/ChatTimelineView.scss +53 -0
  35. package/src/components/chat/ChatTimelineView.tsx +158 -0
  36. package/src/components/chat/CodeBlock.scss +87 -0
  37. package/src/components/chat/CodeBlock.tsx +179 -0
  38. package/src/components/chat/CompletionMenu.scss +70 -0
  39. package/src/components/chat/CompletionMenu.tsx +58 -0
  40. package/src/components/chat/CurrentTodoList.scss +217 -0
  41. package/src/components/chat/CurrentTodoList.tsx +103 -0
  42. package/src/components/chat/MarkdownContent.tsx +43 -0
  43. package/src/components/chat/MessageFooter.tsx +48 -0
  44. package/src/components/chat/MessageItem.scss +251 -0
  45. package/src/components/chat/MessageItem.tsx +78 -0
  46. package/src/components/chat/NewSessionGuide.scss +186 -0
  47. package/src/components/chat/NewSessionGuide.tsx +167 -0
  48. package/src/components/chat/Sender.scss +367 -0
  49. package/src/components/chat/Sender.tsx +541 -0
  50. package/src/components/chat/SessionTimelinePanel/EventList.scss +58 -0
  51. package/src/components/chat/SessionTimelinePanel/EventList.tsx +212 -0
  52. package/src/components/chat/SessionTimelinePanel/gantt.ts +177 -0
  53. package/src/components/chat/SessionTimelinePanel/git-graph.ts +518 -0
  54. package/src/components/chat/SessionTimelinePanel/index.scss +28 -0
  55. package/src/components/chat/SessionTimelinePanel/index.tsx +121 -0
  56. package/src/components/chat/SessionTimelinePanel/mermaid.ts +4 -0
  57. package/src/components/chat/SessionTimelinePanel/types.ts +64 -0
  58. package/src/components/chat/SessionTimelinePanel/utils.ts +20 -0
  59. package/src/components/chat/ThinkingStatus.scss +70 -0
  60. package/src/components/chat/ThinkingStatus.tsx +13 -0
  61. package/src/components/chat/ToolCallBox.scss +137 -0
  62. package/src/components/chat/ToolCallBox.tsx +55 -0
  63. package/src/components/chat/ToolGroup.scss +154 -0
  64. package/src/components/chat/ToolGroup.tsx +102 -0
  65. package/src/components/chat/ToolRenderer.tsx +45 -0
  66. package/src/components/chat/messageUtils.ts +171 -0
  67. package/src/components/chat/safeSerialize.ts +84 -0
  68. package/src/components/chat/tools/DefaultTool.tsx +63 -0
  69. package/src/components/chat/tools/adapter-claude/BashTool.scss +71 -0
  70. package/src/components/chat/tools/adapter-claude/BashTool.tsx +82 -0
  71. package/src/components/chat/tools/adapter-claude/GlobTool.scss +88 -0
  72. package/src/components/chat/tools/adapter-claude/GlobTool.tsx +85 -0
  73. package/src/components/chat/tools/adapter-claude/GrepTool.scss +96 -0
  74. package/src/components/chat/tools/adapter-claude/GrepTool.tsx +114 -0
  75. package/src/components/chat/tools/adapter-claude/LSTool.scss +85 -0
  76. package/src/components/chat/tools/adapter-claude/LSTool.tsx +94 -0
  77. package/src/components/chat/tools/adapter-claude/ReadTool.scss +57 -0
  78. package/src/components/chat/tools/adapter-claude/ReadTool.tsx +87 -0
  79. package/src/components/chat/tools/adapter-claude/TodoTool.scss +78 -0
  80. package/src/components/chat/tools/adapter-claude/TodoTool.tsx +60 -0
  81. package/src/components/chat/tools/adapter-claude/WriteTool.scss +92 -0
  82. package/src/components/chat/tools/adapter-claude/WriteTool.tsx +86 -0
  83. package/src/components/chat/tools/adapter-claude/components/FileList.scss +65 -0
  84. package/src/components/chat/tools/adapter-claude/components/FileList.tsx +185 -0
  85. package/src/components/chat/tools/adapter-claude/index.ts +28 -0
  86. package/src/components/chat/tools/defineToolRender.ts +28 -0
  87. package/src/components/chat/tools/task/GetTaskInfoTool.scss +50 -0
  88. package/src/components/chat/tools/task/GetTaskInfoTool.tsx +88 -0
  89. package/src/components/chat/tools/task/ListTasksTool.scss +56 -0
  90. package/src/components/chat/tools/task/ListTasksTool.tsx +83 -0
  91. package/src/components/chat/tools/task/StartTasksTool.scss +56 -0
  92. package/src/components/chat/tools/task/StartTasksTool.tsx +96 -0
  93. package/src/components/chat/tools/task/components/TaskToolCard.scss +127 -0
  94. package/src/components/chat/tools/task/components/TaskToolCard.tsx +177 -0
  95. package/src/components/chat/tools/task/index.ts +15 -0
  96. package/src/components/chat/useChatModels.tsx +206 -0
  97. package/src/components/chat/useChatSession.ts +370 -0
  98. package/src/components/config/ConfigAboutSection.scss +111 -0
  99. package/src/components/config/ConfigAboutSection.tsx +86 -0
  100. package/src/components/config/ConfigDisplayValue.scss +22 -0
  101. package/src/components/config/ConfigDisplayValue.tsx +62 -0
  102. package/src/components/config/ConfigEditors.scss +65 -0
  103. package/src/components/config/ConfigEditors.tsx +98 -0
  104. package/src/components/config/ConfigFieldRow.scss +97 -0
  105. package/src/components/config/ConfigFieldRow.tsx +36 -0
  106. package/src/components/config/ConfigSectionForm.scss +94 -0
  107. package/src/components/config/ConfigSectionForm.tsx +436 -0
  108. package/src/components/config/ConfigSectionPanel.tsx +67 -0
  109. package/src/components/config/ConfigShortcutInput.scss +11 -0
  110. package/src/components/config/ConfigShortcutInput.tsx +52 -0
  111. package/src/components/config/ConfigSourceSwitch.tsx +57 -0
  112. package/src/components/config/configSchema.ts +319 -0
  113. package/src/components/config/configUtils.ts +83 -0
  114. package/src/components/config/index.tsx +5 -0
  115. package/src/components/config/recordEditors/BooleanRecordEditor.scss +1 -0
  116. package/src/components/config/recordEditors/BooleanRecordEditor.tsx +75 -0
  117. package/src/components/config/recordEditors/KeyValueEditor.scss +1 -0
  118. package/src/components/config/recordEditors/KeyValueEditor.tsx +97 -0
  119. package/src/components/config/recordEditors/McpServersRecordEditor.scss +1 -0
  120. package/src/components/config/recordEditors/McpServersRecordEditor.tsx +258 -0
  121. package/src/components/config/recordEditors/ModelServicesRecordEditor.scss +1 -0
  122. package/src/components/config/recordEditors/ModelServicesRecordEditor.tsx +233 -0
  123. package/src/components/config/recordEditors/RecordEditors.scss +117 -0
  124. package/src/components/config/recordEditors/RecordJsonEditor.scss +1 -0
  125. package/src/components/config/recordEditors/RecordJsonEditor.tsx +113 -0
  126. package/src/components/config/recordEditors/index.tsx +5 -0
  127. package/src/components/knowledge-base/KnowledgeBaseView.scss +19 -0
  128. package/src/components/knowledge-base/KnowledgeBaseView.tsx +186 -0
  129. package/src/components/knowledge-base/components/ActionButton.scss +5 -0
  130. package/src/components/knowledge-base/components/ActionButton.tsx +9 -0
  131. package/src/components/knowledge-base/components/EmptyState.scss +19 -0
  132. package/src/components/knowledge-base/components/EmptyState.tsx +42 -0
  133. package/src/components/knowledge-base/components/EntitiesTab.scss +5 -0
  134. package/src/components/knowledge-base/components/EntitiesTab.tsx +80 -0
  135. package/src/components/knowledge-base/components/EntityItem.scss +82 -0
  136. package/src/components/knowledge-base/components/EntityItem.tsx +79 -0
  137. package/src/components/knowledge-base/components/EntityList.scss +5 -0
  138. package/src/components/knowledge-base/components/EntityList.tsx +70 -0
  139. package/src/components/knowledge-base/components/FilterBar.scss +21 -0
  140. package/src/components/knowledge-base/components/FilterBar.tsx +51 -0
  141. package/src/components/knowledge-base/components/FlowsTab.scss +5 -0
  142. package/src/components/knowledge-base/components/FlowsTab.tsx +80 -0
  143. package/src/components/knowledge-base/components/KnowledgeBaseHeader.scss +27 -0
  144. package/src/components/knowledge-base/components/KnowledgeBaseHeader.tsx +29 -0
  145. package/src/components/knowledge-base/components/KnowledgeList.scss +19 -0
  146. package/src/components/knowledge-base/components/KnowledgeList.tsx +19 -0
  147. package/src/components/knowledge-base/components/LoadingState.scss +5 -0
  148. package/src/components/knowledge-base/components/LoadingState.tsx +11 -0
  149. package/src/components/knowledge-base/components/MetaList.scss +19 -0
  150. package/src/components/knowledge-base/components/MetaList.tsx +18 -0
  151. package/src/components/knowledge-base/components/RulesTab.scss +5 -0
  152. package/src/components/knowledge-base/components/RulesTab.tsx +49 -0
  153. package/src/components/knowledge-base/components/SectionHeader.scss +22 -0
  154. package/src/components/knowledge-base/components/SectionHeader.tsx +21 -0
  155. package/src/components/knowledge-base/components/SkillsTab.scss +5 -0
  156. package/src/components/knowledge-base/components/SkillsTab.tsx +49 -0
  157. package/src/components/knowledge-base/components/SpecItem.scss +138 -0
  158. package/src/components/knowledge-base/components/SpecItem.tsx +131 -0
  159. package/src/components/knowledge-base/components/SpecList.scss +5 -0
  160. package/src/components/knowledge-base/components/SpecList.tsx +70 -0
  161. package/src/components/knowledge-base/components/TabContent.scss +8 -0
  162. package/src/components/knowledge-base/components/TabContent.tsx +17 -0
  163. package/src/components/knowledge-base/components/TabLabel.scss +10 -0
  164. package/src/components/knowledge-base/components/TabLabel.tsx +15 -0
  165. package/src/components/knowledge-base/index.tsx +1 -0
  166. package/src/components/sidebar/SessionItem.scss +256 -0
  167. package/src/components/sidebar/SessionItem.tsx +265 -0
  168. package/src/components/sidebar/SessionList.scss +92 -0
  169. package/src/components/sidebar/SessionList.tsx +166 -0
  170. package/src/components/sidebar/SidebarHeader.scss +79 -0
  171. package/src/components/sidebar/SidebarHeader.tsx +128 -0
  172. package/src/connectionManager.ts +172 -0
  173. package/src/hooks/useGlobalShortcut.ts +26 -0
  174. package/src/hooks/useQueryParams.ts +54 -0
  175. package/src/i18n.ts +22 -0
  176. package/src/main.tsx +41 -0
  177. package/src/resources/locales/en.json +765 -0
  178. package/src/resources/locales/zh.json +766 -0
  179. package/src/store/index.ts +23 -0
  180. package/src/styles/global.scss +100 -0
  181. package/src/utils/shortcutUtils.ts +88 -0
  182. package/src/vite-env.d.ts +12 -0
  183. package/src/ws.ts +33 -0
  184. package/vite.config.ts +26 -0
@@ -0,0 +1,258 @@
1
+ import './RuleSidebar.scss'
2
+
3
+ import { Button, Empty, Input, List, Switch, Tag, Tooltip } from 'antd'
4
+ import dayjs from 'dayjs'
5
+ import React, { useCallback, useEffect, useMemo, useState } from 'react'
6
+ import { useTranslation } from 'react-i18next'
7
+
8
+ import type { AutomationRule } from '#~/api.js'
9
+
10
+ interface RuleSidebarProps {
11
+ rules: AutomationRule[]
12
+ selectedRuleId: string | null
13
+ query: string
14
+ isCreating: boolean
15
+ onCreate: () => void
16
+ onSelect: (id: string) => void
17
+ onRun: (rule: AutomationRule) => void
18
+ onDelete: (rule: AutomationRule) => void
19
+ onToggle: (rule: AutomationRule, enabled: boolean) => void
20
+ onQueryChange: (value: string) => void
21
+ }
22
+
23
+ export function RuleSidebar({
24
+ rules,
25
+ selectedRuleId,
26
+ query,
27
+ isCreating,
28
+ onCreate,
29
+ onSelect,
30
+ onRun,
31
+ onDelete,
32
+ onToggle,
33
+ onQueryChange
34
+ }: RuleSidebarProps) {
35
+ const { t } = useTranslation()
36
+ const [favorites, setFavorites] = useState<string[]>(() => {
37
+ try {
38
+ const raw = window.localStorage.getItem('automationRuleFavorites')
39
+ if (!raw) return []
40
+ const parsed = JSON.parse(raw) as string[]
41
+ if (!Array.isArray(parsed)) return []
42
+ return parsed
43
+ } catch {
44
+ return []
45
+ }
46
+ })
47
+
48
+ useEffect(() => {
49
+ window.localStorage.setItem('automationRuleFavorites', JSON.stringify(favorites))
50
+ }, [favorites])
51
+
52
+ const favoriteSet = useMemo(() => new Set(favorites), [favorites])
53
+ const filteredRules = useMemo(() => {
54
+ const keyword = query.trim().toLowerCase()
55
+ const list = keyword
56
+ ? rules.filter(rule => {
57
+ const nameMatch = rule.name.toLowerCase().includes(keyword)
58
+ const descMatch = (rule.description ?? '').toLowerCase().includes(keyword)
59
+ return nameMatch || descMatch
60
+ })
61
+ : rules
62
+ return [...list].sort((a, b) => {
63
+ const favA = favoriteSet.has(a.id) ? 1 : 0
64
+ const favB = favoriteSet.has(b.id) ? 1 : 0
65
+ if (favA !== favB) return favB - favA
66
+ return b.createdAt - a.createdAt
67
+ })
68
+ }, [favoriteSet, query, rules])
69
+
70
+ const toggleFavorite = useCallback((ruleId: string) => {
71
+ setFavorites(prev => prev.includes(ruleId) ? prev.filter(id => id !== ruleId) : [...prev, ruleId])
72
+ }, [])
73
+
74
+ const renderTriggerBadge = useCallback((trigger: NonNullable<AutomationRule['triggers']>[number]) => {
75
+ if (trigger.type === 'interval') {
76
+ const minutes = trigger.intervalMs ? Math.max(1, Math.round(trigger.intervalMs / 60000)) : 0
77
+ return (
78
+ <span className='automation-view__trigger-chip'>
79
+ <span className='material-symbols-rounded automation-view__trigger-icon'>timer</span>
80
+ {t('automation.intervalEvery', { minutes })}
81
+ </span>
82
+ )
83
+ }
84
+ if (trigger.type === 'cron') {
85
+ return (
86
+ <span className='automation-view__trigger-chip'>
87
+ <span className='material-symbols-rounded automation-view__trigger-icon'>schedule</span>
88
+ {t('automation.cronExpression', { expression: trigger.cronExpression ?? '-' })}
89
+ </span>
90
+ )
91
+ }
92
+ return (
93
+ <span className='automation-view__trigger-chip'>
94
+ <span className='material-symbols-rounded automation-view__trigger-icon'>webhook</span>
95
+ {t('automation.webhookTrigger')}
96
+ </span>
97
+ )
98
+ }, [t])
99
+
100
+ return (
101
+ <div className='automation-view__sidebar'>
102
+ <div className='automation-view__sidebar-header'>
103
+ <div className='automation-view__title'>
104
+ <h2 className='automation-view__title-text'>{t('automation.title')}</h2>
105
+ </div>
106
+ <Tooltip title={isCreating ? t('automation.creatingRule') : t('automation.newRule')}>
107
+ <Button
108
+ className='automation-view__icon-button automation-view__icon-button--add'
109
+ type='text'
110
+ onClick={onCreate}
111
+ disabled={isCreating}
112
+ >
113
+ <span className='material-symbols-rounded automation-view__action-icon'>
114
+ {isCreating ? 'progress_activity' : 'add'}
115
+ </span>
116
+ </Button>
117
+ </Tooltip>
118
+ </div>
119
+ <div className='automation-view__sidebar-search'>
120
+ <Input
121
+ value={query}
122
+ onChange={(event) => onQueryChange(event.target.value)}
123
+ placeholder={t('automation.searchRule')}
124
+ prefix={<span className='material-symbols-rounded automation-view__search-icon'>search</span>}
125
+ allowClear
126
+ />
127
+ </div>
128
+
129
+ {filteredRules.length === 0
130
+ ? (
131
+ <div className='automation-view__empty'>
132
+ <Empty description={t('automation.emptyRules')} />
133
+ </div>
134
+ )
135
+ : (
136
+ <List
137
+ className='automation-view__rule-list'
138
+ dataSource={filteredRules}
139
+ renderItem={(rule) => {
140
+ const active = rule.id === selectedRuleId
141
+ const isFavorite = favoriteSet.has(rule.id)
142
+ const triggers = rule.triggers ?? []
143
+ const displayTriggers = triggers.slice(0, 2)
144
+ const remainingTriggers = Math.max(triggers.length - displayTriggers.length, 0)
145
+ const taskCount = rule.tasks?.length ?? 0
146
+ const primaryType = triggers[0]?.type ?? 'interval'
147
+ return (
148
+ <List.Item
149
+ className={`automation-view__rule-item ${active ? 'automation-view__rule-item--active' : ''}`}
150
+ onClick={() => onSelect(rule.id)}
151
+ >
152
+ <div className='automation-view__rule-card'>
153
+ <div className='automation-view__rule-content'>
154
+ <div className='automation-view__rule-name'>
155
+ <span
156
+ className={`material-symbols-rounded automation-view__rule-icon automation-view__rule-icon--${primaryType}`}
157
+ >
158
+ {primaryType === 'interval' ? 'timer' : primaryType === 'cron' ? 'schedule' : 'webhook'}
159
+ </span>
160
+ <span className='automation-view__rule-title'>{rule.name}</span>
161
+ <Tag
162
+ color={primaryType === 'interval' ? 'blue' : primaryType === 'cron' ? 'geekblue' : 'purple'}
163
+ >
164
+ {primaryType === 'interval'
165
+ ? t('automation.typeInterval')
166
+ : primaryType === 'cron'
167
+ ? t('automation.typeCron')
168
+ : t('automation.typeWebhook')}
169
+ </Tag>
170
+ </div>
171
+ <div className='automation-view__rule-meta'>
172
+ <div className='automation-view__rule-trigger-list'>
173
+ <span className='material-symbols-rounded automation-view__meta-icon'>bolt</span>
174
+ {displayTriggers.map(trigger => (
175
+ <span key={trigger.id}>{renderTriggerBadge(trigger)}</span>
176
+ ))}
177
+ {remainingTriggers > 0 && (
178
+ <span className='automation-view__trigger-more'>+{remainingTriggers}</span>
179
+ )}
180
+ </div>
181
+ <span className='automation-view__rule-tasks'>
182
+ <span className='material-symbols-rounded automation-view__meta-icon'>checklist</span>
183
+ {t('automation.taskCount', { count: taskCount })}
184
+ </span>
185
+ <span className='automation-view__rule-last'>
186
+ <span className='material-symbols-rounded automation-view__meta-icon'>update</span>
187
+ {rule.lastRunAt
188
+ ? t('automation.lastRunAt', { time: dayjs(rule.lastRunAt).format('YYYY-MM-DD HH:mm') })
189
+ : t('automation.noRunYet')}
190
+ </span>
191
+ </div>
192
+ </div>
193
+ <div className='automation-view__rule-actions'>
194
+ <div className='automation-view__rule-actions-top'>
195
+ <Tooltip title={t('automation.toggleEnabled')}>
196
+ <Switch
197
+ checked={rule.enabled}
198
+ onChange={(next) => void onToggle(rule, next)}
199
+ onClick={(_, event) => event.stopPropagation()}
200
+ />
201
+ </Tooltip>
202
+ </div>
203
+ <div className='automation-view__rule-actions-bottom'>
204
+ <Tooltip title={t('automation.run')}>
205
+ <Button
206
+ className='automation-view__icon-button automation-view__icon-button--run'
207
+ type='text'
208
+ onClick={(event) => {
209
+ event.stopPropagation()
210
+ void onRun(rule)
211
+ }}
212
+ >
213
+ <span className='material-symbols-rounded automation-view__action-icon'>play_arrow</span>
214
+ </Button>
215
+ </Tooltip>
216
+ <Tooltip title={t('automation.delete')}>
217
+ <Button
218
+ className='automation-view__icon-button automation-view__icon-button--delete'
219
+ type='text'
220
+ onClick={(event) => {
221
+ event.stopPropagation()
222
+ void onDelete(rule)
223
+ }}
224
+ >
225
+ <span className='material-symbols-rounded automation-view__action-icon'>delete</span>
226
+ </Button>
227
+ </Tooltip>
228
+ <Tooltip title={isFavorite ? t('automation.unfavorite') : t('automation.favorite')}>
229
+ <Button
230
+ className={`automation-view__icon-button automation-view__icon-button--favorite ${
231
+ isFavorite ? 'automation-view__icon-button--active' : ''
232
+ }`}
233
+ type='text'
234
+ onClick={(event) => {
235
+ event.stopPropagation()
236
+ toggleFavorite(rule.id)
237
+ }}
238
+ >
239
+ <span
240
+ className={`material-symbols-rounded automation-view__action-icon ${
241
+ isFavorite ? 'automation-view__action-icon--star' : ''
242
+ }`}
243
+ >
244
+ {isFavorite ? 'star' : 'star_outline'}
245
+ </span>
246
+ </Button>
247
+ </Tooltip>
248
+ </div>
249
+ </div>
250
+ </div>
251
+ </List.Item>
252
+ )
253
+ }}
254
+ />
255
+ )}
256
+ </div>
257
+ )
258
+ }
@@ -0,0 +1,286 @@
1
+ .automation-view {
2
+ &__content {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: 12px;
6
+ height: 100%;
7
+ }
8
+
9
+ &__content-header {
10
+ display: flex;
11
+ align-items: baseline;
12
+ justify-content: space-between;
13
+ }
14
+
15
+ &__content-title {
16
+ display: flex;
17
+ align-items: center;
18
+ gap: 8px;
19
+ }
20
+
21
+ &__content-icon {
22
+ font-size: 22px;
23
+ color: var(--sub-text-color);
24
+ }
25
+
26
+ &__content-text {
27
+ margin: 0;
28
+ color: var(--text-color);
29
+ font-size: 16px;
30
+ }
31
+
32
+ &__detail {
33
+ display: flex;
34
+ flex-direction: column;
35
+ gap: 12px;
36
+ }
37
+
38
+ &__detail-header {
39
+ display: flex;
40
+ align-items: center;
41
+ justify-content: space-between;
42
+ }
43
+
44
+ &__detail-title {
45
+ display: flex;
46
+ flex-direction: column;
47
+ align-items: flex-start;
48
+ gap: 4px;
49
+ }
50
+
51
+ &__detail-id {
52
+ color: var(--placeholder-color);
53
+ font-size: 12px;
54
+ }
55
+
56
+ &__detail-description {
57
+ display: flex;
58
+ align-items: center;
59
+ gap: 8px;
60
+ font-size: 12px;
61
+ }
62
+
63
+ &__detail-body {
64
+ display: grid;
65
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
66
+ gap: 16px;
67
+ }
68
+
69
+ &__detail-left {
70
+ display: flex;
71
+ flex-direction: column;
72
+ gap: 12px;
73
+ }
74
+
75
+ &__detail-right {
76
+ display: flex;
77
+ flex-direction: column;
78
+ gap: 12px;
79
+ }
80
+
81
+ &__detail-row {
82
+ display: inline-flex;
83
+ align-items: center;
84
+ gap: 8px;
85
+ font-size: 12px;
86
+ }
87
+
88
+ &__detail-list {
89
+ display: flex;
90
+ flex-direction: column;
91
+ gap: 8px;
92
+ }
93
+
94
+ &__run-list {
95
+ display: flex;
96
+ flex-direction: column;
97
+ gap: 6px;
98
+ padding-left: 22px;
99
+ }
100
+
101
+ &__run-item {
102
+ display: flex;
103
+ align-items: center;
104
+ justify-content: space-between;
105
+ gap: 12px;
106
+ font-size: 12px;
107
+ }
108
+
109
+ &__run-link {
110
+ color: var(--primary-color);
111
+ max-width: 260px;
112
+ overflow: hidden;
113
+ text-overflow: ellipsis;
114
+ white-space: nowrap;
115
+ }
116
+
117
+ &__run-time {
118
+ color: var(--placeholder-color);
119
+ white-space: nowrap;
120
+ }
121
+
122
+ &__detail-label {
123
+ color: var(--placeholder-color);
124
+ }
125
+
126
+ &__detail-value {
127
+ color: var(--text-color);
128
+
129
+ &[data-status='enabled'] {
130
+ color: var(--success-color);
131
+ }
132
+
133
+ &[data-status='disabled'] {
134
+ color: var(--danger-color);
135
+ }
136
+ }
137
+
138
+ &__detail-link {
139
+ color: var(--primary-color);
140
+ }
141
+
142
+ &__detail-section {
143
+ display: flex;
144
+ flex-direction: column;
145
+ gap: 8px;
146
+ }
147
+
148
+ &__detail-section-title {
149
+ display: inline-flex;
150
+ align-items: center;
151
+ gap: 6px;
152
+ color: var(--text-color);
153
+ font-size: 13px;
154
+ font-weight: 600;
155
+ }
156
+
157
+ &__detail-chips {
158
+ display: flex;
159
+ flex-wrap: wrap;
160
+ gap: 8px;
161
+ }
162
+
163
+ &__detail-chip {
164
+ display: inline-flex;
165
+ align-items: center;
166
+ border-radius: 999px;
167
+ padding: 4px 10px;
168
+ background: var(--tag-bg);
169
+ color: var(--text-color);
170
+ font-size: 12px;
171
+ }
172
+
173
+ &__detail-placeholder {
174
+ color: var(--sub-text-color);
175
+ font-size: 12px;
176
+ }
177
+
178
+ &__run-filters {
179
+ display: flex;
180
+ align-items: center;
181
+ gap: 12px;
182
+ }
183
+
184
+ &__run-search {
185
+ max-width: 240px;
186
+ }
187
+
188
+ &__run-select {
189
+ min-width: 140px;
190
+ }
191
+
192
+ &__run-table {
193
+ flex: 1;
194
+ }
195
+
196
+ &__run-summary {
197
+ display: inline-block;
198
+ max-width: 320px;
199
+ overflow: hidden;
200
+ text-overflow: ellipsis;
201
+ white-space: nowrap;
202
+ color: var(--text-color);
203
+ }
204
+
205
+ &__task-link {
206
+ display: inline-flex;
207
+ align-items: center;
208
+ gap: 6px;
209
+ padding: 0;
210
+ color: var(--primary-color);
211
+ }
212
+
213
+ &__task-icon {
214
+ font-size: 16px;
215
+ color: var(--sub-text-color);
216
+ }
217
+
218
+ &__status {
219
+ display: inline-flex;
220
+ align-items: center;
221
+ gap: 6px;
222
+ color: var(--sub-text-color);
223
+
224
+ &-icon {
225
+ font-size: 10px;
226
+ }
227
+
228
+ &[data-status='completed'] {
229
+ .automation-view__status-icon {
230
+ color: var(--success-color);
231
+ }
232
+ }
233
+
234
+ &[data-status='failed'] {
235
+ .automation-view__status-icon {
236
+ color: var(--danger-color);
237
+ }
238
+ }
239
+
240
+ &[data-status='terminated'] {
241
+ .automation-view__status-icon {
242
+ color: var(--warning-color);
243
+ }
244
+ }
245
+
246
+ &[data-status='running'] {
247
+ .automation-view__status-icon {
248
+ color: var(--primary-color);
249
+ }
250
+ }
251
+
252
+ &[data-status='waiting_input'] {
253
+ .automation-view__status-icon {
254
+ color: var(--warning-color);
255
+ }
256
+ }
257
+ }
258
+
259
+ &__icon-button {
260
+ display: inline-flex;
261
+ align-items: center;
262
+ justify-content: center;
263
+ width: 32px;
264
+ height: 32px;
265
+ padding: 0;
266
+
267
+ &--edit .automation-view__action-icon {
268
+ color: var(--primary-text-color);
269
+ }
270
+ }
271
+
272
+ &__action-icon {
273
+ font-size: 18px;
274
+ }
275
+
276
+ &__meta-icon {
277
+ font-size: 14px;
278
+ }
279
+
280
+ &__empty {
281
+ flex: 1;
282
+ display: flex;
283
+ align-items: center;
284
+ justify-content: center;
285
+ }
286
+ }