@yancyyu/openhermit 1.6.41 → 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-Br0X83Jf.js → ProjectEditorOverlay-C98qSs7-.js} +1 -1
- package/dist-renderer/assets/{TeamGraphOverlay-DHMTbZPZ.js → TeamGraphOverlay-CsBbZwcL.js} +1 -1
- package/dist-renderer/assets/{_basePickBy-DzIiX7yH.js → _basePickBy-ZOyLWjMK.js} +1 -1
- package/dist-renderer/assets/{_baseUniq-6hZuzTLU.js → _baseUniq-DBb726rt.js} +1 -1
- package/dist-renderer/assets/{arc-CXgO6fx_.js → arc-CdiTaR_R.js} +1 -1
- package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-DKWgtDHr.js → architectureDiagram-VXUJARFQ-Cz3sc5TH.js} +1 -1
- package/dist-renderer/assets/{blockDiagram-VD42YOAC-DOMUcC40.js → blockDiagram-VD42YOAC-DE4c-KJ3.js} +1 -1
- package/dist-renderer/assets/{c4Diagram-YG6GDRKO-B_k2L7qX.js → c4Diagram-YG6GDRKO-CmTMDTrV.js} +1 -1
- package/dist-renderer/assets/channel-KTpqi9eT.js +1 -0
- package/dist-renderer/assets/{chunk-4BX2VUAB-BeD_ccFy.js → chunk-4BX2VUAB-rhHy3tFl.js} +1 -1
- package/dist-renderer/assets/{chunk-55IACEB6-ClZfkA5w.js → chunk-55IACEB6-fLZBzuo_.js} +1 -1
- package/dist-renderer/assets/{chunk-B4BG7PRW-5XluxXsn.js → chunk-B4BG7PRW-DOzxQhim.js} +1 -1
- package/dist-renderer/assets/{chunk-DI55MBZ5-BzIjjNVm.js → chunk-DI55MBZ5-COQCcXC5.js} +1 -1
- package/dist-renderer/assets/{chunk-FMBD7UC4-HgH3MK_H.js → chunk-FMBD7UC4-IKU9U_Y4.js} +1 -1
- package/dist-renderer/assets/{chunk-QN33PNHL-WeC5T3Ba.js → chunk-QN33PNHL-D6WV154X.js} +1 -1
- package/dist-renderer/assets/{chunk-QZHKN3VN-Cu1ApHfW.js → chunk-QZHKN3VN-D90_2DQp.js} +1 -1
- package/dist-renderer/assets/{chunk-TZMSLE5B-BOhlynJM.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-DGZSihDQ.js → cose-bilkent-S5V4N54A-6WiK6U2P.js} +1 -1
- package/dist-renderer/assets/{dagre-6UL2VRFP-CnxwCbku.js → dagre-6UL2VRFP-DF4MMuTn.js} +1 -1
- package/dist-renderer/assets/{diagram-PSM6KHXK-DsIhoxdI.js → diagram-PSM6KHXK-CcF1eZ7E.js} +1 -1
- package/dist-renderer/assets/{diagram-QEK2KX5R-Cmh9KUF5.js → diagram-QEK2KX5R-DYlOVPQB.js} +1 -1
- package/dist-renderer/assets/{diagram-S2PKOQOG-CKxV456A.js → diagram-S2PKOQOG-BHXWsZOP.js} +1 -1
- package/dist-renderer/assets/{erDiagram-Q2GNP2WA-EnvYjOjc.js → erDiagram-Q2GNP2WA-GjmuBx8d.js} +1 -1
- package/dist-renderer/assets/{flowDiagram-NV44I4VS-BmNeWY_A.js → flowDiagram-NV44I4VS-BuS7YVHk.js} +1 -1
- package/dist-renderer/assets/{ganttDiagram-JELNMOA3-D30fyK-u.js → ganttDiagram-JELNMOA3-3Teu5tAa.js} +1 -1
- package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-CrUNiYg1.js → gitGraphDiagram-V2S2FVAM-BiLdCYu5.js} +1 -1
- package/dist-renderer/assets/{graph-CY1gTfTb.js → graph-CDP_R8ct.js} +1 -1
- package/dist-renderer/assets/{index-CaEbzwAU.js → index-BSZdT-g-.js} +1 -1
- package/dist-renderer/assets/{index-D5K-SjBG.js → index-BhWvMqsz.js} +1 -1
- package/dist-renderer/assets/{index-9_hO4N1e.js → index-C2_AupSj.js} +1 -1
- package/dist-renderer/assets/{index-59r209c1.js → index-C5ujiwAR.js} +580 -588
- package/dist-renderer/assets/index-CIS2CTK9.css +1 -0
- package/dist-renderer/assets/{index-DMR9B1UP.js → index-CVNjLwkq.js} +1 -1
- package/dist-renderer/assets/{index-BC2hXmg_.js → index-CwG3se0q.js} +1 -1
- package/dist-renderer/assets/{infoDiagram-HS3SLOUP-By_XUlcD.js → infoDiagram-HS3SLOUP-DLHUFo72.js} +1 -1
- package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-BM1LJE9m.js → journeyDiagram-XKPGCS4Q-BE07RpJD.js} +1 -1
- package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-DHIW3aTA.js → kanban-definition-3W4ZIXB7-DDHZy4NB.js} +1 -1
- package/dist-renderer/assets/{layout-DAKiL_Mo.js → layout-5nA5wUxO.js} +1 -1
- package/dist-renderer/assets/{linear-DwOaRYea.js → linear-BtF1i2qN.js} +1 -1
- package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-b7bJ2cha.js → mindmap-definition-VGOIOE7T-Z1Ui9Sqy.js} +1 -1
- package/dist-renderer/assets/{pieDiagram-ADFJNKIX-DxyL9Zr2.js → pieDiagram-ADFJNKIX-LCjxckWv.js} +1 -1
- package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-CR33pHlF.js → quadrantDiagram-AYHSOK5B-BOwKjSco.js} +1 -1
- package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-BAiSRSlh.js → requirementDiagram-UZGBJVZJ-pChP8Znd.js} +1 -1
- package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-C8JmDjoa.js → sankeyDiagram-TZEHDZUN-DifZ2qpo.js} +1 -1
- package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-c1d0Wi1m.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-nT8BiH2O.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-DpoRepUA.js → timeline-definition-IT6M3QCI-CPgokIo8.js} +1 -1
- package/dist-renderer/assets/{treemap-GDKQZRPO-C41UJeIH.js → treemap-GDKQZRPO-DAVqSR9L.js} +1 -1
- package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-KMjGARKN.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 +1731 -539
- 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 +744 -0
- 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 +132 -52
- 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 +144 -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 +189 -57
- 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 +43 -3
- 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-D0XS_akr.js +0 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-D13Ffs0U.js +0 -1
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-D13Ffs0U.js +0 -1
- package/dist-renderer/assets/clone-B1ZrxI1D.js +0 -1
- package/dist-renderer/assets/index-iyjkpSus.css +0 -32
- package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-Dmibmlso.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
|
@@ -25,6 +25,7 @@ import { useCreateTeamDraft } from '@renderer/hooks/useCreateTeamDraft';
|
|
|
25
25
|
import { useTheme } from '@renderer/hooks/useTheme';
|
|
26
26
|
import { cn } from '@renderer/lib/utils';
|
|
27
27
|
import { normalizePath } from '@renderer/utils/pathNormalize';
|
|
28
|
+
import { generateBindProject, isValidBindProject } from '@renderer/utils/bindProjectSlug';
|
|
28
29
|
import { isEphemeralProjectPath } from '@shared/utils/ephemeralProjectPath';
|
|
29
30
|
import { AlertTriangle, CheckCircle2, X } from 'lucide-react';
|
|
30
31
|
|
|
@@ -62,19 +63,7 @@ export interface TeamCopyData {
|
|
|
62
63
|
templateDirectoryId?: string;
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
* Sanitize team name: keep Unicode letters and digits (Chinese, Latin, etc.),
|
|
67
|
-
* replace other sequences with `-`, then lowercase Latin chars.
|
|
68
|
-
*/
|
|
69
|
-
function sanitizeTeamName(name: string): string {
|
|
70
|
-
const trimmed = name.trim();
|
|
71
|
-
if (!trimmed) return '';
|
|
72
|
-
let result = trimmed
|
|
73
|
-
.replace(/[^\p{L}\p{N}]+/gu, '-')
|
|
74
|
-
.replace(/^-+|-+$/g, '')
|
|
75
|
-
.toLowerCase();
|
|
76
|
-
return result;
|
|
77
|
-
}
|
|
66
|
+
// bindProject slug rules live in @renderer/utils/bindProjectSlug (unit-tested).
|
|
78
67
|
|
|
79
68
|
// ---------------------------------------------------------------------------
|
|
80
69
|
// Wizard step types
|
|
@@ -92,6 +81,8 @@ interface CreateTeamDialogProps {
|
|
|
92
81
|
provisioningErrorsByTeam: Record<string, string | null>;
|
|
93
82
|
clearProvisioningError?: (teamName?: string) => void;
|
|
94
83
|
existingTeamNames: string[];
|
|
84
|
+
existingBindProjects?: string[];
|
|
85
|
+
existingDisplayNames?: string[];
|
|
95
86
|
provisioningTeamNames?: string[];
|
|
96
87
|
activeTeams?: ActiveTeamRef[];
|
|
97
88
|
initialData?: unknown;
|
|
@@ -107,6 +98,8 @@ export const CreateTeamDialog = ({
|
|
|
107
98
|
provisioningErrorsByTeam,
|
|
108
99
|
clearProvisioningError,
|
|
109
100
|
existingTeamNames,
|
|
101
|
+
existingBindProjects = [],
|
|
102
|
+
existingDisplayNames = [],
|
|
110
103
|
provisioningTeamNames = [],
|
|
111
104
|
activeTeams,
|
|
112
105
|
defaultProjectPath,
|
|
@@ -137,6 +130,14 @@ export const CreateTeamDialog = ({
|
|
|
137
130
|
const [selectedHarness, setSelectedHarness] = useState<CcAgentType>('claudecode');
|
|
138
131
|
const [description, setDescription] = useState('');
|
|
139
132
|
|
|
133
|
+
// ── bindProject (ASCII unique identifier) ────────────────────────────
|
|
134
|
+
// Only the *manual* override is state. The auto value is DERIVED (below) so
|
|
135
|
+
// it is collision-free in the SAME render as `existingBindProjectSet`. A
|
|
136
|
+
// state + useEffect pair lagged one render behind the set and flickered a
|
|
137
|
+
// false "该项目标识已存在" red box whenever the teams list refreshed.
|
|
138
|
+
const [manualBindProject, setManualBindProject] = useState('');
|
|
139
|
+
const [bindProjectManuallyEdited, setBindProjectManuallyEdited] = useState(false);
|
|
140
|
+
|
|
140
141
|
// ── Projects (for path selector) ─────────────────────────────────────
|
|
141
142
|
const [projects, setProjects] = useState<Project[]>([]);
|
|
142
143
|
const [projectsLoading, setProjectsLoading] = useState(false);
|
|
@@ -150,21 +151,63 @@ export const CreateTeamDialog = ({
|
|
|
150
151
|
const [localError, setLocalError] = useState<string | null>(null);
|
|
151
152
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
152
153
|
const [fieldErrors, setFieldErrors] = useState<{ teamName?: string; cwd?: string }>({});
|
|
154
|
+
// The slug ACTUALLY used at creation. The live `bindProject` re-derives once
|
|
155
|
+
// the parent's fetchTeams() refreshes existingBindProjects (the just-created
|
|
156
|
+
// slug is now taken) and its numeric-counter fallback can land on an
|
|
157
|
+
// UNRELATED existing team's slug — so the done step's "open" button must use
|
|
158
|
+
// this captured id, not the re-derived one. See the "opens the JUST-CREATED
|
|
159
|
+
// team" regression test.
|
|
160
|
+
const [createdTeamName, setCreatedTeamName] = useState<string | null>(null);
|
|
153
161
|
|
|
154
162
|
// ── Name conflict detection ──────────────────────────────────────────
|
|
155
|
-
const
|
|
156
|
-
() =>
|
|
157
|
-
[
|
|
163
|
+
const existingBindProjectSet = useMemo(
|
|
164
|
+
() => new Set(existingBindProjects.map((value) => value.trim().toLowerCase()).filter(Boolean)),
|
|
165
|
+
[existingBindProjects]
|
|
166
|
+
);
|
|
167
|
+
const provisioningTeamNameSet = useMemo(
|
|
168
|
+
() => new Set(provisioningTeamNames.map((value) => value.trim().toLowerCase()).filter(Boolean)),
|
|
169
|
+
[provisioningTeamNames]
|
|
170
|
+
);
|
|
171
|
+
// displayName (the human-readable name) must be unique too. A duplicate name
|
|
172
|
+
// silently produced a ghost team (the 222-2 incident: draft-restored name +
|
|
173
|
+
// auto-collision-free bindProject + a second create click), so block it up front.
|
|
174
|
+
const existingDisplayNameSet = useMemo(
|
|
175
|
+
() => new Set(existingDisplayNames.map((value) => value.trim().toLowerCase()).filter(Boolean)),
|
|
176
|
+
[existingDisplayNames]
|
|
158
177
|
);
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
//
|
|
162
|
-
//
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
178
|
+
const isDisplayNameTaken =
|
|
179
|
+
Boolean(teamName.trim()) && existingDisplayNameSet.has(teamName.trim().toLowerCase());
|
|
180
|
+
// The collision check is reactive to the live `teams` list. The instant a
|
|
181
|
+
// create succeeds, the parent store adds the new team and `isDisplayNameTaken`
|
|
182
|
+
// trips on the just-created name for the one frame before the dialog moves to
|
|
183
|
+
// the success step — a false "该名称已存在" red-box flicker. Validation
|
|
184
|
+
// (validateCreateFields) runs pre-submit and still uses the raw check, but the
|
|
185
|
+
// *visual* red box / error text / disabled state is suppressed while a create
|
|
186
|
+
// is in flight, since by then the name has already been accepted.
|
|
187
|
+
const showDisplayNameTaken = isDisplayNameTaken && !isSubmitting;
|
|
188
|
+
|
|
189
|
+
// bindProject is DERIVED, not state. The auto value is generated in the same
|
|
190
|
+
// render as `existingBindProjectSet`, so it is collision-free BY CONSTRUCTION
|
|
191
|
+
// and `isBindProjectTaken` can never flicker true between a set change and an
|
|
192
|
+
// effect flush. (The previous state + useEffect implementation lagged one
|
|
193
|
+
// render and produced a transient false "该项目标识已存在" red box.)
|
|
194
|
+
const autoBindProject = useMemo(
|
|
195
|
+
() => generateBindProject(teamName, existingBindProjectSet),
|
|
196
|
+
[teamName, existingBindProjectSet]
|
|
197
|
+
);
|
|
198
|
+
const bindProject = bindProjectManuallyEdited ? manualBindProject : autoBindProject;
|
|
199
|
+
const normalizedBindProject = bindProject.trim().toLowerCase();
|
|
200
|
+
|
|
201
|
+
const isBindProjectTaken = existingBindProjectSet.has(normalizedBindProject);
|
|
202
|
+
// Slug the done-step "open" + provisioning-error lookup target: the one
|
|
203
|
+
// actually used at creation (captured), falling back to the live form value
|
|
204
|
+
// before creation. Never the re-derived `bindProject` once the parent list
|
|
205
|
+
// refreshes — that drifts to a different/colliding id (createdTeamName note).
|
|
206
|
+
const openTeamSlug = createdTeamName ?? bindProject;
|
|
166
207
|
const isNameProvisioning =
|
|
167
|
-
|
|
208
|
+
provisioningTeamNameSet.has(normalizedBindProject) && !isBindProjectTaken;
|
|
209
|
+
const isBindProjectFormatInvalid =
|
|
210
|
+
Boolean(bindProject) && !isValidBindProject(normalizedBindProject);
|
|
168
211
|
|
|
169
212
|
const effectiveCwd =
|
|
170
213
|
cwdMode === 'project'
|
|
@@ -267,8 +310,8 @@ export const CreateTeamDialog = ({
|
|
|
267
310
|
|
|
268
311
|
// ── Clear provisioning error on open ─────────────────────────────────
|
|
269
312
|
useEffect(() => {
|
|
270
|
-
if (open &&
|
|
271
|
-
}, [open, clearProvisioningError,
|
|
313
|
+
if (open && bindProject) clearProvisioningError?.(bindProject);
|
|
314
|
+
}, [open, clearProvisioningError, bindProject]);
|
|
272
315
|
|
|
273
316
|
// ── Reset state on close ─────────────────────────────────────────────
|
|
274
317
|
const resetState = () => {
|
|
@@ -277,12 +320,24 @@ export const CreateTeamDialog = ({
|
|
|
277
320
|
setIsSubmitting(false);
|
|
278
321
|
setConflictDismissed(false);
|
|
279
322
|
setSelectedProviderRef(null);
|
|
323
|
+
setManualBindProject('');
|
|
324
|
+
setBindProjectManuallyEdited(false);
|
|
325
|
+
setCreatedTeamName(null);
|
|
280
326
|
setStep('name');
|
|
281
327
|
};
|
|
282
328
|
|
|
329
|
+
// Every close path (overlay click, ✕, 取消) clears the persisted draft so a
|
|
330
|
+
// stale restored name can never seed a duplicate create on reopen.
|
|
331
|
+
const handleClose = () => {
|
|
332
|
+
clearDraft();
|
|
333
|
+
resetState();
|
|
334
|
+
onClose();
|
|
335
|
+
};
|
|
336
|
+
|
|
283
337
|
const buildCreateRequest = (): TeamCreateRequest => ({
|
|
284
|
-
teamName:
|
|
285
|
-
|
|
338
|
+
teamName: normalizedBindProject,
|
|
339
|
+
bindProject: normalizedBindProject,
|
|
340
|
+
displayName: teamName.trim(),
|
|
286
341
|
description: description.trim() || undefined,
|
|
287
342
|
color: teamColor || undefined,
|
|
288
343
|
members: [],
|
|
@@ -295,12 +350,30 @@ export const CreateTeamDialog = ({
|
|
|
295
350
|
});
|
|
296
351
|
|
|
297
352
|
const validateCreateFields = (): boolean => {
|
|
298
|
-
if (
|
|
299
|
-
setLocalError(
|
|
353
|
+
if (!teamName.trim()) {
|
|
354
|
+
setLocalError('请输入数字员工名称');
|
|
300
355
|
return false;
|
|
301
356
|
}
|
|
302
|
-
if (
|
|
303
|
-
setLocalError('
|
|
357
|
+
if (isDisplayNameTaken) {
|
|
358
|
+
setLocalError('该名称已存在,请换一个');
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
if (!normalizedBindProject) {
|
|
362
|
+
setLocalError('请输入项目标识');
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
if (!isValidBindProject(normalizedBindProject)) {
|
|
366
|
+
setLocalError(
|
|
367
|
+
'项目标识为必填,只能包含小写英文字母、数字、连字符和下划线,且必须以字母或数字开头'
|
|
368
|
+
);
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
if (isNameProvisioning) {
|
|
372
|
+
setLocalError('数字员工正在启动中');
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
if (isBindProjectTaken) {
|
|
376
|
+
setLocalError(`项目标识"${normalizedBindProject}"已存在,请换一个`);
|
|
304
377
|
return false;
|
|
305
378
|
}
|
|
306
379
|
if (!effectiveCwd) {
|
|
@@ -310,8 +383,8 @@ export const CreateTeamDialog = ({
|
|
|
310
383
|
return true;
|
|
311
384
|
};
|
|
312
385
|
|
|
313
|
-
const createLocalTeam = async (): Promise<
|
|
314
|
-
if (!validateCreateFields()) return
|
|
386
|
+
const createLocalTeam = async (): Promise<boolean> => {
|
|
387
|
+
if (!validateCreateFields()) return false;
|
|
315
388
|
|
|
316
389
|
setFieldErrors({});
|
|
317
390
|
setLocalError(null);
|
|
@@ -320,19 +393,31 @@ export const CreateTeamDialog = ({
|
|
|
320
393
|
try {
|
|
321
394
|
const request = buildCreateRequest();
|
|
322
395
|
await onCreate(request);
|
|
323
|
-
|
|
396
|
+
// Capture the slug that was actually persisted. The done step opens /
|
|
397
|
+
// surfaces errors for THIS team; the live `bindProject` would drift to a
|
|
398
|
+
// different id once the parent list refreshes (see createdTeamName note).
|
|
399
|
+
setCreatedTeamName(request.teamName);
|
|
400
|
+
// Advance to the success step in the SAME synchronous block as the
|
|
401
|
+
// `finally` that releases isSubmitting. The create just added this name
|
|
402
|
+
// to the parent's existingDisplayNames; if the name step re-rendered
|
|
403
|
+
// with isSubmitting already false, `showDisplayNameTaken` would trip on
|
|
404
|
+
// the just-created name for one frame — the false "该名称已存在"
|
|
405
|
+
// red-box flicker right before the success screen. Setting 'done' here
|
|
406
|
+
// (no await between it and the finally) batches with
|
|
407
|
+
// setIsSubmitting(false), so the name step is unmounted atomically and
|
|
408
|
+
// that transition window never opens.
|
|
409
|
+
setStep('done');
|
|
410
|
+
return true;
|
|
324
411
|
} catch {
|
|
325
412
|
// error shown via provisioningErrorsByTeam
|
|
326
|
-
return
|
|
413
|
+
return false;
|
|
327
414
|
} finally {
|
|
328
415
|
setIsSubmitting(false);
|
|
329
416
|
}
|
|
330
417
|
};
|
|
331
418
|
|
|
332
419
|
const handleCreate = async () => {
|
|
333
|
-
|
|
334
|
-
if (!request) return;
|
|
335
|
-
setStep('done');
|
|
420
|
+
await createLocalTeam();
|
|
336
421
|
};
|
|
337
422
|
|
|
338
423
|
// ── Render ───────────────────────────────────────────────────────────
|
|
@@ -340,10 +425,7 @@ export const CreateTeamDialog = ({
|
|
|
340
425
|
<Dialog
|
|
341
426
|
open={open}
|
|
342
427
|
onOpenChange={(next: boolean) => {
|
|
343
|
-
if (!next)
|
|
344
|
-
resetState();
|
|
345
|
-
onClose();
|
|
346
|
-
}
|
|
428
|
+
if (!next) handleClose();
|
|
347
429
|
}}
|
|
348
430
|
>
|
|
349
431
|
<DialogContent className="w-[calc(100vw-2rem)] max-w-2xl sm:w-[40rem]">
|
|
@@ -368,7 +450,7 @@ export const CreateTeamDialog = ({
|
|
|
368
450
|
<AlertTriangle className="mt-0.5 size-4 shrink-0" />
|
|
369
451
|
<div className="min-w-0 flex-1 space-y-1">
|
|
370
452
|
<p className="font-medium">
|
|
371
|
-
|
|
453
|
+
该工作目录下已有数字员工"{conflictingTeam.displayName}"正在运行
|
|
372
454
|
</p>
|
|
373
455
|
<p className="opacity-80">在同一目录同时运行两个数字员工存在风险。</p>
|
|
374
456
|
</div>
|
|
@@ -387,28 +469,65 @@ export const CreateTeamDialog = ({
|
|
|
387
469
|
{step === 'name' && (
|
|
388
470
|
<div className="space-y-4 py-2">
|
|
389
471
|
<div className="space-y-1.5">
|
|
390
|
-
<Label htmlFor="team-name"
|
|
472
|
+
<Label htmlFor="team-name">数字员工名称 *</Label>
|
|
391
473
|
<Input
|
|
392
474
|
id="team-name"
|
|
475
|
+
required
|
|
393
476
|
className={cn(
|
|
394
477
|
'h-8 text-xs',
|
|
395
|
-
fieldErrors.teamName
|
|
478
|
+
(fieldErrors.teamName || showDisplayNameTaken) &&
|
|
479
|
+
'border-[var(--field-error-border)]'
|
|
396
480
|
)}
|
|
397
481
|
value={teamName}
|
|
398
482
|
onChange={(e) => setTeamName(e.target.value)}
|
|
399
483
|
placeholder="例如:产品助手 / 前端工程师"
|
|
400
484
|
autoFocus
|
|
401
485
|
/>
|
|
402
|
-
{
|
|
486
|
+
{isNameProvisioning && (
|
|
487
|
+
<p className="text-[11px]" style={{ color: 'var(--warning-text)' }}>
|
|
488
|
+
同名数字员工正在启动中
|
|
489
|
+
</p>
|
|
490
|
+
)}
|
|
491
|
+
{showDisplayNameTaken && (
|
|
492
|
+
<p className="text-[11px] text-red-400">该名称已存在,请换一个</p>
|
|
493
|
+
)}
|
|
494
|
+
</div>
|
|
495
|
+
|
|
496
|
+
<div className="space-y-1.5">
|
|
497
|
+
<Label htmlFor="team-bind-project">项目标识 *</Label>
|
|
498
|
+
<Input
|
|
499
|
+
id="team-bind-project"
|
|
500
|
+
required
|
|
501
|
+
className={cn(
|
|
502
|
+
'h-8 font-mono text-xs',
|
|
503
|
+
(isBindProjectTaken || isBindProjectFormatInvalid) &&
|
|
504
|
+
'border-[var(--field-error-border)]'
|
|
505
|
+
)}
|
|
506
|
+
value={bindProject}
|
|
507
|
+
onChange={(e) => {
|
|
508
|
+
setManualBindProject(e.target.value.toLowerCase().replace(/[^a-z0-9_-]/g, ''));
|
|
509
|
+
setBindProjectManuallyEdited(true);
|
|
510
|
+
}}
|
|
511
|
+
placeholder="auto-generated-id"
|
|
512
|
+
/>
|
|
513
|
+
{isBindProjectFormatInvalid && (
|
|
403
514
|
<p className="text-[11px]" style={{ color: 'var(--field-error-text)' }}>
|
|
404
|
-
|
|
515
|
+
项目标识只能包含小写英文、数字、连字符和下划线,且必须以字母或数字开头
|
|
405
516
|
</p>
|
|
406
517
|
)}
|
|
407
518
|
{isNameProvisioning && (
|
|
408
519
|
<p className="text-[11px]" style={{ color: 'var(--warning-text)' }}>
|
|
409
|
-
|
|
520
|
+
该项目标识正在创建中
|
|
410
521
|
</p>
|
|
411
522
|
)}
|
|
523
|
+
{isBindProjectTaken && (
|
|
524
|
+
<p className="text-[11px]" style={{ color: 'var(--field-error-text)' }}>
|
|
525
|
+
该项目标识已存在
|
|
526
|
+
</p>
|
|
527
|
+
)}
|
|
528
|
+
<p className="text-[11px] text-[var(--color-text-muted)]">
|
|
529
|
+
用于 URL 路由和 cc-connect 项目绑定,仅限小写英文/数字/连字符
|
|
530
|
+
</p>
|
|
412
531
|
</div>
|
|
413
532
|
|
|
414
533
|
<div className="space-y-1.5">
|
|
@@ -474,8 +593,8 @@ export const CreateTeamDialog = ({
|
|
|
474
593
|
onClick={() => selectProviderRef(provider.name)}
|
|
475
594
|
className={`w-full rounded-lg border px-3 py-2 text-left transition-colors ${
|
|
476
595
|
checked
|
|
477
|
-
? '
|
|
478
|
-
: 'border-[var(--color-border-subtle)] bg-black/10 hover:border-[var(--color-border)] hover:bg-
|
|
596
|
+
? 'shadow-[var(--color-accent-glow)]/20 border-[var(--color-accent-border)] bg-[var(--color-accent-muted)] shadow-sm'
|
|
597
|
+
: 'border-[var(--color-border-subtle)] bg-black/10 hover:border-[var(--color-border)] hover:bg-[var(--color-accent-soft)]'
|
|
479
598
|
}`}
|
|
480
599
|
>
|
|
481
600
|
<div className="flex items-center justify-between gap-3">
|
|
@@ -490,7 +609,7 @@ export const CreateTeamDialog = ({
|
|
|
490
609
|
<span
|
|
491
610
|
className={`shrink-0 rounded-full px-2 py-0.5 text-[10px] ${
|
|
492
611
|
checked
|
|
493
|
-
? 'bg-
|
|
612
|
+
? 'bg-[var(--color-accent-soft)] text-[var(--color-accent)]'
|
|
494
613
|
: 'bg-white/5 text-[var(--color-text-muted)]'
|
|
495
614
|
}`}
|
|
496
615
|
>
|
|
@@ -541,7 +660,7 @@ export const CreateTeamDialog = ({
|
|
|
541
660
|
{localError}
|
|
542
661
|
</p>
|
|
543
662
|
)}
|
|
544
|
-
{provisioningErrorsByTeam[
|
|
663
|
+
{provisioningErrorsByTeam[openTeamSlug] && (
|
|
545
664
|
<p
|
|
546
665
|
className="mt-1 rounded border p-2 text-xs"
|
|
547
666
|
style={{
|
|
@@ -550,7 +669,7 @@ export const CreateTeamDialog = ({
|
|
|
550
669
|
backgroundColor: 'var(--field-error-bg)',
|
|
551
670
|
}}
|
|
552
671
|
>
|
|
553
|
-
{provisioningErrorsByTeam[
|
|
672
|
+
{provisioningErrorsByTeam[openTeamSlug]}
|
|
554
673
|
</p>
|
|
555
674
|
)}
|
|
556
675
|
</div>
|
|
@@ -572,7 +691,7 @@ export const CreateTeamDialog = ({
|
|
|
572
691
|
<Button
|
|
573
692
|
size="sm"
|
|
574
693
|
onClick={() => {
|
|
575
|
-
onOpenTeam(
|
|
694
|
+
onOpenTeam(openTeamSlug, effectiveCwd || undefined, {
|
|
576
695
|
displayName: teamName.trim() || undefined,
|
|
577
696
|
});
|
|
578
697
|
clearDraft();
|
|
@@ -585,10 +704,23 @@ export const CreateTeamDialog = ({
|
|
|
585
704
|
</>
|
|
586
705
|
) : (
|
|
587
706
|
<>
|
|
588
|
-
<Button variant="outline" size="sm" onClick={
|
|
707
|
+
<Button variant="outline" size="sm" onClick={handleClose}>
|
|
589
708
|
取消
|
|
590
709
|
</Button>
|
|
591
|
-
<Button
|
|
710
|
+
<Button
|
|
711
|
+
size="sm"
|
|
712
|
+
disabled={
|
|
713
|
+
!teamName.trim() ||
|
|
714
|
+
!normalizedBindProject ||
|
|
715
|
+
!effectiveCwd ||
|
|
716
|
+
isBindProjectFormatInvalid ||
|
|
717
|
+
isBindProjectTaken ||
|
|
718
|
+
showDisplayNameTaken ||
|
|
719
|
+
isNameProvisioning ||
|
|
720
|
+
isSubmitting
|
|
721
|
+
}
|
|
722
|
+
onClick={handleCreate}
|
|
723
|
+
>
|
|
592
724
|
{isSubmitting ? '创建中...' : '创建数字员工'}
|
|
593
725
|
</Button>
|
|
594
726
|
</>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import { Button } from '@renderer/components/ui/button';
|
|
4
|
-
import { Checkbox } from '@renderer/components/ui/checkbox';
|
|
5
4
|
import {
|
|
6
5
|
Dialog,
|
|
7
6
|
DialogContent,
|
|
@@ -42,60 +41,20 @@ export const EditTeamDialog = ({
|
|
|
42
41
|
}));
|
|
43
42
|
|
|
44
43
|
// ── Derived defaults ─────────────────────────────────────────
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
[data?.settings]
|
|
48
|
-
);
|
|
49
|
-
|
|
44
|
+
// Loop 动态设置(语言/管理来源/飞书权限/消息格式)已统一迁入 RuntimeConfigDialog,
|
|
45
|
+
// 这里只保留团队基础信息:名称、描述、颜色 (#21)。
|
|
50
46
|
const defaults = useMemo(() => {
|
|
51
47
|
const cfg = data?.config;
|
|
52
48
|
return {
|
|
53
49
|
name: cfg?.name ?? '',
|
|
54
50
|
description: cfg?.description ?? '',
|
|
55
51
|
color: cfg?.color ?? '',
|
|
56
|
-
language:
|
|
57
|
-
cfg?.language ?? (typeof rawSettings.language === 'string' ? rawSettings.language : 'zh'),
|
|
58
|
-
managedSources:
|
|
59
|
-
cfg?.managedSources ??
|
|
60
|
-
(typeof rawSettings.admin_from === 'string' ? rawSettings.admin_from : '*'),
|
|
61
|
-
platformAllowFrom:
|
|
62
|
-
cfg?.platformAllowFrom ??
|
|
63
|
-
(typeof rawSettings.platform_allow_from === 'object' &&
|
|
64
|
-
rawSettings.platform_allow_from !== null &&
|
|
65
|
-
!Array.isArray(rawSettings.platform_allow_from)
|
|
66
|
-
? (rawSettings.platform_allow_from as Record<string, string>)
|
|
67
|
-
: {}),
|
|
68
|
-
platformAllowChat:
|
|
69
|
-
cfg?.platformAllowChat ??
|
|
70
|
-
(typeof (rawSettings as Record<string, unknown>).platform_allow_chat === 'object' &&
|
|
71
|
-
(rawSettings as Record<string, unknown>).platform_allow_chat !== null &&
|
|
72
|
-
!Array.isArray((rawSettings as Record<string, unknown>).platform_allow_chat)
|
|
73
|
-
? ((rawSettings as Record<string, unknown>).platform_allow_chat as Record<string, string>)
|
|
74
|
-
: {}),
|
|
75
|
-
showContextIndicator:
|
|
76
|
-
cfg?.showContextIndicator ??
|
|
77
|
-
(typeof rawSettings.show_context_indicator === 'boolean'
|
|
78
|
-
? rawSettings.show_context_indicator
|
|
79
|
-
: true),
|
|
80
|
-
replyFooter:
|
|
81
|
-
cfg?.replyFooter ??
|
|
82
|
-
(typeof rawSettings.reply_footer === 'boolean' ? rawSettings.reply_footer : true),
|
|
83
|
-
injectSender:
|
|
84
|
-
cfg?.injectSender ??
|
|
85
|
-
(typeof rawSettings.inject_sender === 'boolean' ? rawSettings.inject_sender : false),
|
|
86
52
|
};
|
|
87
|
-
}, [data
|
|
53
|
+
}, [data]);
|
|
88
54
|
|
|
89
55
|
// ── Local form state ─────────────────────────────────────────
|
|
90
56
|
const [name, setName] = useState(defaults.name);
|
|
91
57
|
const [description, setDescription] = useState(defaults.description);
|
|
92
|
-
const [language, setLanguage] = useState(defaults.language);
|
|
93
|
-
const [managedSources, setManagedSources] = useState(defaults.managedSources);
|
|
94
|
-
const [feishuAllowFrom, setFeishuAllowFrom] = useState(defaults.platformAllowFrom.feishu ?? '*');
|
|
95
|
-
const [feishuAllowChat, setFeishuAllowChat] = useState(defaults.platformAllowChat.feishu ?? '*');
|
|
96
|
-
const [showContextIndicator, setShowContextIndicator] = useState(defaults.showContextIndicator);
|
|
97
|
-
const [replyFooter, setReplyFooter] = useState(defaults.replyFooter);
|
|
98
|
-
const [injectSender, setInjectSender] = useState(defaults.injectSender);
|
|
99
58
|
const [savePhase, setSavePhase] = useState<'idle' | 'saving' | 'done'>('idle');
|
|
100
59
|
const [error, setError] = useState<string | null>(null);
|
|
101
60
|
const saving = savePhase === 'saving';
|
|
@@ -115,13 +74,6 @@ export const EditTeamDialog = ({
|
|
|
115
74
|
setError(null);
|
|
116
75
|
setName(d.name);
|
|
117
76
|
setDescription(d.description);
|
|
118
|
-
setLanguage(d.language);
|
|
119
|
-
setManagedSources(d.managedSources);
|
|
120
|
-
setFeishuAllowFrom(d.platformAllowFrom.feishu ?? '*');
|
|
121
|
-
setFeishuAllowChat(d.platformAllowChat.feishu ?? '*');
|
|
122
|
-
setShowContextIndicator(d.showContextIndicator);
|
|
123
|
-
setReplyFooter(d.replyFooter);
|
|
124
|
-
setInjectSender(d.injectSender);
|
|
125
77
|
}, [open]);
|
|
126
78
|
|
|
127
79
|
const handleSave = (): void => {
|
|
@@ -133,22 +85,12 @@ export const EditTeamDialog = ({
|
|
|
133
85
|
setSavePhase('saving');
|
|
134
86
|
setError(null);
|
|
135
87
|
|
|
136
|
-
const feishu = feishuAllowFrom.trim();
|
|
137
|
-
const feishuChat = feishuAllowChat.trim();
|
|
138
|
-
|
|
139
88
|
void (async () => {
|
|
140
89
|
try {
|
|
141
90
|
await api.teams.updateConfig(teamName, {
|
|
142
91
|
name: name.trim(),
|
|
143
92
|
description: description.trim(),
|
|
144
93
|
color: defaultsRef.current.color,
|
|
145
|
-
language: language.trim() || undefined,
|
|
146
|
-
managedSources: managedSources.trim() || undefined,
|
|
147
|
-
platformAllowFrom: feishu ? { feishu } : {},
|
|
148
|
-
platformAllowChat: feishuChat ? { feishu: feishuChat } : {},
|
|
149
|
-
showContextIndicator,
|
|
150
|
-
replyFooter,
|
|
151
|
-
injectSender,
|
|
152
94
|
});
|
|
153
95
|
await Promise.all([fetchTeams(), selectTeam(teamName)]);
|
|
154
96
|
setSavePhase('done');
|
|
@@ -173,7 +115,7 @@ export const EditTeamDialog = ({
|
|
|
173
115
|
<DialogContent className="max-w-lg">
|
|
174
116
|
<DialogHeader>
|
|
175
117
|
<DialogTitle>编辑团队</DialogTitle>
|
|
176
|
-
<DialogDescription
|
|
118
|
+
<DialogDescription>修改团队名称和描述</DialogDescription>
|
|
177
119
|
</DialogHeader>
|
|
178
120
|
|
|
179
121
|
<div className="space-y-4">
|
|
@@ -214,105 +156,15 @@ export const EditTeamDialog = ({
|
|
|
214
156
|
/>
|
|
215
157
|
</div>
|
|
216
158
|
|
|
217
|
-
{/* Messaging settings */}
|
|
218
|
-
<div className="rounded-md border border-[var(--color-border)] p-3">
|
|
219
|
-
<h3 className="text-xs font-medium text-[var(--color-text)]">消息设置</h3>
|
|
220
|
-
<div className="mt-3 space-y-3">
|
|
221
|
-
<div className="grid gap-3 md:grid-cols-2">
|
|
222
|
-
<div>
|
|
223
|
-
<label className={labelCls}>语言</label>
|
|
224
|
-
<input
|
|
225
|
-
type="text"
|
|
226
|
-
value={language}
|
|
227
|
-
onChange={(e) => {
|
|
228
|
-
setError(null);
|
|
229
|
-
setLanguage(e.target.value);
|
|
230
|
-
}}
|
|
231
|
-
className={inputCls}
|
|
232
|
-
placeholder="zh"
|
|
233
|
-
/>
|
|
234
|
-
</div>
|
|
235
|
-
<div>
|
|
236
|
-
<label className={labelCls}>管理来源</label>
|
|
237
|
-
<input
|
|
238
|
-
type="text"
|
|
239
|
-
value={managedSources}
|
|
240
|
-
onChange={(e) => {
|
|
241
|
-
setError(null);
|
|
242
|
-
setManagedSources(e.target.value);
|
|
243
|
-
}}
|
|
244
|
-
className={inputCls}
|
|
245
|
-
placeholder="user1,user2 或 *"
|
|
246
|
-
/>
|
|
247
|
-
</div>
|
|
248
|
-
</div>
|
|
249
|
-
<div className="grid gap-3 md:grid-cols-2">
|
|
250
|
-
<div>
|
|
251
|
-
<label className={labelCls}>飞书私聊权限</label>
|
|
252
|
-
<input
|
|
253
|
-
type="text"
|
|
254
|
-
value={feishuAllowFrom}
|
|
255
|
-
onChange={(e) => {
|
|
256
|
-
setError(null);
|
|
257
|
-
setFeishuAllowFrom(e.target.value);
|
|
258
|
-
}}
|
|
259
|
-
className={inputCls}
|
|
260
|
-
placeholder="ou_xxx 或 *"
|
|
261
|
-
/>
|
|
262
|
-
</div>
|
|
263
|
-
<div>
|
|
264
|
-
<label className={labelCls}>飞书群聊权限</label>
|
|
265
|
-
<input
|
|
266
|
-
type="text"
|
|
267
|
-
value={feishuAllowChat}
|
|
268
|
-
onChange={(e) => {
|
|
269
|
-
setError(null);
|
|
270
|
-
setFeishuAllowChat(e.target.value);
|
|
271
|
-
}}
|
|
272
|
-
className={inputCls}
|
|
273
|
-
placeholder="oc_xxx 或 *"
|
|
274
|
-
/>
|
|
275
|
-
</div>
|
|
276
|
-
</div>
|
|
277
|
-
<div className="grid gap-2 md:grid-cols-3">
|
|
278
|
-
<label className="flex cursor-pointer items-center gap-2 rounded-md border border-[var(--color-border)] px-2 py-1.5 text-xs text-[var(--color-text-secondary)]">
|
|
279
|
-
<Checkbox
|
|
280
|
-
checked={showContextIndicator}
|
|
281
|
-
onCheckedChange={(c) => {
|
|
282
|
-
setError(null);
|
|
283
|
-
setShowContextIndicator(c === true);
|
|
284
|
-
}}
|
|
285
|
-
/>
|
|
286
|
-
上下文指示
|
|
287
|
-
</label>
|
|
288
|
-
<label className="flex cursor-pointer items-center gap-2 rounded-md border border-[var(--color-border)] px-2 py-1.5 text-xs text-[var(--color-text-secondary)]">
|
|
289
|
-
<Checkbox
|
|
290
|
-
checked={replyFooter}
|
|
291
|
-
onCheckedChange={(c) => {
|
|
292
|
-
setError(null);
|
|
293
|
-
setReplyFooter(c === true);
|
|
294
|
-
}}
|
|
295
|
-
/>
|
|
296
|
-
回复尾部信息
|
|
297
|
-
</label>
|
|
298
|
-
<label className="flex cursor-pointer items-center gap-2 rounded-md border border-[var(--color-border)] px-2 py-1.5 text-xs text-[var(--color-text-secondary)]">
|
|
299
|
-
<Checkbox
|
|
300
|
-
checked={injectSender}
|
|
301
|
-
onCheckedChange={(c) => {
|
|
302
|
-
setError(null);
|
|
303
|
-
setInjectSender(c === true);
|
|
304
|
-
}}
|
|
305
|
-
/>
|
|
306
|
-
注入发送者
|
|
307
|
-
</label>
|
|
308
|
-
</div>
|
|
309
|
-
</div>
|
|
310
|
-
</div>
|
|
311
|
-
|
|
312
159
|
{error && <p className="text-xs text-red-400">{error}</p>}
|
|
313
160
|
</div>
|
|
314
161
|
|
|
315
162
|
<DialogFooter>
|
|
163
|
+
{onDeleteTeam && teamName !== 'default' ? (
|
|
164
|
+
<Button variant="ghost" size="sm" onClick={onDeleteTeam} disabled={saving}>
|
|
165
|
+
删除项目
|
|
166
|
+
</Button>
|
|
167
|
+
) : null}
|
|
316
168
|
<Button variant="outline" size="sm" onClick={onClose} disabled={saving}>
|
|
317
169
|
{savePhase === 'done' ? '关闭' : '取消'}
|
|
318
170
|
</Button>
|