fix(ui): prioritize displayName over label in webchat session picker (#13108)

* fix(ui): prioritize displayName over label in webchat session picker

The session picker dropdown in the webchat UI was showing raw session
keys instead of human-readable display names. resolveSessionDisplayName()
checked label before displayName and formatted displayName-based entries
as key (displayName) instead of displayName (key).

Swap the priority so displayName is checked first, and use a consistent
humanName (key) format for both displayName and label fallbacks.

Fixes #6645

* test: use deterministic updatedAt in session display name tests
This commit is contained in:
Marcus Castro
2026-02-10 02:02:54 -03:00
committed by GitHub
parent f38dfe4544
commit 137b7d9aab
2 changed files with 87 additions and 5 deletions

View File

@@ -0,0 +1,79 @@
import { describe, expect, it } from "vitest";
import type { SessionsListResult } from "./types.ts";
import { resolveSessionDisplayName } from "./app-render.helpers.ts";
type SessionRow = SessionsListResult["sessions"][number];
function row(overrides: Partial<SessionRow> & { key: string }): SessionRow {
return { kind: "direct", updatedAt: 0, ...overrides };
}
describe("resolveSessionDisplayName", () => {
it("returns key when no row is provided", () => {
expect(resolveSessionDisplayName("agent:main:main")).toBe("agent:main:main");
});
it("returns key when row has no label or displayName", () => {
expect(resolveSessionDisplayName("agent:main:main", row({ key: "agent:main:main" }))).toBe(
"agent:main:main",
);
});
it("returns key when displayName matches key", () => {
expect(resolveSessionDisplayName("mykey", row({ key: "mykey", displayName: "mykey" }))).toBe(
"mykey",
);
});
it("returns key when label matches key", () => {
expect(resolveSessionDisplayName("mykey", row({ key: "mykey", label: "mykey" }))).toBe("mykey");
});
it("uses displayName prominently when available", () => {
expect(
resolveSessionDisplayName(
"discord:123:456",
row({ key: "discord:123:456", displayName: "My Chat" }),
),
).toBe("My Chat (discord:123:456)");
});
it("falls back to label when displayName is absent", () => {
expect(
resolveSessionDisplayName(
"discord:123:456",
row({ key: "discord:123:456", label: "General" }),
),
).toBe("General (discord:123:456)");
});
it("prefers displayName over label when both are present", () => {
expect(
resolveSessionDisplayName(
"discord:123:456",
row({ key: "discord:123:456", displayName: "My Chat", label: "General" }),
),
).toBe("My Chat (discord:123:456)");
});
it("ignores whitespace-only displayName", () => {
expect(
resolveSessionDisplayName(
"discord:123:456",
row({ key: "discord:123:456", displayName: " ", label: "General" }),
),
).toBe("General (discord:123:456)");
});
it("ignores whitespace-only label", () => {
expect(
resolveSessionDisplayName("discord:123:456", row({ key: "discord:123:456", label: " " })),
).toBe("discord:123:456");
});
it("trims displayName and label", () => {
expect(resolveSessionDisplayName("k", row({ key: "k", displayName: " My Chat " }))).toBe(
"My Chat (k)",
);
});
});

View File

@@ -219,15 +219,18 @@ function resolveMainSessionKey(
return null;
}
function resolveSessionDisplayName(key: string, row?: SessionsListResult["sessions"][number]) {
const label = row?.label?.trim() || "";
export function resolveSessionDisplayName(
key: string,
row?: SessionsListResult["sessions"][number],
) {
const displayName = row?.displayName?.trim() || "";
const label = row?.label?.trim() || "";
if (displayName && displayName !== key) {
return `${displayName} (${key})`;
}
if (label && label !== key) {
return `${label} (${key})`;
}
if (displayName && displayName !== key) {
return `${key} (${displayName})`;
}
return key;
}