源码
packages/ui/src/components/SubagentMessageToolBlock.tsx
// ZCode local-agent message renderers: public input details, no transport payloads.
import { Reply, Send } from "lucide-react";
import { useContext } from "react";
import { SubagentContext } from "./SubagentToolBlock.tsx";
import type { ToolBlockProps } from "./ToolBlock.tsx";
import { ToolFailure } from "./ToolFailure.tsx";
import { ToolLayout } from "./ToolLayout.tsx";
import { toolInput } from "./tool-presentation.ts";
export function SubagentMessageToolBlock({ block, expanded, toggle, onCopy }: ToolBlockProps) {
const input = toolInput(block);
const reply = block.name === "RespondToCoordinator";
const running = block.status === "preparing" || block.status === "running";
const summary = typeof input.summary === "string" ? input.summary : "";
const target = typeof input.to === "string" ? input.to : "";
const { tasks } = useContext(SubagentContext);
const targetName = tasks.find((task) => task.agentId === target)?.description.trim();
const message = typeof input.message === "string" ? input.message : "";
const details = !reply && Boolean(summary || target || message);
return (
<div className="tool-block" data-testid="tool-block" data-tool-name={block.name}>
<ToolLayout
icon={reply ? Reply : Send}
label={reply ? (running ? "正在回复" : "回复") : running ? "正在发送消息" : "消息"}
running={running}
expanded={details && expanded}
toggle={details ? toggle : undefined}
title={!reply && target ? (targetName ? `${targetName}\n${target}` : target) : undefined}
separator="·"
// 与 ZCode SendMessage 一致:摘要和目标只占一行,侧栏打开后不能换行撑高工具行。
primary={<span className="tool-summary-text">{summary || block.name}</span>}
secondary={
!reply && target ? (
<span className="tool-message-target">
<span>到</span>
{targetName ? (
<span className="tool-summary-text">{targetName}</span>
) : (
<code className="tool-summary-text">{target}</code>
)}
</span>
) : undefined
}
trailing={
reply && !running && block.status !== "error" ? (
<span className="tool-summary-status">回复已排队</span>
) : undefined
}
failure={
block.status === "error" ? (
<ToolFailure
text={reply ? "回复投递失败,请重试。" : block.output || "消息发送失败"}
onCopy={onCopy}
/>
) : undefined
}
content={
<dl className="subagent-message-details">
{[
["目标", targetName || target],
["摘要", summary],
["消息", message],
]
.filter(([, value]) => value)
.map(([label, value]) => (
<div key={label}>
<dt>{label}</dt>
<dd>{value}</dd>
</div>
))}
</dl>
}
/>
</div>
);
}