@yancyyu/openhermit 1.6.38 → 1.6.39

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 (188) hide show
  1. package/dist-renderer/assets/ProjectEditorOverlay-krO5vQxX.js +58 -0
  2. package/dist-renderer/assets/{TeamGraphOverlay-ZEDfZyHb.js → TeamGraphOverlay-DqhQzcTr.js} +1 -1
  3. package/dist-renderer/assets/{_basePickBy-CIhniz70.js → _basePickBy-B7kSYPxr.js} +1 -1
  4. package/dist-renderer/assets/{_baseUniq-cKAW4Q8I.js → _baseUniq-CnjxqwAk.js} +1 -1
  5. package/dist-renderer/assets/{arc-YmNsoDXW.js → arc-CLeZuINP.js} +1 -1
  6. package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-DHEls2sX.js → architectureDiagram-VXUJARFQ-QKtqaqdY.js} +1 -1
  7. package/dist-renderer/assets/{blockDiagram-VD42YOAC-Bpwf1Sbg.js → blockDiagram-VD42YOAC-BqdrzO_f.js} +1 -1
  8. package/dist-renderer/assets/{c4Diagram-YG6GDRKO-B0IaQ4w5.js → c4Diagram-YG6GDRKO-gwPlCxDC.js} +1 -1
  9. package/dist-renderer/assets/channel-DpMHF50r.js +1 -0
  10. package/dist-renderer/assets/{chunk-4BX2VUAB-DLk-hcFc.js → chunk-4BX2VUAB-C6XLurL4.js} +1 -1
  11. package/dist-renderer/assets/{chunk-55IACEB6-1XRmX_Zm.js → chunk-55IACEB6-Ds6quhEP.js} +1 -1
  12. package/dist-renderer/assets/{chunk-B4BG7PRW-1waH1DAD.js → chunk-B4BG7PRW-5UlA1_e9.js} +1 -1
  13. package/dist-renderer/assets/{chunk-DI55MBZ5-BqpZBtrN.js → chunk-DI55MBZ5-ywFrqIsY.js} +1 -1
  14. package/dist-renderer/assets/{chunk-FMBD7UC4-Bly7vVym.js → chunk-FMBD7UC4-C7ifUA17.js} +1 -1
  15. package/dist-renderer/assets/{chunk-QN33PNHL-Ci2QWBAs.js → chunk-QN33PNHL-BxGCo80U.js} +1 -1
  16. package/dist-renderer/assets/{chunk-QZHKN3VN-YCqFW7d-.js → chunk-QZHKN3VN-B2CuaZs6.js} +1 -1
  17. package/dist-renderer/assets/{chunk-TZMSLE5B-B0xGXInl.js → chunk-TZMSLE5B-Ds1hInvp.js} +1 -1
  18. package/dist-renderer/assets/classDiagram-2ON5EDUG-CBYCBVRl.js +1 -0
  19. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-CBYCBVRl.js +1 -0
  20. package/dist-renderer/assets/clone-DcMF6Psb.js +1 -0
  21. package/dist-renderer/assets/{cose-bilkent-S5V4N54A-DxcFNQKT.js → cose-bilkent-S5V4N54A-Cz1GVtLp.js} +1 -1
  22. package/dist-renderer/assets/{dagre-6UL2VRFP-DPo_RfZY.js → dagre-6UL2VRFP-BrmR-P4h.js} +1 -1
  23. package/dist-renderer/assets/{diagram-PSM6KHXK-U3hQsFe4.js → diagram-PSM6KHXK-DbNjC5Rg.js} +1 -1
  24. package/dist-renderer/assets/{diagram-QEK2KX5R-OrwrAy0V.js → diagram-QEK2KX5R-qkRX5_Mq.js} +1 -1
  25. package/dist-renderer/assets/{diagram-S2PKOQOG-CXATPWVw.js → diagram-S2PKOQOG-CyL5rCv2.js} +1 -1
  26. package/dist-renderer/assets/{erDiagram-Q2GNP2WA-B0e8AfMF.js → erDiagram-Q2GNP2WA-Dox3-bA5.js} +1 -1
  27. package/dist-renderer/assets/{flowDiagram-NV44I4VS-CXfzA4jJ.js → flowDiagram-NV44I4VS-BtkaxlDL.js} +1 -1
  28. package/dist-renderer/assets/{ganttDiagram-JELNMOA3-CMr08qVl.js → ganttDiagram-JELNMOA3-Dhy_d9GK.js} +1 -1
  29. package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-vYFHpPmy.js → gitGraphDiagram-V2S2FVAM-B5XRhIQA.js} +1 -1
  30. package/dist-renderer/assets/{graph-DOe5j8dH.js → graph-CsoEwUhS.js} +1 -1
  31. package/dist-renderer/assets/{index-BySQS7AB.js → index-BWPWmJNo.js} +1 -1
  32. package/dist-renderer/assets/{index-V7dAKPqd.js → index-Bu2R-Se7.js} +587 -705
  33. package/dist-renderer/assets/index-CnWV3BhG.css +32 -0
  34. package/dist-renderer/assets/{index-CzWxVCRL.js → index-D-3KgskL.js} +1 -1
  35. package/dist-renderer/assets/{index-VJ-MM9xa.js → index-DGEBzLNT.js} +1 -1
  36. package/dist-renderer/assets/{index-B2Dy7M2G.js → index-NhHNs2Oo.js} +1 -1
  37. package/dist-renderer/assets/{index-C_okzZXP.js → index-h17WuEyf.js} +1 -1
  38. package/dist-renderer/assets/{infoDiagram-HS3SLOUP-D_WubR0B.js → infoDiagram-HS3SLOUP-hMGmNojH.js} +1 -1
  39. package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-w9ca-1TI.js → journeyDiagram-XKPGCS4Q-DXV2rBDl.js} +1 -1
  40. package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-Jg9p6_pN.js → kanban-definition-3W4ZIXB7-Bf99WLRy.js} +1 -1
  41. package/dist-renderer/assets/{layout-B-z3y17c.js → layout-C3XWrpwo.js} +1 -1
  42. package/dist-renderer/assets/{linear-D-RTX5UW.js → linear-OEEcn8KN.js} +1 -1
  43. package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-CDQmHOYP.js → mindmap-definition-VGOIOE7T-Dpi3S2x4.js} +1 -1
  44. package/dist-renderer/assets/{pieDiagram-ADFJNKIX-D_odsQL7.js → pieDiagram-ADFJNKIX-xTPPhtNx.js} +1 -1
  45. package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-BRsmYWSA.js → quadrantDiagram-AYHSOK5B-euniyDlz.js} +1 -1
  46. package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-ChNE_BOV.js → requirementDiagram-UZGBJVZJ-D9Uiw4kF.js} +1 -1
  47. package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-C8FtpwKc.js → sankeyDiagram-TZEHDZUN-CySU4nED.js} +1 -1
  48. package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-DmLCzNcc.js → sequenceDiagram-WL72ISMW-JVGpET6V.js} +1 -1
  49. package/dist-renderer/assets/splashScene-D0YB9uxm.js +17 -0
  50. package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-WJBm4bhu.js → stateDiagram-FKZM4ZOC-B2FY5qqi.js} +1 -1
  51. package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-DcoMiR8H.js +1 -0
  52. package/dist-renderer/assets/{timeline-definition-IT6M3QCI-BXs_hOJs.js → timeline-definition-IT6M3QCI-DmycNUUe.js} +1 -1
  53. package/dist-renderer/assets/{treemap-GDKQZRPO-o04MA0G9.js → treemap-GDKQZRPO-DPq4gZuB.js} +1 -1
  54. package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-Czj69XRd.js → xychartDiagram-PRI3JC2R-J6VVJzRq.js} +1 -1
  55. package/dist-renderer/index.html +20 -53
  56. package/package.json +25 -18
  57. package/src/main/ipc/extensions.ts +2 -1
  58. package/src/main/server.ts +873 -221
  59. package/src/main/services/extensions/ExtensionFacadeService.ts +2 -5
  60. package/src/main/services/extensions/catalog/PluginCatalogService.ts +4 -2
  61. package/src/main/services/session-intelligence/ConversationTelemetryService.ts +1101 -0
  62. package/src/main/services/session-intelligence/LocalSessionScanner.ts +512 -0
  63. package/src/main/services/session-intelligence/SessionUsageParser.ts +4 -4
  64. package/src/main/services/system-manager/SystemManagerConfigService.ts +122 -0
  65. package/src/main/services/system-manager/SystemManagerPtyService.ts +233 -0
  66. package/src/main/services/system-manager/WorkflowPromptService.ts +75 -0
  67. package/src/main/services/teams-mvp/TaskDispatchService.ts +5 -6
  68. package/src/main/services/teams-mvp/TeamProvisioningService.ts +39 -2
  69. package/src/main/services/teams-mvp/TeamWorkspaceService.ts +22 -4
  70. package/src/main/utils/teamProjectResolution.ts +15 -0
  71. package/src/renderer/App.tsx +8 -4
  72. package/src/renderer/api/httpClient.ts +68 -18
  73. package/src/renderer/api/providers.ts +23 -2
  74. package/src/renderer/assets/participant-avatars/01.svg +3 -0
  75. package/src/renderer/assets/participant-avatars/02.svg +3 -0
  76. package/src/renderer/assets/participant-avatars/03.svg +3 -0
  77. package/src/renderer/assets/participant-avatars/04.svg +3 -0
  78. package/src/renderer/assets/participant-avatars/05.svg +3 -0
  79. package/src/renderer/assets/participant-avatars/06.svg +3 -0
  80. package/src/renderer/assets/participant-avatars/07.svg +3 -0
  81. package/src/renderer/assets/participant-avatars/08.svg +3 -0
  82. package/src/renderer/assets/participant-avatars/09.svg +3 -0
  83. package/src/renderer/assets/participant-avatars/10.svg +3 -0
  84. package/src/renderer/assets/participant-avatars/11.svg +3 -0
  85. package/src/renderer/assets/participant-avatars/12.svg +3 -0
  86. package/src/renderer/assets/participant-avatars/13.svg +3 -0
  87. package/src/renderer/components/common/TerminalPane.tsx +213 -0
  88. package/src/renderer/components/dashboard/DashboardView.tsx +9 -36
  89. package/src/renderer/components/extensions/ExtensionStoreView.tsx +6 -125
  90. package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +1 -1
  91. package/src/renderer/components/extensions/mcp/McpLibraryEnableDialog.tsx +305 -0
  92. package/src/renderer/components/extensions/mcp/McpLibraryEntryDialog.tsx +418 -0
  93. package/src/renderer/components/extensions/mcp/McpLibraryPanel.tsx +404 -0
  94. package/src/renderer/components/extensions/plugins/PluginCard.tsx +6 -6
  95. package/src/renderer/components/extensions/plugins/PluginsPanel.tsx +34 -21
  96. package/src/renderer/components/extensions/skills/SkillsLibraryPanel.tsx +335 -0
  97. package/src/renderer/components/layout/PaneContent.tsx +8 -1
  98. package/src/renderer/components/layout/Sidebar.tsx +11 -54
  99. package/src/renderer/components/layout/SortableTab.tsx +20 -31
  100. package/src/renderer/components/layout/TabBar.tsx +1 -1
  101. package/src/renderer/components/layout/TabContextMenu.tsx +1 -1
  102. package/src/renderer/components/runtime/ProviderRuntimeSettingsDialog.tsx +768 -157
  103. package/src/renderer/components/schedules/SchedulesView.tsx +51 -462
  104. package/src/renderer/components/schedules/calendar/CalendarDayView.tsx +173 -0
  105. package/src/renderer/components/schedules/calendar/CalendarEventBlock.tsx +113 -0
  106. package/src/renderer/components/schedules/calendar/CalendarHeader.tsx +148 -0
  107. package/src/renderer/components/schedules/calendar/CalendarMonthView.tsx +142 -0
  108. package/src/renderer/components/schedules/calendar/CalendarWeekView.tsx +219 -0
  109. package/src/renderer/components/schedules/calendar/ScheduleCalendarBoard.tsx +41 -0
  110. package/src/renderer/components/schedules/calendar/TeamGanttView.tsx +405 -0
  111. package/src/renderer/components/schedules/calendar/computeOccurrences.ts +234 -0
  112. package/src/renderer/components/schedules/calendar/index.ts +2 -0
  113. package/src/renderer/components/schedules/calendar/types.ts +44 -0
  114. package/src/renderer/components/settings/SettingsTabs.tsx +50 -55
  115. package/src/renderer/components/settings/SettingsView.tsx +30 -35
  116. package/src/renderer/components/settings/components/SettingsSectionHeader.tsx +5 -1
  117. package/src/renderer/components/settings/components/SettingsSelect.tsx +5 -3
  118. package/src/renderer/components/settings/components/SettingsToggle.tsx +2 -2
  119. package/src/renderer/components/settings/sections/AdvancedSection.tsx +11 -42
  120. package/src/renderer/components/settings/sections/CliStatusSection.tsx +71 -112
  121. package/src/renderer/components/settings/sections/ConfigEditorDialog.tsx +1 -1
  122. package/src/renderer/components/settings/sections/GeneralSection.tsx +11 -3
  123. package/src/renderer/components/settings/sections/HarnessSection.tsx +18 -14
  124. package/src/renderer/components/settings/sections/PlatformsSection.tsx +3 -3
  125. package/src/renderer/components/settings/sections/TaskBusSection.tsx +33 -40
  126. package/src/renderer/components/settings/sections/index.ts +0 -1
  127. package/src/renderer/components/sidebar/SidebarSessions.tsx +182 -4
  128. package/src/renderer/components/sidebar/SidebarTaskItem.tsx +4 -4
  129. package/src/renderer/components/sidebar/WorkspaceBrowser.tsx +39 -4
  130. package/src/renderer/components/splash/splashScene.ts +121 -929
  131. package/src/renderer/components/system-manager/FolderBrowser.tsx +163 -0
  132. package/src/renderer/components/system-manager/SystemManagerView.tsx +351 -0
  133. package/src/renderer/components/tasks/TasksView.tsx +112 -134
  134. package/src/renderer/components/team/CcSessionsSection.tsx +431 -89
  135. package/src/renderer/components/team/CollapsibleTeamSection.tsx +17 -32
  136. package/src/renderer/components/team/TeamDetailView.tsx +319 -123
  137. package/src/renderer/components/team/TeamListView.tsx +108 -123
  138. package/src/renderer/components/team/dialogs/CreateTaskDialog.tsx +2 -2
  139. package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +84 -306
  140. package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +259 -342
  141. package/src/renderer/components/team/dialogs/GlobalTaskDetailDialog.tsx +1 -1
  142. package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +17 -15
  143. package/src/renderer/components/team/dialogs/PlatformBindingDialog.tsx +221 -0
  144. package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +7 -0
  145. package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +1 -1
  146. package/src/renderer/components/team/dialogs/RuntimeConfigDialog.tsx +361 -0
  147. package/src/renderer/components/team/dialogs/platformMeta.ts +122 -11
  148. package/src/renderer/components/team/dialogs/useTeamEditForm.ts +17 -5
  149. package/src/renderer/components/team/kanban/KanbanBoard.tsx +9 -9
  150. package/src/renderer/components/team/members/MemberCard.tsx +14 -47
  151. package/src/renderer/components/team/members/MemberDetailDialog.tsx +3 -95
  152. package/src/renderer/components/team/members/MemberDetailStats.tsx +50 -65
  153. package/src/renderer/components/team/messages/MessageComposer.tsx +8 -110
  154. package/src/renderer/components/team/messages/MessagesPanel.tsx +131 -114
  155. package/src/renderer/components/team/schedule/ScheduleStatusBadge.tsx +2 -2
  156. package/src/renderer/components/team/tools/AddMcpInline.tsx +27 -17
  157. package/src/renderer/components/team/tools/McpChip.tsx +6 -3
  158. package/src/renderer/components/team/tools/SkillChip.tsx +2 -2
  159. package/src/renderer/components/team/tools/ToolsSection.tsx +418 -70
  160. package/src/renderer/hooks/useExtensionsTabState.ts +3 -114
  161. package/src/renderer/index.css +39 -22
  162. package/src/renderer/index.html +17 -50
  163. package/src/renderer/store/index.ts +2 -1
  164. package/src/renderer/store/slices/scheduleSlice.ts +1 -1
  165. package/src/renderer/store/slices/teamSlice.ts +45 -168
  166. package/src/renderer/utils/claudeCodeOnlyProviders.ts +3 -10
  167. package/src/renderer/utils/memberHelpers.ts +5 -17
  168. package/src/renderer/utils/openCodeRuntimeDeliveryDiagnostics.ts +4 -2
  169. package/src/renderer/utils/providerSlashCommands.ts +0 -5
  170. package/src/renderer/utils/scheduleFormatters.ts +3 -1
  171. package/src/renderer/utils/teamMessageFiltering.ts +14 -1
  172. package/src/renderer/utils/teamModelAvailability.ts +18 -2
  173. package/src/shared/types/api.ts +121 -2
  174. package/src/shared/types/ccConnect.ts +2 -0
  175. package/src/shared/types/index.ts +3 -0
  176. package/src/shared/types/systemManager.ts +49 -0
  177. package/src/shared/types/team.ts +29 -0
  178. package/src/shared/types/terminal.ts +4 -2
  179. package/src/shared/utils/extensionNormalizers.ts +15 -8
  180. package/src/shared/utils/providerExtensionCapabilities.ts +2 -2
  181. package/dist-renderer/assets/ProjectEditorOverlay-lJZi-9Hp.js +0 -52
  182. package/dist-renderer/assets/channel-yIlSKy0e.js +0 -1
  183. package/dist-renderer/assets/classDiagram-2ON5EDUG-24fHez0s.js +0 -1
  184. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-24fHez0s.js +0 -1
  185. package/dist-renderer/assets/clone-BTNuUva-.js +0 -1
  186. package/dist-renderer/assets/index-Bi6nrZ4z.css +0 -1
  187. package/dist-renderer/assets/splashScene-C8lWNnm4.js +0 -1
  188. package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-_m6iPPUR.js +0 -1
@@ -1,20 +1,15 @@
1
1
  /**
2
- * CreateTeamDialog — simplified to match cc-connect project creation flow.
2
+ * CreateTeamDialog — create a new digital worker (数字员工).
3
3
  *
4
4
  * Wizard steps:
5
5
  * 1. Name + Agent type + Work directory
6
- * 2. Platform selection grid
7
- * 3a. QR code setup (feishu/weixin)
8
- * 3b. Manual credential form (telegram/slack/etc.)
9
- * 3c. Bridge (no setup needed)
10
- *
11
- * Uses Hermit's existing UI components (Dialog, Button, Input, etc.)
12
- * but with cc-connect's parameters and flow.
6
+ * 2. Done (success confirmation)
13
7
  */
14
8
 
15
9
  import React, { useEffect, useMemo, useState } from 'react';
16
10
 
17
11
  import { api } from '@renderer/api';
12
+ import { providersApi } from '@renderer/api/providers';
18
13
  import { Button } from '@renderer/components/ui/button';
19
14
  import {
20
15
  Dialog,
@@ -26,33 +21,16 @@ import {
26
21
  } from '@renderer/components/ui/dialog';
27
22
  import { Input } from '@renderer/components/ui/input';
28
23
  import { Label } from '@renderer/components/ui/label';
29
- import { getTeamColorSet, getThemedBadge } from '@renderer/constants/teamColors';
30
24
  import { useCreateTeamDraft } from '@renderer/hooks/useCreateTeamDraft';
31
25
  import { useTheme } from '@renderer/hooks/useTheme';
32
26
  import { cn } from '@renderer/lib/utils';
33
- import { useStore } from '@renderer/store';
34
- import { isEphemeralProjectPath } from '@shared/utils/ephemeralProjectPath';
35
27
  import { normalizePath } from '@renderer/utils/pathNormalize';
36
- import {
37
- AlertTriangle,
38
- CheckCircle2,
39
- FolderKanban,
40
- Info,
41
- Loader2,
42
- Settings2,
43
- Smartphone,
44
- X,
45
- } from 'lucide-react';
28
+ import { isEphemeralProjectPath } from '@shared/utils/ephemeralProjectPath';
29
+ import { AlertTriangle, CheckCircle2, X } from 'lucide-react';
46
30
 
47
31
  import { AGENT_TYPE_LABELS } from '../HarnessCards';
48
32
  import { HarnessSelect } from '../HarnessSelect';
49
33
  import { ProjectPathSelector } from './ProjectPathSelector';
50
- import { OptionalSettingsSection } from './OptionalSettingsSection';
51
- import { AutoResizeTextarea } from '@renderer/components/ui/auto-resize-textarea';
52
- import { platformMeta, isQRPlatform } from './platformMeta';
53
- import PlatformSetupQR from './PlatformSetupQR';
54
- import PlatformManualForm from './PlatformManualForm';
55
-
56
34
  import type {
57
35
  EffortLevel,
58
36
  Project,
@@ -63,8 +41,6 @@ import type {
63
41
  import type { CcAgentType } from '@shared/types/ccConnect';
64
42
  import type { GlobalProvider } from '@shared/types/providers';
65
43
 
66
- import { providersApi } from '@renderer/api/providers';
67
-
68
44
  export interface ActiveTeamRef {
69
45
  teamName: string;
70
46
  displayName: string;
@@ -86,108 +62,25 @@ export interface TeamCopyData {
86
62
  templateDirectoryId?: string;
87
63
  }
88
64
 
89
- // ---------------------------------------------------------------------------
90
- // Platform selection grid data
91
- // ---------------------------------------------------------------------------
92
-
93
- interface PlatformOption {
94
- key: string;
95
- label: string;
96
- color: string;
97
- icon: 'qr' | 'settings';
65
+ /**
66
+ * Sanitize team name: keep Unicode letters and digits (Chinese, Latin, etc.),
67
+ * replace other sequences with `-`, then lowercase Latin chars.
68
+ */
69
+ function sanitizeTeamName(name: string): string {
70
+ const trimmed = name.trim();
71
+ if (!trimmed) return '';
72
+ let result = trimmed
73
+ .replace(/[^\p{L}\p{N}]+/gu, '-')
74
+ .replace(/^-+|-+$/g, '')
75
+ .toLowerCase();
76
+ return result;
98
77
  }
99
78
 
100
- const PLATFORM_OPTIONS: PlatformOption[] = [
101
- {
102
- key: 'feishu',
103
- label: '飞书 / Lark',
104
- color: 'bg-blue-50 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400',
105
- icon: 'qr',
106
- },
107
- {
108
- key: 'weixin',
109
- label: '微信',
110
- color: 'bg-green-50 dark:bg-green-900/30 text-green-600 dark:text-green-400',
111
- icon: 'qr',
112
- },
113
- {
114
- key: 'telegram',
115
- label: 'Telegram',
116
- color: 'bg-sky-50 dark:bg-sky-900/30 text-sky-600 dark:text-sky-400',
117
- icon: 'settings',
118
- },
119
- {
120
- key: 'discord',
121
- label: 'Discord',
122
- color: 'bg-indigo-50 dark:bg-indigo-900/30 text-indigo-600 dark:text-indigo-400',
123
- icon: 'settings',
124
- },
125
- {
126
- key: 'slack',
127
- label: 'Slack',
128
- color: 'bg-purple-50 dark:bg-purple-900/30 text-purple-600 dark:text-purple-400',
129
- icon: 'settings',
130
- },
131
- {
132
- key: 'dingtalk',
133
- label: '钉钉',
134
- color: 'bg-orange-50 dark:bg-orange-900/30 text-orange-600 dark:text-orange-400',
135
- icon: 'settings',
136
- },
137
- {
138
- key: 'wecom',
139
- label: '企业微信',
140
- color: 'bg-emerald-50 dark:bg-emerald-900/30 text-emerald-600 dark:text-emerald-400',
141
- icon: 'settings',
142
- },
143
- {
144
- key: 'qq',
145
- label: 'QQ (OneBot)',
146
- color: 'bg-cyan-50 dark:bg-cyan-900/30 text-cyan-600 dark:text-cyan-400',
147
- icon: 'settings',
148
- },
149
- {
150
- key: 'qqbot',
151
- label: 'QQ Bot (官方)',
152
- color: 'bg-cyan-50 dark:bg-cyan-900/30 text-cyan-600 dark:text-cyan-400',
153
- icon: 'settings',
154
- },
155
- {
156
- key: 'line',
157
- label: 'LINE',
158
- color: 'bg-lime-50 dark:bg-lime-900/30 text-lime-600 dark:text-lime-400',
159
- icon: 'settings',
160
- },
161
- {
162
- key: 'weibo',
163
- label: '微博',
164
- color: 'bg-red-50 dark:bg-red-900/30 text-red-600 dark:text-red-400',
165
- icon: 'settings',
166
- },
167
- {
168
- key: 'bridge',
169
- label: 'Bridge (默认)',
170
- color: 'bg-gray-50 dark:bg-gray-800/30 text-gray-600 dark:text-gray-400',
171
- icon: 'settings',
172
- },
173
- ];
174
-
175
- const TEAM_COLOR_NAMES = [
176
- 'blue',
177
- 'green',
178
- 'red',
179
- 'yellow',
180
- 'purple',
181
- 'cyan',
182
- 'orange',
183
- 'pink',
184
- ] as const;
185
-
186
79
  // ---------------------------------------------------------------------------
187
80
  // Wizard step types
188
81
  // ---------------------------------------------------------------------------
189
82
 
190
- type WizardStep = 'name' | 'platform' | 'qr' | 'form' | 'done';
83
+ type WizardStep = 'name' | 'done';
191
84
 
192
85
  // ---------------------------------------------------------------------------
193
86
  // Component
@@ -205,27 +98,7 @@ interface CreateTeamDialogProps {
205
98
  defaultProjectPath?: string | null;
206
99
  onClose: () => void;
207
100
  onCreate: (request: TeamCreateRequest) => Promise<void>;
208
- onOpenTeam: (teamName: string, projectPath?: string) => void;
209
- }
210
-
211
- /** Sanitize team name: non-alphanumeric → `-`, then lowercase. */
212
- function sanitizeTeamName(name: string): string {
213
- const trimmed = name.trim();
214
- let result = name
215
- .replace(/[^a-zA-Z0-9]/g, '-')
216
- .replace(/-{2,}/g, '-')
217
- .toLowerCase();
218
- while (result.startsWith('-')) result = result.slice(1);
219
- while (result.endsWith('-')) result = result.slice(0, -1);
220
- if (!result && trimmed) {
221
- let hash = 2166136261;
222
- for (const ch of name) {
223
- hash ^= ch.codePointAt(0) ?? 0;
224
- hash = Math.imul(hash, 16777619);
225
- }
226
- result = `team-${(hash >>> 0).toString(36)}`;
227
- }
228
- return result;
101
+ onOpenTeam: (teamName: string, projectPath?: string, options?: { displayName?: string }) => void;
229
102
  }
230
103
 
231
104
  export const CreateTeamDialog = ({
@@ -262,7 +135,6 @@ export const CreateTeamDialog = ({
262
135
  // ── Wizard state ─────────────────────────────────────────────────────
263
136
  const [step, setStep] = useState<WizardStep>('name');
264
137
  const [selectedHarness, setSelectedHarness] = useState<CcAgentType>('claudecode');
265
- const [selectedPlatform, setSelectedPlatform] = useState('');
266
138
  const [description, setDescription] = useState('');
267
139
 
268
140
  // ── Projects (for path selector) ─────────────────────────────────────
@@ -279,14 +151,20 @@ export const CreateTeamDialog = ({
279
151
  const [isSubmitting, setIsSubmitting] = useState(false);
280
152
  const [fieldErrors, setFieldErrors] = useState<{ teamName?: string; cwd?: string }>({});
281
153
 
282
- // ── Conflict detection ───────────────────────────────────────────────
154
+ // ── Name conflict detection ──────────────────────────────────────────
283
155
  const allTakenTeamNames = useMemo(
284
156
  () => [...new Set([...existingTeamNames, ...provisioningTeamNames])],
285
157
  [existingTeamNames, provisioningTeamNames]
286
158
  );
287
- const sanitizedTeamName = sanitizeTeamName(teamName.trim());
288
- const isNameTaken = existingTeamNames.includes(sanitizedTeamName);
289
- const isNameProvisioning = provisioningTeamNames.includes(sanitizedTeamName) && !isNameTaken;
159
+ const sanitizedTeamName = sanitizeTeamName(teamName);
160
+ const trimmedInputName = teamName.trim().toLowerCase();
161
+ // Check both slug (for ASCII names) and display name (for Chinese/Unicode names)
162
+ // This prevents creating "产品经理团队" multiple times with different slugs (team-3, team-4...)
163
+ const isNameTaken =
164
+ existingTeamNames.includes(sanitizedTeamName) ||
165
+ activeTeams?.some((t) => t.displayName.toLowerCase() === trimmedInputName) === true;
166
+ const isNameProvisioning =
167
+ (provisioningTeamNames.includes(sanitizedTeamName) && !isNameTaken);
290
168
 
291
169
  const effectiveCwd =
292
170
  cwdMode === 'project'
@@ -399,85 +277,64 @@ export const CreateTeamDialog = ({
399
277
  setIsSubmitting(false);
400
278
  setConflictDismissed(false);
401
279
  setSelectedProviderRef(null);
280
+ setStep('name');
402
281
  };
403
282
 
404
- // ── Platform selection ───────────────────────────────────────────────
405
- const handlePlatformSelect = (key: string) => {
406
- setSelectedPlatform(key);
407
- if (isQRPlatform(key)) {
408
- setStep('qr');
409
- } else if (platformMeta[key]) {
410
- setStep('form');
411
- } else {
412
- // bridge or unknown — skip to done
413
- setStep('done');
414
- }
415
- };
416
-
417
- // ── Completion handlers ──────────────────────────────────────────────
418
- const handleQRComplete = () => {
419
- // QR setup already created the project via cc-connect
420
- clearDraft();
421
- resetState();
422
- setStep('done');
423
- };
424
-
425
- const handleManualComplete = () => {
426
- // Manual form already created the project via cc-connect
427
- clearDraft();
428
- resetState();
429
- setStep('done');
430
- };
431
-
432
- const handleBridgeDone = () => {
433
- setStep('done');
434
- };
435
-
436
- // ── Final submission (for bridge or non-QR platforms that need server call) ──
437
- const handleCreate = async () => {
283
+ const buildCreateRequest = (): TeamCreateRequest => ({
284
+ teamName: sanitizedTeamName,
285
+ displayName: teamName.trim() || undefined,
286
+ description: description.trim() || undefined,
287
+ color: teamColor || undefined,
288
+ members: [],
289
+ cwd: effectiveCwd,
290
+ executionTarget: { type: 'local', cwd: effectiveCwd || undefined },
291
+ harness: selectedHarness,
292
+ platform: 'bridge',
293
+ platformOptions: {},
294
+ providerRefs: selectedProviderRef ? [selectedProviderRef] : undefined,
295
+ });
296
+
297
+ const validateCreateFields = (): boolean => {
438
298
  if (allTakenTeamNames.includes(sanitizedTeamName)) {
439
- setLocalError(isNameProvisioning ? '团队正在启动中' : '团队名称已存在');
440
- return;
299
+ setLocalError(isNameProvisioning ? '数字员工正在启动中' : '数字员工名称已存在');
300
+ return false;
441
301
  }
442
302
  if (!sanitizedTeamName) {
443
- setLocalError('请输入团队名称');
444
- return;
303
+ setLocalError('请输入数字员工名称');
304
+ return false;
445
305
  }
446
306
  if (!effectiveCwd) {
447
307
  setLocalError('请选择工作目录');
448
- return;
308
+ return false;
449
309
  }
310
+ return true;
311
+ };
312
+
313
+ const createLocalTeam = async (): Promise<TeamCreateRequest | null> => {
314
+ if (!validateCreateFields()) return null;
450
315
 
451
316
  setFieldErrors({});
452
317
  setLocalError(null);
453
318
  setIsSubmitting(true);
454
319
 
455
320
  try {
456
- const request: TeamCreateRequest = {
457
- teamName: sanitizedTeamName,
458
- displayName: teamName.trim() || undefined,
459
- description: description.trim() || undefined,
460
- color: teamColor || undefined,
461
- members: [],
462
- cwd: effectiveCwd,
463
- executionTarget: { type: 'local', cwd: effectiveCwd || undefined },
464
- harness: selectedHarness,
465
- platform: selectedPlatform || 'bridge',
466
- platformOptions: {},
467
- providerRefs: selectedProviderRef ? [selectedProviderRef] : undefined,
468
- };
321
+ const request = buildCreateRequest();
469
322
  await onCreate(request);
470
- onOpenTeam(request.teamName, effectiveCwd || undefined);
471
- clearDraft();
472
- resetState();
473
- onClose();
323
+ return request;
474
324
  } catch {
475
325
  // error shown via provisioningErrorsByTeam
326
+ return null;
476
327
  } finally {
477
328
  setIsSubmitting(false);
478
329
  }
479
330
  };
480
331
 
332
+ const handleCreate = async () => {
333
+ const request = await createLocalTeam();
334
+ if (!request) return;
335
+ setStep('done');
336
+ };
337
+
481
338
  // ── Render ───────────────────────────────────────────────────────────
482
339
  return (
483
340
  <Dialog
@@ -491,13 +348,10 @@ export const CreateTeamDialog = ({
491
348
  >
492
349
  <DialogContent className="w-[calc(100vw-2rem)] max-w-2xl sm:w-[40rem]">
493
350
  <DialogHeader>
494
- <DialogTitle className="text-sm">创建团队</DialogTitle>
351
+ <DialogTitle className="text-sm">创建数字员工</DialogTitle>
495
352
  <DialogDescription className="text-xs">
496
- {step === 'name' && '设置团队名称、Agent 类型和工作目录'}
497
- {step === 'platform' && '选择要绑定的平台渠道'}
498
- {step === 'qr' && '扫描二维码绑定平台'}
499
- {step === 'form' && '填写平台凭证信息'}
500
- {step === 'done' && '团队创建完成'}
353
+ {step === 'name' && '设置数字员工名称、Agent 类型和工作目录'}
354
+ {step === 'done' && '数字员工创建完成'}
501
355
  </DialogDescription>
502
356
  </DialogHeader>
503
357
 
@@ -514,9 +368,9 @@ export const CreateTeamDialog = ({
514
368
  <AlertTriangle className="mt-0.5 size-4 shrink-0" />
515
369
  <div className="min-w-0 flex-1 space-y-1">
516
370
  <p className="font-medium">
517
- 该工作目录下已有团队"{conflictingTeam.displayName}"正在运行
371
+ 该工作目录下已有数字员工"{conflictingTeam.displayName}"正在运行
518
372
  </p>
519
- <p className="opacity-80">在同一目录同时运行两个团队存在风险。</p>
373
+ <p className="opacity-80">在同一目录同时运行两个数字员工存在风险。</p>
520
374
  </div>
521
375
  <button
522
376
  type="button"
@@ -533,7 +387,7 @@ export const CreateTeamDialog = ({
533
387
  {step === 'name' && (
534
388
  <div className="space-y-4 py-2">
535
389
  <div className="space-y-1.5">
536
- <Label htmlFor="team-name">团队名称</Label>
390
+ <Label htmlFor="team-name">数字员工名称</Label>
537
391
  <Input
538
392
  id="team-name"
539
393
  className={cn(
@@ -542,22 +396,17 @@ export const CreateTeamDialog = ({
542
396
  )}
543
397
  value={teamName}
544
398
  onChange={(e) => setTeamName(e.target.value)}
545
- placeholder="my-team"
399
+ placeholder="例如:产品助手 / 前端工程师"
546
400
  autoFocus
547
401
  />
548
402
  {isNameTaken && (
549
403
  <p className="text-[11px]" style={{ color: 'var(--field-error-text)' }}>
550
- 团队名称已存在
404
+ 数字员工名称已存在
551
405
  </p>
552
406
  )}
553
407
  {isNameProvisioning && (
554
408
  <p className="text-[11px]" style={{ color: 'var(--warning-text)' }}>
555
- 同名团队正在启动中
556
- </p>
557
- )}
558
- {sanitizedTeamName && sanitizedTeamName !== teamName.trim() && (
559
- <p className="text-[11px] text-[var(--color-text-muted)]">
560
- 内部标识:<span className="font-mono">{sanitizedTeamName}</span>
409
+ 同名数字员工正在启动中
561
410
  </p>
562
411
  )}
563
412
  </div>
@@ -662,81 +511,16 @@ export const CreateTeamDialog = ({
662
511
  </div>
663
512
  )}
664
513
 
665
- {/* ── Step 2: Platform selection ── */}
666
- {step === 'platform' && (
667
- <div className="space-y-3 py-2">
668
- <p className="mb-2 text-sm text-gray-500 dark:text-gray-400">选择要绑定的平台渠道:</p>
669
- <div className="grid max-h-80 grid-cols-2 gap-2 overflow-y-auto">
670
- {PLATFORM_OPTIONS.map(({ key, label, color, icon }) => (
671
- <button
672
- key={key}
673
- onClick={() => handlePlatformSelect(key)}
674
- className="flex items-center gap-2.5 rounded-xl border border-gray-200 p-3 text-left transition-all hover:border-blue-500/50 hover:bg-blue-500/5 dark:border-gray-700"
675
- >
676
- <div
677
- className={`h-9 w-9 rounded-lg ${color} flex shrink-0 items-center justify-center`}
678
- >
679
- {icon === 'qr' ? <Smartphone size={16} /> : <Settings2 size={16} />}
680
- </div>
681
- <div className="min-w-0">
682
- <div className="truncate text-sm font-medium text-gray-900 dark:text-white">
683
- {label}
684
- </div>
685
- <div className="text-[11px] text-gray-400">
686
- {icon === 'qr' ? '扫码绑定' : '手动配置'}
687
- </div>
688
- </div>
689
- </button>
690
- ))}
691
- </div>
692
- <div className="flex justify-start pt-2">
693
- <Button variant="outline" size="sm" onClick={() => setStep('name')}>
694
- 返回
695
- </Button>
696
- </div>
697
- </div>
698
- )}
699
-
700
- {/* ── Step 3a: QR setup (feishu/weixin) ── */}
701
- {step === 'qr' &&
702
- (selectedPlatform === 'feishu' ||
703
- selectedPlatform === 'lark' ||
704
- selectedPlatform === 'weixin') && (
705
- <PlatformSetupQR
706
- platformType={selectedPlatform as 'feishu' | 'lark' | 'weixin'}
707
- projectName={sanitizedTeamName}
708
- workDir={effectiveCwd}
709
- agentType={selectedHarness}
710
- onComplete={handleQRComplete}
711
- onCancel={() => setStep('platform')}
712
- />
713
- )}
714
-
715
- {/* ── Step 3b: Manual form (telegram/slack/etc.) ── */}
716
- {step === 'form' && platformMeta[selectedPlatform] && (
717
- <PlatformManualForm
718
- platformType={selectedPlatform}
719
- platformMeta={platformMeta[selectedPlatform]}
720
- projectName={sanitizedTeamName}
721
- workDir={effectiveCwd}
722
- agentType={selectedHarness}
723
- onComplete={handleManualComplete}
724
- onCancel={() => setStep('platform')}
725
- />
726
- )}
727
-
728
- {/* ── Step 3c: Bridge (no setup) ── */}
514
+ {/* ── Step 2: Done ── */}
729
515
  {step === 'done' && (
730
516
  <div className="space-y-4 py-4">
731
517
  <div className="flex flex-col items-center gap-3 py-4">
732
518
  <CheckCircle2 size={48} className="text-green-500" />
733
519
  <p className="text-sm font-medium text-green-700 dark:text-green-400">
734
- 团队已创建成功!
520
+ 数字员工已创建成功!
735
521
  </p>
736
522
  <p className="text-center text-xs text-gray-500">
737
- {selectedPlatform && selectedPlatform !== 'bridge'
738
- ? '平台绑定完成,重启服务使配置生效'
739
- : 'Bridge 模式已启用,无需额外配置'}
523
+ 已在本机创建。外部渠道绑定可稍后在详情页完成。
740
524
  </p>
741
525
  </div>
742
526
  </div>
@@ -788,33 +572,27 @@ export const CreateTeamDialog = ({
788
572
  <Button
789
573
  size="sm"
790
574
  onClick={() => {
791
- onOpenTeam(sanitizedTeamName, effectiveCwd);
575
+ onOpenTeam(sanitizedTeamName, effectiveCwd || undefined, {
576
+ displayName: teamName.trim() || undefined,
577
+ });
792
578
  clearDraft();
793
579
  resetState();
794
580
  onClose();
795
581
  }}
796
582
  >
797
- 打开团队
583
+ 打开数字员工
798
584
  </Button>
799
585
  </>
800
- ) : step === 'name' ? (
586
+ ) : (
801
587
  <>
802
588
  <Button variant="outline" size="sm" onClick={onClose}>
803
589
  取消
804
590
  </Button>
805
- <Button
806
- size="sm"
807
- disabled={!sanitizedTeamName || !effectiveCwd}
808
- onClick={() => setStep('platform')}
809
- >
810
- 下一步
591
+ <Button size="sm" disabled={!sanitizedTeamName || !effectiveCwd || isSubmitting} onClick={handleCreate}>
592
+ {isSubmitting ? '创建中...' : '创建数字员工'}
811
593
  </Button>
812
594
  </>
813
- ) : step === 'platform' ? (
814
- <Button variant="outline" size="sm" onClick={() => setStep('name')}>
815
- 返回
816
- </Button>
817
- ) : null}
595
+ )}
818
596
  </div>
819
597
  </DialogFooter>
820
598
  </DialogContent>