@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
|
@@ -607,55 +607,22 @@ export const MemberCard = ({
|
|
|
607
607
|
className="shrink-0"
|
|
608
608
|
title={totalTasks > 0 ? `${completed}/${totalTasks} completed` : undefined}
|
|
609
609
|
>
|
|
610
|
-
<Badge
|
|
611
|
-
variant="secondary"
|
|
612
|
-
className="shrink-0 px-1.5 py-0.5 text-[10px] font-normal leading-none"
|
|
613
|
-
>
|
|
614
|
-
{member.taskCount} {member.taskCount === 1 ? 'task' : 'tasks'}
|
|
615
|
-
</Badge>
|
|
616
610
|
{totalTasks > 0 && (
|
|
617
|
-
|
|
618
|
-
<
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
/>
|
|
622
|
-
</div>
|
|
623
|
-
)}
|
|
624
|
-
{/* NOTE: lead context bar disabled — usage formula is inaccurate */}
|
|
625
|
-
</div>
|
|
626
|
-
)}
|
|
627
|
-
{!isRemoved && (
|
|
628
|
-
<div className="flex shrink-0 items-center gap-0.5">
|
|
629
|
-
<Tooltip>
|
|
630
|
-
<TooltipTrigger asChild>
|
|
631
|
-
<button
|
|
632
|
-
type="button"
|
|
633
|
-
className="rounded p-1 text-[var(--color-text-muted)] transition-colors hover:bg-[var(--color-surface)] hover:text-[var(--color-text)]"
|
|
634
|
-
onClick={(e) => {
|
|
635
|
-
e.stopPropagation();
|
|
636
|
-
onSendMessage?.();
|
|
637
|
-
}}
|
|
638
|
-
>
|
|
639
|
-
<MessageSquare size={13} />
|
|
640
|
-
</button>
|
|
641
|
-
</TooltipTrigger>
|
|
642
|
-
<TooltipContent side="bottom">发送消息</TooltipContent>
|
|
643
|
-
</Tooltip>
|
|
644
|
-
<Tooltip>
|
|
645
|
-
<TooltipTrigger asChild>
|
|
646
|
-
<button
|
|
647
|
-
type="button"
|
|
648
|
-
className="rounded p-1 text-[var(--color-text-muted)] transition-colors hover:bg-[var(--color-surface)] hover:text-[var(--color-text)]"
|
|
649
|
-
onClick={(e) => {
|
|
650
|
-
e.stopPropagation();
|
|
651
|
-
onAssignTask?.();
|
|
652
|
-
}}
|
|
611
|
+
<>
|
|
612
|
+
<Badge
|
|
613
|
+
variant="secondary"
|
|
614
|
+
className="shrink-0 px-1.5 py-0.5 text-[10px] font-normal leading-none"
|
|
653
615
|
>
|
|
654
|
-
|
|
655
|
-
</
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
616
|
+
{completed}/{totalTasks}
|
|
617
|
+
</Badge>
|
|
618
|
+
<div className="mx-0.5 mt-0.5 h-[2px] rounded-full bg-[var(--color-border)]">
|
|
619
|
+
<div
|
|
620
|
+
className="h-full rounded-full bg-emerald-500 transition-all duration-500"
|
|
621
|
+
style={{ width: `${progressPercent}%` }}
|
|
622
|
+
/>
|
|
623
|
+
</div>
|
|
624
|
+
</>
|
|
625
|
+
)}
|
|
659
626
|
</div>
|
|
660
627
|
)}
|
|
661
628
|
</div>
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { useEffect, useMemo, useState } from 'react';
|
|
2
2
|
|
|
3
|
-
import { Button } from '@renderer/components/ui/button';
|
|
4
3
|
import { Dialog, DialogContent, DialogFooter, DialogHeader } from '@renderer/components/ui/dialog';
|
|
5
|
-
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@renderer/components/ui/tabs';
|
|
6
4
|
import { useMemberStats } from '@renderer/hooks/useMemberStats';
|
|
7
|
-
import { useStore } from '@renderer/store';
|
|
8
|
-
import { selectMemberMessagesForTeamMember } from '@renderer/store/slices/teamSlice';
|
|
9
5
|
import {
|
|
10
6
|
buildMemberLaunchDiagnosticsPayload,
|
|
11
7
|
getMemberLaunchDiagnosticsErrorMessage,
|
|
@@ -17,16 +13,10 @@ import {
|
|
|
17
13
|
resolveMemberRuntimeSummary,
|
|
18
14
|
} from '@renderer/utils/memberRuntimeSummary';
|
|
19
15
|
import { isLeadMember } from '@shared/utils/leadDetection';
|
|
20
|
-
import { BarChart3, FolderOpen, Loader2 } from 'lucide-react';
|
|
21
16
|
|
|
22
|
-
import { buildMemberActivityEntries } from './memberActivityEntries';
|
|
23
17
|
import { MemberDetailHeader } from './MemberDetailHeader';
|
|
24
18
|
import { MemberDetailStats } from './MemberDetailStats';
|
|
25
|
-
import { type MemberActivityFilter, type MemberDetailTab } from './memberDetailTypes';
|
|
26
19
|
import { MemberLaunchDiagnosticsButton } from './MemberLaunchDiagnosticsButton';
|
|
27
|
-
import { MemberMessagesTab } from './MemberMessagesTab';
|
|
28
|
-
import { MemberStatsTab } from './MemberStatsTab';
|
|
29
|
-
import { MemberWorkspaceTab } from './MemberWorkspaceTab';
|
|
30
20
|
|
|
31
21
|
import type { TeamLaunchParams } from '@renderer/store/slices/teamSlice';
|
|
32
22
|
import type {
|
|
@@ -43,8 +33,6 @@ interface MemberDetailDialogProps {
|
|
|
43
33
|
teamName: string;
|
|
44
34
|
members: ResolvedTeamMember[];
|
|
45
35
|
tasks: TeamTaskWithKanban[];
|
|
46
|
-
initialTab?: MemberDetailTab;
|
|
47
|
-
initialActivityFilter?: MemberActivityFilter;
|
|
48
36
|
isTeamAlive?: boolean;
|
|
49
37
|
isTeamProvisioning?: boolean;
|
|
50
38
|
isLaunchSettling?: boolean;
|
|
@@ -72,8 +60,6 @@ export const MemberDetailDialog = ({
|
|
|
72
60
|
teamName,
|
|
73
61
|
members,
|
|
74
62
|
tasks,
|
|
75
|
-
initialTab = 'tasks',
|
|
76
|
-
initialActivityFilter = 'all',
|
|
77
63
|
isTeamAlive,
|
|
78
64
|
isTeamProvisioning,
|
|
79
65
|
isLaunchSettling,
|
|
@@ -90,25 +76,6 @@ export const MemberDetailDialog = ({
|
|
|
90
76
|
updatingRole,
|
|
91
77
|
onViewMemberChanges,
|
|
92
78
|
}: MemberDetailDialogProps): React.JSX.Element | null => {
|
|
93
|
-
const memberMessages = useStore((state) =>
|
|
94
|
-
selectMemberMessagesForTeamMember(state, teamName, member?.name ?? null)
|
|
95
|
-
);
|
|
96
|
-
const memberActivityCount = useMemo(() => {
|
|
97
|
-
if (!member) {
|
|
98
|
-
return 0;
|
|
99
|
-
}
|
|
100
|
-
return buildMemberActivityEntries({
|
|
101
|
-
teamName,
|
|
102
|
-
memberName: member.name,
|
|
103
|
-
members,
|
|
104
|
-
tasks,
|
|
105
|
-
messages: memberMessages,
|
|
106
|
-
}).length;
|
|
107
|
-
}, [member, memberMessages, members, tasks, teamName]);
|
|
108
|
-
|
|
109
|
-
const [activeTab, setActiveTab] = useState<MemberDetailTab>(
|
|
110
|
-
initialTab === 'tasks' ? 'workspace' : initialTab
|
|
111
|
-
);
|
|
112
79
|
const [restarting, setRestarting] = useState(false);
|
|
113
80
|
const [restartError, setRestartError] = useState<string | null>(null);
|
|
114
81
|
|
|
@@ -149,10 +116,9 @@ export const MemberDetailDialog = ({
|
|
|
149
116
|
if (!open || !member) {
|
|
150
117
|
return;
|
|
151
118
|
}
|
|
152
|
-
setActiveTab(initialTab);
|
|
153
119
|
setRestartError(null);
|
|
154
120
|
setRestarting(false);
|
|
155
|
-
}, [
|
|
121
|
+
}, [member, open]);
|
|
156
122
|
|
|
157
123
|
const {
|
|
158
124
|
stats: memberStats,
|
|
@@ -160,8 +126,6 @@ export const MemberDetailDialog = ({
|
|
|
160
126
|
error: statsError,
|
|
161
127
|
} = useMemberStats(teamName, member?.name ?? null);
|
|
162
128
|
|
|
163
|
-
const totalTokens = memberStats ? memberStats.inputTokens + memberStats.outputTokens : null;
|
|
164
|
-
|
|
165
129
|
if (!member) return null;
|
|
166
130
|
|
|
167
131
|
return (
|
|
@@ -189,68 +153,12 @@ export const MemberDetailDialog = ({
|
|
|
189
153
|
</DialogHeader>
|
|
190
154
|
|
|
191
155
|
<MemberDetailStats
|
|
192
|
-
|
|
193
|
-
inProgressTasks={0}
|
|
194
|
-
totalTokens={totalTokens}
|
|
156
|
+
stats={memberStats}
|
|
195
157
|
statsLoading={statsLoading}
|
|
196
|
-
|
|
197
|
-
onTabChange={setActiveTab}
|
|
158
|
+
statsError={statsError}
|
|
198
159
|
/>
|
|
199
160
|
</div>
|
|
200
161
|
|
|
201
|
-
<Tabs
|
|
202
|
-
value={activeTab}
|
|
203
|
-
onValueChange={(v) => setActiveTab(v as MemberDetailTab)}
|
|
204
|
-
className="min-w-0 overflow-hidden"
|
|
205
|
-
>
|
|
206
|
-
<TabsList className="w-full">
|
|
207
|
-
<TabsTrigger value="workspace" className="flex-1 gap-1.5">
|
|
208
|
-
<FolderOpen size={12} />
|
|
209
|
-
Workspace
|
|
210
|
-
</TabsTrigger>
|
|
211
|
-
<TabsTrigger value="activity" className="flex-1 gap-1.5">
|
|
212
|
-
Activity
|
|
213
|
-
{memberActivityCount > 0 && (
|
|
214
|
-
<span className="rounded-full bg-[var(--color-surface)] px-1.5 text-[10px]">
|
|
215
|
-
{memberActivityCount}
|
|
216
|
-
</span>
|
|
217
|
-
)}
|
|
218
|
-
</TabsTrigger>
|
|
219
|
-
<TabsTrigger value="stats" className="flex-1 gap-1.5">
|
|
220
|
-
<BarChart3 size={12} />
|
|
221
|
-
Stats
|
|
222
|
-
</TabsTrigger>
|
|
223
|
-
</TabsList>
|
|
224
|
-
<TabsContent value="workspace">
|
|
225
|
-
<MemberWorkspaceTab
|
|
226
|
-
teamName={teamName}
|
|
227
|
-
memberName={member.name}
|
|
228
|
-
onFileClick={(filePath) => onViewMemberChanges?.(member.name, filePath)}
|
|
229
|
-
onViewAllChanges={() => onViewMemberChanges?.(member.name)}
|
|
230
|
-
/>
|
|
231
|
-
</TabsContent>
|
|
232
|
-
<TabsContent value="activity">
|
|
233
|
-
<MemberMessagesTab
|
|
234
|
-
teamName={teamName}
|
|
235
|
-
memberName={member.name}
|
|
236
|
-
members={members}
|
|
237
|
-
tasks={tasks}
|
|
238
|
-
initialFilter={initialActivityFilter}
|
|
239
|
-
/>
|
|
240
|
-
</TabsContent>
|
|
241
|
-
<TabsContent value="stats">
|
|
242
|
-
<MemberStatsTab
|
|
243
|
-
teamName={teamName}
|
|
244
|
-
memberName={member.name}
|
|
245
|
-
prefetchedStats={memberStats}
|
|
246
|
-
prefetchedLoading={statsLoading}
|
|
247
|
-
prefetchedError={statsError}
|
|
248
|
-
onFileClick={(filePath) => onViewMemberChanges?.(member.name, filePath)}
|
|
249
|
-
onShowAllFiles={() => onViewMemberChanges?.(member.name)}
|
|
250
|
-
/>
|
|
251
|
-
</TabsContent>
|
|
252
|
-
</Tabs>
|
|
253
|
-
|
|
254
162
|
<DialogFooter>
|
|
255
163
|
{restartError ? (
|
|
256
164
|
<div className="text-xs text-red-400">{restartError}</div>
|
|
@@ -1,80 +1,65 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { formatDuration, formatTokensCompact } from '@renderer/utils/formatters';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { MemberFullStats } from '@shared/types';
|
|
4
4
|
|
|
5
5
|
interface MemberDetailStatsProps {
|
|
6
|
-
|
|
7
|
-
inProgressTasks: number;
|
|
8
|
-
totalTokens: number | null;
|
|
6
|
+
stats: MemberFullStats | null;
|
|
9
7
|
statsLoading?: boolean;
|
|
10
|
-
|
|
11
|
-
onTabChange?: (tab: MemberDetailTab) => void;
|
|
8
|
+
statsError?: string | null;
|
|
12
9
|
}
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}: {
|
|
25
|
-
label: string;
|
|
26
|
-
value: string | number;
|
|
27
|
-
sub?: string;
|
|
28
|
-
onClick?: () => void;
|
|
29
|
-
}): React.JSX.Element => {
|
|
30
|
-
const classes = onClick ? `${baseClasses} ${clickableClasses}` : baseClasses;
|
|
31
|
-
const content = (
|
|
32
|
-
<>
|
|
33
|
-
<p className="text-base font-semibold leading-tight text-[var(--color-text)]">{value}</p>
|
|
34
|
-
<p className="text-[10px] text-[var(--color-text-muted)]">{label}</p>
|
|
35
|
-
{sub && <p className="mt-0.5 text-[9px] text-[var(--color-text-muted)]">{sub}</p>}
|
|
36
|
-
</>
|
|
37
|
-
);
|
|
38
|
-
if (onClick) {
|
|
39
|
-
return (
|
|
40
|
-
<button type="button" className={classes} onClick={onClick}>
|
|
41
|
-
{content}
|
|
42
|
-
</button>
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
return <div className={classes}>{content}</div>;
|
|
46
|
-
};
|
|
11
|
+
function formatDurationShort(ms: number): string {
|
|
12
|
+
if (ms < 60_000) return `${Math.round(ms / 1000)}s`;
|
|
13
|
+
const minutes = Math.floor(ms / 60_000);
|
|
14
|
+
if (minutes < 60) return `${minutes}m`;
|
|
15
|
+
const hours = Math.floor(minutes / 60);
|
|
16
|
+
const remainMin = minutes % 60;
|
|
17
|
+
if (hours < 24) return `${hours}h ${remainMin}m`;
|
|
18
|
+
const days = Math.floor(hours / 24);
|
|
19
|
+
return `${days}d ${hours % 24}h`;
|
|
20
|
+
}
|
|
47
21
|
|
|
48
22
|
export const MemberDetailStats = ({
|
|
49
|
-
|
|
50
|
-
inProgressTasks,
|
|
51
|
-
totalTokens,
|
|
23
|
+
stats,
|
|
52
24
|
statsLoading,
|
|
53
|
-
statsComputedAt,
|
|
54
|
-
onTabChange,
|
|
55
25
|
}: MemberDetailStatsProps): React.JSX.Element => {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
: '
|
|
61
|
-
|
|
62
|
-
|
|
26
|
+
const totalTokens = stats ? stats.inputTokens + stats.outputTokens : 0;
|
|
27
|
+
|
|
28
|
+
const items = [
|
|
29
|
+
{
|
|
30
|
+
label: 'Sessions',
|
|
31
|
+
value: statsLoading ? '...' : String(stats?.sessionCount ?? 0),
|
|
32
|
+
sub: !statsLoading && stats ? `${stats.messageCount} messages` : undefined,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: 'Tokens',
|
|
36
|
+
value: statsLoading ? '...' : formatTokensCompact(totalTokens),
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
label: 'Duration',
|
|
40
|
+
value: statsLoading ? '...' : stats?.totalDurationMs ? formatDurationShort(stats.totalDurationMs) : '—',
|
|
41
|
+
sub: !statsLoading && stats?.tasksCompleted ? `${stats.tasksCompleted} completed` : undefined,
|
|
42
|
+
},
|
|
43
|
+
];
|
|
63
44
|
|
|
64
45
|
return (
|
|
65
|
-
<div className="grid min-w-0 flex-1 grid-cols-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
46
|
+
<div className="grid min-w-0 flex-1 grid-cols-3 gap-1.5">
|
|
47
|
+
{items.map((item) => (
|
|
48
|
+
<div
|
|
49
|
+
key={item.label}
|
|
50
|
+
className="rounded-md border border-[var(--color-border)] bg-[var(--color-surface-raised)] px-2.5 py-1.5"
|
|
51
|
+
>
|
|
52
|
+
<div className="flex items-baseline gap-1.5">
|
|
53
|
+
<span className="text-sm font-semibold tabular-nums text-[var(--color-text)]">
|
|
54
|
+
{item.value}
|
|
55
|
+
</span>
|
|
56
|
+
<span className="text-[10px] text-[var(--color-text-muted)]">{item.label}</span>
|
|
57
|
+
</div>
|
|
58
|
+
{item.sub && (
|
|
59
|
+
<span className="block text-[9px] text-[var(--color-text-muted)]">{item.sub}</span>
|
|
60
|
+
)}
|
|
61
|
+
</div>
|
|
62
|
+
))}
|
|
78
63
|
</div>
|
|
79
64
|
);
|
|
80
65
|
};
|
|
@@ -33,14 +33,12 @@ import {
|
|
|
33
33
|
normalizeOptionalTeamProviderId,
|
|
34
34
|
} from '@shared/utils/teamProvider';
|
|
35
35
|
import { AlertCircle, Check, ChevronDown, Mic, Paperclip, Search, Send } from 'lucide-react';
|
|
36
|
-
import { useShallow } from 'zustand/react/shallow';
|
|
37
36
|
|
|
38
37
|
import type { MentionSuggestion } from '@renderer/types/mention';
|
|
39
38
|
import type { OpenCodeRuntimeDeliveryDebugDetails } from '@renderer/utils/openCodeRuntimeDeliveryDiagnostics';
|
|
40
39
|
import type {
|
|
41
40
|
AgentActionMode,
|
|
42
41
|
AttachmentPayload,
|
|
43
|
-
CcSession,
|
|
44
42
|
ResolvedTeamMember,
|
|
45
43
|
SendMessageResult,
|
|
46
44
|
TaskRef,
|
|
@@ -56,9 +54,6 @@ interface MessageComposerProps {
|
|
|
56
54
|
sendWarning?: string | null;
|
|
57
55
|
sendDebugDetails?: OpenCodeRuntimeDeliveryDebugDetails | null;
|
|
58
56
|
lastResult?: SendMessageResult | null;
|
|
59
|
-
sessions?: CcSession[];
|
|
60
|
-
selectedSessionKey?: string | null;
|
|
61
|
-
onSessionChange?: (sessionKey: string | null) => void;
|
|
62
57
|
/** Ref to the underlying textarea element for external focus management. */
|
|
63
58
|
textareaRef?: React.Ref<HTMLTextAreaElement>;
|
|
64
59
|
onSend: (
|
|
@@ -86,9 +81,6 @@ export const MessageComposer = ({
|
|
|
86
81
|
sendWarning,
|
|
87
82
|
sendDebugDetails,
|
|
88
83
|
lastResult,
|
|
89
|
-
sessions = [],
|
|
90
|
-
selectedSessionKey = null,
|
|
91
|
-
onSessionChange,
|
|
92
84
|
textareaRef: externalTextareaRef,
|
|
93
85
|
onSend,
|
|
94
86
|
onDispatchTask,
|
|
@@ -118,7 +110,6 @@ export const MessageComposer = ({
|
|
|
118
110
|
const [fileRestrictionError, setFileRestrictionError] = useState<string | null>(null);
|
|
119
111
|
const fileRestrictionTimerRef = useRef(0);
|
|
120
112
|
const dismissMentionsRef = useRef<(() => void) | null>(null);
|
|
121
|
-
const [teamSelectorOpen, setTeamSelectorOpen] = useState(false);
|
|
122
113
|
|
|
123
114
|
// Members load async with team data; keep recipient stable if valid, otherwise default to lead/first.
|
|
124
115
|
useEffect(() => {
|
|
@@ -135,6 +126,9 @@ export const MessageComposer = ({
|
|
|
135
126
|
const projectPath = useStore((s) =>
|
|
136
127
|
s.selectedTeamName === teamName ? (s.selectedTeamData?.config.projectPath ?? null) : null
|
|
137
128
|
);
|
|
129
|
+
const skillsUserCatalog = useStore((s) => s.skillsUserCatalog);
|
|
130
|
+
const skillsProjectCatalogByProjectPath = useStore((s) => s.skillsProjectCatalogByProjectPath);
|
|
131
|
+
const fetchSkillsCatalog = useStore((s) => s.fetchSkillsCatalog);
|
|
138
132
|
const currentTeamColor = useStore((s) => {
|
|
139
133
|
if (s.selectedTeamName !== teamName) {
|
|
140
134
|
return nameColorSet(teamName).border;
|
|
@@ -146,17 +140,6 @@ export const MessageComposer = ({
|
|
|
146
140
|
});
|
|
147
141
|
const isProvisioning = useStore((s) => isTeamProvisioningActive(s, teamName));
|
|
148
142
|
const draft = useComposerDraft(teamName);
|
|
149
|
-
const selectedSession = useMemo(
|
|
150
|
-
() => sessions.find((session) => session.sessionKey === selectedSessionKey) ?? null,
|
|
151
|
-
[selectedSessionKey, sessions]
|
|
152
|
-
);
|
|
153
|
-
const selectedSessionLabel =
|
|
154
|
-
selectedSession?.chatName ||
|
|
155
|
-
selectedSession?.title ||
|
|
156
|
-
selectedSession?.userName ||
|
|
157
|
-
selectedSession?.sessionKey ||
|
|
158
|
-
'选择会话';
|
|
159
|
-
|
|
160
143
|
const colorMap = useMemo(() => buildMemberColorMap(members), [members]);
|
|
161
144
|
|
|
162
145
|
const mentionSuggestions = useMemo<MentionSuggestion[]>(
|
|
@@ -176,29 +159,22 @@ export const MessageComposer = ({
|
|
|
176
159
|
);
|
|
177
160
|
}, [members]);
|
|
178
161
|
|
|
179
|
-
const { suggestions: teamMentionSuggestions } = useTeamSuggestions(teamName);
|
|
180
|
-
const { suggestions: taskSuggestions } = useTaskSuggestions(teamName);
|
|
181
|
-
// Project skills as slash command suggestions
|
|
182
|
-
const projectSkills = useStore(
|
|
183
|
-
useShallow((s) => (projectPath ? (s.skillsProjectCatalogByProjectPath[projectPath] ?? []) : []))
|
|
184
|
-
);
|
|
185
|
-
const userSkills = useStore(useShallow((s) => s.skillsUserCatalog));
|
|
186
|
-
const fetchSkillsCatalog = useStore((s) => s.fetchSkillsCatalog);
|
|
187
|
-
|
|
188
|
-
// Fetch skills catalog for the team's project on mount / project change
|
|
189
162
|
useEffect(() => {
|
|
190
163
|
void fetchSkillsCatalog(projectPath ?? undefined);
|
|
191
164
|
}, [fetchSkillsCatalog, projectPath]);
|
|
192
165
|
|
|
166
|
+
const { suggestions: teamMentionSuggestions } = useTeamSuggestions(teamName);
|
|
167
|
+
const { suggestions: taskSuggestions } = useTaskSuggestions(teamName);
|
|
168
|
+
const projectSkills = projectPath ? (skillsProjectCatalogByProjectPath[projectPath] ?? []) : [];
|
|
193
169
|
const slashCommandSuggestions = useMemo<MentionSuggestion[]>(
|
|
194
170
|
() =>
|
|
195
171
|
buildSlashCommandSuggestions(
|
|
196
172
|
getSuggestedSlashCommandsForProvider(leadProviderId),
|
|
197
173
|
projectSkills,
|
|
198
|
-
|
|
174
|
+
skillsUserCatalog,
|
|
199
175
|
leadProviderId
|
|
200
176
|
),
|
|
201
|
-
[leadProviderId, projectSkills,
|
|
177
|
+
[leadProviderId, projectSkills, skillsUserCatalog]
|
|
202
178
|
);
|
|
203
179
|
|
|
204
180
|
const trimmed = stripEncodedTaskReferenceMetadata(draft.text).trim();
|
|
@@ -473,84 +449,6 @@ export const MessageComposer = ({
|
|
|
473
449
|
'border-[var(--color-border)]'
|
|
474
450
|
)}
|
|
475
451
|
>
|
|
476
|
-
<Popover open={teamSelectorOpen} onOpenChange={setTeamSelectorOpen}>
|
|
477
|
-
<PopoverTrigger asChild>
|
|
478
|
-
<button
|
|
479
|
-
type="button"
|
|
480
|
-
className={cn(
|
|
481
|
-
'inline-flex items-center gap-1.5 border-r border-r-[var(--color-border)] px-2.5 py-1 text-xs transition-colors',
|
|
482
|
-
shouldDockRecipientSelector
|
|
483
|
-
? 'rounded-bl-none rounded-tl-[1.35rem]'
|
|
484
|
-
: 'rounded-l-full',
|
|
485
|
-
'hover:bg-[var(--color-surface-raised)]'
|
|
486
|
-
)}
|
|
487
|
-
>
|
|
488
|
-
{currentTeamColor ? (
|
|
489
|
-
<span
|
|
490
|
-
className="inline-block size-2 shrink-0 rounded-full"
|
|
491
|
-
style={{ backgroundColor: currentTeamColor }}
|
|
492
|
-
/>
|
|
493
|
-
) : null}
|
|
494
|
-
<span className="max-w-[120px] truncate text-[var(--color-text-secondary)]">
|
|
495
|
-
{selectedSessionLabel}
|
|
496
|
-
</span>
|
|
497
|
-
<ChevronDown size={12} className="shrink-0 text-[var(--color-text-muted)]" />
|
|
498
|
-
</button>
|
|
499
|
-
</PopoverTrigger>
|
|
500
|
-
<PopoverContent align="end" className="w-56 p-1.5">
|
|
501
|
-
<div className="max-h-48 space-y-0.5 overflow-y-auto">
|
|
502
|
-
{sessions.length > 0 && (
|
|
503
|
-
<>
|
|
504
|
-
<div className="px-2 py-1 text-[10px] font-medium uppercase tracking-wide text-[var(--color-text-muted)]">
|
|
505
|
-
会话
|
|
506
|
-
</div>
|
|
507
|
-
{sessions.map((session) => {
|
|
508
|
-
const isSelected = selectedSessionKey === session.sessionKey;
|
|
509
|
-
const label =
|
|
510
|
-
session.chatName ||
|
|
511
|
-
session.title ||
|
|
512
|
-
session.userName ||
|
|
513
|
-
session.sessionKey;
|
|
514
|
-
return (
|
|
515
|
-
<button
|
|
516
|
-
key={session.sessionKey}
|
|
517
|
-
type="button"
|
|
518
|
-
className={cn(
|
|
519
|
-
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-xs transition-colors hover:bg-[var(--color-surface-raised)]',
|
|
520
|
-
isSelected && 'bg-[var(--color-surface-raised)]'
|
|
521
|
-
)}
|
|
522
|
-
onClick={() => {
|
|
523
|
-
onSessionChange?.(session.sessionKey);
|
|
524
|
-
setTeamSelectorOpen(false);
|
|
525
|
-
}}
|
|
526
|
-
>
|
|
527
|
-
<span
|
|
528
|
-
className={cn(
|
|
529
|
-
'inline-block size-2 shrink-0 rounded-full',
|
|
530
|
-
session.live && 'animate-pulse'
|
|
531
|
-
)}
|
|
532
|
-
style={{
|
|
533
|
-
backgroundColor: session.live ? '#22c55e' : currentTeamColor,
|
|
534
|
-
}}
|
|
535
|
-
/>
|
|
536
|
-
<span className="min-w-0 flex-1 truncate text-[var(--color-text)]">
|
|
537
|
-
{label}
|
|
538
|
-
</span>
|
|
539
|
-
<span className="shrink-0 text-[10px] text-[var(--color-text-muted)]">
|
|
540
|
-
{session.platform}
|
|
541
|
-
</span>
|
|
542
|
-
{isSelected ? (
|
|
543
|
-
<Check size={12} className="ml-auto shrink-0 text-blue-400" />
|
|
544
|
-
) : null}
|
|
545
|
-
</button>
|
|
546
|
-
);
|
|
547
|
-
})}
|
|
548
|
-
</>
|
|
549
|
-
)}
|
|
550
|
-
</div>
|
|
551
|
-
</PopoverContent>
|
|
552
|
-
</Popover>
|
|
553
|
-
|
|
554
452
|
<Popover open={recipientOpen} onOpenChange={setRecipientOpen}>
|
|
555
453
|
<PopoverTrigger asChild>
|
|
556
454
|
<button
|