@yancyyu/openhermit 1.6.42 → 1.6.43
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/README.md +98 -89
- package/bin/hermit.mjs +96 -0
- package/dist-renderer/assets/{ProjectEditorOverlay-DlFQ6mai.js → ProjectEditorOverlay-C98qSs7-.js} +1 -1
- package/dist-renderer/assets/{TeamGraphOverlay-D2TPMPGR.js → TeamGraphOverlay-CsBbZwcL.js} +1 -1
- package/dist-renderer/assets/{_basePickBy-Cmd0RHLQ.js → _basePickBy-ZOyLWjMK.js} +1 -1
- package/dist-renderer/assets/{_baseUniq-BI_iy8ea.js → _baseUniq-DBb726rt.js} +1 -1
- package/dist-renderer/assets/{arc-NzW2mjTP.js → arc-CdiTaR_R.js} +1 -1
- package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-Bzq85AYv.js → architectureDiagram-VXUJARFQ-Cz3sc5TH.js} +1 -1
- package/dist-renderer/assets/{blockDiagram-VD42YOAC-D1PvYS-b.js → blockDiagram-VD42YOAC-DE4c-KJ3.js} +1 -1
- package/dist-renderer/assets/{c4Diagram-YG6GDRKO-D49RKzPC.js → c4Diagram-YG6GDRKO-CmTMDTrV.js} +1 -1
- package/dist-renderer/assets/channel-KTpqi9eT.js +1 -0
- package/dist-renderer/assets/{chunk-4BX2VUAB-fmI_MQmQ.js → chunk-4BX2VUAB-rhHy3tFl.js} +1 -1
- package/dist-renderer/assets/{chunk-55IACEB6-Xsv9RCXZ.js → chunk-55IACEB6-fLZBzuo_.js} +1 -1
- package/dist-renderer/assets/{chunk-B4BG7PRW-BE1KO8Um.js → chunk-B4BG7PRW-DOzxQhim.js} +1 -1
- package/dist-renderer/assets/{chunk-DI55MBZ5-tqJ7Mv7f.js → chunk-DI55MBZ5-COQCcXC5.js} +1 -1
- package/dist-renderer/assets/{chunk-FMBD7UC4-DMD45MVJ.js → chunk-FMBD7UC4-IKU9U_Y4.js} +1 -1
- package/dist-renderer/assets/{chunk-QN33PNHL-DOhGrz-q.js → chunk-QN33PNHL-D6WV154X.js} +1 -1
- package/dist-renderer/assets/{chunk-QZHKN3VN-D8yDgJdD.js → chunk-QZHKN3VN-D90_2DQp.js} +1 -1
- package/dist-renderer/assets/{chunk-TZMSLE5B-BcsEDu7A.js → chunk-TZMSLE5B-BQEil57G.js} +1 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-lpzulY5X.js +1 -0
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-lpzulY5X.js +1 -0
- package/dist-renderer/assets/clone-CriGymY9.js +1 -0
- package/dist-renderer/assets/{cose-bilkent-S5V4N54A-DlSqGHMX.js → cose-bilkent-S5V4N54A-6WiK6U2P.js} +1 -1
- package/dist-renderer/assets/{dagre-6UL2VRFP-BTT9tSAx.js → dagre-6UL2VRFP-DF4MMuTn.js} +1 -1
- package/dist-renderer/assets/{diagram-PSM6KHXK-Du-U-mK2.js → diagram-PSM6KHXK-CcF1eZ7E.js} +1 -1
- package/dist-renderer/assets/{diagram-QEK2KX5R-jFdHeKas.js → diagram-QEK2KX5R-DYlOVPQB.js} +1 -1
- package/dist-renderer/assets/{diagram-S2PKOQOG-DKLNK2bu.js → diagram-S2PKOQOG-BHXWsZOP.js} +1 -1
- package/dist-renderer/assets/{erDiagram-Q2GNP2WA-CZxHgIIo.js → erDiagram-Q2GNP2WA-GjmuBx8d.js} +1 -1
- package/dist-renderer/assets/{flowDiagram-NV44I4VS-v4XStCD0.js → flowDiagram-NV44I4VS-BuS7YVHk.js} +1 -1
- package/dist-renderer/assets/{ganttDiagram-JELNMOA3-DJjD_BEL.js → ganttDiagram-JELNMOA3-3Teu5tAa.js} +1 -1
- package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-BNy-jr03.js → gitGraphDiagram-V2S2FVAM-BiLdCYu5.js} +1 -1
- package/dist-renderer/assets/{graph-DDTrn6je.js → graph-CDP_R8ct.js} +1 -1
- package/dist-renderer/assets/{index-BBp78BAu.js → index-BSZdT-g-.js} +1 -1
- package/dist-renderer/assets/{index-eotrJaYy.js → index-BhWvMqsz.js} +1 -1
- package/dist-renderer/assets/{index-D8_B-cfs.js → index-C2_AupSj.js} +1 -1
- package/dist-renderer/assets/{index-BQrwHZ-k.js → index-C5ujiwAR.js} +580 -588
- package/dist-renderer/assets/index-CIS2CTK9.css +1 -0
- package/dist-renderer/assets/{index-CRKQSG9S.js → index-CVNjLwkq.js} +1 -1
- package/dist-renderer/assets/{index-DR6Wz52b.js → index-CwG3se0q.js} +1 -1
- package/dist-renderer/assets/{infoDiagram-HS3SLOUP-DqnOsuza.js → infoDiagram-HS3SLOUP-DLHUFo72.js} +1 -1
- package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-DTobaO1d.js → journeyDiagram-XKPGCS4Q-BE07RpJD.js} +1 -1
- package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-HbwVOvWc.js → kanban-definition-3W4ZIXB7-DDHZy4NB.js} +1 -1
- package/dist-renderer/assets/{layout--VYmTcw2.js → layout-5nA5wUxO.js} +1 -1
- package/dist-renderer/assets/{linear-BsJh89Mr.js → linear-BtF1i2qN.js} +1 -1
- package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-BZqUZePd.js → mindmap-definition-VGOIOE7T-Z1Ui9Sqy.js} +1 -1
- package/dist-renderer/assets/{pieDiagram-ADFJNKIX-B1q_nH6P.js → pieDiagram-ADFJNKIX-LCjxckWv.js} +1 -1
- package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-UD8QhSEu.js → quadrantDiagram-AYHSOK5B-BOwKjSco.js} +1 -1
- package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-BA_i7Nw8.js → requirementDiagram-UZGBJVZJ-pChP8Znd.js} +1 -1
- package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-CMTnX-2d.js → sankeyDiagram-TZEHDZUN-DifZ2qpo.js} +1 -1
- package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-BQXDB615.js → sequenceDiagram-WL72ISMW-CJg-WYyY.js} +1 -1
- package/dist-renderer/assets/{splashScene-D0YB9uxm.js → splashScene-94xWCzLA.js} +1 -1
- package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-BAsPXy6X.js → stateDiagram-FKZM4ZOC-DWHOoFdv.js} +1 -1
- package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-CGYZOoMb.js +1 -0
- package/dist-renderer/assets/{timeline-definition-IT6M3QCI-BdasmVkC.js → timeline-definition-IT6M3QCI-CPgokIo8.js} +1 -1
- package/dist-renderer/assets/{treemap-GDKQZRPO-BkKQqIui.js → treemap-GDKQZRPO-DAVqSR9L.js} +1 -1
- package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-EAlPHOdx.js → xychartDiagram-PRI3JC2R-CCOcGbrD.js} +1 -1
- package/dist-renderer/chat-community-qr.jpg +0 -0
- package/dist-renderer/fonts/Agave-Bold.ttf +0 -0
- package/dist-renderer/fonts/Agave-Regular.ttf +0 -0
- package/dist-renderer/icon.png +0 -0
- package/dist-renderer/icon.rar +0 -0
- package/dist-renderer/index.html +3 -3
- package/package.json +21 -26
- package/src/features/worker-society/core/application/WorkerSocietyService.test.ts +802 -0
- package/src/features/worker-society/core/application/WorkerSocietyService.ts +428 -0
- package/src/features/worker-society/core/application/fakes.ts +101 -0
- package/src/features/worker-society/core/application/ports.ts +70 -0
- package/src/features/worker-society/core/domain/models/society.ts +141 -0
- package/src/features/worker-society/core/domain/policies/societyPolicies.test.ts +739 -0
- package/src/features/worker-society/core/domain/policies/societyPolicies.ts +496 -0
- package/src/features/worker-society/main/adapters/input/societyMcp.test.ts +317 -0
- package/src/features/worker-society/main/adapters/input/societyMcp.ts +257 -0
- package/src/features/worker-society/main/adapters/input/societyRoutes.test.ts +695 -0
- package/src/features/worker-society/main/adapters/input/societyRoutes.ts +194 -0
- package/src/features/worker-society/main/composition/societyComposition.test.ts +74 -0
- package/src/features/worker-society/main/composition/societyComposition.ts +70 -0
- package/src/features/worker-society/main/composition/workerSocietyPlugin.test.ts +69 -0
- package/src/features/worker-society/main/composition/workerSocietyPlugin.ts +67 -0
- package/src/features/worker-society/main/infrastructure/crossTeamMessageGateway.test.ts +132 -0
- package/src/features/worker-society/main/infrastructure/crossTeamMessageGateway.ts +84 -0
- package/src/features/worker-society/main/infrastructure/fsStores.test.ts +216 -0
- package/src/features/worker-society/main/infrastructure/fsStores.ts +113 -0
- package/src/features/worker-society/main/infrastructure/mergingProfileStore.test.ts +195 -0
- package/src/features/worker-society/main/infrastructure/mergingProfileStore.ts +96 -0
- package/src/features/worker-society/renderer/SocietyGraph.tsx +166 -0
- package/src/features/worker-society/renderer/SocietyNodeLabels.tsx +139 -0
- package/src/features/worker-society/renderer/SocietyNodeOverlay.tsx +339 -0
- package/src/features/worker-society/renderer/SocietyView.tsx +437 -0
- package/src/features/worker-society/renderer/index.ts +11 -0
- package/src/features/worker-society/renderer/societyApi.test.ts +259 -0
- package/src/features/worker-society/renderer/societyApi.ts +144 -0
- package/src/features/worker-society/renderer/societyGraphAdapter.test.ts +321 -0
- package/src/features/worker-society/renderer/societyGraphAdapter.ts +240 -0
- package/src/features/worker-society/renderer/societyOverlayActions.test.ts +57 -0
- package/src/features/worker-society/renderer/societyOverlayActions.ts +49 -0
- package/src/features/worker-society/renderer/societyStore.test.ts +218 -0
- package/src/features/worker-society/renderer/societyStore.ts +146 -0
- package/src/features/worker-society/renderer/societyViewUtils.test.ts +81 -0
- package/src/features/worker-society/renderer/societyViewUtils.ts +68 -0
- package/src/main/ipc/extensions.ts +27 -0
- package/src/main/server.ts +1709 -534
- package/src/main/services/ccConnect/CcConnectBridge.ts +26 -11
- package/src/main/services/ccConnect/CcConnectClient.ts +9 -2
- package/src/main/services/ccConnect/workDirReconcile.test.ts +57 -0
- package/src/main/services/ccConnect/workDirReconcile.ts +36 -0
- package/src/main/services/direct-cli/DirectCliSessionManager.test.ts +397 -0
- package/src/main/services/direct-cli/DirectCliSessionManager.ts +508 -0
- package/src/main/services/direct-cli/DirectCliSessionStore.test.ts +79 -0
- package/src/main/services/direct-cli/DirectCliSessionStore.ts +97 -0
- package/src/main/services/direct-cli/__tests__/directCliMessageId.test.ts +40 -0
- package/src/main/services/direct-cli/directCliMessageId.ts +21 -0
- package/src/main/services/direct-cli/index.ts +17 -0
- package/src/main/services/extensions/capability-packs/CapabilityPackLoaderService.ts +637 -0
- package/src/main/services/extensions/catalog/PluginCatalogService.ts +2 -2
- package/src/main/services/loop-assets/LoopAssetsScannerService.ts +657 -0
- package/src/main/services/runtime/providerAwareCliEnv.ts +33 -5
- package/src/main/services/session-intelligence/LocalSessionScanner.ts +156 -71
- package/src/main/services/session-intelligence/SessionUsageParser.ts +103 -8
- package/src/main/services/session-intelligence/UsageTelemetryService.ts +11 -0
- package/src/main/services/session-intelligence/__tests__/teamSessionListMapper.test.ts +104 -0
- package/src/main/services/session-intelligence/teamSessionListMapper.ts +78 -0
- package/src/main/services/system-manager/AdminLoopInitializer.ts +95 -0
- package/src/main/services/system-manager/BuiltinWorkflowSeeder.ts +679 -74
- package/src/main/services/system-manager/SystemManagerConfigService.ts +19 -1
- package/src/main/services/system-manager/WorkflowPromptService.ts +58 -5
- package/src/main/services/system-manager/__tests__/AdminLoopInitializer.test.ts +129 -0
- package/src/main/services/system-manager/__tests__/SystemManagerConfigService.test.ts +60 -0
- package/src/main/services/teams-mvp/CollaborationBoardService.ts +2 -0
- package/src/main/services/teams-mvp/OpsRunbookContext.ts +60 -0
- package/src/main/services/teams-mvp/TaskDispatchService.test.ts +305 -0
- package/src/main/services/teams-mvp/TaskDispatchService.ts +250 -131
- package/src/main/services/teams-mvp/TeamProvisioningService.ts +12 -2
- package/src/main/services/teams-mvp/TeamWorkspaceService.test.ts +207 -0
- package/src/main/services/teams-mvp/TeamWorkspaceService.ts +104 -51
- package/src/main/services/teams-mvp/index.ts +6 -0
- package/src/main/utils/externalPlatformSessionRouting.ts +92 -0
- package/src/main/utils/toolApprovalRules.ts +151 -0
- package/src/renderer/App.tsx +24 -89
- package/src/renderer/api/httpClient.ts +115 -37
- package/src/renderer/api/providers.ts +5 -16
- package/src/renderer/components/chat/CommunityChatView.tsx +81 -0
- package/src/renderer/components/dashboard/DashboardView.tsx +130 -84
- package/src/renderer/components/extensions/ExtensionStoreView.tsx +39 -5
- package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +2 -1
- package/src/renderer/components/extensions/capability-packs/CapabilityPacksPanel.tsx +170 -0
- package/src/renderer/components/layout/PaneContent.tsx +10 -2
- package/src/renderer/components/layout/SortableTab.tsx +4 -0
- package/src/renderer/components/layout/TabBarActions.tsx +13 -16
- package/src/renderer/components/runtime/ProviderRuntimeSettingsDialog.tsx +4 -135
- package/src/renderer/components/schedules/SchedulesView.tsx +22 -14
- package/src/renderer/components/schedules/calendar/CalendarEventBlock.tsx +7 -6
- package/src/renderer/components/settings/SettingsTabs.tsx +24 -21
- package/src/renderer/components/settings/SettingsView.tsx +22 -13
- package/src/renderer/components/settings/components/SettingRow.tsx +13 -5
- package/src/renderer/components/settings/components/SettingsSectionCard.tsx +53 -0
- package/src/renderer/components/settings/components/SettingsSectionHeader.tsx +10 -6
- package/src/renderer/components/settings/components/SettingsSelect.tsx +12 -9
- package/src/renderer/components/settings/components/SettingsToggle.tsx +6 -5
- package/src/renderer/components/settings/components/index.ts +1 -0
- package/src/renderer/components/settings/sections/AdvancedSection.tsx +78 -59
- package/src/renderer/components/settings/sections/CliStatusSection.tsx +32 -44
- package/src/renderer/components/settings/sections/ConfigEditorDialog.tsx +1 -1
- package/src/renderer/components/settings/sections/GeneralSection.tsx +216 -186
- package/src/renderer/components/settings/sections/PlatformsSection.tsx +25 -17
- package/src/renderer/components/settings/sections/TaskBusSection.tsx +63 -22
- package/src/renderer/components/sidebar/SidebarSessions.tsx +120 -80
- package/src/renderer/components/sidebar/SidebarTaskItem.tsx +1 -1
- package/src/renderer/components/splash/splashScene.ts +6 -2
- package/src/renderer/components/system-manager/SystemManagerView.tsx +169 -255
- package/src/renderer/components/tasks/TasksView.tsx +63 -37
- package/src/renderer/components/team/CcSessionsSection.tsx +124 -89
- package/src/renderer/components/team/HarnessBrandLogos.tsx +318 -0
- package/src/renderer/components/team/HarnessSelect.tsx +25 -26
- package/src/renderer/components/team/TeamDetailView.tsx +137 -153
- package/src/renderer/components/team/TeamEmptyState.tsx +9 -37
- package/src/renderer/components/team/TeamListView.tsx +143 -30
- package/src/renderer/components/team/__tests__/CcSessionsSection.hasLocalFile.test.tsx +128 -0
- package/src/renderer/components/team/activity/ActivityItem.tsx +21 -9
- package/src/renderer/components/team/activity/ActivityTimeline.tsx +2 -2
- package/src/renderer/components/team/dialogs/AdvancedCliSection.tsx +1 -1
- package/src/renderer/components/team/dialogs/CreateTaskDialog.tsx +13 -10
- package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +156 -83
- package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +9 -157
- package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +19 -15
- package/src/renderer/components/team/dialogs/PlatformBindingDialog.tsx +48 -10
- package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +11 -12
- package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +39 -37
- package/src/renderer/components/team/dialogs/RuntimeConfigDialog.tsx +434 -64
- package/src/renderer/components/team/dialogs/SendMessageDialog.tsx +12 -10
- package/src/renderer/components/team/dialogs/TaskDetailDialog.tsx +2 -2
- package/src/renderer/components/team/dialogs/__tests__/CreateTeamDialog.bindProject.test.tsx +399 -0
- package/src/renderer/components/team/dialogs/__tests__/CreateTeamDialog.chineseRepro.test.tsx +253 -0
- package/src/renderer/components/team/dialogs/platformAllowUtils.ts +91 -0
- package/src/renderer/components/team/dialogs/teammateRuntimeCompatibility.tsx +1 -1
- package/src/renderer/components/team/kanban/KanbanTaskCard.test.tsx +41 -0
- package/src/renderer/components/team/kanban/KanbanTaskCard.tsx +41 -86
- package/src/renderer/components/team/loop-console/LoopCommandComposer.tsx +310 -0
- package/src/renderer/components/team/loop-console/LoopConsolePanel.tsx +372 -0
- package/src/renderer/components/team/loop-console/loopSendIntent.test.ts +85 -0
- package/src/renderer/components/team/loop-console/loopSendIntent.ts +221 -0
- package/src/renderer/components/team/loop-console/useLeadSessionToolActivity.ts +74 -0
- package/src/renderer/components/team/loop-console/useLoopCommandSuggestions.ts +165 -0
- package/src/renderer/components/team/loop-console/useLoopConsoleController.ts +266 -0
- package/src/renderer/components/team/members/LeadModelRow.test.tsx +1 -1
- package/src/renderer/components/team/members/LeadModelRow.tsx +5 -3
- package/src/renderer/components/team/members/MemberDetailDialog.tsx +11 -0
- package/src/renderer/components/team/members/MemberDetailStats.tsx +13 -3
- package/src/renderer/components/team/members/MemberDraftRow.test.tsx +1 -1
- package/src/renderer/components/team/members/MemberDraftRow.tsx +1 -1
- package/src/renderer/components/team/members/MemberMessagesTab.tsx +2 -2
- package/src/renderer/components/team/members/MemberStatsTab.tsx +1 -1
- package/src/renderer/components/team/messages/MessageComposer.tsx +150 -44
- package/src/renderer/components/team/messages/MessagesFilterPopover.tsx +2 -2
- package/src/renderer/components/team/messages/MessagesPanel.tsx +34 -28
- package/src/renderer/components/team/schedule/CcCronScheduleDialog.tsx +6 -6
- package/src/renderer/components/team/taskLogs/ExactTaskLogCard.tsx +2 -2
- package/src/renderer/components/team/taskLogs/TaskLogStreamSection.tsx +1 -1
- package/src/renderer/components/terminal/TerminalPanel.tsx +2 -3
- package/src/renderer/components/ui/MentionableTextarea.tsx +5 -1
- package/src/renderer/constants/teamColors.ts +5 -5
- package/src/renderer/hooks/useExtensionsTabState.ts +1 -1
- package/src/renderer/hooks/useMentionDetection.ts +5 -1
- package/src/renderer/hooks/useProjectWorkflowCommands.ts +57 -0
- package/src/renderer/hooks/useTeamSuggestions.ts +2 -0
- package/src/renderer/index.css +19 -2
- package/src/renderer/main.tsx +7 -1
- package/src/renderer/store/index.ts +18 -1
- package/src/renderer/store/slices/extensionsSlice.ts +83 -0
- package/src/renderer/store/slices/tabSlice.ts +61 -0
- package/src/renderer/store/slices/teamSlice.ts +138 -9
- package/src/renderer/types/mention.ts +8 -0
- package/src/renderer/types/tabs.ts +3 -1
- package/src/renderer/utils/__tests__/bindProjectSlug.test.ts +69 -0
- package/src/renderer/utils/__tests__/groupTransformer.test.ts +148 -0
- package/src/renderer/utils/__tests__/initialRoute.test.ts +101 -0
- package/src/renderer/utils/__tests__/leadToolActivity.test.ts +124 -0
- package/src/renderer/utils/__tests__/mergeTeamMessages.test.ts +81 -0
- package/src/renderer/utils/__tests__/teamMessageFiltering.test.ts +213 -0
- package/src/renderer/utils/__tests__/teamMessageKey.test.ts +75 -0
- package/src/renderer/utils/__tests__/workflowCommandExecution.test.ts +173 -0
- package/src/renderer/utils/__tests__/workflowCommandSuggestions.test.ts +59 -0
- package/src/renderer/utils/bindProjectSlug.ts +57 -0
- package/src/renderer/utils/capabilityCommandExecution.ts +113 -0
- package/src/renderer/utils/initialRoute.ts +89 -0
- package/src/renderer/utils/leadToolActivity.ts +117 -0
- package/src/renderer/utils/loopShortcutSuggestions.ts +106 -0
- package/src/renderer/utils/mentionSuggestions.ts +1 -1
- package/src/renderer/utils/slashCommandRegistry.ts +231 -0
- package/src/renderer/utils/teamMentionDirective.ts +31 -0
- package/src/renderer/utils/workflowCommandExecution.ts +96 -0
- package/src/renderer/utils/workflowCommandSuggestions.ts +49 -0
- package/src/shared/types/api.ts +79 -4
- package/src/shared/types/ccConnect.ts +1 -0
- package/src/shared/types/extensions/api.ts +19 -0
- package/src/shared/types/extensions/capabilityPack.ts +118 -0
- package/src/shared/types/extensions/index.ts +29 -1
- package/src/shared/types/index.ts +6 -0
- package/src/shared/types/loopAssets.ts +54 -0
- package/src/shared/types/providers.ts +0 -16
- package/src/shared/types/systemManager.ts +26 -1
- package/src/shared/types/team.ts +41 -5
- package/src/shared/types/terminal.ts +2 -36
- package/src/shared/types/worker.test.ts +28 -0
- package/src/shared/types/worker.ts +3 -0
- package/src/shared/utils/__tests__/effortLevels.test.ts +88 -0
- package/src/shared/utils/__tests__/providerBackend.test.ts +88 -0
- package/src/shared/utils/__tests__/providerLaunchArgs.test.ts +220 -0
- package/src/shared/utils/claudeStreamJson.test.ts +187 -0
- package/src/shared/utils/claudeStreamJson.ts +153 -0
- package/src/shared/utils/providerLaunchArgs.ts +217 -0
- package/src/shared/utils/slashCommands.ts +10 -0
- package/src/types/node-pty.d.ts +8 -0
- package/dist-renderer/assets/channel-Ch7JrfUu.js +0 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-z9I4AnFy.js +0 -1
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-z9I4AnFy.js +0 -1
- package/dist-renderer/assets/clone-Dfi1Jx6l.js +0 -1
- package/dist-renderer/assets/index-iyjkpSus.css +0 -32
- package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-DTUIBfce.js +0 -1
- package/src/main/services/system-manager/SystemManagerPtyService.ts +0 -233
- package/src/renderer/components/common/TerminalPane.tsx +0 -213
- package/src/renderer/components/team/dialogs/useTeamEditForm.ts +0 -292
|
@@ -78,7 +78,7 @@ export const CcCronScheduleDialog = ({
|
|
|
78
78
|
const normalizedTimeout = Number.parseInt(timeoutMins, 10);
|
|
79
79
|
|
|
80
80
|
if (!normalizedTeamName) {
|
|
81
|
-
setError('
|
|
81
|
+
setError('请选择 Loop workspace');
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
84
|
if (!normalizedCron) {
|
|
@@ -86,7 +86,7 @@ export const CcCronScheduleDialog = ({
|
|
|
86
86
|
return;
|
|
87
87
|
}
|
|
88
88
|
if (!normalizedPrompt) {
|
|
89
|
-
setError('
|
|
89
|
+
setError('请填写定时指令');
|
|
90
90
|
return;
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -138,13 +138,13 @@ export const CcCronScheduleDialog = ({
|
|
|
138
138
|
<div className="space-y-4">
|
|
139
139
|
{canChooseTeam ? (
|
|
140
140
|
<div className="space-y-1.5">
|
|
141
|
-
<Label
|
|
141
|
+
<Label>Loop workspace</Label>
|
|
142
142
|
<select
|
|
143
143
|
value={selectedTeamName}
|
|
144
144
|
onChange={(event) => setSelectedTeamName(event.target.value)}
|
|
145
145
|
className="h-9 w-full rounded-md border border-[var(--color-border)] bg-[var(--color-surface)] px-2 text-sm text-[var(--color-text)]"
|
|
146
146
|
>
|
|
147
|
-
<option value=""
|
|
147
|
+
<option value="">选择 Loop workspace...</option>
|
|
148
148
|
{teams.map((team) => (
|
|
149
149
|
<option key={team.teamName} value={team.teamName}>
|
|
150
150
|
{team.displayName || team.teamName}
|
|
@@ -175,11 +175,11 @@ export const CcCronScheduleDialog = ({
|
|
|
175
175
|
</div>
|
|
176
176
|
|
|
177
177
|
<div className="space-y-1.5">
|
|
178
|
-
<Label
|
|
178
|
+
<Label>定时指令</Label>
|
|
179
179
|
<Textarea
|
|
180
180
|
value={prompt}
|
|
181
181
|
onChange={(event) => setPrompt(event.target.value)}
|
|
182
|
-
placeholder="
|
|
182
|
+
placeholder="到时间后发送给 Lead 的循环指令..."
|
|
183
183
|
className="min-h-28"
|
|
184
184
|
/>
|
|
185
185
|
</div>
|
|
@@ -30,7 +30,7 @@ function actorLabel(summary: BoardTaskExactLogSummary): string {
|
|
|
30
30
|
return summary.actor.memberName;
|
|
31
31
|
}
|
|
32
32
|
if (summary.actor.role === 'lead' || summary.actor.isSidechain === false) {
|
|
33
|
-
return '
|
|
33
|
+
return 'Loop Lead 会话';
|
|
34
34
|
}
|
|
35
35
|
return '未知参与者';
|
|
36
36
|
}
|
|
@@ -40,7 +40,7 @@ function describeSummary(summary: BoardTaskExactLogSummary): string {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function anchorKindLabel(summary: BoardTaskExactLogSummary): string {
|
|
43
|
-
return summary.anchorKind === 'tool' ? '工具' : '
|
|
43
|
+
return summary.anchorKind === 'tool' ? '工具' : '动态';
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
function describeDetailState(state: ExactTaskLogDetailState | undefined): string | null {
|
|
@@ -39,7 +39,7 @@ function actorLabel(actor: BoardTaskLogActor): string {
|
|
|
39
39
|
return actor.memberName;
|
|
40
40
|
}
|
|
41
41
|
if (actor.role === 'lead' || actor.isSidechain === false) {
|
|
42
|
-
return '
|
|
42
|
+
return 'Loop Lead 会话';
|
|
43
43
|
}
|
|
44
44
|
if (actor.agentId) {
|
|
45
45
|
return `成员 ${actor.agentId.slice(0, 8)}`;
|
|
@@ -9,9 +9,8 @@
|
|
|
9
9
|
* final frame instead of dumping every intermediate line
|
|
10
10
|
* - optional `$ command` prompt line so a Bash call reads like a real terminal
|
|
11
11
|
*
|
|
12
|
-
* It is intentionally lightweight
|
|
13
|
-
*
|
|
14
|
-
* live PTY.
|
|
12
|
+
* It is intentionally lightweight: the session view is a read-only viewer of
|
|
13
|
+
* recorded output, so we only need faithful rendering, not a live PTY.
|
|
15
14
|
*/
|
|
16
15
|
|
|
17
16
|
import { useMemo, useState } from 'react';
|
|
@@ -356,6 +356,8 @@ interface MentionableTextareaProps extends Omit<
|
|
|
356
356
|
taskSuggestions?: MentionSuggestion[];
|
|
357
357
|
/** Slash command suggestions for /command autocomplete */
|
|
358
358
|
commandSuggestions?: MentionSuggestion[];
|
|
359
|
+
/** Called after a suggestion is inserted into the textarea. */
|
|
360
|
+
onSuggestionSelected?: (suggestion: MentionSuggestion, insertedText: string) => void;
|
|
359
361
|
/** Called when Enter (without Shift) is pressed. */
|
|
360
362
|
onModEnter?: () => void;
|
|
361
363
|
/** Called when Shift+Tab is pressed. */
|
|
@@ -388,6 +390,7 @@ export const MentionableTextarea = React.forwardRef<HTMLTextAreaElement, Mention
|
|
|
388
390
|
teamSuggestions = [],
|
|
389
391
|
taskSuggestions = [],
|
|
390
392
|
commandSuggestions = [],
|
|
393
|
+
onSuggestionSelected,
|
|
391
394
|
onModEnter,
|
|
392
395
|
onShiftTab,
|
|
393
396
|
dismissMentionsRef,
|
|
@@ -454,6 +457,7 @@ export const MentionableTextarea = React.forwardRef<HTMLTextAreaElement, Mention
|
|
|
454
457
|
if (trigger.triggerChar !== '/') return true;
|
|
455
458
|
return text.slice(0, trigger.triggerIndex).trim().length === 0;
|
|
456
459
|
},
|
|
460
|
+
onSuggestionSelected,
|
|
457
461
|
});
|
|
458
462
|
|
|
459
463
|
// Expose dismiss to parent via ref for external close (e.g. Send button click)
|
|
@@ -1069,7 +1073,7 @@ export const MentionableTextarea = React.forwardRef<HTMLTextAreaElement, Mention
|
|
|
1069
1073
|
const rotatingTips = React.useMemo(
|
|
1070
1074
|
() => [
|
|
1071
1075
|
'Tips:输入 @ 可提及成员、团队或文件,输入 # 可引用任务。',
|
|
1072
|
-
'Tips
|
|
1076
|
+
'Tips:不要把所有工作都堆给 Loop Lead,可以让 Lead 把循环分配给合适的成员。',
|
|
1073
1077
|
...extraTips,
|
|
1074
1078
|
],
|
|
1075
1079
|
[extraTips]
|
|
@@ -24,11 +24,11 @@ export interface TeamColorSet {
|
|
|
24
24
|
|
|
25
25
|
const TEAMMATE_COLORS: Record<string, TeamColorSet> = {
|
|
26
26
|
blue: {
|
|
27
|
-
border: '#
|
|
28
|
-
badge: 'rgba(
|
|
29
|
-
badgeLight: 'rgba(
|
|
30
|
-
text: '#
|
|
31
|
-
textLight: '#
|
|
27
|
+
border: '#3b82f6',
|
|
28
|
+
badge: 'rgba(59, 130, 246, 0.15)',
|
|
29
|
+
badgeLight: 'rgba(59, 130, 246, 0.12)',
|
|
30
|
+
text: '#60a5fa',
|
|
31
|
+
textLight: '#2563eb',
|
|
32
32
|
},
|
|
33
33
|
saffron: {
|
|
34
34
|
border: '#eab308',
|
|
@@ -8,7 +8,7 @@ import { useCallback, useMemo, useState } from 'react';
|
|
|
8
8
|
|
|
9
9
|
import type { PluginCapability, PluginFilters, PluginSortField } from '@shared/types/extensions';
|
|
10
10
|
|
|
11
|
-
export type ExtensionsSubTab = 'plugins';
|
|
11
|
+
export type ExtensionsSubTab = 'plugins' | 'capability-packs';
|
|
12
12
|
|
|
13
13
|
interface PluginSortState {
|
|
14
14
|
field: PluginSortField;
|
|
@@ -17,6 +17,8 @@ interface UseMentionDetectionOptions {
|
|
|
17
17
|
isTriggerEnabled?: (triggerChar: string) => boolean;
|
|
18
18
|
/** Additional validation for trigger matches before opening the dropdown. */
|
|
19
19
|
isTriggerMatchValid?: (trigger: MentionTrigger, text: string) => boolean;
|
|
20
|
+
/** Called after a suggestion is inserted into the textarea. */
|
|
21
|
+
onSuggestionSelected?: (suggestion: MentionSuggestion, insertedText: string) => void;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export interface DropdownPosition {
|
|
@@ -179,6 +181,7 @@ export function useMentionDetection({
|
|
|
179
181
|
triggerChars = ['@'],
|
|
180
182
|
isTriggerEnabled,
|
|
181
183
|
isTriggerMatchValid,
|
|
184
|
+
onSuggestionSelected,
|
|
182
185
|
}: UseMentionDetectionOptions): UseMentionDetectionResult {
|
|
183
186
|
const [isOpen, setIsOpen] = useState(false);
|
|
184
187
|
const [activeTriggerChar, setActiveTriggerChar] = useState<string | null>(null);
|
|
@@ -234,6 +237,7 @@ export function useMentionDetection({
|
|
|
234
237
|
const newCursorPos = before.length + insertion.length;
|
|
235
238
|
|
|
236
239
|
onValueChange(newValue);
|
|
240
|
+
onSuggestionSelected?.(s, insertionBody);
|
|
237
241
|
dismiss();
|
|
238
242
|
|
|
239
243
|
// Set cursor position after React re-render
|
|
@@ -242,7 +246,7 @@ export function useMentionDetection({
|
|
|
242
246
|
textarea.setSelectionRange(newCursorPos, newCursorPos);
|
|
243
247
|
});
|
|
244
248
|
},
|
|
245
|
-
[value, onValueChange, textareaRef, dismiss]
|
|
249
|
+
[value, onValueChange, onSuggestionSelected, textareaRef, dismiss]
|
|
246
250
|
);
|
|
247
251
|
|
|
248
252
|
/**
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load a team project's `.claude/commands/*.md` workflow prompts and expose them
|
|
3
|
+
* as command suggestions for the Loop console.
|
|
4
|
+
*
|
|
5
|
+
* The team Loop console previously only showed global shortcuts + capability
|
|
6
|
+
* packs, so a project's own commands never appeared. This mirrors the admin
|
|
7
|
+
* console's workflow loading, scoped to the team's project path.
|
|
8
|
+
*/
|
|
9
|
+
import { useEffect, useState } from 'react';
|
|
10
|
+
|
|
11
|
+
import { api } from '@renderer/api';
|
|
12
|
+
import { buildWorkflowCommandSuggestion } from '@renderer/utils/workflowCommandSuggestions';
|
|
13
|
+
|
|
14
|
+
import type { MentionSuggestion } from '@renderer/types/mention';
|
|
15
|
+
|
|
16
|
+
const EMPTY: MentionSuggestion[] = [];
|
|
17
|
+
|
|
18
|
+
function commandsFolder(projectPath: string): string {
|
|
19
|
+
return `${projectPath.replace(/[\\/]+$/, '')}/.claude/commands`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function useProjectWorkflowCommands(projectPath?: string | null): MentionSuggestion[] {
|
|
23
|
+
const [suggestions, setSuggestions] = useState<MentionSuggestion[]>(EMPTY);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const trimmed = projectPath?.trim();
|
|
27
|
+
if (!trimmed) {
|
|
28
|
+
setSuggestions(EMPTY);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
let cancelled = false;
|
|
32
|
+
void (async () => {
|
|
33
|
+
try {
|
|
34
|
+
const result = await api.systemManager.listWorkflowPrompts(commandsFolder(trimmed));
|
|
35
|
+
if (cancelled) return;
|
|
36
|
+
const seen = new Set<string>();
|
|
37
|
+
const next = result.prompts
|
|
38
|
+
.map((prompt) => buildWorkflowCommandSuggestion(prompt, 'team-workflow'))
|
|
39
|
+
.filter((suggestion) => {
|
|
40
|
+
const key = suggestion.command ?? suggestion.id;
|
|
41
|
+
if (seen.has(key)) return false;
|
|
42
|
+
seen.add(key);
|
|
43
|
+
return true;
|
|
44
|
+
});
|
|
45
|
+
setSuggestions(next);
|
|
46
|
+
} catch {
|
|
47
|
+
// Missing .claude/commands is normal — the project simply has no custom commands.
|
|
48
|
+
if (!cancelled) setSuggestions(EMPTY);
|
|
49
|
+
}
|
|
50
|
+
})();
|
|
51
|
+
return () => {
|
|
52
|
+
cancelled = true;
|
|
53
|
+
};
|
|
54
|
+
}, [projectPath]);
|
|
55
|
+
|
|
56
|
+
return suggestions;
|
|
57
|
+
}
|
package/src/renderer/index.css
CHANGED
|
@@ -24,6 +24,11 @@
|
|
|
24
24
|
--color-text-secondary: #7a8190;
|
|
25
25
|
--color-text-muted: #4f5564;
|
|
26
26
|
--color-accent: #4ade80;
|
|
27
|
+
--color-accent-rgb: 74, 222, 128;
|
|
28
|
+
--color-accent-soft: rgba(74, 222, 128, 0.08);
|
|
29
|
+
--color-accent-muted: rgba(74, 222, 128, 0.14);
|
|
30
|
+
--color-accent-border: rgba(74, 222, 128, 0.32);
|
|
31
|
+
--color-accent-glow: rgba(74, 222, 128, 0.24);
|
|
27
32
|
/* Accent — phosphor green */
|
|
28
33
|
/* Scrollbar colors */
|
|
29
34
|
--scrollbar-thumb: rgba(74, 222, 128, 0.12);
|
|
@@ -473,6 +478,11 @@
|
|
|
473
478
|
--color-text-muted: #6d6b65;
|
|
474
479
|
/* Warm muted text */
|
|
475
480
|
--color-accent: #4f46e5;
|
|
481
|
+
--color-accent-rgb: 79, 70, 229;
|
|
482
|
+
--color-accent-soft: rgba(79, 70, 229, 0.08);
|
|
483
|
+
--color-accent-muted: rgba(79, 70, 229, 0.14);
|
|
484
|
+
--color-accent-border: rgba(79, 70, 229, 0.32);
|
|
485
|
+
--color-accent-glow: rgba(79, 70, 229, 0.22);
|
|
476
486
|
/* Accent — indigo-600, visible on light surfaces */
|
|
477
487
|
/* Assessment severity colors - darker for light backgrounds */
|
|
478
488
|
--assess-good: #16a34a;
|
|
@@ -797,8 +807,15 @@ body {
|
|
|
797
807
|
height: 100%;
|
|
798
808
|
overflow: hidden;
|
|
799
809
|
font-family:
|
|
800
|
-
'Agave',
|
|
801
|
-
|
|
810
|
+
'Agave',
|
|
811
|
+
'JetBrains Mono',
|
|
812
|
+
'Menlo',
|
|
813
|
+
'Monaco',
|
|
814
|
+
'Consolas',
|
|
815
|
+
-apple-system,
|
|
816
|
+
BlinkMacSystemFont,
|
|
817
|
+
'Segoe UI',
|
|
818
|
+
monospace;
|
|
802
819
|
-webkit-font-smoothing: antialiased;
|
|
803
820
|
-moz-osx-font-smoothing: grayscale;
|
|
804
821
|
background-color: var(--color-surface);
|
package/src/renderer/main.tsx
CHANGED
|
@@ -7,7 +7,8 @@ import ReactDOM from 'react-dom/client';
|
|
|
7
7
|
|
|
8
8
|
import { App } from './App';
|
|
9
9
|
import { initSentryRenderer } from './sentry';
|
|
10
|
-
import { initializeNotificationListeners } from './store';
|
|
10
|
+
import { initializeNotificationListeners, useStore } from './store';
|
|
11
|
+
import { restoreInitialRoute } from './utils/initialRoute';
|
|
11
12
|
|
|
12
13
|
declare global {
|
|
13
14
|
interface Window {
|
|
@@ -23,6 +24,11 @@ if (!window.__claudeTeamsUiDidInit) {
|
|
|
23
24
|
initializeNotificationListeners();
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
// Restore the URL route into the store BEFORE first render so the initial paint
|
|
28
|
+
// already shows the correct tab. This closes the first-load blank-content race
|
|
29
|
+
// (e.g. /teams rendering empty until a post-mount effect opened the tab).
|
|
30
|
+
restoreInitialRoute(useStore.getState(), window.location.pathname);
|
|
31
|
+
|
|
26
32
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
27
33
|
<React.StrictMode>
|
|
28
34
|
<App />
|
|
@@ -1216,6 +1216,23 @@ export function initializeNotificationListeners(): () => void {
|
|
|
1216
1216
|
return;
|
|
1217
1217
|
}
|
|
1218
1218
|
|
|
1219
|
+
// Live token stream from a direct-CLI subprocess: accumulate each text delta into
|
|
1220
|
+
// an in-progress optimistic assistant reply keyed by messageId. The canonical reply
|
|
1221
|
+
// (same messageId, appended on the turn's result) prunes this twin on the next inbox
|
|
1222
|
+
// refresh — so no duplicate, and a missing/failed turn just leaves a partial bubble.
|
|
1223
|
+
if (event.type === 'direct-cli-stream') {
|
|
1224
|
+
if (isStaleRuntimeEvent) return;
|
|
1225
|
+
if (event.kind === 'delta' && event.messageId && typeof event.text === 'string') {
|
|
1226
|
+
useStore.getState().appendStreamingTeamReply(event.teamName, {
|
|
1227
|
+
messageId: event.messageId,
|
|
1228
|
+
delta: event.text,
|
|
1229
|
+
from: event.from ?? event.teamName,
|
|
1230
|
+
to: 'user',
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1219
1236
|
if (event.type === 'log-source-change') {
|
|
1220
1237
|
if (!event?.teamName || !isTeamVisibleInAnyPane(event.teamName)) {
|
|
1221
1238
|
return;
|
|
@@ -1422,7 +1439,7 @@ export function initializeNotificationListeners(): () => void {
|
|
|
1422
1439
|
useStore.setState({ cliInstallerState: 'verifying', cliInstallerDetail: detail });
|
|
1423
1440
|
break;
|
|
1424
1441
|
case 'installing': {
|
|
1425
|
-
// Accumulate log lines and raw chunks for
|
|
1442
|
+
// Accumulate log lines and raw chunks for terminal-style rendering
|
|
1426
1443
|
const prevLogs = useStore.getState().cliInstallerLogs;
|
|
1427
1444
|
const prevRaw = useStore.getState().cliInstallerRawChunks;
|
|
1428
1445
|
const newLogs = detail ? [...prevLogs, detail].slice(-50) : prevLogs;
|
|
@@ -18,10 +18,15 @@ import { findPaneByTabId, updatePane } from '../utils/paneHelpers';
|
|
|
18
18
|
|
|
19
19
|
import type { AppState } from '../types';
|
|
20
20
|
import type {
|
|
21
|
+
CapabilityPackExportRequest,
|
|
22
|
+
CapabilityPackImportRequest,
|
|
23
|
+
CapabilityPackListResult,
|
|
24
|
+
CapabilityPackMutationResult,
|
|
21
25
|
EnrichedPlugin,
|
|
22
26
|
ExtensionOperationState,
|
|
23
27
|
InstalledMcpEntry,
|
|
24
28
|
InstallScope,
|
|
29
|
+
LoadedCapabilityPack,
|
|
25
30
|
McpCatalogItem,
|
|
26
31
|
McpCustomInstallRequest,
|
|
27
32
|
McpInstallRequest,
|
|
@@ -79,6 +84,14 @@ export interface ExtensionsSlice {
|
|
|
79
84
|
message?: string;
|
|
80
85
|
}>;
|
|
81
86
|
|
|
87
|
+
// ── Capability packs cache ──
|
|
88
|
+
capabilityPackList: CapabilityPackListResult | null;
|
|
89
|
+
capabilityPacks: LoadedCapabilityPack[];
|
|
90
|
+
capabilityPacksLoading: boolean;
|
|
91
|
+
capabilityPacksError: string | null;
|
|
92
|
+
capabilityPacksMutationLoading: boolean;
|
|
93
|
+
capabilityPacksMutationError: string | null;
|
|
94
|
+
|
|
82
95
|
// ── Skills catalog cache ──
|
|
83
96
|
skillsUserCatalog: SkillCatalogItem[];
|
|
84
97
|
skillsProjectCatalogByProjectPath: Record<string, SkillCatalogItem[]>;
|
|
@@ -101,6 +114,13 @@ export interface ExtensionsSlice {
|
|
|
101
114
|
mcpBrowse: (cursor?: string) => Promise<void>;
|
|
102
115
|
mcpFetchInstalled: (projectPath?: string) => Promise<void>;
|
|
103
116
|
runMcpDiagnostics: (projectPath?: string) => Promise<void>;
|
|
117
|
+
fetchCapabilityPacks: () => Promise<void>;
|
|
118
|
+
importCapabilityPack: (
|
|
119
|
+
request: CapabilityPackImportRequest
|
|
120
|
+
) => Promise<CapabilityPackMutationResult>;
|
|
121
|
+
exportCapabilityPack: (
|
|
122
|
+
request: CapabilityPackExportRequest
|
|
123
|
+
) => Promise<CapabilityPackMutationResult>;
|
|
104
124
|
fetchSkillsCatalog: (projectPath?: string) => Promise<void>;
|
|
105
125
|
fetchSkillDetail: (skillId: string, projectPath?: string) => Promise<void>;
|
|
106
126
|
previewSkillUpsert: (request: SkillUpsertRequest) => Promise<SkillReviewPreview>;
|
|
@@ -394,6 +414,13 @@ export const createExtensionsSlice: StateCreator<AppState, [], [], ExtensionsSli
|
|
|
394
414
|
installErrors: {},
|
|
395
415
|
extensionToasts: [],
|
|
396
416
|
|
|
417
|
+
capabilityPackList: null,
|
|
418
|
+
capabilityPacks: [],
|
|
419
|
+
capabilityPacksLoading: false,
|
|
420
|
+
capabilityPacksError: null,
|
|
421
|
+
capabilityPacksMutationLoading: false,
|
|
422
|
+
capabilityPacksMutationError: null,
|
|
423
|
+
|
|
397
424
|
skillsUserCatalog: [],
|
|
398
425
|
skillsProjectCatalogByProjectPath: {},
|
|
399
426
|
skillsCatalogLoadingByProjectPath: {},
|
|
@@ -668,6 +695,62 @@ export const createExtensionsSlice: StateCreator<AppState, [], [], ExtensionsSli
|
|
|
668
695
|
await promise;
|
|
669
696
|
},
|
|
670
697
|
|
|
698
|
+
fetchCapabilityPacks: async () => {
|
|
699
|
+
if (!api.capabilityPacks) return;
|
|
700
|
+
|
|
701
|
+
set({ capabilityPacksLoading: true, capabilityPacksError: null });
|
|
702
|
+
try {
|
|
703
|
+
const result = await api.capabilityPacks.list();
|
|
704
|
+
set({
|
|
705
|
+
capabilityPackList: result,
|
|
706
|
+
capabilityPacks: result.packs,
|
|
707
|
+
capabilityPacksLoading: false,
|
|
708
|
+
capabilityPacksError: null,
|
|
709
|
+
});
|
|
710
|
+
} catch (err) {
|
|
711
|
+
set({
|
|
712
|
+
capabilityPacksLoading: false,
|
|
713
|
+
capabilityPacksError:
|
|
714
|
+
err instanceof Error ? err.message : 'Failed to load capability packs',
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
},
|
|
718
|
+
|
|
719
|
+
importCapabilityPack: async (request: CapabilityPackImportRequest) => {
|
|
720
|
+
if (!api.capabilityPacks) {
|
|
721
|
+
throw new Error('Capability packs API is not available');
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
set({ capabilityPacksMutationLoading: true, capabilityPacksMutationError: null });
|
|
725
|
+
try {
|
|
726
|
+
const result = await api.capabilityPacks.importPack(request);
|
|
727
|
+
await get().fetchCapabilityPacks();
|
|
728
|
+
set({ capabilityPacksMutationLoading: false });
|
|
729
|
+
return result;
|
|
730
|
+
} catch (err) {
|
|
731
|
+
const message = err instanceof Error ? err.message : 'Failed to import capability pack';
|
|
732
|
+
set({ capabilityPacksMutationLoading: false, capabilityPacksMutationError: message });
|
|
733
|
+
throw err;
|
|
734
|
+
}
|
|
735
|
+
},
|
|
736
|
+
|
|
737
|
+
exportCapabilityPack: async (request: CapabilityPackExportRequest) => {
|
|
738
|
+
if (!api.capabilityPacks) {
|
|
739
|
+
throw new Error('Capability packs API is not available');
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
set({ capabilityPacksMutationLoading: true, capabilityPacksMutationError: null });
|
|
743
|
+
try {
|
|
744
|
+
const result = await api.capabilityPacks.exportPack(request);
|
|
745
|
+
set({ capabilityPacksMutationLoading: false });
|
|
746
|
+
return result;
|
|
747
|
+
} catch (err) {
|
|
748
|
+
const message = err instanceof Error ? err.message : 'Failed to export capability pack';
|
|
749
|
+
set({ capabilityPacksMutationLoading: false, capabilityPacksMutationError: message });
|
|
750
|
+
throw err;
|
|
751
|
+
}
|
|
752
|
+
},
|
|
753
|
+
|
|
671
754
|
fetchSkillsCatalog: async (projectPath?: string) => {
|
|
672
755
|
if (!api.skills) return;
|
|
673
756
|
|
|
@@ -52,6 +52,8 @@ export interface TabSlice {
|
|
|
52
52
|
closeTab: (tabId: string) => void;
|
|
53
53
|
setActiveTab: (tabId: string) => void;
|
|
54
54
|
openDashboard: () => void;
|
|
55
|
+
openSocietyTab: () => void;
|
|
56
|
+
openChatTab: () => void;
|
|
55
57
|
openSessionReport: (sourceTabId: string) => void;
|
|
56
58
|
getActiveTab: () => Tab | null;
|
|
57
59
|
isSessionOpen: (sessionId: string) => boolean;
|
|
@@ -455,6 +457,65 @@ export const createTabSlice: StateCreator<AppState, [], [], TabSlice> = (set, ge
|
|
|
455
457
|
set(syncFromLayout(newLayout));
|
|
456
458
|
},
|
|
457
459
|
|
|
460
|
+
// Open a worker-society tab — reuse existing one if found, otherwise create new
|
|
461
|
+
openSocietyTab: () => {
|
|
462
|
+
const state = get();
|
|
463
|
+
const { paneLayout } = state;
|
|
464
|
+
|
|
465
|
+
const existing = getAllTabs(paneLayout).find((t) => t.type === 'society');
|
|
466
|
+
if (existing) {
|
|
467
|
+
const pane = findPaneByTabId(paneLayout, existing.id);
|
|
468
|
+
if (pane) {
|
|
469
|
+
const fromIndex = pane.tabs.findIndex((t) => t.id === existing.id);
|
|
470
|
+
const lastIndex = pane.tabs.length - 1;
|
|
471
|
+
if (fromIndex !== -1 && fromIndex !== lastIndex) {
|
|
472
|
+
const reordered = [...pane.tabs];
|
|
473
|
+
const [moved] = reordered.splice(fromIndex, 1);
|
|
474
|
+
reordered.push(moved);
|
|
475
|
+
const updatedPane = { ...pane, tabs: reordered, activeTabId: existing.id };
|
|
476
|
+
const newLayout = updatePane(paneLayout, updatedPane);
|
|
477
|
+
set(syncFromLayout(newLayout));
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
state.setActiveTab(existing.id);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const focusedPane = findPane(paneLayout, paneLayout.focusedPaneId);
|
|
486
|
+
if (!focusedPane) return;
|
|
487
|
+
|
|
488
|
+
const newTab: Tab = {
|
|
489
|
+
id: crypto.randomUUID(),
|
|
490
|
+
type: 'society',
|
|
491
|
+
label: 'Worker 社会',
|
|
492
|
+
createdAt: Date.now(),
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
const updatedPane = {
|
|
496
|
+
...focusedPane,
|
|
497
|
+
tabs: [...focusedPane.tabs, newTab],
|
|
498
|
+
activeTabId: newTab.id,
|
|
499
|
+
};
|
|
500
|
+
const newLayout = updatePane(paneLayout, updatedPane);
|
|
501
|
+
set(syncFromLayout(newLayout));
|
|
502
|
+
},
|
|
503
|
+
|
|
504
|
+
openChatTab: () => {
|
|
505
|
+
const state = get();
|
|
506
|
+
const focusedPane = findPane(state.paneLayout, state.paneLayout.focusedPaneId);
|
|
507
|
+
const existingTab = focusedPane?.tabs.find((tab) => tab.type === 'chat');
|
|
508
|
+
if (existingTab) {
|
|
509
|
+
state.setActiveTab(existingTab.id);
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
state.openTab({
|
|
514
|
+
type: 'chat',
|
|
515
|
+
label: '加入飞书群',
|
|
516
|
+
});
|
|
517
|
+
},
|
|
518
|
+
|
|
458
519
|
// Open a session report tab based on a source session tab
|
|
459
520
|
openSessionReport: (sourceTabId: string) => {
|
|
460
521
|
const state = get();
|