mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-06 16:34:36 +00:00
Dismiss a failed agent's red dot by reading it (#8831)
* fix(sidebar): clear the failed status once the error is read Reading an errored agent already cleared its error attention, but the state bucket also mapped lifecycle status "error" to failed. Lifecycle only leaves "error" when the next turn starts, so the red dot and the Failed group stuck until the agent was prompted again. The failed bucket now follows unread error attention, the same way the green dot follows unread finished attention; lifecycle status stays "error". Because failed now depends on attention, a failure must replace unread finished attention, otherwise a reload that fails on an unread agent would show green. * fix(sidebar): keep failed subagents red and let read failures be marked unread The failed bucket now follows unread error attention, which broke three places that relied on lifecycle "error" alone: - Subagent track rows and provider-subagent tabs have no read state of their own, so failed children lost their red mark. They now map the child's lifecycle directly. - A read errored workspace became "done" and offered Mark as unread, but the daemon only accepted idle or closed agents. Marking it unread now restores error attention. - A reload that failed again while the lifecycle was already "error" raised no new attention. A failed reload now raises error attention directly instead of relying on a lifecycle transition.
This commit is contained in:
@@ -31,7 +31,7 @@ import {
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { PendingPermission } from "@/types/shared";
|
||||
import type { StreamItem } from "@/types/stream";
|
||||
import { deriveSidebarStateBucket } from "@/utils/sidebar-agent-state";
|
||||
import { deriveSubagentStatusBucket } from "@/subagents";
|
||||
import { TIMELINE_FETCH_PAGE_SIZE } from "@/timeline/timeline-fetch-policy";
|
||||
import type { TurnPresentation } from "@/timeline/turn-liveness";
|
||||
import { buildWorkspaceTabPersistenceKey } from "@/workspace-tabs/model";
|
||||
@@ -107,10 +107,7 @@ function useProviderSubagentDescriptor(
|
||||
titleState: descriptor ? "ready" : "loading",
|
||||
icon: useProviderIcon(provider, context.serverId),
|
||||
statusBucket: descriptor
|
||||
? deriveSidebarStateBucket({
|
||||
status: providerSubagentLifecycleStatus(descriptor.status),
|
||||
requiresAttention: descriptor.status === "failed",
|
||||
})
|
||||
? deriveSubagentStatusBucket(providerSubagentLifecycleStatus(descriptor.status))
|
||||
: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,3 +10,4 @@ export {
|
||||
type UseArchiveFinishedSubagentsInput,
|
||||
} from "./use-archive-finished";
|
||||
export { useSubagentSheetTab } from "./sheet-tab";
|
||||
export { deriveSubagentStatusBucket } from "./track-presentation";
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { TFunction } from "i18next";
|
||||
import type { ComposerTrackPillSegment } from "@/composer/tracks";
|
||||
import type { SidebarStateBucket } from "@/utils/sidebar-agent-state";
|
||||
import { deriveSidebarStateBucket, STATUS_BUCKET_ORDER } from "@/utils/sidebar-agent-state";
|
||||
import type { AgentLifecycleStatus } from "@getpaseo/protocol/agent-lifecycle";
|
||||
import { STATUS_BUCKET_ORDER } from "@/utils/sidebar-agent-state";
|
||||
import type { SubagentRow } from "./select";
|
||||
import { isFinishedSubagent } from "./archive-finished";
|
||||
import { providerSubagentLifecycleStatus } from "./provider-store";
|
||||
@@ -14,6 +15,16 @@ function presentationStatus(row: SubagentRow) {
|
||||
return providerSubagentLifecycleStatus(row.status);
|
||||
}
|
||||
|
||||
/**
|
||||
* A child's mark reports what it is doing, not whether anyone read it: the track is where a
|
||||
* failed child stays visible after the parent's own attention is cleared.
|
||||
*/
|
||||
export function deriveSubagentStatusBucket(status: AgentLifecycleStatus): SidebarStateBucket {
|
||||
if (status === "error") return "failed";
|
||||
if (status === "running") return "running";
|
||||
return "done";
|
||||
}
|
||||
|
||||
export interface SubagentRowPresentationData {
|
||||
key: string;
|
||||
kind: "agent";
|
||||
@@ -38,10 +49,7 @@ export function buildSubagentRowPresentationData(row: SubagentRow): SubagentRowP
|
||||
label: label ?? "",
|
||||
subtitle: subtitle ?? "",
|
||||
titleState: label ? "ready" : "loading",
|
||||
statusBucket: deriveSidebarStateBucket({
|
||||
status,
|
||||
requiresAttention: false,
|
||||
}),
|
||||
statusBucket: deriveSubagentStatusBucket(status),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -93,6 +93,8 @@ describe("workspace agent activity index", () => {
|
||||
workspaceId: "workspace-error",
|
||||
status: "error",
|
||||
turn: { phase: "idle", cancellationRequestId: null },
|
||||
requiresAttention: true,
|
||||
attentionReason: "error",
|
||||
updatedAt: "2026-01-01T00:00:00.000Z",
|
||||
}),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user