fix(team): block lead relaunches and clarify log counts

This commit is contained in:
iliya 2026-04-07 12:59:42 +03:00
parent 7f737f985b
commit dd6f50cad6
3 changed files with 33 additions and 9 deletions

View file

@ -171,7 +171,8 @@ const FS_MONITOR_POLL_MS = 2000;
const TASK_WAIT_FALLBACK_MS = 15_000; const TASK_WAIT_FALLBACK_MS = 15_000;
const STALL_CHECK_INTERVAL_MS = 10_000; const STALL_CHECK_INTERVAL_MS = 10_000;
const STALL_WARNING_THRESHOLD_MS = 20_000; const STALL_WARNING_THRESHOLD_MS = 20_000;
const APP_TEAM_RUNTIME_DISALLOWED_TOOLS = 'TeamDelete,TodoWrite,TaskCreate,TaskUpdate'; const APP_TEAM_RUNTIME_DISALLOWED_TOOLS =
'TeamDelete,TodoWrite,TaskCreate,TaskUpdate,Agent,mcp__agent-teams__team_launch,mcp__agent-teams__team_stop';
const TEAM_JSON_READ_TIMEOUT_MS = 5_000; const TEAM_JSON_READ_TIMEOUT_MS = 5_000;
const TEAM_CONFIG_MAX_BYTES = 10 * 1024 * 1024; const TEAM_CONFIG_MAX_BYTES = 10 * 1024 * 1024;
const TEAM_INBOX_MAX_BYTES = 2 * 1024 * 1024; const TEAM_INBOX_MAX_BYTES = 2 * 1024 * 1024;

View file

@ -50,6 +50,8 @@ export const ClaudeLogsPanel = ({
pendingNewCount, pendingNewCount,
isAlive, isAlive,
filteredText, filteredText,
totalGroupCount,
filteredGroupCount,
showMoreVisible, showMoreVisible,
searchQuery, searchQuery,
setSearchQuery, setSearchQuery,
@ -70,10 +72,17 @@ export const ClaudeLogsPanel = ({
{/* Toolbar */} {/* Toolbar */}
<div className="flex items-center justify-between gap-2 pb-2"> <div className="flex items-center justify-between gap-2 pb-2">
<span className="text-[11px] text-[var(--color-text-muted)]"> <span className="text-[11px] text-[var(--color-text-muted)]">
{data.total > 0 ? ( {totalGroupCount > 0 ? (
<> <>
<span className="font-mono">{Math.min(data.total, data.lines.length)}</span> of{' '} <span className="font-mono">{filteredGroupCount}</span> of{' '}
<span className="font-mono">{data.total}</span> <span className="font-mono">{totalGroupCount}</span> groups
{data.total !== totalGroupCount ? (
<>
{' '}
<span aria-hidden="true">·</span> <span className="font-mono">{data.total}</span>{' '}
raw lines
</>
) : null}
</> </>
) : isAlive ? ( ) : isAlive ? (
'No logs yet.' 'No logs yet.'

View file

@ -19,6 +19,7 @@ import {
setTeamClaudeLogsSidebarUiState, setTeamClaudeLogsSidebarUiState,
} from './sidebar/teamSidebarUiState'; } from './sidebar/teamSidebarUiState';
import { DEFAULT_CLAUDE_LOGS_FILTER } from './ClaudeLogsFilterPopover'; import { DEFAULT_CLAUDE_LOGS_FILTER } from './ClaudeLogsFilterPopover';
import { parseStreamJsonToGroups } from '@renderer/utils/streamJsonParser';
import type { ClaudeLogsFilterState } from './ClaudeLogsFilterPopover'; import type { ClaudeLogsFilterState } from './ClaudeLogsFilterPopover';
import type { ClaudeLogsViewerState } from './CliLogsRichView'; import type { ClaudeLogsViewerState } from './CliLogsRichView';
@ -59,6 +60,8 @@ export interface ClaudeLogsController {
filteredText: string; filteredText: string;
online: boolean; online: boolean;
badge: number | undefined; badge: number | undefined;
totalGroupCount: number;
filteredGroupCount: number;
showMoreVisible: boolean; showMoreVisible: boolean;
lastLogPreview: LastLogPreview | null; lastLogPreview: LastLogPreview | null;
@ -585,7 +588,6 @@ export function useClaudeLogsController(teamName: string): ClaudeLogsController
// ── Computed values ─────────────────────────────────────────────────── // ── Computed values ───────────────────────────────────────────────────
const online = useMemo(() => isRecent(data.updatedAt), [data.updatedAt]); const online = useMemo(() => isRecent(data.updatedAt), [data.updatedAt]);
const badge = data.total > 0 ? data.total : undefined;
const showMoreVisible = data.hasMore || loadingMore; const showMoreVisible = data.hasMore || loadingMore;
const lastLogPreview = useMemo( const lastLogPreview = useMemo(
@ -593,6 +595,8 @@ export function useClaudeLogsController(teamName: string): ClaudeLogsController
[data.lines] [data.lines]
); );
const normalizedText = useMemo(() => normalizeToStreamJsonText(data.lines), [data.lines]);
const filteredText = useMemo(() => { const filteredText = useMemo(() => {
if (data.lines.length === 0) return ''; if (data.lines.length === 0) return '';
const isDefault = const isDefault =
@ -601,11 +605,19 @@ export function useClaudeLogsController(teamName: string): ClaudeLogsController
[...DEFAULT_CLAUDE_LOGS_FILTER.streams].every((s) => filter.streams.has(s)) && [...DEFAULT_CLAUDE_LOGS_FILTER.streams].every((s) => filter.streams.has(s)) &&
[...DEFAULT_CLAUDE_LOGS_FILTER.kinds].every((k) => filter.kinds.has(k)); [...DEFAULT_CLAUDE_LOGS_FILTER.kinds].every((k) => filter.kinds.has(k));
if (!searchQuery.trim() && isDefault) { if (!searchQuery.trim() && isDefault) return normalizedText;
return normalizeToStreamJsonText(data.lines);
}
return filterStreamJsonText(data.lines, searchQuery, filter); return filterStreamJsonText(data.lines, searchQuery, filter);
}, [data.lines, searchQuery, filter]); }, [data.lines, normalizedText, searchQuery, filter]);
const totalGroupCount = useMemo(
() => parseStreamJsonToGroups(normalizedText).length,
[normalizedText]
);
const filteredGroupCount = useMemo(
() => parseStreamJsonToGroups(filteredText).length,
[filteredText]
);
const badge = totalGroupCount > 0 ? totalGroupCount : undefined;
// ── Container ref callback ──────────────────────────────────────────── // ── Container ref callback ────────────────────────────────────────────
const containerRefCallback = useCallback((el: HTMLDivElement | null) => { const containerRefCallback = useCallback((el: HTMLDivElement | null) => {
@ -647,6 +659,8 @@ export function useClaudeLogsController(teamName: string): ClaudeLogsController
filteredText, filteredText,
online, online,
badge, badge,
totalGroupCount,
filteredGroupCount,
showMoreVisible, showMoreVisible,
lastLogPreview, lastLogPreview,
searchQuery, searchQuery,