@yancyyu/openhermit 1.5.8 → 1.5.10
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 +10 -1
- package/bin/alias-loader.mjs +51 -0
- package/bin/hermit.mjs +14 -5
- package/dist-renderer/assets/{ProjectEditorOverlay-BNoDw9T1.js → ProjectEditorOverlay-C5D83Zxv.js} +1 -1
- package/dist-renderer/assets/{TeamGraphOverlay-CfGRKQIu.js → TeamGraphOverlay-ajzuM1-u.js} +1 -1
- package/dist-renderer/assets/{_basePickBy-Ct8Hm5_h.js → _basePickBy-C9H2zmVj.js} +1 -1
- package/dist-renderer/assets/{_baseUniq-BofrAFBx.js → _baseUniq-CpGZGemc.js} +1 -1
- package/dist-renderer/assets/{arc-AbJgatzR.js → arc-CbGBDw-m.js} +1 -1
- package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-gpniCJVk.js → architectureDiagram-VXUJARFQ-nuKXUIpb.js} +1 -1
- package/dist-renderer/assets/{blockDiagram-VD42YOAC-aBbbmONC.js → blockDiagram-VD42YOAC-DHUUE7Jc.js} +1 -1
- package/dist-renderer/assets/{c4Diagram-YG6GDRKO-DJio1IsU.js → c4Diagram-YG6GDRKO-OILHhqLM.js} +1 -1
- package/dist-renderer/assets/channel-DpUKLLrj.js +1 -0
- package/dist-renderer/assets/{chunk-4BX2VUAB-D1_HKao2.js → chunk-4BX2VUAB-dqNpZaQ8.js} +1 -1
- package/dist-renderer/assets/{chunk-55IACEB6-NAmVxF4k.js → chunk-55IACEB6-BCoSJQM-.js} +1 -1
- package/dist-renderer/assets/{chunk-B4BG7PRW-Ce829laz.js → chunk-B4BG7PRW-BLbg8yVR.js} +1 -1
- package/dist-renderer/assets/{chunk-DI55MBZ5-Ct2Le12y.js → chunk-DI55MBZ5-CUUWOs1Q.js} +1 -1
- package/dist-renderer/assets/{chunk-FMBD7UC4-Cie3DzKk.js → chunk-FMBD7UC4-D9geTN5P.js} +1 -1
- package/dist-renderer/assets/{chunk-QN33PNHL-4f5Yb50e.js → chunk-QN33PNHL-BGT8-BRX.js} +1 -1
- package/dist-renderer/assets/{chunk-QZHKN3VN-D9ranl9c.js → chunk-QZHKN3VN-CC8ebGaM.js} +1 -1
- package/dist-renderer/assets/{chunk-TZMSLE5B-bdGZWlEy.js → chunk-TZMSLE5B-CajekcT6.js} +1 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-LL85aSlz.js +1 -0
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-LL85aSlz.js +1 -0
- package/dist-renderer/assets/clone-BHWsFzFA.js +1 -0
- package/dist-renderer/assets/{cose-bilkent-S5V4N54A-C6tvfcVi.js → cose-bilkent-S5V4N54A-C_x7hSy3.js} +1 -1
- package/dist-renderer/assets/{dagre-6UL2VRFP-B-4qcZam.js → dagre-6UL2VRFP-C4Y1k4DZ.js} +1 -1
- package/dist-renderer/assets/{diagram-PSM6KHXK-CwT3TLjx.js → diagram-PSM6KHXK-oRIeULoh.js} +1 -1
- package/dist-renderer/assets/{diagram-QEK2KX5R-BWH6-ZFd.js → diagram-QEK2KX5R-DwSqw5HF.js} +1 -1
- package/dist-renderer/assets/{diagram-S2PKOQOG-DfpPnfi1.js → diagram-S2PKOQOG-DqjGYje2.js} +1 -1
- package/dist-renderer/assets/{erDiagram-Q2GNP2WA-BFbEFR4x.js → erDiagram-Q2GNP2WA-CEV5bBgg.js} +1 -1
- package/dist-renderer/assets/{flowDiagram-NV44I4VS-Dg3cf5hW.js → flowDiagram-NV44I4VS-BQQkrRyu.js} +1 -1
- package/dist-renderer/assets/{ganttDiagram-JELNMOA3-B21y55W5.js → ganttDiagram-JELNMOA3-CLy4WR1G.js} +1 -1
- package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-BDV3BJzn.js → gitGraphDiagram-V2S2FVAM-6W3ioQu_.js} +1 -1
- package/dist-renderer/assets/{graph-BfaZ4hZt.js → graph-BnLKQvhH.js} +1 -1
- package/dist-renderer/assets/{index-CCqtDawH.js → index-B4aiRxoU.js} +1 -1
- package/dist-renderer/assets/{index-pMg_LlsS.js → index-B8lKqPVq.js} +1 -1
- package/dist-renderer/assets/{index-CZltVMDP.js → index-BRuhNKyU.js} +12 -12
- package/dist-renderer/assets/{index-BMXHMpkG.js → index-BufvLVIl.js} +1 -1
- package/dist-renderer/assets/{index-Ct0-y9TF.js → index-C1xShqKH.js} +1 -1
- package/dist-renderer/assets/{index-CVMSpK8C.js → index-zIOLLI7O.js} +1 -1
- package/dist-renderer/assets/{infoDiagram-HS3SLOUP-DvMlS0CL.js → infoDiagram-HS3SLOUP-BoBweEEY.js} +1 -1
- package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-DIyMluRv.js → journeyDiagram-XKPGCS4Q-DLL0V5oP.js} +1 -1
- package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-CVOx8f-7.js → kanban-definition-3W4ZIXB7-HsFtEDG3.js} +1 -1
- package/dist-renderer/assets/{layout-BPKIXUf4.js → layout-ClIooAAq.js} +1 -1
- package/dist-renderer/assets/{linear-CScZGLr2.js → linear-r3RJcj8y.js} +1 -1
- package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-CmDQ7Wo6.js → mindmap-definition-VGOIOE7T-BA_P1U4V.js} +1 -1
- package/dist-renderer/assets/{pieDiagram-ADFJNKIX-DbVClin-.js → pieDiagram-ADFJNKIX-CzPAfkTB.js} +1 -1
- package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-CAB0MYcW.js → quadrantDiagram-AYHSOK5B-PvdPWzFJ.js} +1 -1
- package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-w2Lfpg3T.js → requirementDiagram-UZGBJVZJ-CHqIL_Od.js} +1 -1
- package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-kvG1QoKY.js → sankeyDiagram-TZEHDZUN-ConzpACM.js} +1 -1
- package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-DCVBQ23J.js → sequenceDiagram-WL72ISMW-Zryq4oxP.js} +1 -1
- package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-ItZ0JBvq.js → stateDiagram-FKZM4ZOC-BA9V7NHF.js} +1 -1
- package/dist-renderer/assets/{stateDiagram-v2-4FDKWEC3-Hpmw4dMm.js → stateDiagram-v2-4FDKWEC3-CGnaujD-.js} +1 -1
- package/dist-renderer/assets/{timeline-definition-IT6M3QCI-BzSFaAjV.js → timeline-definition-IT6M3QCI-DPs2ZjMm.js} +1 -1
- package/dist-renderer/assets/{treemap-GDKQZRPO-fSz4hQn0.js → treemap-GDKQZRPO-B0lzrLxb.js} +1 -1
- package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-CT1kaGlv.js → xychartDiagram-PRI3JC2R-CINGmMxX.js} +1 -1
- package/dist-renderer/index.html +1 -1
- package/package.json +2 -1
- package/src/main/server.ts +993 -764
- package/src/main/services/UpdateService.ts +4 -1
- package/src/main/services/ccConnect/CcConnectBridge.ts +1 -8
- package/src/main/services/ccConnect/CcConnectClient.ts +7 -2
- package/src/main/services/teams-mvp/TeamProvisioningService.ts +14 -4
- package/src/main/services/teams-mvp/TeamWorkspaceService.ts +11 -6
- package/src/renderer/App.tsx +18 -7
- package/src/renderer/api/httpClient.ts +136 -42
- package/src/renderer/components/chat/ChatHistory.tsx +11 -8
- package/src/renderer/components/dashboard/DashboardView.tsx +4 -2
- package/src/renderer/components/extensions/ExtensionStoreView.tsx +2 -7
- package/src/renderer/components/layout/Sidebar.tsx +3 -1
- package/src/renderer/components/schedules/SchedulesView.tsx +15 -13
- package/src/renderer/components/settings/SettingsTabs.tsx +2 -1
- package/src/renderer/components/settings/hooks/useSettingsHandlers.ts +4 -5
- package/src/renderer/components/settings/sections/AdvancedSection.tsx +19 -4
- package/src/renderer/components/settings/sections/CliStatusSection.tsx +63 -59
- package/src/renderer/components/settings/sections/GeneralSection.tsx +5 -11
- package/src/renderer/components/settings/sections/HarnessSection.tsx +30 -15
- package/src/renderer/components/settings/sections/PlatformsSection.tsx +110 -51
- package/src/renderer/components/sidebar/SidebarSessions.tsx +100 -67
- package/src/renderer/components/sidebar/WorkspaceBrowser.tsx +26 -43
- package/src/renderer/components/team/CcSessionsSection.tsx +34 -14
- package/src/renderer/components/team/TeamDetailView.tsx +150 -148
- package/src/renderer/components/team/TeamEmptyState.tsx +27 -16
- package/src/renderer/components/team/TeamListView.tsx +4 -2
- package/src/renderer/components/team/activity/ActivityItem.tsx +6 -1
- package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +282 -75
- package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +2 -1
- package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +64 -21
- package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +68 -19
- package/src/renderer/components/team/dialogs/ProjectPathSelector.tsx +20 -16
- package/src/renderer/components/team/dialogs/platformMeta.ts +66 -11
- package/src/renderer/components/team/editor/EditorFileTree.tsx +9 -7
- package/src/renderer/components/team/kanban/KanbanBoard.tsx +7 -10
- package/src/renderer/components/team/kanban/KanbanTaskCard.tsx +1 -3
- package/src/renderer/components/team/members/MemberDetailDialog.tsx +1 -5
- package/src/renderer/components/team/messages/MessageComposer.tsx +3 -1
- package/src/renderer/components/team/messages/MessagesPanel.tsx +34 -26
- package/src/renderer/components/team/schedule/CcCronScheduleDialog.tsx +1 -3
- package/src/renderer/components/team/schedule/ScheduleSection.tsx +9 -10
- package/src/renderer/store/slices/scheduleSlice.ts +4 -1
- package/src/renderer/store/slices/teamSlice.ts +3 -1
- package/src/shared/types/api.ts +70 -21
- package/src/shared/utils/leadDetection.ts +5 -1
- package/tsconfig.json +26 -0
- package/dist-renderer/assets/channel-CZ8sd5Xf.js +0 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-CMcfSKj5.js +0 -1
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-CMcfSKj5.js +0 -1
- package/dist-renderer/assets/clone-CMuwA8RV.js +0 -1
|
@@ -420,63 +420,63 @@ export const CliStatusSection = ({
|
|
|
420
420
|
</p>
|
|
421
421
|
)}
|
|
422
422
|
<div className="ml-6 mt-3 space-y-2">
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
style={{ color: 'var(--color-text-muted)' }}
|
|
441
|
-
/>
|
|
442
|
-
<span
|
|
443
|
-
className="font-medium"
|
|
444
|
-
style={{ color: 'var(--color-text-secondary)' }}
|
|
445
|
-
>
|
|
446
|
-
{AGENT_TYPE_LABELS[agentType]}
|
|
447
|
-
</span>
|
|
448
|
-
<span style={{ color: 'var(--color-text-muted)' }}>
|
|
449
|
-
{harnessProviders.length > 0
|
|
450
|
-
? `${harnessProviders.length} 个 Provider`
|
|
451
|
-
: '未配置 Provider'}
|
|
452
|
-
</span>
|
|
453
|
-
</div>
|
|
454
|
-
<div
|
|
455
|
-
className="mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[11px]"
|
|
423
|
+
{ALL_AGENT_TYPES.map((agentType) => {
|
|
424
|
+
const provider = cliProviderStatusByAgentType.get(agentType) ?? null;
|
|
425
|
+
const harnessProviders = globalProvidersByAgentType.get(agentType) ?? [];
|
|
426
|
+
if (!provider) {
|
|
427
|
+
return (
|
|
428
|
+
<div
|
|
429
|
+
key={agentType}
|
|
430
|
+
className="grid grid-cols-[minmax(0,1fr)_auto] gap-x-3 gap-y-2 rounded-md border px-3 py-2"
|
|
431
|
+
style={{
|
|
432
|
+
borderColor: 'var(--color-border-subtle)',
|
|
433
|
+
backgroundColor: 'rgba(255, 255, 255, 0.02)',
|
|
434
|
+
}}
|
|
435
|
+
>
|
|
436
|
+
<div className="min-w-0">
|
|
437
|
+
<div className="flex items-center gap-2 text-xs">
|
|
438
|
+
<Terminal
|
|
439
|
+
className="size-4 shrink-0"
|
|
456
440
|
style={{ color: 'var(--color-text-muted)' }}
|
|
441
|
+
/>
|
|
442
|
+
<span
|
|
443
|
+
className="font-medium"
|
|
444
|
+
style={{ color: 'var(--color-text-secondary)' }}
|
|
457
445
|
>
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
446
|
+
{AGENT_TYPE_LABELS[agentType]}
|
|
447
|
+
</span>
|
|
448
|
+
<span style={{ color: 'var(--color-text-muted)' }}>
|
|
449
|
+
{harnessProviders.length > 0
|
|
450
|
+
? `${harnessProviders.length} 个 Provider`
|
|
451
|
+
: '未配置 Provider'}
|
|
452
|
+
</span>
|
|
461
453
|
</div>
|
|
462
|
-
<div
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
borderColor: 'var(--color-border)',
|
|
469
|
-
color: 'var(--color-text-secondary)',
|
|
470
|
-
}}
|
|
471
|
-
>
|
|
472
|
-
<SlidersHorizontal className="size-3" />
|
|
473
|
-
配置
|
|
474
|
-
</button>
|
|
454
|
+
<div
|
|
455
|
+
className="mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[11px]"
|
|
456
|
+
style={{ color: 'var(--color-text-muted)' }}
|
|
457
|
+
>
|
|
458
|
+
<span>Agent 类型:{agentType}</span>
|
|
459
|
+
<span>Provider:{harnessProviders.length}</span>
|
|
475
460
|
</div>
|
|
476
461
|
</div>
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
462
|
+
<div className="flex shrink-0 items-start gap-2">
|
|
463
|
+
<button
|
|
464
|
+
type="button"
|
|
465
|
+
onClick={() => handleHarnessManage(agentType)}
|
|
466
|
+
className="flex items-center gap-1 rounded-md border px-2 py-[3px] text-[10px] font-medium transition-colors hover:bg-white/5"
|
|
467
|
+
style={{
|
|
468
|
+
borderColor: 'var(--color-border)',
|
|
469
|
+
color: 'var(--color-text-secondary)',
|
|
470
|
+
}}
|
|
471
|
+
>
|
|
472
|
+
<SlidersHorizontal className="size-3" />
|
|
473
|
+
配置
|
|
474
|
+
</button>
|
|
475
|
+
</div>
|
|
476
|
+
</div>
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
return (
|
|
480
480
|
<div
|
|
481
481
|
key={agentType}
|
|
482
482
|
className="grid grid-cols-[minmax(0,1fr)_auto] gap-x-3 gap-y-2 rounded-md border px-3 py-2"
|
|
@@ -526,9 +526,9 @@ export const CliStatusSection = ({
|
|
|
526
526
|
</div>
|
|
527
527
|
</div>
|
|
528
528
|
</div>
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
529
|
+
);
|
|
530
|
+
})}
|
|
531
|
+
</div>
|
|
532
532
|
</div>
|
|
533
533
|
) : (
|
|
534
534
|
<div className="space-y-2 text-sm" style={{ color: 'var(--color-text-secondary)' }}>
|
|
@@ -683,7 +683,9 @@ export const CliStatusSection = ({
|
|
|
683
683
|
<GenericHarnessProviderDialog
|
|
684
684
|
agentType={genericHarnessAgentType}
|
|
685
685
|
providers={
|
|
686
|
-
genericHarnessAgentType
|
|
686
|
+
genericHarnessAgentType
|
|
687
|
+
? (globalProvidersByAgentType.get(genericHarnessAgentType) ?? [])
|
|
688
|
+
: []
|
|
687
689
|
}
|
|
688
690
|
loading={globalProvidersLoading}
|
|
689
691
|
error={globalProvidersError}
|
|
@@ -793,7 +795,9 @@ const GenericHarnessProviderDialog = ({
|
|
|
793
795
|
placeholder="API Key(可选)"
|
|
794
796
|
/>
|
|
795
797
|
</div>
|
|
796
|
-
{addProviderError ?
|
|
798
|
+
{addProviderError ? (
|
|
799
|
+
<div className="text-xs text-red-400">{addProviderError}</div>
|
|
800
|
+
) : null}
|
|
797
801
|
<div className="flex justify-end">
|
|
798
802
|
<button
|
|
799
803
|
type="button"
|
|
@@ -919,8 +923,8 @@ const GenericHarnessProviderDialog = ({
|
|
|
919
923
|
color: 'var(--color-text-muted)',
|
|
920
924
|
}}
|
|
921
925
|
>
|
|
922
|
-
当前还没有绑定到 {title} 的 Provider。请在 Hermit 配置中添加
|
|
923
|
-
|
|
926
|
+
当前还没有绑定到 {title} 的 Provider。请在 Hermit 配置中添加 `agent_types` 包含 `
|
|
927
|
+
{agentType ?? 'agent'}` 的 Provider。
|
|
924
928
|
</div>
|
|
925
929
|
)}
|
|
926
930
|
</div>
|
|
@@ -451,11 +451,7 @@ export const GeneralSection = ({
|
|
|
451
451
|
{copied ? '已复制' : '复制链接'}
|
|
452
452
|
</button>
|
|
453
453
|
</div>
|
|
454
|
-
{serverError &&
|
|
455
|
-
<p className="mb-2 text-xs text-red-400">
|
|
456
|
-
服务状态获取失败:{serverError}
|
|
457
|
-
</p>
|
|
458
|
-
)}
|
|
454
|
+
{serverError && <p className="mb-2 text-xs text-red-400">服务状态获取失败:{serverError}</p>}
|
|
459
455
|
<p className="text-xs" style={{ color: 'var(--color-text-muted)' }}>
|
|
460
456
|
当前为 Web 控制台模式。服务由 Hermit 后端托管,不能在浏览器内启动或关闭。
|
|
461
457
|
</p>
|
|
@@ -590,7 +586,9 @@ export const GeneralSection = ({
|
|
|
590
586
|
min={100}
|
|
591
587
|
value={ccSettings.stream_preview_interval_ms}
|
|
592
588
|
onChange={(event) =>
|
|
593
|
-
patchCcSettings({
|
|
589
|
+
patchCcSettings({
|
|
590
|
+
stream_preview_interval_ms: Number(event.target.value) || 100,
|
|
591
|
+
})
|
|
594
592
|
}
|
|
595
593
|
className="h-8 w-full rounded-md border border-[var(--color-border)] bg-[var(--color-surface)] px-2 text-xs text-[var(--color-text)]"
|
|
596
594
|
/>
|
|
@@ -625,11 +623,7 @@ export const GeneralSection = ({
|
|
|
625
623
|
</div>
|
|
626
624
|
|
|
627
625
|
<div className="flex items-center gap-3">
|
|
628
|
-
<Button
|
|
629
|
-
size="sm"
|
|
630
|
-
onClick={() => void saveCcSettings()}
|
|
631
|
-
disabled={ccSettingsSaving}
|
|
632
|
-
>
|
|
626
|
+
<Button size="sm" onClick={() => void saveCcSettings()} disabled={ccSettingsSaving}>
|
|
633
627
|
{ccSettingsSaving ? <Loader2 className="mr-1.5 size-3.5 animate-spin" /> : null}
|
|
634
628
|
保存运行设置
|
|
635
629
|
</Button>
|
|
@@ -30,7 +30,8 @@ export const HarnessSection = (): React.JSX.Element => {
|
|
|
30
30
|
fetch('/api/v1/projects'),
|
|
31
31
|
]);
|
|
32
32
|
|
|
33
|
-
const providerData =
|
|
33
|
+
const providerData =
|
|
34
|
+
providerRes.status === 'fulfilled' ? providerRes.value : { providers: [] };
|
|
34
35
|
const providerCoverage = new Map<CcAgentType, string[]>(
|
|
35
36
|
ALL_AGENT_TYPES.map((type) => [type, []])
|
|
36
37
|
);
|
|
@@ -50,10 +51,12 @@ export const HarnessSection = (): React.JSX.Element => {
|
|
|
50
51
|
if (projectsRes.status === 'fulfilled' && projectsRes.value.ok) {
|
|
51
52
|
try {
|
|
52
53
|
const json = await projectsRes.value.json();
|
|
53
|
-
for (const proj of
|
|
54
|
+
for (const proj of json.data?.projects ?? []) {
|
|
54
55
|
if (proj.agent_type) projectAgentTypes.add(proj.agent_type);
|
|
55
56
|
}
|
|
56
|
-
} catch {
|
|
57
|
+
} catch {
|
|
58
|
+
/* ignore parse errors */
|
|
59
|
+
}
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
setUsedAgentTypes(projectAgentTypes);
|
|
@@ -83,11 +86,11 @@ export const HarnessSection = (): React.JSX.Element => {
|
|
|
83
86
|
{/* Supported agent types reference */}
|
|
84
87
|
<div>
|
|
85
88
|
<SettingsSectionHeader title="支持的 Agent 类型" />
|
|
86
|
-
<p className="text-xs
|
|
89
|
+
<p className="mb-3 text-xs" style={{ color: 'var(--color-text-muted)' }}>
|
|
87
90
|
hermit 支持的全部 Agent CLI 类型。绿色表示已配置对应 Provider。
|
|
88
91
|
</p>
|
|
89
92
|
|
|
90
|
-
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4
|
|
93
|
+
<div className="grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4">
|
|
91
94
|
{ALL_AGENT_TYPES.map((type) => {
|
|
92
95
|
const covering = coveredTypes.get(type) ?? [];
|
|
93
96
|
const covered = covering.length > 0;
|
|
@@ -96,23 +99,34 @@ export const HarnessSection = (): React.JSX.Element => {
|
|
|
96
99
|
<div
|
|
97
100
|
key={type}
|
|
98
101
|
className="flex items-center gap-2 rounded-lg border px-3 py-2.5"
|
|
99
|
-
style={{
|
|
102
|
+
style={{
|
|
103
|
+
borderColor: 'var(--color-border)',
|
|
104
|
+
background: 'var(--color-surface-raised)',
|
|
105
|
+
}}
|
|
100
106
|
>
|
|
101
|
-
<div
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
107
|
+
<div
|
|
108
|
+
className={cn(
|
|
109
|
+
'h-2 w-2 shrink-0 rounded-full',
|
|
110
|
+
covered ? 'bg-green-500' : 'bg-gray-500'
|
|
111
|
+
)}
|
|
112
|
+
/>
|
|
105
113
|
<div className="min-w-0 flex-1">
|
|
106
|
-
<p
|
|
114
|
+
<p
|
|
115
|
+
className="truncate text-xs font-medium"
|
|
116
|
+
style={{ color: 'var(--color-text)' }}
|
|
117
|
+
>
|
|
107
118
|
{AGENT_TYPE_LABELS[type]}
|
|
108
119
|
</p>
|
|
109
120
|
{covered && (
|
|
110
|
-
<p
|
|
121
|
+
<p
|
|
122
|
+
className="truncate text-[10px]"
|
|
123
|
+
style={{ color: 'var(--color-text-muted)' }}
|
|
124
|
+
>
|
|
111
125
|
{covering.join(', ')}
|
|
112
126
|
</p>
|
|
113
127
|
)}
|
|
114
128
|
</div>
|
|
115
|
-
{covered && <CheckCircle2 size={12} className="text-green-500
|
|
129
|
+
{covered && <CheckCircle2 size={12} className="shrink-0 text-green-500" />}
|
|
116
130
|
</div>
|
|
117
131
|
);
|
|
118
132
|
})}
|
|
@@ -122,8 +136,9 @@ export const HarnessSection = (): React.JSX.Element => {
|
|
|
122
136
|
{/* Unified harness configuration: runtime + providers */}
|
|
123
137
|
<div>
|
|
124
138
|
<SettingsSectionHeader title="Harness 配置" />
|
|
125
|
-
<p className="text-xs
|
|
126
|
-
点击对应 Harness 的“配置”,安装、检查运行时,并配置 settings.json、API
|
|
139
|
+
<p className="mb-3 text-xs" style={{ color: 'var(--color-text-muted)' }}>
|
|
140
|
+
点击对应 Harness 的“配置”,安装、检查运行时,并配置 settings.json、API
|
|
141
|
+
Key、端点和认证方式。
|
|
127
142
|
</p>
|
|
128
143
|
|
|
129
144
|
<CliStatusSection showSectionHeader={false} />
|
|
@@ -53,7 +53,9 @@ const PLATFORM_META: Record<PlatformType, { label: string; fields: PlatformField
|
|
|
53
53
|
{ key: 'app_secret', label: 'App Secret', placeholder: '...', required: true, secret: true },
|
|
54
54
|
{ key: 'allow_from', label: '允许来源(用户 ID 或 *)', placeholder: '* 或 ou_xxxx' },
|
|
55
55
|
{
|
|
56
|
-
key: 'share_session_in_channel',
|
|
56
|
+
key: 'share_session_in_channel',
|
|
57
|
+
label: '群内共享记忆',
|
|
58
|
+
placeholder: '',
|
|
57
59
|
type: 'select',
|
|
58
60
|
options: [
|
|
59
61
|
{ value: 'false', label: '关闭(默认)— 每人独立上下文' },
|
|
@@ -61,7 +63,9 @@ const PLATFORM_META: Record<PlatformType, { label: string; fields: PlatformField
|
|
|
61
63
|
],
|
|
62
64
|
},
|
|
63
65
|
{
|
|
64
|
-
key: 'thread_isolation',
|
|
66
|
+
key: 'thread_isolation',
|
|
67
|
+
label: '按回复串隔离',
|
|
68
|
+
placeholder: '',
|
|
65
69
|
type: 'select',
|
|
66
70
|
options: [
|
|
67
71
|
{ value: 'false', label: '关闭(默认)' },
|
|
@@ -77,7 +81,9 @@ const PLATFORM_META: Record<PlatformType, { label: string; fields: PlatformField
|
|
|
77
81
|
{ key: 'app_secret', label: 'App Secret', placeholder: '...', required: true, secret: true },
|
|
78
82
|
{ key: 'allow_from', label: '允许来源', placeholder: '* 或 ou_xxxx' },
|
|
79
83
|
{
|
|
80
|
-
key: 'share_session_in_channel',
|
|
84
|
+
key: 'share_session_in_channel',
|
|
85
|
+
label: '群内共享记忆',
|
|
86
|
+
placeholder: '',
|
|
81
87
|
type: 'select',
|
|
82
88
|
options: [
|
|
83
89
|
{ value: 'false', label: '关闭(默认)— 每人独立上下文' },
|
|
@@ -98,10 +104,18 @@ const PLATFORM_META: Record<PlatformType, { label: string; fields: PlatformField
|
|
|
98
104
|
telegram: {
|
|
99
105
|
label: 'Telegram',
|
|
100
106
|
fields: [
|
|
101
|
-
{
|
|
107
|
+
{
|
|
108
|
+
key: 'bot_token',
|
|
109
|
+
label: 'Bot Token',
|
|
110
|
+
placeholder: '1234567890:AAH...',
|
|
111
|
+
required: true,
|
|
112
|
+
secret: true,
|
|
113
|
+
},
|
|
102
114
|
{ key: 'allow_from', label: '允许的 Chat ID', placeholder: '* 或 123456789' },
|
|
103
115
|
{
|
|
104
|
-
key: 'share_session_in_channel',
|
|
116
|
+
key: 'share_session_in_channel',
|
|
117
|
+
label: '群内共享记忆',
|
|
118
|
+
placeholder: '',
|
|
105
119
|
type: 'select',
|
|
106
120
|
options: [
|
|
107
121
|
{ value: 'false', label: '关闭(默认)— 每人独立上下文' },
|
|
@@ -117,7 +131,9 @@ const PLATFORM_META: Record<PlatformType, { label: string; fields: PlatformField
|
|
|
117
131
|
{ key: 'app_secret', label: 'App Secret', placeholder: '...', required: true, secret: true },
|
|
118
132
|
{ key: 'allow_from', label: '允许来源', placeholder: '*' },
|
|
119
133
|
{
|
|
120
|
-
key: 'share_session_in_channel',
|
|
134
|
+
key: 'share_session_in_channel',
|
|
135
|
+
label: '群内共享记忆',
|
|
136
|
+
placeholder: '',
|
|
121
137
|
type: 'select',
|
|
122
138
|
options: [
|
|
123
139
|
{ value: 'false', label: '关闭(默认)— 每人独立上下文' },
|
|
@@ -129,15 +145,19 @@ const PLATFORM_META: Record<PlatformType, { label: string; fields: PlatformField
|
|
|
129
145
|
slack: {
|
|
130
146
|
label: 'Slack',
|
|
131
147
|
fields: [
|
|
132
|
-
{
|
|
148
|
+
{
|
|
149
|
+
key: 'bot_token',
|
|
150
|
+
label: 'Bot Token',
|
|
151
|
+
placeholder: 'xoxb-...',
|
|
152
|
+
required: true,
|
|
153
|
+
secret: true,
|
|
154
|
+
},
|
|
133
155
|
{ key: 'app_token', label: 'App Token', placeholder: 'xapp-...', secret: true },
|
|
134
156
|
],
|
|
135
157
|
},
|
|
136
158
|
bridge: {
|
|
137
159
|
label: 'Bridge(内部)',
|
|
138
|
-
fields: [
|
|
139
|
-
{ key: 'allow_from', label: '允许来源', placeholder: '* 或平台名' },
|
|
140
|
-
],
|
|
160
|
+
fields: [{ key: 'allow_from', label: '允许来源', placeholder: '* 或平台名' }],
|
|
141
161
|
},
|
|
142
162
|
};
|
|
143
163
|
|
|
@@ -177,7 +197,7 @@ async function fetchProjectDetail(name: string): Promise<ProjectDetail> {
|
|
|
177
197
|
async function addPlatform(
|
|
178
198
|
projectName: string,
|
|
179
199
|
type: string,
|
|
180
|
-
options: Record<string, string
|
|
200
|
+
options: Record<string, string>
|
|
181
201
|
): Promise<void> {
|
|
182
202
|
const res = await fetch(`/api/v1/projects/${encodeURIComponent(projectName)}/add-platform`, {
|
|
183
203
|
method: 'POST',
|
|
@@ -213,16 +233,23 @@ export const PlatformsSection = (): React.JSX.Element => {
|
|
|
213
233
|
}
|
|
214
234
|
}, []);
|
|
215
235
|
|
|
216
|
-
useEffect(() => {
|
|
236
|
+
useEffect(() => {
|
|
237
|
+
void refresh();
|
|
238
|
+
}, [refresh]);
|
|
217
239
|
|
|
218
240
|
const toggleExpand = async (name: string) => {
|
|
219
|
-
if (expanded === name) {
|
|
241
|
+
if (expanded === name) {
|
|
242
|
+
setExpanded(null);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
220
245
|
setExpanded(name);
|
|
221
246
|
if (!details[name]) {
|
|
222
247
|
try {
|
|
223
248
|
const d = await fetchProjectDetail(name);
|
|
224
249
|
setDetails((prev) => ({ ...prev, [name]: d }));
|
|
225
|
-
} catch {
|
|
250
|
+
} catch {
|
|
251
|
+
/* ignore */
|
|
252
|
+
}
|
|
226
253
|
}
|
|
227
254
|
};
|
|
228
255
|
|
|
@@ -232,7 +259,9 @@ export const PlatformsSection = (): React.JSX.Element => {
|
|
|
232
259
|
try {
|
|
233
260
|
const d = await fetchProjectDetail(projectName);
|
|
234
261
|
setDetails((prev) => ({ ...prev, [projectName]: d }));
|
|
235
|
-
} catch {
|
|
262
|
+
} catch {
|
|
263
|
+
/* ignore */
|
|
264
|
+
}
|
|
236
265
|
void refresh();
|
|
237
266
|
};
|
|
238
267
|
|
|
@@ -257,7 +286,9 @@ export const PlatformsSection = (): React.JSX.Element => {
|
|
|
257
286
|
</div>
|
|
258
287
|
|
|
259
288
|
{loading && (
|
|
260
|
-
<p className="text-sm" style={{ color: 'var(--color-text-muted)' }}
|
|
289
|
+
<p className="text-sm" style={{ color: 'var(--color-text-muted)' }}>
|
|
290
|
+
加载中…
|
|
291
|
+
</p>
|
|
261
292
|
)}
|
|
262
293
|
|
|
263
294
|
<div className="space-y-2">
|
|
@@ -277,11 +308,17 @@ export const PlatformsSection = (): React.JSX.Element => {
|
|
|
277
308
|
onClick={() => void toggleExpand(proj.name)}
|
|
278
309
|
>
|
|
279
310
|
{isExpanded ? (
|
|
280
|
-
<ChevronDown
|
|
311
|
+
<ChevronDown
|
|
312
|
+
className="size-4 shrink-0"
|
|
313
|
+
style={{ color: 'var(--color-text-muted)' }}
|
|
314
|
+
/>
|
|
281
315
|
) : (
|
|
282
|
-
<ChevronRight
|
|
316
|
+
<ChevronRight
|
|
317
|
+
className="size-4 shrink-0"
|
|
318
|
+
style={{ color: 'var(--color-text-muted)' }}
|
|
319
|
+
/>
|
|
283
320
|
)}
|
|
284
|
-
<span className="flex-1 font-medium
|
|
321
|
+
<span className="flex-1 text-sm font-medium" style={{ color: 'var(--color-text)' }}>
|
|
285
322
|
{proj.name}
|
|
286
323
|
</span>
|
|
287
324
|
<span className="text-xs" style={{ color: 'var(--color-text-muted)' }}>
|
|
@@ -308,29 +345,33 @@ export const PlatformsSection = (): React.JSX.Element => {
|
|
|
308
345
|
{/* Expanded detail */}
|
|
309
346
|
{isExpanded && (
|
|
310
347
|
<div
|
|
311
|
-
className="border-t px-4 py-3
|
|
348
|
+
className="space-y-3 border-t px-4 py-3"
|
|
312
349
|
style={{ borderColor: 'var(--color-border)', background: 'var(--color-surface)' }}
|
|
313
350
|
>
|
|
314
351
|
{detail ? (
|
|
315
352
|
<>
|
|
316
353
|
{detail.platforms.map((p) => {
|
|
317
354
|
const meta = PLATFORM_META[p.type as PlatformType];
|
|
318
|
-
const cfg = detail.platform_configs.find(
|
|
319
|
-
(c) => c.type === p.type,
|
|
320
|
-
);
|
|
355
|
+
const cfg = detail.platform_configs.find((c) => c.type === p.type);
|
|
321
356
|
return (
|
|
322
357
|
<div
|
|
323
358
|
key={p.type}
|
|
324
359
|
className="rounded-lg border p-3"
|
|
325
|
-
style={{
|
|
360
|
+
style={{
|
|
361
|
+
borderColor: 'var(--color-border)',
|
|
362
|
+
background: 'var(--color-surface-raised)',
|
|
363
|
+
}}
|
|
326
364
|
>
|
|
327
|
-
<div className="flex items-center gap-2
|
|
365
|
+
<div className="mb-2 flex items-center gap-2">
|
|
328
366
|
{p.connected ? (
|
|
329
367
|
<Wifi className="size-3.5 text-green-400" />
|
|
330
368
|
) : (
|
|
331
369
|
<WifiOff className="size-3.5 text-red-400" />
|
|
332
370
|
)}
|
|
333
|
-
<span
|
|
371
|
+
<span
|
|
372
|
+
className="text-sm font-medium"
|
|
373
|
+
style={{ color: 'var(--color-text)' }}
|
|
374
|
+
>
|
|
334
375
|
{meta?.label ?? p.type}
|
|
335
376
|
</span>
|
|
336
377
|
<span
|
|
@@ -340,31 +381,40 @@ export const PlatformsSection = (): React.JSX.Element => {
|
|
|
340
381
|
{p.connected ? '已连接' : '未连接'}
|
|
341
382
|
</span>
|
|
342
383
|
</div>
|
|
343
|
-
{cfg &&
|
|
344
|
-
.
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
<
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
384
|
+
{cfg &&
|
|
385
|
+
Object.entries(cfg)
|
|
386
|
+
.filter(([k]) => k !== 'type')
|
|
387
|
+
.map(([k, v]) => (
|
|
388
|
+
<div key={k} className="mt-1 flex gap-2 text-xs">
|
|
389
|
+
<span
|
|
390
|
+
className="w-28 shrink-0"
|
|
391
|
+
style={{ color: 'var(--color-text-muted)' }}
|
|
392
|
+
>
|
|
393
|
+
{k}
|
|
394
|
+
</span>
|
|
395
|
+
<span
|
|
396
|
+
className="truncate font-mono"
|
|
397
|
+
style={{ color: 'var(--color-text-secondary)' }}
|
|
398
|
+
>
|
|
399
|
+
{k.toLowerCase().includes('secret') ||
|
|
400
|
+
k.toLowerCase().includes('token') ||
|
|
401
|
+
k.toLowerCase().includes('key')
|
|
402
|
+
? `${String(v).slice(0, 6)}••••`
|
|
403
|
+
: String(v)}
|
|
404
|
+
</span>
|
|
405
|
+
</div>
|
|
406
|
+
))}
|
|
355
407
|
</div>
|
|
356
408
|
);
|
|
357
409
|
})}
|
|
358
410
|
</>
|
|
359
411
|
) : (
|
|
360
|
-
<p className="text-xs" style={{ color: 'var(--color-text-muted)' }}
|
|
412
|
+
<p className="text-xs" style={{ color: 'var(--color-text-muted)' }}>
|
|
413
|
+
加载中…
|
|
414
|
+
</p>
|
|
361
415
|
)}
|
|
362
416
|
|
|
363
|
-
<Button
|
|
364
|
-
size="sm"
|
|
365
|
-
variant="outline"
|
|
366
|
-
onClick={() => setAddOpen(proj.name)}
|
|
367
|
-
>
|
|
417
|
+
<Button size="sm" variant="outline" onClick={() => setAddOpen(proj.name)}>
|
|
368
418
|
<Plus className="mr-1.5 size-3.5" />
|
|
369
419
|
添加渠道
|
|
370
420
|
</Button>
|
|
@@ -407,7 +457,11 @@ function AddPlatformDialog({
|
|
|
407
457
|
const [error, setError] = useState<string | null>(null);
|
|
408
458
|
|
|
409
459
|
useEffect(() => {
|
|
410
|
-
if (open) {
|
|
460
|
+
if (open) {
|
|
461
|
+
setPlatformType('feishu');
|
|
462
|
+
setFields({});
|
|
463
|
+
setError(null);
|
|
464
|
+
}
|
|
411
465
|
}, [open]);
|
|
412
466
|
|
|
413
467
|
const meta = PLATFORM_META[platformType];
|
|
@@ -449,7 +503,10 @@ function AddPlatformDialog({
|
|
|
449
503
|
<Label>平台类型</Label>
|
|
450
504
|
<Select
|
|
451
505
|
value={platformType}
|
|
452
|
-
onValueChange={(v) => {
|
|
506
|
+
onValueChange={(v) => {
|
|
507
|
+
setPlatformType(v as PlatformType);
|
|
508
|
+
setFields({});
|
|
509
|
+
}}
|
|
453
510
|
>
|
|
454
511
|
<SelectTrigger className="mt-1">
|
|
455
512
|
<SelectValue />
|
|
@@ -480,7 +537,9 @@ function AddPlatformDialog({
|
|
|
480
537
|
</SelectTrigger>
|
|
481
538
|
<SelectContent>
|
|
482
539
|
{f.options.map((o) => (
|
|
483
|
-
<SelectItem key={o.value} value={o.value}>
|
|
540
|
+
<SelectItem key={o.value} value={o.value}>
|
|
541
|
+
{o.label}
|
|
542
|
+
</SelectItem>
|
|
484
543
|
))}
|
|
485
544
|
</SelectContent>
|
|
486
545
|
</Select>
|
|
@@ -496,9 +555,7 @@ function AddPlatformDialog({
|
|
|
496
555
|
</div>
|
|
497
556
|
))}
|
|
498
557
|
|
|
499
|
-
{error &&
|
|
500
|
-
<p className="text-sm text-red-400">{error}</p>
|
|
501
|
-
)}
|
|
558
|
+
{error && <p className="text-sm text-red-400">{error}</p>}
|
|
502
559
|
|
|
503
560
|
<p className="text-xs" style={{ color: 'var(--color-text-muted)' }}>
|
|
504
561
|
添加后需要重启 cc-connect 才能生效。
|
|
@@ -506,7 +563,9 @@ function AddPlatformDialog({
|
|
|
506
563
|
</div>
|
|
507
564
|
|
|
508
565
|
<DialogFooter>
|
|
509
|
-
<Button variant="outline" onClick={onClose}
|
|
566
|
+
<Button variant="outline" onClick={onClose}>
|
|
567
|
+
取消
|
|
568
|
+
</Button>
|
|
510
569
|
<Button onClick={() => void handleSave()} disabled={saving}>
|
|
511
570
|
{saving ? '添加中…' : '添加'}
|
|
512
571
|
</Button>
|