mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Fix queued prompt dispatch after idle transition
This commit is contained in:
@@ -49,6 +49,7 @@ import { derivePendingPermissionKey, normalizeAgentSnapshot } from "@/utils/agen
|
||||
import { resolveProjectPlacement } from "@/utils/project-placement";
|
||||
import { buildDraftStoreKey } from "@/stores/draft-keys";
|
||||
import type { AttachmentMetadata } from "@/attachments/types";
|
||||
import { reconcilePreviousAgentStatuses } from "@/contexts/session-status-tracking";
|
||||
|
||||
// Re-export types from session-store and draft-store for backward compatibility
|
||||
export type { DraftInput } from "@/stores/draft-store";
|
||||
@@ -295,15 +296,10 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!sessionAgents) {
|
||||
previousAgentStatusRef.current.clear();
|
||||
return;
|
||||
}
|
||||
const nextStatuses = new Map<string, AgentLifecycleStatus>();
|
||||
for (const nextAgent of sessionAgents.values()) {
|
||||
nextStatuses.set(nextAgent.id, nextAgent.status);
|
||||
}
|
||||
previousAgentStatusRef.current = nextStatuses;
|
||||
previousAgentStatusRef.current = reconcilePreviousAgentStatuses(
|
||||
previousAgentStatusRef.current,
|
||||
sessionAgents,
|
||||
);
|
||||
}, [sessionAgents]);
|
||||
|
||||
const hydrateWorkspaces = useCallback(
|
||||
|
||||
72
packages/app/src/contexts/session-status-tracking.test.ts
Normal file
72
packages/app/src/contexts/session-status-tracking.test.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { Agent } from "@/stores/session-store";
|
||||
import { reconcilePreviousAgentStatuses } from "./session-status-tracking";
|
||||
|
||||
function createAgent(status: Agent["status"]): Agent {
|
||||
return {
|
||||
serverId: "server-1",
|
||||
id: "agent-1",
|
||||
provider: "codex",
|
||||
status,
|
||||
createdAt: new Date(0),
|
||||
updatedAt: new Date(0),
|
||||
lastUserMessageAt: null,
|
||||
lastActivityAt: new Date(0),
|
||||
capabilities: {
|
||||
supportsStreaming: true,
|
||||
supportsSessionPersistence: true,
|
||||
supportsDynamicModes: true,
|
||||
supportsMcpServers: true,
|
||||
supportsReasoningStream: true,
|
||||
supportsToolInvocations: true,
|
||||
},
|
||||
currentModeId: null,
|
||||
availableModes: [],
|
||||
pendingPermissions: [],
|
||||
persistence: null,
|
||||
title: "Agent",
|
||||
cwd: "/tmp",
|
||||
model: null,
|
||||
labels: {},
|
||||
projectPlacement: null,
|
||||
};
|
||||
}
|
||||
|
||||
describe("reconcilePreviousAgentStatuses", () => {
|
||||
it("preserves previously seen status for existing agents", () => {
|
||||
const previous = new Map([["agent-1", "running" as const]]);
|
||||
const sessionAgents = new Map([["agent-1", createAgent("idle")]]);
|
||||
|
||||
const result = reconcilePreviousAgentStatuses(previous, sessionAgents);
|
||||
|
||||
expect(result).toEqual(new Map([["agent-1", "running"]]));
|
||||
});
|
||||
|
||||
it("seeds newly seen agents from the current snapshot", () => {
|
||||
const sessionAgents = new Map([["agent-1", createAgent("idle")]]);
|
||||
|
||||
const result = reconcilePreviousAgentStatuses(new Map(), sessionAgents);
|
||||
|
||||
expect(result).toEqual(new Map([["agent-1", "idle"]]));
|
||||
});
|
||||
|
||||
it("removes agents that are no longer present", () => {
|
||||
const previous = new Map([
|
||||
["agent-1", "running" as const],
|
||||
["agent-2", "idle" as const],
|
||||
]);
|
||||
const sessionAgents = new Map([["agent-1", createAgent("idle")]]);
|
||||
|
||||
const result = reconcilePreviousAgentStatuses(previous, sessionAgents);
|
||||
|
||||
expect(result).toEqual(new Map([["agent-1", "running"]]));
|
||||
});
|
||||
|
||||
it("clears all tracked statuses when the session is unavailable", () => {
|
||||
const previous = new Map([["agent-1", "running" as const]]);
|
||||
|
||||
const result = reconcilePreviousAgentStatuses(previous, undefined);
|
||||
|
||||
expect(result).toEqual(new Map());
|
||||
});
|
||||
});
|
||||
29
packages/app/src/contexts/session-status-tracking.ts
Normal file
29
packages/app/src/contexts/session-status-tracking.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { AgentLifecycleStatus } from "@server/shared/agent-lifecycle";
|
||||
import type { Agent } from "@/stores/session-store";
|
||||
|
||||
export function reconcilePreviousAgentStatuses(
|
||||
previousStatuses: Map<string, AgentLifecycleStatus>,
|
||||
sessionAgents: Map<string, Agent> | undefined,
|
||||
): Map<string, AgentLifecycleStatus> {
|
||||
if (!sessionAgents) {
|
||||
return new Map();
|
||||
}
|
||||
|
||||
const nextStatuses = new Map(previousStatuses);
|
||||
const seenAgentIds = new Set<string>();
|
||||
|
||||
for (const agent of sessionAgents.values()) {
|
||||
seenAgentIds.add(agent.id);
|
||||
if (!nextStatuses.has(agent.id)) {
|
||||
nextStatuses.set(agent.id, agent.status);
|
||||
}
|
||||
}
|
||||
|
||||
for (const agentId of nextStatuses.keys()) {
|
||||
if (!seenAgentIds.has(agentId)) {
|
||||
nextStatuses.delete(agentId);
|
||||
}
|
||||
}
|
||||
|
||||
return nextStatuses;
|
||||
}
|
||||
Reference in New Issue
Block a user