104 lines
4.0 KiB
TypeScript
104 lines
4.0 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import { activeSessionKeyFromRuntime, sessionTabsFromConversations, sessionTabsFromMessages } from "./app-session-tabs.ts";
|
|
|
|
test("session tabs group messages and filter the active session", () => {
|
|
const messages = [
|
|
message("user", "ses_alpha", "cnv_alpha", "trc_alpha_1", "sent", "2026-06-03T00:00:01Z"),
|
|
message("agent", "ses_alpha", "cnv_alpha", "trc_alpha_1", "completed", "2026-06-03T00:00:02Z"),
|
|
message("user", "ses_beta", "cnv_beta", "trc_beta_1", "sent", "2026-06-03T00:00:03Z"),
|
|
message("agent", "ses_beta", "cnv_beta", "trc_beta_1", "running", "2026-06-03T00:00:04Z")
|
|
];
|
|
|
|
const view = sessionTabsFromMessages(messages, { activeSessionKey: "ses_alpha" });
|
|
|
|
assert.equal(view.tabs.length, 2);
|
|
assert.equal(view.activeKey, "ses_alpha");
|
|
assert.deepEqual(view.messages.map((item) => item.traceId), ["trc_alpha_1", "trc_alpha_1"]);
|
|
assert.equal(view.tabs.find((tab) => tab.key === "ses_beta")?.status, "running");
|
|
});
|
|
|
|
test("session tabs default to newest session when no preferred key is active", () => {
|
|
const messages = [
|
|
message("agent", "ses_old", "cnv_old", "trc_old", "completed", "2026-06-03T00:00:01Z"),
|
|
message("agent", "ses_new", "cnv_new", "trc_new", "completed", "2026-06-03T00:00:05Z")
|
|
];
|
|
|
|
const view = sessionTabsFromMessages(messages, { activeSessionKey: "missing" });
|
|
|
|
assert.equal(view.activeKey, "ses_new");
|
|
assert.deepEqual(view.messages.map((item) => item.sessionId), ["ses_new"]);
|
|
});
|
|
|
|
test("session tabs keep first-turn user and agent messages together when session id arrives later", () => {
|
|
const messages = [
|
|
{ ...message("user", null, "cnv_first", "trc_first", "sent", "2026-06-03T00:00:01Z"), sessionId: null },
|
|
message("agent", "ses_first", "cnv_first", "trc_first", "completed", "2026-06-03T00:00:02Z")
|
|
];
|
|
|
|
const view = sessionTabsFromMessages(messages, { activeSessionKey: "cnv_first" });
|
|
|
|
assert.equal(view.tabs.length, 1);
|
|
assert.equal(view.activeKey, "ses_first");
|
|
assert.equal(view.tabs[0].status, "completed");
|
|
assert.deepEqual(view.messages.map((item) => item.role), ["user", "agent"]);
|
|
});
|
|
|
|
test("runtime active session prefers current request session before global state", () => {
|
|
const key = activeSessionKeyFromRuntime({
|
|
currentRequest: { sessionId: "ses_current", conversationId: "cnv_current" },
|
|
sessionId: "ses_global",
|
|
conversationId: "cnv_global"
|
|
});
|
|
|
|
assert.equal(key, "ses_current");
|
|
});
|
|
|
|
test("session tabs use account conversations and keep the selected session active", () => {
|
|
const view = sessionTabsFromConversations([
|
|
conversation("cnv_old", "ses_old", "trc_old", "idle", "2026-06-03T00:00:01Z"),
|
|
conversation("cnv_new", "ses_new", "trc_new", "running", "2026-06-03T00:00:03Z")
|
|
], { selectedConversationId: "cnv_old" });
|
|
|
|
assert.equal(view.tabs.length, 2);
|
|
assert.equal(view.activeConversation?.conversationId, "cnv_old");
|
|
assert.equal(view.tabs[0].conversationId, "cnv_new");
|
|
assert.equal(view.tabs.find((tab) => tab.conversationId === "cnv_new")?.subtitle, "处理中");
|
|
});
|
|
|
|
test("session tabs default to newest visible conversation", () => {
|
|
const view = sessionTabsFromConversations([
|
|
conversation("cnv_a", "ses_a", "trc_a", "idle", "2026-06-03T00:00:01Z"),
|
|
conversation("cnv_b", "ses_b", "trc_b", "completed", "2026-06-03T00:00:05Z")
|
|
], { selectedConversationId: "missing" });
|
|
|
|
assert.equal(view.activeConversation?.conversationId, "cnv_b");
|
|
assert.equal(view.activeKey, "ses_b");
|
|
});
|
|
|
|
function message(role, sessionId, conversationId, traceId, status, createdAt) {
|
|
return {
|
|
id: `${role}_${traceId}`,
|
|
role,
|
|
title: role,
|
|
text: traceId,
|
|
status,
|
|
sessionId,
|
|
conversationId,
|
|
traceId,
|
|
createdAt
|
|
};
|
|
}
|
|
|
|
function conversation(conversationId, sessionId, traceId, status, updatedAt) {
|
|
return {
|
|
conversationId,
|
|
sessionId,
|
|
status,
|
|
updatedAt,
|
|
lastTraceId: traceId,
|
|
messages: [{ role: "agent", text: traceId, status, traceId, updatedAt }]
|
|
};
|
|
}
|