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";