@yancyyu/openhermit 1.6.42 → 1.6.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +98 -89
- package/bin/hermit.mjs +96 -0
- package/dist-renderer/assets/{ProjectEditorOverlay-DlFQ6mai.js → ProjectEditorOverlay-C98qSs7-.js} +1 -1
- package/dist-renderer/assets/{TeamGraphOverlay-D2TPMPGR.js → TeamGraphOverlay-CsBbZwcL.js} +1 -1
- package/dist-renderer/assets/{_basePickBy-Cmd0RHLQ.js → _basePickBy-ZOyLWjMK.js} +1 -1
- package/dist-renderer/assets/{_baseUniq-BI_iy8ea.js → _baseUniq-DBb726rt.js} +1 -1
- package/dist-renderer/assets/{arc-NzW2mjTP.js → arc-CdiTaR_R.js} +1 -1
- package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-Bzq85AYv.js → architectureDiagram-VXUJARFQ-Cz3sc5TH.js} +1 -1
- package/dist-renderer/assets/{blockDiagram-VD42YOAC-D1PvYS-b.js → blockDiagram-VD42YOAC-DE4c-KJ3.js} +1 -1
- package/dist-renderer/assets/{c4Diagram-YG6GDRKO-D49RKzPC.js → c4Diagram-YG6GDRKO-CmTMDTrV.js} +1 -1
- package/dist-renderer/assets/channel-KTpqi9eT.js +1 -0
- package/dist-renderer/assets/{chunk-4BX2VUAB-fmI_MQmQ.js → chunk-4BX2VUAB-rhHy3tFl.js} +1 -1
- package/dist-renderer/assets/{chunk-55IACEB6-Xsv9RCXZ.js → chunk-55IACEB6-fLZBzuo_.js} +1 -1
- package/dist-renderer/assets/{chunk-B4BG7PRW-BE1KO8Um.js → chunk-B4BG7PRW-DOzxQhim.js} +1 -1
- package/dist-renderer/assets/{chunk-DI55MBZ5-tqJ7Mv7f.js → chunk-DI55MBZ5-COQCcXC5.js} +1 -1
- package/dist-renderer/assets/{chunk-FMBD7UC4-DMD45MVJ.js → chunk-FMBD7UC4-IKU9U_Y4.js} +1 -1
- package/dist-renderer/assets/{chunk-QN33PNHL-DOhGrz-q.js → chunk-QN33PNHL-D6WV154X.js} +1 -1
- package/dist-renderer/assets/{chunk-QZHKN3VN-D8yDgJdD.js → chunk-QZHKN3VN-D90_2DQp.js} +1 -1
- package/dist-renderer/assets/{chunk-TZMSLE5B-BcsEDu7A.js → chunk-TZMSLE5B-BQEil57G.js} +1 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-lpzulY5X.js +1 -0
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-lpzulY5X.js +1 -0
- package/dist-renderer/assets/clone-CriGymY9.js +1 -0
- package/dist-renderer/assets/{cose-bilkent-S5V4N54A-DlSqGHMX.js → cose-bilkent-S5V4N54A-6WiK6U2P.js} +1 -1
- package/dist-renderer/assets/{dagre-6UL2VRFP-BTT9tSAx.js → dagre-6UL2VRFP-DF4MMuTn.js} +1 -1
- package/dist-renderer/assets/{diagram-PSM6KHXK-Du-U-mK2.js → diagram-PSM6KHXK-CcF1eZ7E.js} +1 -1
- package/dist-renderer/assets/{diagram-QEK2KX5R-jFdHeKas.js → diagram-QEK2KX5R-DYlOVPQB.js} +1 -1
- package/dist-renderer/assets/{diagram-S2PKOQOG-DKLNK2bu.js → diagram-S2PKOQOG-BHXWsZOP.js} +1 -1
- package/dist-renderer/assets/{erDiagram-Q2GNP2WA-CZxHgIIo.js → erDiagram-Q2GNP2WA-GjmuBx8d.js} +1 -1
- package/dist-renderer/assets/{flowDiagram-NV44I4VS-v4XStCD0.js → flowDiagram-NV44I4VS-BuS7YVHk.js} +1 -1
- package/dist-renderer/assets/{ganttDiagram-JELNMOA3-DJjD_BEL.js → ganttDiagram-JELNMOA3-3Teu5tAa.js} +1 -1
- package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-BNy-jr03.js → gitGraphDiagram-V2S2FVAM-BiLdCYu5.js} +1 -1
- package/dist-renderer/assets/{graph-DDTrn6je.js → graph-CDP_R8ct.js} +1 -1
- package/dist-renderer/assets/{index-BBp78BAu.js → index-BSZdT-g-.js} +1 -1
- package/dist-renderer/assets/{index-eotrJaYy.js → index-BhWvMqsz.js} +1 -1
- package/dist-renderer/assets/{index-D8_B-cfs.js → index-C2_AupSj.js} +1 -1
- package/dist-renderer/assets/{index-BQrwHZ-k.js → index-C5ujiwAR.js} +580 -588
- package/dist-renderer/assets/index-CIS2CTK9.css +1 -0
- package/dist-renderer/assets/{index-CRKQSG9S.js → index-CVNjLwkq.js} +1 -1
- package/dist-renderer/assets/{index-DR6Wz52b.js → index-CwG3se0q.js} +1 -1
- package/dist-renderer/assets/{infoDiagram-HS3SLOUP-DqnOsuza.js → infoDiagram-HS3SLOUP-DLHUFo72.js} +1 -1
- package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-DTobaO1d.js → journeyDiagram-XKPGCS4Q-BE07RpJD.js} +1 -1
- package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-HbwVOvWc.js → kanban-definition-3W4ZIXB7-DDHZy4NB.js} +1 -1
- package/dist-renderer/assets/{layout--VYmTcw2.js → layout-5nA5wUxO.js} +1 -1
- package/dist-renderer/assets/{linear-BsJh89Mr.js → linear-BtF1i2qN.js} +1 -1
- package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-BZqUZePd.js → mindmap-definition-VGOIOE7T-Z1Ui9Sqy.js} +1 -1
- package/dist-renderer/assets/{pieDiagram-ADFJNKIX-B1q_nH6P.js → pieDiagram-ADFJNKIX-LCjxckWv.js} +1 -1
- package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-UD8QhSEu.js → quadrantDiagram-AYHSOK5B-BOwKjSco.js} +1 -1
- package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-BA_i7Nw8.js → requirementDiagram-UZGBJVZJ-pChP8Znd.js} +1 -1
- package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-CMTnX-2d.js → sankeyDiagram-TZEHDZUN-DifZ2qpo.js} +1 -1
- package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-BQXDB615.js → sequenceDiagram-WL72ISMW-CJg-WYyY.js} +1 -1
- package/dist-renderer/assets/{splashScene-D0YB9uxm.js → splashScene-94xWCzLA.js} +1 -1
- package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-BAsPXy6X.js → stateDiagram-FKZM4ZOC-DWHOoFdv.js} +1 -1
- package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-CGYZOoMb.js +1 -0
- package/dist-renderer/assets/{timeline-definition-IT6M3QCI-BdasmVkC.js → timeline-definition-IT6M3QCI-CPgokIo8.js} +1 -1
- package/dist-renderer/assets/{treemap-GDKQZRPO-BkKQqIui.js → treemap-GDKQZRPO-DAVqSR9L.js} +1 -1
- package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-EAlPHOdx.js → xychartDiagram-PRI3JC2R-CCOcGbrD.js} +1 -1
- package/dist-renderer/chat-community-qr.jpg +0 -0
- package/dist-renderer/fonts/Agave-Bold.ttf +0 -0
- package/dist-renderer/fonts/Agave-Regular.ttf +0 -0
- package/dist-renderer/icon.png +0 -0
- package/dist-renderer/icon.rar +0 -0
- package/dist-renderer/index.html +3 -3
- package/package.json +21 -26
- package/src/features/worker-society/core/application/WorkerSocietyService.test.ts +802 -0
- package/src/features/worker-society/core/application/WorkerSocietyService.ts +428 -0
- package/src/features/worker-society/core/application/fakes.ts +101 -0
- package/src/features/worker-society/core/application/ports.ts +70 -0
- package/src/features/worker-society/core/domain/models/society.ts +141 -0
- package/src/features/worker-society/core/domain/policies/societyPolicies.test.ts +739 -0
- package/src/features/worker-society/core/domain/policies/societyPolicies.ts +496 -0
- package/src/features/worker-society/main/adapters/input/societyMcp.test.ts +317 -0
- package/src/features/worker-society/main/adapters/input/societyMcp.ts +257 -0
- package/src/features/worker-society/main/adapters/input/societyRoutes.test.ts +695 -0
- package/src/features/worker-society/main/adapters/input/societyRoutes.ts +194 -0
- package/src/features/worker-society/main/composition/societyComposition.test.ts +74 -0
- package/src/features/worker-society/main/composition/societyComposition.ts +70 -0
- package/src/features/worker-society/main/composition/workerSocietyPlugin.test.ts +69 -0
- package/src/features/worker-society/main/composition/workerSocietyPlugin.ts +67 -0
- package/src/features/worker-society/main/infrastructure/crossTeamMessageGateway.test.ts +132 -0
- package/src/features/worker-society/main/infrastructure/crossTeamMessageGateway.ts +84 -0
- package/src/features/worker-society/main/infrastructure/fsStores.test.ts +216 -0
- package/src/features/worker-society/main/infrastructure/fsStores.ts +113 -0
- package/src/features/worker-society/main/infrastructure/mergingProfileStore.test.ts +195 -0
- package/src/features/worker-society/main/infrastructure/mergingProfileStore.ts +96 -0
- package/src/features/worker-society/renderer/SocietyGraph.tsx +166 -0
- package/src/features/worker-society/renderer/SocietyNodeLabels.tsx +139 -0
- package/src/features/worker-society/renderer/SocietyNodeOverlay.tsx +339 -0
- package/src/features/worker-society/renderer/SocietyView.tsx +437 -0
- package/src/features/worker-society/renderer/index.ts +11 -0
- package/src/features/worker-society/renderer/societyApi.test.ts +259 -0
- package/src/features/worker-society/renderer/societyApi.ts +144 -0
- package/src/features/worker-society/renderer/societyGraphAdapter.test.ts +321 -0
- package/src/features/worker-society/renderer/societyGraphAdapter.ts +240 -0
- package/src/features/worker-society/renderer/societyOverlayActions.test.ts +57 -0
- package/src/features/worker-society/renderer/societyOverlayActions.ts +49 -0
- package/src/features/worker-society/renderer/societyStore.test.ts +218 -0
- package/src/features/worker-society/renderer/societyStore.ts +146 -0
- package/src/features/worker-society/renderer/societyViewUtils.test.ts +81 -0
- package/src/features/worker-society/renderer/societyViewUtils.ts +68 -0
- package/src/main/ipc/extensions.ts +27 -0
- package/src/main/server.ts +1709 -534
- package/src/main/services/ccConnect/CcConnectBridge.ts +26 -11
- package/src/main/services/ccConnect/CcConnectClient.ts +9 -2
- package/src/main/services/ccConnect/workDirReconcile.test.ts +57 -0
- package/src/main/services/ccConnect/workDirReconcile.ts +36 -0
- package/src/main/services/direct-cli/DirectCliSessionManager.test.ts +397 -0
- package/src/main/services/direct-cli/DirectCliSessionManager.ts +508 -0
- package/src/main/services/direct-cli/DirectCliSessionStore.test.ts +79 -0
- package/src/main/services/direct-cli/DirectCliSessionStore.ts +97 -0
- package/src/main/services/direct-cli/__tests__/directCliMessageId.test.ts +40 -0
- package/src/main/services/direct-cli/directCliMessageId.ts +21 -0
- package/src/main/services/direct-cli/index.ts +17 -0
- package/src/main/services/extensions/capability-packs/CapabilityPackLoaderService.ts +637 -0
- package/src/main/services/extensions/catalog/PluginCatalogService.ts +2 -2
- package/src/main/services/loop-assets/LoopAssetsScannerService.ts +657 -0
- package/src/main/services/runtime/providerAwareCliEnv.ts +33 -5
- package/src/main/services/session-intelligence/LocalSessionScanner.ts +156 -71
- package/src/main/services/session-intelligence/SessionUsageParser.ts +103 -8
- package/src/main/services/session-intelligence/UsageTelemetryService.ts +11 -0
- package/src/main/services/session-intelligence/__tests__/teamSessionListMapper.test.ts +104 -0
- package/src/main/services/session-intelligence/teamSessionListMapper.ts +78 -0
- package/src/main/services/system-manager/AdminLoopInitializer.ts +95 -0
- package/src/main/services/system-manager/BuiltinWorkflowSeeder.ts +679 -74
- package/src/main/services/system-manager/SystemManagerConfigService.ts +19 -1
- package/src/main/services/system-manager/WorkflowPromptService.ts +58 -5
- package/src/main/services/system-manager/__tests__/AdminLoopInitializer.test.ts +129 -0
- package/src/main/services/system-manager/__tests__/SystemManagerConfigService.test.ts +60 -0
- package/src/main/services/teams-mvp/CollaborationBoardService.ts +2 -0
- package/src/main/services/teams-mvp/OpsRunbookContext.ts +60 -0
- package/src/main/services/teams-mvp/TaskDispatchService.test.ts +305 -0
- package/src/main/services/teams-mvp/TaskDispatchService.ts +250 -131
- package/src/main/services/teams-mvp/TeamProvisioningService.ts +12 -2
- package/src/main/services/teams-mvp/TeamWorkspaceService.test.ts +207 -0
- package/src/main/services/teams-mvp/TeamWorkspaceService.ts +104 -51
- package/src/main/services/teams-mvp/index.ts +6 -0
- package/src/main/utils/externalPlatformSessionRouting.ts +92 -0
- package/src/main/utils/toolApprovalRules.ts +151 -0
- package/src/renderer/App.tsx +24 -89
- package/src/renderer/api/httpClient.ts +115 -37
- package/src/renderer/api/providers.ts +5 -16
- package/src/renderer/components/chat/CommunityChatView.tsx +81 -0
- package/src/renderer/components/dashboard/DashboardView.tsx +130 -84
- package/src/renderer/components/extensions/ExtensionStoreView.tsx +39 -5
- package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +2 -1
- package/src/renderer/components/extensions/capability-packs/CapabilityPacksPanel.tsx +170 -0
- package/src/renderer/components/layout/PaneContent.tsx +10 -2
- package/src/renderer/components/layout/SortableTab.tsx +4 -0
- package/src/renderer/components/layout/TabBarActions.tsx +13 -16
- package/src/renderer/components/runtime/ProviderRuntimeSettingsDialog.tsx +4 -135
- package/src/renderer/components/schedules/SchedulesView.tsx +22 -14
- package/src/renderer/components/schedules/calendar/CalendarEventBlock.tsx +7 -6
- package/src/renderer/components/settings/SettingsTabs.tsx +24 -21
- package/src/renderer/components/settings/SettingsView.tsx +22 -13
- package/src/renderer/components/settings/components/SettingRow.tsx +13 -5
- package/src/renderer/components/settings/components/SettingsSectionCard.tsx +53 -0
- package/src/renderer/components/settings/components/SettingsSectionHeader.tsx +10 -6
- package/src/renderer/components/settings/components/SettingsSelect.tsx +12 -9
- package/src/renderer/components/settings/components/SettingsToggle.tsx +6 -5
- package/src/renderer/components/settings/components/index.ts +1 -0
- package/src/renderer/components/settings/sections/AdvancedSection.tsx +78 -59
- package/src/renderer/components/settings/sections/CliStatusSection.tsx +32 -44
- package/src/renderer/components/settings/sections/ConfigEditorDialog.tsx +1 -1
- package/src/renderer/components/settings/sections/GeneralSection.tsx +216 -186
- package/src/renderer/components/settings/sections/PlatformsSection.tsx +25 -17
- package/src/renderer/components/settings/sections/TaskBusSection.tsx +63 -22
- package/src/renderer/components/sidebar/SidebarSessions.tsx +120 -80
- package/src/renderer/components/sidebar/SidebarTaskItem.tsx +1 -1
- package/src/renderer/components/splash/splashScene.ts +6 -2
- package/src/renderer/components/system-manager/SystemManagerView.tsx +169 -255
- package/src/renderer/components/tasks/TasksView.tsx +63 -37
- package/src/renderer/components/team/CcSessionsSection.tsx +124 -89
- package/src/renderer/components/team/HarnessBrandLogos.tsx +318 -0
- package/src/renderer/components/team/HarnessSelect.tsx +25 -26
- package/src/renderer/components/team/TeamDetailView.tsx +137 -153
- package/src/renderer/components/team/TeamEmptyState.tsx +9 -37
- package/src/renderer/components/team/TeamListView.tsx +143 -30
- package/src/renderer/components/team/__tests__/CcSessionsSection.hasLocalFile.test.tsx +128 -0
- package/src/renderer/components/team/activity/ActivityItem.tsx +21 -9
- package/src/renderer/components/team/activity/ActivityTimeline.tsx +2 -2
- package/src/renderer/components/team/dialogs/AdvancedCliSection.tsx +1 -1
- package/src/renderer/components/team/dialogs/CreateTaskDialog.tsx +13 -10
- package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +156 -83
- package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +9 -157
- package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +19 -15
- package/src/renderer/components/team/dialogs/PlatformBindingDialog.tsx +48 -10
- package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +11 -12
- package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +39 -37
- package/src/renderer/components/team/dialogs/RuntimeConfigDialog.tsx +434 -64
- package/src/renderer/components/team/dialogs/SendMessageDialog.tsx +12 -10
- package/src/renderer/components/team/dialogs/TaskDetailDialog.tsx +2 -2
- package/src/renderer/components/team/dialogs/__tests__/CreateTeamDialog.bindProject.test.tsx +399 -0
- package/src/renderer/components/team/dialogs/__tests__/CreateTeamDialog.chineseRepro.test.tsx +253 -0
- package/src/renderer/components/team/dialogs/platformAllowUtils.ts +91 -0
- package/src/renderer/components/team/dialogs/teammateRuntimeCompatibility.tsx +1 -1
- package/src/renderer/components/team/kanban/KanbanTaskCard.test.tsx +41 -0
- package/src/renderer/components/team/kanban/KanbanTaskCard.tsx +41 -86
- package/src/renderer/components/team/loop-console/LoopCommandComposer.tsx +310 -0
- package/src/renderer/components/team/loop-console/LoopConsolePanel.tsx +372 -0
- package/src/renderer/components/team/loop-console/loopSendIntent.test.ts +85 -0
- package/src/renderer/components/team/loop-console/loopSendIntent.ts +221 -0
- package/src/renderer/components/team/loop-console/useLeadSessionToolActivity.ts +74 -0
- package/src/renderer/components/team/loop-console/useLoopCommandSuggestions.ts +165 -0
- package/src/renderer/components/team/loop-console/useLoopConsoleController.ts +266 -0
- package/src/renderer/components/team/members/LeadModelRow.test.tsx +1 -1
- package/src/renderer/components/team/members/LeadModelRow.tsx +5 -3
- package/src/renderer/components/team/members/MemberDetailDialog.tsx +11 -0
- package/src/renderer/components/team/members/MemberDetailStats.tsx +13 -3
- package/src/renderer/components/team/members/MemberDraftRow.test.tsx +1 -1
- package/src/renderer/components/team/members/MemberDraftRow.tsx +1 -1
- package/src/renderer/components/team/members/MemberMessagesTab.tsx +2 -2
- package/src/renderer/components/team/members/MemberStatsTab.tsx +1 -1
- package/src/renderer/components/team/messages/MessageComposer.tsx +150 -44
- package/src/renderer/components/team/messages/MessagesFilterPopover.tsx +2 -2
- package/src/renderer/components/team/messages/MessagesPanel.tsx +34 -28
- package/src/renderer/components/team/schedule/CcCronScheduleDialog.tsx +6 -6
- package/src/renderer/components/team/taskLogs/ExactTaskLogCard.tsx +2 -2
- package/src/renderer/components/team/taskLogs/TaskLogStreamSection.tsx +1 -1
- package/src/renderer/components/terminal/TerminalPanel.tsx +2 -3
- package/src/renderer/components/ui/MentionableTextarea.tsx +5 -1
- package/src/renderer/constants/teamColors.ts +5 -5
- package/src/renderer/hooks/useExtensionsTabState.ts +1 -1
- package/src/renderer/hooks/useMentionDetection.ts +5 -1
- package/src/renderer/hooks/useProjectWorkflowCommands.ts +57 -0
- package/src/renderer/hooks/useTeamSuggestions.ts +2 -0
- package/src/renderer/index.css +19 -2
- package/src/renderer/main.tsx +7 -1
- package/src/renderer/store/index.ts +18 -1
- package/src/renderer/store/slices/extensionsSlice.ts +83 -0
- package/src/renderer/store/slices/tabSlice.ts +61 -0
- package/src/renderer/store/slices/teamSlice.ts +138 -9
- package/src/renderer/types/mention.ts +8 -0
- package/src/renderer/types/tabs.ts +3 -1
- package/src/renderer/utils/__tests__/bindProjectSlug.test.ts +69 -0
- package/src/renderer/utils/__tests__/groupTransformer.test.ts +148 -0
- package/src/renderer/utils/__tests__/initialRoute.test.ts +101 -0
- package/src/renderer/utils/__tests__/leadToolActivity.test.ts +124 -0
- package/src/renderer/utils/__tests__/mergeTeamMessages.test.ts +81 -0
- package/src/renderer/utils/__tests__/teamMessageFiltering.test.ts +213 -0
- package/src/renderer/utils/__tests__/teamMessageKey.test.ts +75 -0
- package/src/renderer/utils/__tests__/workflowCommandExecution.test.ts +173 -0
- package/src/renderer/utils/__tests__/workflowCommandSuggestions.test.ts +59 -0
- package/src/renderer/utils/bindProjectSlug.ts +57 -0
- package/src/renderer/utils/capabilityCommandExecution.ts +113 -0
- package/src/renderer/utils/initialRoute.ts +89 -0
- package/src/renderer/utils/leadToolActivity.ts +117 -0
- package/src/renderer/utils/loopShortcutSuggestions.ts +106 -0
- package/src/renderer/utils/mentionSuggestions.ts +1 -1
- package/src/renderer/utils/slashCommandRegistry.ts +231 -0
- package/src/renderer/utils/teamMentionDirective.ts +31 -0
- package/src/renderer/utils/workflowCommandExecution.ts +96 -0
- package/src/renderer/utils/workflowCommandSuggestions.ts +49 -0
- package/src/shared/types/api.ts +79 -4
- package/src/shared/types/ccConnect.ts +1 -0
- package/src/shared/types/extensions/api.ts +19 -0
- package/src/shared/types/extensions/capabilityPack.ts +118 -0
- package/src/shared/types/extensions/index.ts +29 -1
- package/src/shared/types/index.ts +6 -0
- package/src/shared/types/loopAssets.ts +54 -0
- package/src/shared/types/providers.ts +0 -16
- package/src/shared/types/systemManager.ts +26 -1
- package/src/shared/types/team.ts +41 -5
- package/src/shared/types/terminal.ts +2 -36
- package/src/shared/types/worker.test.ts +28 -0
- package/src/shared/types/worker.ts +3 -0
- package/src/shared/utils/__tests__/effortLevels.test.ts +88 -0
- package/src/shared/utils/__tests__/providerBackend.test.ts +88 -0
- package/src/shared/utils/__tests__/providerLaunchArgs.test.ts +220 -0
- package/src/shared/utils/claudeStreamJson.test.ts +187 -0
- package/src/shared/utils/claudeStreamJson.ts +153 -0
- package/src/shared/utils/providerLaunchArgs.ts +217 -0
- package/src/shared/utils/slashCommands.ts +10 -0
- package/src/types/node-pty.d.ts +8 -0
- package/dist-renderer/assets/channel-Ch7JrfUu.js +0 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-z9I4AnFy.js +0 -1
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-z9I4AnFy.js +0 -1
- package/dist-renderer/assets/clone-Dfi1Jx6l.js +0 -1
- package/dist-renderer/assets/index-iyjkpSus.css +0 -32
- package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-DTUIBfce.js +0 -1
- package/src/main/services/system-manager/SystemManagerPtyService.ts +0 -233
- package/src/renderer/components/common/TerminalPane.tsx +0 -213
- package/src/renderer/components/team/dialogs/useTeamEditForm.ts +0 -292
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import type { ToolApprovalSettings } from '@shared/types/team';
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Safe bash command prefixes — commands that never need manual approval
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
const SAFE_PREFIXES: readonly string[] = [
|
|
8
|
+
// Version control
|
|
9
|
+
'git ',
|
|
10
|
+
'git\t',
|
|
11
|
+
// Package managers
|
|
12
|
+
'pnpm ',
|
|
13
|
+
'npm ',
|
|
14
|
+
'npx ',
|
|
15
|
+
'yarn ',
|
|
16
|
+
// File inspection (read-only)
|
|
17
|
+
'ls',
|
|
18
|
+
'cat ',
|
|
19
|
+
'head ',
|
|
20
|
+
'tail ',
|
|
21
|
+
'wc ',
|
|
22
|
+
'less ',
|
|
23
|
+
'more ',
|
|
24
|
+
// Output
|
|
25
|
+
'echo ',
|
|
26
|
+
'printf ',
|
|
27
|
+
// System info
|
|
28
|
+
'pwd',
|
|
29
|
+
'whoami',
|
|
30
|
+
'hostname',
|
|
31
|
+
'date',
|
|
32
|
+
'uname',
|
|
33
|
+
// Search & find (read-only)
|
|
34
|
+
'find ',
|
|
35
|
+
'grep ',
|
|
36
|
+
'rg ',
|
|
37
|
+
'fd ',
|
|
38
|
+
'ag ',
|
|
39
|
+
// Directory & file info
|
|
40
|
+
'tree ',
|
|
41
|
+
'which ',
|
|
42
|
+
'type ',
|
|
43
|
+
'file ',
|
|
44
|
+
// Text processing (read-only)
|
|
45
|
+
'diff ',
|
|
46
|
+
'sort ',
|
|
47
|
+
'uniq ',
|
|
48
|
+
'tr ',
|
|
49
|
+
'cut ',
|
|
50
|
+
// Path utilities
|
|
51
|
+
'basename ',
|
|
52
|
+
'dirname ',
|
|
53
|
+
'realpath ',
|
|
54
|
+
'readlink ',
|
|
55
|
+
// Environment
|
|
56
|
+
'env',
|
|
57
|
+
'printenv',
|
|
58
|
+
// Scripting one-liners (read-only)
|
|
59
|
+
'node -e',
|
|
60
|
+
'node --eval',
|
|
61
|
+
'python -c',
|
|
62
|
+
'python3 -c',
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Dangerous patterns — these OVERRIDE safe prefixes and always need approval
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
const DANGEROUS_PATTERNS: readonly RegExp[] = [
|
|
70
|
+
/\brm\s/, // rm (with space to avoid false positives like "rmdir" intent)
|
|
71
|
+
/\brm$/, // bare "rm" at end
|
|
72
|
+
/\bsudo\b/,
|
|
73
|
+
/\bchmod\b/,
|
|
74
|
+
/\bchown\b/,
|
|
75
|
+
/\bcurl\b.*\|\s*(ba)?sh/,
|
|
76
|
+
/\bwget\b.*\|\s*(ba)?sh/,
|
|
77
|
+
/\bmkfs\b/,
|
|
78
|
+
/\bdd\b/,
|
|
79
|
+
/\bkill\b/,
|
|
80
|
+
/\bkillall\b/,
|
|
81
|
+
/\bpkill\b/,
|
|
82
|
+
/>\s*\//, // redirect to absolute path root
|
|
83
|
+
/\beval\b/,
|
|
84
|
+
/\bexec\b/,
|
|
85
|
+
/\bformat\b/,
|
|
86
|
+
/\bshutdown\b/,
|
|
87
|
+
/\breboot\b/,
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// File edit tools that can be auto-allowed
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
const FILE_EDIT_TOOLS = new Set(['Edit', 'Write', 'NotebookEdit']);
|
|
95
|
+
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Public API
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
export interface AutoAllowResult {
|
|
101
|
+
autoAllow: boolean;
|
|
102
|
+
reason?: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Determines whether a tool call should be auto-allowed based on user settings.
|
|
107
|
+
*
|
|
108
|
+
* Logic:
|
|
109
|
+
* 1. File edit tools — auto-allow if `autoAllowFileEdits` is enabled
|
|
110
|
+
* 2. Bash commands — check dangerous patterns FIRST (always block),
|
|
111
|
+
* then check safe prefixes (auto-allow if `autoAllowSafeBash` is enabled)
|
|
112
|
+
* 3. Everything else — requires manual approval
|
|
113
|
+
*/
|
|
114
|
+
export function shouldAutoAllow(
|
|
115
|
+
settings: ToolApprovalSettings,
|
|
116
|
+
toolName: string,
|
|
117
|
+
toolInput: Record<string, unknown>
|
|
118
|
+
): AutoAllowResult {
|
|
119
|
+
// Auto-allow ALL tools (overrides everything)
|
|
120
|
+
if (settings.autoAllowAll) {
|
|
121
|
+
return { autoAllow: true, reason: 'auto_allow_all' };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// File edit auto-allow
|
|
125
|
+
if (settings.autoAllowFileEdits && FILE_EDIT_TOOLS.has(toolName)) {
|
|
126
|
+
return { autoAllow: true, reason: 'auto_allow_category' };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Safe bash auto-allow
|
|
130
|
+
if (settings.autoAllowSafeBash && toolName === 'Bash') {
|
|
131
|
+
const command = typeof toolInput.command === 'string' ? toolInput.command.trim() : '';
|
|
132
|
+
if (!command) return { autoAllow: false };
|
|
133
|
+
|
|
134
|
+
// Dangerous patterns override safe prefixes — check FIRST
|
|
135
|
+
for (const pattern of DANGEROUS_PATTERNS) {
|
|
136
|
+
if (pattern.test(command)) {
|
|
137
|
+
return { autoAllow: false };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Check safe prefixes
|
|
142
|
+
for (const prefix of SAFE_PREFIXES) {
|
|
143
|
+
const trimmedPrefix = prefix.trimEnd();
|
|
144
|
+
if (command === trimmedPrefix || command.startsWith(prefix)) {
|
|
145
|
+
return { autoAllow: true, reason: 'auto_allow_category' };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return { autoAllow: false };
|
|
151
|
+
}
|
package/src/renderer/App.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useMemo
|
|
1
|
+
import React, { useEffect, useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
import { TooltipProvider } from '@renderer/components/ui/tooltip';
|
|
4
4
|
|
|
@@ -18,14 +18,6 @@ import type { Tab } from './types/tabs';
|
|
|
18
18
|
const PERSIST_KEY = 'hermit:lastTeam';
|
|
19
19
|
const DEFAULT_APP_PATH = '/teams';
|
|
20
20
|
|
|
21
|
-
function safeDecodeURIComponent(value: string): string {
|
|
22
|
-
try {
|
|
23
|
-
return decodeURIComponent(value);
|
|
24
|
-
} catch {
|
|
25
|
-
return value;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
21
|
function getActiveTabFromLayout(activeTabId: string | null, paneLayout: PaneLayout): Tab | null {
|
|
30
22
|
if (!activeTabId) return null;
|
|
31
23
|
for (const pane of paneLayout.panes) {
|
|
@@ -57,6 +49,8 @@ function buildPathForTab(activeTab: Tab | null): string {
|
|
|
57
49
|
return '/tasks';
|
|
58
50
|
case 'dashboard':
|
|
59
51
|
return '/dashboard';
|
|
52
|
+
case 'society':
|
|
53
|
+
return '/society';
|
|
60
54
|
case 'session': {
|
|
61
55
|
if (!activeTab.projectId || !activeTab.sessionId) return DEFAULT_APP_PATH;
|
|
62
56
|
return `/session/${encodeURIComponent(activeTab.projectId)}/${encodeURIComponent(activeTab.sessionId)}`;
|
|
@@ -115,93 +109,20 @@ function useTabPathPersistence() {
|
|
|
115
109
|
activeTabId: s.activeTabId,
|
|
116
110
|
paneLayout: s.paneLayout,
|
|
117
111
|
}));
|
|
118
|
-
const [routeReady, setRouteReady] = useState(false);
|
|
119
|
-
const didInitialRouteRestoreRef = useRef(false);
|
|
120
|
-
|
|
121
|
-
useEffect(() => {
|
|
122
|
-
if (didInitialRouteRestoreRef.current) return;
|
|
123
|
-
didInitialRouteRestoreRef.current = true;
|
|
124
|
-
|
|
125
|
-
const pathname = window.location.pathname;
|
|
126
|
-
const segments = pathname
|
|
127
|
-
.split('/')
|
|
128
|
-
.map((segment) => segment.trim())
|
|
129
|
-
.filter((segment) => segment.length > 0)
|
|
130
|
-
.map(safeDecodeURIComponent);
|
|
131
|
-
const state = useStore.getState();
|
|
132
|
-
|
|
133
|
-
if (segments.length === 0) {
|
|
134
|
-
setRouteReady(true);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const [route, arg1, arg2] = segments;
|
|
139
|
-
switch (route) {
|
|
140
|
-
case 'team':
|
|
141
|
-
if (arg1) state.openTeamTab(arg1);
|
|
142
|
-
break;
|
|
143
|
-
case 'teams':
|
|
144
|
-
state.openTeamsTab();
|
|
145
|
-
break;
|
|
146
|
-
case 'system-manager':
|
|
147
|
-
void state.openSystemManager();
|
|
148
|
-
break;
|
|
149
|
-
case 'settings':
|
|
150
|
-
state.openSettingsTab();
|
|
151
|
-
break;
|
|
152
|
-
case 'extensions':
|
|
153
|
-
state.openExtensionsTab();
|
|
154
|
-
break;
|
|
155
|
-
case 'schedules':
|
|
156
|
-
state.openSchedulesTab();
|
|
157
|
-
break;
|
|
158
|
-
case 'tasks':
|
|
159
|
-
state.openTasksTab();
|
|
160
|
-
break;
|
|
161
|
-
case 'dashboard':
|
|
162
|
-
state.openDashboard();
|
|
163
|
-
break;
|
|
164
|
-
case 'session':
|
|
165
|
-
if (arg1 && arg2) {
|
|
166
|
-
state.navigateToSession(arg1, arg2);
|
|
167
|
-
}
|
|
168
|
-
break;
|
|
169
|
-
case 'notifications':
|
|
170
|
-
state.openTab({ type: 'notifications', label: '通知' });
|
|
171
|
-
break;
|
|
172
|
-
case 'graph':
|
|
173
|
-
if (arg1) {
|
|
174
|
-
state.openTab({ type: 'graph', label: arg1, teamName: arg1 });
|
|
175
|
-
}
|
|
176
|
-
break;
|
|
177
|
-
case 'report':
|
|
178
|
-
if (arg1 && arg2) {
|
|
179
|
-
state.openTab({
|
|
180
|
-
type: 'report',
|
|
181
|
-
label: 'Session Report',
|
|
182
|
-
projectId: arg1,
|
|
183
|
-
sessionId: arg2,
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
break;
|
|
187
|
-
default:
|
|
188
|
-
break;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
setRouteReady(true);
|
|
192
|
-
}, []);
|
|
193
112
|
|
|
194
113
|
const activeTab = useMemo(
|
|
195
114
|
() => getActiveTabFromLayout(activeTabId, paneLayout),
|
|
196
115
|
[activeTabId, paneLayout]
|
|
197
116
|
);
|
|
198
117
|
|
|
118
|
+
// The initial route is restored before first render (main.tsx →
|
|
119
|
+
// restoreInitialRoute), so this hook only keeps the URL in sync as the active
|
|
120
|
+
// tab changes. No post-mount restore, no routeReady gate.
|
|
199
121
|
useEffect(() => {
|
|
200
|
-
if (!routeReady) return;
|
|
201
122
|
const nextPath = buildPathForTab(activeTab);
|
|
202
123
|
if (window.location.pathname === nextPath) return;
|
|
203
124
|
window.history.replaceState(null, '', nextPath);
|
|
204
|
-
}, [activeTab
|
|
125
|
+
}, [activeTab]);
|
|
205
126
|
}
|
|
206
127
|
|
|
207
128
|
declare global {
|
|
@@ -215,6 +136,7 @@ declare global {
|
|
|
215
136
|
const SPLASH_MIN_DURATION_MS = 2800;
|
|
216
137
|
const SPLASH_ENHANCED_HOLD_MS = 800;
|
|
217
138
|
const SPLASH_FADE_MS = 480;
|
|
139
|
+
const SPLASH_ROUTE_RESTORE_FADE_MS = 120;
|
|
218
140
|
const SPLASH_REDUCED_MIN_DURATION_MS = 600;
|
|
219
141
|
const SPLASH_REDUCED_HOLD_MS = 200;
|
|
220
142
|
const SPLASH_REDUCED_FADE_MS = 180;
|
|
@@ -240,9 +162,22 @@ export const App = (): React.JSX.Element => {
|
|
|
240
162
|
const enhancedStartedAt = window.__claudeTeamsSplashEnhancedStartedAt ?? performance.now();
|
|
241
163
|
const elapsed = performance.now() - startedAt;
|
|
242
164
|
const enhancedElapsed = performance.now() - enhancedStartedAt;
|
|
243
|
-
const
|
|
244
|
-
const
|
|
245
|
-
|
|
165
|
+
const routeRestored = window.location.pathname !== '/' && window.location.pathname !== '';
|
|
166
|
+
const minDuration = routeRestored
|
|
167
|
+
? 0
|
|
168
|
+
: reducedMotion
|
|
169
|
+
? SPLASH_REDUCED_MIN_DURATION_MS
|
|
170
|
+
: SPLASH_MIN_DURATION_MS;
|
|
171
|
+
const enhancedHold = routeRestored
|
|
172
|
+
? 0
|
|
173
|
+
: reducedMotion
|
|
174
|
+
? SPLASH_REDUCED_HOLD_MS
|
|
175
|
+
: SPLASH_ENHANCED_HOLD_MS;
|
|
176
|
+
const fadeDuration = routeRestored
|
|
177
|
+
? SPLASH_ROUTE_RESTORE_FADE_MS
|
|
178
|
+
: reducedMotion
|
|
179
|
+
? SPLASH_REDUCED_FADE_MS
|
|
180
|
+
: SPLASH_FADE_MS;
|
|
246
181
|
const avatarReadyMaxWait = reducedMotion
|
|
247
182
|
? SPLASH_REDUCED_AVATAR_READY_MAX_WAIT_MS
|
|
248
183
|
: SPLASH_AVATAR_READY_MAX_WAIT_MS;
|
|
@@ -21,6 +21,8 @@ import type {
|
|
|
21
21
|
BoardTaskLogStreamSummary,
|
|
22
22
|
CcSession,
|
|
23
23
|
CcSessionDetail,
|
|
24
|
+
LoopSessionRequest,
|
|
25
|
+
LoopSessionResponse,
|
|
24
26
|
ClaudeMdFileInfo,
|
|
25
27
|
ClaudeRootFolderSelection,
|
|
26
28
|
ClaudeRootInfo,
|
|
@@ -34,12 +36,14 @@ import type {
|
|
|
34
36
|
CrossTeamAPI,
|
|
35
37
|
CrossTeamMessage,
|
|
36
38
|
CrossTeamSendResult,
|
|
39
|
+
DiscoverableWorker,
|
|
37
40
|
ElectronAPI,
|
|
38
41
|
FileChangeEvent,
|
|
39
42
|
GlobalTask,
|
|
40
43
|
HttpServerAPI,
|
|
41
44
|
HttpServerStatus,
|
|
42
45
|
KanbanColumnId,
|
|
46
|
+
LoopAssetsSnapshot,
|
|
43
47
|
MachineProfile,
|
|
44
48
|
MachineRuntimeProcess,
|
|
45
49
|
MemberFullStats,
|
|
@@ -108,6 +112,12 @@ import type { AgentConfig } from '@shared/types/api';
|
|
|
108
112
|
import type { CliProviderStatus } from '@shared/types/cliInstaller';
|
|
109
113
|
import type { EditorAPI, ProjectAPI, WorkspaceListResponse } from '@shared/types/editor';
|
|
110
114
|
import type {
|
|
115
|
+
CapabilityCommandPromptRequest,
|
|
116
|
+
CapabilityCommandPromptResult,
|
|
117
|
+
CapabilityPackExportRequest,
|
|
118
|
+
CapabilityPackImportRequest,
|
|
119
|
+
CapabilityPackListResult,
|
|
120
|
+
CapabilityPackMutationResult,
|
|
111
121
|
EnrichedPlugin,
|
|
112
122
|
InstalledMcpEntry,
|
|
113
123
|
McpCatalogItem,
|
|
@@ -535,11 +545,11 @@ export class HttpAPIClient implements ElectronAPI {
|
|
|
535
545
|
work_dir?: string;
|
|
536
546
|
agent_type?: string;
|
|
537
547
|
}
|
|
538
|
-
): Promise<{ message: string; restart_required: boolean }> => {
|
|
539
|
-
const res = await this.
|
|
548
|
+
): Promise<{ message: string; restart_required: boolean; restart_handled?: boolean }> => {
|
|
549
|
+
const res = await this.postLong<{
|
|
540
550
|
ok: boolean;
|
|
541
|
-
data: { message: string; restart_required: boolean };
|
|
542
|
-
}>(`/api/projects/${encodeURIComponent(projectName)}/add-platform`, body);
|
|
551
|
+
data: { message: string; restart_required: boolean; restart_handled?: boolean };
|
|
552
|
+
}>(`/api/projects/${encodeURIComponent(projectName)}/add-platform`, body, 120_000);
|
|
543
553
|
return res.data;
|
|
544
554
|
},
|
|
545
555
|
};
|
|
@@ -1098,6 +1108,20 @@ export class HttpAPIClient implements ElectronAPI {
|
|
|
1098
1108
|
this.post<SystemManagerSummary>('/api/system-manager/ensure'),
|
|
1099
1109
|
getData: async (teamName: string): Promise<TeamViewSnapshot> =>
|
|
1100
1110
|
this.get<TeamViewSnapshot>(`/api/teams/${encodeURIComponent(teamName)}/data`, 30_000),
|
|
1111
|
+
getLoopAssets: async (teamName: string): Promise<LoopAssetsSnapshot> =>
|
|
1112
|
+
this.get<LoopAssetsSnapshot>(
|
|
1113
|
+
`/api/teams/${encodeURIComponent(teamName)}/loop-assets`,
|
|
1114
|
+
30_000
|
|
1115
|
+
),
|
|
1116
|
+
createLoopSession: async (
|
|
1117
|
+
teamName: string,
|
|
1118
|
+
request: LoopSessionRequest
|
|
1119
|
+
): Promise<LoopSessionResponse> =>
|
|
1120
|
+
this.postLong<LoopSessionResponse>(
|
|
1121
|
+
`/api/teams/${encodeURIComponent(teamName)}/loop-session`,
|
|
1122
|
+
request,
|
|
1123
|
+
30_000
|
|
1124
|
+
),
|
|
1101
1125
|
getTaskChangePresence: async (): Promise<
|
|
1102
1126
|
Record<string, 'has_changes' | 'no_changes' | 'unknown'>
|
|
1103
1127
|
> => {
|
|
@@ -1395,7 +1419,15 @@ export class HttpAPIClient implements ElectronAPI {
|
|
|
1395
1419
|
teamName: string,
|
|
1396
1420
|
config: TeamUpdateConfigRequest
|
|
1397
1421
|
): Promise<TeamConfig> => {
|
|
1398
|
-
|
|
1422
|
+
const result = await this.put<TeamConfig>(
|
|
1423
|
+
`/api/teams/${encodeURIComponent(teamName)}/config`,
|
|
1424
|
+
config,
|
|
1425
|
+
120_000
|
|
1426
|
+
);
|
|
1427
|
+
if (result.ccSyncError) {
|
|
1428
|
+
throw new Error(`配置已保存到本地,但同步到运行时失败:${result.ccSyncError}`);
|
|
1429
|
+
}
|
|
1430
|
+
return result;
|
|
1399
1431
|
},
|
|
1400
1432
|
addTaskComment: async (
|
|
1401
1433
|
teamName: string,
|
|
@@ -1656,6 +1688,28 @@ export class HttpAPIClient implements ElectronAPI {
|
|
|
1656
1688
|
this.get<CrossTeamMessage[]>(`/api/cross-team/outbox/${encodeURIComponent(teamName)}`),
|
|
1657
1689
|
};
|
|
1658
1690
|
|
|
1691
|
+
workers = {
|
|
1692
|
+
list: () => this.get<{ workers: DiscoverableWorker[] }>('/api/workers'),
|
|
1693
|
+
invoke: (
|
|
1694
|
+
workerId: string,
|
|
1695
|
+
request: {
|
|
1696
|
+
fromTeam?: string;
|
|
1697
|
+
text: string;
|
|
1698
|
+
summary?: string;
|
|
1699
|
+
sessionName?: string;
|
|
1700
|
+
reuse?: boolean;
|
|
1701
|
+
sessionKey?: string;
|
|
1702
|
+
}
|
|
1703
|
+
) =>
|
|
1704
|
+
this.postLong<{
|
|
1705
|
+
ok: boolean;
|
|
1706
|
+
worker: DiscoverableWorker;
|
|
1707
|
+
session: CcSession;
|
|
1708
|
+
reused: boolean;
|
|
1709
|
+
messageSent: boolean;
|
|
1710
|
+
}>(`/api/workers/${encodeURIComponent(workerId)}/invoke`, request, 30_000),
|
|
1711
|
+
};
|
|
1712
|
+
|
|
1659
1713
|
// Collaboration board API
|
|
1660
1714
|
collab = {
|
|
1661
1715
|
getBoard: () => this.get<{ tasks: CollabTask[] }>('/api/collab/board'),
|
|
@@ -2017,14 +2071,19 @@ export class HttpAPIClient implements ElectronAPI {
|
|
|
2017
2071
|
if (forceRefresh) params.set('forceRefresh', 'true');
|
|
2018
2072
|
const qs = params.toString();
|
|
2019
2073
|
const result = await this.get<{ success: boolean; data?: EnrichedPlugin[]; error?: string }>(
|
|
2020
|
-
`/api/extensions/plugins${qs ? `?${qs}` : ''}
|
|
2074
|
+
`/api/extensions/plugins${qs ? `?${qs}` : ''}`,
|
|
2075
|
+
// Catalog assembly scans local installs + remote registries (GitHub),
|
|
2076
|
+
// which routinely exceeds the default 10s — match the team-endpoint
|
|
2077
|
+
// 30s budget so the Extensions store doesn't time out on first open.
|
|
2078
|
+
30_000
|
|
2021
2079
|
);
|
|
2022
2080
|
if (!result.success) throw new Error(result.error ?? 'Failed to get plugins');
|
|
2023
2081
|
return result.data ?? [];
|
|
2024
2082
|
},
|
|
2025
2083
|
getReadme: async (pluginId: string) => {
|
|
2026
2084
|
const result = await this.get<{ success: boolean; data?: string | null; error?: string }>(
|
|
2027
|
-
`/api/extensions/plugins/${encodeURIComponent(pluginId)}/readme
|
|
2085
|
+
`/api/extensions/plugins/${encodeURIComponent(pluginId)}/readme`,
|
|
2086
|
+
30_000
|
|
2028
2087
|
);
|
|
2029
2088
|
if (!result.success) throw new Error(result.error ?? 'Failed to get readme');
|
|
2030
2089
|
return result.data ?? null;
|
|
@@ -2180,6 +2239,47 @@ export class HttpAPIClient implements ElectronAPI {
|
|
|
2180
2239
|
},
|
|
2181
2240
|
};
|
|
2182
2241
|
|
|
2242
|
+
capabilityPacks = {
|
|
2243
|
+
list: async () => {
|
|
2244
|
+
const result = await this.get<{
|
|
2245
|
+
success: boolean;
|
|
2246
|
+
data?: CapabilityPackListResult;
|
|
2247
|
+
error?: string;
|
|
2248
|
+
}>('/api/extensions/capability-packs');
|
|
2249
|
+
if (!result.success)
|
|
2250
|
+
return { packs: [], warnings: result.error ? [result.error] : [], rootDir: '' };
|
|
2251
|
+
return result.data ?? { packs: [], warnings: [], rootDir: '' };
|
|
2252
|
+
},
|
|
2253
|
+
importPack: async (request: CapabilityPackImportRequest) => {
|
|
2254
|
+
const result = await this.post<{
|
|
2255
|
+
success: boolean;
|
|
2256
|
+
data?: CapabilityPackMutationResult;
|
|
2257
|
+
error?: string;
|
|
2258
|
+
}>('/api/extensions/capability-packs/import', request);
|
|
2259
|
+
if (!result.success) throw new Error(result.error ?? 'Import capability pack failed');
|
|
2260
|
+
return result.data ?? { pack: null, warnings: [] };
|
|
2261
|
+
},
|
|
2262
|
+
exportPack: async (request: CapabilityPackExportRequest) => {
|
|
2263
|
+
const result = await this.post<{
|
|
2264
|
+
success: boolean;
|
|
2265
|
+
data?: CapabilityPackMutationResult;
|
|
2266
|
+
error?: string;
|
|
2267
|
+
}>('/api/extensions/capability-packs/export', request);
|
|
2268
|
+
if (!result.success) throw new Error(result.error ?? 'Export capability pack failed');
|
|
2269
|
+
return result.data ?? { pack: null, warnings: [] };
|
|
2270
|
+
},
|
|
2271
|
+
getCommandPrompt: async (request: CapabilityCommandPromptRequest) => {
|
|
2272
|
+
const result = await this.post<{
|
|
2273
|
+
success: boolean;
|
|
2274
|
+
data?: CapabilityCommandPromptResult;
|
|
2275
|
+
error?: string;
|
|
2276
|
+
}>('/api/extensions/capability-packs/command-prompt', request);
|
|
2277
|
+
if (!result.success) throw new Error(result.error ?? 'Load capability command failed');
|
|
2278
|
+
if (!result.data) throw new Error('Load capability command failed');
|
|
2279
|
+
return result.data;
|
|
2280
|
+
},
|
|
2281
|
+
};
|
|
2282
|
+
|
|
2183
2283
|
skills = {
|
|
2184
2284
|
list: async (projectPath?: string) => {
|
|
2185
2285
|
const params = new URLSearchParams();
|
|
@@ -2307,44 +2407,22 @@ export class HttpAPIClient implements ElectronAPI {
|
|
|
2307
2407
|
getConfig: () => this.get('/api/system-manager/config'),
|
|
2308
2408
|
updateConfig: (patch) => this.put('/api/system-manager/config', patch),
|
|
2309
2409
|
listWorkflowPrompts: (folder) => this.post('/api/system-manager/workflows/list', { folder }),
|
|
2310
|
-
readWorkflowPrompt: (
|
|
2410
|
+
readWorkflowPrompt: (folder, id) =>
|
|
2411
|
+
this.post('/api/system-manager/workflows/read', { folder, id }),
|
|
2311
2412
|
};
|
|
2312
2413
|
|
|
2313
2414
|
// ---------------------------------------------------------------------------
|
|
2314
|
-
// Terminal (
|
|
2415
|
+
// Terminal (system/default terminal)
|
|
2315
2416
|
// ---------------------------------------------------------------------------
|
|
2316
2417
|
|
|
2317
2418
|
terminal: TerminalAPI = {
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
void this.post(`/api/terminal/${encodeURIComponent(ptyId)}/write`, { data });
|
|
2324
|
-
},
|
|
2325
|
-
resize: (ptyId: string, cols: number, rows: number): void => {
|
|
2326
|
-
void this.post(`/api/terminal/${encodeURIComponent(ptyId)}/resize`, { cols, rows });
|
|
2327
|
-
},
|
|
2328
|
-
kill: async (ptyId: string): Promise<void> => {
|
|
2329
|
-
await this.del(`/api/terminal/${encodeURIComponent(ptyId)}`);
|
|
2330
|
-
},
|
|
2331
|
-
openExternal: async (options: { command: string; args?: string[]; cwd?: string }): Promise<void> => {
|
|
2419
|
+
openExternal: async (options: {
|
|
2420
|
+
command: string;
|
|
2421
|
+
args?: string[];
|
|
2422
|
+
cwd?: string;
|
|
2423
|
+
}): Promise<void> => {
|
|
2332
2424
|
await this.post('/api/terminal/open-external', options);
|
|
2333
2425
|
},
|
|
2334
|
-
onData: (callback): (() => void) =>
|
|
2335
|
-
this.addEventListener('terminal:data', (data: unknown) => {
|
|
2336
|
-
const event = data as { ptyId?: string; data?: string };
|
|
2337
|
-
if (event.ptyId && typeof event.data === 'string') {
|
|
2338
|
-
callback(null, event.ptyId, event.data);
|
|
2339
|
-
}
|
|
2340
|
-
}),
|
|
2341
|
-
onExit: (callback): (() => void) =>
|
|
2342
|
-
this.addEventListener('terminal:exit', (data: unknown) => {
|
|
2343
|
-
const event = data as { ptyId?: string; exitCode?: number };
|
|
2344
|
-
if (event.ptyId && typeof event.exitCode === 'number') {
|
|
2345
|
-
callback(null, event.ptyId, event.exitCode);
|
|
2346
|
-
}
|
|
2347
|
-
}),
|
|
2348
2426
|
};
|
|
2349
2427
|
|
|
2350
2428
|
// ---------------------------------------------------------------------------
|
|
@@ -5,11 +5,7 @@
|
|
|
5
5
|
* cc-connect sidecar is the source of truth for provider/channel management.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
9
|
-
CCSwitchListResponse,
|
|
10
|
-
GlobalProvider,
|
|
11
|
-
ProviderPresetsResponse,
|
|
12
|
-
} from '@shared/types/providers';
|
|
8
|
+
import type { GlobalProvider, ProviderPresetsResponse } from '@shared/types/providers';
|
|
13
9
|
|
|
14
10
|
function stringifyProviderPatch(patch: Partial<GlobalProvider>): string {
|
|
15
11
|
return JSON.stringify(patch, (_key, value: unknown) => (value === undefined ? null : value));
|
|
@@ -45,7 +41,7 @@ async function request<T>(path: string, init?: RequestInit & { timeoutMs?: numbe
|
|
|
45
41
|
if (!contentType.includes('json') || !text.trim().startsWith('{')) {
|
|
46
42
|
throw new Error(
|
|
47
43
|
`Provider API ${path} 返回了非 JSON 响应 (HTTP ${res.status})。` +
|
|
48
|
-
|
|
44
|
+
'请检查 cc-connect 是否正在运行且支持该端点。'
|
|
49
45
|
);
|
|
50
46
|
}
|
|
51
47
|
|
|
@@ -53,7 +49,9 @@ async function request<T>(path: string, init?: RequestInit & { timeoutMs?: numbe
|
|
|
53
49
|
try {
|
|
54
50
|
json = JSON.parse(text) as typeof json;
|
|
55
51
|
} catch (e) {
|
|
56
|
-
throw new Error(
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Provider API ${path} 返回了无效 JSON: ${e instanceof Error ? e.message : String(e)}`
|
|
54
|
+
);
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
if (!res.ok || json.ok === false) {
|
|
@@ -86,13 +84,4 @@ export const providersApi = {
|
|
|
86
84
|
timeoutMs: 20_000,
|
|
87
85
|
});
|
|
88
86
|
},
|
|
89
|
-
listCCSwitch(): Promise<CCSwitchListResponse> {
|
|
90
|
-
return request('/providers/cc-switch');
|
|
91
|
-
},
|
|
92
|
-
importCCSwitch(names: string[]): Promise<{ imported: string[]; skipped: string[] }> {
|
|
93
|
-
return request('/providers/cc-switch', {
|
|
94
|
-
method: 'POST',
|
|
95
|
-
body: JSON.stringify({ names }),
|
|
96
|
-
});
|
|
97
|
-
},
|
|
98
87
|
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { MessageCircle, QrCode, Sparkles, Users } from 'lucide-react';
|
|
4
|
+
|
|
5
|
+
const COMMUNITY_QR_IMAGE = '/chat-community-qr.jpg';
|
|
6
|
+
|
|
7
|
+
export const CommunityChatView = (): React.JSX.Element => {
|
|
8
|
+
return (
|
|
9
|
+
<div className="relative flex-1 overflow-auto bg-surface">
|
|
10
|
+
<div
|
|
11
|
+
className="pointer-events-none absolute inset-x-0 top-0 h-[520px] bg-[radial-gradient(ellipse_80%_50%_at_50%_-20%,rgba(132,204,22,0.14),transparent)]"
|
|
12
|
+
aria-hidden="true"
|
|
13
|
+
/>
|
|
14
|
+
|
|
15
|
+
<div className="relative mx-auto flex min-h-full max-w-5xl flex-col px-8 py-12">
|
|
16
|
+
<section className="overflow-hidden rounded-2xl border border-border bg-surface-raised shadow-sm">
|
|
17
|
+
<div className="border-b border-border bg-gradient-to-br from-lime-500/15 via-emerald-500/10 to-transparent px-8 py-8">
|
|
18
|
+
<div className="mb-3 inline-flex items-center gap-2 rounded-full border border-lime-500/25 bg-lime-500/10 px-3 py-1 text-[11px] font-medium text-lime-300">
|
|
19
|
+
<MessageCircle className="size-3.5" />
|
|
20
|
+
Chat / 交流圈
|
|
21
|
+
</div>
|
|
22
|
+
<h1 className="text-3xl font-semibold tracking-tight text-text">加入 Yancy 的朋友们</h1>
|
|
23
|
+
<p className="mt-3 max-w-2xl text-sm leading-6 text-text-secondary">
|
|
24
|
+
扫码加入「野生想法」交流圈,聊 Loop Engineering、Agent
|
|
25
|
+
Teams、自动化工作台和一人公司的实践。
|
|
26
|
+
</p>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div className="grid gap-8 px-8 py-8 lg:grid-cols-[minmax(0,1fr)_360px]">
|
|
30
|
+
<div className="space-y-4">
|
|
31
|
+
<div className="rounded-xl border border-border bg-surface px-5 py-4">
|
|
32
|
+
<div className="mb-2 flex items-center gap-2 text-sm font-medium text-text">
|
|
33
|
+
<Users className="size-4 text-lime-400" />
|
|
34
|
+
适合谁加入
|
|
35
|
+
</div>
|
|
36
|
+
<p className="text-sm leading-6 text-text-muted">
|
|
37
|
+
如果你正在用 Claude Code / Hermit / 多 Agent 团队做真实项目,或者想交流 AI
|
|
38
|
+
自动化、产品工程和独立创造,这里会持续分享实验和想法。
|
|
39
|
+
</p>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<div className="rounded-xl border border-border bg-surface px-5 py-4">
|
|
43
|
+
<div className="mb-2 flex items-center gap-2 text-sm font-medium text-text">
|
|
44
|
+
<Sparkles className="size-4 text-emerald-400" />
|
|
45
|
+
你可以期待
|
|
46
|
+
</div>
|
|
47
|
+
<ul className="space-y-2 text-sm leading-6 text-text-muted">
|
|
48
|
+
<li>• Hermit / OpenHermit 的功能讨论和使用反馈</li>
|
|
49
|
+
<li>• Agent 团队、Loop、Workflow 的实践案例</li>
|
|
50
|
+
<li>• 一人公司、自动化研发和产品想法交流</li>
|
|
51
|
+
</ul>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div className="rounded-xl border border-lime-500/20 bg-lime-500/5 px-5 py-4 text-sm leading-6 text-lime-100/90">
|
|
55
|
+
备注:该二维码来自飞书 / Lark 圈子,仅限企业内部成员加入;如果扫码不可用,请联系
|
|
56
|
+
Yancy 获取新的邀请方式。
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div className="rounded-2xl border border-border bg-surface px-5 py-5 text-center">
|
|
61
|
+
<div className="mb-3 inline-flex items-center gap-2 text-sm font-medium text-text">
|
|
62
|
+
<QrCode className="size-4 text-lime-400" />
|
|
63
|
+
扫码加入
|
|
64
|
+
</div>
|
|
65
|
+
<div className="rounded-2xl border border-border bg-white p-3 shadow-sm">
|
|
66
|
+
<img
|
|
67
|
+
src={COMMUNITY_QR_IMAGE}
|
|
68
|
+
alt="Yancy 的朋友们交流圈二维码"
|
|
69
|
+
className="mx-auto aspect-square w-full rounded-xl object-cover"
|
|
70
|
+
/>
|
|
71
|
+
</div>
|
|
72
|
+
<p className="mt-4 text-xs leading-5 text-text-muted">
|
|
73
|
+
打开飞书 / Lark 扫一扫,加入「Yancy 的朋友们 · 野生想法」。
|
|
74
|
+
</p>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</section>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
};
|