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 { resolveProjectPlacement } from "@/utils/project-placement";
|
||||||
import { buildDraftStoreKey } from "@/stores/draft-keys";
|
import { buildDraftStoreKey } from "@/stores/draft-keys";
|
||||||
import type { AttachmentMetadata } from "@/attachments/types";
|
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
|
// Re-export types from session-store and draft-store for backward compatibility
|
||||||
export type { DraftInput } from "@/stores/draft-store";
|
export type { DraftInput } from "@/stores/draft-store";
|
||||||
@@ -295,15 +296,10 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sessionAgents) {
|
previousAgentStatusRef.current = reconcilePreviousAgentStatuses(
|
||||||
previousAgentStatusRef.current.clear();
|
previousAgentStatusRef.current,
|
||||||
return;
|
sessionAgents,
|
||||||
}
|
);
|
||||||
const nextStatuses = new Map<string, AgentLifecycleStatus>();
|
|
||||||
for (const nextAgent of sessionAgents.values()) {
|
|
||||||
nextStatuses.set(nextAgent.id, nextAgent.status);
|
|
||||||
}
|
|
||||||
previousAgentStatusRef.current = nextStatuses;
|
|
||||||
}, [sessionAgents]);
|
}, [sessionAgents]);
|
||||||
|
|
||||||
const hydrateWorkspaces = useCallback(
|
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