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:
@@ -10,6 +10,8 @@ import {
|
||||
resolveWorkspaceMapKeyByIdentity,
|
||||
} from "@/utils/workspace-identity";
|
||||
import type { ActiveWorkspaceSelection } from "@/stores/last-workspace-selection";
|
||||
import type { WorkspaceTabTarget } from "@/stores/workspace-tabs-store";
|
||||
import { prepareWorkspaceTab, type PrepareWorkspaceTabDeps } from "@/utils/prepare-workspace-tab";
|
||||
|
||||
export interface RouteSelectionInput {
|
||||
pathname: string;
|
||||
@@ -19,10 +21,16 @@ export interface RouteSelectionInput {
|
||||
};
|
||||
}
|
||||
|
||||
export interface NavigateToWorkspaceDeps {
|
||||
export interface NavigateToWorkspaceInput {
|
||||
serverId: string;
|
||||
workspaceId: string;
|
||||
target?: WorkspaceTabTarget;
|
||||
pin?: boolean;
|
||||
}
|
||||
|
||||
export interface NavigateToWorkspaceDeps extends PrepareWorkspaceTabDeps {
|
||||
getSessionWorkspaces: (serverId: string) => Map<string, WorkspaceDescriptor> | null | undefined;
|
||||
getSessionAgents: (serverId: string) => Iterable<Agent>;
|
||||
openWorkspaceAgentTab: (workspaceKey: string, agentId: string) => void;
|
||||
rememberLastWorkspace: (selection: ActiveWorkspaceSelection) => void;
|
||||
navigateToRoute: (route: string) => void;
|
||||
}
|
||||
@@ -71,27 +79,35 @@ export function parseActiveWorkspaceSelection(
|
||||
}
|
||||
|
||||
export function navigateToWorkspace(
|
||||
serverId: string,
|
||||
workspaceId: string,
|
||||
input: NavigateToWorkspaceInput,
|
||||
deps: NavigateToWorkspaceDeps,
|
||||
): void {
|
||||
const workspaces = deps.getSessionWorkspaces(serverId);
|
||||
const resolvedWorkspaceId = resolveWorkspaceMapKeyByIdentity({
|
||||
workspaces,
|
||||
workspaceId,
|
||||
});
|
||||
const workspaceAgents = resolvedWorkspaceId
|
||||
? Array.from(deps.getSessionAgents(serverId)).filter(
|
||||
(agent) => normalizeWorkspaceOpaqueId(agent.workspaceId) === resolvedWorkspaceId,
|
||||
)
|
||||
: [];
|
||||
const attentionAgentId = pickAttentionAgent(workspaceAgents);
|
||||
if (attentionAgentId && resolvedWorkspaceId) {
|
||||
deps.openWorkspaceAgentTab(`${serverId}:${resolvedWorkspaceId}`, attentionAgentId);
|
||||
): string {
|
||||
if (input.target) {
|
||||
prepareWorkspaceTab({ ...input, target: input.target }, deps);
|
||||
} else {
|
||||
const workspaces = deps.getSessionWorkspaces(input.serverId);
|
||||
const resolvedWorkspaceId = resolveWorkspaceMapKeyByIdentity({
|
||||
workspaces,
|
||||
workspaceId: input.workspaceId,
|
||||
});
|
||||
const workspaceAgents = resolvedWorkspaceId
|
||||
? Array.from(deps.getSessionAgents(input.serverId)).filter(
|
||||
(agent) => normalizeWorkspaceOpaqueId(agent.workspaceId) === resolvedWorkspaceId,
|
||||
)
|
||||
: [];
|
||||
const attentionAgentId = pickAttentionAgent(workspaceAgents);
|
||||
if (attentionAgentId && resolvedWorkspaceId) {
|
||||
deps.openTabFocused(`${input.serverId}:${resolvedWorkspaceId}`, {
|
||||
kind: "agent",
|
||||
agentId: attentionAgentId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
deps.rememberLastWorkspace({ serverId, workspaceId });
|
||||
deps.navigateToRoute(buildHostWorkspaceRoute(serverId, workspaceId));
|
||||
const route = buildHostWorkspaceRoute(input.serverId, input.workspaceId);
|
||||
deps.rememberLastWorkspace({ serverId: input.serverId, workspaceId: input.workspaceId });
|
||||
deps.navigateToRoute(route);
|
||||
return route;
|
||||
}
|
||||
|
||||
export function navigateToLastWorkspace(deps: NavigateToLastWorkspaceDeps): boolean {
|
||||
@@ -99,6 +115,6 @@ export function navigateToLastWorkspace(deps: NavigateToLastWorkspaceDeps): bool
|
||||
if (!selection) {
|
||||
return false;
|
||||
}
|
||||
navigateToWorkspace(selection.serverId, selection.workspaceId, deps);
|
||||
navigateToWorkspace(selection, deps);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user