@yancyyu/openhermit 1.6.30 → 1.6.31

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 (69) hide show
  1. package/dist-renderer/assets/{ProjectEditorOverlay-DsQt4FHy.js → ProjectEditorOverlay-DkXfi2pg.js} +1 -1
  2. package/dist-renderer/assets/{TeamGraphOverlay-BjZC53xf.js → TeamGraphOverlay-CHNNVraw.js} +1 -1
  3. package/dist-renderer/assets/{_basePickBy-CrWocIjq.js → _basePickBy-Do-Ff83V.js} +1 -1
  4. package/dist-renderer/assets/{_baseUniq-B6d8ysWi.js → _baseUniq-nDLhSuJI.js} +1 -1
  5. package/dist-renderer/assets/{arc-DAIYCFP8.js → arc-Bp7fA6sx.js} +1 -1
  6. package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-B3UudXJh.js → architectureDiagram-VXUJARFQ-CPC1HdGy.js} +1 -1
  7. package/dist-renderer/assets/{blockDiagram-VD42YOAC-DbptKQ4W.js → blockDiagram-VD42YOAC-DTVKyNTO.js} +1 -1
  8. package/dist-renderer/assets/{c4Diagram-YG6GDRKO-C4WQuZpV.js → c4Diagram-YG6GDRKO-XVu-AN00.js} +1 -1
  9. package/dist-renderer/assets/channel-CIwbNcUO.js +1 -0
  10. package/dist-renderer/assets/{chunk-4BX2VUAB-Dp7fVpI_.js → chunk-4BX2VUAB-BcWmVyA-.js} +1 -1
  11. package/dist-renderer/assets/{chunk-55IACEB6-B8KGfbAy.js → chunk-55IACEB6-Co4Z2jsE.js} +1 -1
  12. package/dist-renderer/assets/{chunk-B4BG7PRW-BG1oJrjA.js → chunk-B4BG7PRW-C8q9gfDT.js} +1 -1
  13. package/dist-renderer/assets/{chunk-DI55MBZ5-DRmxNjht.js → chunk-DI55MBZ5-qDgb1gxO.js} +1 -1
  14. package/dist-renderer/assets/{chunk-FMBD7UC4-D6VLvy16.js → chunk-FMBD7UC4-Cm8Gu2gu.js} +1 -1
  15. package/dist-renderer/assets/{chunk-QN33PNHL-DZou1667.js → chunk-QN33PNHL-DYji1BRS.js} +1 -1
  16. package/dist-renderer/assets/{chunk-QZHKN3VN-CghmasSh.js → chunk-QZHKN3VN-DWAS568H.js} +1 -1
  17. package/dist-renderer/assets/{chunk-TZMSLE5B-B7apcMPK.js → chunk-TZMSLE5B-CLFzXLA8.js} +1 -1
  18. package/dist-renderer/assets/classDiagram-2ON5EDUG-04A-pvql.js +1 -0
  19. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-04A-pvql.js +1 -0
  20. package/dist-renderer/assets/clone-DQnvTIEM.js +1 -0
  21. package/dist-renderer/assets/{cose-bilkent-S5V4N54A-05e5uQDp.js → cose-bilkent-S5V4N54A-CZdGhX_3.js} +1 -1
  22. package/dist-renderer/assets/{dagre-6UL2VRFP-B06bRykF.js → dagre-6UL2VRFP-BVY-G6nO.js} +1 -1
  23. package/dist-renderer/assets/{diagram-PSM6KHXK-CY7VYQ7c.js → diagram-PSM6KHXK-CUACvAwG.js} +1 -1
  24. package/dist-renderer/assets/{diagram-QEK2KX5R-BjKEH7dD.js → diagram-QEK2KX5R-3SfnesSG.js} +1 -1
  25. package/dist-renderer/assets/{diagram-S2PKOQOG-Bf4ELS1_.js → diagram-S2PKOQOG-E3ksXClJ.js} +1 -1
  26. package/dist-renderer/assets/{erDiagram-Q2GNP2WA-DJ753_L9.js → erDiagram-Q2GNP2WA-aYjGXss7.js} +1 -1
  27. package/dist-renderer/assets/{flowDiagram-NV44I4VS-B71S-lC-.js → flowDiagram-NV44I4VS-JMHrrTQs.js} +1 -1
  28. package/dist-renderer/assets/{ganttDiagram-JELNMOA3-C_U42mSZ.js → ganttDiagram-JELNMOA3-CVQ-R5rN.js} +1 -1
  29. package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-DKUJU4Ns.js → gitGraphDiagram-V2S2FVAM-OLn9jq61.js} +1 -1
  30. package/dist-renderer/assets/{graph-DY3qbzqj.js → graph-BAb2J0l8.js} +1 -1
  31. package/dist-renderer/assets/{index-Dhsk3_DD.js → index-BSoCjBWn.js} +1 -1
  32. package/dist-renderer/assets/{index-Bs27J5gB.js → index-BtG3HbqP.js} +1 -1
  33. package/dist-renderer/assets/{index-BlOrAXp3.js → index-CH8e7g1f.js} +569 -569
  34. package/dist-renderer/assets/index-CSt8DTcn.css +1 -0
  35. package/dist-renderer/assets/{index-C8B_nKOF.js → index-Ca4iNkRA.js} +1 -1
  36. package/dist-renderer/assets/{index-GpUvV2xs.js → index-DU9PGgZJ.js} +1 -1
  37. package/dist-renderer/assets/{index-DLKyDr4T.js → index-DtMzIS9o.js} +1 -1
  38. package/dist-renderer/assets/{infoDiagram-HS3SLOUP-BNs0y3IG.js → infoDiagram-HS3SLOUP-CY_ptQNL.js} +1 -1
  39. package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-CqPnw4UV.js → journeyDiagram-XKPGCS4Q-C2vuHEo_.js} +1 -1
  40. package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-SLlzcUJ2.js → kanban-definition-3W4ZIXB7-mbdNfu8h.js} +1 -1
  41. package/dist-renderer/assets/{layout-BZLlNmbr.js → layout-Do_ArEB1.js} +1 -1
  42. package/dist-renderer/assets/{linear-qz6v45xy.js → linear-BMlMKyiq.js} +1 -1
  43. package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-B1-kmEWV.js → mindmap-definition-VGOIOE7T-Dfntn-o2.js} +1 -1
  44. package/dist-renderer/assets/{pieDiagram-ADFJNKIX-B8a02iNx.js → pieDiagram-ADFJNKIX-LiWHsGMV.js} +1 -1
  45. package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-BKv1Xfou.js → quadrantDiagram-AYHSOK5B-D87St8AF.js} +1 -1
  46. package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-B3DUpZi2.js → requirementDiagram-UZGBJVZJ-DAa6lHBx.js} +1 -1
  47. package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-DmPzuTsy.js → sankeyDiagram-TZEHDZUN-VOUngars.js} +1 -1
  48. package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-Bo7RelRb.js → sequenceDiagram-WL72ISMW-BzwzmFr2.js} +1 -1
  49. package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-1epX98gV.js → stateDiagram-FKZM4ZOC-BjAQEJ52.js} +1 -1
  50. package/dist-renderer/assets/{stateDiagram-v2-4FDKWEC3-03Ym9PTr.js → stateDiagram-v2-4FDKWEC3-BDwy4GJm.js} +1 -1
  51. package/dist-renderer/assets/{timeline-definition-IT6M3QCI-r6isC62H.js → timeline-definition-IT6M3QCI-Y5XBZt3W.js} +1 -1
  52. package/dist-renderer/assets/{treemap-GDKQZRPO-CGKpOUF2.js → treemap-GDKQZRPO-DzkdUEow.js} +1 -1
  53. package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-t4-rwdAw.js → xychartDiagram-PRI3JC2R-D-zbvJOv.js} +1 -1
  54. package/dist-renderer/index.html +2 -2
  55. package/package.json +1 -1
  56. package/src/renderer/components/extensions/ExtensionStoreView.tsx +4 -1
  57. package/src/renderer/components/extensions/mcp/McpServerDetailDialog.tsx +100 -15
  58. package/src/renderer/components/team/TeamDetailView.tsx +55 -139
  59. package/src/renderer/components/team/TeamListFilterPopover.tsx +0 -16
  60. package/src/renderer/components/team/TeamListView.tsx +7 -32
  61. package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +283 -409
  62. package/src/renderer/components/team/dialogs/useTeamEditForm.ts +283 -0
  63. package/src/renderer/utils/multimodelProviderVisibility.ts +17 -0
  64. package/src/renderer/utils/openCodeRuntimeDeliveryDiagnostics.ts +29 -9
  65. package/dist-renderer/assets/channel-DbjZvWii.js +0 -1
  66. package/dist-renderer/assets/classDiagram-2ON5EDUG-D_FGxxsl.js +0 -1
  67. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-D_FGxxsl.js +0 -1
  68. package/dist-renderer/assets/clone-CJ1kxO2J.js +0 -1
  69. package/dist-renderer/assets/index-CmZPUEhS.css +0 -1
@@ -22,6 +22,7 @@ import {
22
22
  DialogHeader,
23
23
  DialogTitle,
24
24
  } from '@renderer/components/ui/dialog';
25
+ import { Popover, PopoverContent, PopoverTrigger } from '@renderer/components/ui/popover';
25
26
  import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip';
26
27
  import { getTeamColorSet, getThemedBadge } from '@renderer/constants/teamColors';
27
28
  import { useTabIdOptional } from '@renderer/contexts/useTabUIContext';
@@ -69,6 +70,7 @@ import {
69
70
  Trash2,
70
71
  Loader2,
71
72
  MessageSquare,
73
+ MoreHorizontal,
72
74
  Shield,
73
75
  Users,
74
76
  } from 'lucide-react';
@@ -883,22 +885,7 @@ export const TeamDetailView = ({
883
885
  const [updatingRoleLoading, setUpdatingRoleLoading] = useState(false);
884
886
  const [editDialogOpen, setEditDialogOpen] = useState(false);
885
887
  const [envDialogOpen, setEnvDialogOpen] = useState(false);
886
- const [savedLaunchRequest, setSavedLaunchRequest] = useState<TeamLaunchRequest | null>(null);
887
- useEffect(() => {
888
- if (!editDialogOpen || !teamName) return;
889
- let cancelled = false;
890
- void (async () => {
891
- try {
892
- const saved = await api.teams.getSavedRequest(teamName);
893
- if (!cancelled) setSavedLaunchRequest(saved ?? null);
894
- } catch {
895
- if (!cancelled) setSavedLaunchRequest(null);
896
- }
897
- })();
898
- return () => {
899
- cancelled = true;
900
- };
901
- }, [editDialogOpen, teamName]);
888
+ const [headerMenuOpen, setHeaderMenuOpen] = useState(false);
902
889
  const [launchDialogState, setLaunchDialogState] = useState<{
903
890
  open: boolean;
904
891
  mode: TeamLaunchDialogMode;
@@ -1643,11 +1630,7 @@ export const TeamDetailView = ({
1643
1630
 
1644
1631
  const handleRestartTeamFromEdit = useCallback(async (): Promise<void> => {
1645
1632
  await api.ccSettings.restart();
1646
- // Wait for cc-connect to come back, then refresh
1647
- setTimeout(() => {
1648
- void fetchTeams();
1649
- void selectTeam(teamName);
1650
- }, 3000);
1633
+ await Promise.all([fetchTeams(), selectTeam(teamName)]);
1651
1634
  }, [fetchTeams, selectTeam, teamName]);
1652
1635
 
1653
1636
  const handleSaveAndRestartFromEdit = useCallback(
@@ -2089,24 +2072,6 @@ export const TeamDetailView = ({
2089
2072
  const headerColorSet = data.config.color
2090
2073
  ? getTeamColorSet(data.config.color)
2091
2074
  : nameColorSet(data.config.name);
2092
- const rawTeamSettings = (data.settings ?? {}) as Record<string, unknown>;
2093
- const currentManagedSources =
2094
- data.config.managedSources ??
2095
- (typeof rawTeamSettings.admin_from === 'string' ? rawTeamSettings.admin_from : '*');
2096
- const currentDisabledCommands =
2097
- data.config.disabledCommands ??
2098
- (Array.isArray(rawTeamSettings.disabled_commands)
2099
- ? rawTeamSettings.disabled_commands.filter(
2100
- (entry): entry is string => typeof entry === 'string' && entry.trim().length > 0
2101
- )
2102
- : []);
2103
- const currentPlatformAllowFrom =
2104
- data.config.platformAllowFrom ??
2105
- (typeof rawTeamSettings.platform_allow_from === 'object' &&
2106
- rawTeamSettings.platform_allow_from !== null &&
2107
- !Array.isArray(rawTeamSettings.platform_allow_from)
2108
- ? (rawTeamSettings.platform_allow_from as Record<string, string>)
2109
- : {});
2110
2075
 
2111
2076
  return (
2112
2077
  <>
@@ -2158,52 +2123,55 @@ export const TeamDetailView = ({
2158
2123
  </div>
2159
2124
  </div>
2160
2125
  <div className="flex shrink-0 items-center gap-1.5">
2161
- {data.config.projectPath && (
2162
- <Tooltip>
2163
- <TooltipTrigger asChild>
2164
- <Button
2165
- variant="ghost"
2166
- size="sm"
2167
- className="h-7 gap-1 px-2 text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text)]"
2168
- onClick={() => setEnvDialogOpen(true)}
2169
- >
2170
- <Shield size={12} />
2171
- </Button>
2172
- </TooltipTrigger>
2173
- <TooltipContent side="bottom">环境变量</TooltipContent>
2174
- </Tooltip>
2175
- )}
2176
- <Tooltip>
2177
- <TooltipTrigger asChild>
2126
+ <Button
2127
+ variant="outline"
2128
+ size="sm"
2129
+ className="h-7 gap-1.5 px-2.5 text-xs text-[var(--color-text-secondary)]"
2130
+ disabled={isTeamProvisioning}
2131
+ onClick={() => setEditDialogOpen(true)}
2132
+ >
2133
+ <Pencil size={12} />
2134
+ 编辑
2135
+ </Button>
2136
+ <Popover open={headerMenuOpen} onOpenChange={setHeaderMenuOpen}>
2137
+ <PopoverTrigger asChild>
2178
2138
  <Button
2179
2139
  variant="ghost"
2180
2140
  size="sm"
2181
- className="h-7 gap-1 px-2 text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text)]"
2182
- disabled={isTeamProvisioning}
2183
- onClick={() => setEditDialogOpen(true)}
2141
+ className="h-7 w-7 px-0 text-[var(--color-text-muted)]"
2184
2142
  >
2185
- <Pencil size={12} />
2143
+ <MoreHorizontal size={14} />
2186
2144
  </Button>
2187
- </TooltipTrigger>
2188
- <TooltipContent side="bottom">
2189
- {isTeamProvisioning ? '团队仍在编排中,暂时无法编辑' : '编辑团队'}
2190
- </TooltipContent>
2191
- </Tooltip>
2192
- {teamName !== 'default' && teamName !== 'my-project' && (
2193
- <Tooltip>
2194
- <TooltipTrigger asChild>
2195
- <Button
2196
- variant="ghost"
2197
- size="sm"
2198
- className="h-7 gap-1 px-2 text-xs text-red-400 hover:bg-red-500/10 hover:text-red-300"
2199
- onClick={handleDeleteTeam}
2145
+ </PopoverTrigger>
2146
+ <PopoverContent align="end" className="w-44 p-1">
2147
+ {data.config.projectPath && (
2148
+ <button
2149
+ type="button"
2150
+ className="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-xs text-[var(--color-text-secondary)] hover:bg-[var(--color-surface-raised)] hover:text-[var(--color-text)]"
2151
+ onClick={() => {
2152
+ setHeaderMenuOpen(false);
2153
+ setEnvDialogOpen(true);
2154
+ }}
2200
2155
  >
2201
- <Trash2 size={12} />
2202
- </Button>
2203
- </TooltipTrigger>
2204
- <TooltipContent side="bottom">删除团队</TooltipContent>
2205
- </Tooltip>
2206
- )}
2156
+ <Shield size={13} />
2157
+ 环境变量
2158
+ </button>
2159
+ )}
2160
+ {teamName !== 'default' && teamName !== 'my-project' && (
2161
+ <button
2162
+ type="button"
2163
+ className="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-xs text-red-400 hover:bg-red-500/10"
2164
+ onClick={() => {
2165
+ setHeaderMenuOpen(false);
2166
+ handleDeleteTeam();
2167
+ }}
2168
+ >
2169
+ <Trash2 size={13} />
2170
+ 删除团队
2171
+ </button>
2172
+ )}
2173
+ </PopoverContent>
2174
+ </Popover>
2207
2175
  </div>
2208
2176
  </div>
2209
2177
  {data.config.description && (
@@ -2275,10 +2243,6 @@ export const TeamDetailView = ({
2275
2243
  })()}
2276
2244
  </div>
2277
2245
 
2278
- {!data.isAlive && !isTeamProvisioning ? (
2279
- <TeamOfflineStatusBanner teamName={teamName} onLaunch={handleStartCcConnectTeam} />
2280
- ) : null}
2281
-
2282
2246
  <div ref={provisioningBannerRef}>
2283
2247
  <TeamProvisioningBanner teamName={teamName} />
2284
2248
  </div>
@@ -2616,62 +2580,6 @@ export const TeamDetailView = ({
2616
2580
  }}
2617
2581
  />
2618
2582
 
2619
- <EditTeamDialog
2620
- open={editDialogOpen}
2621
- teamName={teamName}
2622
- currentName={data.config.name}
2623
- currentDescription={data.config.description ?? ''}
2624
- currentColor={data.config.color ?? ''}
2625
- currentAgentType={data.config.agentType ?? data.harness ?? 'cursor'}
2626
- currentWorkDir={data.workDir ?? data.config.projectPath ?? ''}
2627
- currentPermissionMode={
2628
- data.config.permissionMode ?? data.permissionMode ?? 'default'
2629
- }
2630
- currentLanguage={
2631
- data.config.language ??
2632
- (typeof rawTeamSettings.language === 'string' ? rawTeamSettings.language : 'zh')
2633
- }
2634
- currentShowContextIndicator={
2635
- data.config.showContextIndicator ??
2636
- (typeof rawTeamSettings.show_context_indicator === 'boolean'
2637
- ? rawTeamSettings.show_context_indicator
2638
- : true)
2639
- }
2640
- currentReplyFooter={
2641
- data.config.replyFooter ??
2642
- (typeof rawTeamSettings.reply_footer === 'boolean'
2643
- ? rawTeamSettings.reply_footer
2644
- : true)
2645
- }
2646
- currentInjectSender={
2647
- data.config.injectSender ??
2648
- (typeof rawTeamSettings.inject_sender === 'boolean'
2649
- ? rawTeamSettings.inject_sender
2650
- : false)
2651
- }
2652
- currentManagedSources={currentManagedSources}
2653
- currentDisabledCommands={currentDisabledCommands}
2654
- currentPlatformAllowFrom={currentPlatformAllowFrom}
2655
- currentProviderRefs={data.providerRefs ?? []}
2656
- globalProviders={data.globalProviders ?? []}
2657
- currentMembers={membersWithLiveBranches.filter((m) => !isLeadMember(m))}
2658
- leadMember={membersWithLiveBranches.find((m) => isLeadMember(m)) ?? null}
2659
- resolvedMemberColorMap={resolvedMemberColorMap}
2660
- isTeamAlive={data.isAlive && !isTeamProvisioning}
2661
- isTeamProvisioning={isTeamProvisioning}
2662
- projectPath={data.config.projectPath}
2663
- savedLaunchRequest={savedLaunchRequest}
2664
- onClose={() => setEditDialogOpen(false)}
2665
- onSaved={() => {
2666
- void fetchTeams();
2667
- void selectTeam(teamName);
2668
- }}
2669
- onDeleteTeam={
2670
- teamName !== 'default' && teamName !== 'my-project' ? handleDeleteTeam : undefined
2671
- }
2672
- onRestartTeam={handleRestartTeamFromEdit}
2673
- />
2674
-
2675
2583
  <Dialog open={envDialogOpen} onOpenChange={setEnvDialogOpen}>
2676
2584
  <DialogContent className="max-h-[80vh] max-w-lg overflow-y-auto">
2677
2585
  <DialogHeader>
@@ -2863,6 +2771,14 @@ export const TeamDetailView = ({
2863
2771
  {teamAgentRuntimeWatcher}
2864
2772
  {leadContextWatcher}
2865
2773
  {renderBody()}
2774
+ <EditTeamDialog
2775
+ open={editDialogOpen}
2776
+ teamName={teamName}
2777
+ onClose={() => setEditDialogOpen(false)}
2778
+ onDeleteTeam={
2779
+ teamName !== 'default' && teamName !== 'my-project' ? handleDeleteTeam : undefined
2780
+ }
2781
+ />
2866
2782
  </>
2867
2783
  );
2868
2784
  };
@@ -79,10 +79,6 @@ export const TeamListFilterPopover = ({
79
79
  () => teams.filter((t) => aliveSet.has(t.teamName)).length,
80
80
  [teams, aliveSet]
81
81
  );
82
- const offlineCount = useMemo(
83
- () => teams.filter((t) => !aliveSet.has(t.teamName)).length,
84
- [teams, aliveSet]
85
- );
86
82
 
87
83
  return (
88
84
  <Popover>
@@ -125,18 +121,6 @@ export const TeamListFilterPopover = ({
125
121
  <span className="text-[var(--color-text-muted)]">({runningCount})</span>
126
122
  </span>
127
123
  </label>
128
- {/* eslint-disable-next-line jsx-a11y/label-has-associated-control -- Radix Checkbox renders a button, not a native input */}
129
- <label className="flex cursor-pointer items-center gap-2 rounded-md px-1 py-0.5 text-xs text-[var(--color-text-secondary)] hover:bg-[var(--color-surface-raised)]">
130
- <Checkbox
131
- checked={filter.selectedStatuses.has('offline')}
132
- onCheckedChange={() => handleStatusToggle('offline')}
133
- />
134
- <span className="flex items-center gap-1.5">
135
- <span className="size-1.5 rounded-full bg-zinc-500" />
136
- 离线
137
- <span className="text-[var(--color-text-muted)]">({offlineCount})</span>
138
- </span>
139
- </label>
140
124
  </div>
141
125
  </div>
142
126
 
@@ -85,7 +85,7 @@ function generateUniqueName(sourceName: string, existingNames: string[]): string
85
85
  }
86
86
  }
87
87
 
88
- type TeamStatus = 'active' | 'idle' | 'provisioning' | 'offline';
88
+ type TeamStatus = 'active' | 'idle' | 'provisioning';
89
89
 
90
90
  function getRecentProjects(team: TeamSummary): string[] {
91
91
  const history = team.projectPathHistory;
@@ -162,7 +162,7 @@ function renderMemberChips(members: TeamSummaryMember[], isLight: boolean): Reac
162
162
 
163
163
  function renderTeamRecentPaths(
164
164
  team: TeamSummary,
165
- status: TeamStatus,
165
+ status: TeamStatus | null,
166
166
  matchesCurrentProject: boolean,
167
167
  isLight: boolean
168
168
  ): React.JSX.Element | null {
@@ -211,7 +211,7 @@ function resolveTeamStatus(
211
211
  aliveTeams: string[],
212
212
  currentProgress: ReturnType<typeof getCurrentProvisioningProgressForTeam>,
213
213
  leadActivityByTeam: Record<string, string>
214
- ): TeamStatus {
214
+ ): TeamStatus | null {
215
215
  if (aliveTeams.includes(teamName)) {
216
216
  return leadActivityByTeam[teamName] === 'active' ? 'active' : 'idle';
217
217
  }
@@ -223,10 +223,11 @@ function resolveTeamStatus(
223
223
  ) {
224
224
  return 'provisioning';
225
225
  }
226
- return 'offline';
226
+ return null;
227
227
  }
228
228
 
229
- const StatusBadge = ({ status }: { status: TeamStatus }): React.JSX.Element => {
229
+ const StatusBadge = ({ status }: { status: TeamStatus | null }): React.JSX.Element | null => {
230
+ if (!status) return null;
230
231
  switch (status) {
231
232
  case 'active':
232
233
  return (
@@ -249,13 +250,6 @@ const StatusBadge = ({ status }: { status: TeamStatus }): React.JSX.Element => {
249
250
  启动中...
250
251
  </span>
251
252
  );
252
- case 'offline':
253
- return (
254
- <span className="inline-flex shrink-0 items-center gap-1 whitespace-nowrap rounded-full bg-zinc-500/15 px-2 py-0.5 text-[10px] font-medium text-zinc-500">
255
- <span className="size-1.5 rounded-full bg-zinc-500" />
256
- 离线
257
- </span>
258
- );
259
253
  }
260
254
  };
261
255
 
@@ -436,9 +430,8 @@ export const TeamListView = (): React.JSX.Element => {
436
430
  getCurrentProvisioningProgressForTeam(provisioningState, t.teamName),
437
431
  leadActivityByTeam
438
432
  );
439
- const isRunning = status !== 'offline';
433
+ const isRunning = status !== null;
440
434
  if (filter.selectedStatuses.has('running') && isRunning) return true;
441
- if (filter.selectedStatuses.has('offline') && !isRunning) return true;
442
435
  return false;
443
436
  });
444
437
  }
@@ -1154,24 +1147,6 @@ export const TeamListView = (): React.JSX.Element => {
1154
1147
  })()}
1155
1148
  </div>
1156
1149
  <div className="flex shrink-0 gap-1">
1157
- {status === 'offline' && team.projectPath && (
1158
- <Tooltip>
1159
- <TooltipTrigger asChild>
1160
- <button
1161
- type="button"
1162
- className="shrink-0 rounded p-1 text-[var(--color-text-muted)] opacity-0 transition-opacity hover:bg-emerald-500/10 hover:text-emerald-300 disabled:opacity-50 group-hover:opacity-100"
1163
- onClick={(e) => handleLaunchTeam(team.teamName, team.projectPath, e)}
1164
- disabled={launchingTeamName === team.teamName}
1165
- aria-label="启动团队"
1166
- >
1167
- <Play size={14} fill="currentColor" />
1168
- </button>
1169
- </TooltipTrigger>
1170
- <TooltipContent side="bottom">
1171
- {launchingTeamName === team.teamName ? '启动中…' : '启动团队'}
1172
- </TooltipContent>
1173
- </Tooltip>
1174
- )}
1175
1150
  {!team.pendingCreate && (
1176
1151
  <Tooltip>
1177
1152
  <TooltipTrigger asChild>