mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-06 00:14:54 +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:
@@ -39,6 +39,28 @@ describe("deriveAgentStateBucket", () => {
|
||||
).toBe("failed");
|
||||
});
|
||||
|
||||
it("treats an errored agent whose error was read as done", () => {
|
||||
expect(
|
||||
deriveAgentStateBucket({
|
||||
status: "error",
|
||||
pendingPermissionCount: 0,
|
||||
requiresAttention: false,
|
||||
attentionReason: null,
|
||||
}),
|
||||
).toBe("done");
|
||||
});
|
||||
|
||||
it("treats an errored agent with unread error attention as failed", () => {
|
||||
expect(
|
||||
deriveAgentStateBucket({
|
||||
status: "error",
|
||||
pendingPermissionCount: 0,
|
||||
requiresAttention: true,
|
||||
attentionReason: "error",
|
||||
}),
|
||||
).toBe("failed");
|
||||
});
|
||||
|
||||
it("treats unread finished agents as attention", () => {
|
||||
expect(
|
||||
deriveAgentStateBucket({
|
||||
@@ -83,10 +105,21 @@ describe("getAgentStatusPriority", () => {
|
||||
it("prioritizes pending permissions before errors and running agents", () => {
|
||||
const permission = getAgentStatusPriority({ status: "running", pendingPermissionCount: 1 });
|
||||
expect(permission).toBeLessThan(
|
||||
getAgentStatusPriority({ status: "error", pendingPermissionCount: 0 }),
|
||||
getAgentStatusPriority({
|
||||
status: "error",
|
||||
pendingPermissionCount: 0,
|
||||
requiresAttention: true,
|
||||
attentionReason: "error",
|
||||
}),
|
||||
);
|
||||
expect(permission).toBeLessThan(
|
||||
getAgentStatusPriority({ status: "running", pendingPermissionCount: 0 }),
|
||||
);
|
||||
});
|
||||
|
||||
it("ranks an errored agent with a read error alongside completed agents", () => {
|
||||
expect(getAgentStatusPriority({ status: "error", requiresAttention: false })).toBe(
|
||||
getAgentStatusPriority({ status: "idle" }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,11 +19,17 @@ const WORKSPACE_STATE_BUCKET_PRIORITY = {
|
||||
done: 4,
|
||||
} as const satisfies Record<WorkspaceStateBucket, number>;
|
||||
|
||||
// An error is a notification like a finish: once the user has seen it, the agent stops showing as
|
||||
// failed even though its lifecycle stays "error" until the next turn starts.
|
||||
function hasUnreadError(input: AgentStateBucketInput): boolean {
|
||||
return input.requiresAttention === true && input.attentionReason === "error";
|
||||
}
|
||||
|
||||
export function deriveAgentStateBucket(input: AgentStateBucketInput): WorkspaceStateBucket {
|
||||
if ((input.pendingPermissionCount ?? 0) > 0 || input.attentionReason === "permission") {
|
||||
return "needs_input";
|
||||
}
|
||||
if (input.status === "error" || input.attentionReason === "error") {
|
||||
if (hasUnreadError(input)) {
|
||||
return "failed";
|
||||
}
|
||||
if (input.status === "running") {
|
||||
@@ -43,7 +49,7 @@ export function getAgentStatusPriority(input: AgentStateBucketInput): number {
|
||||
if ((input.pendingPermissionCount ?? 0) > 0 || input.attentionReason === "permission") {
|
||||
return 0;
|
||||
}
|
||||
if (input.status === "error" || input.attentionReason === "error") {
|
||||
if (hasUnreadError(input)) {
|
||||
return 1;
|
||||
}
|
||||
if (input.status === "running") {
|
||||
|
||||
Reference in New Issue
Block a user