@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.
- package/dist-renderer/assets/ProjectEditorOverlay-krO5vQxX.js +58 -0
- package/dist-renderer/assets/{TeamGraphOverlay-ZEDfZyHb.js → TeamGraphOverlay-DqhQzcTr.js} +1 -1
- package/dist-renderer/assets/{_basePickBy-CIhniz70.js → _basePickBy-B7kSYPxr.js} +1 -1
- package/dist-renderer/assets/{_baseUniq-cKAW4Q8I.js → _baseUniq-CnjxqwAk.js} +1 -1
- package/dist-renderer/assets/{arc-YmNsoDXW.js → arc-CLeZuINP.js} +1 -1
- package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-DHEls2sX.js → architectureDiagram-VXUJARFQ-QKtqaqdY.js} +1 -1
- package/dist-renderer/assets/{blockDiagram-VD42YOAC-Bpwf1Sbg.js → blockDiagram-VD42YOAC-BqdrzO_f.js} +1 -1
- package/dist-renderer/assets/{c4Diagram-YG6GDRKO-B0IaQ4w5.js → c4Diagram-YG6GDRKO-gwPlCxDC.js} +1 -1
- package/dist-renderer/assets/channel-DpMHF50r.js +1 -0
- package/dist-renderer/assets/{chunk-4BX2VUAB-DLk-hcFc.js → chunk-4BX2VUAB-C6XLurL4.js} +1 -1
- package/dist-renderer/assets/{chunk-55IACEB6-1XRmX_Zm.js → chunk-55IACEB6-Ds6quhEP.js} +1 -1
- package/dist-renderer/assets/{chunk-B4BG7PRW-1waH1DAD.js → chunk-B4BG7PRW-5UlA1_e9.js} +1 -1
- package/dist-renderer/assets/{chunk-DI55MBZ5-BqpZBtrN.js → chunk-DI55MBZ5-ywFrqIsY.js} +1 -1
- package/dist-renderer/assets/{chunk-FMBD7UC4-Bly7vVym.js → chunk-FMBD7UC4-C7ifUA17.js} +1 -1
- package/dist-renderer/assets/{chunk-QN33PNHL-Ci2QWBAs.js → chunk-QN33PNHL-BxGCo80U.js} +1 -1
- package/dist-renderer/assets/{chunk-QZHKN3VN-YCqFW7d-.js → chunk-QZHKN3VN-B2CuaZs6.js} +1 -1
- package/dist-renderer/assets/{chunk-TZMSLE5B-B0xGXInl.js → chunk-TZMSLE5B-Ds1hInvp.js} +1 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-CBYCBVRl.js +1 -0
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-CBYCBVRl.js +1 -0
- package/dist-renderer/assets/clone-DcMF6Psb.js +1 -0
- package/dist-renderer/assets/{cose-bilkent-S5V4N54A-DxcFNQKT.js → cose-bilkent-S5V4N54A-Cz1GVtLp.js} +1 -1
- package/dist-renderer/assets/{dagre-6UL2VRFP-DPo_RfZY.js → dagre-6UL2VRFP-BrmR-P4h.js} +1 -1
- package/dist-renderer/assets/{diagram-PSM6KHXK-U3hQsFe4.js → diagram-PSM6KHXK-DbNjC5Rg.js} +1 -1
- package/dist-renderer/assets/{diagram-QEK2KX5R-OrwrAy0V.js → diagram-QEK2KX5R-qkRX5_Mq.js} +1 -1
- package/dist-renderer/assets/{diagram-S2PKOQOG-CXATPWVw.js → diagram-S2PKOQOG-CyL5rCv2.js} +1 -1
- package/dist-renderer/assets/{erDiagram-Q2GNP2WA-B0e8AfMF.js → erDiagram-Q2GNP2WA-Dox3-bA5.js} +1 -1
- package/dist-renderer/assets/{flowDiagram-NV44I4VS-CXfzA4jJ.js → flowDiagram-NV44I4VS-BtkaxlDL.js} +1 -1
- package/dist-renderer/assets/{ganttDiagram-JELNMOA3-CMr08qVl.js → ganttDiagram-JELNMOA3-Dhy_d9GK.js} +1 -1
- package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-vYFHpPmy.js → gitGraphDiagram-V2S2FVAM-B5XRhIQA.js} +1 -1
- package/dist-renderer/assets/{graph-DOe5j8dH.js → graph-CsoEwUhS.js} +1 -1
- package/dist-renderer/assets/{index-BySQS7AB.js → index-BWPWmJNo.js} +1 -1
- package/dist-renderer/assets/{index-V7dAKPqd.js → index-Bu2R-Se7.js} +587 -705
- package/dist-renderer/assets/index-CnWV3BhG.css +32 -0
- package/dist-renderer/assets/{index-CzWxVCRL.js → index-D-3KgskL.js} +1 -1
- package/dist-renderer/assets/{index-VJ-MM9xa.js → index-DGEBzLNT.js} +1 -1
- package/dist-renderer/assets/{index-B2Dy7M2G.js → index-NhHNs2Oo.js} +1 -1
- package/dist-renderer/assets/{index-C_okzZXP.js → index-h17WuEyf.js} +1 -1
- package/dist-renderer/assets/{infoDiagram-HS3SLOUP-D_WubR0B.js → infoDiagram-HS3SLOUP-hMGmNojH.js} +1 -1
- package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-w9ca-1TI.js → journeyDiagram-XKPGCS4Q-DXV2rBDl.js} +1 -1
- package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-Jg9p6_pN.js → kanban-definition-3W4ZIXB7-Bf99WLRy.js} +1 -1
- package/dist-renderer/assets/{layout-B-z3y17c.js → layout-C3XWrpwo.js} +1 -1
- package/dist-renderer/assets/{linear-D-RTX5UW.js → linear-OEEcn8KN.js} +1 -1
- package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-CDQmHOYP.js → mindmap-definition-VGOIOE7T-Dpi3S2x4.js} +1 -1
- package/dist-renderer/assets/{pieDiagram-ADFJNKIX-D_odsQL7.js → pieDiagram-ADFJNKIX-xTPPhtNx.js} +1 -1
- package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-BRsmYWSA.js → quadrantDiagram-AYHSOK5B-euniyDlz.js} +1 -1
- package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-ChNE_BOV.js → requirementDiagram-UZGBJVZJ-D9Uiw4kF.js} +1 -1
- package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-C8FtpwKc.js → sankeyDiagram-TZEHDZUN-CySU4nED.js} +1 -1
- package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-DmLCzNcc.js → sequenceDiagram-WL72ISMW-JVGpET6V.js} +1 -1
- package/dist-renderer/assets/splashScene-D0YB9uxm.js +17 -0
- package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-WJBm4bhu.js → stateDiagram-FKZM4ZOC-B2FY5qqi.js} +1 -1
- package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-DcoMiR8H.js +1 -0
- package/dist-renderer/assets/{timeline-definition-IT6M3QCI-BXs_hOJs.js → timeline-definition-IT6M3QCI-DmycNUUe.js} +1 -1
- package/dist-renderer/assets/{treemap-GDKQZRPO-o04MA0G9.js → treemap-GDKQZRPO-DPq4gZuB.js} +1 -1
- package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-Czj69XRd.js → xychartDiagram-PRI3JC2R-J6VVJzRq.js} +1 -1
- package/dist-renderer/index.html +20 -53
- package/package.json +25 -18
- package/src/main/ipc/extensions.ts +2 -1
- package/src/main/server.ts +873 -221
- package/src/main/services/extensions/ExtensionFacadeService.ts +2 -5
- package/src/main/services/extensions/catalog/PluginCatalogService.ts +4 -2
- package/src/main/services/session-intelligence/ConversationTelemetryService.ts +1101 -0
- package/src/main/services/session-intelligence/LocalSessionScanner.ts +512 -0
- package/src/main/services/session-intelligence/SessionUsageParser.ts +4 -4
- package/src/main/services/system-manager/SystemManagerConfigService.ts +122 -0
- package/src/main/services/system-manager/SystemManagerPtyService.ts +233 -0
- package/src/main/services/system-manager/WorkflowPromptService.ts +75 -0
- package/src/main/services/teams-mvp/TaskDispatchService.ts +5 -6
- package/src/main/services/teams-mvp/TeamProvisioningService.ts +39 -2
- package/src/main/services/teams-mvp/TeamWorkspaceService.ts +22 -4
- package/src/main/utils/teamProjectResolution.ts +15 -0
- package/src/renderer/App.tsx +8 -4
- package/src/renderer/api/httpClient.ts +68 -18
- package/src/renderer/api/providers.ts +23 -2
- package/src/renderer/assets/participant-avatars/01.svg +3 -0
- package/src/renderer/assets/participant-avatars/02.svg +3 -0
- package/src/renderer/assets/participant-avatars/03.svg +3 -0
- package/src/renderer/assets/participant-avatars/04.svg +3 -0
- package/src/renderer/assets/participant-avatars/05.svg +3 -0
- package/src/renderer/assets/participant-avatars/06.svg +3 -0
- package/src/renderer/assets/participant-avatars/07.svg +3 -0
- package/src/renderer/assets/participant-avatars/08.svg +3 -0
- package/src/renderer/assets/participant-avatars/09.svg +3 -0
- package/src/renderer/assets/participant-avatars/10.svg +3 -0
- package/src/renderer/assets/participant-avatars/11.svg +3 -0
- package/src/renderer/assets/participant-avatars/12.svg +3 -0
- package/src/renderer/assets/participant-avatars/13.svg +3 -0
- package/src/renderer/components/common/TerminalPane.tsx +213 -0
- package/src/renderer/components/dashboard/DashboardView.tsx +9 -36
- package/src/renderer/components/extensions/ExtensionStoreView.tsx +6 -125
- package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +1 -1
- package/src/renderer/components/extensions/mcp/McpLibraryEnableDialog.tsx +305 -0
- package/src/renderer/components/extensions/mcp/McpLibraryEntryDialog.tsx +418 -0
- package/src/renderer/components/extensions/mcp/McpLibraryPanel.tsx +404 -0
- package/src/renderer/components/extensions/plugins/PluginCard.tsx +6 -6
- package/src/renderer/components/extensions/plugins/PluginsPanel.tsx +34 -21
- package/src/renderer/components/extensions/skills/SkillsLibraryPanel.tsx +335 -0
- package/src/renderer/components/layout/PaneContent.tsx +8 -1
- package/src/renderer/components/layout/Sidebar.tsx +11 -54
- package/src/renderer/components/layout/SortableTab.tsx +20 -31
- package/src/renderer/components/layout/TabBar.tsx +1 -1
- package/src/renderer/components/layout/TabContextMenu.tsx +1 -1
- package/src/renderer/components/runtime/ProviderRuntimeSettingsDialog.tsx +768 -157
- package/src/renderer/components/schedules/SchedulesView.tsx +51 -462
- package/src/renderer/components/schedules/calendar/CalendarDayView.tsx +173 -0
- package/src/renderer/components/schedules/calendar/CalendarEventBlock.tsx +113 -0
- package/src/renderer/components/schedules/calendar/CalendarHeader.tsx +148 -0
- package/src/renderer/components/schedules/calendar/CalendarMonthView.tsx +142 -0
- package/src/renderer/components/schedules/calendar/CalendarWeekView.tsx +219 -0
- package/src/renderer/components/schedules/calendar/ScheduleCalendarBoard.tsx +41 -0
- package/src/renderer/components/schedules/calendar/TeamGanttView.tsx +405 -0
- package/src/renderer/components/schedules/calendar/computeOccurrences.ts +234 -0
- package/src/renderer/components/schedules/calendar/index.ts +2 -0
- package/src/renderer/components/schedules/calendar/types.ts +44 -0
- package/src/renderer/components/settings/SettingsTabs.tsx +50 -55
- package/src/renderer/components/settings/SettingsView.tsx +30 -35
- package/src/renderer/components/settings/components/SettingsSectionHeader.tsx +5 -1
- package/src/renderer/components/settings/components/SettingsSelect.tsx +5 -3
- package/src/renderer/components/settings/components/SettingsToggle.tsx +2 -2
- package/src/renderer/components/settings/sections/AdvancedSection.tsx +11 -42
- package/src/renderer/components/settings/sections/CliStatusSection.tsx +71 -112
- package/src/renderer/components/settings/sections/ConfigEditorDialog.tsx +1 -1
- package/src/renderer/components/settings/sections/GeneralSection.tsx +11 -3
- package/src/renderer/components/settings/sections/HarnessSection.tsx +18 -14
- package/src/renderer/components/settings/sections/PlatformsSection.tsx +3 -3
- package/src/renderer/components/settings/sections/TaskBusSection.tsx +33 -40
- package/src/renderer/components/settings/sections/index.ts +0 -1
- package/src/renderer/components/sidebar/SidebarSessions.tsx +182 -4
- package/src/renderer/components/sidebar/SidebarTaskItem.tsx +4 -4
- package/src/renderer/components/sidebar/WorkspaceBrowser.tsx +39 -4
- package/src/renderer/components/splash/splashScene.ts +121 -929
- package/src/renderer/components/system-manager/FolderBrowser.tsx +163 -0
- package/src/renderer/components/system-manager/SystemManagerView.tsx +351 -0
- package/src/renderer/components/tasks/TasksView.tsx +112 -134
- package/src/renderer/components/team/CcSessionsSection.tsx +431 -89
- package/src/renderer/components/team/CollapsibleTeamSection.tsx +17 -32
- package/src/renderer/components/team/TeamDetailView.tsx +319 -123
- package/src/renderer/components/team/TeamListView.tsx +108 -123
- package/src/renderer/components/team/dialogs/CreateTaskDialog.tsx +2 -2
- package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +84 -306
- package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +259 -342
- package/src/renderer/components/team/dialogs/GlobalTaskDetailDialog.tsx +1 -1
- package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +17 -15
- package/src/renderer/components/team/dialogs/PlatformBindingDialog.tsx +221 -0
- package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +7 -0
- package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +1 -1
- package/src/renderer/components/team/dialogs/RuntimeConfigDialog.tsx +361 -0
- package/src/renderer/components/team/dialogs/platformMeta.ts +122 -11
- package/src/renderer/components/team/dialogs/useTeamEditForm.ts +17 -5
- package/src/renderer/components/team/kanban/KanbanBoard.tsx +9 -9
- package/src/renderer/components/team/members/MemberCard.tsx +14 -47
- package/src/renderer/components/team/members/MemberDetailDialog.tsx +3 -95
- package/src/renderer/components/team/members/MemberDetailStats.tsx +50 -65
- package/src/renderer/components/team/messages/MessageComposer.tsx +8 -110
- package/src/renderer/components/team/messages/MessagesPanel.tsx +131 -114
- package/src/renderer/components/team/schedule/ScheduleStatusBadge.tsx +2 -2
- package/src/renderer/components/team/tools/AddMcpInline.tsx +27 -17
- package/src/renderer/components/team/tools/McpChip.tsx +6 -3
- package/src/renderer/components/team/tools/SkillChip.tsx +2 -2
- package/src/renderer/components/team/tools/ToolsSection.tsx +418 -70
- package/src/renderer/hooks/useExtensionsTabState.ts +3 -114
- package/src/renderer/index.css +39 -22
- package/src/renderer/index.html +17 -50
- package/src/renderer/store/index.ts +2 -1
- package/src/renderer/store/slices/scheduleSlice.ts +1 -1
- package/src/renderer/store/slices/teamSlice.ts +45 -168
- package/src/renderer/utils/claudeCodeOnlyProviders.ts +3 -10
- package/src/renderer/utils/memberHelpers.ts +5 -17
- package/src/renderer/utils/openCodeRuntimeDeliveryDiagnostics.ts +4 -2
- package/src/renderer/utils/providerSlashCommands.ts +0 -5
- package/src/renderer/utils/scheduleFormatters.ts +3 -1
- package/src/renderer/utils/teamMessageFiltering.ts +14 -1
- package/src/renderer/utils/teamModelAvailability.ts +18 -2
- package/src/shared/types/api.ts +121 -2
- package/src/shared/types/ccConnect.ts +2 -0
- package/src/shared/types/index.ts +3 -0
- package/src/shared/types/systemManager.ts +49 -0
- package/src/shared/types/team.ts +29 -0
- package/src/shared/types/terminal.ts +4 -2
- package/src/shared/utils/extensionNormalizers.ts +15 -8
- package/src/shared/utils/providerExtensionCapabilities.ts +2 -2
- package/dist-renderer/assets/ProjectEditorOverlay-lJZi-9Hp.js +0 -52
- package/dist-renderer/assets/channel-yIlSKy0e.js +0 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-24fHez0s.js +0 -1
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-24fHez0s.js +0 -1
- package/dist-renderer/assets/clone-BTNuUva-.js +0 -1
- package/dist-renderer/assets/index-Bi6nrZ4z.css +0 -1
- package/dist-renderer/assets/splashScene-C8lWNnm4.js +0 -1
- package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-_m6iPPUR.js +0 -1
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CreateTeamDialog —
|
|
2
|
+
* CreateTeamDialog — create a new digital worker (数字员工).
|
|
3
3
|
*
|
|
4
4
|
* Wizard steps:
|
|
5
5
|
* 1. Name + Agent type + Work directory
|
|
6
|
-
* 2.
|
|
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
|
-
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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' | '
|
|
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
|
-
// ──
|
|
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
|
|
288
|
-
const
|
|
289
|
-
|
|
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
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
const
|
|
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
|
|
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
|
-
|
|
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"
|
|
351
|
+
<DialogTitle className="text-sm">创建数字员工</DialogTitle>
|
|
495
352
|
<DialogDescription className="text-xs">
|
|
496
|
-
{step === 'name' && '
|
|
497
|
-
{step === '
|
|
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
|
-
|
|
371
|
+
该工作目录下已有数字员工"{conflictingTeam.displayName}"正在运行
|
|
518
372
|
</p>
|
|
519
|
-
<p className="opacity-80"
|
|
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"
|
|
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="
|
|
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:
|
|
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
|
-
|
|
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
|
-
) :
|
|
586
|
+
) : (
|
|
801
587
|
<>
|
|
802
588
|
<Button variant="outline" size="sm" onClick={onClose}>
|
|
803
589
|
取消
|
|
804
590
|
</Button>
|
|
805
|
-
<Button
|
|
806
|
-
|
|
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
|
-
)
|
|
814
|
-
<Button variant="outline" size="sm" onClick={() => setStep('name')}>
|
|
815
|
-
返回
|
|
816
|
-
</Button>
|
|
817
|
-
) : null}
|
|
595
|
+
)}
|
|
818
596
|
</div>
|
|
819
597
|
</DialogFooter>
|
|
820
598
|
</DialogContent>
|