Skip to content

Commit eeb62da

Browse files
committed
fix(threads): avoid nested workspace bleed on reload
1 parent 85f0e59 commit eeb62da

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

src/features/threads/hooks/useThreadActions.test.tsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,53 @@ describe("useThreadActions", () => {
11821182
});
11831183
});
11841184

1185+
it("does not absorb nested child workspace threads when reloading one workspace", async () => {
1186+
const parentWorkspace: WorkspaceInfo = {
1187+
...workspace,
1188+
id: "ws-parent",
1189+
path: "/tmp/codex",
1190+
};
1191+
const childWorkspace: WorkspaceInfo = {
1192+
...workspaceTwo,
1193+
id: "ws-child",
1194+
path: "/tmp/codex/subdir",
1195+
};
1196+
vi.mocked(listWorkspaces).mockResolvedValue([parentWorkspace, childWorkspace]);
1197+
vi.mocked(listThreads).mockResolvedValue({
1198+
result: {
1199+
data: [
1200+
{
1201+
id: "thread-child-only",
1202+
cwd: "/tmp/codex/subdir/project",
1203+
preview: "Child workspace thread",
1204+
updated_at: 5000,
1205+
},
1206+
],
1207+
nextCursor: null,
1208+
},
1209+
});
1210+
vi.mocked(getThreadTimestamp).mockReturnValue(5000);
1211+
1212+
const { result, dispatch } = renderActions();
1213+
1214+
await act(async () => {
1215+
await result.current.listThreadsForWorkspace(parentWorkspace);
1216+
});
1217+
1218+
expect(listWorkspaces).toHaveBeenCalled();
1219+
const parentSetThreadsAction = dispatch.mock.calls
1220+
.map(([action]) => action)
1221+
.find(
1222+
(action) =>
1223+
action?.type === "setThreads" &&
1224+
action?.workspaceId === "ws-parent",
1225+
) as
1226+
| { type: "setThreads"; threads: Array<{ id: string }>; workspaceId: string }
1227+
| undefined;
1228+
1229+
expect(parentSetThreadsAction?.threads.map((thread) => thread.id) ?? []).toEqual([]);
1230+
});
1231+
11851232
it("preserves list state when requested", async () => {
11861233
vi.mocked(listThreads).mockResolvedValue({
11871234
result: {

src/features/threads/hooks/useThreadActions.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,18 @@ export function useThreadActions({
569569
try {
570570
const requester = targets.find((workspace) => workspace.connected) ?? targets[0];
571571
const matchingThreadsByWorkspace: Record<string, Record<string, unknown>[]> = {};
572-
const workspacePathLookup = buildWorkspacePathLookup(targets);
572+
let workspacePathLookup = buildWorkspacePathLookup(targets);
573+
try {
574+
const knownWorkspaces = await listWorkspacesService();
575+
if (knownWorkspaces.length > 0) {
576+
workspacePathLookup = buildWorkspacePathLookup([
577+
...knownWorkspaces,
578+
...targets,
579+
]);
580+
}
581+
} catch {
582+
workspacePathLookup = buildWorkspacePathLookup(targets);
583+
}
573584
const uniqueThreadIdsByWorkspace: Record<string, Set<string>> = {};
574585
const resumeCursorByWorkspace: Record<string, string | null> = {};
575586
targets.forEach((workspace) => {

0 commit comments

Comments
 (0)