@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
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
|
+
import { api } from '@renderer/api';
|
|
4
|
+
import { AGENT_TYPE_LABELS } from '@renderer/components/team/HarnessCards';
|
|
5
|
+
import { HarnessSelect } from '@renderer/components/team/HarnessSelect';
|
|
3
6
|
import { Button } from '@renderer/components/ui/button';
|
|
4
7
|
import {
|
|
5
8
|
Dialog,
|
|
@@ -9,17 +12,19 @@ import {
|
|
|
9
12
|
DialogHeader,
|
|
10
13
|
DialogTitle,
|
|
11
14
|
} from '@renderer/components/ui/dialog';
|
|
12
|
-
import { AGENT_TYPE_LABELS } from '@renderer/components/team/HarnessCards';
|
|
13
|
-
import { HarnessSelect } from '@renderer/components/team/HarnessSelect';
|
|
14
|
-
import { Loader2, Settings2 } from 'lucide-react';
|
|
15
|
-
|
|
16
|
-
import { api } from '@renderer/api';
|
|
17
15
|
import { useStore } from '@renderer/store';
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
import
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
import { Loader2, Plug2, Settings2, Wifi, WifiOff } from 'lucide-react';
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
PlatformBindingContent,
|
|
20
|
+
type PlatformBindingCompleteOptions,
|
|
21
|
+
} from './PlatformBindingDialog';
|
|
22
|
+
import { buildPlatformAllowUpdatePayload, readStringRecord } from './platformAllowUtils';
|
|
23
|
+
import { platformMeta } from './platformMeta';
|
|
24
|
+
|
|
25
|
+
import type { CcAgentType, CcProjectPlatform } from '@shared/types/ccConnect';
|
|
26
|
+
import type { TeamUpdateConfigRequest } from '@shared/types/team';
|
|
27
|
+
import { SYSTEM_MANAGER_TEAM_NAME } from '@shared/types/team';
|
|
23
28
|
|
|
24
29
|
// ── Section wrapper ──────────────────────────────────────────
|
|
25
30
|
function FormSection({
|
|
@@ -32,10 +37,13 @@ function FormSection({
|
|
|
32
37
|
children: React.ReactNode;
|
|
33
38
|
}): React.JSX.Element {
|
|
34
39
|
return (
|
|
35
|
-
<div className="rounded-
|
|
40
|
+
<div className="bg-[var(--color-surface-raised)]/55 relative overflow-hidden rounded-xl border border-[var(--color-border-subtle)] p-3 shadow-sm shadow-black/10">
|
|
41
|
+
<div className="pointer-events-none absolute inset-x-6 top-0 h-px bg-gradient-to-r from-transparent via-[var(--color-accent-border)] to-transparent" />
|
|
36
42
|
<h3 className="text-sm font-medium text-[var(--color-text)]">{title}</h3>
|
|
37
43
|
{description && (
|
|
38
|
-
<p className="mt-0.5 text-xs text-[var(--color-text-muted)]">
|
|
44
|
+
<p className="mt-0.5 text-xs leading-relaxed text-[var(--color-text-muted)]">
|
|
45
|
+
{description}
|
|
46
|
+
</p>
|
|
39
47
|
)}
|
|
40
48
|
<div className="mt-3 space-y-3">{children}</div>
|
|
41
49
|
</div>
|
|
@@ -43,9 +51,86 @@ function FormSection({
|
|
|
43
51
|
}
|
|
44
52
|
|
|
45
53
|
const inputCls =
|
|
46
|
-
'w-full rounded-
|
|
54
|
+
'w-full rounded-lg border border-[var(--color-border-subtle)] bg-[var(--color-surface)] px-3 py-1.5 text-sm text-[var(--color-text)] outline-none transition-colors focus:border-[var(--color-accent-border)] focus:ring-1 focus:ring-[var(--color-accent-border)]';
|
|
47
55
|
const labelCls = 'mb-1 block text-xs font-medium text-[var(--color-text-secondary)]';
|
|
48
56
|
|
|
57
|
+
const PERMISSION_MODE_OPTIONS = [
|
|
58
|
+
{ value: 'default', label: '默认' },
|
|
59
|
+
{ value: 'acceptEdits', label: '自动接受编辑' },
|
|
60
|
+
{ value: 'bypassPermissions', label: '跳过权限确认' },
|
|
61
|
+
{ value: 'plan', label: '计划模式' },
|
|
62
|
+
] as const;
|
|
63
|
+
|
|
64
|
+
function getPlatformLabel(type: string): string {
|
|
65
|
+
if (type === 'feishu' || type === 'lark') return '飞书 / Lark';
|
|
66
|
+
if (type === 'weixin') return '微信';
|
|
67
|
+
return platformMeta[type]?.label ?? type;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function getPlatformAllowPlaceholder(platformType: string, kind: 'from' | 'chat'): string {
|
|
71
|
+
const fieldKey = kind === 'from' ? 'allow_from' : 'allow_chat';
|
|
72
|
+
const field = platformMeta[platformType]?.fields.find((item) => item.key === fieldKey);
|
|
73
|
+
if (field?.placeholder) return `留空表示未单独配置;${field.placeholder}`;
|
|
74
|
+
return kind === 'from'
|
|
75
|
+
? '留空表示未单独配置;输入 * 表示允许所有用户'
|
|
76
|
+
: '留空表示未单独配置;输入 * 表示允许所有群聊/频道';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function uniquePlatformTypes(platforms: CcProjectPlatform[]): string[] {
|
|
80
|
+
return [
|
|
81
|
+
...new Set(
|
|
82
|
+
platforms
|
|
83
|
+
.map((platform) => platform.type)
|
|
84
|
+
.filter((type) => Boolean(type) && type !== 'bridge')
|
|
85
|
+
),
|
|
86
|
+
];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function BoundPlatformList({ platforms }: { platforms: CcProjectPlatform[] }): React.JSX.Element {
|
|
90
|
+
if (platforms.length === 0) {
|
|
91
|
+
return (
|
|
92
|
+
<div className="rounded-lg border border-dashed border-[var(--color-border)] px-3 py-3 text-xs text-[var(--color-text-muted)]">
|
|
93
|
+
暂无已绑定渠道。
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<div className="space-y-2">
|
|
100
|
+
{platforms.map((platform) => (
|
|
101
|
+
<div
|
|
102
|
+
key={`${platform.type}:${String(platform.connected)}`}
|
|
103
|
+
className="flex items-center justify-between gap-3 rounded-lg border border-[var(--color-border-subtle)] bg-[var(--color-surface)] px-3 py-2"
|
|
104
|
+
>
|
|
105
|
+
<div className="flex min-w-0 items-center gap-2.5">
|
|
106
|
+
<div className="flex size-7 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-[var(--color-accent)]">
|
|
107
|
+
<Plug2 className="size-3.5" />
|
|
108
|
+
</div>
|
|
109
|
+
<div className="min-w-0">
|
|
110
|
+
<div className="truncate text-xs font-medium text-[var(--color-text)]">
|
|
111
|
+
{getPlatformLabel(platform.type)}
|
|
112
|
+
</div>
|
|
113
|
+
<div className="mt-0.5 font-mono text-[10px] text-[var(--color-text-muted)]">
|
|
114
|
+
{platform.type}
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
<span
|
|
119
|
+
className={`flex shrink-0 items-center gap-1 rounded-full px-2 py-0.5 text-[10px] ${
|
|
120
|
+
platform.connected
|
|
121
|
+
? 'bg-[var(--color-accent-soft)] text-[var(--color-accent)]'
|
|
122
|
+
: 'bg-white/5 text-[var(--color-text-muted)]'
|
|
123
|
+
}`}
|
|
124
|
+
>
|
|
125
|
+
{platform.connected ? <Wifi className="size-3" /> : <WifiOff className="size-3" />}
|
|
126
|
+
{platform.connected ? '已连接' : '已绑定未连接'}
|
|
127
|
+
</span>
|
|
128
|
+
</div>
|
|
129
|
+
))}
|
|
130
|
+
</div>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
49
134
|
interface RuntimeConfigDialogProps {
|
|
50
135
|
open: boolean;
|
|
51
136
|
teamName: string;
|
|
@@ -57,24 +142,43 @@ export function RuntimeConfigDialog({
|
|
|
57
142
|
teamName,
|
|
58
143
|
onClose,
|
|
59
144
|
}: RuntimeConfigDialogProps): React.JSX.Element {
|
|
145
|
+
const isAdminTeam = teamName === SYSTEM_MANAGER_TEAM_NAME;
|
|
60
146
|
const { data, fetchTeams, selectTeam } = useStore((s) => ({
|
|
61
147
|
data: s.selectedTeamName === teamName ? s.selectedTeamData : null,
|
|
62
148
|
fetchTeams: s.fetchTeams,
|
|
63
149
|
selectTeam: s.selectTeam,
|
|
64
150
|
}));
|
|
65
|
-
const isProvisioning = useStore((s) => isTeamProvisioningActive(s, teamName));
|
|
66
151
|
|
|
67
152
|
// ── Derived defaults ─────────────────────────────────────────
|
|
68
153
|
const defaults = useMemo(() => {
|
|
69
154
|
const cfg = data?.config;
|
|
70
155
|
const d = data as Record<string, unknown> | null;
|
|
156
|
+
const rawSettings = (data?.settings ?? {}) as Record<string, unknown>;
|
|
71
157
|
return {
|
|
72
158
|
agentType: cfg?.agentType ?? (d?.harness as string | undefined) ?? 'claudecode',
|
|
73
|
-
workDir: (d?.workDir as string | undefined) ??
|
|
159
|
+
workDir: cfg?.projectPath ?? (d?.workDir as string | undefined) ?? '',
|
|
74
160
|
permissionMode: cfg?.permissionMode ?? (d?.permissionMode as string | undefined) ?? 'default',
|
|
75
|
-
disabledCommands: Array.isArray(cfg?.disabledCommands)
|
|
76
|
-
|
|
77
|
-
|
|
161
|
+
disabledCommands: Array.isArray(cfg?.disabledCommands) ? cfg.disabledCommands : [],
|
|
162
|
+
managedSources:
|
|
163
|
+
cfg?.managedSources ??
|
|
164
|
+
(typeof rawSettings.admin_from === 'string' ? rawSettings.admin_from : '*'),
|
|
165
|
+
language:
|
|
166
|
+
cfg?.language ?? (typeof rawSettings.language === 'string' ? rawSettings.language : 'zh'),
|
|
167
|
+
showContextIndicator:
|
|
168
|
+
cfg?.showContextIndicator ??
|
|
169
|
+
(typeof rawSettings.show_context_indicator === 'boolean'
|
|
170
|
+
? rawSettings.show_context_indicator
|
|
171
|
+
: true),
|
|
172
|
+
replyFooter:
|
|
173
|
+
cfg?.replyFooter ??
|
|
174
|
+
(typeof rawSettings.reply_footer === 'boolean' ? rawSettings.reply_footer : true),
|
|
175
|
+
injectSender:
|
|
176
|
+
cfg?.injectSender ??
|
|
177
|
+
(typeof rawSettings.inject_sender === 'boolean' ? rawSettings.inject_sender : false),
|
|
178
|
+
platformAllowFrom:
|
|
179
|
+
cfg?.platformAllowFrom ?? readStringRecord(rawSettings.platform_allow_from),
|
|
180
|
+
platformAllowChat:
|
|
181
|
+
cfg?.platformAllowChat ?? readStringRecord(rawSettings.platform_allow_chat),
|
|
78
182
|
providerRefs: data?.providerRefs ?? [],
|
|
79
183
|
globalProviders: data?.globalProviders ?? [],
|
|
80
184
|
bindProject: (d?.bindProject as string | undefined) ?? teamName,
|
|
@@ -89,10 +193,18 @@ export function RuntimeConfigDialog({
|
|
|
89
193
|
defaults.disabledCommands.join(', ')
|
|
90
194
|
);
|
|
91
195
|
const [providerRef, setProviderRef] = useState(defaults.providerRefs[0] ?? '');
|
|
92
|
-
|
|
196
|
+
const [platformAllowFrom, setPlatformAllowFrom] = useState(defaults.platformAllowFrom);
|
|
197
|
+
const [platformAllowChat, setPlatformAllowChat] = useState(defaults.platformAllowChat);
|
|
198
|
+
const [language, setLanguage] = useState(defaults.language);
|
|
199
|
+
const [managedSources, setManagedSources] = useState(defaults.managedSources);
|
|
200
|
+
const [showContextIndicator, setShowContextIndicator] = useState(defaults.showContextIndicator);
|
|
201
|
+
const [replyFooter, setReplyFooter] = useState(defaults.replyFooter);
|
|
202
|
+
const [injectSender, setInjectSender] = useState(defaults.injectSender);
|
|
93
203
|
const [savePhase, setSavePhase] = useState<'idle' | 'saving' | 'restarting' | 'done'>('idle');
|
|
94
204
|
const [error, setError] = useState<string | null>(null);
|
|
95
205
|
const saving = savePhase === 'saving' || savePhase === 'restarting';
|
|
206
|
+
const [bindingStep, setBindingStep] = useState<'runtime' | 'bind'>('runtime');
|
|
207
|
+
const [bindingSavePending, setBindingSavePending] = useState(false);
|
|
96
208
|
|
|
97
209
|
const defaultsRef = useRef(defaults);
|
|
98
210
|
if (defaults.agentType) defaultsRef.current = defaults;
|
|
@@ -108,11 +220,20 @@ export function RuntimeConfigDialog({
|
|
|
108
220
|
const d = defaultsRef.current;
|
|
109
221
|
setSavePhase('idle');
|
|
110
222
|
setError(null);
|
|
223
|
+
setBindingStep('runtime');
|
|
224
|
+
setBindingSavePending(false);
|
|
111
225
|
setAgentType(d.agentType);
|
|
112
226
|
setPermissionMode(d.permissionMode);
|
|
113
227
|
setWorkDir(d.workDir);
|
|
114
228
|
setDisabledCommandsInput(d.disabledCommands.join(', '));
|
|
115
229
|
setProviderRef(d.providerRefs[0] ?? '');
|
|
230
|
+
setPlatformAllowFrom(d.platformAllowFrom);
|
|
231
|
+
setPlatformAllowChat(d.platformAllowChat);
|
|
232
|
+
setLanguage(d.language);
|
|
233
|
+
setManagedSources(d.managedSources);
|
|
234
|
+
setShowContextIndicator(d.showContextIndicator);
|
|
235
|
+
setReplyFooter(d.replyFooter);
|
|
236
|
+
setInjectSender(d.injectSender);
|
|
116
237
|
}, [open]);
|
|
117
238
|
|
|
118
239
|
// ── Computed ─────────────────────────────────────────────────
|
|
@@ -127,42 +248,93 @@ export function RuntimeConfigDialog({
|
|
|
127
248
|
[defaults.globalProviders, agentType]
|
|
128
249
|
);
|
|
129
250
|
|
|
130
|
-
const
|
|
251
|
+
const boundPlatforms = useMemo<CcProjectPlatform[]>(
|
|
252
|
+
() => data?.platforms ?? [],
|
|
253
|
+
[data?.platforms]
|
|
254
|
+
);
|
|
255
|
+
const platformTypes = useMemo(() => uniquePlatformTypes(boundPlatforms), [boundPlatforms]);
|
|
256
|
+
|
|
257
|
+
const updatePlatformAllowValue = (
|
|
258
|
+
kind: 'from' | 'chat',
|
|
259
|
+
platformType: string,
|
|
260
|
+
value: string
|
|
261
|
+
): void => {
|
|
262
|
+
markRuntimeEdited();
|
|
263
|
+
const setter = kind === 'from' ? setPlatformAllowFrom : setPlatformAllowChat;
|
|
264
|
+
setter((current) => ({ ...current, [platformType]: value }));
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const markRuntimeEdited = (): void => {
|
|
131
268
|
setError(null);
|
|
269
|
+
setSavePhase((phase) => (phase === 'done' ? 'idle' : phase));
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const toggleProviderRef = (providerName: string): void => {
|
|
273
|
+
markRuntimeEdited();
|
|
132
274
|
setProviderRef(providerRef === providerName ? '' : providerName);
|
|
133
275
|
};
|
|
134
276
|
|
|
135
277
|
// ── Save ─────────────────────────────────────────────────────
|
|
136
|
-
const
|
|
137
|
-
if (savePhase !== 'idle') return;
|
|
278
|
+
const buildConfigPayload = (): TeamUpdateConfigRequest => {
|
|
138
279
|
const disabledCommands = disabledCommandsInput
|
|
139
280
|
.split(',')
|
|
140
281
|
.map((e) => e.trim())
|
|
141
282
|
.filter((e) => e.length > 0);
|
|
142
283
|
|
|
284
|
+
const platformAllowFromPatch = buildPlatformAllowUpdatePayload(
|
|
285
|
+
defaults.platformAllowFrom,
|
|
286
|
+
platformAllowFrom
|
|
287
|
+
);
|
|
288
|
+
const platformAllowChatPatch = buildPlatformAllowUpdatePayload(
|
|
289
|
+
defaults.platformAllowChat,
|
|
290
|
+
platformAllowChat
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
agentType: agentType.trim() || undefined,
|
|
295
|
+
workDir: workDir.trim() || undefined,
|
|
296
|
+
permissionMode: permissionMode.trim() || undefined,
|
|
297
|
+
disabledCommands,
|
|
298
|
+
platformAllowFrom: platformAllowFromPatch,
|
|
299
|
+
platformAllowChat: platformAllowChatPatch,
|
|
300
|
+
language: language.trim() || undefined,
|
|
301
|
+
managedSources: managedSources.trim() || undefined,
|
|
302
|
+
showContextIndicator,
|
|
303
|
+
replyFooter,
|
|
304
|
+
injectSender,
|
|
305
|
+
providerRefs: providerRef ? [providerRef] : [],
|
|
306
|
+
};
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
const saveRuntimeConfig = async (): Promise<void> => {
|
|
310
|
+
await api.teams.updateConfig(teamName, buildConfigPayload());
|
|
311
|
+
await Promise.all([fetchTeams(), selectTeam(teamName)]);
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const handleSave = (): void => {
|
|
315
|
+
if (savePhase !== 'idle') return;
|
|
316
|
+
|
|
143
317
|
setSavePhase('saving');
|
|
144
318
|
setError(null);
|
|
145
319
|
|
|
146
320
|
void (async () => {
|
|
147
321
|
try {
|
|
148
|
-
await
|
|
149
|
-
agentType: agentType.trim() || undefined,
|
|
150
|
-
workDir: workDir.trim() || undefined,
|
|
151
|
-
permissionMode: permissionMode.trim() || undefined,
|
|
152
|
-
disabledCommands,
|
|
153
|
-
providerRefs: providerRef ? [providerRef] : [],
|
|
154
|
-
});
|
|
155
|
-
await Promise.all([fetchTeams(), selectTeam(teamName)]);
|
|
322
|
+
await saveRuntimeConfig();
|
|
156
323
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
await api.ccSettings.restart();
|
|
324
|
+
if (isAdminTeam) {
|
|
325
|
+
void Promise.all([fetchTeams(), selectTeam(teamName)]);
|
|
160
326
|
setSavePhase('done');
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
327
|
+
} else {
|
|
328
|
+
setSavePhase('restarting');
|
|
329
|
+
try {
|
|
330
|
+
await api.ccSettings.restart();
|
|
331
|
+
setSavePhase('done');
|
|
332
|
+
} catch (restartErr) {
|
|
333
|
+
setError(
|
|
334
|
+
`配置已保存,但重启失败:${restartErr instanceof Error ? restartErr.message : '未知错误'}`
|
|
335
|
+
);
|
|
336
|
+
setSavePhase('idle');
|
|
337
|
+
}
|
|
166
338
|
}
|
|
167
339
|
} catch (err) {
|
|
168
340
|
setError(err instanceof Error ? err.message : '保存失败');
|
|
@@ -171,6 +343,45 @@ export function RuntimeConfigDialog({
|
|
|
171
343
|
})();
|
|
172
344
|
};
|
|
173
345
|
|
|
346
|
+
const handleStartBinding = (): void => {
|
|
347
|
+
if (saving || bindingSavePending) return;
|
|
348
|
+
|
|
349
|
+
setBindingSavePending(true);
|
|
350
|
+
setError(null);
|
|
351
|
+
void (async () => {
|
|
352
|
+
try {
|
|
353
|
+
await saveRuntimeConfig();
|
|
354
|
+
setBindingStep('bind');
|
|
355
|
+
} catch (err) {
|
|
356
|
+
setError(err instanceof Error ? err.message : '保存配置失败,无法进入渠道绑定');
|
|
357
|
+
} finally {
|
|
358
|
+
setBindingSavePending(false);
|
|
359
|
+
}
|
|
360
|
+
})();
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const handleBindingComplete = (options?: PlatformBindingCompleteOptions): void => {
|
|
364
|
+
if (saving) return;
|
|
365
|
+
|
|
366
|
+
setSavePhase(options?.restartHandled ? 'saving' : 'restarting');
|
|
367
|
+
setError(null);
|
|
368
|
+
void (async () => {
|
|
369
|
+
try {
|
|
370
|
+
if (!options?.restartHandled && !isAdminTeam) {
|
|
371
|
+
await api.ccSettings.restart();
|
|
372
|
+
}
|
|
373
|
+
await Promise.all([fetchTeams(), selectTeam(teamName)]);
|
|
374
|
+
setBindingStep('runtime');
|
|
375
|
+
setSavePhase('done');
|
|
376
|
+
} catch (err) {
|
|
377
|
+
setError(`渠道已绑定,但重启失败:${err instanceof Error ? err.message : '未知错误'}`);
|
|
378
|
+
setBindingStep('runtime');
|
|
379
|
+
setSavePhase('idle');
|
|
380
|
+
void Promise.all([fetchTeams(), selectTeam(teamName)]).catch(() => undefined);
|
|
381
|
+
}
|
|
382
|
+
})();
|
|
383
|
+
};
|
|
384
|
+
|
|
174
385
|
const saveLabel =
|
|
175
386
|
savePhase === 'done'
|
|
176
387
|
? '已完成'
|
|
@@ -178,15 +389,15 @@ export function RuntimeConfigDialog({
|
|
|
178
389
|
? '正在重启...'
|
|
179
390
|
: savePhase === 'saving'
|
|
180
391
|
? '保存中...'
|
|
181
|
-
:
|
|
182
|
-
|
|
183
|
-
|
|
392
|
+
: isAdminTeam
|
|
393
|
+
? '保存'
|
|
394
|
+
: '保存并重启';
|
|
184
395
|
|
|
185
396
|
return (
|
|
186
397
|
<Dialog
|
|
187
|
-
open={
|
|
398
|
+
open={saving || bindingSavePending ? true : open}
|
|
188
399
|
onOpenChange={(nextOpen) => {
|
|
189
|
-
if (saving) return;
|
|
400
|
+
if (saving || bindingSavePending) return;
|
|
190
401
|
if (!nextOpen) onClose();
|
|
191
402
|
}}
|
|
192
403
|
>
|
|
@@ -197,7 +408,7 @@ export function RuntimeConfigDialog({
|
|
|
197
408
|
运行时配置
|
|
198
409
|
</DialogTitle>
|
|
199
410
|
<DialogDescription>
|
|
200
|
-
修改 Agent
|
|
411
|
+
修改 Agent 类型、渠道、Loop 动态设置等运行时参数。部分变更需要重启服务。
|
|
201
412
|
</DialogDescription>
|
|
202
413
|
</DialogHeader>
|
|
203
414
|
|
|
@@ -206,7 +417,9 @@ export function RuntimeConfigDialog({
|
|
|
206
417
|
projectName={defaults.bindProject}
|
|
207
418
|
workDir={workDir}
|
|
208
419
|
agentType={agentType}
|
|
209
|
-
|
|
420
|
+
platformAllowFrom={platformAllowFrom}
|
|
421
|
+
platformAllowChat={platformAllowChat}
|
|
422
|
+
onComplete={handleBindingComplete}
|
|
210
423
|
onCancel={() => setBindingStep('runtime')}
|
|
211
424
|
/>
|
|
212
425
|
) : (
|
|
@@ -218,7 +431,10 @@ export function RuntimeConfigDialog({
|
|
|
218
431
|
<label className={labelCls}>Agent 类型</label>
|
|
219
432
|
<HarnessSelect
|
|
220
433
|
value={agentType as CcAgentType}
|
|
221
|
-
onChange={(v) => {
|
|
434
|
+
onChange={(v) => {
|
|
435
|
+
markRuntimeEdited();
|
|
436
|
+
setAgentType(v);
|
|
437
|
+
}}
|
|
222
438
|
className="w-full"
|
|
223
439
|
/>
|
|
224
440
|
</div>
|
|
@@ -226,11 +442,16 @@ export function RuntimeConfigDialog({
|
|
|
226
442
|
<label className={labelCls}>权限模式</label>
|
|
227
443
|
<select
|
|
228
444
|
value={permissionMode}
|
|
229
|
-
onChange={(e) => {
|
|
445
|
+
onChange={(e) => {
|
|
446
|
+
markRuntimeEdited();
|
|
447
|
+
setPermissionMode(e.target.value);
|
|
448
|
+
}}
|
|
230
449
|
className={inputCls}
|
|
231
450
|
>
|
|
232
451
|
{PERMISSION_MODE_OPTIONS.map((opt) => (
|
|
233
|
-
<option key={opt.value} value={opt.value}>
|
|
452
|
+
<option key={opt.value} value={opt.value}>
|
|
453
|
+
{opt.label}
|
|
454
|
+
</option>
|
|
234
455
|
))}
|
|
235
456
|
</select>
|
|
236
457
|
</div>
|
|
@@ -240,7 +461,10 @@ export function RuntimeConfigDialog({
|
|
|
240
461
|
<input
|
|
241
462
|
type="text"
|
|
242
463
|
value={workDir}
|
|
243
|
-
onChange={(e) => {
|
|
464
|
+
onChange={(e) => {
|
|
465
|
+
markRuntimeEdited();
|
|
466
|
+
setWorkDir(e.target.value);
|
|
467
|
+
}}
|
|
244
468
|
className={`${inputCls} font-mono`}
|
|
245
469
|
placeholder="/Users/you/code/project"
|
|
246
470
|
/>
|
|
@@ -248,30 +472,160 @@ export function RuntimeConfigDialog({
|
|
|
248
472
|
</FormSection>
|
|
249
473
|
|
|
250
474
|
{/* 渠道 */}
|
|
251
|
-
<FormSection title="渠道" description="
|
|
475
|
+
<FormSection title="渠道" description="绑定外部协作平台(飞书、Telegram 等)。">
|
|
476
|
+
<BoundPlatformList platforms={boundPlatforms} />
|
|
477
|
+
{platformTypes.length > 0 ? (
|
|
478
|
+
<div className="space-y-2">
|
|
479
|
+
{platformTypes.map((platformType) => (
|
|
480
|
+
<details
|
|
481
|
+
key={platformType}
|
|
482
|
+
className="rounded-lg border border-[var(--color-border-subtle)] bg-[var(--color-surface)] px-3 py-2"
|
|
483
|
+
>
|
|
484
|
+
<summary className="cursor-pointer text-xs font-medium text-[var(--color-text)]">
|
|
485
|
+
{getPlatformLabel(platformType)} 入口权限
|
|
486
|
+
</summary>
|
|
487
|
+
<div className="mt-3 grid gap-3 md:grid-cols-2">
|
|
488
|
+
<div>
|
|
489
|
+
<label className={labelCls}>允许用户</label>
|
|
490
|
+
<input
|
|
491
|
+
type="text"
|
|
492
|
+
value={platformAllowFrom[platformType] ?? ''}
|
|
493
|
+
onChange={(event) =>
|
|
494
|
+
updatePlatformAllowValue('from', platformType, event.target.value)
|
|
495
|
+
}
|
|
496
|
+
className={`${inputCls} font-mono`}
|
|
497
|
+
placeholder={getPlatformAllowPlaceholder(platformType, 'from')}
|
|
498
|
+
/>
|
|
499
|
+
</div>
|
|
500
|
+
<div>
|
|
501
|
+
<label className={labelCls}>允许群聊/频道</label>
|
|
502
|
+
<input
|
|
503
|
+
type="text"
|
|
504
|
+
value={platformAllowChat[platformType] ?? ''}
|
|
505
|
+
onChange={(event) =>
|
|
506
|
+
updatePlatformAllowValue('chat', platformType, event.target.value)
|
|
507
|
+
}
|
|
508
|
+
className={`${inputCls} font-mono`}
|
|
509
|
+
placeholder={getPlatformAllowPlaceholder(platformType, 'chat')}
|
|
510
|
+
/>
|
|
511
|
+
</div>
|
|
512
|
+
</div>
|
|
513
|
+
</details>
|
|
514
|
+
))}
|
|
515
|
+
</div>
|
|
516
|
+
) : null}
|
|
517
|
+
<p className="text-[11px] leading-relaxed text-[var(--color-text-muted)]">
|
|
518
|
+
按渠道控制运行时入口。留空代表未单独配置,不等于允许所有;只有显式填写 *
|
|
519
|
+
才表示放行所有。
|
|
520
|
+
</p>
|
|
252
521
|
<Button
|
|
253
522
|
variant="outline"
|
|
254
523
|
size="sm"
|
|
255
|
-
onClick={
|
|
524
|
+
onClick={handleStartBinding}
|
|
525
|
+
disabled={saving || bindingSavePending}
|
|
256
526
|
>
|
|
257
|
-
|
|
527
|
+
{bindingSavePending && <Loader2 size={14} className="mr-1.5 animate-spin" />}
|
|
528
|
+
{bindingSavePending ? '保存配置中...' : '绑定新渠道'}
|
|
258
529
|
</Button>
|
|
259
530
|
</FormSection>
|
|
260
531
|
|
|
532
|
+
{/* Loop 动态设置 — 语言/管理来源/消息格式,保存即生效 (#21) */}
|
|
533
|
+
<FormSection
|
|
534
|
+
title="Loop 动态设置"
|
|
535
|
+
description="语言、管理来源与消息格式,保存即生效(无需重启)。"
|
|
536
|
+
>
|
|
537
|
+
<div className="grid gap-3 md:grid-cols-2">
|
|
538
|
+
<div>
|
|
539
|
+
<label className={labelCls}>语言</label>
|
|
540
|
+
<input
|
|
541
|
+
type="text"
|
|
542
|
+
value={language}
|
|
543
|
+
onChange={(e) => {
|
|
544
|
+
markRuntimeEdited();
|
|
545
|
+
setLanguage(e.target.value);
|
|
546
|
+
}}
|
|
547
|
+
className={inputCls}
|
|
548
|
+
placeholder="zh"
|
|
549
|
+
data-testid="loop-language"
|
|
550
|
+
/>
|
|
551
|
+
</div>
|
|
552
|
+
<div>
|
|
553
|
+
<label className={labelCls}>管理来源</label>
|
|
554
|
+
<input
|
|
555
|
+
type="text"
|
|
556
|
+
value={managedSources}
|
|
557
|
+
onChange={(e) => {
|
|
558
|
+
markRuntimeEdited();
|
|
559
|
+
setManagedSources(e.target.value);
|
|
560
|
+
}}
|
|
561
|
+
className={inputCls}
|
|
562
|
+
placeholder="user1,user2 或 *"
|
|
563
|
+
data-testid="loop-managed-sources"
|
|
564
|
+
/>
|
|
565
|
+
</div>
|
|
566
|
+
</div>
|
|
567
|
+
<div className="flex flex-wrap gap-2">
|
|
568
|
+
<label className="flex cursor-pointer items-center gap-2 rounded-lg border border-[var(--color-border-subtle)] px-2.5 py-1.5 text-xs text-[var(--color-text-secondary)]">
|
|
569
|
+
<input
|
|
570
|
+
type="checkbox"
|
|
571
|
+
checked={showContextIndicator}
|
|
572
|
+
onChange={(e) => {
|
|
573
|
+
markRuntimeEdited();
|
|
574
|
+
setShowContextIndicator(e.target.checked);
|
|
575
|
+
}}
|
|
576
|
+
className="size-3.5"
|
|
577
|
+
data-testid="loop-show-context-indicator"
|
|
578
|
+
/>
|
|
579
|
+
上下文指示
|
|
580
|
+
</label>
|
|
581
|
+
<label className="flex cursor-pointer items-center gap-2 rounded-lg border border-[var(--color-border-subtle)] px-2.5 py-1.5 text-xs text-[var(--color-text-secondary)]">
|
|
582
|
+
<input
|
|
583
|
+
type="checkbox"
|
|
584
|
+
checked={replyFooter}
|
|
585
|
+
onChange={(e) => {
|
|
586
|
+
markRuntimeEdited();
|
|
587
|
+
setReplyFooter(e.target.checked);
|
|
588
|
+
}}
|
|
589
|
+
className="size-3.5"
|
|
590
|
+
data-testid="loop-reply-footer"
|
|
591
|
+
/>
|
|
592
|
+
回复尾部信息
|
|
593
|
+
</label>
|
|
594
|
+
<label className="flex cursor-pointer items-center gap-2 rounded-lg border border-[var(--color-border-subtle)] px-2.5 py-1.5 text-xs text-[var(--color-text-secondary)]">
|
|
595
|
+
<input
|
|
596
|
+
type="checkbox"
|
|
597
|
+
checked={injectSender}
|
|
598
|
+
onChange={(e) => {
|
|
599
|
+
markRuntimeEdited();
|
|
600
|
+
setInjectSender(e.target.checked);
|
|
601
|
+
}}
|
|
602
|
+
className="size-3.5"
|
|
603
|
+
data-testid="loop-inject-sender"
|
|
604
|
+
/>
|
|
605
|
+
注入发送者
|
|
606
|
+
</label>
|
|
607
|
+
</div>
|
|
608
|
+
</FormSection>
|
|
609
|
+
|
|
261
610
|
{/* Provider */}
|
|
262
|
-
<div className="rounded-
|
|
611
|
+
<div className="bg-[var(--color-surface-raised)]/55 relative overflow-hidden rounded-xl border border-[var(--color-border-subtle)] p-3 shadow-sm shadow-black/10">
|
|
612
|
+
<div className="pointer-events-none absolute inset-x-6 top-0 h-px bg-gradient-to-r from-transparent via-[var(--color-accent-border)] to-transparent" />
|
|
263
613
|
<div className="flex items-start justify-between gap-3">
|
|
264
614
|
<div>
|
|
265
615
|
<p className="text-xs font-medium text-[var(--color-text)]">Provider(可选)</p>
|
|
266
616
|
<p className="mt-1 text-[11px] leading-relaxed text-[var(--color-text-muted)]">
|
|
267
|
-
留空时使用本机 {AGENT_TYPE_LABELS[agentType as CcAgentType] ?? agentType}
|
|
617
|
+
留空时使用本机 {AGENT_TYPE_LABELS[agentType as CcAgentType] ?? agentType}{' '}
|
|
618
|
+
默认配置。
|
|
268
619
|
</p>
|
|
269
620
|
</div>
|
|
270
621
|
{providerRef ? (
|
|
271
622
|
<button
|
|
272
623
|
type="button"
|
|
273
624
|
className="shrink-0 rounded-md border border-[var(--color-border)] px-2 py-1 text-[11px] text-[var(--color-text-muted)] hover:bg-white/5"
|
|
274
|
-
onClick={() =>
|
|
625
|
+
onClick={() => {
|
|
626
|
+
markRuntimeEdited();
|
|
627
|
+
setProviderRef('');
|
|
628
|
+
}}
|
|
275
629
|
>
|
|
276
630
|
使用本机默认
|
|
277
631
|
</button>
|
|
@@ -284,7 +638,10 @@ export function RuntimeConfigDialog({
|
|
|
284
638
|
const at = agentType as CcAgentType;
|
|
285
639
|
const endpoint = provider.endpoints?.[at] ?? provider.base_url ?? '默认端点';
|
|
286
640
|
const model =
|
|
287
|
-
provider.agent_models?.[at] ??
|
|
641
|
+
provider.agent_models?.[at] ??
|
|
642
|
+
provider.model ??
|
|
643
|
+
provider.models?.[0]?.model ??
|
|
644
|
+
'未指定模型';
|
|
288
645
|
return (
|
|
289
646
|
<button
|
|
290
647
|
key={provider.name}
|
|
@@ -292,20 +649,24 @@ export function RuntimeConfigDialog({
|
|
|
292
649
|
onClick={() => toggleProviderRef(provider.name)}
|
|
293
650
|
className={`w-full rounded-lg border px-3 py-2 text-left transition-colors ${
|
|
294
651
|
checked
|
|
295
|
-
? '
|
|
296
|
-
: 'border-[var(--color-border-subtle)] bg-black/10 hover:border-[var(--color-border)] hover:bg-
|
|
652
|
+
? 'shadow-[var(--color-accent-glow)]/20 border-[var(--color-accent-border)] bg-[var(--color-accent-muted)] shadow-sm'
|
|
653
|
+
: 'border-[var(--color-border-subtle)] bg-black/10 hover:border-[var(--color-border)] hover:bg-[var(--color-accent-soft)]'
|
|
297
654
|
}`}
|
|
298
655
|
>
|
|
299
656
|
<div className="flex items-center justify-between gap-3">
|
|
300
657
|
<div className="min-w-0">
|
|
301
|
-
<p className="truncate text-xs font-medium text-[var(--color-text)]">
|
|
658
|
+
<p className="truncate text-xs font-medium text-[var(--color-text)]">
|
|
659
|
+
{provider.name}
|
|
660
|
+
</p>
|
|
302
661
|
<p className="mt-0.5 truncate text-[11px] text-[var(--color-text-muted)]">
|
|
303
662
|
{model} · {endpoint}
|
|
304
663
|
</p>
|
|
305
664
|
</div>
|
|
306
665
|
<span
|
|
307
666
|
className={`shrink-0 rounded-full px-2 py-0.5 text-[10px] ${
|
|
308
|
-
checked
|
|
667
|
+
checked
|
|
668
|
+
? 'bg-[var(--color-accent-soft)] text-[var(--color-accent)]'
|
|
669
|
+
: 'bg-white/5 text-[var(--color-text-muted)]'
|
|
309
670
|
}`}
|
|
310
671
|
>
|
|
311
672
|
{checked ? '已绑定' : '可绑定'}
|
|
@@ -316,7 +677,8 @@ export function RuntimeConfigDialog({
|
|
|
316
677
|
})
|
|
317
678
|
) : (
|
|
318
679
|
<div className="rounded-md border border-dashed border-[var(--color-border)] px-3 py-3 text-xs text-[var(--color-text-muted)]">
|
|
319
|
-
暂无适用于 {AGENT_TYPE_LABELS[agentType as CcAgentType] ?? agentType} 的全局
|
|
680
|
+
暂无适用于 {AGENT_TYPE_LABELS[agentType as CcAgentType] ?? agentType} 的全局
|
|
681
|
+
Provider。
|
|
320
682
|
</div>
|
|
321
683
|
)}
|
|
322
684
|
</div>
|
|
@@ -329,7 +691,10 @@ export function RuntimeConfigDialog({
|
|
|
329
691
|
<input
|
|
330
692
|
type="text"
|
|
331
693
|
value={disabledCommandsInput}
|
|
332
|
-
onChange={(e) => {
|
|
694
|
+
onChange={(e) => {
|
|
695
|
+
markRuntimeEdited();
|
|
696
|
+
setDisabledCommandsInput(e.target.value);
|
|
697
|
+
}}
|
|
333
698
|
className={inputCls}
|
|
334
699
|
placeholder="restart, upgrade, cron"
|
|
335
700
|
/>
|
|
@@ -342,13 +707,18 @@ export function RuntimeConfigDialog({
|
|
|
342
707
|
|
|
343
708
|
{bindingStep === 'runtime' && (
|
|
344
709
|
<DialogFooter>
|
|
345
|
-
<Button
|
|
710
|
+
<Button
|
|
711
|
+
variant="outline"
|
|
712
|
+
size="sm"
|
|
713
|
+
onClick={onClose}
|
|
714
|
+
disabled={saving || bindingSavePending}
|
|
715
|
+
>
|
|
346
716
|
{savePhase === 'done' ? '关闭' : '取消'}
|
|
347
717
|
</Button>
|
|
348
718
|
<Button
|
|
349
719
|
size="sm"
|
|
350
720
|
onClick={handleSave}
|
|
351
|
-
disabled={saving || savePhase === 'done'}
|
|
721
|
+
disabled={saving || bindingSavePending || savePhase === 'done'}
|
|
352
722
|
>
|
|
353
723
|
{saving && <Loader2 size={14} className="mr-1.5 animate-spin" />}
|
|
354
724
|
{saveLabel}
|