@yancyyu/openhermit 1.6.37 → 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-DYT3bwFR.js → TeamGraphOverlay-DqhQzcTr.js} +1 -1
- package/dist-renderer/assets/{_basePickBy-Dbt_EU-e.js → _basePickBy-B7kSYPxr.js} +1 -1
- package/dist-renderer/assets/{_baseUniq-DWo68sXI.js → _baseUniq-CnjxqwAk.js} +1 -1
- package/dist-renderer/assets/{arc-DXH1iZQK.js → arc-CLeZuINP.js} +1 -1
- package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-cjffS2Qr.js → architectureDiagram-VXUJARFQ-QKtqaqdY.js} +1 -1
- package/dist-renderer/assets/{blockDiagram-VD42YOAC-BKdZF02Y.js → blockDiagram-VD42YOAC-BqdrzO_f.js} +1 -1
- package/dist-renderer/assets/{c4Diagram-YG6GDRKO-CN27pqaI.js → c4Diagram-YG6GDRKO-gwPlCxDC.js} +1 -1
- package/dist-renderer/assets/channel-DpMHF50r.js +1 -0
- package/dist-renderer/assets/{chunk-4BX2VUAB-CXPCI7g_.js → chunk-4BX2VUAB-C6XLurL4.js} +1 -1
- package/dist-renderer/assets/{chunk-55IACEB6-BGAXQZRC.js → chunk-55IACEB6-Ds6quhEP.js} +1 -1
- package/dist-renderer/assets/{chunk-B4BG7PRW-TPDaA_KQ.js → chunk-B4BG7PRW-5UlA1_e9.js} +1 -1
- package/dist-renderer/assets/{chunk-DI55MBZ5-D1ADe_tq.js → chunk-DI55MBZ5-ywFrqIsY.js} +1 -1
- package/dist-renderer/assets/{chunk-FMBD7UC4-Beimtg3a.js → chunk-FMBD7UC4-C7ifUA17.js} +1 -1
- package/dist-renderer/assets/{chunk-QN33PNHL-OjNBu854.js → chunk-QN33PNHL-BxGCo80U.js} +1 -1
- package/dist-renderer/assets/{chunk-QZHKN3VN-DinqvbH8.js → chunk-QZHKN3VN-B2CuaZs6.js} +1 -1
- package/dist-renderer/assets/{chunk-TZMSLE5B-BfFtlPSZ.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-D9z9Dgt7.js → cose-bilkent-S5V4N54A-Cz1GVtLp.js} +1 -1
- package/dist-renderer/assets/{dagre-6UL2VRFP-n1g-DhEE.js → dagre-6UL2VRFP-BrmR-P4h.js} +1 -1
- package/dist-renderer/assets/{diagram-PSM6KHXK-BvxFq-BE.js → diagram-PSM6KHXK-DbNjC5Rg.js} +1 -1
- package/dist-renderer/assets/{diagram-QEK2KX5R-wVnJuwza.js → diagram-QEK2KX5R-qkRX5_Mq.js} +1 -1
- package/dist-renderer/assets/{diagram-S2PKOQOG-B707WJQw.js → diagram-S2PKOQOG-CyL5rCv2.js} +1 -1
- package/dist-renderer/assets/{erDiagram-Q2GNP2WA-C-_1dGHs.js → erDiagram-Q2GNP2WA-Dox3-bA5.js} +1 -1
- package/dist-renderer/assets/{flowDiagram-NV44I4VS-CMTSi3H6.js → flowDiagram-NV44I4VS-BtkaxlDL.js} +1 -1
- package/dist-renderer/assets/{ganttDiagram-JELNMOA3-DZ0bNrAA.js → ganttDiagram-JELNMOA3-Dhy_d9GK.js} +1 -1
- package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-DNVfGooQ.js → gitGraphDiagram-V2S2FVAM-B5XRhIQA.js} +1 -1
- package/dist-renderer/assets/{graph-865j_tM_.js → graph-CsoEwUhS.js} +1 -1
- package/dist-renderer/assets/{index-C_F9N5x-.js → index-BWPWmJNo.js} +1 -1
- package/dist-renderer/assets/{index-LwDIsXJN.js → index-Bu2R-Se7.js} +586 -740
- package/dist-renderer/assets/index-CnWV3BhG.css +32 -0
- package/dist-renderer/assets/{index-DuUaf8at.js → index-D-3KgskL.js} +1 -1
- package/dist-renderer/assets/{index-BTx1nc4T.js → index-DGEBzLNT.js} +1 -1
- package/dist-renderer/assets/{index-2EW-eu3q.js → index-NhHNs2Oo.js} +1 -1
- package/dist-renderer/assets/{index-4dEMStJj.js → index-h17WuEyf.js} +1 -1
- package/dist-renderer/assets/{infoDiagram-HS3SLOUP-CyqtElLq.js → infoDiagram-HS3SLOUP-hMGmNojH.js} +1 -1
- package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-BvjQ0Hm0.js → journeyDiagram-XKPGCS4Q-DXV2rBDl.js} +1 -1
- package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-CJJ-k0zT.js → kanban-definition-3W4ZIXB7-Bf99WLRy.js} +1 -1
- package/dist-renderer/assets/{layout-CnV6rQAG.js → layout-C3XWrpwo.js} +1 -1
- package/dist-renderer/assets/{linear-Cw3UQgyX.js → linear-OEEcn8KN.js} +1 -1
- package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-C5tDaGSK.js → mindmap-definition-VGOIOE7T-Dpi3S2x4.js} +1 -1
- package/dist-renderer/assets/{pieDiagram-ADFJNKIX-CiIpPsau.js → pieDiagram-ADFJNKIX-xTPPhtNx.js} +1 -1
- package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-C3gtowNj.js → quadrantDiagram-AYHSOK5B-euniyDlz.js} +1 -1
- package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-CXBTrAnU.js → requirementDiagram-UZGBJVZJ-D9Uiw4kF.js} +1 -1
- package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-wziX77xG.js → sankeyDiagram-TZEHDZUN-CySU4nED.js} +1 -1
- package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-sYqopcrj.js → sequenceDiagram-WL72ISMW-JVGpET6V.js} +1 -1
- package/dist-renderer/assets/splashScene-D0YB9uxm.js +17 -0
- package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-Bl1-0_Cp.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-CIRjJUBo.js → timeline-definition-IT6M3QCI-DmycNUUe.js} +1 -1
- package/dist-renderer/assets/{treemap-GDKQZRPO-CVPuNe1n.js → treemap-GDKQZRPO-DPq4gZuB.js} +1 -1
- package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-3nT9yHwp.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 +30 -50
- package/src/main/server.ts +890 -247
- package/src/main/services/extensions/ExtensionFacadeService.ts +4 -56
- package/src/main/services/extensions/catalog/PluginCatalogService.ts +4 -2
- package/src/main/services/extensions/library/McpLibraryService.ts +243 -0
- 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/session-intelligence/UsageTelemetryService.ts +14 -1
- 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 +32 -8
- 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 +174 -38
- 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 +12 -221
- 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 +10 -2
- package/src/renderer/components/extensions/plugins/PluginsPanel.tsx +40 -22
- 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 +325 -114
- 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 +57 -0
- package/src/renderer/components/team/tools/AddSkillInline.tsx +61 -0
- package/src/renderer/components/team/tools/McpChip.tsx +45 -0
- package/src/renderer/components/team/tools/SkillChip.tsx +35 -0
- package/src/renderer/components/team/tools/ToolsSection.tsx +556 -0
- 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/extensions/api.ts +9 -0
- package/src/shared/types/extensions/index.ts +4 -0
- package/src/shared/types/extensions/mcp.ts +41 -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 +29 -0
- package/src/shared/utils/providerExtensionCapabilities.ts +2 -2
- package/dist-renderer/assets/ProjectEditorOverlay-Va_Vz-zz.js +0 -52
- package/dist-renderer/assets/channel-5dJIx68e.js +0 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-BMGXWJ2d.js +0 -1
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-BMGXWJ2d.js +0 -1
- package/dist-renderer/assets/clone-D7FWfGY9.js +0 -1
- package/dist-renderer/assets/index-B2z_IyRH.css +0 -1
- package/dist-renderer/assets/splashScene-C8lWNnm4.js +0 -1
- package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-DOYYvDbi.js +0 -1
- package/src/main/services/extensions/catalog/GlamaMcpEnrichmentService.ts +0 -190
- package/src/main/services/extensions/catalog/McpCatalogAggregator.ts +0 -150
- package/src/main/services/extensions/catalog/OfficialMcpRegistryService.ts +0 -381
- package/src/main/services/extensions/install/McpInstallService.ts +0 -407
- package/src/main/services/extensions/state/McpInstallationStateService.ts +0 -42
- package/src/renderer/components/extensions/mcp/McpServerCard.tsx +0 -314
- package/src/renderer/components/extensions/mcp/McpServerDetailDialog.tsx +0 -765
- package/src/renderer/components/extensions/mcp/McpServersPanel.tsx +0 -593
- package/src/renderer/components/extensions/skills/SkillDetailDialog.tsx +0 -372
- package/src/renderer/components/extensions/skills/SkillImportDialog.tsx +0 -343
- package/src/renderer/components/extensions/skills/SkillsPanel.tsx +0 -659
|
@@ -60,9 +60,11 @@ import { deriveTaskDisplayId, formatTaskDisplayLabel } from '@shared/utils/taskI
|
|
|
60
60
|
import {
|
|
61
61
|
AlertTriangle,
|
|
62
62
|
Columns3,
|
|
63
|
+
Download,
|
|
63
64
|
FolderOpen,
|
|
64
65
|
GitBranch,
|
|
65
66
|
History,
|
|
67
|
+
Link,
|
|
66
68
|
Pencil,
|
|
67
69
|
Play,
|
|
68
70
|
Plus,
|
|
@@ -71,7 +73,6 @@ import {
|
|
|
71
73
|
Loader2,
|
|
72
74
|
MessageSquare,
|
|
73
75
|
MoreHorizontal,
|
|
74
|
-
Shield,
|
|
75
76
|
Users,
|
|
76
77
|
} from 'lucide-react';
|
|
77
78
|
import { useShallow } from 'zustand/react/shallow';
|
|
@@ -79,7 +80,9 @@ import { useShallow } from 'zustand/react/shallow';
|
|
|
79
80
|
import { CreateTaskDialog } from './dialogs/CreateTaskDialog';
|
|
80
81
|
import { EditTeamDialog } from './dialogs/EditTeamDialog';
|
|
81
82
|
import { LaunchTeamDialog, type TeamLaunchDialogMode } from './dialogs/LaunchTeamDialog';
|
|
83
|
+
import { PlatformBindingDialog } from './dialogs/PlatformBindingDialog';
|
|
82
84
|
import { ReviewDialog } from './dialogs/ReviewDialog';
|
|
85
|
+
import { RuntimeConfigDialog } from './dialogs/RuntimeConfigDialog';
|
|
83
86
|
import { SendMessageDialog } from './dialogs/SendMessageDialog';
|
|
84
87
|
import { TaskDetailDialog } from './dialogs/TaskDetailDialog';
|
|
85
88
|
import { executeTeamRelaunch } from './dialogs/teamRelaunchFlow';
|
|
@@ -88,18 +91,20 @@ import { UNASSIGNED_OWNER } from './kanban/KanbanFilterPopover';
|
|
|
88
91
|
import { KanbanSearchInput } from './kanban/KanbanSearchInput';
|
|
89
92
|
import { TrashDialog } from './kanban/TrashDialog';
|
|
90
93
|
import { MemberDetailDialog } from './members/MemberDetailDialog';
|
|
91
|
-
|
|
94
|
+
|
|
92
95
|
|
|
93
96
|
import type { TeamMessagesPanelMode } from '@renderer/types/teamMessagesPanelMode';
|
|
94
97
|
import type { ComponentProps } from 'react';
|
|
95
98
|
|
|
99
|
+
import { TerminalPane, type TerminalPaneRef } from '@renderer/components/common/TerminalPane';
|
|
100
|
+
|
|
96
101
|
const ProjectEditorOverlay = lazy(() =>
|
|
97
102
|
import('./editor/ProjectEditorOverlay').then((m) => ({ default: m.ProjectEditorOverlay }))
|
|
98
103
|
);
|
|
99
104
|
import { MemberList } from './members/MemberList';
|
|
100
105
|
import { MessagesPanel } from './messages/MessagesPanel';
|
|
106
|
+
import { CcSessionsSection, buildAllSessionsCsv, buildAllSessionsCsvFilename, downloadTextFile, hasDataRows, isExportPayload } from './CcSessionsSection';
|
|
101
107
|
import { ChangeReviewDialog } from './review/ChangeReviewDialog';
|
|
102
|
-
import { ProjectEnvPanel } from '../extensions/env/ProjectEnvPanel';
|
|
103
108
|
import {
|
|
104
109
|
getTeamPendingRepliesState,
|
|
105
110
|
setTeamPendingRepliesState,
|
|
@@ -119,6 +124,7 @@ import type { ContextInjection } from '@renderer/types/contextInjection';
|
|
|
119
124
|
import type { Session } from '@renderer/types/data';
|
|
120
125
|
import type { InlineChip } from '@renderer/types/inlineChip';
|
|
121
126
|
import type {
|
|
127
|
+
CcSession,
|
|
122
128
|
EffortLevel,
|
|
123
129
|
GlobalProvider,
|
|
124
130
|
MemberSpawnStatusEntry,
|
|
@@ -132,6 +138,7 @@ import type {
|
|
|
132
138
|
TeamTaskWithKanban,
|
|
133
139
|
TeamViewSnapshot,
|
|
134
140
|
} from '@shared/types';
|
|
141
|
+
import { SYSTEM_MANAGER_TEAM_NAME } from '@shared/types/team';
|
|
135
142
|
import type { EditorSelectionAction } from '@shared/types/editor';
|
|
136
143
|
import type { ContextUsageLike } from '@shared/utils/contextMetrics';
|
|
137
144
|
|
|
@@ -232,7 +239,7 @@ const TeamOfflineStatusBanner = memo(function TeamOfflineStatusBanner({
|
|
|
232
239
|
teamName: string;
|
|
233
240
|
onLaunch: () => void;
|
|
234
241
|
}): React.JSX.Element {
|
|
235
|
-
const message = '
|
|
242
|
+
const message = '数字员工未运行:当前没有本地 Claude/Agent 进程在运行,已有数据和任务仍会保留。';
|
|
236
243
|
|
|
237
244
|
return (
|
|
238
245
|
<div
|
|
@@ -254,7 +261,7 @@ const TeamOfflineStatusBanner = memo(function TeamOfflineStatusBanner({
|
|
|
254
261
|
onClick={onLaunch}
|
|
255
262
|
>
|
|
256
263
|
<Play size={12} />
|
|
257
|
-
|
|
264
|
+
启动数字员工
|
|
258
265
|
</Button>
|
|
259
266
|
</div>
|
|
260
267
|
);
|
|
@@ -859,6 +866,43 @@ const TeamMemberDetailDialogBridge = memo(function TeamMemberDetailDialogBridge(
|
|
|
859
866
|
);
|
|
860
867
|
});
|
|
861
868
|
|
|
869
|
+
/** Map agent harness type to CLI command name */
|
|
870
|
+
function getCommandForHarness(harness?: string): string {
|
|
871
|
+
switch (harness) {
|
|
872
|
+
case 'claudecode':
|
|
873
|
+
return 'claude';
|
|
874
|
+
case 'codex':
|
|
875
|
+
return 'codex';
|
|
876
|
+
case 'opencode':
|
|
877
|
+
return 'opencode';
|
|
878
|
+
case 'cursor':
|
|
879
|
+
return 'cursor';
|
|
880
|
+
case 'gemini':
|
|
881
|
+
return 'gemini';
|
|
882
|
+
case 'iflow':
|
|
883
|
+
return 'iflow';
|
|
884
|
+
case 'kimi':
|
|
885
|
+
return 'kimi';
|
|
886
|
+
case 'qoder':
|
|
887
|
+
return 'qoder';
|
|
888
|
+
case 'pi':
|
|
889
|
+
return 'pi';
|
|
890
|
+
case 'acp':
|
|
891
|
+
return 'acp';
|
|
892
|
+
case 'tmux':
|
|
893
|
+
return 'tmux';
|
|
894
|
+
case 'devin':
|
|
895
|
+
return 'devin';
|
|
896
|
+
default:
|
|
897
|
+
return 'claude';
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
/** All CcAgentType values run as local CLI agents */
|
|
902
|
+
function isLocalHarness(harness?: string): boolean {
|
|
903
|
+
return !!harness;
|
|
904
|
+
}
|
|
905
|
+
|
|
862
906
|
export const TeamDetailView = ({
|
|
863
907
|
teamName,
|
|
864
908
|
isPaneFocused = false,
|
|
@@ -867,10 +911,6 @@ export const TeamDetailView = ({
|
|
|
867
911
|
const [requestChangesTaskId, setRequestChangesTaskId] = useState<string | null>(null);
|
|
868
912
|
const [selectedTask, setSelectedTask] = useState<TeamTaskWithKanban | null>(null);
|
|
869
913
|
const [selectedMember, setSelectedMember] = useState<ResolvedTeamMember | null>(null);
|
|
870
|
-
const [selectedMemberView, setSelectedMemberView] = useState<{
|
|
871
|
-
initialTab?: MemberDetailTab;
|
|
872
|
-
initialActivityFilter?: MemberActivityFilter;
|
|
873
|
-
} | null>(null);
|
|
874
914
|
const [pendingRepliesByMember, setPendingRepliesByMember] = useState<Record<string, number>>(() =>
|
|
875
915
|
getTeamPendingRepliesState(teamName)
|
|
876
916
|
);
|
|
@@ -884,7 +924,7 @@ export const TeamDetailView = ({
|
|
|
884
924
|
const [removeMemberConfirm, setRemoveMemberConfirm] = useState<string | null>(null);
|
|
885
925
|
const [updatingRoleLoading, setUpdatingRoleLoading] = useState(false);
|
|
886
926
|
const [editDialogOpen, setEditDialogOpen] = useState(false);
|
|
887
|
-
const [
|
|
927
|
+
const [bindingDialogOpen, setBindingDialogOpen] = useState(false);
|
|
888
928
|
const [headerMenuOpen, setHeaderMenuOpen] = useState(false);
|
|
889
929
|
const [launchDialogState, setLaunchDialogState] = useState<{
|
|
890
930
|
open: boolean;
|
|
@@ -894,8 +934,11 @@ export const TeamDetailView = ({
|
|
|
894
934
|
mode: 'launch',
|
|
895
935
|
});
|
|
896
936
|
const [editorOpen, setEditorOpen] = useState(false);
|
|
937
|
+
const [terminalHeight, setTerminalHeight] = useState(400);
|
|
897
938
|
const contentRef = useRef<HTMLDivElement>(null);
|
|
898
939
|
const provisioningBannerRef = useRef<HTMLDivElement>(null);
|
|
940
|
+
const terminalPaneRef = useRef<TerminalPaneRef>(null);
|
|
941
|
+
const terminalSpawnedForTeamRef = useRef<string | null>(null);
|
|
899
942
|
const wasProvisioningRef = useRef(false);
|
|
900
943
|
|
|
901
944
|
// Set inert on background content when editor overlay is open (a11y focus trap)
|
|
@@ -929,17 +972,11 @@ export const TeamDetailView = ({
|
|
|
929
972
|
const {
|
|
930
973
|
teamName: tn,
|
|
931
974
|
memberName,
|
|
932
|
-
initialTab,
|
|
933
|
-
initialActivityFilter,
|
|
934
975
|
} = (e as CustomEvent).detail ?? {};
|
|
935
976
|
if (tn !== teamName || !data) return;
|
|
936
977
|
const member = members.find((m: { name: string }) => m.name === memberName);
|
|
937
978
|
if (member) {
|
|
938
979
|
setSelectedMember(member);
|
|
939
|
-
setSelectedMemberView({
|
|
940
|
-
initialTab,
|
|
941
|
-
initialActivityFilter,
|
|
942
|
-
});
|
|
943
980
|
}
|
|
944
981
|
};
|
|
945
982
|
const onCreateTask = (e: Event) => {
|
|
@@ -1086,6 +1123,56 @@ export const TeamDetailView = ({
|
|
|
1086
1123
|
const [sessions, setSessions] = useState<Session[]>([]);
|
|
1087
1124
|
const [sessionsLoading, setSessionsLoading] = useState(false);
|
|
1088
1125
|
const [sessionsError, setSessionsError] = useState<string | null>(null);
|
|
1126
|
+
const [ccSessions, setCcSessions] = useState<CcSession[]>([]);
|
|
1127
|
+
const [ccSessionsLoading, setCcSessionsLoading] = useState(false);
|
|
1128
|
+
const [ccSessionsError, setCcSessionsError] = useState<string | null>(null);
|
|
1129
|
+
const [ccExporting, setCcExporting] = useState(false);
|
|
1130
|
+
|
|
1131
|
+
const handleExportAllCcSessions = useCallback(async () => {
|
|
1132
|
+
if (ccExporting) return;
|
|
1133
|
+
setCcExporting(true);
|
|
1134
|
+
try {
|
|
1135
|
+
const params = new URLSearchParams({
|
|
1136
|
+
teamName,
|
|
1137
|
+
format: 'csv',
|
|
1138
|
+
includeContent: 'full',
|
|
1139
|
+
includeToolResults: 'false',
|
|
1140
|
+
includeSystemMessages: 'false',
|
|
1141
|
+
});
|
|
1142
|
+
const res = await fetch(`/api/telemetry/conversations/export?${params.toString()}`);
|
|
1143
|
+
if (res.ok) {
|
|
1144
|
+
const payload = (await res.json()) as unknown;
|
|
1145
|
+
if (isExportPayload(payload) && hasDataRows(payload.content)) {
|
|
1146
|
+
downloadTextFile(payload.content, payload.filename, payload.mimeType);
|
|
1147
|
+
return;
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
const details = await Promise.all(
|
|
1152
|
+
ccSessions.map(async (session) => {
|
|
1153
|
+
try {
|
|
1154
|
+
const detail = await api.teams.getSessionDetail(
|
|
1155
|
+
teamName,
|
|
1156
|
+
session.id,
|
|
1157
|
+
Math.max(session.historyCount, 1)
|
|
1158
|
+
);
|
|
1159
|
+
return { session, detail };
|
|
1160
|
+
} catch {
|
|
1161
|
+
return { session, detail: null };
|
|
1162
|
+
}
|
|
1163
|
+
})
|
|
1164
|
+
);
|
|
1165
|
+
downloadTextFile(
|
|
1166
|
+
buildAllSessionsCsv(details),
|
|
1167
|
+
buildAllSessionsCsvFilename(teamName),
|
|
1168
|
+
'text/csv;charset=utf-8'
|
|
1169
|
+
);
|
|
1170
|
+
} catch (err) {
|
|
1171
|
+
console.error('Failed to export all conversation telemetry:', err);
|
|
1172
|
+
} finally {
|
|
1173
|
+
setCcExporting(false);
|
|
1174
|
+
}
|
|
1175
|
+
}, [ccExporting, ccSessions, teamName]);
|
|
1089
1176
|
const [kanbanFilter, setKanbanFilter] = useState<KanbanFilterState>({
|
|
1090
1177
|
sessionId: null,
|
|
1091
1178
|
selectedOwners: new Set(),
|
|
@@ -1244,6 +1331,24 @@ export const TeamDetailView = ({
|
|
|
1244
1331
|
void fetchDeletedTasks(teamName);
|
|
1245
1332
|
}, [teamName, selectTeam, fetchDeletedTasks]);
|
|
1246
1333
|
|
|
1334
|
+
// Spawn terminal PTY once per team — imperative, no autoSpawn.
|
|
1335
|
+
// TerminalPane lives outside renderBody() so it never unmounts on data refresh.
|
|
1336
|
+
// terminalSpawnedForTeamRef guards against re-spawning on data changes.
|
|
1337
|
+
useEffect(() => {
|
|
1338
|
+
if (!data || !teamName || teamName === SYSTEM_MANAGER_TEAM_NAME) return;
|
|
1339
|
+
const cwd = data.config.projectPath || data.config.executionTarget?.cwd || data.workDir || '';
|
|
1340
|
+
if (!cwd) return;
|
|
1341
|
+
const harness = data.config.agentType || data.harness;
|
|
1342
|
+
const spawnKey = `${teamName}:${harness ?? ''}`;
|
|
1343
|
+
if (terminalSpawnedForTeamRef.current === spawnKey) return;
|
|
1344
|
+
terminalSpawnedForTeamRef.current = spawnKey;
|
|
1345
|
+
void terminalPaneRef.current?.spawn({
|
|
1346
|
+
command: getCommandForHarness(harness),
|
|
1347
|
+
args: [],
|
|
1348
|
+
cwd,
|
|
1349
|
+
});
|
|
1350
|
+
}, [data, teamName]);
|
|
1351
|
+
|
|
1247
1352
|
// Recovery: after HMR, all mounted TeamDetailView effects re-run simultaneously.
|
|
1248
1353
|
// With CSS display-toggle (all tabs stay mounted), the last selectTeam() call wins
|
|
1249
1354
|
// and other tabs get stuck with mismatched data (permanent skeleton).
|
|
@@ -1352,6 +1457,38 @@ export const TeamDetailView = ({
|
|
|
1352
1457
|
teamName,
|
|
1353
1458
|
]);
|
|
1354
1459
|
|
|
1460
|
+
useEffect(() => {
|
|
1461
|
+
if (!teamName) return;
|
|
1462
|
+
let cancelled = false;
|
|
1463
|
+
setCcSessions([]);
|
|
1464
|
+
|
|
1465
|
+
const loadCcSessions = async (showLoading: boolean): Promise<void> => {
|
|
1466
|
+
if (showLoading) setCcSessionsLoading(true);
|
|
1467
|
+
setCcSessionsError(null);
|
|
1468
|
+
try {
|
|
1469
|
+
const result = await api.teams.getTeamSessions(teamName);
|
|
1470
|
+
if (!cancelled) setCcSessions(result);
|
|
1471
|
+
} catch (e) {
|
|
1472
|
+
if (!cancelled) {
|
|
1473
|
+
setCcSessions([]);
|
|
1474
|
+
setCcSessionsError(e instanceof Error ? e.message : '加载运行会话失败');
|
|
1475
|
+
}
|
|
1476
|
+
} finally {
|
|
1477
|
+
if (!cancelled && showLoading) setCcSessionsLoading(false);
|
|
1478
|
+
}
|
|
1479
|
+
};
|
|
1480
|
+
|
|
1481
|
+
void loadCcSessions(true);
|
|
1482
|
+
const interval = window.setInterval(() => {
|
|
1483
|
+
void loadCcSessions(false);
|
|
1484
|
+
}, 3_000);
|
|
1485
|
+
|
|
1486
|
+
return () => {
|
|
1487
|
+
cancelled = true;
|
|
1488
|
+
window.clearInterval(interval);
|
|
1489
|
+
};
|
|
1490
|
+
}, [teamName, data?.isAlive]);
|
|
1491
|
+
|
|
1355
1492
|
useEffect(() => {
|
|
1356
1493
|
if (!projectId) return;
|
|
1357
1494
|
|
|
@@ -1579,8 +1716,21 @@ export const TeamDetailView = ({
|
|
|
1579
1716
|
}, []);
|
|
1580
1717
|
|
|
1581
1718
|
const handleRestartTeam = useCallback(() => {
|
|
1719
|
+
const cfg = data?.config;
|
|
1720
|
+
const harness = cfg?.agentType || data?.harness;
|
|
1721
|
+
if (isLocalHarness(harness)) {
|
|
1722
|
+
const cwd = cfg?.projectPath || cfg?.executionTarget?.cwd || data?.workDir || '';
|
|
1723
|
+
if (cwd) {
|
|
1724
|
+
terminalPaneRef.current?.spawn({
|
|
1725
|
+
command: getCommandForHarness(harness),
|
|
1726
|
+
args: [],
|
|
1727
|
+
cwd,
|
|
1728
|
+
});
|
|
1729
|
+
return;
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1582
1732
|
openLaunchDialog('relaunch');
|
|
1583
|
-
}, [openLaunchDialog]);
|
|
1733
|
+
}, [data, openLaunchDialog]);
|
|
1584
1734
|
|
|
1585
1735
|
const handleStartCcConnectTeam = useCallback(() => {
|
|
1586
1736
|
void (async () => {
|
|
@@ -1588,7 +1738,6 @@ export const TeamDetailView = ({
|
|
|
1588
1738
|
openLaunchDialog('launch');
|
|
1589
1739
|
return;
|
|
1590
1740
|
}
|
|
1591
|
-
await api.ccSettings.restart();
|
|
1592
1741
|
await api.teams.launchTeam({
|
|
1593
1742
|
teamName,
|
|
1594
1743
|
cwd: data.config.projectPath,
|
|
@@ -1629,7 +1778,6 @@ export const TeamDetailView = ({
|
|
|
1629
1778
|
);
|
|
1630
1779
|
|
|
1631
1780
|
const handleRestartTeamFromEdit = useCallback(async (): Promise<void> => {
|
|
1632
|
-
await api.ccSettings.restart();
|
|
1633
1781
|
await Promise.all([fetchTeams(), selectTeam(teamName)]);
|
|
1634
1782
|
}, [fetchTeams, selectTeam, teamName]);
|
|
1635
1783
|
|
|
@@ -1675,12 +1823,12 @@ export const TeamDetailView = ({
|
|
|
1675
1823
|
|
|
1676
1824
|
const handleSelectMember = useCallback((member: ResolvedTeamMember) => {
|
|
1677
1825
|
setSelectedMember(member);
|
|
1678
|
-
|
|
1826
|
+
setSelectedMember(null);
|
|
1679
1827
|
}, []);
|
|
1680
1828
|
|
|
1681
1829
|
const closeSelectedMemberDialog = useCallback(() => {
|
|
1682
1830
|
setSelectedMember(null);
|
|
1683
|
-
|
|
1831
|
+
setSelectedMember(null);
|
|
1684
1832
|
}, []);
|
|
1685
1833
|
|
|
1686
1834
|
const handleSendMessageToMember = useCallback((member: ResolvedTeamMember) => {
|
|
@@ -1769,7 +1917,7 @@ export const TeamDetailView = ({
|
|
|
1769
1917
|
const member = membersWithLiveBranches.find((m) => m.name === pendingMemberProfile);
|
|
1770
1918
|
if (member) {
|
|
1771
1919
|
setSelectedMember(member);
|
|
1772
|
-
|
|
1920
|
+
setSelectedMember(null);
|
|
1773
1921
|
}
|
|
1774
1922
|
useStore.getState().closeMemberProfile();
|
|
1775
1923
|
}, [pendingMemberProfile, membersWithLiveBranches]);
|
|
@@ -1835,9 +1983,6 @@ export const TeamDetailView = ({
|
|
|
1835
1983
|
void (async () => {
|
|
1836
1984
|
try {
|
|
1837
1985
|
const result = await deleteTeam(teamName);
|
|
1838
|
-
if (result.restartRequired) {
|
|
1839
|
-
await api.ccSettings.restart();
|
|
1840
|
-
}
|
|
1841
1986
|
await fetchTeams();
|
|
1842
1987
|
setDeleteConfirmOpen(false);
|
|
1843
1988
|
if (tabId) closeTab(tabId);
|
|
@@ -1904,7 +2049,7 @@ export const TeamDetailView = ({
|
|
|
1904
2049
|
tasks: data?.tasks ?? [],
|
|
1905
2050
|
isTeamAlive: data?.isAlive,
|
|
1906
2051
|
timeWindow,
|
|
1907
|
-
|
|
2052
|
+
sessions: ccSessions,
|
|
1908
2053
|
currentLeadSessionId: data?.config.leadSessionId,
|
|
1909
2054
|
pendingRepliesByMember,
|
|
1910
2055
|
onPendingReplyChange: setPendingRepliesByMember,
|
|
@@ -1919,12 +2064,12 @@ export const TeamDetailView = ({
|
|
|
1919
2064
|
data?.config.leadSessionId,
|
|
1920
2065
|
data?.isAlive,
|
|
1921
2066
|
data?.tasks,
|
|
2067
|
+
ccSessions,
|
|
1922
2068
|
handleReplyToMessage,
|
|
1923
2069
|
handleRestartTeam,
|
|
1924
2070
|
handleSelectMember,
|
|
1925
2071
|
pendingRepliesByMember,
|
|
1926
2072
|
teamName,
|
|
1927
|
-
teamSessionIds,
|
|
1928
2073
|
timeWindow,
|
|
1929
2074
|
keepMessagesInline,
|
|
1930
2075
|
]
|
|
@@ -1987,6 +2132,7 @@ export const TeamDetailView = ({
|
|
|
1987
2132
|
if (error === 'TEAM_DRAFT') {
|
|
1988
2133
|
const draftTeamSummary = useStore.getState().teamByName[teamName];
|
|
1989
2134
|
const draftDisplayName = draftTeamSummary?.displayName || teamName;
|
|
2135
|
+
const draftCwd = draftTeamSummary?.projectPath || draftTeamSummary?.workDir || '';
|
|
1990
2136
|
|
|
1991
2137
|
return (
|
|
1992
2138
|
<>
|
|
@@ -1994,44 +2140,27 @@ export const TeamDetailView = ({
|
|
|
1994
2140
|
<div ref={provisioningBannerRef}>
|
|
1995
2141
|
<TeamProvisioningBanner teamName={teamName} />
|
|
1996
2142
|
</div>
|
|
1997
|
-
<div className="flex
|
|
1998
|
-
<
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
>
|
|
2017
|
-
删除
|
|
2018
|
-
</button>
|
|
2019
|
-
</div>
|
|
2020
|
-
</div>
|
|
2143
|
+
<div className="flex items-center gap-3 py-2">
|
|
2144
|
+
<p className="text-sm font-medium text-text">{draftDisplayName}</p>
|
|
2145
|
+
<span className="rounded-full bg-blue-500/20 px-2 py-0.5 text-[10px] font-medium text-blue-400">
|
|
2146
|
+
{getCommandForHarness()}
|
|
2147
|
+
</span>
|
|
2148
|
+
</div>
|
|
2149
|
+
<div className="h-[calc(100vh-16rem)] overflow-hidden rounded-lg border border-[var(--color-border-subtle)]">
|
|
2150
|
+
<TerminalPane
|
|
2151
|
+
ref={terminalPaneRef}
|
|
2152
|
+
autoSpawn={
|
|
2153
|
+
draftCwd
|
|
2154
|
+
? {
|
|
2155
|
+
command: getCommandForHarness(),
|
|
2156
|
+
args: [],
|
|
2157
|
+
cwd: draftCwd,
|
|
2158
|
+
}
|
|
2159
|
+
: undefined
|
|
2160
|
+
}
|
|
2161
|
+
/>
|
|
2021
2162
|
</div>
|
|
2022
2163
|
</div>
|
|
2023
|
-
<LaunchTeamDialog
|
|
2024
|
-
mode={launchDialogState.mode}
|
|
2025
|
-
open={launchDialogOpen}
|
|
2026
|
-
teamName={teamName}
|
|
2027
|
-
members={[]}
|
|
2028
|
-
defaultProjectPath={draftTeamSummary?.projectPath}
|
|
2029
|
-
provisioningError={provisioningError}
|
|
2030
|
-
clearProvisioningError={clearProvisioningError}
|
|
2031
|
-
onClose={closeLaunchDialog}
|
|
2032
|
-
onLaunch={handleLaunchDialogSubmit}
|
|
2033
|
-
onRelaunch={handleRelaunchDialogSubmit}
|
|
2034
|
-
/>
|
|
2035
2164
|
</>
|
|
2036
2165
|
);
|
|
2037
2166
|
}
|
|
@@ -2108,13 +2237,16 @@ export const TeamDetailView = ({
|
|
|
2108
2237
|
<h2 className="text-base font-semibold text-[var(--color-text)]">
|
|
2109
2238
|
{data.config.name}
|
|
2110
2239
|
</h2>
|
|
2111
|
-
{data.
|
|
2112
|
-
<span
|
|
2240
|
+
{data.platforms?.filter((pl) => pl.type !== 'bridge').map((pl) => (
|
|
2241
|
+
<span
|
|
2242
|
+
key={pl.type}
|
|
2243
|
+
className="inline-flex items-center gap-1 rounded-full bg-emerald-500/15 px-1.5 py-0.5 text-[10px] font-medium text-emerald-400"
|
|
2244
|
+
>
|
|
2113
2245
|
<span className="size-1.5 rounded-full bg-emerald-400" />
|
|
2114
|
-
|
|
2246
|
+
{pl.type}
|
|
2115
2247
|
</span>
|
|
2116
|
-
)}
|
|
2117
|
-
{
|
|
2248
|
+
))}
|
|
2249
|
+
{isTeamProvisioning && (
|
|
2118
2250
|
<span className="inline-flex items-center gap-1 rounded-full bg-yellow-500/15 px-1.5 py-0.5 text-[10px] font-medium text-yellow-400">
|
|
2119
2251
|
<span className="size-1.5 animate-pulse rounded-full bg-yellow-400" />
|
|
2120
2252
|
启动中...
|
|
@@ -2123,6 +2255,18 @@ export const TeamDetailView = ({
|
|
|
2123
2255
|
</div>
|
|
2124
2256
|
</div>
|
|
2125
2257
|
<div className="flex shrink-0 items-center gap-1.5">
|
|
2258
|
+
{teamName !== SYSTEM_MANAGER_TEAM_NAME ? (
|
|
2259
|
+
<Button
|
|
2260
|
+
variant="outline"
|
|
2261
|
+
size="sm"
|
|
2262
|
+
className="h-7 gap-1.5 px-2.5 text-xs text-[var(--color-text-secondary)]"
|
|
2263
|
+
disabled={isTeamProvisioning}
|
|
2264
|
+
onClick={() => setBindingDialogOpen(true)}
|
|
2265
|
+
>
|
|
2266
|
+
<Link size={12} />
|
|
2267
|
+
运行时
|
|
2268
|
+
</Button>
|
|
2269
|
+
) : null}
|
|
2126
2270
|
<Button
|
|
2127
2271
|
variant="outline"
|
|
2128
2272
|
size="sm"
|
|
@@ -2144,32 +2288,21 @@ export const TeamDetailView = ({
|
|
|
2144
2288
|
</Button>
|
|
2145
2289
|
</PopoverTrigger>
|
|
2146
2290
|
<PopoverContent align="end" className="w-44 p-1">
|
|
2147
|
-
{
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
type="button"
|
|
2163
|
-
className="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-xs text-red-400 hover:bg-red-500/10"
|
|
2164
|
-
onClick={() => {
|
|
2165
|
-
setHeaderMenuOpen(false);
|
|
2166
|
-
handleDeleteTeam();
|
|
2167
|
-
}}
|
|
2168
|
-
>
|
|
2169
|
-
<Trash2 size={13} />
|
|
2170
|
-
删除团队
|
|
2171
|
-
</button>
|
|
2172
|
-
)}
|
|
2291
|
+
{teamName !== 'default' &&
|
|
2292
|
+
teamName !== 'my-project' &&
|
|
2293
|
+
teamName !== SYSTEM_MANAGER_TEAM_NAME && (
|
|
2294
|
+
<button
|
|
2295
|
+
type="button"
|
|
2296
|
+
className="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-xs text-red-400 hover:bg-red-500/10"
|
|
2297
|
+
onClick={() => {
|
|
2298
|
+
setHeaderMenuOpen(false);
|
|
2299
|
+
handleDeleteTeam();
|
|
2300
|
+
}}
|
|
2301
|
+
>
|
|
2302
|
+
<Trash2 size={13} />
|
|
2303
|
+
删除团队
|
|
2304
|
+
</button>
|
|
2305
|
+
)}
|
|
2173
2306
|
</PopoverContent>
|
|
2174
2307
|
</Popover>
|
|
2175
2308
|
</div>
|
|
@@ -2279,6 +2412,42 @@ export const TeamDetailView = ({
|
|
|
2279
2412
|
/>
|
|
2280
2413
|
</CollapsibleTeamSection>
|
|
2281
2414
|
|
|
2415
|
+
<CollapsibleTeamSection
|
|
2416
|
+
sectionId="team-sessions"
|
|
2417
|
+
title="会话"
|
|
2418
|
+
icon={<MessageSquare size={14} />}
|
|
2419
|
+
badge={ccSessions.length}
|
|
2420
|
+
defaultOpen={ccSessions.length > 0}
|
|
2421
|
+
action={
|
|
2422
|
+
ccSessions.length > 0 ? (
|
|
2423
|
+
<button
|
|
2424
|
+
type="button"
|
|
2425
|
+
className="inline-flex items-center gap-1 rounded-md px-2 py-0.5 text-[11px] text-[var(--color-text-muted)] transition-colors hover:bg-[var(--color-surface-raised)] hover:text-[var(--color-text)] disabled:cursor-not-allowed disabled:opacity-50"
|
|
2426
|
+
onClick={(e) => {
|
|
2427
|
+
e.stopPropagation();
|
|
2428
|
+
void handleExportAllCcSessions();
|
|
2429
|
+
}}
|
|
2430
|
+
disabled={ccExporting}
|
|
2431
|
+
title="导出所有会话为 CSV 表格"
|
|
2432
|
+
>
|
|
2433
|
+
{ccExporting ? (
|
|
2434
|
+
<Loader2 size={12} className="animate-spin" />
|
|
2435
|
+
) : (
|
|
2436
|
+
<Download size={12} />
|
|
2437
|
+
)}
|
|
2438
|
+
导出
|
|
2439
|
+
</button>
|
|
2440
|
+
) : undefined
|
|
2441
|
+
}
|
|
2442
|
+
>
|
|
2443
|
+
<CcSessionsSection
|
|
2444
|
+
teamName={teamName}
|
|
2445
|
+
sessions={ccSessions}
|
|
2446
|
+
loading={ccSessionsLoading}
|
|
2447
|
+
error={ccSessionsError}
|
|
2448
|
+
/>
|
|
2449
|
+
</CollapsibleTeamSection>
|
|
2450
|
+
|
|
2282
2451
|
<CollapsibleTeamSection
|
|
2283
2452
|
sectionId="kanban"
|
|
2284
2453
|
title="外部派单"
|
|
@@ -2472,8 +2641,6 @@ export const TeamDetailView = ({
|
|
|
2472
2641
|
</div>
|
|
2473
2642
|
</CollapsibleTeamSection>
|
|
2474
2643
|
|
|
2475
|
-
<TeamMessagesPanelBridge position="inline" {...sharedMessagesPanelProps} />
|
|
2476
|
-
|
|
2477
2644
|
{(data.processes?.length ?? 0) > 0 && (
|
|
2478
2645
|
<CollapsibleTeamSection
|
|
2479
2646
|
sectionId="processes"
|
|
@@ -2532,8 +2699,6 @@ export const TeamDetailView = ({
|
|
|
2532
2699
|
teamName={teamName}
|
|
2533
2700
|
members={membersWithLiveBranches}
|
|
2534
2701
|
tasks={data.tasks}
|
|
2535
|
-
initialTab={selectedMemberView?.initialTab}
|
|
2536
|
-
initialActivityFilter={selectedMemberView?.initialActivityFilter}
|
|
2537
2702
|
isTeamAlive={data.isAlive}
|
|
2538
2703
|
isTeamProvisioning={isTeamProvisioning}
|
|
2539
2704
|
launchParams={launchParams}
|
|
@@ -2580,18 +2745,6 @@ export const TeamDetailView = ({
|
|
|
2580
2745
|
}}
|
|
2581
2746
|
/>
|
|
2582
2747
|
|
|
2583
|
-
<Dialog open={envDialogOpen} onOpenChange={setEnvDialogOpen}>
|
|
2584
|
-
<DialogContent className="max-h-[80vh] max-w-lg overflow-y-auto">
|
|
2585
|
-
<DialogHeader>
|
|
2586
|
-
<DialogTitle>项目环境变量</DialogTitle>
|
|
2587
|
-
<DialogDescription>
|
|
2588
|
-
管理当前项目所需的环境变量,供 MCP 和 Skills 使用。
|
|
2589
|
-
</DialogDescription>
|
|
2590
|
-
</DialogHeader>
|
|
2591
|
-
<ProjectEnvPanel projectPath={data.config.projectPath ?? null} />
|
|
2592
|
-
</DialogContent>
|
|
2593
|
-
</Dialog>
|
|
2594
|
-
|
|
2595
2748
|
<Dialog
|
|
2596
2749
|
open={removeMemberConfirm !== null}
|
|
2597
2750
|
onOpenChange={(open) => {
|
|
@@ -2770,14 +2923,72 @@ export const TeamDetailView = ({
|
|
|
2770
2923
|
{spawnStatusWatcher}
|
|
2771
2924
|
{teamAgentRuntimeWatcher}
|
|
2772
2925
|
{leadContextWatcher}
|
|
2773
|
-
|
|
2926
|
+
<div className="flex size-full flex-col overflow-hidden">
|
|
2927
|
+
<div className="min-h-0 flex-1 overflow-hidden">
|
|
2928
|
+
{renderBody()}
|
|
2929
|
+
</div>
|
|
2930
|
+
{/* Persistent terminal — survives data refreshes because it's outside renderBody() */}
|
|
2931
|
+
{teamName && teamName !== SYSTEM_MANAGER_TEAM_NAME && (
|
|
2932
|
+
<div className="shrink-0" style={{ height: terminalHeight }}>
|
|
2933
|
+
{/* Drag handle */}
|
|
2934
|
+
<div
|
|
2935
|
+
className="flex cursor-row-resize items-center justify-center border-t border-[var(--color-border)] py-0.5 transition-colors hover:bg-[var(--color-surface-raised)]"
|
|
2936
|
+
onMouseDown={(e) => {
|
|
2937
|
+
e.preventDefault();
|
|
2938
|
+
const startY = e.clientY;
|
|
2939
|
+
const startH = terminalHeight;
|
|
2940
|
+
const onMove = (ev: MouseEvent) => {
|
|
2941
|
+
const delta = startY - ev.clientY; // drag up = grow
|
|
2942
|
+
const next = Math.max(120, Math.min(800, startH + delta));
|
|
2943
|
+
setTerminalHeight(next);
|
|
2944
|
+
};
|
|
2945
|
+
const onUp = () => {
|
|
2946
|
+
window.removeEventListener('mousemove', onMove);
|
|
2947
|
+
window.removeEventListener('mouseup', onUp);
|
|
2948
|
+
};
|
|
2949
|
+
window.addEventListener('mousemove', onMove);
|
|
2950
|
+
window.addEventListener('mouseup', onUp);
|
|
2951
|
+
}}
|
|
2952
|
+
>
|
|
2953
|
+
<div className="h-1 w-8 rounded-full bg-[var(--color-border)]" />
|
|
2954
|
+
</div>
|
|
2955
|
+
<div className="h-[calc(100%-14px)] overflow-hidden">
|
|
2956
|
+
<div className="flex items-center justify-between px-1 pb-1">
|
|
2957
|
+
<div className="flex items-center gap-1.5 text-xs font-medium text-[var(--color-text-secondary)]">
|
|
2958
|
+
<Terminal size={14} />
|
|
2959
|
+
终端
|
|
2960
|
+
</div>
|
|
2961
|
+
<button
|
|
2962
|
+
type="button"
|
|
2963
|
+
className="flex items-center gap-1 rounded px-1 py-0.5 text-[10px] text-[var(--color-text-muted)] transition-colors hover:bg-[var(--color-surface-raised)] hover:text-[var(--color-text-secondary)]"
|
|
2964
|
+
onClick={() => {
|
|
2965
|
+
const cwd = data?.config.projectPath || data?.config.executionTarget?.cwd || data?.workDir || '';
|
|
2966
|
+
const harness = data?.config.agentType || data?.harness;
|
|
2967
|
+
void api.terminal.openExternal({ command: getCommandForHarness(harness), cwd });
|
|
2968
|
+
}}
|
|
2969
|
+
>
|
|
2970
|
+
<Play size={10} />
|
|
2971
|
+
外部终端
|
|
2972
|
+
</button>
|
|
2973
|
+
</div>
|
|
2974
|
+
<div className="h-[calc(100%-22px)] overflow-hidden rounded-lg border border-[var(--color-border-subtle)]">
|
|
2975
|
+
<TerminalPane ref={terminalPaneRef} />
|
|
2976
|
+
</div>
|
|
2977
|
+
</div>
|
|
2978
|
+
</div>
|
|
2979
|
+
)}
|
|
2980
|
+
</div>
|
|
2981
|
+
{data && teamName !== SYSTEM_MANAGER_TEAM_NAME ? (
|
|
2982
|
+
<RuntimeConfigDialog
|
|
2983
|
+
open={bindingDialogOpen}
|
|
2984
|
+
teamName={teamName}
|
|
2985
|
+
onClose={() => setBindingDialogOpen(false)}
|
|
2986
|
+
/>
|
|
2987
|
+
) : null}
|
|
2774
2988
|
<EditTeamDialog
|
|
2775
2989
|
open={editDialogOpen}
|
|
2776
2990
|
teamName={teamName}
|
|
2777
2991
|
onClose={() => setEditDialogOpen(false)}
|
|
2778
|
-
onDeleteTeam={
|
|
2779
|
-
teamName !== 'default' && teamName !== 'my-project' ? handleDeleteTeam : undefined
|
|
2780
|
-
}
|
|
2781
2992
|
/>
|
|
2782
2993
|
</>
|
|
2783
2994
|
);
|