diff --git a/ui/src/pages/AgentDetail.tsx b/ui/src/pages/AgentDetail.tsx
index f9d92dabe5..0d09353efd 100644
--- a/ui/src/pages/AgentDetail.tsx
+++ b/ui/src/pages/AgentDetail.tsx
@@ -1264,7 +1264,6 @@ export function AgentDetail() {
agent={agent}
companyId={resolvedCompanyId}
assignLabel="Assign Task"
- showRun={false}
showStatus={false}
canRunWithProviderTrace={canUseProviderTrace}
actionsDisabled={agentAction.isPending}
diff --git a/ui/src/pages/Agents.production.tsx b/ui/src/pages/Agents.production.tsx
index 8e519f538b..7ba12ed9e4 100644
--- a/ui/src/pages/Agents.production.tsx
+++ b/ui/src/pages/Agents.production.tsx
@@ -13,7 +13,6 @@ import { useSidebar } from "../context/SidebarContext";
import { queryKeys } from "../lib/queryKeys";
import { isPlatformManagedEnvironment } from "../lib/managed-sandbox-environment";
import { AgentStatusBadge, AgentStatusCapsule } from "../components/StatusBadge";
-import { AgentActionButtons } from "../components/AgentActionButtons";
import { MembershipAction } from "../components/MembershipAction";
import { StarToggle } from "../components/StarToggle";
import { EntityRow } from "../components/EntityRow";
@@ -442,22 +441,6 @@ export function Agents() {
- {/* Row actions mirror the agent detail page; stop the click
- from bubbling to the row link so buttons don't navigate.
- Hidden on mobile so the agent name keeps room to render. */}
-
{
- e.preventDefault();
- e.stopPropagation();
- }}
- >
-
-
({
@@ -357,6 +358,40 @@ describe("Agents", () => {
vi.clearAllMocks();
});
+ it.each([
+ ["streamlined", Agents],
+ ["production", ProductionAgents],
+ ] as const)("omits the action bar from %s agent list rows", async (_mode, AgentList) => {
+ mockAgentsApi.list.mockResolvedValue([
+ makeAgent({ name: "Alpha", status: "active" }),
+ makeAgent({ id: "agent-paused", name: "Paused agent", status: "paused" }),
+ ]);
+ root = createRoot(container);
+ await act(async () => {
+ root!.render(
+
+
+
+
+ ,
+ );
+ });
+ await flushReact();
+ await flushReact();
+ const listToggle = container.querySelector('button[aria-label="List view"]');
+ await act(async () => { listToggle?.click(); });
+ await flushReact();
+
+ for (const name of ["Alpha", "Paused agent"]) {
+ const row = findAgentRow(container, name);
+ expect(row).not.toBeNull();
+ expect(row?.getAttribute("href")).toMatch(/^\/agents\//);
+ expect(row?.querySelector('button[aria-label^="Open actions for"]')).toBeNull();
+ const buttons = Array.from(row?.querySelectorAll("button") ?? []).map((button) => button.textContent);
+ expect(buttons).not.toEqual(expect.arrayContaining([expect.stringMatching(/Assign Task|Run Heartbeat|Run with provider trace|Pause|Resume/)]));
+ }
+ });
+
it("shows the configured model beside the adapter on the all agents page", async () => {
root = createRoot(container);
await act(async () => {
@@ -479,15 +514,11 @@ describe("Agents", () => {
expect(subtitle).toBeDefined();
expect(subtitle?.classList.contains("truncate")).toBe(true);
const actions = row?.querySelector('button[aria-label="Open actions for Paperclip Engineer With A Much Longer Display Name"]');
- expect(actions).not.toBeNull();
- // Neither the action button nor its ancestors may hide the mobile menu.
- for (let node = actions; node && node !== row; node = node.parentElement) {
- expect(node.classList.contains("hidden")).toBe(false);
- }
- await act(async () => { (actions as HTMLButtonElement).click(); });
- await flushReact();
- expect(document.body.textContent).toContain("Duplicate");
- expect(document.body.textContent).toContain("Terminate");
+ expect(actions).toBeNull();
+ expect(row?.textContent).not.toContain("Assign Task");
+ expect(row?.textContent).not.toContain("Run Heartbeat");
+ expect(row?.textContent).not.toContain("Run with provider trace");
+ expect(row?.textContent).not.toContain("Pause");
});
it("uses the built-in agents route segment as the built-in filter", async () => {
diff --git a/ui/src/pages/Agents.tsx b/ui/src/pages/Agents.tsx
index 9c83b9ec01..1c0584c05a 100644
--- a/ui/src/pages/Agents.tsx
+++ b/ui/src/pages/Agents.tsx
@@ -6,7 +6,6 @@ import { builtInAgentsApi, type BuiltInAgentState } from "../api/builtInAgents";
import { environmentsApi } from "../api/environments";
import { heartbeatsApi } from "../api/heartbeats";
import { instanceSettingsApi } from "../api/instanceSettings";
-import { accessApi } from "../api/access";
import { useCompany } from "../context/CompanyContext";
import { useDialogActions } from "../context/DialogContext";
import { useBreadcrumbs } from "../context/BreadcrumbContext";
@@ -15,7 +14,6 @@ import { useStreamlinedUiEnabled } from "../hooks/useStreamlinedUiEnabled";
import { queryKeys } from "../lib/queryKeys";
import { isPlatformManagedEnvironment } from "../lib/managed-sandbox-environment";
import { AgentStatusBadge, AgentStatusCapsule } from "../components/StatusBadge";
-import { AgentActionButtons } from "../components/AgentActionButtons";
import { MembershipAction } from "../components/MembershipAction";
import { StarToggle } from "../components/StarToggle";
import { EntityRow } from "../components/EntityRow";
@@ -211,15 +209,6 @@ export function Agents({ initialView = "list" }: { initialView?: AgentsView } =
setView(streamlinedUiEnabled ? initialView : "org");
}, [initialView, streamlinedUiEnabled]);
- const { data: boardAccess } = useQuery({
- queryKey: queryKeys.access.currentBoardAccess,
- queryFn: () => accessApi.getCurrentBoardAccess(),
- retry: false,
- });
- const canUseProviderTrace =
- boardAccess?.source === "local_implicit" ||
- boardAccess?.isInstanceAdmin === true;
-
const { data: instanceSettings } = useQuery({
queryKey: queryKeys.instance.settings,
queryFn: () => instanceSettingsApi.get(),
@@ -411,32 +400,11 @@ export function Agents({ initialView = "list" }: { initialView?: AgentsView } =
) : (
)}
- secondaryRow={
-
- {builtInCluster && (
-
- {builtInCluster}
-
- )}
- {/* Actions have their own wrapping line, so names keep their width. */}
-
{
- e.preventDefault();
- e.stopPropagation();
- }}
- >
-
-
+ secondaryRow={builtInCluster && (
+
+ {builtInCluster}
- }
+ )}
meta={
{builtInCluster && (