Files
paseo/packages/app/src/utils/agent-directory-reconciliation.test.ts
T
Mohamed Boudra e79e826e23 Stop re-rendering every chat message on each agent update (#8916)
* fix(app): keep unchanged agent fields when an agent update is accepted

* fix(app): share unchanged agent fields at the store write, not in the update policy
2026-11-06 14:48:10 +07:00

229 lines
6.4 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { FetchAgentsEntry } from "@getpaseo/client/internal/daemon-client";
import type { AgentSnapshotPayload } from "@getpaseo/protocol/messages";
import { reconcileAgentDirectory } from "./agent-directory-reconciliation";
function snapshot(id: string, status: AgentSnapshotPayload["status"]): AgentSnapshotPayload {
return {
id,
provider: "codex",
cwd: "/repo",
model: null,
createdAt: "2026-07-12T10:00:00.000Z",
updatedAt: "2026-07-12T10:00:00.000Z",
lastUserMessageAt: null,
status,
capabilities: {
supportsStreaming: true,
supportsSessionPersistence: true,
supportsDynamicModes: true,
supportsMcpServers: true,
supportsReasoningStream: true,
supportsToolInvocations: true,
},
currentModeId: null,
availableModes: [],
pendingPermissions: [],
persistence: null,
title: null,
labels: {},
};
}
function entry(id: string, status: AgentSnapshotPayload["status"]): FetchAgentsEntry {
return {
agent: snapshot(id, status),
project: {
projectKey: "/repo",
projectName: "repo",
checkout: {
cwd: "/repo",
isGit: false,
currentBranch: null,
remoteUrl: null,
worktreeRoot: null,
isPaseoOwnedWorktree: false,
mainRepoRoot: null,
},
},
};
}
describe("agent directory reconciliation", () => {
it("preserves snapshot and buffered protocol status without interpreting liveness", () => {
const result = reconcileAgentDirectory({
snapshot: [entry("snapshot", "idle"), entry("buffered", "running")],
deltas: [
{
kind: "upsert",
agent: snapshot("buffered", "idle"),
project: entry("buffered", "idle").project,
},
{
kind: "upsert",
agent: snapshot("buffered", "idle"),
project: entry("buffered", "idle").project,
},
],
});
expect(result.map(({ agent }) => [agent.id, agent.status])).toEqual([
["snapshot", "idle"],
["buffered", "idle"],
]);
});
it("preserves ordered upserts and removals received after page one", () => {
const result = reconcileAgentDirectory({
snapshot: [entry("updated", "idle"), entry("removed", "idle")],
deltas: [
{
kind: "upsert",
agent: { ...snapshot("updated", "idle"), title: "live" },
project: entry("updated", "idle").project,
},
{ kind: "remove", agentId: "removed" },
],
});
expect(result.map(({ agent }) => [agent.id, agent.title])).toEqual([["updated", "live"]]);
});
it("keeps newer page metadata when a stale buffered upsert arrives", () => {
const snapshotEntry = entry("agent", "running");
const staleProject = {
...snapshotEntry.project,
projectName: "stale project",
};
const result = reconcileAgentDirectory({
snapshot: [
{
...entry("agent", "running"),
agent: {
...snapshot("agent", "running"),
title: "newer page",
updatedAt: "2026-07-12T12:00:00.000Z",
},
},
],
deltas: [
{
kind: "upsert",
agent: {
...snapshot("agent", "idle"),
title: "stale live",
updatedAt: "2026-07-12T11:00:00.000Z",
},
project: staleProject,
},
],
});
expect({
title: result[0]?.agent.title,
status: result[0]?.agent.status,
projectName: result[0]?.project.projectName,
}).toEqual({ title: "newer page", status: "running", projectName: "repo" });
});
it("takes the project of a newer buffered upsert", () => {
const snapshotEntry = entry("agent", "idle");
const newerProject = { ...snapshotEntry.project, projectName: "renamed project" };
const result = reconcileAgentDirectory({
snapshot: [snapshotEntry],
deltas: [
{
kind: "upsert",
agent: { ...snapshot("agent", "idle"), updatedAt: "2026-07-12T11:00:00.000Z" },
project: newerProject,
},
],
});
expect(result[0]?.project.projectName).toBe("renamed project");
});
it("clears a snapshot stop when a newer buffered upsert is running", () => {
const result = reconcileAgentDirectory({
snapshot: [entry("agent", "idle")],
deltas: [
{
kind: "upsert",
agent: {
...snapshot("agent", "running"),
updatedAt: "2026-07-12T11:00:00.000Z",
},
project: entry("agent", "running").project,
},
],
});
expect(result[0]?.agent.status).toBe("running");
});
it("accepts usage from a stale buffered upsert without regressing metadata", () => {
const result = reconcileAgentDirectory({
snapshot: [
{
...entry("agent", "idle"),
agent: {
...snapshot("agent", "idle"),
title: "newer page",
updatedAt: "2026-07-12T12:00:00.000Z",
lastUsage: { inputTokens: 10, outputTokens: 5 },
},
},
],
deltas: [
{
kind: "upsert",
agent: {
...snapshot("agent", "running"),
title: "stale live",
updatedAt: "2026-07-12T11:00:00.000Z",
lastUsage: { inputTokens: 20, outputTokens: 8 },
},
project: entry("agent", "idle").project,
},
],
});
expect({
title: result[0]?.agent.title,
status: result[0]?.agent.status,
usage: result[0]?.agent.lastUsage,
}).toEqual({
title: "newer page",
status: "idle",
usage: { inputTokens: 20, outputTokens: 8 },
});
});
it("preserves usage when a stale buffered upsert omits it", () => {
const result = reconcileAgentDirectory({
snapshot: [
{
...entry("agent", "idle"),
agent: {
...snapshot("agent", "idle"),
updatedAt: "2026-07-12T12:00:00.000Z",
lastUsage: { inputTokens: 10, outputTokens: 5 },
},
},
],
deltas: [
{
kind: "upsert",
agent: {
...snapshot("agent", "running"),
updatedAt: "2026-07-12T11:00:00.000Z",
},
project: entry("agent", "idle").project,
},
],
});
expect(result[0]?.agent.lastUsage).toEqual({ inputTokens: 10, outputTokens: 5 });
});
});