mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
fix(ui): preserve configured agent labels
This commit is contained in:
@@ -135,9 +135,7 @@ function sidebarAgentMenuRows(params: {
|
||||
const agentId = normalizeAgentId(entry.id);
|
||||
return (
|
||||
agentId.toLowerCase().includes(query) ||
|
||||
(params.identities.get(agentId)?.name?.trim() || normalizeAgentLabel(entry))
|
||||
.toLowerCase()
|
||||
.includes(query)
|
||||
normalizeAgentLabel(entry, params.identities.get(agentId)).toLowerCase().includes(query)
|
||||
);
|
||||
});
|
||||
return { rows, showFilter: true };
|
||||
@@ -164,7 +162,7 @@ function sidebarAgentMenuRows(params: {
|
||||
function renderAgentRow(agent: AgentMenuAgent, params: SidebarAgentMenuParams) {
|
||||
const agentId = normalizeAgentId(agent.id);
|
||||
const identity = params.identities.get(agentId) ?? null;
|
||||
const label = identity?.name?.trim() || normalizeAgentLabel(agent);
|
||||
const label = normalizeAgentLabel(agent, identity);
|
||||
const active = agentId === params.activeId;
|
||||
const unread = active ? 0 : params.agentUnreadCount(agentId);
|
||||
const approvals = params.agentApprovalCount(agentId);
|
||||
|
||||
@@ -82,8 +82,7 @@ export function renderAppSidebarBrand(host: AppSidebarRenderHost) {
|
||||
const agentId = normalizeAgentId(entry.id);
|
||||
return agentId !== cardAgentId && host.agentUnreadCount(agentId) > 0;
|
||||
});
|
||||
const cardName =
|
||||
cardIdentity?.name?.trim() || (cardAgent ? normalizeAgentLabel(cardAgent) : cardAgentId);
|
||||
const cardName = cardAgent ? normalizeAgentLabel(cardAgent, cardIdentity) : cardAgentId;
|
||||
const approvalCount = host.sessionData.approvalBadgeSnapshot().agentCounts.get(cardAgentId) ?? 0;
|
||||
const gateway = host.sessionDataContext?.gateway;
|
||||
const avatarAuthToken = gateway
|
||||
|
||||
@@ -84,7 +84,7 @@ export function renderSidebarAgentMenuForController(controller: SidebarMenusCont
|
||||
position,
|
||||
basePath: host.basePath,
|
||||
activeId,
|
||||
activeName: identity?.name?.trim() || (agent ? normalizeAgentLabel(agent) : activeId),
|
||||
activeName: agent ? normalizeAgentLabel(agent, identity) : activeId,
|
||||
agents,
|
||||
identities,
|
||||
filter: controller.agentMenuFilter,
|
||||
|
||||
@@ -23,6 +23,8 @@ import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "../str
|
||||
type AgentRosterEntry = {
|
||||
id: string;
|
||||
kind?: "agent" | "system";
|
||||
name?: string;
|
||||
identity?: { name?: string };
|
||||
};
|
||||
|
||||
/** Ordinary agent targets; system rows remain available to diagnostic surfaces. */
|
||||
@@ -319,13 +321,16 @@ type ConfigSnapshot = {
|
||||
};
|
||||
};
|
||||
|
||||
export function normalizeAgentLabel(agent: {
|
||||
id: string;
|
||||
name?: string;
|
||||
identity?: { name?: string };
|
||||
}) {
|
||||
export function normalizeAgentLabel(
|
||||
agent: AgentRosterEntry,
|
||||
hydratedIdentity?: { name?: string } | null,
|
||||
) {
|
||||
// Roster labels own operator target identity; workspace identity only fills gaps.
|
||||
return (
|
||||
normalizeOptionalString(agent.name) ?? normalizeOptionalString(agent.identity?.name) ?? agent.id
|
||||
normalizeOptionalString(agent.name) ??
|
||||
normalizeOptionalString(agent.identity?.name) ??
|
||||
normalizeOptionalString(hydratedIdentity?.name) ??
|
||||
agent.id
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,52 @@ describe("AppSidebar agent chip", () => {
|
||||
expect(request).toHaveBeenCalledWith("agent.identity.get", { agentId: "main" });
|
||||
});
|
||||
|
||||
it("keeps the configured roster label when identity hydration returns a fallback", async () => {
|
||||
const request = vi.fn(async (_method: string, params: { agentId: string }) =>
|
||||
params.agentId === "main"
|
||||
? { agentId: "main", name: "Workspace Molty", avatar: "🦞" }
|
||||
: { agentId: "rust-claw", name: "Assistant", avatar: "🦀" },
|
||||
);
|
||||
const gatewayHarness = createGatewayHarness({ request } as unknown as GatewayBrowserClient);
|
||||
const agentIdentity = createAgentIdentityCapability(gatewayHarness.gateway);
|
||||
const { sidebar } = await mountSidebar(
|
||||
gatewayHarness.gateway,
|
||||
createSessions("main", ["agent:main:main"]),
|
||||
"panel",
|
||||
{
|
||||
defaultId: "main",
|
||||
mainKey: "main",
|
||||
scope: "per-sender",
|
||||
agents: [{ id: "main" }, { id: "rust-claw", name: "rust-claw" }],
|
||||
},
|
||||
[],
|
||||
agentIdentity,
|
||||
);
|
||||
|
||||
sidebar.connected = true;
|
||||
await vi.waitFor(() => {
|
||||
expect(sidebar.querySelector(".sidebar-agent-card__name")?.textContent?.trim()).toBe(
|
||||
"Workspace Molty",
|
||||
);
|
||||
});
|
||||
sidebar.querySelector<HTMLButtonElement>(".sidebar-agent-card__main")?.click();
|
||||
await vi.waitFor(() => {
|
||||
expect(request).toHaveBeenCalledWith("agent.identity.get", { agentId: "rust-claw" });
|
||||
const labels = [
|
||||
...sidebar.querySelectorAll(".sidebar-agent-menu .agent-select__option-label"),
|
||||
].map((element) => element.textContent?.trim());
|
||||
expect(labels).toEqual(["Workspace Molty", "rust-claw"]);
|
||||
});
|
||||
await vi.waitFor(() => {
|
||||
const rustRow = [
|
||||
...sidebar.querySelectorAll<HTMLElement>(".sidebar-agent-menu__agent-switch"),
|
||||
].find((row) => row.textContent?.includes("rust-claw"));
|
||||
expect(
|
||||
rustRow?.querySelector(".agent-select__avatar--text")?.getAttribute("data-avatar"),
|
||||
).toBe("🦀");
|
||||
});
|
||||
});
|
||||
|
||||
it("hydrates agents added while the switcher remains open", async () => {
|
||||
const request = vi.fn(async (_method: string, params: { agentId: string }) => ({
|
||||
agentId: params.agentId,
|
||||
|
||||
Reference in New Issue
Block a user