fix: keep optimistic status during agent bootstrap phase
This commit is contained in:
@@ -47,6 +47,19 @@ function createAgent(id: string): Agent {
|
||||
};
|
||||
}
|
||||
|
||||
function createAgentWithStatus({
|
||||
id,
|
||||
status,
|
||||
}: {
|
||||
id: string;
|
||||
status: Agent["status"];
|
||||
}): Agent {
|
||||
return {
|
||||
...createAgent(id),
|
||||
status,
|
||||
};
|
||||
}
|
||||
|
||||
function createBaseInput(): AgentScreenMachineInput {
|
||||
return {
|
||||
agent: null,
|
||||
@@ -357,6 +370,86 @@ describe("deriveAgentScreenViewState", () => {
|
||||
expect(handoffReady.agent.id).toBe("draft-agent");
|
||||
});
|
||||
|
||||
it("keeps optimistic running status while authoritative agent is still bootstrapping", () => {
|
||||
const memory = createBaseMemory();
|
||||
const input: AgentScreenMachineInput = {
|
||||
...createBaseInput(),
|
||||
agent: createAgentWithStatus({ id: "agent-1", status: "idle" }),
|
||||
placeholderAgent: createAgent("agent-1"),
|
||||
shouldUseOptimisticStream: true,
|
||||
};
|
||||
|
||||
const result = deriveAgentScreenViewState({ input, memory });
|
||||
const ready = expectReadyState(result.state);
|
||||
|
||||
expect(ready.source).toBe("optimistic");
|
||||
expect(ready.agent.status).toBe("running");
|
||||
});
|
||||
|
||||
it("keeps optimistic running status while authoritative agent is initializing", () => {
|
||||
const memory = createBaseMemory();
|
||||
const input: AgentScreenMachineInput = {
|
||||
...createBaseInput(),
|
||||
agent: createAgentWithStatus({ id: "agent-1", status: "initializing" }),
|
||||
placeholderAgent: createAgent("agent-1"),
|
||||
shouldUseOptimisticStream: true,
|
||||
};
|
||||
|
||||
const result = deriveAgentScreenViewState({ input, memory });
|
||||
const ready = expectReadyState(result.state);
|
||||
|
||||
expect(ready.source).toBe("optimistic");
|
||||
expect(ready.agent.status).toBe("running");
|
||||
});
|
||||
|
||||
it("hands off to authoritative once agent reaches running", () => {
|
||||
const memory = createBaseMemory();
|
||||
const input: AgentScreenMachineInput = {
|
||||
...createBaseInput(),
|
||||
agent: createAgentWithStatus({ id: "agent-1", status: "running" }),
|
||||
placeholderAgent: createAgent("agent-1"),
|
||||
shouldUseOptimisticStream: true,
|
||||
};
|
||||
|
||||
const result = deriveAgentScreenViewState({ input, memory });
|
||||
const ready = expectReadyState(result.state);
|
||||
|
||||
expect(ready.source).toBe("authoritative");
|
||||
expect(ready.agent.status).toBe("running");
|
||||
});
|
||||
|
||||
it("hands off to authoritative for terminal error states", () => {
|
||||
const memory = createBaseMemory();
|
||||
const input: AgentScreenMachineInput = {
|
||||
...createBaseInput(),
|
||||
agent: createAgentWithStatus({ id: "agent-1", status: "error" }),
|
||||
placeholderAgent: createAgent("agent-1"),
|
||||
shouldUseOptimisticStream: true,
|
||||
};
|
||||
|
||||
const result = deriveAgentScreenViewState({ input, memory });
|
||||
const ready = expectReadyState(result.state);
|
||||
|
||||
expect(ready.source).toBe("authoritative");
|
||||
expect(ready.agent.status).toBe("error");
|
||||
});
|
||||
|
||||
it("hands off to authoritative for terminal closed states", () => {
|
||||
const memory = createBaseMemory();
|
||||
const input: AgentScreenMachineInput = {
|
||||
...createBaseInput(),
|
||||
agent: createAgentWithStatus({ id: "agent-1", status: "closed" }),
|
||||
placeholderAgent: createAgent("agent-1"),
|
||||
shouldUseOptimisticStream: true,
|
||||
};
|
||||
|
||||
const result = deriveAgentScreenViewState({ input, memory });
|
||||
const ready = expectReadyState(result.state);
|
||||
|
||||
expect(ready.source).toBe("authoritative");
|
||||
expect(ready.agent.status).toBe("closed");
|
||||
});
|
||||
|
||||
it("emits history refresh toast only on transition into toast catch-up state", () => {
|
||||
const memory = createBaseMemory({
|
||||
hasRenderedReady: true,
|
||||
|
||||
@@ -93,7 +93,17 @@ export function deriveAgentScreenViewState({
|
||||
nextMemory.hadInitialSyncFailure = true;
|
||||
}
|
||||
|
||||
const candidateAgent = input.agent ?? input.placeholderAgent;
|
||||
const useOptimisticCreateFlowAgent =
|
||||
input.shouldUseOptimisticStream &&
|
||||
Boolean(input.placeholderAgent) &&
|
||||
(!input.agent ||
|
||||
input.agent.status === "initializing" ||
|
||||
input.agent.status === "idle");
|
||||
|
||||
const candidateAgent =
|
||||
input.agent && useOptimisticCreateFlowAgent && input.placeholderAgent
|
||||
? { ...input.agent, status: input.placeholderAgent.status }
|
||||
: input.agent ?? input.placeholderAgent;
|
||||
if (candidateAgent) {
|
||||
nextMemory.hasRenderedReady = true;
|
||||
nextMemory.lastReadyAgent = candidateAgent;
|
||||
@@ -132,11 +142,13 @@ export function deriveAgentScreenViewState({
|
||||
};
|
||||
}
|
||||
|
||||
const source: "authoritative" | "optimistic" | "stale" = input.agent
|
||||
? "authoritative"
|
||||
: input.shouldUseOptimisticStream
|
||||
? "optimistic"
|
||||
: "stale";
|
||||
const source: "authoritative" | "optimistic" | "stale" = useOptimisticCreateFlowAgent
|
||||
? "optimistic"
|
||||
: input.agent
|
||||
? "authoritative"
|
||||
: input.shouldUseOptimisticStream
|
||||
? "optimistic"
|
||||
: "stale";
|
||||
|
||||
let sync: AgentScreenReadySyncState;
|
||||
if (!input.isConnected) {
|
||||
|
||||
Reference in New Issue
Block a user