diff --git a/apps/web/src/pages/agents-page.tsx b/apps/web/src/pages/agents-page.tsx index eefe7b812..7a096b3a4 100644 --- a/apps/web/src/pages/agents-page.tsx +++ b/apps/web/src/pages/agents-page.tsx @@ -26,9 +26,9 @@ import type { ReactNode } from "react"; import type { AgentDefinition, AgentInstance } from "../agents-api"; import type { AgentDirectoryData } from "../agents-api"; -import { PrincipalsSchema, useAPIQuery } from "../api"; import type { APIQuery } from "../api"; import { useAgentDirectory } from "../agents-api"; +import { useBench } from "../bench-context"; import { countProp } from "../optional-props"; import { QueryView } from "../query-view"; import { CreateAgentDialog } from "./create-agent-dialog"; @@ -275,6 +275,8 @@ export function AgentsPage({ const [createOpen, setCreateOpen] = useState(false); const isReady = directory.kind === "ready"; + const canCreate = + directory.kind === "ready" && directory.data.tenantId !== ""; return ( <> @@ -299,7 +301,7 @@ export function AgentsPage({ @@ -434,7 +436,7 @@ export function AgentsPage({ }} - {isReady && ( + {canCreate && ( = - principals.kind !== "ready" - ? principals - : membership === undefined + memberships.kind !== "ready" + ? memberships + : selectedTenantId === null ? { kind: "ready", data: { diff --git a/apps/web/src/pages/routines-page.tsx b/apps/web/src/pages/routines-page.tsx index 09c872239..8933c5d32 100644 --- a/apps/web/src/pages/routines-page.tsx +++ b/apps/web/src/pages/routines-page.tsx @@ -1,8 +1,8 @@ // The Routines screen: named automations over workflow runs. Follows // runs-page.tsx / library-page.tsx's shape (pure `*Page` components fed -// `APIQuery` props, a `*Route` container that resolves data) plus -// chat-page.tsx's tenant-resolution convention — the account's first -// bench membership, since this app has no bench switcher yet. +// `APIQuery` props, a `*Route` container that resolves data). The active +// bench comes from `useBench()` — the shell's one source of truth — never +// a page-local `/api/me/principals` fetch that ignores the switcher. // // The create flow's trigger picker is workbench-specific composition // (`RoutineTrigger`'s exact shape, including the raw-cron escape hatch) @@ -41,9 +41,11 @@ import type { BadgeTone } from "@corbits/react-ui"; import { Clock, Plus } from "lucide-react"; import { useState } from "react"; -import { PrincipalsSchema, RunsSchema, useAPIQuery } from "../api"; +import { RunsSchema, useAPIQuery } from "../api"; import type { APIQuery, WorkflowRun } from "../api"; +import { useBench } from "../bench-context"; import { countProp } from "../optional-props"; + import { QueryView } from "../query-view"; import { approximateNextRun, cadenceLabel } from "../routine-trigger"; import { @@ -645,12 +647,11 @@ export function RoutinesRoute({ readonly path: string; readonly navigate: (to: string) => void; }) { - const principals = useAPIQuery("/api/me/principals", PrincipalsSchema); + // BenchProvider owns the active tenant. Never re-fetch principals and take + // memberships[0] — that ignores the shell's bench switcher. + const { selectedTenantId } = useBench(); const allRuns = useAPIQuery("/api/me/workflows/runs", RunsSchema); - const tenantId = - principals.kind === "ready" - ? (principals.data.data[0]?.tenantId ?? null) - : null; + const tenantId = selectedTenantId; // Bumped after a mutation (create/toggle) so the affected queries // re-run without a full page reload — `useTenantQuery`'s effect keys diff --git a/apps/web/test/pages.test.tsx b/apps/web/test/pages.test.tsx index c0e847037..d2635ce77 100644 --- a/apps/web/test/pages.test.tsx +++ b/apps/web/test/pages.test.tsx @@ -212,6 +212,25 @@ describe("live data", () => { expect(markup).toContain("No agents yet"); }); + test("agents disables Create when no bench is selected", () => { + const markup = renderToStaticMarkup( + undefined} + />, + ); + expect(markup).toMatch( + /disabled[^>]*>[\s\S]*Create agent|Create agent[\s\S]*disabled/, + ); + // Dialog must not mount without a real tenant — no create form markup. + expect(markup).not.toContain("Define a new agent"); + }); + test("home counts what the hub reports", () => { const markup = renderToStaticMarkup(