@yancyyu/openhermit 1.6.38 → 1.6.39

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.
Files changed (188) hide show
  1. package/dist-renderer/assets/ProjectEditorOverlay-krO5vQxX.js +58 -0
  2. package/dist-renderer/assets/{TeamGraphOverlay-ZEDfZyHb.js → TeamGraphOverlay-DqhQzcTr.js} +1 -1
  3. package/dist-renderer/assets/{_basePickBy-CIhniz70.js → _basePickBy-B7kSYPxr.js} +1 -1
  4. package/dist-renderer/assets/{_baseUniq-cKAW4Q8I.js → _baseUniq-CnjxqwAk.js} +1 -1
  5. package/dist-renderer/assets/{arc-YmNsoDXW.js → arc-CLeZuINP.js} +1 -1
  6. package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-DHEls2sX.js → architectureDiagram-VXUJARFQ-QKtqaqdY.js} +1 -1
  7. package/dist-renderer/assets/{blockDiagram-VD42YOAC-Bpwf1Sbg.js → blockDiagram-VD42YOAC-BqdrzO_f.js} +1 -1
  8. package/dist-renderer/assets/{c4Diagram-YG6GDRKO-B0IaQ4w5.js → c4Diagram-YG6GDRKO-gwPlCxDC.js} +1 -1
  9. package/dist-renderer/assets/channel-DpMHF50r.js +1 -0
  10. package/dist-renderer/assets/{chunk-4BX2VUAB-DLk-hcFc.js → chunk-4BX2VUAB-C6XLurL4.js} +1 -1
  11. package/dist-renderer/assets/{chunk-55IACEB6-1XRmX_Zm.js → chunk-55IACEB6-Ds6quhEP.js} +1 -1
  12. package/dist-renderer/assets/{chunk-B4BG7PRW-1waH1DAD.js → chunk-B4BG7PRW-5UlA1_e9.js} +1 -1
  13. package/dist-renderer/assets/{chunk-DI55MBZ5-BqpZBtrN.js → chunk-DI55MBZ5-ywFrqIsY.js} +1 -1
  14. package/dist-renderer/assets/{chunk-FMBD7UC4-Bly7vVym.js → chunk-FMBD7UC4-C7ifUA17.js} +1 -1
  15. package/dist-renderer/assets/{chunk-QN33PNHL-Ci2QWBAs.js → chunk-QN33PNHL-BxGCo80U.js} +1 -1
  16. package/dist-renderer/assets/{chunk-QZHKN3VN-YCqFW7d-.js → chunk-QZHKN3VN-B2CuaZs6.js} +1 -1
  17. package/dist-renderer/assets/{chunk-TZMSLE5B-B0xGXInl.js → chunk-TZMSLE5B-Ds1hInvp.js} +1 -1
  18. package/dist-renderer/assets/classDiagram-2ON5EDUG-CBYCBVRl.js +1 -0
  19. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-CBYCBVRl.js +1 -0
  20. package/dist-renderer/assets/clone-DcMF6Psb.js +1 -0
  21. package/dist-renderer/assets/{cose-bilkent-S5V4N54A-DxcFNQKT.js → cose-bilkent-S5V4N54A-Cz1GVtLp.js} +1 -1
  22. package/dist-renderer/assets/{dagre-6UL2VRFP-DPo_RfZY.js → dagre-6UL2VRFP-BrmR-P4h.js} +1 -1
  23. package/dist-renderer/assets/{diagram-PSM6KHXK-U3hQsFe4.js → diagram-PSM6KHXK-DbNjC5Rg.js} +1 -1
  24. package/dist-renderer/assets/{diagram-QEK2KX5R-OrwrAy0V.js → diagram-QEK2KX5R-qkRX5_Mq.js} +1 -1
  25. package/dist-renderer/assets/{diagram-S2PKOQOG-CXATPWVw.js → diagram-S2PKOQOG-CyL5rCv2.js} +1 -1
  26. package/dist-renderer/assets/{erDiagram-Q2GNP2WA-B0e8AfMF.js → erDiagram-Q2GNP2WA-Dox3-bA5.js} +1 -1
  27. package/dist-renderer/assets/{flowDiagram-NV44I4VS-CXfzA4jJ.js → flowDiagram-NV44I4VS-BtkaxlDL.js} +1 -1
  28. package/dist-renderer/assets/{ganttDiagram-JELNMOA3-CMr08qVl.js → ganttDiagram-JELNMOA3-Dhy_d9GK.js} +1 -1
  29. package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-vYFHpPmy.js → gitGraphDiagram-V2S2FVAM-B5XRhIQA.js} +1 -1
  30. package/dist-renderer/assets/{graph-DOe5j8dH.js → graph-CsoEwUhS.js} +1 -1
  31. package/dist-renderer/assets/{index-BySQS7AB.js → index-BWPWmJNo.js} +1 -1
  32. package/dist-renderer/assets/{index-V7dAKPqd.js → index-Bu2R-Se7.js} +587 -705
  33. package/dist-renderer/assets/index-CnWV3BhG.css +32 -0
  34. package/dist-renderer/assets/{index-CzWxVCRL.js → index-D-3KgskL.js} +1 -1
  35. package/dist-renderer/assets/{index-VJ-MM9xa.js → index-DGEBzLNT.js} +1 -1
  36. package/dist-renderer/assets/{index-B2Dy7M2G.js → index-NhHNs2Oo.js} +1 -1
  37. package/dist-renderer/assets/{index-C_okzZXP.js → index-h17WuEyf.js} +1 -1
  38. package/dist-renderer/assets/{infoDiagram-HS3SLOUP-D_WubR0B.js → infoDiagram-HS3SLOUP-hMGmNojH.js} +1 -1
  39. package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-w9ca-1TI.js → journeyDiagram-XKPGCS4Q-DXV2rBDl.js} +1 -1
  40. package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-Jg9p6_pN.js → kanban-definition-3W4ZIXB7-Bf99WLRy.js} +1 -1
  41. package/dist-renderer/assets/{layout-B-z3y17c.js → layout-C3XWrpwo.js} +1 -1
  42. package/dist-renderer/assets/{linear-D-RTX5UW.js → linear-OEEcn8KN.js} +1 -1
  43. package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-CDQmHOYP.js → mindmap-definition-VGOIOE7T-Dpi3S2x4.js} +1 -1
  44. package/dist-renderer/assets/{pieDiagram-ADFJNKIX-D_odsQL7.js → pieDiagram-ADFJNKIX-xTPPhtNx.js} +1 -1
  45. package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-BRsmYWSA.js → quadrantDiagram-AYHSOK5B-euniyDlz.js} +1 -1
  46. package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-ChNE_BOV.js → requirementDiagram-UZGBJVZJ-D9Uiw4kF.js} +1 -1
  47. package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-C8FtpwKc.js → sankeyDiagram-TZEHDZUN-CySU4nED.js} +1 -1
  48. package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-DmLCzNcc.js → sequenceDiagram-WL72ISMW-JVGpET6V.js} +1 -1
  49. package/dist-renderer/assets/splashScene-D0YB9uxm.js +17 -0
  50. package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-WJBm4bhu.js → stateDiagram-FKZM4ZOC-B2FY5qqi.js} +1 -1
  51. package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-DcoMiR8H.js +1 -0
  52. package/dist-renderer/assets/{timeline-definition-IT6M3QCI-BXs_hOJs.js → timeline-definition-IT6M3QCI-DmycNUUe.js} +1 -1
  53. package/dist-renderer/assets/{treemap-GDKQZRPO-o04MA0G9.js → treemap-GDKQZRPO-DPq4gZuB.js} +1 -1
  54. package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-Czj69XRd.js → xychartDiagram-PRI3JC2R-J6VVJzRq.js} +1 -1
  55. package/dist-renderer/index.html +20 -53
  56. package/package.json +25 -18
  57. package/src/main/ipc/extensions.ts +2 -1
  58. package/src/main/server.ts +873 -221
  59. package/src/main/services/extensions/ExtensionFacadeService.ts +2 -5
  60. package/src/main/services/extensions/catalog/PluginCatalogService.ts +4 -2
  61. package/src/main/services/session-intelligence/ConversationTelemetryService.ts +1101 -0
  62. package/src/main/services/session-intelligence/LocalSessionScanner.ts +512 -0
  63. package/src/main/services/session-intelligence/SessionUsageParser.ts +4 -4
  64. package/src/main/services/system-manager/SystemManagerConfigService.ts +122 -0
  65. package/src/main/services/system-manager/SystemManagerPtyService.ts +233 -0
  66. package/src/main/services/system-manager/WorkflowPromptService.ts +75 -0
  67. package/src/main/services/teams-mvp/TaskDispatchService.ts +5 -6
  68. package/src/main/services/teams-mvp/TeamProvisioningService.ts +39 -2
  69. package/src/main/services/teams-mvp/TeamWorkspaceService.ts +22 -4
  70. package/src/main/utils/teamProjectResolution.ts +15 -0
  71. package/src/renderer/App.tsx +8 -4
  72. package/src/renderer/api/httpClient.ts +68 -18
  73. package/src/renderer/api/providers.ts +23 -2
  74. package/src/renderer/assets/participant-avatars/01.svg +3 -0
  75. package/src/renderer/assets/participant-avatars/02.svg +3 -0
  76. package/src/renderer/assets/participant-avatars/03.svg +3 -0
  77. package/src/renderer/assets/participant-avatars/04.svg +3 -0
  78. package/src/renderer/assets/participant-avatars/05.svg +3 -0
  79. package/src/renderer/assets/participant-avatars/06.svg +3 -0
  80. package/src/renderer/assets/participant-avatars/07.svg +3 -0
  81. package/src/renderer/assets/participant-avatars/08.svg +3 -0
  82. package/src/renderer/assets/participant-avatars/09.svg +3 -0
  83. package/src/renderer/assets/participant-avatars/10.svg +3 -0
  84. package/src/renderer/assets/participant-avatars/11.svg +3 -0
  85. package/src/renderer/assets/participant-avatars/12.svg +3 -0
  86. package/src/renderer/assets/participant-avatars/13.svg +3 -0
  87. package/src/renderer/components/common/TerminalPane.tsx +213 -0
  88. package/src/renderer/components/dashboard/DashboardView.tsx +9 -36
  89. package/src/renderer/components/extensions/ExtensionStoreView.tsx +6 -125
  90. package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +1 -1
  91. package/src/renderer/components/extensions/mcp/McpLibraryEnableDialog.tsx +305 -0
  92. package/src/renderer/components/extensions/mcp/McpLibraryEntryDialog.tsx +418 -0
  93. package/src/renderer/components/extensions/mcp/McpLibraryPanel.tsx +404 -0
  94. package/src/renderer/components/extensions/plugins/PluginCard.tsx +6 -6
  95. package/src/renderer/components/extensions/plugins/PluginsPanel.tsx +34 -21
  96. package/src/renderer/components/extensions/skills/SkillsLibraryPanel.tsx +335 -0
  97. package/src/renderer/components/layout/PaneContent.tsx +8 -1
  98. package/src/renderer/components/layout/Sidebar.tsx +11 -54
  99. package/src/renderer/components/layout/SortableTab.tsx +20 -31
  100. package/src/renderer/components/layout/TabBar.tsx +1 -1
  101. package/src/renderer/components/layout/TabContextMenu.tsx +1 -1
  102. package/src/renderer/components/runtime/ProviderRuntimeSettingsDialog.tsx +768 -157
  103. package/src/renderer/components/schedules/SchedulesView.tsx +51 -462
  104. package/src/renderer/components/schedules/calendar/CalendarDayView.tsx +173 -0
  105. package/src/renderer/components/schedules/calendar/CalendarEventBlock.tsx +113 -0
  106. package/src/renderer/components/schedules/calendar/CalendarHeader.tsx +148 -0
  107. package/src/renderer/components/schedules/calendar/CalendarMonthView.tsx +142 -0
  108. package/src/renderer/components/schedules/calendar/CalendarWeekView.tsx +219 -0
  109. package/src/renderer/components/schedules/calendar/ScheduleCalendarBoard.tsx +41 -0
  110. package/src/renderer/components/schedules/calendar/TeamGanttView.tsx +405 -0
  111. package/src/renderer/components/schedules/calendar/computeOccurrences.ts +234 -0
  112. package/src/renderer/components/schedules/calendar/index.ts +2 -0
  113. package/src/renderer/components/schedules/calendar/types.ts +44 -0
  114. package/src/renderer/components/settings/SettingsTabs.tsx +50 -55
  115. package/src/renderer/components/settings/SettingsView.tsx +30 -35
  116. package/src/renderer/components/settings/components/SettingsSectionHeader.tsx +5 -1
  117. package/src/renderer/components/settings/components/SettingsSelect.tsx +5 -3
  118. package/src/renderer/components/settings/components/SettingsToggle.tsx +2 -2
  119. package/src/renderer/components/settings/sections/AdvancedSection.tsx +11 -42
  120. package/src/renderer/components/settings/sections/CliStatusSection.tsx +71 -112
  121. package/src/renderer/components/settings/sections/ConfigEditorDialog.tsx +1 -1
  122. package/src/renderer/components/settings/sections/GeneralSection.tsx +11 -3
  123. package/src/renderer/components/settings/sections/HarnessSection.tsx +18 -14
  124. package/src/renderer/components/settings/sections/PlatformsSection.tsx +3 -3
  125. package/src/renderer/components/settings/sections/TaskBusSection.tsx +33 -40
  126. package/src/renderer/components/settings/sections/index.ts +0 -1
  127. package/src/renderer/components/sidebar/SidebarSessions.tsx +182 -4
  128. package/src/renderer/components/sidebar/SidebarTaskItem.tsx +4 -4
  129. package/src/renderer/components/sidebar/WorkspaceBrowser.tsx +39 -4
  130. package/src/renderer/components/splash/splashScene.ts +121 -929
  131. package/src/renderer/components/system-manager/FolderBrowser.tsx +163 -0
  132. package/src/renderer/components/system-manager/SystemManagerView.tsx +351 -0
  133. package/src/renderer/components/tasks/TasksView.tsx +112 -134
  134. package/src/renderer/components/team/CcSessionsSection.tsx +431 -89
  135. package/src/renderer/components/team/CollapsibleTeamSection.tsx +17 -32
  136. package/src/renderer/components/team/TeamDetailView.tsx +319 -123
  137. package/src/renderer/components/team/TeamListView.tsx +108 -123
  138. package/src/renderer/components/team/dialogs/CreateTaskDialog.tsx +2 -2
  139. package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +84 -306
  140. package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +259 -342
  141. package/src/renderer/components/team/dialogs/GlobalTaskDetailDialog.tsx +1 -1
  142. package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +17 -15
  143. package/src/renderer/components/team/dialogs/PlatformBindingDialog.tsx +221 -0
  144. package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +7 -0
  145. package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +1 -1
  146. package/src/renderer/components/team/dialogs/RuntimeConfigDialog.tsx +361 -0
  147. package/src/renderer/components/team/dialogs/platformMeta.ts +122 -11
  148. package/src/renderer/components/team/dialogs/useTeamEditForm.ts +17 -5
  149. package/src/renderer/components/team/kanban/KanbanBoard.tsx +9 -9
  150. package/src/renderer/components/team/members/MemberCard.tsx +14 -47
  151. package/src/renderer/components/team/members/MemberDetailDialog.tsx +3 -95
  152. package/src/renderer/components/team/members/MemberDetailStats.tsx +50 -65
  153. package/src/renderer/components/team/messages/MessageComposer.tsx +8 -110
  154. package/src/renderer/components/team/messages/MessagesPanel.tsx +131 -114
  155. package/src/renderer/components/team/schedule/ScheduleStatusBadge.tsx +2 -2
  156. package/src/renderer/components/team/tools/AddMcpInline.tsx +27 -17
  157. package/src/renderer/components/team/tools/McpChip.tsx +6 -3
  158. package/src/renderer/components/team/tools/SkillChip.tsx +2 -2
  159. package/src/renderer/components/team/tools/ToolsSection.tsx +418 -70
  160. package/src/renderer/hooks/useExtensionsTabState.ts +3 -114
  161. package/src/renderer/index.css +39 -22
  162. package/src/renderer/index.html +17 -50
  163. package/src/renderer/store/index.ts +2 -1
  164. package/src/renderer/store/slices/scheduleSlice.ts +1 -1
  165. package/src/renderer/store/slices/teamSlice.ts +45 -168
  166. package/src/renderer/utils/claudeCodeOnlyProviders.ts +3 -10
  167. package/src/renderer/utils/memberHelpers.ts +5 -17
  168. package/src/renderer/utils/openCodeRuntimeDeliveryDiagnostics.ts +4 -2
  169. package/src/renderer/utils/providerSlashCommands.ts +0 -5
  170. package/src/renderer/utils/scheduleFormatters.ts +3 -1
  171. package/src/renderer/utils/teamMessageFiltering.ts +14 -1
  172. package/src/renderer/utils/teamModelAvailability.ts +18 -2
  173. package/src/shared/types/api.ts +121 -2
  174. package/src/shared/types/ccConnect.ts +2 -0
  175. package/src/shared/types/index.ts +3 -0
  176. package/src/shared/types/systemManager.ts +49 -0
  177. package/src/shared/types/team.ts +29 -0
  178. package/src/shared/types/terminal.ts +4 -2
  179. package/src/shared/utils/extensionNormalizers.ts +15 -8
  180. package/src/shared/utils/providerExtensionCapabilities.ts +2 -2
  181. package/dist-renderer/assets/ProjectEditorOverlay-lJZi-9Hp.js +0 -52
  182. package/dist-renderer/assets/channel-yIlSKy0e.js +0 -1
  183. package/dist-renderer/assets/classDiagram-2ON5EDUG-24fHez0s.js +0 -1
  184. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-24fHez0s.js +0 -1
  185. package/dist-renderer/assets/clone-BTNuUva-.js +0 -1
  186. package/dist-renderer/assets/index-Bi6nrZ4z.css +0 -1
  187. package/dist-renderer/assets/splashScene-C8lWNnm4.js +0 -1
  188. package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-_m6iPPUR.js +0 -1
@@ -0,0 +1,361 @@
1
+ import { useEffect, useMemo, useRef, useState } from 'react';
2
+
3
+ import { Button } from '@renderer/components/ui/button';
4
+ import {
5
+ Dialog,
6
+ DialogContent,
7
+ DialogDescription,
8
+ DialogFooter,
9
+ DialogHeader,
10
+ DialogTitle,
11
+ } 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
+ import { useStore } from '@renderer/store';
18
+ import { isTeamProvisioningActive } from '@renderer/store/slices/teamSlice';
19
+ import type { GlobalProvider } from '@shared/types';
20
+ import type { CcAgentType } from '@shared/types/ccConnect';
21
+ import { PERMISSION_MODE_OPTIONS } from './useTeamEditForm';
22
+ import { PlatformBindingContent } from './PlatformBindingDialog';
23
+
24
+ // ── Section wrapper ──────────────────────────────────────────
25
+ function FormSection({
26
+ title,
27
+ description,
28
+ children,
29
+ }: {
30
+ title: string;
31
+ description?: string;
32
+ children: React.ReactNode;
33
+ }): React.JSX.Element {
34
+ return (
35
+ <div className="rounded-md border border-[var(--color-border)] p-3">
36
+ <h3 className="text-sm font-medium text-[var(--color-text)]">{title}</h3>
37
+ {description && (
38
+ <p className="mt-0.5 text-xs text-[var(--color-text-muted)]">{description}</p>
39
+ )}
40
+ <div className="mt-3 space-y-3">{children}</div>
41
+ </div>
42
+ );
43
+ }
44
+
45
+ const inputCls =
46
+ 'w-full rounded-md border border-[var(--color-border)] bg-[var(--color-surface)] px-3 py-1.5 text-sm text-[var(--color-text)] outline-none focus:border-[var(--color-border-emphasis)]';
47
+ const labelCls = 'mb-1 block text-xs font-medium text-[var(--color-text-secondary)]';
48
+
49
+ interface RuntimeConfigDialogProps {
50
+ open: boolean;
51
+ teamName: string;
52
+ onClose: () => void;
53
+ }
54
+
55
+ export function RuntimeConfigDialog({
56
+ open,
57
+ teamName,
58
+ onClose,
59
+ }: RuntimeConfigDialogProps): React.JSX.Element {
60
+ const { data, fetchTeams, selectTeam } = useStore((s) => ({
61
+ data: s.selectedTeamName === teamName ? s.selectedTeamData : null,
62
+ fetchTeams: s.fetchTeams,
63
+ selectTeam: s.selectTeam,
64
+ }));
65
+ const isProvisioning = useStore((s) => isTeamProvisioningActive(s, teamName));
66
+
67
+ // ── Derived defaults ─────────────────────────────────────────
68
+ const defaults = useMemo(() => {
69
+ const cfg = data?.config;
70
+ const d = data as Record<string, unknown> | null;
71
+ return {
72
+ agentType: cfg?.agentType ?? (d?.harness as string | undefined) ?? 'claudecode',
73
+ workDir: (d?.workDir as string | undefined) ?? cfg?.projectPath ?? '',
74
+ permissionMode: cfg?.permissionMode ?? (d?.permissionMode as string | undefined) ?? 'default',
75
+ disabledCommands: Array.isArray(cfg?.disabledCommands)
76
+ ? cfg.disabledCommands
77
+ : [],
78
+ providerRefs: data?.providerRefs ?? [],
79
+ globalProviders: data?.globalProviders ?? [],
80
+ bindProject: (d?.bindProject as string | undefined) ?? teamName,
81
+ };
82
+ }, [data, teamName]);
83
+
84
+ // ── Local form state ─────────────────────────────────────────
85
+ const [agentType, setAgentType] = useState(defaults.agentType);
86
+ const [permissionMode, setPermissionMode] = useState(defaults.permissionMode);
87
+ const [workDir, setWorkDir] = useState(defaults.workDir);
88
+ const [disabledCommandsInput, setDisabledCommandsInput] = useState(
89
+ defaults.disabledCommands.join(', ')
90
+ );
91
+ const [providerRef, setProviderRef] = useState(defaults.providerRefs[0] ?? '');
92
+
93
+ const [savePhase, setSavePhase] = useState<'idle' | 'saving' | 'restarting' | 'done'>('idle');
94
+ const [error, setError] = useState<string | null>(null);
95
+ const saving = savePhase === 'saving' || savePhase === 'restarting';
96
+
97
+ const defaultsRef = useRef(defaults);
98
+ if (defaults.agentType) defaultsRef.current = defaults;
99
+
100
+ // ── Reset form when dialog opens ─────────────────────────────
101
+ const prevOpenRef = useRef(false);
102
+ useEffect(() => {
103
+ if (!open || prevOpenRef.current) {
104
+ prevOpenRef.current = open;
105
+ return;
106
+ }
107
+ prevOpenRef.current = true;
108
+ const d = defaultsRef.current;
109
+ setSavePhase('idle');
110
+ setError(null);
111
+ setAgentType(d.agentType);
112
+ setPermissionMode(d.permissionMode);
113
+ setWorkDir(d.workDir);
114
+ setDisabledCommandsInput(d.disabledCommands.join(', '));
115
+ setProviderRef(d.providerRefs[0] ?? '');
116
+ }, [open]);
117
+
118
+ // ── Computed ─────────────────────────────────────────────────
119
+ const compatibleProviders = useMemo(
120
+ () =>
121
+ defaults.globalProviders.filter(
122
+ (p) =>
123
+ !p.agent_types ||
124
+ p.agent_types.length === 0 ||
125
+ (p.agent_types as string[]).includes(agentType)
126
+ ),
127
+ [defaults.globalProviders, agentType]
128
+ );
129
+
130
+ const toggleProviderRef = (providerName: string): void => {
131
+ setError(null);
132
+ setProviderRef(providerRef === providerName ? '' : providerName);
133
+ };
134
+
135
+ // ── Save ─────────────────────────────────────────────────────
136
+ const handleSave = (): void => {
137
+ if (savePhase !== 'idle') return;
138
+ const disabledCommands = disabledCommandsInput
139
+ .split(',')
140
+ .map((e) => e.trim())
141
+ .filter((e) => e.length > 0);
142
+
143
+ setSavePhase('saving');
144
+ setError(null);
145
+
146
+ void (async () => {
147
+ try {
148
+ await api.teams.updateConfig(teamName, {
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)]);
156
+
157
+ setSavePhase('restarting');
158
+ try {
159
+ await api.ccSettings.restart();
160
+ setSavePhase('done');
161
+ } catch (restartErr) {
162
+ setError(
163
+ `配置已保存,但重启失败:${restartErr instanceof Error ? restartErr.message : '未知错误'}`
164
+ );
165
+ setSavePhase('idle');
166
+ }
167
+ } catch (err) {
168
+ setError(err instanceof Error ? err.message : '保存失败');
169
+ setSavePhase('idle');
170
+ }
171
+ })();
172
+ };
173
+
174
+ const saveLabel =
175
+ savePhase === 'done'
176
+ ? '已完成'
177
+ : savePhase === 'restarting'
178
+ ? '正在重启...'
179
+ : savePhase === 'saving'
180
+ ? '保存中...'
181
+ : '保存并重启';
182
+
183
+ const [bindingStep, setBindingStep] = useState<'runtime' | 'bind'>('runtime');
184
+
185
+ return (
186
+ <Dialog
187
+ open={savePhase === 'saving' ? true : open}
188
+ onOpenChange={(nextOpen) => {
189
+ if (saving) return;
190
+ if (!nextOpen) onClose();
191
+ }}
192
+ >
193
+ <DialogContent className="max-w-2xl">
194
+ <DialogHeader>
195
+ <DialogTitle className="flex items-center gap-2">
196
+ <Settings2 size={16} />
197
+ 运行时配置
198
+ </DialogTitle>
199
+ <DialogDescription>
200
+ 修改 Agent 类型、渠道、消息设置等运行时参数。部分变更需要重启服务。
201
+ </DialogDescription>
202
+ </DialogHeader>
203
+
204
+ {bindingStep === 'bind' ? (
205
+ <PlatformBindingContent
206
+ projectName={defaults.bindProject}
207
+ workDir={workDir}
208
+ agentType={agentType}
209
+ onComplete={() => setBindingStep('runtime')}
210
+ onCancel={() => setBindingStep('runtime')}
211
+ />
212
+ ) : (
213
+ <div className="space-y-4">
214
+ {/* Agent & 权限 */}
215
+ <FormSection title="Agent & 权限">
216
+ <div className="grid gap-3 md:grid-cols-2">
217
+ <div>
218
+ <label className={labelCls}>Agent 类型</label>
219
+ <HarnessSelect
220
+ value={agentType as CcAgentType}
221
+ onChange={(v) => { setError(null); setAgentType(v); }}
222
+ className="w-full"
223
+ />
224
+ </div>
225
+ <div>
226
+ <label className={labelCls}>权限模式</label>
227
+ <select
228
+ value={permissionMode}
229
+ onChange={(e) => { setError(null); setPermissionMode(e.target.value); }}
230
+ className={inputCls}
231
+ >
232
+ {PERMISSION_MODE_OPTIONS.map((opt) => (
233
+ <option key={opt.value} value={opt.value}>{opt.label}</option>
234
+ ))}
235
+ </select>
236
+ </div>
237
+ </div>
238
+ <div>
239
+ <label className={labelCls}>工作目录</label>
240
+ <input
241
+ type="text"
242
+ value={workDir}
243
+ onChange={(e) => { setError(null); setWorkDir(e.target.value); }}
244
+ className={`${inputCls} font-mono`}
245
+ placeholder="/Users/you/code/project"
246
+ />
247
+ </div>
248
+ </FormSection>
249
+
250
+ {/* 渠道 */}
251
+ <FormSection title="渠道" description="绑定外部消息平台(飞书、Telegram 等)。">
252
+ <Button
253
+ variant="outline"
254
+ size="sm"
255
+ onClick={() => setBindingStep('bind')}
256
+ >
257
+ 绑定新渠道
258
+ </Button>
259
+ </FormSection>
260
+
261
+ {/* Provider */}
262
+ <div className="rounded-lg border border-[var(--color-border-subtle)] bg-white/[0.02] p-3">
263
+ <div className="flex items-start justify-between gap-3">
264
+ <div>
265
+ <p className="text-xs font-medium text-[var(--color-text)]">Provider(可选)</p>
266
+ <p className="mt-1 text-[11px] leading-relaxed text-[var(--color-text-muted)]">
267
+ 留空时使用本机 {AGENT_TYPE_LABELS[agentType as CcAgentType] ?? agentType} 默认配置。
268
+ </p>
269
+ </div>
270
+ {providerRef ? (
271
+ <button
272
+ type="button"
273
+ 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={() => setProviderRef('')}
275
+ >
276
+ 使用本机默认
277
+ </button>
278
+ ) : null}
279
+ </div>
280
+ <div className="mt-3 space-y-2">
281
+ {compatibleProviders.length > 0 ? (
282
+ compatibleProviders.map((provider) => {
283
+ const checked = providerRef === provider.name;
284
+ const at = agentType as CcAgentType;
285
+ const endpoint = provider.endpoints?.[at] ?? provider.base_url ?? '默认端点';
286
+ const model =
287
+ provider.agent_models?.[at] ?? provider.model ?? provider.models?.[0]?.model ?? '未指定模型';
288
+ return (
289
+ <button
290
+ key={provider.name}
291
+ type="button"
292
+ onClick={() => toggleProviderRef(provider.name)}
293
+ className={`w-full rounded-lg border px-3 py-2 text-left transition-colors ${
294
+ checked
295
+ ? 'border-indigo-400/60 bg-indigo-500/10'
296
+ : 'border-[var(--color-border-subtle)] bg-black/10 hover:border-[var(--color-border)] hover:bg-white/[0.04]'
297
+ }`}
298
+ >
299
+ <div className="flex items-center justify-between gap-3">
300
+ <div className="min-w-0">
301
+ <p className="truncate text-xs font-medium text-[var(--color-text)]">{provider.name}</p>
302
+ <p className="mt-0.5 truncate text-[11px] text-[var(--color-text-muted)]">
303
+ {model} · {endpoint}
304
+ </p>
305
+ </div>
306
+ <span
307
+ className={`shrink-0 rounded-full px-2 py-0.5 text-[10px] ${
308
+ checked ? 'bg-indigo-400/20 text-indigo-200' : 'bg-white/5 text-[var(--color-text-muted)]'
309
+ }`}
310
+ >
311
+ {checked ? '已绑定' : '可绑定'}
312
+ </span>
313
+ </div>
314
+ </button>
315
+ );
316
+ })
317
+ ) : (
318
+ <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} 的全局 Provider。
320
+ </div>
321
+ )}
322
+ </div>
323
+ </div>
324
+
325
+ {/* 高级 */}
326
+ <FormSection title="高级">
327
+ <div>
328
+ <label className={labelCls}>已禁用命令</label>
329
+ <input
330
+ type="text"
331
+ value={disabledCommandsInput}
332
+ onChange={(e) => { setError(null); setDisabledCommandsInput(e.target.value); }}
333
+ className={inputCls}
334
+ placeholder="restart, upgrade, cron"
335
+ />
336
+ </div>
337
+ </FormSection>
338
+
339
+ {error && <p className="text-xs text-red-400">{error}</p>}
340
+ </div>
341
+ )}
342
+
343
+ {bindingStep === 'runtime' && (
344
+ <DialogFooter>
345
+ <Button variant="outline" size="sm" onClick={onClose} disabled={saving}>
346
+ {savePhase === 'done' ? '关闭' : '取消'}
347
+ </Button>
348
+ <Button
349
+ size="sm"
350
+ onClick={handleSave}
351
+ disabled={saving || savePhase === 'done'}
352
+ >
353
+ {saving && <Loader2 size={14} className="mr-1.5 animate-spin" />}
354
+ {saveLabel}
355
+ </Button>
356
+ </DialogFooter>
357
+ )}
358
+ </DialogContent>
359
+ </Dialog>
360
+ );
361
+ }
@@ -31,10 +31,17 @@ export const platformMeta: Record<string, PlatformMeta> = {
31
31
  },
32
32
  {
33
33
  key: 'allow_from',
34
- label: 'Allow From',
35
- placeholder: '* (all)',
34
+ label: '私聊权限(允许的用户 ID)',
35
+ placeholder: '* 或 user_id',
36
36
  group: 'advanced',
37
- hint: '限制可交互的用户/群,* 表示所有',
37
+ hint: '控制哪些用户可以私聊机器人,* 表示所有',
38
+ },
39
+ {
40
+ key: 'allow_chat',
41
+ label: '群聊权限(允许的群聊 ID)',
42
+ placeholder: '* 或 chat_id',
43
+ group: 'advanced',
44
+ hint: '控制哪些群聊可以 @机器人,* 表示所有群聊',
38
45
  },
39
46
  { key: 'group_reply_all', label: '群聊回复全部', type: 'boolean', group: 'advanced' },
40
47
  { key: 'share_session_in_channel', label: '共享群会话', type: 'boolean', group: 'advanced' },
@@ -44,7 +51,20 @@ export const platformMeta: Record<string, PlatformMeta> = {
44
51
  label: 'Discord',
45
52
  fields: [
46
53
  { key: 'token', label: 'Bot Token', required: true, type: 'password' },
47
- { key: 'allow_from', label: 'Allow From', placeholder: '* (all)', group: 'advanced' },
54
+ {
55
+ key: 'allow_from',
56
+ label: '私聊权限(允许的用户 ID)',
57
+ placeholder: '* 或 user_id',
58
+ group: 'advanced',
59
+ hint: '控制哪些用户可以私聊机器人',
60
+ },
61
+ {
62
+ key: 'allow_chat',
63
+ label: '群聊权限(允许的频道 ID)',
64
+ placeholder: '* 或 channel_id',
65
+ group: 'advanced',
66
+ hint: '控制哪些频道可以 @机器人',
67
+ },
48
68
  {
49
69
  key: 'guild_id',
50
70
  label: 'Guild ID',
@@ -79,7 +99,20 @@ export const platformMeta: Record<string, PlatformMeta> = {
79
99
  type: 'password',
80
100
  placeholder: 'xapp-...',
81
101
  },
82
- { key: 'allow_from', label: 'Allow From', placeholder: '* (all)', group: 'advanced' },
102
+ {
103
+ key: 'allow_from',
104
+ label: '私聊权限(允许的用户 ID)',
105
+ placeholder: '* 或 user_id',
106
+ group: 'advanced',
107
+ hint: '控制哪些用户可以私聊机器人',
108
+ },
109
+ {
110
+ key: 'allow_chat',
111
+ label: '群聊权限(允许的频道 ID)',
112
+ placeholder: '* 或 channel_id',
113
+ group: 'advanced',
114
+ hint: '控制哪些频道可以 @机器人',
115
+ },
83
116
  {
84
117
  key: 'share_session_in_channel',
85
118
  label: '共享频道会话',
@@ -93,7 +126,20 @@ export const platformMeta: Record<string, PlatformMeta> = {
93
126
  fields: [
94
127
  { key: 'client_id', label: 'Client ID', required: true },
95
128
  { key: 'client_secret', label: 'Client Secret', required: true, type: 'password' },
96
- { key: 'allow_from', label: 'Allow From', placeholder: '* (all)', group: 'advanced' },
129
+ {
130
+ key: 'allow_from',
131
+ label: '私聊权限(允许的用户 ID)',
132
+ placeholder: '* 或 user_id',
133
+ group: 'advanced',
134
+ hint: '控制哪些用户可以私聊机器人',
135
+ },
136
+ {
137
+ key: 'allow_chat',
138
+ label: '群聊权限(允许的群聊 ID)',
139
+ placeholder: '* 或 chat_id',
140
+ group: 'advanced',
141
+ hint: '控制哪些群聊可以 @机器人',
142
+ },
97
143
  { key: 'share_session_in_channel', label: '共享群会话', type: 'boolean', group: 'advanced' },
98
144
  ],
99
145
  },
@@ -123,7 +169,20 @@ export const platformMeta: Record<string, PlatformMeta> = {
123
169
  placeholder: 'https://qyapi.weixin.qq.com',
124
170
  group: 'advanced',
125
171
  },
126
- { key: 'allow_from', label: 'Allow From', placeholder: '* (all)', group: 'advanced' },
172
+ {
173
+ key: 'allow_from',
174
+ label: '私聊权限(允许的用户 ID)',
175
+ placeholder: '* 或 user_id',
176
+ group: 'advanced',
177
+ hint: '控制哪些用户可以私聊机器人',
178
+ },
179
+ {
180
+ key: 'allow_chat',
181
+ label: '群聊权限(允许的群聊 ID)',
182
+ placeholder: '* 或 chat_id',
183
+ group: 'advanced',
184
+ hint: '控制哪些群聊可以 @机器人',
185
+ },
127
186
  ],
128
187
  },
129
188
  qq: {
@@ -131,7 +190,20 @@ export const platformMeta: Record<string, PlatformMeta> = {
131
190
  fields: [
132
191
  { key: 'ws_url', label: 'WebSocket URL', required: true, placeholder: 'ws://127.0.0.1:3001' },
133
192
  { key: 'token', label: 'Access Token', type: 'password', group: 'advanced' },
134
- { key: 'allow_from', label: 'Allow From', placeholder: '* (all)', group: 'advanced' },
193
+ {
194
+ key: 'allow_from',
195
+ label: '私聊权限(允许的用户 ID)',
196
+ placeholder: '* 或 user_id',
197
+ group: 'advanced',
198
+ hint: '控制哪些用户可以私聊机器人',
199
+ },
200
+ {
201
+ key: 'allow_chat',
202
+ label: '群聊权限(允许的群聊 ID)',
203
+ placeholder: '* 或 group_id',
204
+ group: 'advanced',
205
+ hint: '控制哪些群聊可以 @机器人',
206
+ },
135
207
  { key: 'share_session_in_channel', label: '共享群会话', type: 'boolean', group: 'advanced' },
136
208
  ],
137
209
  },
@@ -141,7 +213,20 @@ export const platformMeta: Record<string, PlatformMeta> = {
141
213
  { key: 'app_id', label: 'App ID', required: true },
142
214
  { key: 'app_secret', label: 'App Secret', required: true, type: 'password' },
143
215
  { key: 'sandbox', label: '沙盒模式', type: 'boolean', group: 'advanced' },
144
- { key: 'allow_from', label: 'Allow From', placeholder: '* (all)', group: 'advanced' },
216
+ {
217
+ key: 'allow_from',
218
+ label: '私聊权限(允许的用户 ID)',
219
+ placeholder: '* 或 user_id',
220
+ group: 'advanced',
221
+ hint: '控制哪些用户可以私聊机器人',
222
+ },
223
+ {
224
+ key: 'allow_chat',
225
+ label: '群聊权限(允许的群聊 ID)',
226
+ placeholder: '* 或 group_id',
227
+ group: 'advanced',
228
+ hint: '控制哪些群聊可以 @机器人',
229
+ },
145
230
  { key: 'share_session_in_channel', label: '共享群会话', type: 'boolean', group: 'advanced' },
146
231
  ],
147
232
  },
@@ -152,7 +237,20 @@ export const platformMeta: Record<string, PlatformMeta> = {
152
237
  { key: 'channel_token', label: 'Channel Token', required: true, type: 'password' },
153
238
  { key: 'port', label: '端口', required: true, placeholder: '8080' },
154
239
  { key: 'callback_path', label: 'Callback Path', placeholder: '/callback', group: 'advanced' },
155
- { key: 'allow_from', label: 'Allow From', placeholder: '* (all)', group: 'advanced' },
240
+ {
241
+ key: 'allow_from',
242
+ label: '私聊权限(允许的用户 ID)',
243
+ placeholder: '* 或 user_id',
244
+ group: 'advanced',
245
+ hint: '控制哪些用户可以私聊机器人',
246
+ },
247
+ {
248
+ key: 'allow_chat',
249
+ label: '群聊权限(允许的群聊 ID)',
250
+ placeholder: '* 或 room_id',
251
+ group: 'advanced',
252
+ hint: '控制哪些群聊可以 @机器人',
253
+ },
156
254
  ],
157
255
  },
158
256
  weibo: {
@@ -160,7 +258,20 @@ export const platformMeta: Record<string, PlatformMeta> = {
160
258
  fields: [
161
259
  { key: 'app_id', label: 'App ID', required: true, placeholder: '1234567890' },
162
260
  { key: 'app_secret', label: 'App Secret', required: true, type: 'password' },
163
- { key: 'allow_from', label: 'Allow From', placeholder: '* (all)', group: 'advanced' },
261
+ {
262
+ key: 'allow_from',
263
+ label: '私聊权限(允许的用户 ID)',
264
+ placeholder: '* 或 user_id',
265
+ group: 'advanced',
266
+ hint: '控制哪些用户可以私聊机器人',
267
+ },
268
+ {
269
+ key: 'allow_chat',
270
+ label: '群聊权限(允许的群聊 ID)',
271
+ placeholder: '* 或 chat_id',
272
+ group: 'advanced',
273
+ hint: '控制哪些群聊可以 @机器人',
274
+ },
164
275
  ],
165
276
  },
166
277
  };
@@ -8,7 +8,7 @@ import { useShallow } from 'zustand/react/shallow';
8
8
  import type { GlobalProvider } from '@shared/types';
9
9
  import type { CcAgentType } from '@shared/types/ccConnect';
10
10
 
11
- type SavePhase = 'idle' | 'saving' | 'restarting' | 'done';
11
+ type SavePhase = 'idle' | 'saving' | 'done';
12
12
 
13
13
  export interface UseTeamEditFormReturn {
14
14
  loading: boolean;
@@ -29,6 +29,8 @@ export interface UseTeamEditFormReturn {
29
29
  setManagedSources: (v: string) => void;
30
30
  feishuAllowFrom: string;
31
31
  setFeishuAllowFrom: (v: string) => void;
32
+ feishuAllowChat: string;
33
+ setFeishuAllowChat: (v: string) => void;
32
34
  disabledCommandsInput: string;
33
35
  setDisabledCommandsInput: (v: string) => void;
34
36
  providerRef: string;
@@ -106,6 +108,13 @@ export function useTeamEditForm(teamName: string, open: boolean): UseTeamEditFor
106
108
  !Array.isArray(rawSettings.platform_allow_from)
107
109
  ? (rawSettings.platform_allow_from as Record<string, string>)
108
110
  : {}),
111
+ platformAllowChat:
112
+ cfg?.platformAllowChat ??
113
+ (typeof (rawSettings as Record<string, unknown>).platform_allow_chat === 'object' &&
114
+ (rawSettings as Record<string, unknown>).platform_allow_chat !== null &&
115
+ !Array.isArray((rawSettings as Record<string, unknown>).platform_allow_chat)
116
+ ? ((rawSettings as Record<string, unknown>).platform_allow_chat as Record<string, string>)
117
+ : {}),
109
118
  providerRefs: data?.providerRefs ?? [],
110
119
  globalProviders: data?.globalProviders ?? [],
111
120
  showContextIndicator:
@@ -134,6 +143,7 @@ export function useTeamEditForm(teamName: string, open: boolean): UseTeamEditFor
134
143
  defaults.disabledCommands.join(', ')
135
144
  );
136
145
  const [feishuAllowFrom, setFeishuAllowFrom] = useState(defaults.platformAllowFrom.feishu ?? '*');
146
+ const [feishuAllowChat, setFeishuAllowChat] = useState(defaults.platformAllowChat.feishu ?? '*');
137
147
  const [providerRef, setProviderRef] = useState(defaults.providerRefs[0] ?? '');
138
148
  const [showContextIndicator, setShowContextIndicator] = useState(defaults.showContextIndicator);
139
149
  const [replyFooter, setReplyFooter] = useState(defaults.replyFooter);
@@ -142,7 +152,7 @@ export function useTeamEditForm(teamName: string, open: boolean): UseTeamEditFor
142
152
  // ── Single async lifecycle state ─────────────────────────────
143
153
  const [savePhase, setSavePhase] = useState<SavePhase>('idle');
144
154
  const [error, setError] = useState<string | null>(null);
145
- const saving = savePhase === 'saving' || savePhase === 'restarting';
155
+ const saving = savePhase === 'saving';
146
156
 
147
157
  // ── Refs ─────────────────────────────────────────────────────
148
158
  const defaultsRef = useRef(defaults);
@@ -170,6 +180,7 @@ export function useTeamEditForm(teamName: string, open: boolean): UseTeamEditFor
170
180
  setManagedSources(d.managedSources);
171
181
  setDisabledCommandsInput(d.disabledCommands.join(', '));
172
182
  setFeishuAllowFrom(d.platformAllowFrom.feishu ?? '*');
183
+ setFeishuAllowChat(d.platformAllowChat.feishu ?? '*');
173
184
  setProviderRef(d.providerRefs[0] ?? '');
174
185
  setShowContextIndicator(d.showContextIndicator);
175
186
  setReplyFooter(d.replyFooter);
@@ -204,6 +215,7 @@ export function useTeamEditForm(teamName: string, open: boolean): UseTeamEditFor
204
215
  .map((e) => e.trim())
205
216
  .filter((e) => e.length > 0);
206
217
  const feishu = feishuAllowFrom.trim();
218
+ const feishuChat = feishuAllowChat.trim();
207
219
 
208
220
  setSavePhase('saving');
209
221
  setError(null);
@@ -224,12 +236,10 @@ export function useTeamEditForm(teamName: string, open: boolean): UseTeamEditFor
224
236
  managedSources: managedSources.trim() || undefined,
225
237
  disabledCommands,
226
238
  platformAllowFrom: feishu ? { feishu } : {},
239
+ platformAllowChat: feishuChat ? { feishu: feishuChat } : {},
227
240
  providerRefs: providerRef ? [providerRef] : [],
228
241
  });
229
242
 
230
- setSavePhase('restarting');
231
- await api.ccSettings.restart();
232
-
233
243
  await Promise.all([fetchTeams(), selectTeam(teamName)]);
234
244
  setSavePhase('done');
235
245
  } catch (err) {
@@ -258,6 +268,8 @@ export function useTeamEditForm(teamName: string, open: boolean): UseTeamEditFor
258
268
  setManagedSources,
259
269
  feishuAllowFrom,
260
270
  setFeishuAllowFrom,
271
+ feishuAllowChat,
272
+ setFeishuAllowChat,
261
273
  disabledCommandsInput,
262
274
  setDisabledCommandsInput,
263
275
  providerRef,
@@ -37,19 +37,19 @@ const COLUMN_ACCENTS: Record<
37
37
  { headerBg: string; bodyBg: string; icon: React.ReactNode }
38
38
  > = {
39
39
  todo: {
40
- headerBg: 'rgba(59, 130, 246, 0.22)',
41
- bodyBg: 'rgba(59, 130, 246, 0.05)',
42
- icon: <ClipboardList size={14} className="shrink-0 text-[var(--color-text-muted)]" />,
40
+ headerBg: 'rgba(148, 163, 184, 0.08)',
41
+ bodyBg: 'rgba(148, 163, 184, 0.02)',
42
+ icon: <ClipboardList size={13} className="shrink-0 text-[var(--color-text-muted)]" />,
43
43
  },
44
44
  in_progress: {
45
- headerBg: 'rgba(234, 179, 8, 0.24)',
46
- bodyBg: 'rgba(234, 179, 8, 0.06)',
47
- icon: <PlayCircle size={14} className="shrink-0 text-[var(--color-text-muted)]" />,
45
+ headerBg: 'rgba(6, 182, 212, 0.08)',
46
+ bodyBg: 'rgba(6, 182, 212, 0.02)',
47
+ icon: <PlayCircle size={13} className="shrink-0 text-cyan-400/60" />,
48
48
  },
49
49
  done: {
50
- headerBg: 'rgba(34, 197, 94, 0.22)',
51
- bodyBg: 'rgba(34, 197, 94, 0.05)',
52
- icon: <CheckCircle2 size={14} className="shrink-0 text-[var(--color-text-muted)]" />,
50
+ headerBg: 'rgba(34, 197, 94, 0.08)',
51
+ bodyBg: 'rgba(34, 197, 94, 0.02)',
52
+ icon: <CheckCircle2 size={13} className="shrink-0 text-green-400/60" />,
53
53
  },
54
54
  };
55
55