Keep forked chats focused in new tabs (#2038)

* fix(app): focus explicitly opened workspace tabs

Explicit tab navigation could be overwritten by attention-aware workspace
navigation when the visible agent had just finished. Make workspace navigation
own both normal attention selection and explicit targets so callers cannot
sequence them inconsistently.

* test(app): strengthen forked tab focus assertion
This commit is contained in:
Mohamed Boudra
2026-07-13 15:38:09 +02:00
committed by GitHub
parent fe9a486ac1
commit f350c716b9
18 changed files with 156 additions and 139 deletions
@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import type { WorkspaceTabTarget } from "@/stores/workspace-tabs-store";
import { navigateToPreparedWorkspaceTab, prepareWorkspaceTab } from "@/utils/prepare-workspace-tab";
import { prepareWorkspaceTab } from "@/utils/prepare-workspace-tab";
const SERVER_ID = "server-1";
const WORKSPACE_ID = "/repo/worktree";
@@ -16,11 +16,6 @@ interface RecordedPin {
agentId: string;
}
interface RecordedNavigation {
serverId: string;
workspaceId: string;
}
function createFakeLayout() {
const openedTabs: RecordedOpenedTab[] = [];
const pinnedAgents: RecordedPin[] = [];
@@ -37,21 +32,11 @@ function createFakeLayout() {
};
}
function createFakeNavigator() {
const navigations: RecordedNavigation[] = [];
return {
navigations,
navigateToWorkspace: (serverId: string, workspaceId: string) => {
navigations.push({ serverId, workspaceId });
},
};
}
describe("prepareWorkspaceTab", () => {
it("opens and focuses an agent tab", () => {
const layout = createFakeLayout();
const route = prepareWorkspaceTab(
prepareWorkspaceTab(
{
serverId: SERVER_ID,
workspaceId: WORKSPACE_ID,
@@ -60,30 +45,9 @@ describe("prepareWorkspaceTab", () => {
layout,
);
expect(route).toBe("/h/server-1/workspace/b64_L3JlcG8vd29ya3RyZWU");
expect(layout.openedTabs).toEqual([
{ key: "server-1:/repo/worktree", target: { kind: "agent", agentId: AGENT_ID } },
]);
expect(layout.pinnedAgents).toEqual([]);
});
it("prepares a tab and navigates through the workspace navigation helper", () => {
const layout = createFakeLayout();
const navigator = createFakeNavigator();
const route = navigateToPreparedWorkspaceTab(
{
serverId: SERVER_ID,
workspaceId: WORKSPACE_ID,
target: { kind: "agent", agentId: AGENT_ID },
},
{ ...layout, navigateToWorkspace: navigator.navigateToWorkspace },
);
expect(route).toBe("/h/server-1/workspace/b64_L3JlcG8vd29ya3RyZWU");
expect(layout.openedTabs).toEqual([
{ key: "server-1:/repo/worktree", target: { kind: "agent", agentId: AGENT_ID } },
]);
expect(navigator.navigations).toEqual([{ serverId: SERVER_ID, workspaceId: WORKSPACE_ID }]);
});
});