Files
tutti/packages/agent/gui/agent-message-center/workspaceAgentMessageCenterViewModel.spec.ts
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

290 lines
7.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
groupMessageCenterItems,
messageCenterAgentUserStackId,
messageCenterStackScrollSyncSegment,
partitionMessageCenterItemsByAgentUser
} from "./workspaceAgentMessageCenterViewModel";
import type { WorkspaceAgentMessageCenterItem } from "./workspaceAgentMessageCenterModel";
describe("partitionMessageCenterItemsByAgentUser", () => {
it("stacks only sessions with the same agent provider and user id", () => {
const stacks = partitionMessageCenterItemsByAgentUser([
item({
agentSessionId: "codex-user-a-1",
provider: "codex",
userId: "user-a"
}),
item({
agentSessionId: "codex-user-a-2",
provider: "codex",
userId: "user-a"
}),
item({
agentSessionId: "codex-user-b",
provider: "codex",
userId: "user-b"
}),
item({
agentSessionId: "openclaw-user-a",
provider: "openclaw",
userId: "user-a"
})
]);
expect(
stacks.map((stack) => ({
id: stack.id,
provider: stack.provider,
userId: stack.userId,
sessionIds: stack.items.map((item) => item.agentSessionId)
}))
).toEqual([
{
id: "agent-user:codex:user-a",
provider: "codex",
userId: "user-a",
sessionIds: ["codex-user-a-1", "codex-user-a-2"]
},
{
id: "agent-user:codex:user-b",
provider: "codex",
userId: "user-b",
sessionIds: ["codex-user-b"]
},
{
id: "agent-user:openclaw:user-a",
provider: "openclaw",
userId: "user-a",
sessionIds: ["openclaw-user-a"]
}
]);
});
it("normalizes provider casing and blank user ids in the stack key", () => {
expect(
messageCenterAgentUserStackId({
provider: " Codex ",
userId: " user-a "
})
).toBe("agent-user:codex:user-a");
expect(
messageCenterAgentUserStackId({
provider: " ",
userId: null
})
).toBe("agent-user:unknown-agent:unknown-user");
});
it("summarizes collapsed stack scroll sync keys without every stacked item id", () => {
const stack = partitionMessageCenterItemsByAgentUser([
item({
agentSessionId: "codex-user-a-1",
provider: "codex",
userId: "user-a"
}),
item({
agentSessionId: "codex-user-a-2",
provider: "codex",
userId: "user-a"
}),
item({
agentSessionId: "codex-user-a-3",
provider: "codex",
userId: "user-a"
})
])[0];
if (!stack) {
throw new Error("Expected a stack to be created.");
}
const collapsed = messageCenterStackScrollSyncSegment({
expanded: false,
groupId: "working",
stack
});
const expanded = messageCenterStackScrollSyncSegment({
expanded: true,
groupId: "working",
stack
});
expect(collapsed).toContain("collapsed:working:agent-user:codex:user-a");
expect(collapsed).toContain("message-center-codex-user-a-1");
expect(collapsed).not.toContain("message-center-codex-user-a-2");
expect(collapsed).not.toContain("message-center-codex-user-a-3");
expect(expanded).toContain("message-center-codex-user-a-1");
expect(expanded).toContain("message-center-codex-user-a-2");
expect(expanded).toContain("message-center-codex-user-a-3");
});
});
describe("groupMessageCenterItems", () => {
it("groups the agent view by provider and user id", () => {
const groups = groupMessageCenterItems(
[
item({
agentSessionId: "codex-user-a-1",
provider: "codex",
userId: "user-a",
identity: {
userName: "Jessica",
agentName: "Codex"
}
}),
item({
agentSessionId: "codex-user-a-2",
provider: "codex",
userId: "user-a",
identity: {
userName: "Jessica",
agentName: "Codex"
}
}),
item({
agentSessionId: "codex-user-b",
provider: "codex",
userId: "user-b",
identity: {
userName: "Taylor",
agentName: "Codex"
}
})
],
"agent",
(key) => key
);
expect(
groups.map((group) => ({
id: group.id,
label: group.label,
provider: group.provider,
userId: group.userId,
sessionIds: group.items.map((item) => item.agentSessionId)
}))
).toEqual([
{
id: "agent-user:codex:user-a",
label: "Jessica & Codex",
provider: "codex",
userId: "user-a",
sessionIds: ["codex-user-a-1", "codex-user-a-2"]
},
{
id: "agent-user:codex:user-b",
label: "Taylor & Codex",
provider: "codex",
userId: "user-b",
sessionIds: ["codex-user-b"]
}
]);
});
it("splits failed items into their own group in the priority view", () => {
const groups = groupMessageCenterItems(
[
item({
agentSessionId: "waiting-session",
status: "working",
needsAttentionKind: "question"
}),
item({
agentSessionId: "failed-session",
status: "failed"
})
],
"priority",
(key) => key
);
expect(
groups.map((group) => ({
id: group.id,
sessionIds: group.items.map((entry) => entry.agentSessionId)
}))
).toEqual([
{
id: "needs-attention",
sessionIds: ["waiting-session"]
},
{
id: "failed",
sessionIds: ["failed-session"]
}
]);
});
it("keeps imported completed items out of the recently completed group", () => {
const now = Date.now();
const groups = groupMessageCenterItems(
[
item({
agentSessionId: "recent-runtime",
lastAgentMessageAtUnixMs: now,
sortTimeUnixMs: now,
status: "completed"
}),
item({
agentSessionId: "recent-imported",
imported: true,
lastAgentMessageAtUnixMs: now,
sortTimeUnixMs: now,
status: "completed"
})
],
"priority",
(key) => key
);
expect(
groups.map((group) => ({
id: group.id,
sessionIds: group.items.map((entry) => entry.agentSessionId)
}))
).toEqual([
{
id: "recently-completed",
sessionIds: ["recent-runtime"]
},
{
id: "completed",
sessionIds: ["recent-imported"]
}
]);
});
});
function item(
overrides: Partial<WorkspaceAgentMessageCenterItem> & {
agentSessionId: string;
}
): WorkspaceAgentMessageCenterItem {
const { agentSessionId, ...rest } = overrides;
return {
id: `message-center-${agentSessionId}`,
agentSessionId,
provider: "codex",
userId: null,
title: agentSessionId,
identity: null,
cwd: "/workspace",
status: "working",
digest: {
primary: {
kind: "progress",
summary: `${agentSessionId} summary`,
occurredAtUnixMs: 1
}
},
lastAgentMessageSummary: `${agentSessionId} summary`,
lastAgentMessageAtUnixMs: 1,
pendingInteractionTarget: null,
pendingPrompt: null,
needsAttentionKind: null,
needsAttentionSummary: null,
sortTimeUnixMs: 1,
...rest
};
}