Skip to content

Commit ebf999f

Browse files
committed
fix(web): keep inactive thread reads unlinked
1 parent 6a1cbed commit ebf999f

3 files changed

Lines changed: 29 additions & 4 deletions

File tree

‎apps/web/src/components/chat/MessagesTimeline.logic.test.ts‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
shouldPreserveAssistantLineBreaks,
3636
threadReadLabelPrefix,
3737
threadReadTargetId,
38+
threadReadTargetTitle,
3839
type MessagesTimelineRow,
3940
resolveTimelineToolPresentation,
4041
workEntryDisplayLabel,
@@ -93,6 +94,18 @@ describe("expanded tool group scrolling", () => {
9394
});
9495

9596
describe("work entry labels", () => {
97+
it("uses live titles only for active thread shells", () => {
98+
const shell = { title: " Review auth flow ", archivedAt: null, deletedAt: null };
99+
expect(threadReadTargetTitle(shell)).toBe("Review auth flow");
100+
expect(threadReadTargetTitle({ ...shell, title: "Harden session refresh" })).toBe(
101+
"Harden session refresh",
102+
);
103+
expect(threadReadTargetTitle({ ...shell, archivedAt: "2026-10-07T12:00:00Z" })).toBeNull();
104+
expect(threadReadTargetTitle({ ...shell, deletedAt: "2026-10-07T12:00:00Z" })).toBeNull();
105+
expect(threadReadTargetTitle({ ...shell, title: " " })).toBeNull();
106+
expect(threadReadTargetTitle(null)).toBeNull();
107+
});
108+
96109
const entry = {
97110
id: "tool-1",
98111
createdAt: "2026-09-01T12:00:00Z",

‎apps/web/src/components/chat/MessagesTimeline.logic.ts‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ import {
3434
type TimelineEntry,
3535
type WorkLogEntry,
3636
} from "../../session-logic";
37-
import { type ChatMessage, type ProposedPlan, type TurnDiffSummary } from "../../types";
37+
import {
38+
type ChatMessage,
39+
type ProposedPlan,
40+
type ThreadShell,
41+
type TurnDiffSummary,
42+
} from "../../types";
3843
import {
3944
type MessageId,
4045
type WorktreeSetupSnapshot,
@@ -182,6 +187,13 @@ export function threadReadTargetId(entry: Pick<WorkLogEntry, "structuredPayload"
182187

183188
const THREAD_READ_OBJECT = " a T3 thread";
184189

190+
export function threadReadTargetTitle(
191+
shell: Pick<ThreadShell, "title" | "archivedAt" | "deletedAt"> | null,
192+
) {
193+
if (!shell || shell.archivedAt !== null || shell.deletedAt !== null) return null;
194+
return shell.title.trim() || null;
195+
}
196+
185197
/**
186198
* Names the read thread in place of the generic object ("Read a T3 thread" becomes
187199
* `Read thread “Title”`), keeping the label's tense. Null keeps the generic label.

‎apps/web/src/components/chat/MessagesTimeline.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ import {
210210
shouldPreserveAssistantLineBreaks,
211211
threadReadLabelPrefix,
212212
threadReadTargetId,
213+
threadReadTargetTitle,
213214
toolGroupAction,
214215
workEntryDisplayLabel,
215216
workEntryReadOutput,
@@ -3728,9 +3729,8 @@ function LiveActivityContent({
37283729
function useThreadReadTarget(entry: TimelineWorkEntry, environmentId: EnvironmentId) {
37293730
const rawThreadId = threadReadTargetId(entry);
37303731
const threadId = rawThreadId === null ? null : ThreadId.make(rawThreadId);
3731-
const title = useThreadShell(
3732-
threadId ? scopeThreadRef(environmentId, threadId) : null,
3733-
)?.title.trim();
3732+
const shell = useThreadShell(threadId ? scopeThreadRef(environmentId, threadId) : null);
3733+
const title = threadReadTargetTitle(shell);
37343734
return threadId && title ? { threadId, title } : null;
37353735
}
37363736

0 commit comments

Comments
 (0)