Stop counting initializing agents as running

This commit is contained in:
Mohamed Boudra
2026-06-04 00:53:38 +07:00
parent f6c0b60b7c
commit b345ef1242
10 changed files with 35 additions and 19 deletions

View File

@@ -324,7 +324,7 @@ export function AgentList({
const handleAgentLongPress = useCallback(
(agent: AggregatedAgent) => {
const isRunning = agent.status === "running" || agent.status === "initializing";
const isRunning = agent.status === "running";
if (isRunning) {
setActionAgent(agent);
return;

View File

@@ -420,7 +420,7 @@ describe("deriveAgentScreenViewState", () => {
expect(transitions.join(" -> ")).not.toContain("loading -> idle");
});
it("keeps optimistic running status while authoritative agent is initializing", () => {
it("uses authoritative initializing status instead of optimistic running status", () => {
const memory = createBaseMemory();
const input: AgentScreenMachineInput = {
...createBaseInput(),
@@ -431,8 +431,8 @@ describe("deriveAgentScreenViewState", () => {
const result = deriveAgentScreenViewState({ input, memory });
const ready = expectReadyState(result.state);
expect(ready.source).toBe("optimistic");
expect(ready.agent.status).toBe("running");
expect(ready.source).toBe("authoritative");
expect(ready.agent.status).toBe("initializing");
});
it("hands off to authoritative once agent reaches running", () => {

View File

@@ -100,8 +100,7 @@ function updateInitialSyncFailureMemory(args: {
function shouldUseOptimisticCreateFlowAgent(input: AgentScreenMachineInput): boolean {
return (
input.continuity.kind === "optimistic-create" &&
(!input.agent || input.agent.status === "initializing" || input.agent.status === "idle")
input.continuity.kind === "optimistic-create" && (!input.agent || input.agent.status === "idle")
);
}

View File

@@ -2404,7 +2404,7 @@ function WorkspaceScreenContent({
const agent =
useSessionStore.getState().sessions[normalizedServerId]?.agents?.get(agentId) ?? null;
const closePolicy = resolveCloseAgentTabPolicy(agent);
const isRunning = agent?.status === "running" || agent?.status === "initializing";
const isRunning = agent?.status === "running";
if (isRunning && closePolicy.kind === "archive-on-close") {
const confirmed = await confirmDialog({

View File

@@ -68,16 +68,15 @@ describe("resolveArchiveSubagentDialog", () => {
});
});
it("uses running copy for initializing subagents", () => {
it("does not use running copy for initializing subagents", () => {
expect(
resolveArchiveSubagentDialog({
title: "Starting child",
status: "initializing",
}),
).toEqual({
title: "Archive running subagent?",
message:
"Starting child is still running. Archiving it will stop the subagent and remove it from the track.",
title: "Archive subagent?",
message: "Remove Starting child from the track. The subagent will be archived.",
confirmLabel: "Archive",
cancelLabel: "Cancel",
destructive: true,

View File

@@ -24,7 +24,7 @@ export function resolveArchiveSubagentDialog(
input: ResolveArchiveSubagentDialogInput,
): ConfirmDialogInput {
const subagentLabel = resolveSubagentLabel(input.title) ?? "this subagent";
const isRunning = input.status === "running" || input.status === "initializing";
const isRunning = input.status === "running";
return {
title: isRunning ? "Archive running subagent?" : "Archive subagent?",

View File

@@ -35,7 +35,7 @@ describe("deriveSidebarStateBucket", () => {
).toBe("attention");
});
it("treats initializing agents as running", () => {
it("does not count initializing agents as running", () => {
expect(
deriveSidebarStateBucket({
status: "initializing",
@@ -43,6 +43,6 @@ describe("deriveSidebarStateBucket", () => {
requiresAttention: false,
attentionReason: null,
}),
).toBe("running");
).toBe("done");
});
});

View File

@@ -50,7 +50,7 @@ describe("deriveAgentStateBucket", () => {
).toBe("attention");
});
it("treats initializing agents as running for workspace buckets", () => {
it("does not count initializing agents as running for workspace buckets", () => {
expect(
deriveAgentStateBucket({
status: "initializing",
@@ -58,7 +58,7 @@ describe("deriveAgentStateBucket", () => {
requiresAttention: false,
attentionReason: null,
}),
).toBe("running");
).toBe("done");
});
});

View File

@@ -26,7 +26,7 @@ export function deriveAgentStateBucket(input: AgentStateBucketInput): WorkspaceS
if (input.status === "error" || input.attentionReason === "error") {
return "failed";
}
if (input.status === "running" || input.status === "initializing") {
if (input.status === "running") {
return "running";
}
if (input.requiresAttention) {

View File

@@ -4201,7 +4201,25 @@ test("buildWorkspaceDescriptorMap computes statusEnteredAt from runtime agent fi
expect(descriptor.statusEnteredAt).toBe(updatedAt);
}
// 3. Highest-priority across all buckets: a "needs_input" agent beats
// 3. A root agent that is still initializing does not make the workspace
// look like it is actively working.
{
const { session, workspace } = setupSession();
const updatedAt = "2026-05-12T09:45:00.000Z";
session.listAgentPayloads = async () => [
makeAgent({
id: "agent-initializing",
cwd: workspace.cwd,
status: "initializing",
updatedAt,
}),
];
const descriptor = await buildDescriptor(session, workspace.workspaceId);
expect(descriptor.status).toBe("done");
expect(descriptor.statusEnteredAt).toBe(updatedAt);
}
// 4. Highest-priority across all buckets: a "needs_input" agent beats
// a "running" agent beats a "done" agent. statusEnteredAt is the winning
// bucket's newest agent timestamp.
{
@@ -4235,7 +4253,7 @@ test("buildWorkspaceDescriptorMap computes statusEnteredAt from runtime agent fi
expect(descriptor.statusEnteredAt).toBe(needsInputUpdatedAt);
}
// 4. Same-bucket: keep the previous bucket entry time even when newer
// 5. Same-bucket: keep the previous bucket entry time even when newer
// agents contribute to the same winning bucket.
{
const { session, workspace } = setupSession();