From 9152d8fa6197f55bda94b364e9db08016dd90809 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Fri, 17 Jul 2026 14:25:30 -0700 Subject: [PATCH] FN-8229: remove background AI tasks pill Replace the redundant footer AI session control with progress and action visibility in the session notification banner. - Delete the BackgroundTasksIndicator component, styles, footer wiring, and obsolete translations. - Surface non-planning generating and retained error sessions through the notification banner while leaving Planning in its dedicated view. - Update session lifecycle, localization, documentation, and regression coverage. Files changed: .../fn-8229-remove-ai-background-tasks-pill.md | 7 + docs/dashboard-guide.md | 4 +- packages/dashboard/README.md | 1 - packages/dashboard/app/App.tsx | 28 +-- .../app/__tests__/css-hygiene-scan.test.ts | 2 - .../dashboard-component-color-tokenization.test.ts | 1 - packages/dashboard/app/api/legacy.ts | 2 +- .../app/components/BackgroundTasksIndicator.css | 130 ------------- .../app/components/BackgroundTasksIndicator.tsx | 210 --------------------- .../dashboard/app/components/ExecutorStatusBar.css | 3 - .../dashboard/app/components/ExecutorStatusBar.tsx | 30 +-- .../app/components/SessionNotificationBanner.css | 10 + .../app/components/SessionNotificationBanner.tsx | 52 ++++- .../app/components/SubtaskBreakdownModal.tsx | 7 +- .../app/components/__tests__/App.test.tsx | 11 +- .../__tests__/ExecutorStatusBar.test.tsx | 1 - .../__tests__/SessionNotificationBanner.test.tsx | 88 ++++----- .../components/__tests__/utility-mobile.test.tsx | 191 +------------------ .../app/components/dashboard/DashboardBanners.tsx | 8 +- .../dashboard/__tests__/DashboardBanners.test.tsx | 30 ++- .../hooks/__tests__/useBackgroundSessions.test.ts | 21 ++- .../dashboard/app/hooks/useBackgroundSessions.ts | 21 ++- .../app/utils/__tests__/appLifecycle.test.ts | 61 ++---- packages/dashboard/app/utils/appLifecycle.ts | 16 +- packages/dashboard/src/routes.ts | 2 +- packages/i18n/locales/en/app.json | 33 +--- packages/i18n/locales/es/app.json | 44 ++--- packages/i18n/locales/fr/app.json | 44 ++--- packages/i18n/locales/ko/app.json | 44 ++--- packages/i18n/locales/zh-CN/app.json | 44 ++--- packages/i18n/locales/zh-TW/app.json | 44 ++--- packages/i18n/src/resources.d.ts | 48 ++--- 32 files changed, 316 insertions(+), 922 deletions(-) Fusion-Task-Id: FN-8229 Fusion-Task-Lineage: a232fb04-08ff-4f0a-a440-e94545243e61 Co-authored-by: Fusion (runfusion.ai) --- ...fn-8229-remove-ai-background-tasks-pill.md | 7 + docs/dashboard-guide.md | 4 +- packages/dashboard/README.md | 1 - packages/dashboard/app/App.tsx | 28 +-- .../app/__tests__/css-hygiene-scan.test.ts | 2 - ...board-component-color-tokenization.test.ts | 1 - packages/dashboard/app/api/legacy.ts | 2 +- .../components/BackgroundTasksIndicator.css | 130 ----------- .../components/BackgroundTasksIndicator.tsx | 210 ------------------ .../app/components/ExecutorStatusBar.css | 3 - .../app/components/ExecutorStatusBar.tsx | 30 +-- .../components/SessionNotificationBanner.css | 10 + .../components/SessionNotificationBanner.tsx | 52 ++++- .../app/components/SubtaskBreakdownModal.tsx | 7 +- .../app/components/__tests__/App.test.tsx | 11 +- .../__tests__/ExecutorStatusBar.test.tsx | 1 - .../SessionNotificationBanner.test.tsx | 88 +++----- .../__tests__/utility-mobile.test.tsx | 191 +--------------- .../components/dashboard/DashboardBanners.tsx | 8 +- .../__tests__/DashboardBanners.test.tsx | 30 ++- .../__tests__/useBackgroundSessions.test.ts | 21 +- .../app/hooks/useBackgroundSessions.ts | 21 +- .../app/utils/__tests__/appLifecycle.test.ts | 61 ++--- packages/dashboard/app/utils/appLifecycle.ts | 16 +- packages/dashboard/src/routes.ts | 2 +- packages/i18n/locales/en/app.json | 33 +-- packages/i18n/locales/es/app.json | 44 ++-- packages/i18n/locales/fr/app.json | 44 ++-- packages/i18n/locales/ko/app.json | 44 ++-- packages/i18n/locales/zh-CN/app.json | 44 ++-- packages/i18n/locales/zh-TW/app.json | 44 ++-- packages/i18n/src/resources.d.ts | 48 ++-- 32 files changed, 316 insertions(+), 922 deletions(-) create mode 100644 .changeset/fn-8229-remove-ai-background-tasks-pill.md delete mode 100644 packages/dashboard/app/components/BackgroundTasksIndicator.css delete mode 100644 packages/dashboard/app/components/BackgroundTasksIndicator.tsx diff --git a/.changeset/fn-8229-remove-ai-background-tasks-pill.md b/.changeset/fn-8229-remove-ai-background-tasks-pill.md new file mode 100644 index 0000000000..94303f0f01 --- /dev/null +++ b/.changeset/fn-8229-remove-ai-background-tasks-pill.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": minor +--- + +summary: Remove the footer AI session pill; background progress now appears in the session notification banner. +category: feature +dev: Deletes BackgroundTasksIndicator and its footer wiring. The banner now shows non-planning generating and retained error sessions; planning remains in its docked view and nav badge, while cli-agent progress is observational to avoid a dead Resume action. diff --git a/docs/dashboard-guide.md b/docs/dashboard-guide.md index bb12624fdd..81de124e65 100644 --- a/docs/dashboard-guide.md +++ b/docs/dashboard-guide.md @@ -490,9 +490,9 @@ Use **Show worktree grouping on the board** in **Settings → Worktrees** when y Planning is a desktop/tablet left-sidebar main-content destination after **Command Center**. It opens the planning-session list and composer in the main content region; mobile continues to use the compact planning entry points. Planning Mode now includes branch controls on the summary screen before you create a task. - + -When a Planning session is awaiting your input, use its **Background Tasks** footer row or **Resume** banner action to open the docked Planning view and reconnect to that session. The Planning navigation item also opens the docked Planning view; its yellow needs-input dot is visible on the desktop left sidebar and mobile More controls. +When a Planning session needs your input or needs attention, open the docked Planning view from the **Planning** navigation item. Its yellow needs-input dot is visible on the desktop left sidebar and mobile More controls. Non-planning in-progress, needs-input, and error sessions appear in the session notification banner, where available Resume actions reconnect to their matching surface. When Planning AI generation appears stuck, Planning Mode automatically retries the same session up to three times and shows **Retrying… (attempt N of 3)** before falling back to the permanent **Retry**/**Dismiss** error panel. Any successful question or summary progress resets the automatic retry budget. diff --git a/packages/dashboard/README.md b/packages/dashboard/README.md index 63abf8e444..43481d76ca 100644 --- a/packages/dashboard/README.md +++ b/packages/dashboard/README.md @@ -260,7 +260,6 @@ In addition to the global mobile foundation, several power-user surfaces now inc - Tree-view indentation is reduced (`.agent-tree__indent--1..4`) to prevent horizontal overflow at deeper hierarchy levels. - **Utility components** - - **BackgroundTasksIndicator** popover switches to fixed viewport anchoring on mobile (`left/right: 8px`, `bottom: 40px`) so it is not clipped by parent containers. - **ExecutorStatusBar** mobile layout includes tighter spacing and overflow guards (`min-width: 0`, hidden overflow in segments) for narrow screens. - **ActiveAgentsPanel** grid stacks to one column on mobile (`.active-agents-grid { grid-template-columns: 1fr; }`). - **ToastContainer** shifts above footer surfaces with safe-area awareness (`bottom: calc(44px + env(safe-area-inset-bottom, 0px))`, full-width toasts). diff --git a/packages/dashboard/app/App.tsx b/packages/dashboard/app/App.tsx index 15f3086eba..e5abd27a1b 100644 --- a/packages/dashboard/app/App.tsx +++ b/packages/dashboard/app/App.tsx @@ -93,8 +93,7 @@ import { resolveDesktopShellRedirectTarget, requiresNativeShellOnboarding, shouldShowFirstEverBootLoader, - isSessionNeedingInputForBanner, - isPlanningAwaitingInput, + shouldShowSessionInBanner, getCliActionDisabledReasonForBanner, executeCliSessionBannerAction, } from "./utils/appLifecycle"; @@ -106,7 +105,7 @@ export { requiresNativeShellOnboarding, shouldShowFirstEverBootLoader, isSessionNeedingInputForBanner, - isPlanningAwaitingInput, + shouldShowSessionInBanner, getCliActionDisabledReasonForBanner, executeCliSessionBannerAction, } from "./utils/appLifecycle"; @@ -382,18 +381,14 @@ function AppInner() { const { themeMode, colorTheme, dashboardFontScalePct, shadcnCustomColors, resolvedThemeMode, setThemeMode, setColorTheme, setDashboardFontScalePct, setShadcnCustomColors } = useTheme(); // Background AI sessions - required before useModalManager - const { sessions: bgSessions, generating: bgGenerating, needsInput: bgNeedsInput, planningSessions: bgPlanningSessions, dismissSession: bgDismiss } = useBackgroundSessions(currentProject?.id); + const { sessions: bgSessions, planningSessions: bgPlanningSessions } = useBackgroundSessions(currentProject?.id); /* - * FNXC:SessionBanner 2026-06-14-19:32: - * CLI agent sessions use `waiting_on_input` and `needs_attention` to represent user-actionable states. The banner feed must include those statuses in addition to the legacy planning-session statuses so visible CLI actions cannot be silently hidden from users. - * - * FNXC:SessionBanner 2026-07-05-00:00: - * Planning `awaiting_input` sessions are excluded from the banner feed: the banner's Resume button did not - * reliably redirect into Planning Mode. That signal now surfaces as a yellow `status-dot--pending` nav badge - * (see `planningNeedsInput` below) whose click target is the already-correct `planning` view navigation. - * Planning sessions in `error` status are unaffected and still render in the banner. + * FNXC:SessionBanner 2026-07-16-20:55: + * FN-8229 replaces the removed footer AI pill with this banner feed. It keeps + * non-planning generating and error sessions observable while Planning owns + * all of its statuses through the docked view and navigation badge. */ - const sessionsNeedingInput = bgSessions.filter((s) => isSessionNeedingInputForBanner(s) && !isPlanningAwaitingInput(s)); + const sessionsNeedingInput = bgSessions.filter(shouldShowSessionInBanner); const sessionBannersHidden = useSessionBannersHidden(); const planningNeedsInput = bgPlanningSessions.some((s) => s.status === "awaiting_input"); @@ -1275,7 +1270,7 @@ function AppInner() { // Dismissing the "needs input" banner only hides the prompt — it must NOT // delete the underlying session. Sessions remain accessible from the - // Planning modal's sidebar (or the AI background tasks pill) so the user + // Planning modal's sidebar or the session notification banner so the user // can return to them later. The banner already tracks dismissals locally // via its own `dismissedIds` set, so these handlers are intentional no-ops. const handleDismissNeedingInputSession = useCallback(() => { @@ -1752,11 +1747,6 @@ function AppInner() { projectId={currentProject.id} taskStuckTimeoutMs={taskStuckTimeoutMs} staleHighFanoutBlockerAgeThresholdMs={staleHighFanoutBlockerAgeThresholdMs} - backgroundSessions={bgSessions} - backgroundGenerating={bgGenerating} - backgroundNeedsInput={bgNeedsInput} - onOpenBackgroundSession={handleOpenBackgroundSession} - onDismissBackgroundSession={bgDismiss} lastFetchTimeMs={lastFetchTimeMs} currentProjectPath={currentProject.path} onOpenProjectDirectory={handleOpenProjectDirectory} diff --git a/packages/dashboard/app/__tests__/css-hygiene-scan.test.ts b/packages/dashboard/app/__tests__/css-hygiene-scan.test.ts index f0e927b452..26151242cf 100644 --- a/packages/dashboard/app/__tests__/css-hygiene-scan.test.ts +++ b/packages/dashboard/app/__tests__/css-hygiene-scan.test.ts @@ -15,7 +15,6 @@ const recentlyLandedResponsiveFiles = [ const recentlyLandedHygieneFiles = [ ...recentlyLandedResponsiveFiles, "MobileWorkflowGraphView.css", - "BackgroundTasksIndicator.css", "PullRequestView.css", "TaskCard.css", "TaskFieldsSection.css", @@ -69,7 +68,6 @@ function extractSelectorBlocks(source: string, selector: string): string[] { describe("component CSS hygiene scan regressions", () => { it("keeps fixed text-on-accent CSS on --cta-text instead of hardcoded white", () => { const fixedSelectors: Array<[string, string]> = [ - ["BackgroundTasksIndicator.css", ".background-tasks-indicator__pill--attention"], ["PullRequestView.css", ".pr-action--merge-confirm"], ["TaskCard.css", ".card-field-badge--boolean"], ["TaskFieldsSection.css", ".task-field-chip.is-active"], diff --git a/packages/dashboard/app/__tests__/dashboard-component-color-tokenization.test.ts b/packages/dashboard/app/__tests__/dashboard-component-color-tokenization.test.ts index faf53cc80a..d230fa5f5f 100644 --- a/packages/dashboard/app/__tests__/dashboard-component-color-tokenization.test.ts +++ b/packages/dashboard/app/__tests__/dashboard-component-color-tokenization.test.ts @@ -8,7 +8,6 @@ const root = resolve(__dirname, "../components"); const auditedCompliant = ["ChatView.css", "MobileNavBar.css", "ListView.css", "WorkflowResultsTab.css"]; const cleanedFiles = [ "AgentReflectionsTab.css", - "BackgroundTasksIndicator.css", "CliBinaryInstallBanner.css", "CliBinaryPanel.css", "FileMentionPopup.css", diff --git a/packages/dashboard/app/api/legacy.ts b/packages/dashboard/app/api/legacy.ts index b6d9bed007..1594408419 100644 --- a/packages/dashboard/app/api/legacy.ts +++ b/packages/dashboard/app/api/legacy.ts @@ -8420,7 +8420,7 @@ export function reorderTodoItems(listId: string, itemIds: string[], projectId?: }); } -// ── AI Sessions (Background Tasks) ───────────────────────────────────────── +// ── AI Sessions ──────────────────────────────────────────────────────────── /** * Needs-attention variants for a CLI agent session (CLI Agent Executor, U11). diff --git a/packages/dashboard/app/components/BackgroundTasksIndicator.css b/packages/dashboard/app/components/BackgroundTasksIndicator.css deleted file mode 100644 index 41af636456..0000000000 --- a/packages/dashboard/app/components/BackgroundTasksIndicator.css +++ /dev/null @@ -1,130 +0,0 @@ -/* === Background Tasks Indicator === */ -.background-tasks-indicator { - position: relative; -} - -.background-tasks-indicator__pill { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 1px 8px; - border-radius: 12px; - border: 1px solid var(--border); - background: var(--surface); - color: var(--text-muted); - cursor: pointer; - font-size: 12px; - font-weight: 500; - line-height: 18px; - white-space: nowrap; - transition: background var(--transition-fast); -} - -.background-tasks-indicator__pill:hover:not(.background-tasks-indicator__pill--attention) { - background: color-mix(in srgb, var(--surface) 85%, var(--text-muted)); -} - -.background-tasks-indicator__pill--attention { - background: var(--triage); - color: var(--cta-text); - border-color: var(--triage); -} - -.background-tasks-indicator__pill--attention:hover { - background: color-mix(in srgb, var(--triage) 85%, #000); -} - -.background-tasks-indicator__popover { - position: absolute; - bottom: calc(100% + 8px); - left: 0; - min-width: 280px; - max-width: 360px; - background: var(--surface); - border: 1px solid var(--border); - border-radius: 8px; - box-shadow: var(--shadow-md); - z-index: 1000; - overflow: hidden; -} - -.background-tasks-indicator__popover-header { - padding: 8px 12px; - border-bottom: 1px solid var(--border); - font-size: 12px; - font-weight: 600; - color: var(--text-muted); -} - -.background-tasks-indicator__popover-list { - max-height: 240px; - overflow-y: auto; -} - -.background-tasks-indicator__item { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 12px; - border-bottom: 1px solid var(--border); - cursor: pointer; -} - -.background-tasks-indicator__item:last-child { - border-bottom: none; -} - -.background-tasks-indicator__session-icon { - flex-shrink: 0; - color: var(--text-muted); -} - -.background-tasks-indicator__session-content { - flex: 1; - min-width: 0; -} - -.background-tasks-indicator__session-title { - font-size: 13px; - font-weight: 500; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.background-tasks-indicator__session-meta { - font-size: calc(var(--space-sm) + var(--space-xs) * 0.75); - color: var(--text-muted); -} - -.background-tasks-indicator__item-dismiss { - flex-shrink: 0; - background: none; - border: none; - cursor: pointer; - padding: 2px; - color: var(--text-muted); - border-radius: 4px; -} - -@media (max-width: 768px) { - .background-tasks-indicator__popover { - position: fixed; - /* Add iOS home-indicator inset so the popover doesn't sit inside the - indicator zone on iPhone with viewport-fit=cover. */ - bottom: calc( - var(--mobile-nav-height) + - env(safe-area-inset-bottom, 0px) + - var(--standalone-bottom-gap) - ); - left: max(8px, env(safe-area-inset-left, 0px)); - right: max(8px, env(safe-area-inset-right, 0px)); - min-width: auto; - max-width: none; - } - - .background-tasks-indicator__pill { - min-height: 28px; - } -} - diff --git a/packages/dashboard/app/components/BackgroundTasksIndicator.tsx b/packages/dashboard/app/components/BackgroundTasksIndicator.tsx deleted file mode 100644 index 485d27e842..0000000000 --- a/packages/dashboard/app/components/BackgroundTasksIndicator.tsx +++ /dev/null @@ -1,210 +0,0 @@ -import "./BackgroundTasksIndicator.css"; -import { useState, useRef, useEffect, useMemo } from "react"; -import { Lightbulb, Layers, Target, Terminal, Loader2, HelpCircle, X, AlertCircle } from "lucide-react"; -import { useTranslation } from "react-i18next"; -import type { AiSessionSummary } from "../api"; - -interface BackgroundTasksIndicatorProps { - sessions: AiSessionSummary[]; - generating: number; - needsInput: number; - onOpenSession: (session: AiSessionSummary) => void; - onDismissSession: (id: string) => void; -} - -const TYPE_ICONS = { - planning: Lightbulb, - subtask: Layers, - mission_interview: Target, - milestone_interview: Target, - slice_interview: Target, - "cli-agent": Terminal, -} as const; - -export function BackgroundTasksIndicator({ - sessions, - generating, - needsInput, - onOpenSession, - onDismissSession, -}: BackgroundTasksIndicatorProps) { - const { t } = useTranslation("app"); - const [popoverOpen, setPopoverOpen] = useState(false); - const [recentlyUpdated, setRecentlyUpdated] = useState>(new Set()); - const containerRef = useRef(null); - const previousSessionSignatureRef = useRef>(new Map()); - const clearUpdatedTimerRef = useRef | null>(null); - - - // Type labels that are translatable - const TYPE_LABELS = useMemo( - () => ({ - planning: t("backgroundTasks.typeLabel.planning", "Planning"), - subtask: t("backgroundTasks.typeLabel.subtask", "Subtask Breakdown"), - mission_interview: t("backgroundTasks.typeLabel.missionInterview", "Mission Interview"), - milestone_interview: t("backgroundTasks.typeLabel.milestoneInterview", "Milestone Interview"), - slice_interview: t("backgroundTasks.typeLabel.sliceInterview", "Slice Interview"), - "cli-agent": t("backgroundTasks.typeLabel.cliAgent", "CLI Agent"), - }), - [t], - ); - - // Close popover on outside click - useEffect(() => { - if (!popoverOpen) return; - const handler = (e: MouseEvent) => { - if (containerRef.current && !containerRef.current.contains(e.target as Node)) { - setPopoverOpen(false); - } - }; - document.addEventListener("mousedown", handler); - return () => document.removeEventListener("mousedown", handler); - }, [popoverOpen]); - - /* - FNXC:PlanningMultiTab 2026-07-14-00:00: - No tab-ownership concept remains: AI interview sessions are multi-tab, so every session opens - directly with no "active in another tab" gate, confirm prompt, or lock badge. Item animation - keys off server-derived status/timestamp only. - */ - // Animate per-item changes when session status/timestamp changes. - useEffect(() => { - const changed = new Set(); - const nextSignature = new Map(); - - for (const session of sessions) { - const signature = [session.status, session.updatedAt].join("|"); - - const previous = previousSessionSignatureRef.current.get(session.id); - if (previous && previous !== signature) { - changed.add(session.id); - } - - nextSignature.set(session.id, signature); - } - - previousSessionSignatureRef.current = nextSignature; - - if (changed.size === 0) { - return; - } - - setRecentlyUpdated(changed); - - if (clearUpdatedTimerRef.current) { - clearTimeout(clearUpdatedTimerRef.current); - } - - clearUpdatedTimerRef.current = setTimeout(() => { - setRecentlyUpdated(new Set()); - clearUpdatedTimerRef.current = null; - }, 500); - - return () => { - if (clearUpdatedTimerRef.current) { - clearTimeout(clearUpdatedTimerRef.current); - clearUpdatedTimerRef.current = null; - } - }; - }, [sessions]); - - if (sessions.length === 0) return null; - - const total = sessions.length; - const hasAttention = needsInput > 0; - - return ( -
- - - {popoverOpen && ( -
-
- {t("backgroundTasks.popoverHeader", "Background Tasks")} -
-
- {sessions.map((session) => { - const Icon = TYPE_ICONS[session.type]; - const isGenerating = session.status === "generating"; - const isAwaiting = session.status === "awaiting_input"; - const isError = session.status === "error"; - const isUpdated = recentlyUpdated.has(session.id); - - return ( -
{ - onOpenSession(session); - setPopoverOpen(false); - }} - > - {isError ? ( - - ) : ( - - )} -
-
- {session.title} -
-
- {isError ? t("backgroundTasks.status.failed", "Failed") : TYPE_LABELS[session.type]} - {isGenerating && ` — ${t("backgroundTasks.status.generating", "generating...")}`} - {isAwaiting && ` — ${t("backgroundTasks.status.needsInput", "needs input")}`} -
-
- {isGenerating && ( - - )} - {isAwaiting && ( - - )} - -
- ); - })} -
-
- )} -
- ); -} diff --git a/packages/dashboard/app/components/ExecutorStatusBar.css b/packages/dashboard/app/components/ExecutorStatusBar.css index 5b3e06ac44..5be63cc167 100644 --- a/packages/dashboard/app/components/ExecutorStatusBar.css +++ b/packages/dashboard/app/components/ExecutorStatusBar.css @@ -463,9 +463,6 @@ FN-6887 makes the footer status bar the canonical desktop/tablet terminal launch max-width: min(26ch, 30vw); } - .background-tasks-indicator { - flex-shrink: 0; - } } /* Light theme support */ diff --git a/packages/dashboard/app/components/ExecutorStatusBar.tsx b/packages/dashboard/app/components/ExecutorStatusBar.tsx index 5da86b8d3a..410a428834 100644 --- a/packages/dashboard/app/components/ExecutorStatusBar.tsx +++ b/packages/dashboard/app/components/ExecutorStatusBar.tsx @@ -13,8 +13,7 @@ import { computeBlockerFanoutMap } from "../hooks/useBlockerFanout"; import { useExecutorStats } from "../hooks/useExecutorStats"; import { isLikelyTabSuspensionError } from "../hooks/visibilitySuspension"; import { LoadingSpinner } from "./LoadingSpinner"; -import type { ExecutorState, AiSessionSummary } from "../api"; -import { BackgroundTasksIndicator } from "./BackgroundTasksIndicator"; +import type { ExecutorState } from "../api"; import { EngineControlMenu, type EngineControlMenuHandle } from "./EngineControlMenu"; import { TerminalLauncher } from "./TerminalLauncher"; import { useViewportMode } from "../hooks/useViewportMode"; @@ -66,12 +65,6 @@ interface ExecutorStatusBarProps { taskStuckTimeoutMs?: number; /** Age threshold in milliseconds before high fan-out blockers escalate in dashboard surfaces. */ staleHighFanoutBlockerAgeThresholdMs?: number; - /** Background AI sessions */ - backgroundSessions?: AiSessionSummary[]; - backgroundGenerating?: number; - backgroundNeedsInput?: number; - onOpenBackgroundSession?: (session: AiSessionSummary) => void; - onDismissBackgroundSession?: (id: string) => void; /** Timestamp (ms) when task data was last confirmed fresh from the server. Used for freshness-aware stuck detection. */ lastFetchTimeMs?: number; /** Absolute path for the currently selected project directory. */ @@ -148,7 +141,7 @@ function getStateDisplay(state: ExecutorState, t: TFunction<"app">): { label: st * - Executor state badge (idle/running/paused/stopped) * - Last activity timestamp */ -export function ExecutorStatusBar({ tasks, projectId, taskStuckTimeoutMs, staleHighFanoutBlockerAgeThresholdMs, backgroundSessions, backgroundGenerating, backgroundNeedsInput, onOpenBackgroundSession, onDismissBackgroundSession, lastFetchTimeMs, currentProjectPath, onOpenProjectDirectory, keyboardOpen, hideWhenKeyboardOpen, onToggleTerminal, onOpenScripts, onRunScript, quickChatButtonMode = "off", onOpenQuickChat }: ExecutorStatusBarProps) { +export function ExecutorStatusBar({ tasks, projectId, taskStuckTimeoutMs, staleHighFanoutBlockerAgeThresholdMs, lastFetchTimeMs, currentProjectPath, onOpenProjectDirectory, keyboardOpen, hideWhenKeyboardOpen, onToggleTerminal, onOpenScripts, onRunScript, quickChatButtonMode = "off", onOpenQuickChat }: ExecutorStatusBarProps) { const { t } = useTranslation("app"); const viewportMode = useViewportMode(); const isMobile = viewportMode === "mobile"; @@ -282,19 +275,12 @@ export function ExecutorStatusBar({ tasks, projectId, taskStuckTimeoutMs, staleH role="status" aria-label={t("executor.status", "Executor status")} > - {/* Background AI tasks indicator */} - {backgroundSessions && backgroundSessions.length > 0 && onOpenBackgroundSession && onDismissBackgroundSession && ( - <> - -