diff --git a/src/renderer/components/organization/OrgChart.tsx b/src/renderer/components/organization/OrgChart.tsx
index 338cdb60..4e093768 100644
--- a/src/renderer/components/organization/OrgChart.tsx
+++ b/src/renderer/components/organization/OrgChart.tsx
@@ -6,6 +6,16 @@ import { EmptyState } from "../ui";
import { useT } from "../../i18n";
import { buildOrgTree, layoutForest, flattenLayout, collectEdges, statusDotColor, CARD_W, CARD_H, CHART_PADDING } from "./orgTreeLayout";
+const LEGEND_ORDER: Array<{ status: string; labelKey: string }> = [
+ { status: "running", labelKey: "agent.form.statusRunning" },
+ { status: "active", labelKey: "agent.form.statusActive" },
+ { status: "idle", labelKey: "agent.form.statusIdle" },
+ { status: "paused", labelKey: "agent.form.statusPaused" },
+ { status: "pending_approval", labelKey: "agent.pendingApproval" },
+ { status: "error", labelKey: "agent.form.statusError" },
+ { status: "terminated", labelKey: "agent.form.statusTerminated" },
+];
+
export function OrgChart({ agents, connectors, onSelectAgent }: { agents: AgentRecord[]; connectors?: ConnectorRecord[]; onSelectAgent?: (agentId: string) => void }) {
const t = useT();
const containerRef = useRef(null);
@@ -18,6 +28,11 @@ export function OrgChart({ agents, connectors, onSelectAgent }: { agents: AgentR
const layout = useMemo(() => layoutForest(orgTree), [orgTree]);
const allNodes = useMemo(() => flattenLayout(layout), [layout]);
const edges = useMemo(() => collectEdges(layout), [layout]);
+ const legendEntries = useMemo(() => {
+ const present = new Set();
+ for (const a of agents) present.add(a.status);
+ return LEGEND_ORDER.filter((entry) => present.has(entry.status));
+ }, [agents]);
const bounds = useMemo(() => {
if (allNodes.length === 0) return { width: 800, height: 600 };
let maxX = 0, maxY = 0;
@@ -85,6 +100,17 @@ export function OrgChart({ agents, connectors, onSelectAgent }: { agents: AgentR
))}
+ {legendEntries.length > 0 ? (
+
+
{t("org.statusLegend")}
+ {legendEntries.map((entry) => (
+
+
+ {t(entry.labelKey)}
+
+ ))}
+
+ ) : null}
) : null}
+ {isRootAgent && !pendingApproval ? (
+ {t("agent.form.rootDeleteBlocked")}
+ ) : null}
{saveError ? {saveError}
: null}
);
diff --git a/src/renderer/i18n/en.ts b/src/renderer/i18n/en.ts
index dace8827..32f36a8f 100644
--- a/src/renderer/i18n/en.ts
+++ b/src/renderer/i18n/en.ts
@@ -1274,6 +1274,7 @@ export const en: Record = {
"org.zoomIn": "Zoom in",
"org.zoomOut": "Zoom out",
"org.fitChart": "Fit chart to screen",
+ "org.statusLegend": "Status",
"org.agentAria": "{name}, {title}, {status}",
"org.statusAria": "Status: {status}",
@@ -1380,6 +1381,8 @@ export const en: Record = {
"agent.form.statusPaused": "Paused",
"agent.form.statusError": "Error",
"agent.form.statusTerminated": "Terminated",
+ "agent.form.rootDeleteBlocked": "Top-of-chain agents cannot be deleted. Reassign their direct reports to another manager first.",
+ "agent.form.rootTerminateBlocked": "Top-of-chain agents cannot be terminated. Reassign their direct reports to another manager first.",
"agent.form.pendingReadOnly": "Pending hires are read-only here. Use Hiring or Approvals to approve or reject the request before editing the agent profile.",
"agent.form.saveFailed": "Failed to save agent.",
"agent.form.wakeFailed": "Failed to wake agent.",
diff --git a/src/renderer/i18n/zh.ts b/src/renderer/i18n/zh.ts
index 6e67654c..bc35383a 100644
--- a/src/renderer/i18n/zh.ts
+++ b/src/renderer/i18n/zh.ts
@@ -1274,6 +1274,7 @@ export const zh: Record = {
"org.zoomIn": "放大",
"org.zoomOut": "缩小",
"org.fitChart": "适应画布",
+ "org.statusLegend": "状态",
"org.agentAria": "{name},{title},{status}",
"org.statusAria": "状态:{status}",
@@ -1380,6 +1381,8 @@ export const zh: Record = {
"agent.form.statusPaused": "已暂停",
"agent.form.statusError": "错误",
"agent.form.statusTerminated": "已终止",
+ "agent.form.rootDeleteBlocked": "顶层成员无法删除。先把下属重新分配给其他上级。",
+ "agent.form.rootTerminateBlocked": "顶层成员无法终止。先把下属重新分配给其他上级。",
"agent.form.pendingReadOnly": "待招聘状态为只读。先在招聘或审批里批准或拒绝,再编辑智能体资料。",
"agent.form.saveFailed": "保存智能体失败。",
"agent.form.wakeFailed": "唤醒智能体失败。",