From 7e4f858486812010022d833e8360e7cb129b4038 Mon Sep 17 00:00:00 2001 From: Sawyer Date: Tue, 29 Sep 2026 23:22:31 -0700 Subject: [PATCH] fix(web): workers show their real workbench and Settings Models matches the other sections (CL-9603) --- apps/web/src/bench/tools-tab.tsx | 7 ++- apps/web/src/pages/worker-page.tsx | 11 +--- apps/web/src/pages/workers-page.tsx | 30 ++++----- apps/web/src/settings/models-section.tsx | 77 +++++++----------------- apps/web/src/settings/people-section.tsx | 7 ++- apps/web/src/shell/sidebar-footer.css | 4 ++ apps/web/src/shell/sidebar-footer.tsx | 1 + 7 files changed, 54 insertions(+), 83 deletions(-) create mode 100644 apps/web/src/shell/sidebar-footer.css diff --git a/apps/web/src/bench/tools-tab.tsx b/apps/web/src/bench/tools-tab.tsx index 566ae9f64..35ffb7e27 100644 --- a/apps/web/src/bench/tools-tab.tsx +++ b/apps/web/src/bench/tools-tab.tsx @@ -1,9 +1,10 @@ -import { Badge, Button } from "@corbits/react-ui"; +import { Button } from "@corbits/react-ui"; import { QueryView } from "@/lib/api-query"; import { Plugs } from "@/lib/icons"; import { Link } from "../navigation"; import { useMcpServers } from "../tools/mcp-servers-query"; +import "../tools/tools-page.css"; /** Tools the workspace catalog makes available here; "Connected" once an * agent in this workbench binds the server. */ @@ -36,9 +37,9 @@ export function ToolsTab({ workbenchTenantId }: { readonly workbenchTenantId: st {server.name} {server.url} - 0 ? "success" : "neutral"}> + 0 ? "tool-live" : "tool-kind"}> {server.agentNames.length > 0 ? "Connected" : "Available"} - + Manage diff --git a/apps/web/src/pages/worker-page.tsx b/apps/web/src/pages/worker-page.tsx index 4f49cde55..2bec71a42 100644 --- a/apps/web/src/pages/worker-page.tsx +++ b/apps/web/src/pages/worker-page.tsx @@ -9,7 +9,6 @@ import type { GrantEffect } from "@intx/types"; import { WorkbenchAvatar } from "@/chat/avatar"; import { isMyraAgent, listChatAgents, type ChatAgent } from "@/chat/threads-api"; -import { listWorkbenches } from "@/chat/workbench-tenants"; import { ChatCircle } from "@/lib/icons"; import { QueryView, describeApiError } from "@/lib/api-query"; import { listTopLevelRuns } from "../agents-api"; @@ -29,7 +28,7 @@ import { useTenantQuery } from "../routines-api"; import { StageTopBar } from "../shell/stage-top-bar"; import { WORKERS_PATH_PREFIX } from "../path-ids"; import { workbenchPath } from "../workbench-path"; -import { StatusPill, workerStatus } from "./workers-page"; +import { StatusPill, useWorkbenchList, workerStatus } from "./workers-page"; function sourceKey(tenantId: string, agentId: string) { return [...tenantKeys.agents(tenantId), "source", agentId] as const; @@ -308,13 +307,7 @@ export function WorkerRoute({ agentId }: { readonly agentId: string }) { selectedTenantId !== null, () => listChatAgents(selectedTenantId as string), ); - // The workspace is not a bench; the worker's workbench is one of its child - // tenants, the same rows the sidebar lists. - const benches = useQuery({ - queryKey: tenantKeys.workbenches(selectedTenantId ?? "none"), - enabled: selectedTenantId !== null, - queryFn: () => listWorkbenches(selectedTenantId as string), - }); + const benches = useWorkbenchList(selectedTenantId); const bench = benches.data?.[0]; return ( diff --git a/apps/web/src/pages/workers-page.tsx b/apps/web/src/pages/workers-page.tsx index f9533349e..9487c296f 100644 --- a/apps/web/src/pages/workers-page.tsx +++ b/apps/web/src/pages/workers-page.tsx @@ -4,13 +4,14 @@ import { useState } from "react"; import { Button, RichEmptyState, toast } from "@corbits/react-ui"; import { Plus, Robot } from "@/lib/icons"; -import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { reportError } from "@corbits/error-sink"; import { QueryView } from "@/lib/api-query"; import { tenantKeys } from "../query-client"; import { isAgentNotRunning, listChatAgents, type ChatAgent } from "@/chat/threads-api"; import { WorkbenchAvatar } from "@/chat/avatar"; +import { listWorkbenches } from "@/chat/workbench-tenants"; import { describeRestartFailure, redeployWorkbenchAgent } from "../workbench-create"; import { useBench } from "../bench-context"; import { Link } from "../navigation"; @@ -35,6 +36,16 @@ export function workerStatus(agent: Pick listWorkbenches(tenantId as string), + }); +} + export function workerPath(agentId: string): string { return `${WORKERS_PATH_PREFIX}/${encodeURIComponent(agentId)}`; } @@ -69,13 +80,12 @@ const ROW_GRID = export function WorkersRosterList({ tenantId, - benchName, agents, }: { readonly tenantId: string; - readonly benchName: string; readonly agents: readonly ChatAgent[]; }) { + const benchName = useWorkbenchList(tenantId).data?.[0]?.title ?? ""; const [filter, setFilter] = useState("all"); const [query, setQuery] = useState(""); const queryClient = useQueryClient(); @@ -191,7 +201,7 @@ export function WorkersRosterList({ } export function WorkersRoute() { - const { selectedTenantId, benchMemberships } = useBench(); + const { selectedTenantId } = useBench(); const agentsQuery = useTenantQuery( tenantKeys.agents(selectedTenantId ?? "none"), selectedTenantId !== null, @@ -200,10 +210,6 @@ export function WorkersRoute() { // seen without a reload. (agents) => ((agents?.some((agent) => agent.liveAddress === null) ?? false) ? 3000 : false), ); - const benchName = - benchMemberships.find((member) => member.tenantId === selectedTenantId)?.tenantName ?? - "This workbench"; - const queryClient = useQueryClient(); const [createOpen, setCreateOpen] = useState(false); @@ -231,13 +237,7 @@ export function WorkersRoute() { ) : ( <> - {(agents) => ( - - )} + {(agents) => } {({ providers, models }) => ( - @@ -60,7 +51,7 @@ export function ModelsSection({ tenantId }: { readonly tenantId: string | null }

{SETTINGS_STRINGS.modelsCatalogHeading}

-
+ )} ); @@ -76,24 +67,11 @@ function ProvidersTable({ providers }: { readonly providers: readonly Provider[] ); } return ( -
- - - - {SETTINGS_STRINGS.modelsProviderColumn} - Plugin - - - - {providers.map((provider) => ( - - {provider.name} - {provider.plugin} - - ))} - -
-
+ <> + {providers.map((provider) => ( + + ))} + ); } @@ -107,30 +85,19 @@ function ModelsTable({ models }: { readonly models: readonly ModelInfo[] }) { ); } return ( -
- - - - {SETTINGS_STRINGS.modelsModelColumn} - {SETTINGS_STRINGS.modelsOfferingsColumn} - - - - {models.map((model) => ( - - {model.displayName ?? model.canonicalName} - - {model.offerings.map((offering, index) => ( - - {offering.providerName} - {index === 0 ? ` · ${SETTINGS_STRINGS.modelsDefaultBadge}` : ""} - - ))} - - + <> + {models.map((model) => ( + ( + + {offering.providerName} + {index === 0 ? ` · ${SETTINGS_STRINGS.modelsDefaultBadge}` : ""} + ))} - -
-
+ /> + ))} + ); } diff --git a/apps/web/src/settings/people-section.tsx b/apps/web/src/settings/people-section.tsx index 5c55da154..18fa8668c 100644 --- a/apps/web/src/settings/people-section.tsx +++ b/apps/web/src/settings/people-section.tsx @@ -36,6 +36,7 @@ import { } from "./tenancy-api"; import { ConfirmButton } from "../components/confirm-button"; import { SettingsGroup, SettingsRow } from "./rows"; +import "../tools/tools-page.css"; const STATUS_TONE: Record = { active: "success", @@ -363,7 +364,11 @@ export function PeopleTable({ <> {person.email !== undefined ? {person.email} : null} {PRINCIPAL_KIND_LABEL[person.kind]} - {person.status} + {person.status === "active" ? ( + {person.status} + ) : ( + {person.status} + )} {selectableRoles.length === 2 ? null : person.roles.length === 0 diff --git a/apps/web/src/shell/sidebar-footer.css b/apps/web/src/shell/sidebar-footer.css new file mode 100644 index 000000000..b5d5bcc4d --- /dev/null +++ b/apps/web/src/shell/sidebar-footer.css @@ -0,0 +1,4 @@ +/* Canvas surface is near-white; the Tools button sits on the sunk token. */ +[data-theme="canvas"] .sb-tools { + background: var(--surface-sunk); +} diff --git a/apps/web/src/shell/sidebar-footer.tsx b/apps/web/src/shell/sidebar-footer.tsx index 20b3b4c6a..ab2accfe7 100644 --- a/apps/web/src/shell/sidebar-footer.tsx +++ b/apps/web/src/shell/sidebar-footer.tsx @@ -3,6 +3,7 @@ import { Moon, Palette, Plugs, SignOut, SlidersHorizontal, Sun, type Icon } from "@/lib/icons"; import { useEffect, useRef, useState, type KeyboardEvent } from "react"; +import "./sidebar-footer.css"; import { IdentityAvatar } from "../chat/avatar"; import { useSessionUser, useSignOut } from "../navigation"; import { matchesRoute, SETTINGS_PATH } from "../routes";