@yancyyu/openhermit 1.6.38 → 1.6.40
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-CemDOX-3.js +58 -0
- package/dist-renderer/assets/{TeamGraphOverlay-ZEDfZyHb.js → TeamGraphOverlay-hPY770Db.js} +1 -1
- package/dist-renderer/assets/{_basePickBy-CIhniz70.js → _basePickBy-BHHrJT1i.js} +1 -1
- package/dist-renderer/assets/{_baseUniq-cKAW4Q8I.js → _baseUniq-CWErBtke.js} +1 -1
- package/dist-renderer/assets/{arc-YmNsoDXW.js → arc-C_o2_Uv8.js} +1 -1
- package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-DHEls2sX.js → architectureDiagram-VXUJARFQ-DUW0LI3t.js} +1 -1
- package/dist-renderer/assets/{blockDiagram-VD42YOAC-Bpwf1Sbg.js → blockDiagram-VD42YOAC-CWbCE9hQ.js} +1 -1
- package/dist-renderer/assets/{c4Diagram-YG6GDRKO-B0IaQ4w5.js → c4Diagram-YG6GDRKO-BjLadrfV.js} +1 -1
- package/dist-renderer/assets/channel-DyP9YlCF.js +1 -0
- package/dist-renderer/assets/{chunk-4BX2VUAB-DLk-hcFc.js → chunk-4BX2VUAB-CPnvjZl9.js} +1 -1
- package/dist-renderer/assets/{chunk-55IACEB6-1XRmX_Zm.js → chunk-55IACEB6-OlL47yXQ.js} +1 -1
- package/dist-renderer/assets/{chunk-B4BG7PRW-1waH1DAD.js → chunk-B4BG7PRW-DTasjbm8.js} +1 -1
- package/dist-renderer/assets/{chunk-DI55MBZ5-BqpZBtrN.js → chunk-DI55MBZ5-C5_Xaqkk.js} +1 -1
- package/dist-renderer/assets/{chunk-FMBD7UC4-Bly7vVym.js → chunk-FMBD7UC4-NdoM4DMR.js} +1 -1
- package/dist-renderer/assets/{chunk-QN33PNHL-Ci2QWBAs.js → chunk-QN33PNHL-C8Fybejy.js} +1 -1
- package/dist-renderer/assets/{chunk-QZHKN3VN-YCqFW7d-.js → chunk-QZHKN3VN-E98TYFXJ.js} +1 -1
- package/dist-renderer/assets/{chunk-TZMSLE5B-B0xGXInl.js → chunk-TZMSLE5B-h4lFgkIq.js} +1 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-BqffFTae.js +1 -0
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-BqffFTae.js +1 -0
- package/dist-renderer/assets/clone-MPcKWs2O.js +1 -0
- package/dist-renderer/assets/{cose-bilkent-S5V4N54A-DxcFNQKT.js → cose-bilkent-S5V4N54A-DtQ7fkrs.js} +1 -1
- package/dist-renderer/assets/{dagre-6UL2VRFP-DPo_RfZY.js → dagre-6UL2VRFP-CN-nL_z4.js} +1 -1
- package/dist-renderer/assets/{diagram-PSM6KHXK-U3hQsFe4.js → diagram-PSM6KHXK-DVJtqmm-.js} +1 -1
- package/dist-renderer/assets/{diagram-QEK2KX5R-OrwrAy0V.js → diagram-QEK2KX5R-DlxHxyXh.js} +1 -1
- package/dist-renderer/assets/{diagram-S2PKOQOG-CXATPWVw.js → diagram-S2PKOQOG-7dpzO6x6.js} +1 -1
- package/dist-renderer/assets/{erDiagram-Q2GNP2WA-B0e8AfMF.js → erDiagram-Q2GNP2WA-GP1TqsHi.js} +1 -1
- package/dist-renderer/assets/{flowDiagram-NV44I4VS-CXfzA4jJ.js → flowDiagram-NV44I4VS-C7ZLETuH.js} +1 -1
- package/dist-renderer/assets/{ganttDiagram-JELNMOA3-CMr08qVl.js → ganttDiagram-JELNMOA3-CvPB68dH.js} +1 -1
- package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-vYFHpPmy.js → gitGraphDiagram-V2S2FVAM-B5yOm3w7.js} +1 -1
- package/dist-renderer/assets/{graph-DOe5j8dH.js → graph-smeyY1YZ.js} +1 -1
- package/dist-renderer/assets/{index-BySQS7AB.js → index-BJx8XvG1.js} +1 -1
- package/dist-renderer/assets/{index-C_okzZXP.js → index-CQaXUAua.js} +1 -1
- package/dist-renderer/assets/{index-VJ-MM9xa.js → index-CajRpxO2.js} +1 -1
- package/dist-renderer/assets/{index-V7dAKPqd.js → index-ChG4rE-E.js} +587 -705
- package/dist-renderer/assets/index-DUd0uw9C.css +32 -0
- package/dist-renderer/assets/{index-CzWxVCRL.js → index-IhmXZWqf.js} +1 -1
- package/dist-renderer/assets/{index-B2Dy7M2G.js → index-x_JkoDRH.js} +1 -1
- package/dist-renderer/assets/{infoDiagram-HS3SLOUP-D_WubR0B.js → infoDiagram-HS3SLOUP-D-hWRQGY.js} +1 -1
- package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-w9ca-1TI.js → journeyDiagram-XKPGCS4Q-Bb6W8rUG.js} +1 -1
- package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-Jg9p6_pN.js → kanban-definition-3W4ZIXB7-CnHdUX0q.js} +1 -1
- package/dist-renderer/assets/{layout-B-z3y17c.js → layout-pqss_zkI.js} +1 -1
- package/dist-renderer/assets/{linear-D-RTX5UW.js → linear-B1mFITNh.js} +1 -1
- package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-CDQmHOYP.js → mindmap-definition-VGOIOE7T-DTD9q7-D.js} +1 -1
- package/dist-renderer/assets/{pieDiagram-ADFJNKIX-D_odsQL7.js → pieDiagram-ADFJNKIX-Df3mhrn7.js} +1 -1
- package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-BRsmYWSA.js → quadrantDiagram-AYHSOK5B-B1FZ09vH.js} +1 -1
- package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-ChNE_BOV.js → requirementDiagram-UZGBJVZJ-aEO78thZ.js} +1 -1
- package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-C8FtpwKc.js → sankeyDiagram-TZEHDZUN-6Ui--jp-.js} +1 -1
- package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-DmLCzNcc.js → sequenceDiagram-WL72ISMW-DF4Q1cAM.js} +1 -1
- package/dist-renderer/assets/splashScene-D0YB9uxm.js +17 -0
- package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-WJBm4bhu.js → stateDiagram-FKZM4ZOC-BqA2BI8C.js} +1 -1
- package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-Cs2ZtUD2.js +1 -0
- package/dist-renderer/assets/{timeline-definition-IT6M3QCI-BXs_hOJs.js → timeline-definition-IT6M3QCI-DoOkw_A8.js} +1 -1
- package/dist-renderer/assets/{treemap-GDKQZRPO-o04MA0G9.js → treemap-GDKQZRPO-DUe26QdD.js} +1 -1
- package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-Czj69XRd.js → xychartDiagram-PRI3JC2R-BKCnj5Xn.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/chat/ChatHistoryItem.tsx +1 -1
- package/src/renderer/components/chat/items/SubagentItem.tsx +2 -2
- package/src/renderer/components/chat/viewers/MermaidDiagram.tsx +2 -2
- package/src/renderer/components/common/ErrorBoundary.tsx +1 -1
- package/src/renderer/components/common/TerminalPane.tsx +213 -0
- package/src/renderer/components/dashboard/CliStatusBanner.tsx +7 -7
- package/src/renderer/components/dashboard/DashboardView.tsx +9 -36
- package/src/renderer/components/extensions/ExtensionStoreView.tsx +7 -126
- package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +1 -1
- package/src/renderer/components/extensions/common/ExtensionToast.tsx +3 -3
- package/src/renderer/components/extensions/common/SourceBadge.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/CategoryChips.tsx +1 -1
- package/src/renderer/components/extensions/plugins/PluginCard.tsx +6 -6
- package/src/renderer/components/extensions/plugins/PluginDetailDialog.tsx +2 -2
- package/src/renderer/components/extensions/plugins/PluginsPanel.tsx +34 -21
- package/src/renderer/components/extensions/skills/SkillEditorDialog.tsx +1 -1
- package/src/renderer/components/extensions/skills/SkillsLibraryPanel.tsx +335 -0
- package/src/renderer/components/layout/PaneContent.tsx +8 -1
- package/src/renderer/components/layout/PaneResizeHandle.tsx +2 -2
- package/src/renderer/components/layout/Sidebar.tsx +13 -56
- package/src/renderer/components/layout/SortableTab.tsx +22 -33
- package/src/renderer/components/layout/TabBar.tsx +1 -1
- package/src/renderer/components/layout/TabContextMenu.tsx +1 -1
- package/src/renderer/components/report/sections/CostSection.tsx +2 -2
- package/src/renderer/components/report/sections/InsightsSection.tsx +1 -1
- package/src/renderer/components/runtime/ProviderRuntimeBackendSelector.tsx +2 -2
- 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/search/CommandPalette.tsx +4 -4
- 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 +72 -113
- 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/SessionFiltersPopover.tsx +1 -1
- package/src/renderer/components/sidebar/SessionItem.tsx +3 -3
- package/src/renderer/components/sidebar/SidebarSessions.tsx +184 -6
- package/src/renderer/components/sidebar/SidebarTaskItem.tsx +4 -4
- package/src/renderer/components/sidebar/WorkspaceBrowser.tsx +40 -5
- 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/ClaudeLogsFilterPopover.tsx +1 -1
- package/src/renderer/components/team/ClaudeLogsPanel.tsx +1 -1
- package/src/renderer/components/team/CollapsibleTeamSection.tsx +17 -32
- package/src/renderer/components/team/ProcessesSection.tsx +2 -2
- package/src/renderer/components/team/TaskTooltip.tsx +2 -2
- package/src/renderer/components/team/TeamDetailView.tsx +319 -123
- package/src/renderer/components/team/TeamListFilterPopover.tsx +1 -1
- package/src/renderer/components/team/TeamListView.tsx +109 -124
- package/src/renderer/components/team/TeamSessionsSection.tsx +6 -6
- package/src/renderer/components/team/UnreadCommentsBadge.tsx +1 -1
- package/src/renderer/components/team/activity/ActivityItem.tsx +9 -9
- package/src/renderer/components/team/activity/ActivityTimeline.tsx +5 -5
- package/src/renderer/components/team/activity/LeadThoughtsGroup.tsx +3 -3
- package/src/renderer/components/team/activity/ReplyQuoteBlock.tsx +4 -4
- package/src/renderer/components/team/dialogs/CreateTaskDialog.tsx +4 -4
- 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 +18 -16
- package/src/renderer/components/team/dialogs/PlatformBindingDialog.tsx +221 -0
- package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +8 -1
- package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +5 -5
- package/src/renderer/components/team/dialogs/RuntimeConfigDialog.tsx +361 -0
- package/src/renderer/components/team/dialogs/SendMessageDialog.tsx +6 -6
- package/src/renderer/components/team/dialogs/SkipPermissionsCheckbox.tsx +6 -6
- package/src/renderer/components/team/dialogs/StatusHistoryTimeline.tsx +1 -1
- package/src/renderer/components/team/dialogs/TaskAttachments.tsx +1 -1
- package/src/renderer/components/team/dialogs/TaskCommentInput.tsx +6 -6
- package/src/renderer/components/team/dialogs/TaskCommentsSection.tsx +4 -4
- package/src/renderer/components/team/dialogs/TaskDetailDialog.tsx +3 -3
- 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/editor/EditorFileTree.tsx +4 -4
- package/src/renderer/components/team/editor/EditorSearchPanel.tsx +1 -1
- package/src/renderer/components/team/editor/MarkdownSplitView.tsx +1 -1
- package/src/renderer/components/team/editor/NewFileDialog.tsx +1 -1
- package/src/renderer/components/team/editor/ProjectEditorOverlay.tsx +1 -1
- package/src/renderer/components/team/editor/SearchInFilesPanel.tsx +1 -1
- package/src/renderer/components/team/kanban/KanbanBoard.tsx +9 -9
- package/src/renderer/components/team/kanban/KanbanFilterPopover.tsx +4 -4
- package/src/renderer/components/team/kanban/KanbanSearchInput.tsx +1 -1
- package/src/renderer/components/team/kanban/KanbanSortPopover.tsx +5 -5
- package/src/renderer/components/team/kanban/KanbanTaskCard.tsx +4 -4
- 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/members/MemberDraftRow.tsx +1 -1
- package/src/renderer/components/team/members/MemberStatsTab.tsx +2 -2
- package/src/renderer/components/team/members/MemberWorkspaceTab.tsx +1 -1
- package/src/renderer/components/team/messages/MessageComposer.tsx +10 -112
- package/src/renderer/components/team/messages/MessagesFilterPopover.tsx +1 -1
- package/src/renderer/components/team/messages/MessagesPanel.tsx +136 -119
- package/src/renderer/components/team/review/ChangeReviewDialog.tsx +1 -1
- package/src/renderer/components/team/schedule/ScheduleStatusBadge.tsx +3 -3
- package/src/renderer/components/team/sidebar/TeamSidebarRail.tsx +4 -4
- package/src/renderer/components/team/tasks/TaskRow.tsx +1 -1
- 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 +3 -3
- package/src/renderer/components/team/tools/ToolsSection.tsx +418 -70
- package/src/renderer/components/ui/MemberSelect.tsx +2 -2
- package/src/renderer/components/ui/MentionSuggestionList.tsx +2 -2
- package/src/renderer/components/ui/MentionableTextarea.tsx +3 -3
- package/src/renderer/hooks/useExtensionsTabState.ts +3 -114
- package/src/renderer/index.css +56 -39
- 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
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SkillsLibraryPanel — global user skills library management.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { api } from '@renderer/api';
|
|
8
|
+
import { confirm } from '@renderer/components/common/ConfirmDialog';
|
|
9
|
+
import { Badge } from '@renderer/components/ui/badge';
|
|
10
|
+
import { Button } from '@renderer/components/ui/button';
|
|
11
|
+
import { useStore } from '@renderer/store';
|
|
12
|
+
import { formatSkillRootKind, getSkillAudienceLabel } from '@shared/utils/skillRoots';
|
|
13
|
+
import { AlertCircle, Edit, FileText, Plus, RefreshCw, Trash2 } from 'lucide-react';
|
|
14
|
+
|
|
15
|
+
import { SearchInput } from '../common/SearchInput';
|
|
16
|
+
|
|
17
|
+
import { SkillEditorDialog } from './SkillEditorDialog';
|
|
18
|
+
|
|
19
|
+
import type { SkillCatalogItem, SkillDetail } from '@shared/types/extensions';
|
|
20
|
+
|
|
21
|
+
interface SkillsLibraryPanelProps {
|
|
22
|
+
projectPath: string | null;
|
|
23
|
+
projectLabel: string | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type EditorState =
|
|
27
|
+
| { mode: 'create'; detail: null }
|
|
28
|
+
| { mode: 'edit'; detail: SkillDetail | null; skillId: string };
|
|
29
|
+
|
|
30
|
+
function formatScope(scope: SkillCatalogItem['scope']): string {
|
|
31
|
+
return scope === 'project' ? '项目' : '个人';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function formatInvocationMode(mode: SkillCatalogItem['invocationMode']): string {
|
|
35
|
+
return mode === 'manual-only' ? '手动调用' : '自动触发';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function matchesSearch(skill: SkillCatalogItem, query: string): boolean {
|
|
39
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
40
|
+
if (!normalizedQuery) return true;
|
|
41
|
+
|
|
42
|
+
return [skill.name, skill.description, skill.folderName, skill.rootKind, skill.scope]
|
|
43
|
+
.filter(Boolean)
|
|
44
|
+
.some((value) => value.toLowerCase().includes(normalizedQuery));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface SkillLibraryCardProps {
|
|
48
|
+
skill: SkillCatalogItem;
|
|
49
|
+
isLoadingDetail: boolean;
|
|
50
|
+
isDeleting: boolean;
|
|
51
|
+
onEdit: (skill: SkillCatalogItem) => void;
|
|
52
|
+
onDelete: (skill: SkillCatalogItem) => void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const SkillLibraryCard = ({
|
|
56
|
+
skill,
|
|
57
|
+
isLoadingDetail,
|
|
58
|
+
isDeleting,
|
|
59
|
+
onEdit,
|
|
60
|
+
onDelete,
|
|
61
|
+
}: SkillLibraryCardProps): React.JSX.Element => {
|
|
62
|
+
const statusBadge = skill.isValid ? (
|
|
63
|
+
<Badge className="border-emerald-500/30 bg-emerald-500/10 text-emerald-400" variant="outline">
|
|
64
|
+
可用
|
|
65
|
+
</Badge>
|
|
66
|
+
) : (
|
|
67
|
+
<Badge className="border-amber-500/30 bg-amber-500/10 text-amber-300" variant="outline">
|
|
68
|
+
需检查
|
|
69
|
+
</Badge>
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<div className="flex flex-col gap-3 rounded-xl border border-border bg-white/[0.025] p-4 transition-colors hover:border-border-emphasis hover:bg-white/[0.045]">
|
|
74
|
+
<div className="flex items-start justify-between gap-3">
|
|
75
|
+
<div className="min-w-0 space-y-1">
|
|
76
|
+
<div className="flex min-w-0 items-center gap-2">
|
|
77
|
+
<FileText className="size-4 shrink-0 text-text-muted" />
|
|
78
|
+
<h3 className="truncate text-sm font-semibold text-text">{skill.name}</h3>
|
|
79
|
+
</div>
|
|
80
|
+
<div className="flex flex-wrap items-center gap-1.5">
|
|
81
|
+
<Badge variant="secondary" className="text-[11px]">
|
|
82
|
+
{formatSkillRootKind(skill.rootKind)}
|
|
83
|
+
</Badge>
|
|
84
|
+
<Badge
|
|
85
|
+
variant="outline"
|
|
86
|
+
className="bg-surface-raised/60 border-border text-[11px] text-text-secondary"
|
|
87
|
+
>
|
|
88
|
+
{formatScope(skill.scope)}
|
|
89
|
+
</Badge>
|
|
90
|
+
<Badge
|
|
91
|
+
variant="outline"
|
|
92
|
+
className="bg-surface-raised/60 border-border text-[11px] text-text-secondary"
|
|
93
|
+
>
|
|
94
|
+
{getSkillAudienceLabel(skill.rootKind)}
|
|
95
|
+
</Badge>
|
|
96
|
+
<Badge
|
|
97
|
+
variant="outline"
|
|
98
|
+
className="bg-surface-raised/60 border-border text-[11px] text-text-secondary"
|
|
99
|
+
>
|
|
100
|
+
{formatInvocationMode(skill.invocationMode)}
|
|
101
|
+
</Badge>
|
|
102
|
+
{statusBadge}
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
<div className="flex shrink-0 items-center gap-1">
|
|
106
|
+
<Button
|
|
107
|
+
variant="ghost"
|
|
108
|
+
size="icon"
|
|
109
|
+
className="size-8"
|
|
110
|
+
onClick={() => onEdit(skill)}
|
|
111
|
+
disabled={isLoadingDetail || isDeleting}
|
|
112
|
+
title="编辑 Skill"
|
|
113
|
+
>
|
|
114
|
+
<Edit className="size-3.5" />
|
|
115
|
+
</Button>
|
|
116
|
+
<Button
|
|
117
|
+
variant="ghost"
|
|
118
|
+
size="icon"
|
|
119
|
+
className="size-8 text-red-300 hover:text-red-200"
|
|
120
|
+
onClick={() => onDelete(skill)}
|
|
121
|
+
disabled={isDeleting || isLoadingDetail}
|
|
122
|
+
title="删除 Skill"
|
|
123
|
+
>
|
|
124
|
+
<Trash2 className="size-3.5" />
|
|
125
|
+
</Button>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<p className="line-clamp-3 min-h-[3.75rem] text-xs leading-5 text-text-secondary">
|
|
130
|
+
{skill.description || '没有描述。'}
|
|
131
|
+
</p>
|
|
132
|
+
|
|
133
|
+
<div className="flex flex-wrap items-center gap-2 text-[11px] text-text-muted">
|
|
134
|
+
<span className="truncate">{skill.folderName}</span>
|
|
135
|
+
{skill.flags.hasScripts ? <Badge variant="outline">脚本</Badge> : null}
|
|
136
|
+
{skill.flags.hasReferences ? <Badge variant="outline">参考资料</Badge> : null}
|
|
137
|
+
{skill.flags.hasAssets ? <Badge variant="outline">资源</Badge> : null}
|
|
138
|
+
{skill.issues.length > 0 ? (
|
|
139
|
+
<span className="inline-flex items-center gap-1 text-amber-300">
|
|
140
|
+
<AlertCircle className="size-3" />
|
|
141
|
+
{skill.issues.length} 个提示
|
|
142
|
+
</span>
|
|
143
|
+
) : null}
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export const SkillsLibraryPanel = ({
|
|
150
|
+
projectPath,
|
|
151
|
+
projectLabel,
|
|
152
|
+
}: SkillsLibraryPanelProps): React.JSX.Element => {
|
|
153
|
+
const fetchSkillDetail = useStore((s) => s.fetchSkillDetail);
|
|
154
|
+
const deleteSkill = useStore((s) => s.deleteSkill);
|
|
155
|
+
const skillDetailsById = useStore((s) => s.skillsDetailsById);
|
|
156
|
+
const skillDetailLoadingById = useStore((s) => s.skillsDetailLoadingById);
|
|
157
|
+
|
|
158
|
+
const [skills, setSkills] = useState<SkillCatalogItem[]>([]);
|
|
159
|
+
const [search, setSearch] = useState('');
|
|
160
|
+
const [loading, setLoading] = useState(false);
|
|
161
|
+
const [error, setError] = useState<string | null>(null);
|
|
162
|
+
const [editorState, setEditorState] = useState<EditorState | null>(null);
|
|
163
|
+
const [openingSkillId, setOpeningSkillId] = useState<string | null>(null);
|
|
164
|
+
const [deletingSkillId, setDeletingSkillId] = useState<string | null>(null);
|
|
165
|
+
|
|
166
|
+
const loadSkills = useCallback(async (): Promise<void> => {
|
|
167
|
+
setLoading(true);
|
|
168
|
+
setError(null);
|
|
169
|
+
try {
|
|
170
|
+
const nextSkills = (await api.skills?.list()) ?? [];
|
|
171
|
+
setSkills(nextSkills);
|
|
172
|
+
} catch (err) {
|
|
173
|
+
setError(err instanceof Error ? err.message : '加载全局 Skill 失败');
|
|
174
|
+
} finally {
|
|
175
|
+
setLoading(false);
|
|
176
|
+
}
|
|
177
|
+
}, []);
|
|
178
|
+
|
|
179
|
+
useEffect(() => {
|
|
180
|
+
void loadSkills();
|
|
181
|
+
}, [loadSkills]);
|
|
182
|
+
|
|
183
|
+
const filteredSkills = useMemo(
|
|
184
|
+
() => skills.filter((skill) => matchesSearch(skill, search)),
|
|
185
|
+
[skills, search]
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const openCreateDialog = useCallback(() => {
|
|
189
|
+
setEditorState({ mode: 'create', detail: null });
|
|
190
|
+
}, []);
|
|
191
|
+
|
|
192
|
+
const openEditDialog = useCallback(
|
|
193
|
+
(skill: SkillCatalogItem) => {
|
|
194
|
+
const cachedDetail = skillDetailsById[skill.id];
|
|
195
|
+
if (cachedDetail) {
|
|
196
|
+
setEditorState({ mode: 'edit', skillId: skill.id, detail: cachedDetail });
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
setOpeningSkillId(skill.id);
|
|
201
|
+
setError(null);
|
|
202
|
+
void fetchSkillDetail(skill.id)
|
|
203
|
+
.then(() => {
|
|
204
|
+
setEditorState({ mode: 'edit', skillId: skill.id, detail: null });
|
|
205
|
+
})
|
|
206
|
+
.catch((err) => {
|
|
207
|
+
setError(err instanceof Error ? err.message : '加载 Skill 详情失败');
|
|
208
|
+
})
|
|
209
|
+
.finally(() => {
|
|
210
|
+
setOpeningSkillId((current) => (current === skill.id ? null : current));
|
|
211
|
+
});
|
|
212
|
+
},
|
|
213
|
+
[fetchSkillDetail, skillDetailsById]
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
const handleDelete = useCallback(
|
|
217
|
+
(skill: SkillCatalogItem) => {
|
|
218
|
+
void (async () => {
|
|
219
|
+
const confirmed = await confirm({
|
|
220
|
+
title: '删除 Skill',
|
|
221
|
+
message: `确认删除全局 Skill「${skill.name}」?此操作会删除对应的 Skill 文件。`,
|
|
222
|
+
confirmLabel: '删除',
|
|
223
|
+
cancelLabel: '取消',
|
|
224
|
+
variant: 'danger',
|
|
225
|
+
});
|
|
226
|
+
if (!confirmed) return;
|
|
227
|
+
|
|
228
|
+
setDeletingSkillId(skill.id);
|
|
229
|
+
setError(null);
|
|
230
|
+
try {
|
|
231
|
+
await deleteSkill({ skillId: skill.id });
|
|
232
|
+
await loadSkills();
|
|
233
|
+
} catch (err) {
|
|
234
|
+
setError(err instanceof Error ? err.message : '删除 Skill 失败');
|
|
235
|
+
} finally {
|
|
236
|
+
setDeletingSkillId(null);
|
|
237
|
+
}
|
|
238
|
+
})();
|
|
239
|
+
},
|
|
240
|
+
[deleteSkill, loadSkills]
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
const handleSaved = useCallback(
|
|
244
|
+
(_skillId: string | null) => {
|
|
245
|
+
setEditorState(null);
|
|
246
|
+
void loadSkills();
|
|
247
|
+
},
|
|
248
|
+
[loadSkills]
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
const editorDetail = useMemo(() => {
|
|
252
|
+
if (!editorState) return null;
|
|
253
|
+
if (editorState.mode === 'create') return null;
|
|
254
|
+
return skillDetailsById[editorState.skillId] ?? editorState.detail;
|
|
255
|
+
}, [editorState, skillDetailsById]);
|
|
256
|
+
|
|
257
|
+
return (
|
|
258
|
+
<div className="flex flex-col gap-4">
|
|
259
|
+
<div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
|
|
260
|
+
<div>
|
|
261
|
+
<h2 className="text-sm font-semibold text-text">全局 Skill 库</h2>
|
|
262
|
+
<p className="text-xs text-text-muted">
|
|
263
|
+
管理个人范围 Skill。创建和编辑会保存到全局用户范围,不会写入当前项目。
|
|
264
|
+
</p>
|
|
265
|
+
</div>
|
|
266
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
267
|
+
<Badge variant="secondary" className="font-normal">
|
|
268
|
+
{skills.length} 个 Skill
|
|
269
|
+
</Badge>
|
|
270
|
+
{projectPath ? (
|
|
271
|
+
<Badge variant="outline" className="font-normal text-text-muted">
|
|
272
|
+
当前项目:{projectLabel ?? projectPath}
|
|
273
|
+
</Badge>
|
|
274
|
+
) : null}
|
|
275
|
+
<Button variant="outline" size="sm" onClick={() => void loadSkills()} disabled={loading}>
|
|
276
|
+
<RefreshCw className={loading ? 'mr-2 size-3.5 animate-spin' : 'mr-2 size-3.5'} />
|
|
277
|
+
刷新
|
|
278
|
+
</Button>
|
|
279
|
+
<Button size="sm" onClick={openCreateDialog}>
|
|
280
|
+
<Plus className="mr-2 size-3.5" />
|
|
281
|
+
新建 Skill
|
|
282
|
+
</Button>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
|
|
286
|
+
<SearchInput
|
|
287
|
+
value={search}
|
|
288
|
+
onChange={setSearch}
|
|
289
|
+
placeholder="搜索 Skill..."
|
|
290
|
+
debounceMs={120}
|
|
291
|
+
/>
|
|
292
|
+
|
|
293
|
+
{error ? (
|
|
294
|
+
<div className="rounded-md border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-sm text-amber-300">
|
|
295
|
+
{error}
|
|
296
|
+
</div>
|
|
297
|
+
) : null}
|
|
298
|
+
|
|
299
|
+
{loading && skills.length === 0 ? (
|
|
300
|
+
<div className="rounded-xl border border-border bg-white/[0.025] px-4 py-8 text-center text-sm text-text-muted">
|
|
301
|
+
正在加载全局 Skill...
|
|
302
|
+
</div>
|
|
303
|
+
) : filteredSkills.length > 0 ? (
|
|
304
|
+
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
|
|
305
|
+
{filteredSkills.map((skill) => (
|
|
306
|
+
<SkillLibraryCard
|
|
307
|
+
key={skill.id}
|
|
308
|
+
skill={skill}
|
|
309
|
+
isLoadingDetail={
|
|
310
|
+
openingSkillId === skill.id || Boolean(skillDetailLoadingById[skill.id])
|
|
311
|
+
}
|
|
312
|
+
isDeleting={deletingSkillId === skill.id}
|
|
313
|
+
onEdit={openEditDialog}
|
|
314
|
+
onDelete={handleDelete}
|
|
315
|
+
/>
|
|
316
|
+
))}
|
|
317
|
+
</div>
|
|
318
|
+
) : (
|
|
319
|
+
<div className="rounded-xl border border-border bg-white/[0.025] px-4 py-8 text-center text-sm text-text-muted">
|
|
320
|
+
{search ? '没有匹配的 Skill。' : '全局 Skill 库为空,点击“新建 Skill”创建第一个 Skill。'}
|
|
321
|
+
</div>
|
|
322
|
+
)}
|
|
323
|
+
|
|
324
|
+
<SkillEditorDialog
|
|
325
|
+
open={Boolean(editorState)}
|
|
326
|
+
mode={editorState?.mode ?? 'create'}
|
|
327
|
+
projectPath={null}
|
|
328
|
+
projectLabel={projectLabel}
|
|
329
|
+
detail={editorDetail}
|
|
330
|
+
onClose={() => setEditorState(null)}
|
|
331
|
+
onSaved={handleSaved}
|
|
332
|
+
/>
|
|
333
|
+
</div>
|
|
334
|
+
);
|
|
335
|
+
};
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { TeamGraphTab } from '@features/agent-graph/renderer';
|
|
7
7
|
import { TabUIProvider } from '@renderer/contexts/TabUIContext';
|
|
8
|
+
import { SYSTEM_MANAGER_TEAM_NAME } from '@shared/types/team';
|
|
8
9
|
|
|
9
10
|
import { DashboardView } from '../dashboard/DashboardView';
|
|
10
11
|
import { ExtensionStoreView } from '../extensions/ExtensionStoreView';
|
|
@@ -13,6 +14,7 @@ import { SessionReportTab } from '../report/SessionReportTab';
|
|
|
13
14
|
import { SchedulesView } from '../schedules/SchedulesView';
|
|
14
15
|
import { SettingsView } from '../settings/SettingsView';
|
|
15
16
|
import { TasksView } from '../tasks/TasksView';
|
|
17
|
+
import { SystemManagerView } from '../system-manager/SystemManagerView';
|
|
16
18
|
import { TeamDetailView } from '../team/TeamDetailView';
|
|
17
19
|
import { TeamListView } from '../team/TeamListView';
|
|
18
20
|
|
|
@@ -51,7 +53,12 @@ export const PaneContent = ({ pane, isPaneFocused }: PaneContentProps): React.JS
|
|
|
51
53
|
{tab.type === 'notifications' && <NotificationsView />}
|
|
52
54
|
{tab.type === 'settings' && <SettingsView />}
|
|
53
55
|
{tab.type === 'teams' && <TeamListView />}
|
|
54
|
-
{tab.type === 'team' && (
|
|
56
|
+
{tab.type === 'team' && tab.teamName === SYSTEM_MANAGER_TEAM_NAME && (
|
|
57
|
+
<TabUIProvider tabId={tab.id}>
|
|
58
|
+
<SystemManagerView isPaneFocused={isPaneFocused} />
|
|
59
|
+
</TabUIProvider>
|
|
60
|
+
)}
|
|
61
|
+
{tab.type === 'team' && tab.teamName !== SYSTEM_MANAGER_TEAM_NAME && (
|
|
55
62
|
<TabUIProvider tabId={tab.id}>
|
|
56
63
|
<TeamDetailView teamName={tab.teamName ?? ''} isPaneFocused={isPaneFocused} />
|
|
57
64
|
</TabUIProvider>
|
|
@@ -73,8 +73,8 @@ export const PaneResizeHandle = ({ leftPaneId }: PaneResizeHandleProps): React.J
|
|
|
73
73
|
return (
|
|
74
74
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions -- resize handle requires mouse interaction
|
|
75
75
|
<div
|
|
76
|
-
className={`flex w-1 shrink-0 cursor-col-resize items-center justify-center transition-colors hover:bg-
|
|
77
|
-
isResizing ? 'bg-
|
|
76
|
+
className={`flex w-1 shrink-0 cursor-col-resize items-center justify-center transition-colors hover:bg-indigo-500/50 ${
|
|
77
|
+
isResizing ? 'bg-indigo-500/50' : ''
|
|
78
78
|
}`}
|
|
79
79
|
style={{
|
|
80
80
|
backgroundColor: isResizing ? undefined : 'var(--color-border)',
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Sidebar - Navigation with task list and session list.
|
|
3
3
|
*
|
|
4
4
|
* Structure:
|
|
5
|
-
* - Tab bar: Collapse button +
|
|
6
|
-
* - Scrollable Body:
|
|
5
|
+
* - Tab bar: Collapse button + Workspace
|
|
6
|
+
* - Scrollable Body: workspace browser
|
|
7
7
|
* - Resizable: Drag right edge to resize
|
|
8
8
|
* - Collapsible: Cmd+B to toggle (Notion-style)
|
|
9
9
|
*/
|
|
@@ -15,11 +15,9 @@ import { formatShortcut } from '@renderer/utils/stringUtils';
|
|
|
15
15
|
import { PanelLeft } from 'lucide-react';
|
|
16
16
|
import { useShallow } from 'zustand/react/shallow';
|
|
17
17
|
|
|
18
|
-
import { DateGroupedSessions } from '../sidebar/DateGroupedSessions';
|
|
19
|
-
import { SidebarSessions } from '../sidebar/SidebarSessions';
|
|
20
18
|
import { WorkspaceBrowser } from '../sidebar/WorkspaceBrowser';
|
|
21
19
|
|
|
22
|
-
type SidebarTab = 'workspace'
|
|
20
|
+
type SidebarTab = 'workspace';
|
|
23
21
|
|
|
24
22
|
const MIN_WIDTH = 200;
|
|
25
23
|
const MAX_WIDTH = 500;
|
|
@@ -34,7 +32,7 @@ export const Sidebar = (): React.JSX.Element => {
|
|
|
34
32
|
);
|
|
35
33
|
const [width, setWidth] = useState(DEFAULT_WIDTH);
|
|
36
34
|
const [isResizing, setIsResizing] = useState(false);
|
|
37
|
-
const [sidebarTab
|
|
35
|
+
const [sidebarTab] = useState<SidebarTab>('workspace');
|
|
38
36
|
const [isCollapseHovered, setIsCollapseHovered] = useState(false);
|
|
39
37
|
const sidebarRef = useRef<HTMLDivElement>(null);
|
|
40
38
|
|
|
@@ -123,54 +121,22 @@ export const Sidebar = (): React.JSX.Element => {
|
|
|
123
121
|
<button
|
|
124
122
|
type="button"
|
|
125
123
|
role="tab"
|
|
126
|
-
aria-selected
|
|
124
|
+
aria-selected
|
|
127
125
|
aria-controls="sidebar-workspace-panel"
|
|
128
126
|
id="sidebar-tab-workspace"
|
|
129
|
-
className=
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
style={
|
|
135
|
-
sidebarTab === 'workspace'
|
|
136
|
-
? {
|
|
137
|
-
borderBottom: '2px solid var(--color-text)',
|
|
138
|
-
marginBottom: '-1px',
|
|
139
|
-
}
|
|
140
|
-
: undefined
|
|
141
|
-
}
|
|
142
|
-
onClick={() => setSidebarTab('workspace')}
|
|
127
|
+
className="relative px-3 py-1.5 text-[11px] font-medium text-text transition-colors"
|
|
128
|
+
style={{
|
|
129
|
+
borderBottom: '2px solid var(--color-text)',
|
|
130
|
+
marginBottom: '-1px',
|
|
131
|
+
}}
|
|
143
132
|
>
|
|
144
133
|
工作空间
|
|
145
134
|
</button>
|
|
146
|
-
<button
|
|
147
|
-
type="button"
|
|
148
|
-
role="tab"
|
|
149
|
-
aria-selected={sidebarTab === 'sessions'}
|
|
150
|
-
aria-controls="sidebar-sessions-panel"
|
|
151
|
-
id="sidebar-tab-sessions"
|
|
152
|
-
className={`relative px-3 py-1.5 text-[11px] font-medium transition-colors ${
|
|
153
|
-
sidebarTab === 'sessions'
|
|
154
|
-
? 'text-text'
|
|
155
|
-
: 'text-text-muted hover:text-text-secondary'
|
|
156
|
-
}`}
|
|
157
|
-
style={
|
|
158
|
-
sidebarTab === 'sessions'
|
|
159
|
-
? {
|
|
160
|
-
borderBottom: '2px solid var(--color-text)',
|
|
161
|
-
marginBottom: '-1px',
|
|
162
|
-
}
|
|
163
|
-
: undefined
|
|
164
|
-
}
|
|
165
|
-
onClick={() => setSidebarTab('sessions')}
|
|
166
|
-
>
|
|
167
|
-
会话
|
|
168
|
-
</button>
|
|
169
135
|
</div>
|
|
170
136
|
<div className="flex-1" />
|
|
171
137
|
</div>
|
|
172
138
|
|
|
173
|
-
{/* Content: Workspace
|
|
139
|
+
{/* Content: Workspace browser */}
|
|
174
140
|
<div
|
|
175
141
|
id="sidebar-workspace-panel"
|
|
176
142
|
role="tabpanel"
|
|
@@ -180,15 +146,6 @@ export const Sidebar = (): React.JSX.Element => {
|
|
|
180
146
|
>
|
|
181
147
|
<WorkspaceBrowser />
|
|
182
148
|
</div>
|
|
183
|
-
<div
|
|
184
|
-
id="sidebar-sessions-panel"
|
|
185
|
-
role="tabpanel"
|
|
186
|
-
aria-labelledby="sidebar-tab-sessions"
|
|
187
|
-
hidden={sidebarTab !== 'sessions'}
|
|
188
|
-
className="min-w-0 flex-1 overflow-hidden"
|
|
189
|
-
>
|
|
190
|
-
<SidebarSessions />
|
|
191
|
-
</div>
|
|
192
149
|
</div>
|
|
193
150
|
|
|
194
151
|
{/* Resize handle - only interactive when expanded */}
|
|
@@ -196,8 +153,8 @@ export const Sidebar = (): React.JSX.Element => {
|
|
|
196
153
|
<button
|
|
197
154
|
type="button"
|
|
198
155
|
aria-label="调整侧栏宽度"
|
|
199
|
-
className={`absolute left-0 top-0 z-20 h-full w-1 cursor-col-resize border-0 bg-transparent p-0 transition-colors hover:bg-
|
|
200
|
-
isResizing ? 'bg-
|
|
156
|
+
className={`absolute left-0 top-0 z-20 h-full w-1 cursor-col-resize border-0 bg-transparent p-0 transition-colors hover:bg-indigo-500/50 ${
|
|
157
|
+
isResizing ? 'bg-indigo-500/50' : ''
|
|
201
158
|
}`}
|
|
202
159
|
onMouseDown={handleResizeStart}
|
|
203
160
|
/>
|
|
@@ -8,12 +8,7 @@ import { useCallback, useState } from 'react';
|
|
|
8
8
|
import { useSortable } from '@dnd-kit/sortable';
|
|
9
9
|
import { CSS } from '@dnd-kit/utilities';
|
|
10
10
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip';
|
|
11
|
-
import {
|
|
12
|
-
getTeamColorSet,
|
|
13
|
-
getThemedBadge,
|
|
14
|
-
getThemedBorder,
|
|
15
|
-
getThemedText,
|
|
16
|
-
} from '@renderer/constants/teamColors';
|
|
11
|
+
import { getTeamColorSet } from '@renderer/constants/teamColors';
|
|
17
12
|
import { useTheme } from '@renderer/hooks/useTheme';
|
|
18
13
|
import { useStore } from '@renderer/store';
|
|
19
14
|
import { nameColorSet } from '@renderer/utils/projectColor';
|
|
@@ -91,15 +86,11 @@ export const SortableTab = ({
|
|
|
91
86
|
team?.color ??
|
|
92
87
|
(s.selectedTeamName === tab.teamName ? s.selectedTeamData?.config.color : undefined);
|
|
93
88
|
if (explicitColor) return getTeamColorSet(explicitColor);
|
|
94
|
-
// Fallback: deterministic color derived from display name
|
|
95
89
|
const displayName = team?.displayName ?? tab.label;
|
|
96
90
|
return nameColorSet(displayName, isLight);
|
|
97
91
|
})
|
|
98
92
|
);
|
|
99
|
-
const
|
|
100
|
-
? getThemedBorder(teamColorSet, isLight)
|
|
101
|
-
: 'var(--color-accent, #6366f1)';
|
|
102
|
-
const inactiveTeamTextColor = teamColorSet ? getThemedText(teamColorSet, isLight) : null;
|
|
93
|
+
const accentColor = teamColorSet?.text ?? null;
|
|
103
94
|
|
|
104
95
|
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
|
105
96
|
id: tab.id,
|
|
@@ -116,33 +107,25 @@ export const SortableTab = ({
|
|
|
116
107
|
transition: isDragging ? 'none' : transition,
|
|
117
108
|
opacity: isDragging ? 0.3 : 1,
|
|
118
109
|
backgroundColor: isActive
|
|
119
|
-
?
|
|
120
|
-
? getThemedBadge(teamColorSet, isLight)
|
|
121
|
-
: 'var(--color-surface-raised)'
|
|
110
|
+
? 'var(--color-surface-raised)'
|
|
122
111
|
: isHovered
|
|
123
|
-
?
|
|
124
|
-
|
|
125
|
-
: 'var(--color-surface-overlay)'
|
|
126
|
-
: teamColorSet
|
|
127
|
-
? getThemedBadge(teamColorSet, isLight)
|
|
128
|
-
: 'transparent',
|
|
112
|
+
? 'var(--color-surface-overlay)'
|
|
113
|
+
: 'transparent',
|
|
129
114
|
color: isActive
|
|
130
115
|
? 'var(--color-text)'
|
|
131
|
-
:
|
|
132
|
-
?
|
|
133
|
-
:
|
|
134
|
-
? 'var(--color-text)'
|
|
135
|
-
: 'var(--color-text-muted)',
|
|
116
|
+
: isHovered
|
|
117
|
+
? 'var(--color-text)'
|
|
118
|
+
: 'var(--color-text-muted)',
|
|
136
119
|
outline: isSelected ? '1px solid var(--color-border-emphasis)' : 'none',
|
|
137
120
|
outlineOffset: '-1px',
|
|
138
|
-
borderTop: isActive ?
|
|
139
|
-
borderLeft: '1px solid
|
|
140
|
-
borderRight: '1px solid transparent',
|
|
121
|
+
borderTop: isActive ? '1px solid var(--color-border)' : '1px solid transparent',
|
|
122
|
+
borderLeft: '1px solid var(--color-border-subtle)',
|
|
123
|
+
borderRight: isActive ? '1px solid var(--color-border)' : '1px solid transparent',
|
|
141
124
|
borderBottom: isActive ? '1px solid var(--color-surface-raised)' : '1px solid transparent',
|
|
142
|
-
borderTopLeftRadius: '
|
|
143
|
-
borderTopRightRadius: '
|
|
144
|
-
borderBottomLeftRadius:
|
|
145
|
-
borderBottomRightRadius:
|
|
125
|
+
borderTopLeftRadius: '0',
|
|
126
|
+
borderTopRightRadius: '0',
|
|
127
|
+
borderBottomLeftRadius: '0',
|
|
128
|
+
borderBottomRightRadius: '0',
|
|
146
129
|
marginBottom: isActive ? '-1px' : 0,
|
|
147
130
|
position: 'relative' as const,
|
|
148
131
|
zIndex: isActive ? 1 : 0,
|
|
@@ -184,6 +167,12 @@ export const SortableTab = ({
|
|
|
184
167
|
}
|
|
185
168
|
}}
|
|
186
169
|
>
|
|
170
|
+
{isActive && accentColor && (
|
|
171
|
+
<div
|
|
172
|
+
className="absolute bottom-0 left-2 right-2 h-[2px] rounded-full"
|
|
173
|
+
style={{ backgroundColor: accentColor, opacity: 0.6 }}
|
|
174
|
+
/>
|
|
175
|
+
)}
|
|
187
176
|
<Icon className="size-4 shrink-0" />
|
|
188
177
|
{tab.fromSearch && (
|
|
189
178
|
<span title="从搜索打开">
|
|
@@ -192,7 +181,7 @@ export const SortableTab = ({
|
|
|
192
181
|
)}
|
|
193
182
|
{isPinned && (
|
|
194
183
|
<span title="已固定会话">
|
|
195
|
-
<Pin className="size-3 shrink-0 text-
|
|
184
|
+
<Pin className="size-3 shrink-0 text-indigo-400" />
|
|
196
185
|
</span>
|
|
197
186
|
)}
|
|
198
187
|
<span
|
|
@@ -264,7 +264,7 @@ export const TabBar = ({ paneId }: TabBarProps): React.JSX.Element => {
|
|
|
264
264
|
scrollContainerRef.current = el;
|
|
265
265
|
setDroppableRef(el);
|
|
266
266
|
}}
|
|
267
|
-
className="scrollbar-none flex min-w-0 flex-1 items-center
|
|
267
|
+
className="scrollbar-none flex min-w-0 flex-1 items-center"
|
|
268
268
|
style={{
|
|
269
269
|
outline: isDroppableOver ? '1px dashed var(--color-accent, #6366f1)' : 'none',
|
|
270
270
|
outlineOffset: '-1px',
|
|
@@ -87,7 +87,7 @@ export const TabContextMenu = ({
|
|
|
87
87
|
return (
|
|
88
88
|
<div
|
|
89
89
|
ref={menuRef}
|
|
90
|
-
className="fixed z-50 min-w-[220px] overflow-hidden
|
|
90
|
+
className="fixed z-50 min-w-[220px] overflow-hidden border py-1 shadow-lg"
|
|
91
91
|
style={{
|
|
92
92
|
left: clampedX,
|
|
93
93
|
top: clampedY,
|
|
@@ -97,7 +97,7 @@ export const CostSection = ({
|
|
|
97
97
|
<div className="mb-1.5 flex h-3 w-full overflow-hidden rounded-full">
|
|
98
98
|
<div
|
|
99
99
|
className="h-full"
|
|
100
|
-
style={{ width: `${parentPct}%`, backgroundColor: '#
|
|
100
|
+
style={{ width: `${parentPct}%`, backgroundColor: '#818cf8' }}
|
|
101
101
|
/>
|
|
102
102
|
<div
|
|
103
103
|
className="h-full"
|
|
@@ -108,7 +108,7 @@ export const CostSection = ({
|
|
|
108
108
|
<div className="flex items-center gap-1.5">
|
|
109
109
|
<span
|
|
110
110
|
className="inline-block size-2 rounded-full"
|
|
111
|
-
style={{ backgroundColor: '#
|
|
111
|
+
style={{ backgroundColor: '#818cf8' }}
|
|
112
112
|
/>
|
|
113
113
|
<span className="text-text-secondary">主会话:{fmt(data.parentCostUsd)}</span>
|
|
114
114
|
</div>
|
|
@@ -153,7 +153,7 @@ export const InsightsSection = ({
|
|
|
153
153
|
<div className="mb-2 text-xs font-medium text-text-muted">
|
|
154
154
|
Agent Tree ({agentTree.agentCount} agent{agentTree.agentCount !== 1 ? 's' : ''})
|
|
155
155
|
{agentTree.hasTeamMode && (
|
|
156
|
-
<span className="ml-2 rounded px-1.5 py-0.5 text-xs" style={{ color: '#
|
|
156
|
+
<span className="ml-2 rounded px-1.5 py-0.5 text-xs" style={{ color: '#818cf8' }}>
|
|
157
157
|
Team Mode
|
|
158
158
|
</span>
|
|
159
159
|
)}
|
|
@@ -191,7 +191,7 @@ export const ProviderRuntimeBackendSelector = ({
|
|
|
191
191
|
className="shrink-0 rounded-full px-1.5 py-0.5 text-[10px]"
|
|
192
192
|
style={{
|
|
193
193
|
color: '#93c5fd',
|
|
194
|
-
backgroundColor: 'rgba(
|
|
194
|
+
backgroundColor: 'rgba(99, 102, 241, 0.14)',
|
|
195
195
|
}}
|
|
196
196
|
>
|
|
197
197
|
{getProviderRuntimeBackendAudienceLabel(option)}
|
|
@@ -259,7 +259,7 @@ export const ProviderRuntimeBackendSelector = ({
|
|
|
259
259
|
className="rounded-full px-1.5 py-0.5 text-[10px]"
|
|
260
260
|
style={{
|
|
261
261
|
color: '#93c5fd',
|
|
262
|
-
backgroundColor: 'rgba(
|
|
262
|
+
backgroundColor: 'rgba(99, 102, 241, 0.14)',
|
|
263
263
|
}}
|
|
264
264
|
>
|
|
265
265
|
{selectedAudienceLabel}
|