bingocode 1.0.3 → 1.0.4

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/package.json +1 -1
  2. package/desktop/README.md +0 -30
  3. package/desktop/bunfig.toml +0 -1
  4. package/desktop/index.html +0 -17
  5. package/desktop/package.json +0 -55
  6. package/desktop/pnpm-lock.yaml +0 -3832
  7. package/desktop/public/app-icon.jpg +0 -0
  8. package/desktop/public/fonts/inter-latin-ext.woff2 +0 -0
  9. package/desktop/public/fonts/inter-latin.woff2 +0 -0
  10. package/desktop/public/fonts/jetbrains-mono-latin-ext.woff2 +0 -0
  11. package/desktop/public/fonts/jetbrains-mono-latin.woff2 +0 -0
  12. package/desktop/public/fonts/manrope-latin-ext.woff2 +0 -0
  13. package/desktop/public/fonts/manrope-latin.woff2 +0 -0
  14. package/desktop/public/fonts/material-symbols-outlined.woff2 +0 -0
  15. package/desktop/public/icons/bilibili.svg +0 -1
  16. package/desktop/public/icons/douyin.svg +0 -1
  17. package/desktop/public/icons/github.svg +0 -3
  18. package/desktop/public/icons/xiaohongshu.svg +0 -1
  19. package/desktop/scripts/build-macos-arm64.sh +0 -270
  20. package/desktop/scripts/build-sidecars.ts +0 -183
  21. package/desktop/scripts/build-windows-x64.ps1 +0 -295
  22. package/desktop/scripts/scan-missing-imports.ts +0 -235
  23. package/desktop/sidecars/claude-sidecar.ts +0 -156
  24. package/desktop/src/App.tsx +0 -5
  25. package/desktop/src/__tests__/agentsSettings.test.tsx +0 -349
  26. package/desktop/src/__tests__/pages.test.tsx +0 -290
  27. package/desktop/src/__tests__/skillsSettings.test.tsx +0 -205
  28. package/desktop/src/api/adapters.ts +0 -12
  29. package/desktop/src/api/agents.ts +0 -36
  30. package/desktop/src/api/cliTasks.ts +0 -28
  31. package/desktop/src/api/client.ts +0 -63
  32. package/desktop/src/api/computerUse.ts +0 -76
  33. package/desktop/src/api/filesystem.ts +0 -30
  34. package/desktop/src/api/hahaOAuth.ts +0 -38
  35. package/desktop/src/api/models.ts +0 -28
  36. package/desktop/src/api/providers.ts +0 -63
  37. package/desktop/src/api/search.ts +0 -29
  38. package/desktop/src/api/sessions.ts +0 -56
  39. package/desktop/src/api/settings.ts +0 -20
  40. package/desktop/src/api/skills.ts +0 -19
  41. package/desktop/src/api/tasks.ts +0 -36
  42. package/desktop/src/api/teams.ts +0 -44
  43. package/desktop/src/api/websocket.ts +0 -164
  44. package/desktop/src/components/chat/AskUserQuestion.tsx +0 -268
  45. package/desktop/src/components/chat/AssistantMessage.tsx +0 -29
  46. package/desktop/src/components/chat/AttachmentGallery.tsx +0 -113
  47. package/desktop/src/components/chat/ChatInput.tsx +0 -622
  48. package/desktop/src/components/chat/CodeViewer.tsx +0 -161
  49. package/desktop/src/components/chat/ComputerUsePermissionModal.test.tsx +0 -174
  50. package/desktop/src/components/chat/ComputerUsePermissionModal.tsx +0 -311
  51. package/desktop/src/components/chat/DiffViewer.tsx +0 -157
  52. package/desktop/src/components/chat/FileSearchMenu.tsx +0 -198
  53. package/desktop/src/components/chat/ImageGalleryModal.tsx +0 -91
  54. package/desktop/src/components/chat/InlineImageGallery.tsx +0 -106
  55. package/desktop/src/components/chat/InlineTaskSummary.tsx +0 -60
  56. package/desktop/src/components/chat/MermaidRenderer.test.tsx +0 -98
  57. package/desktop/src/components/chat/MermaidRenderer.tsx +0 -361
  58. package/desktop/src/components/chat/MessageActionBar.tsx +0 -27
  59. package/desktop/src/components/chat/MessageList.test.tsx +0 -313
  60. package/desktop/src/components/chat/MessageList.tsx +0 -249
  61. package/desktop/src/components/chat/PermissionDialog.tsx +0 -262
  62. package/desktop/src/components/chat/SessionTaskBar.test.tsx +0 -99
  63. package/desktop/src/components/chat/SessionTaskBar.tsx +0 -159
  64. package/desktop/src/components/chat/StreamingIndicator.tsx +0 -41
  65. package/desktop/src/components/chat/TerminalChrome.tsx +0 -35
  66. package/desktop/src/components/chat/ThinkingBlock.tsx +0 -87
  67. package/desktop/src/components/chat/ToolCallBlock.tsx +0 -247
  68. package/desktop/src/components/chat/ToolCallGroup.tsx +0 -617
  69. package/desktop/src/components/chat/ToolResultBlock.tsx +0 -107
  70. package/desktop/src/components/chat/UserMessage.tsx +0 -38
  71. package/desktop/src/components/chat/chatBlocks.test.tsx +0 -136
  72. package/desktop/src/components/chat/clipboard.ts +0 -25
  73. package/desktop/src/components/chat/composerUtils.test.ts +0 -55
  74. package/desktop/src/components/chat/composerUtils.ts +0 -149
  75. package/desktop/src/components/controls/ModelSelector.tsx +0 -156
  76. package/desktop/src/components/controls/PermissionModeSelector.tsx +0 -229
  77. package/desktop/src/components/layout/AppShell.tsx +0 -107
  78. package/desktop/src/components/layout/ContentRouter.tsx +0 -27
  79. package/desktop/src/components/layout/ProjectFilter.tsx +0 -126
  80. package/desktop/src/components/layout/Sidebar.test.tsx +0 -158
  81. package/desktop/src/components/layout/Sidebar.tsx +0 -384
  82. package/desktop/src/components/layout/StatusBar.tsx +0 -31
  83. package/desktop/src/components/layout/TabBar.test.tsx +0 -136
  84. package/desktop/src/components/layout/TabBar.tsx +0 -318
  85. package/desktop/src/components/layout/TitleBar.tsx +0 -96
  86. package/desktop/src/components/layout/WindowControls.test.tsx +0 -69
  87. package/desktop/src/components/layout/WindowControls.tsx +0 -89
  88. package/desktop/src/components/markdown/MarkdownRenderer.test.tsx +0 -100
  89. package/desktop/src/components/markdown/MarkdownRenderer.tsx +0 -229
  90. package/desktop/src/components/settings/ClaudeOfficialLogin.tsx +0 -107
  91. package/desktop/src/components/shared/Button.tsx +0 -63
  92. package/desktop/src/components/shared/CopyButton.tsx +0 -58
  93. package/desktop/src/components/shared/DirectoryPicker.tsx +0 -316
  94. package/desktop/src/components/shared/Dropdown.tsx +0 -91
  95. package/desktop/src/components/shared/Input.tsx +0 -38
  96. package/desktop/src/components/shared/Modal.tsx +0 -65
  97. package/desktop/src/components/shared/ProjectContextChip.tsx +0 -30
  98. package/desktop/src/components/shared/Spinner.tsx +0 -30
  99. package/desktop/src/components/shared/Textarea.tsx +0 -38
  100. package/desktop/src/components/shared/Toast.tsx +0 -47
  101. package/desktop/src/components/shared/UpdateChecker.tsx +0 -90
  102. package/desktop/src/components/skills/SkillDetail.test.tsx +0 -89
  103. package/desktop/src/components/skills/SkillDetail.tsx +0 -403
  104. package/desktop/src/components/skills/SkillList.tsx +0 -254
  105. package/desktop/src/components/tasks/DayOfWeekPicker.tsx +0 -57
  106. package/desktop/src/components/tasks/NewTaskModal.tsx +0 -407
  107. package/desktop/src/components/tasks/PromptEditor.tsx +0 -74
  108. package/desktop/src/components/tasks/TaskEmptyState.tsx +0 -30
  109. package/desktop/src/components/tasks/TaskList.tsx +0 -46
  110. package/desktop/src/components/tasks/TaskRow.tsx +0 -253
  111. package/desktop/src/components/tasks/TaskRunsPanel.tsx +0 -195
  112. package/desktop/src/components/teams/TeamStatusBar.tsx +0 -147
  113. package/desktop/src/config/providerPresets.ts +0 -78
  114. package/desktop/src/config/spinnerVerbs.ts +0 -193
  115. package/desktop/src/hooks/useKeyboardShortcuts.ts +0 -60
  116. package/desktop/src/i18n/index.ts +0 -54
  117. package/desktop/src/i18n/locales/en.ts +0 -670
  118. package/desktop/src/i18n/locales/zh.ts +0 -670
  119. package/desktop/src/lib/__tests__/cronDescribe.test.ts +0 -93
  120. package/desktop/src/lib/cronDescribe.ts +0 -188
  121. package/desktop/src/lib/desktopRuntime.ts +0 -54
  122. package/desktop/src/lib/parseRunOutput.ts +0 -79
  123. package/desktop/src/main.tsx +0 -13
  124. package/desktop/src/mocks/data.ts +0 -202
  125. package/desktop/src/pages/ActiveSession.test.tsx +0 -181
  126. package/desktop/src/pages/ActiveSession.tsx +0 -219
  127. package/desktop/src/pages/AdapterSettings.tsx +0 -375
  128. package/desktop/src/pages/AgentTeams.tsx +0 -200
  129. package/desktop/src/pages/ComputerUseSettings.tsx +0 -420
  130. package/desktop/src/pages/EmptySession.tsx +0 -518
  131. package/desktop/src/pages/NewTaskModal.tsx +0 -346
  132. package/desktop/src/pages/ScheduledTasks.tsx +0 -66
  133. package/desktop/src/pages/ScheduledTasksEmpty.tsx +0 -152
  134. package/desktop/src/pages/ScheduledTasksList.tsx +0 -416
  135. package/desktop/src/pages/SessionControls.tsx +0 -460
  136. package/desktop/src/pages/Settings.tsx +0 -1448
  137. package/desktop/src/pages/ToolInspection.tsx +0 -235
  138. package/desktop/src/stores/adapterStore.ts +0 -106
  139. package/desktop/src/stores/agentStore.ts +0 -34
  140. package/desktop/src/stores/chatStore.test.ts +0 -505
  141. package/desktop/src/stores/chatStore.ts +0 -850
  142. package/desktop/src/stores/cliTaskStore.ts +0 -152
  143. package/desktop/src/stores/hahaOAuthStore.test.ts +0 -77
  144. package/desktop/src/stores/hahaOAuthStore.ts +0 -97
  145. package/desktop/src/stores/providerStore.ts +0 -101
  146. package/desktop/src/stores/sessionStore.test.ts +0 -63
  147. package/desktop/src/stores/sessionStore.ts +0 -102
  148. package/desktop/src/stores/settingsStore.ts +0 -120
  149. package/desktop/src/stores/skillStore.ts +0 -51
  150. package/desktop/src/stores/tabStore.ts +0 -169
  151. package/desktop/src/stores/taskStore.ts +0 -68
  152. package/desktop/src/stores/teamStore.ts +0 -344
  153. package/desktop/src/stores/uiStore.ts +0 -100
  154. package/desktop/src/stores/updateStore.test.ts +0 -71
  155. package/desktop/src/stores/updateStore.ts +0 -221
  156. package/desktop/src/theme/globals.css +0 -465
  157. package/desktop/src/types/adapter.ts +0 -33
  158. package/desktop/src/types/chat.ts +0 -152
  159. package/desktop/src/types/cliTask.ts +0 -24
  160. package/desktop/src/types/provider.ts +0 -62
  161. package/desktop/src/types/session.ts +0 -27
  162. package/desktop/src/types/settings.ts +0 -22
  163. package/desktop/src/types/skill.ts +0 -38
  164. package/desktop/src/types/task.ts +0 -56
  165. package/desktop/src/types/team.ts +0 -38
  166. package/desktop/src-tauri/Cargo.lock +0 -5549
  167. package/desktop/src-tauri/Cargo.toml +0 -20
  168. package/desktop/src-tauri/app-icon.svg +0 -13
  169. package/desktop/src-tauri/build.rs +0 -3
  170. package/desktop/src-tauri/capabilities/default.json +0 -106
  171. package/desktop/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml +0 -5
  172. package/desktop/src-tauri/icons/android/values/ic_launcher_background.xml +0 -4
  173. package/desktop/src-tauri/icons/icon.icns +0 -0
  174. package/desktop/src-tauri/icons/icon.ico +0 -0
  175. package/desktop/src-tauri/src/lib.rs +0 -408
  176. package/desktop/src-tauri/src/main.rs +0 -6
  177. package/desktop/src-tauri/tauri.conf.json +0 -78
  178. package/desktop/src-tauri/tauri.macos.conf.json +0 -18
  179. package/desktop/src-tauri/tauri.release-ci.json +0 -5
  180. package/desktop/src-tauri/tauri.windows.conf.json +0 -16
  181. package/desktop/src-tauri/windows-installer-hooks.nsh +0 -17
  182. package/desktop/tsconfig.json +0 -25
  183. package/desktop/vite.config.ts +0 -26
  184. package/desktop/vitest.config.ts +0 -18
@@ -1,375 +0,0 @@
1
- import { useState, useEffect, useCallback } from 'react'
2
- import { useAdapterStore } from '../stores/adapterStore'
3
- import { useTranslation } from '../i18n'
4
- import { Input } from '../components/shared/Input'
5
- import { Button } from '../components/shared/Button'
6
- import { DirectoryPicker } from '../components/shared/DirectoryPicker'
7
-
8
- type ImTab = 'feishu' | 'telegram'
9
-
10
- export function AdapterSettings() {
11
- const t = useTranslation()
12
- const { config, isLoading, fetchConfig, updateConfig, generatePairingCode, removePairedUser } = useAdapterStore()
13
-
14
- // Active IM tab —— Feishu 默认展示,在前
15
- const [activeIm, setActiveIm] = useState<ImTab>('feishu')
16
-
17
- // Server —— serverUrl 不再暴露在 UI 里(见下方 Server URL 注释),
18
- // 桌面端用 Tauri env var 注入动态端口。
19
- const [defaultProjectDir, setDefaultProjectDir] = useState('')
20
-
21
- // Telegram
22
- const [tgBotToken, setTgBotToken] = useState('')
23
- const [tgAllowedUsers, setTgAllowedUsers] = useState('')
24
-
25
- // Feishu
26
- const [fsAppId, setFsAppId] = useState('')
27
- const [fsAppSecret, setFsAppSecret] = useState('')
28
- const [fsEncryptKey, setFsEncryptKey] = useState('')
29
- const [fsVerificationToken, setFsVerificationToken] = useState('')
30
- const [fsAllowedUsers, setFsAllowedUsers] = useState('')
31
- const [fsStreamingCard, setFsStreamingCard] = useState(false)
32
-
33
- const [isSaving, setIsSaving] = useState(false)
34
- const [saveStatus, setSaveStatus] = useState<'idle' | 'saved' | 'error'>('idle')
35
- const [saveError, setSaveError] = useState('')
36
-
37
- // Pairing
38
- const [pairingCode, setPairingCode] = useState<string | null>(null)
39
- const [isGenerating, setIsGenerating] = useState(false)
40
-
41
- useEffect(() => {
42
- fetchConfig()
43
- }, [])
44
-
45
- // Sync form state when config is loaded
46
- useEffect(() => {
47
- setDefaultProjectDir(config.defaultProjectDir ?? '')
48
- setTgBotToken(config.telegram?.botToken ?? '')
49
- setTgAllowedUsers(config.telegram?.allowedUsers?.join(', ') ?? '')
50
- setFsAppId(config.feishu?.appId ?? '')
51
- setFsAppSecret(config.feishu?.appSecret ?? '')
52
- setFsEncryptKey(config.feishu?.encryptKey ?? '')
53
- setFsVerificationToken(config.feishu?.verificationToken ?? '')
54
- setFsAllowedUsers(config.feishu?.allowedUsers?.join(', ') ?? '')
55
- setFsStreamingCard(config.feishu?.streamingCard ?? false)
56
- }, [config])
57
-
58
- async function handleSave() {
59
- setIsSaving(true)
60
- setSaveStatus('idle')
61
- setSaveError('')
62
- try {
63
- const patch: Record<string, unknown> = {}
64
-
65
- if (defaultProjectDir) patch.defaultProjectDir = defaultProjectDir
66
-
67
- const tgUsers = tgAllowedUsers
68
- .split(',')
69
- .map((s) => s.trim())
70
- .filter(Boolean)
71
- .map(Number)
72
- .filter((n) => !isNaN(n))
73
-
74
- patch.telegram = {
75
- botToken: tgBotToken || undefined,
76
- allowedUsers: tgUsers.length ? tgUsers : [],
77
- }
78
-
79
- const fsUsers = fsAllowedUsers
80
- .split(',')
81
- .map((s) => s.trim())
82
- .filter(Boolean)
83
-
84
- patch.feishu = {
85
- appId: fsAppId || undefined,
86
- appSecret: fsAppSecret || undefined,
87
- encryptKey: fsEncryptKey || undefined,
88
- verificationToken: fsVerificationToken || undefined,
89
- allowedUsers: fsUsers.length ? fsUsers : [],
90
- streamingCard: fsStreamingCard,
91
- }
92
-
93
- await updateConfig(patch)
94
- setSaveStatus('saved')
95
- setTimeout(() => setSaveStatus('idle'), 2000)
96
- } catch (err) {
97
- setSaveStatus('error')
98
- setSaveError(err instanceof Error ? err.message : 'Save failed')
99
- } finally {
100
- setIsSaving(false)
101
- }
102
- }
103
-
104
- const handleGenerateCode = useCallback(async () => {
105
- setIsGenerating(true)
106
- try {
107
- const code = await generatePairingCode()
108
- setPairingCode(code)
109
- } catch (err) {
110
- console.error('Failed to generate pairing code:', err)
111
- } finally {
112
- setIsGenerating(false)
113
- }
114
- }, [generatePairingCode])
115
-
116
- const handleUnbind = useCallback(async (platform: 'telegram' | 'feishu', userId: string | number) => {
117
- if (!confirm(t('settings.adapters.unbindConfirm'))) return
118
- await removePairedUser(platform, userId)
119
- await fetchConfig()
120
- }, [removePairedUser, fetchConfig, t])
121
-
122
- // Collect all paired users across platforms
123
- const allPairedUsers = [
124
- ...(config.telegram?.pairedUsers ?? []).map((u) => ({ ...u, platform: 'telegram' as const })),
125
- ...(config.feishu?.pairedUsers ?? []).map((u) => ({ ...u, platform: 'feishu' as const })),
126
- ]
127
-
128
- // Check pairing expiry
129
- const pairingExpiry = config.pairing?.expiresAt
130
- const isPairingActive = pairingExpiry ? Date.now() < pairingExpiry : false
131
- const minutesLeft = pairingExpiry ? Math.max(0, Math.ceil((pairingExpiry - Date.now()) / 60000)) : 0
132
-
133
- if (isLoading) {
134
- return (
135
- <div className="flex items-center justify-center py-12 text-[var(--color-text-tertiary)]">
136
- <span className="material-symbols-outlined animate-spin text-[20px] mr-2">progress_activity</span>
137
- Loading...
138
- </div>
139
- )
140
- }
141
-
142
- return (
143
- <div className="max-w-2xl space-y-8">
144
- {/* Description */}
145
- <div>
146
- <p className="text-sm text-[var(--color-text-secondary)]">{t('settings.adapters.description')}</p>
147
- </div>
148
-
149
- {/* Pairing */}
150
- <section className="rounded-xl border border-[var(--color-border)] overflow-hidden">
151
- <div className="flex items-center gap-2 px-4 py-3 bg-[var(--color-surface-hover)] border-b border-[var(--color-border)]">
152
- <span className="material-symbols-outlined text-[18px] text-[var(--color-text-secondary)]">link</span>
153
- <span className="text-sm font-semibold text-[var(--color-text-primary)]">{t('settings.adapters.pairing')}</span>
154
- </div>
155
- <div className="p-4 space-y-4">
156
- <p className="text-sm text-[var(--color-text-secondary)]">{t('settings.adapters.pairingDesc')}</p>
157
-
158
- {/* Generate code */}
159
- <div className="flex items-center gap-3">
160
- <Button onClick={handleGenerateCode} loading={isGenerating}>
161
- {pairingCode || isPairingActive ? t('settings.adapters.regenerateCode') : t('settings.adapters.generateCode')}
162
- </Button>
163
- {pairingCode && (
164
- <div className="flex items-center gap-2">
165
- <span className="font-mono text-2xl font-bold tracking-[0.3em] text-[var(--color-brand)]">
166
- {pairingCode}
167
- </span>
168
- <span className="text-xs text-[var(--color-text-tertiary)]">
169
- {t('settings.adapters.codeExpiresIn')} 60 {t('settings.adapters.minutes')}
170
- </span>
171
- </div>
172
- )}
173
- {!pairingCode && isPairingActive && (
174
- <span className="text-xs text-[var(--color-text-tertiary)]">
175
- {t('settings.adapters.codeExpiresIn')} {minutesLeft} {t('settings.adapters.minutes')}
176
- </span>
177
- )}
178
- </div>
179
- {pairingCode && (
180
- <p className="text-xs text-[var(--color-text-tertiary)]">{t('settings.adapters.pairingCodeHint')}</p>
181
- )}
182
-
183
- {/* Paired users list */}
184
- <div>
185
- <h4 className="text-sm font-medium text-[var(--color-text-primary)] mb-2">{t('settings.adapters.pairedUsers')}</h4>
186
- {allPairedUsers.length === 0 ? (
187
- <p className="text-sm text-[var(--color-text-tertiary)]">{t('settings.adapters.noPairedUsers')}</p>
188
- ) : (
189
- <div className="space-y-2">
190
- {allPairedUsers.map((user) => (
191
- <div
192
- key={`${user.platform}-${user.userId}`}
193
- className="flex items-center justify-between px-3 py-2 rounded-lg bg-[var(--color-surface-hover)]"
194
- >
195
- <div className="flex items-center gap-2">
196
- <span className="text-xs px-1.5 py-0.5 rounded bg-[var(--color-surface)] text-[var(--color-text-secondary)]">
197
- {t(`settings.adapters.platform.${user.platform}`)}
198
- </span>
199
- <span className="text-sm text-[var(--color-text-primary)]">{user.displayName}</span>
200
- <span className="text-xs text-[var(--color-text-tertiary)]">
201
- {new Date(user.pairedAt).toLocaleDateString()}
202
- </span>
203
- </div>
204
- <button
205
- onClick={() => handleUnbind(user.platform, user.userId)}
206
- className="text-xs text-[var(--color-error)] hover:underline cursor-pointer"
207
- >
208
- {t('settings.adapters.unbind')}
209
- </button>
210
- </div>
211
- ))}
212
- </div>
213
- )}
214
- </div>
215
- </div>
216
- </section>
217
-
218
- {/* Server URL —— 之前是个手填字段,但桌面端 Tauri 启动 adapter sidecar
219
- 时已经把 server 的动态端口通过 ADAPTER_SERVER_URL env var 注进去了,
220
- loadConfig() 里 env 优先级高于这里的 file value,所以这个字段在桌面
221
- 运行时完全不会被读到。用户也根本不知道该填什么端口(每次启动随机)。
222
- Standalone 模式(直接 bun run adapters/...)保留 file 字段兜底就够了。 */}
223
-
224
- {/* Default Project */}
225
- <div className="flex flex-col gap-1">
226
- <label className="text-sm font-medium text-[var(--color-text-primary)]">
227
- {t('settings.adapters.defaultProject')}
228
- </label>
229
- <DirectoryPicker value={defaultProjectDir} onChange={setDefaultProjectDir} />
230
- <p className="text-xs text-[var(--color-text-tertiary)]">
231
- {t('settings.adapters.defaultProjectHint')}
232
- </p>
233
- </div>
234
-
235
- {/* IM Adapter Tabs —— Feishu 默认在前,Telegram 在后 */}
236
- <section className="rounded-xl border border-[var(--color-border)] overflow-hidden">
237
- <div role="tablist" aria-label="IM adapter" className="flex items-stretch border-b border-[var(--color-border)] bg-[var(--color-surface-hover)]">
238
- <ImTabButton
239
- label={t('settings.adapters.feishu')}
240
- active={activeIm === 'feishu'}
241
- onClick={() => setActiveIm('feishu')}
242
- />
243
- <ImTabButton
244
- label={t('settings.adapters.telegram')}
245
- active={activeIm === 'telegram'}
246
- onClick={() => setActiveIm('telegram')}
247
- />
248
- </div>
249
-
250
- {activeIm === 'feishu' && (
251
- <div className="p-4 space-y-4">
252
- <div className="grid grid-cols-2 gap-4">
253
- <Input
254
- label={t('settings.adapters.appId')}
255
- value={fsAppId}
256
- onChange={(e) => setFsAppId(e.target.value)}
257
- placeholder={t('settings.adapters.appIdPlaceholder')}
258
- />
259
- <Input
260
- label={t('settings.adapters.appSecret')}
261
- type="password"
262
- value={fsAppSecret}
263
- onChange={(e) => setFsAppSecret(e.target.value)}
264
- placeholder={t('settings.adapters.appSecretPlaceholder')}
265
- />
266
- </div>
267
- <div className="grid grid-cols-2 gap-4">
268
- <Input
269
- label={t('settings.adapters.encryptKey')}
270
- type="password"
271
- value={fsEncryptKey}
272
- onChange={(e) => setFsEncryptKey(e.target.value)}
273
- placeholder={t('settings.adapters.encryptKeyPlaceholder')}
274
- />
275
- <Input
276
- label={t('settings.adapters.verificationToken')}
277
- type="password"
278
- value={fsVerificationToken}
279
- onChange={(e) => setFsVerificationToken(e.target.value)}
280
- placeholder={t('settings.adapters.verificationTokenPlaceholder')}
281
- />
282
- </div>
283
- <div className="flex flex-col gap-1">
284
- <Input
285
- label={t('settings.adapters.allowedUsers')}
286
- value={fsAllowedUsers}
287
- onChange={(e) => setFsAllowedUsers(e.target.value)}
288
- placeholder={t('settings.adapters.fsAllowedUsersPlaceholder')}
289
- />
290
- <p className="text-xs text-[var(--color-text-tertiary)]">{t('settings.adapters.allowedUsersHint')}</p>
291
- </div>
292
- <label className="flex items-center gap-3 cursor-pointer">
293
- <input
294
- type="checkbox"
295
- checked={fsStreamingCard}
296
- onChange={(e) => setFsStreamingCard(e.target.checked)}
297
- className="w-4 h-4 rounded border-[var(--color-border)] accent-[var(--color-brand)]"
298
- />
299
- <div>
300
- <span className="text-sm text-[var(--color-text-primary)]">{t('settings.adapters.streamingCard')}</span>
301
- <p className="text-xs text-[var(--color-text-tertiary)]">{t('settings.adapters.streamingCardDesc')}</p>
302
- </div>
303
- </label>
304
- </div>
305
- )}
306
-
307
- {activeIm === 'telegram' && (
308
- <div className="p-4 space-y-4">
309
- <Input
310
- label={t('settings.adapters.botToken')}
311
- type="password"
312
- value={tgBotToken}
313
- onChange={(e) => setTgBotToken(e.target.value)}
314
- placeholder={t('settings.adapters.botTokenPlaceholder')}
315
- />
316
- <div className="flex flex-col gap-1">
317
- <Input
318
- label={t('settings.adapters.allowedUsers')}
319
- value={tgAllowedUsers}
320
- onChange={(e) => setTgAllowedUsers(e.target.value)}
321
- placeholder={t('settings.adapters.tgAllowedUsersPlaceholder')}
322
- />
323
- <p className="text-xs text-[var(--color-text-tertiary)]">{t('settings.adapters.allowedUsersHint')}</p>
324
- </div>
325
- </div>
326
- )}
327
- </section>
328
-
329
- {/* Save */}
330
- <div className="flex items-center gap-3">
331
- <Button onClick={handleSave} loading={isSaving}>
332
- {saveStatus === 'saved' ? t('settings.adapters.saved') : t('settings.adapters.save')}
333
- </Button>
334
- {saveStatus === 'saved' && (
335
- <span className="text-sm text-[var(--color-success)]">
336
- <span className="material-symbols-outlined text-[16px] align-middle mr-1">check_circle</span>
337
- {t('settings.adapters.saved')}
338
- </span>
339
- )}
340
- {saveStatus === 'error' && (
341
- <span className="text-sm text-[var(--color-error)]">
342
- <span className="material-symbols-outlined text-[16px] align-middle mr-1">error</span>
343
- {saveError}
344
- </span>
345
- )}
346
- </div>
347
- </div>
348
- )
349
- }
350
-
351
- function ImTabButton({
352
- label,
353
- active,
354
- onClick,
355
- }: {
356
- label: string
357
- active: boolean
358
- onClick: () => void
359
- }) {
360
- return (
361
- <button
362
- type="button"
363
- role="tab"
364
- aria-selected={active}
365
- onClick={onClick}
366
- className={`relative px-4 py-2.5 text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-brand)] focus-visible:ring-inset ${
367
- active
368
- ? 'text-[var(--color-text-primary)] font-semibold after:absolute after:left-3 after:right-3 after:bottom-0 after:h-[2px] after:bg-[var(--color-brand)]'
369
- : 'text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)]'
370
- }`}
371
- >
372
- {label}
373
- </button>
374
- )
375
- }
@@ -1,200 +0,0 @@
1
- import { useState } from 'react'
2
- import { mockTeam, mockTeamMessages } from '../mocks/data'
3
-
4
- // ─── Inline keyframes for pulse-subtle animation ─────────────────
5
- const pulseSubtleStyle = `
6
- @keyframes pulse-subtle {
7
- 0%, 100% { opacity: 1; }
8
- 50% { opacity: 0.7; transform: scale(0.98); }
9
- }
10
- .animate-pulse-subtle {
11
- animation: pulse-subtle 2s ease-in-out infinite;
12
- }
13
- `
14
-
15
- export function AgentTeams() {
16
- const [inputValue, setInputValue] = useState('')
17
-
18
- return (
19
- <>
20
- <style>{pulseSubtleStyle}</style>
21
-
22
- <div className="flex-1 flex flex-col relative overflow-hidden bg-[var(--color-surface)] text-[var(--color-text-primary)]" style={{ fontFamily: 'var(--font-body)' }}>
23
- {/* Code Content Area */}
24
- <div className="flex-1 overflow-y-auto p-6 md:p-10 max-w-5xl mx-auto w-full">
25
- <div className="space-y-8">
26
- {/* ─── Message Thread ─── */}
27
- <div className="space-y-6">
28
- {/* USER message */}
29
- <div className="flex gap-4 group">
30
- <div className="w-8 h-8 rounded-full bg-[var(--color-primary-fixed)] flex-shrink-0 flex items-center justify-center text-[var(--color-on-primary)] font-bold text-xs">
31
- U
32
- </div>
33
- <div className="space-y-2">
34
- <p className="text-xs font-semibold text-[var(--color-text-tertiary)] uppercase tracking-widest">
35
- User
36
- </p>
37
- <p className="text-[var(--color-text-primary)] leading-relaxed">
38
- {mockTeamMessages.userMessage}
39
- </p>
40
- </div>
41
- </div>
42
-
43
- {/* CLAUDE COMPANION response */}
44
- <div className="flex gap-4 group">
45
- <div className="w-8 h-8 rounded-full bg-[var(--color-tertiary-container)] flex-shrink-0 flex items-center justify-center text-[var(--color-tertiary)]">
46
- <span
47
- className="material-symbols-outlined text-sm"
48
- style={{ fontVariationSettings: "'FILL' 1" }}
49
- >
50
- smart_toy
51
- </span>
52
- </div>
53
- <div className="space-y-4 flex-1">
54
- <p className="text-xs font-semibold text-[var(--color-text-tertiary)] uppercase tracking-widest">
55
- Claude Companion
56
- </p>
57
- <div className="rounded-xl border border-[var(--color-border)] bg-[var(--color-surface-container-low)] p-5 shadow-[var(--shadow-dropdown)]">
58
- <p className="mb-4 text-[var(--color-text-primary)]">
59
- {mockTeamMessages.assistantMessage}
60
- </p>
61
- <div className="rounded-lg bg-[var(--color-surface-container-high)] p-4 font-[var(--font-mono)] text-[13px] text-[var(--color-text-secondary)] overflow-x-auto">
62
- <span className="text-[var(--color-brand)]">info:</span> spawning child_processes for parallel development
63
- <br />
64
- <span className="text-[var(--color-secondary)]">active:</span> session-dev cluster initiated
65
- <br />
66
- <span className="text-[var(--color-tertiary)]">ready:</span> 4 agents assigned
67
- </div>
68
- </div>
69
- </div>
70
- </div>
71
- </div>
72
-
73
- {/* ─── TEAM STRIP ─── */}
74
- <div className="relative py-8">
75
- <div className="absolute inset-x-0 top-1/2 -translate-y-1/2 h-px bg-[var(--color-border-separator)]" />
76
-
77
- <div className="relative glass-panel p-4 rounded-2xl flex flex-col md:flex-row md:items-center gap-4 overflow-hidden">
78
- {/* Team label */}
79
- <div className="flex items-center gap-3 pr-4 md:border-r border-[var(--color-border-separator)]">
80
- <div className="p-2 bg-[var(--color-primary-fixed)]/20 rounded-lg">
81
- <span className="material-symbols-outlined text-[var(--color-brand)] text-xl">
82
- groups
83
- </span>
84
- </div>
85
- <div>
86
- <h3 className="text-sm font-bold text-[var(--color-text-primary)]" style={{ fontFamily: 'var(--font-headline)' }}>
87
- Team: {mockTeam.name}
88
- </h3>
89
- <p className="text-[11px] font-medium text-[var(--color-text-tertiary)] uppercase tracking-tighter">
90
- {mockTeam.memberCount} members
91
- </p>
92
- </div>
93
- </div>
94
-
95
- {/* Agent Chips */}
96
- <div className="flex flex-wrap gap-2 items-center flex-1">
97
- {mockTeam.members.map((member) => {
98
- if (member.status === 'completed') {
99
- return (
100
- <div
101
- key={member.id}
102
- className="flex items-center gap-2 px-3 py-1.5 bg-[var(--color-surface-container-high)] rounded-full border border-[var(--color-success)]/20 group hover:border-[var(--color-success)]/50 transition-all cursor-pointer"
103
- >
104
- <div className="w-2 h-2 rounded-full bg-[var(--color-success)] shadow-[0_0_8px_rgba(126,219,139,0.4)]" />
105
- <span className="text-xs font-semibold text-[var(--color-text-primary)]">
106
- {member.role}
107
- </span>
108
- <span
109
- className="material-symbols-outlined text-[14px] text-[var(--color-success)]"
110
- style={{ fontVariationSettings: "'FILL' 1" }}
111
- >
112
- check_circle
113
- </span>
114
- </div>
115
- )
116
- }
117
-
118
- if (member.status === 'running') {
119
- return (
120
- <div
121
- key={member.id}
122
- className="flex items-center gap-2 px-3 py-1.5 bg-[var(--color-surface-container-high)] rounded-full border border-[var(--color-brand)]/20 animate-pulse-subtle group hover:border-[var(--color-brand)]/50 transition-all cursor-pointer"
123
- >
124
- <div className="w-2 h-2 rounded-full bg-[var(--color-warning)] shadow-[0_0_8px_rgba(247,196,108,0.4)]" />
125
- <span className="text-xs font-semibold text-[var(--color-text-primary)]">
126
- {member.role}
127
- </span>
128
- <span
129
- className="material-symbols-outlined text-[14px] text-[var(--color-warning)]"
130
- style={{ fontVariationSettings: "'FILL' 1" }}
131
- >
132
- sync
133
- </span>
134
- </div>
135
- )
136
- }
137
-
138
- return (
139
- <div
140
- key={member.id}
141
- className="flex items-center gap-2 px-3 py-1.5 bg-[var(--color-surface-container-low)] rounded-full border border-[var(--color-border)] grayscale group hover:grayscale-0 hover:border-[var(--color-secondary)]/50 transition-all cursor-pointer"
142
- >
143
- <div className="w-2 h-2 rounded-full bg-[var(--color-text-tertiary)] shadow-[0_0_8px_rgba(135,115,109,0.2)]" />
144
- <span className="text-xs font-semibold text-[var(--color-text-tertiary)] group-hover:text-[var(--color-text-primary)]">
145
- {member.role}
146
- </span>
147
- <span className="material-symbols-outlined text-[14px] text-[var(--color-text-tertiary)]">
148
- {member.role === 'Tester' ? 'schedule' : 'pause_circle'}
149
- </span>
150
- </div>
151
- )
152
- })}
153
- </div>
154
-
155
- {/* Expand button */}
156
- <button className="ml-auto p-2 hover:bg-[var(--color-surface-hover)] rounded-full transition-colors text-[var(--color-text-tertiary)]">
157
- <span className="material-symbols-outlined text-sm">expand_more</span>
158
- </button>
159
- </div>
160
- </div>
161
-
162
- {/* ─── Chat Composer ─── */}
163
- <div className="max-w-3xl mx-auto w-full mt-auto">
164
- <div className="glass-panel relative rounded-xl p-1.5 flex items-center gap-2 transition-all">
165
- <div className="p-2 text-[var(--color-text-secondary)]">
166
- <span className="material-symbols-outlined">attach_file</span>
167
- </div>
168
- <input
169
- className="flex-1 bg-transparent border-none focus:ring-0 focus:outline-none text-sm text-[var(--color-text-primary)] py-2"
170
- placeholder="Type a command or ask Claude..."
171
- type="text"
172
- value={inputValue}
173
- onChange={(e) => setInputValue(e.target.value)}
174
- />
175
- <button className="bg-[image:var(--gradient-btn-primary)] text-[var(--color-btn-primary-fg)] shadow-[var(--shadow-button-primary)] w-9 h-9 rounded-lg flex items-center justify-center transition-all hover:brightness-105 active:scale-95">
176
- <span
177
- className="material-symbols-outlined text-lg"
178
- style={{ fontVariationSettings: "'FILL' 1" }}
179
- >
180
- send
181
- </span>
182
- </button>
183
- </div>
184
- <div className="mt-3 flex justify-center gap-4">
185
- <div className="flex items-center gap-1.5 text-[10px] text-[var(--color-text-tertiary)] font-semibold uppercase tracking-widest">
186
- <span className="w-1.5 h-1.5 rounded-full bg-[var(--color-success)]" />
187
- Auto-run enabled
188
- </div>
189
- <div className="flex items-center gap-1.5 text-[10px] text-[var(--color-text-tertiary)] font-semibold uppercase tracking-widest">
190
- <span className="w-1.5 h-1.5 rounded-full bg-[var(--color-secondary)]" />
191
- Local LLM
192
- </div>
193
- </div>
194
- </div>
195
- </div>
196
- </div>
197
- </div>
198
- </>
199
- )
200
- }