Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/features/threads/utils/threadSummary.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { describe, expect, it } from "vitest";
import { buildThreadSummaryFromThread } from "./threadSummary";

const baseThread = {
id: "thread-1",
name: "Server-provided name",
preview: "First message preview",
source: "vscode",
};

describe("buildThreadSummaryFromThread", () => {
it("prefers the server-provided thread name over the message preview", () => {
const summary = buildThreadSummaryFromThread({
workspaceId: "workspace-1",
thread: baseThread,
fallbackIndex: 0,
});

expect(summary?.name).toBe("Server-provided name");
});

it("keeps an explicit local rename ahead of the server-provided name", () => {
const summary = buildThreadSummaryFromThread({
workspaceId: "workspace-1",
thread: baseThread,
fallbackIndex: 0,
getCustomName: () => "Local rename",
});

expect(summary?.name).toBe("Local rename");
});

it("falls back to the message preview when the server has no name", () => {
const summary = buildThreadSummaryFromThread({
workspaceId: "workspace-1",
thread: { ...baseThread, name: null },
fallbackIndex: 0,
});

expect(summary?.name).toBe("First message preview");
});

it("supports title as a compatibility fallback", () => {
const summary = buildThreadSummaryFromThread({
workspaceId: "workspace-1",
thread: { ...baseThread, name: null, title: "Legacy title" },
fallbackIndex: 0,
});

expect(summary?.name).toBe("Legacy title");
});
});
3 changes: 2 additions & 1 deletion src/features/threads/utils/threadSummary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ export function buildThreadSummaryFromThread({
const preview = asString(thread.preview ?? "").trim();
const customName = getCustomName?.(workspaceId, id);
const fallbackName = `Agent ${fallbackIndex + 1}`;
const serverName = asString(thread.name ?? thread.title ?? "").trim();
const name = customName
? customName
: clampThreadName(preview) ?? fallbackName;
: clampThreadName(serverName || preview) ?? fallbackName;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore UUID placeholder names when building summaries

When the server-provided name is the thread's UUID and no local rename exists, this now chooses the UUID over a useful message preview. onThreadNameUpdated already rejects this exact placeholder in useThreadTurnEvents.ts:172–178, with a corresponding regression test, but list refreshes now bypass that safeguard and replace readable sidebar labels with IDs. Apply the same placeholder check before preferring the server name so these sessions retain the preview or numbered-agent fallback.

Useful? React with 👍 / 👎.

const metadata = extractThreadCodexMetadata(thread);
if (shouldHideSubagentThreadFromSidebar(thread.source)) {
return null;
Expand Down