refactor(site/src/pages): delete unreachable tool render paths (#27527)

This commit is contained in:
Danielle Maywood
2026-07-27 17:59:08 +01:00
committed by GitHub
parent 5af3d95b06
commit 95be28850d
13 changed files with 16 additions and 177 deletions
@@ -23,7 +23,7 @@ const LiveActivitySlot: FC = () => (
data-testid="live-activity-slot"
className="flex h-6 items-center gap-2 text-content-secondary"
>
<ToolIcon name="thinking" isError={false} />
<ToolIcon name="thinking" />
<Shimmer as="span" className="text-[13px] leading-6">
Thinking
</Shimmer>
@@ -1151,30 +1151,4 @@ describe("getSubagentDescriptor", () => {
});
}
});
it("renders list_agents with a fixed generic affordance", () => {
const descriptor = getSubagentDescriptor({
name: "list_agents",
args: {},
result: {
agents: [
{ chat_id: "agent-1", type: "explore", status: "completed" },
{ chat_id: "agent-2", type: "computer_use", status: "running" },
],
total: 2,
returned: 2,
offset: 0,
has_more: false,
},
});
// The list result has no single top-level type, so the descriptor
// must not derive a variant from per-agent types.
expect(descriptor).toMatchObject({
action: "list",
variant: "general",
iconKind: "bot",
supportsDesktopAffordance: false,
});
});
});
@@ -2,7 +2,7 @@ import { ExternalLinkIcon } from "lucide-react";
import type React from "react";
import { Link } from "react-router";
import { ToolCall } from "./ToolCall";
import { asRecord, asString, type ToolStatus } from "./utils";
import { asString, parseArgs, type ToolStatus } from "./utils";
import { WorkspaceBuildLogSection } from "./WorkspaceBuildLogSection";
/**
@@ -32,15 +32,7 @@ export const CreateWorkspaceTool: React.FC<{
labelOverride,
}) => {
const isRunning = status === "running";
let rec: Record<string, unknown> | null = null;
if (resultJson) {
try {
const parsed = JSON.parse(resultJson);
rec = asRecord(parsed);
} catch {
rec = asRecord(resultJson);
}
}
const rec = parseArgs(resultJson);
const ownerName = rec ? asString(rec.owner_name) : "";
const wsName = rec ? asString(rec.workspace_name) : workspaceName;
const workspaceLink = ownerName && wsName ? `/@${ownerName}/${wsName}` : null;
@@ -35,14 +35,6 @@ export const ShortCommand: Story = {
},
};
export const RunningWithoutCommand: Story = {
args: {
command: "",
status: "running",
transcriptBlocks: [],
},
};
export const LongCommand: Story = {
decorators: [
(Story) => (
@@ -56,7 +56,6 @@ export const ExecuteTool: React.FC<ExecuteToolProps> = ({
parsedCommands,
shellToolDisplayMode,
}) => {
const hasCommand = command.trim().length > 0;
const hasTranscriptBlocks = transcriptBlocks.length > 0;
const autoDisplayState: AgentDisplayState =
hasTranscriptBlocks ||
@@ -78,10 +77,6 @@ export const ExecuteTool: React.FC<ExecuteToolProps> = ({
autoDisplayState,
);
if (!hasCommand) {
return null;
}
return (
<ToolCall.Root
key={`${shellToolDisplayMode ?? "auto"}:${autoDisplayState}`}
@@ -53,12 +53,6 @@ const SUBAGENT_VERBS: Record<
error: "Failed to interrupt ",
timeout: "Timed out interrupting ",
},
list: {
completed: "Listed ",
running: "Listing ",
error: "Failed to list ",
timeout: "Timed out listing ",
},
};
/**
@@ -1122,7 +1122,6 @@ export const WaitAgentExploreStreamingFromHistory: Story = {
expect(
canvas.getByRole("button", { name: /Waiting for Explore agent/ }),
).toBeInTheDocument();
expect(canvas.queryByText("Waiting for sub-agent…")).toBeNull();
},
};
@@ -1142,7 +1141,6 @@ export const MessageAgentExploreStreamingFromResult: Story = {
expect(
canvas.getByRole("button", { name: /Messaging Explore agent/ }),
).toBeInTheDocument();
expect(canvas.queryByText("Messaging sub-agent…")).toBeNull();
},
};
@@ -1114,10 +1114,9 @@ export const Tool = memo(
ref,
...props
}: ToolProps) => {
const Renderer =
isSubagentToolName(name) && name !== "list_agents"
? SubagentRenderer
: (toolRenderers[name] ?? GenericToolRenderer);
const Renderer = isSubagentToolName(name)
? SubagentRenderer
: (toolRenderers[name] ?? GenericToolRenderer);
const isShellTool = name === "execute" || name === "process_output";
if (!shouldRenderTool({ name, status, args, result })) {
return null;
@@ -15,7 +15,6 @@ import {
import { cn } from "#/utils/cn";
import { Shimmer } from "../Shimmer";
import { TranscriptRow } from "../TranscriptRow";
import type { SubagentIconKind } from "./subagentDescriptor";
import { ToolIcon } from "./ToolIcon";
import type { ToolStatus } from "./utils";
@@ -208,7 +207,6 @@ type ToolCallLeadingIconProps = {
children?: ReactNode;
iconUrl?: string;
serverName?: string;
subagentIconKind?: SubagentIconKind;
};
const LeadingIcon: FC<ToolCallLeadingIconProps> = ({
@@ -216,9 +214,8 @@ const LeadingIcon: FC<ToolCallLeadingIconProps> = ({
children,
iconUrl,
serverName,
subagentIconKind,
}) => {
const { active, failed } = useToolCallContext();
const { active } = useToolCallContext();
if (children) {
return <>{children}</>;
}
@@ -229,11 +226,9 @@ const LeadingIcon: FC<ToolCallLeadingIconProps> = ({
return (
<ToolIcon
name={name}
isError={failed}
isRunning={active}
iconUrl={iconUrl}
serverName={serverName}
subagentIconKind={subagentIconKind}
/>
);
};
@@ -267,16 +262,11 @@ const Label: FC<ToolCallLabelProps> = ({
type ToolCallStatusProps = {
className?: string;
errorMessage?: string;
};
const Status: FC<ToolCallStatusProps> = ({ className, errorMessage }) => {
const {
active,
errorMessage: contextErrorMessage,
failed,
} = useToolCallContext();
const message = errorMessage || contextErrorMessage || "Tool call failed";
const Status: FC<ToolCallStatusProps> = ({ className }) => {
const { active, errorMessage, failed } = useToolCallContext();
const message = errorMessage || "Tool call failed";
return (
<>
{active && (
@@ -367,7 +357,6 @@ type ToolCallHeaderProps = {
label: ReactNode;
iconUrl?: string;
serverName?: string;
subagentIconKind?: SubagentIconKind;
secondaryLabel?: ReactNode;
trailing?: ReactNode;
showStatus?: boolean;
@@ -388,7 +377,6 @@ const Header: FC<ToolCallHeaderProps> = ({
label,
iconUrl,
serverName,
subagentIconKind,
secondaryLabel,
trailing,
showStatus = true,
@@ -396,12 +384,7 @@ const Header: FC<ToolCallHeaderProps> = ({
}) => {
return (
<HeaderButton className={headerClassName}>
<LeadingIcon
name={iconName}
iconUrl={iconUrl}
serverName={serverName}
subagentIconKind={subagentIconKind}
/>
<LeadingIcon name={iconName} iconUrl={iconUrl} serverName={serverName} />
<Label>{label}</Label>
{secondaryLabel}
{showStatus && <Status />}
@@ -22,19 +22,13 @@ import {
TooltipTrigger,
} from "#/components/Tooltip/Tooltip";
import { cn } from "#/utils/cn";
import {
isSubagentToolName,
type SubagentIconKind,
} from "./subagentDescriptor";
export const ToolIcon: React.FC<{
name: string;
isError: boolean;
iconUrl?: string;
isRunning?: boolean;
serverName?: string;
subagentIconKind?: SubagentIconKind;
}> = ({ name, iconUrl, isRunning, serverName, subagentIconKind }) => {
}> = ({ name, iconUrl, isRunning, serverName }) => {
const [imgError, setImgError] = useState(false);
const color = "text-current";
const base = cn(
@@ -80,20 +74,6 @@ export const ToolIcon: React.FC<{
return img;
}
if (isSubagentToolName(name)) {
// This name-based fallback only exists for legacy callers that do
// not pass a descriptor. The descriptor path should provide
// subagentIconKind for new subagent types instead of extending it.
const iconKind =
subagentIconKind ||
(name === "spawn_computer_use_agent" ? "monitor" : "bot");
return iconKind === "monitor" ? (
<MonitorIcon className={base} />
) : (
<BotIcon className={base} />
);
}
switch (name) {
case "execute":
case "process_output":
@@ -116,6 +96,7 @@ export const ToolIcon: React.FC<{
case "start_workspace":
return <PowerIcon className={base} />;
case "chat_summarized":
case "list_agents":
return <BotIcon className={base} />;
case "thinking":
return <LightbulbIcon className={base} />;
@@ -1,58 +1,7 @@
import type React from "react";
import { getPathBasename } from "../../../utils/path";
import {
getProvidedSubagentTitle,
getSubagentDescriptor,
} from "./subagentDescriptor";
import { asRecord, asString, humanizeMCPToolName, parseArgs } from "./utils";
const renderSubagentLabel = (
name: string,
args: unknown,
result: unknown,
): React.ReactNode | null => {
const descriptor = getSubagentDescriptor({ name, args, result });
if (!descriptor) {
return null;
}
const providedTitle = getProvidedSubagentTitle({ args, result });
const fallbackTitle = descriptor.fallbackTitle;
const text = (() => {
switch (descriptor.action) {
case "spawn":
if (providedTitle) {
return `Spawning ${providedTitle}`;
}
if (descriptor.variant === "explore") {
return "Spawning Explore agent…";
}
if (descriptor.variant === "computer_use") {
return "Spawning computer use sub-agent…";
}
return `Spawning ${fallbackTitle}…`;
case "wait":
return providedTitle
? `Waiting for ${providedTitle}`
: `Waiting for ${fallbackTitle}…`;
case "message":
return providedTitle
? `Messaging ${providedTitle}`
: `Messaging ${fallbackTitle}…`;
case "interrupt":
return providedTitle
? `Interrupting ${providedTitle}`
: `Interrupting ${fallbackTitle}`;
case "list":
return providedTitle
? `Listing ${providedTitle}`
: `Listing ${fallbackTitle}`;
}
})();
return <span className="truncate text-[13px]">{text}</span>;
};
export const ToolLabel: React.FC<{
name: string;
args: unknown;
@@ -61,14 +10,6 @@ export const ToolLabel: React.FC<{
}> = ({ name, args, result, mcpSlug }) => {
const parsed = parseArgs(args);
const parsedResult = asRecord(result);
const subagentLabel = renderSubagentLabel(
name,
parsed ?? args,
parsedResult ?? result,
);
if (subagentLabel) {
return subagentLabel;
}
switch (name) {
case "execute": {
@@ -1,14 +1,9 @@
import { asString } from "../runtimeTypeUtils";
import { parseArgs } from "./utils";
export type SubagentAction =
| "spawn"
| "wait"
| "message"
| "interrupt"
| "list";
export type SubagentAction = "spawn" | "wait" | "message" | "interrupt";
export type SubagentVariant = "general" | "explore" | "computer_use";
export type SubagentIconKind = "bot" | "monitor";
type SubagentIconKind = "bot" | "monitor";
export type SubagentDescriptor = {
action: SubagentAction;
@@ -59,11 +54,6 @@ const actionByToolName: Record<string, SubagentAction> = {
// Legacy persisted tool name kept so old chat histories still render.
close_agent: "interrupt",
interrupt_agent: "interrupt",
// list_agents is a subagent tool but renders through
// ListAgentsRenderer, not SubagentRenderer. The "list" action
// exists for isSubagentToolName classification and ToolIcon
// dispatch, not for the SubagentRenderer label machinery.
list_agents: "list",
};
const variantBySpawnToolName: Record<string, SubagentVariant> = {
@@ -136,7 +136,7 @@ describe("toolVisibility", () => {
).toBe(false);
});
it("renders list_agents rows even without a chat_id", () => {
it("renders list_agents rows regardless of chat_id", () => {
expect(
shouldRenderTool({
name: "list_agents",