refactor(app): move agent tab visibility policy (#851)

This commit is contained in:
Mohamed Boudra
2026-05-09 23:28:35 +08:00
committed by GitHub
parent bb5ac5b1d0
commit 263886fc1c
5 changed files with 78 additions and 23 deletions
@@ -133,9 +133,10 @@ import {
} from "@/screens/workspace/workspace-route-state"; } from "@/screens/workspace/workspace-route-state";
import { renderWorkspaceRouteGate } from "@/screens/workspace/workspace-route-state-views"; import { renderWorkspaceRouteGate } from "@/screens/workspace/workspace-route-state-views";
import { import {
buildWorkspaceTabSnapshot,
deriveWorkspaceAgentVisibility, deriveWorkspaceAgentVisibility,
workspaceAgentVisibilityEqual, workspaceAgentVisibilityEqual,
} from "@/screens/workspace/workspace-agent-visibility"; } from "@/workspace-tabs/agent-visibility";
import { deriveWorkspacePaneState } from "@/screens/workspace/workspace-pane-state"; import { deriveWorkspacePaneState } from "@/screens/workspace/workspace-pane-state";
import { import {
buildWorkspacePaneContentModel, buildWorkspacePaneContentModel,
@@ -1919,16 +1920,17 @@ function WorkspaceScreenContent({
return pending?.serverId === normalizedServerId && pending.lifecycle === "active"; return pending?.serverId === normalizedServerId && pending.lifecycle === "active";
}); });
reconcileWorkspaceTabs(persistenceKey, { reconcileWorkspaceTabs(
agentsHydrated: hasHydratedAgents, persistenceKey,
terminalsHydrated: terminalsQuery.isSuccess, buildWorkspaceTabSnapshot({
activeAgentIds: Array.from(workspaceAgentVisibility.activeAgentIds), agentVisibility: workspaceAgentVisibility,
autoOpenAgentIds: Array.from(workspaceAgentVisibility.autoOpenAgentIds), agentsHydrated: hasHydratedAgents,
knownAgentIds: Array.from(workspaceAgentVisibility.knownAgentIds), terminalsHydrated: terminalsQuery.isSuccess,
knownTerminalIds, knownTerminalIds,
standaloneTerminalIds, standaloneTerminalIds,
hasActivePendingDraftCreate: hasActivePendingDraftCreateInWorkspace, hasActivePendingDraftCreate: hasActivePendingDraftCreateInWorkspace,
}); }),
);
}, [ }, [
hasHydratedAgents, hasHydratedAgents,
hasHydratedWorkspaceLayoutStore, hasHydratedWorkspaceLayoutStore,
@@ -1,9 +1,10 @@
import type { DaemonClient } from "@server/client/daemon-client"; import type { DaemonClient } from "@server/client/daemon-client";
import { afterEach, describe, expect, it, vi } from "vitest"; import { afterEach, describe, expect, it, vi } from "vitest";
import { import {
buildWorkspaceTabSnapshot,
deriveWorkspaceAgentVisibility, deriveWorkspaceAgentVisibility,
type WorkspaceAgentVisibility, type WorkspaceAgentVisibility,
} from "@/screens/workspace/workspace-agent-visibility"; } from "@/workspace-tabs/agent-visibility";
import { selectSubagentsForParent } from "@/subagents"; import { selectSubagentsForParent } from "@/subagents";
import { buildWorkspaceTabPersistenceKey, useWorkspaceLayoutStore } from "./workspace-layout-store"; import { buildWorkspaceTabPersistenceKey, useWorkspaceLayoutStore } from "./workspace-layout-store";
import { useSessionStore, type Agent } from "./session-store"; import { useSessionStore, type Agent } from "./session-store";
@@ -151,15 +152,17 @@ function deriveVisibilityFromSession(): WorkspaceAgentVisibility {
} }
function reconcileWorkspaceTabs(workspaceKey: string, visibility: WorkspaceAgentVisibility): void { function reconcileWorkspaceTabs(workspaceKey: string, visibility: WorkspaceAgentVisibility): void {
useWorkspaceLayoutStore.getState().reconcileTabs(workspaceKey, { useWorkspaceLayoutStore.getState().reconcileTabs(
agentsHydrated: true, workspaceKey,
terminalsHydrated: true, buildWorkspaceTabSnapshot({
activeAgentIds: visibility.activeAgentIds, agentVisibility: visibility,
autoOpenAgentIds: visibility.autoOpenAgentIds, agentsHydrated: true,
knownAgentIds: visibility.knownAgentIds, terminalsHydrated: true,
standaloneTerminalIds: [], knownTerminalIds: [],
hasActivePendingDraftCreate: false, standaloneTerminalIds: [],
}); hasActivePendingDraftCreate: false,
}),
);
} }
function getWorkspaceTabIds(workspaceKey: string): string[] { function getWorkspaceTabIds(workspaceKey: string): string[] {
+1 -1
View File
@@ -1,5 +1,5 @@
// Pure-data entry point for callers that don't want React Native deps in // Pure-data entry point for callers that don't want React Native deps in
// their dependency graph (e.g. workspace-agent-visibility.ts is plain JS // their dependency graph (e.g. workspace-tabs/agent-visibility.ts is plain
// data derivation and its tests run without an RN environment). // data derivation and its tests run without an RN environment).
// //
// The full module entry `@/subagents` re-exports these too, alongside the // The full module entry `@/subagents` re-exports these too, alongside the
@@ -1,10 +1,11 @@
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import type { Agent } from "@/stores/session-store"; import type { Agent } from "@/stores/session-store";
import { import {
buildWorkspaceTabSnapshot,
deriveWorkspaceAgentVisibility, deriveWorkspaceAgentVisibility,
shouldPruneWorkspaceAgentTab, shouldPruneWorkspaceAgentTab,
workspaceAgentVisibilityEqual, workspaceAgentVisibilityEqual,
} from "@/screens/workspace/workspace-agent-visibility"; } from "@/workspace-tabs/agent-visibility";
function makeAgent(input: { function makeAgent(input: {
id: string; id: string;
@@ -265,6 +266,34 @@ describe("workspace agent visibility", () => {
expect(result.knownAgentIds).toEqual(new Set(["recent-agent"])); expect(result.knownAgentIds).toEqual(new Set(["recent-agent"]));
}); });
it("builds the tab reconciliation snapshot without callers unpacking agent visibility", () => {
const agentVisibility = {
activeAgentIds: new Set(["active-agent"]),
autoOpenAgentIds: new Set(["root-agent"]),
knownAgentIds: new Set(["active-agent", "archived-agent"]),
};
expect(
buildWorkspaceTabSnapshot({
agentVisibility,
agentsHydrated: true,
terminalsHydrated: true,
knownTerminalIds: ["terminal-1", "script-terminal"],
standaloneTerminalIds: ["terminal-1"],
hasActivePendingDraftCreate: false,
}),
).toEqual({
agentsHydrated: true,
terminalsHydrated: true,
activeAgentIds: agentVisibility.activeAgentIds,
autoOpenAgentIds: agentVisibility.autoOpenAgentIds,
knownAgentIds: agentVisibility.knownAgentIds,
knownTerminalIds: ["terminal-1", "script-terminal"],
standaloneTerminalIds: ["terminal-1"],
hasActivePendingDraftCreate: false,
});
});
describe("workspaceAgentVisibilityEqual", () => { describe("workspaceAgentVisibilityEqual", () => {
it("returns true for identical sets", () => { it("returns true for identical sets", () => {
const a = { const a = {
@@ -1,4 +1,5 @@
import type { Agent } from "@/stores/session-store"; import type { Agent } from "@/stores/session-store";
import type { WorkspaceTabSnapshot } from "@/stores/workspace-layout-actions";
import { shouldAutoOpenAgentTab } from "@/subagents/policies"; import { shouldAutoOpenAgentTab } from "@/subagents/policies";
import { normalizeWorkspacePath } from "@/utils/workspace-identity"; import { normalizeWorkspacePath } from "@/utils/workspace-identity";
@@ -52,6 +53,26 @@ export function deriveWorkspaceAgentVisibility(input: {
return { activeAgentIds, autoOpenAgentIds, knownAgentIds }; return { activeAgentIds, autoOpenAgentIds, knownAgentIds };
} }
export function buildWorkspaceTabSnapshot(input: {
agentVisibility: WorkspaceAgentVisibility;
agentsHydrated: boolean;
terminalsHydrated: boolean;
knownTerminalIds: Iterable<string>;
standaloneTerminalIds: Iterable<string>;
hasActivePendingDraftCreate: boolean;
}): WorkspaceTabSnapshot {
return {
agentsHydrated: input.agentsHydrated,
terminalsHydrated: input.terminalsHydrated,
activeAgentIds: input.agentVisibility.activeAgentIds,
autoOpenAgentIds: input.agentVisibility.autoOpenAgentIds,
knownAgentIds: input.agentVisibility.knownAgentIds,
knownTerminalIds: input.knownTerminalIds,
standaloneTerminalIds: input.standaloneTerminalIds,
hasActivePendingDraftCreate: input.hasActivePendingDraftCreate,
};
}
export function workspaceAgentVisibilityEqual( export function workspaceAgentVisibilityEqual(
a: WorkspaceAgentVisibility, a: WorkspaceAgentVisibility,
b: WorkspaceAgentVisibility, b: WorkspaceAgentVisibility,