mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 04:15:48 -06:00
fix(ui): stop inferring session sharing identity kind from ID strings (#124257)
* fix(ui): drive session sharing icon from identity type Remove the ID-string channel heuristic in the chat sharing menu. Sharing identities are typed human/agent/system by the Gateway protocol; there is no channel identity kind, so a human profile whose ID happened to contain "channel:" was misrendered with the channel glyph instead of the owner chip. Presentation now branches on identity.type only. * test(ui): describe the sharing fixture ID as opaque, not canonical ClawSweeper flagged the comment on the channel-shaped human ID case: it implied channel-shaped IDs are canonical for human profiles, but durable profile IDs are generated UUIDs. The real supported path is an opaque human identity ID (e.g. an inbound SenderId) that can happen to contain "channel:" as a substring.
This commit is contained in:
committed by
GitHub
parent
80ee4b97e5
commit
8a3fff21a8
@@ -493,9 +493,9 @@ suite.define(() => {
|
||||
label: `Member ${index + 1}`,
|
||||
})),
|
||||
];
|
||||
const channelIdentities = [
|
||||
{ type: "human" as const, id: "channel:chn_design", label: "Design" },
|
||||
{ type: "human" as const, id: "discord:channel:operations", label: "Operations" },
|
||||
const nonHumanIdentities = [
|
||||
{ type: "agent" as const, id: "agent-design", label: "Design" },
|
||||
{ type: "system" as const, id: "system-operations", label: "Operations" },
|
||||
];
|
||||
const gateway = await installMockGateway(currentPage, {
|
||||
sessionKey: "agent:main:ada",
|
||||
@@ -544,7 +544,7 @@ suite.define(() => {
|
||||
"session.members.list": {
|
||||
sessionKey: "agent:main:ada",
|
||||
members: [{ identityId: longMemberId, addedBy: "profile-ada", addedAt: 1 }],
|
||||
identities: [...humanIdentities, ...channelIdentities],
|
||||
identities: [...humanIdentities, ...nonHumanIdentities],
|
||||
role: "owner",
|
||||
allowedVisibilities: ["shared", "read-only", "suggest", "draft"],
|
||||
},
|
||||
@@ -677,7 +677,9 @@ suite.define(() => {
|
||||
await expectBrowser(
|
||||
dropdown.locator(".chat-pane__sharing-member openclaw-session-owner-chip"),
|
||||
).toHaveCount(30);
|
||||
await expectBrowser(dropdown.locator(".chat-pane__sharing-channel-icon")).toHaveCount(2);
|
||||
// Agent and system identities render the non-human icon from identity.type,
|
||||
// not from an ID-string heuristic; owner-chip presentation is human-only.
|
||||
await expectBrowser(dropdown.locator(".chat-pane__sharing-member-icon > svg")).toHaveCount(2);
|
||||
expect(
|
||||
await longNameItem.locator(".chat-pane__sharing-member-label").getAttribute("title"),
|
||||
).toBe(longMemberLabel);
|
||||
|
||||
@@ -71,7 +71,7 @@ describe("chat session sharing menu", () => {
|
||||
expect(onMemberChange).toHaveBeenCalledWith("alice", true);
|
||||
});
|
||||
|
||||
it("distinguishes people from channel-backed members", () => {
|
||||
it("renders member presentation from identity.type, not from ID spelling", () => {
|
||||
const root = mount(
|
||||
renderChatSessionSharing({
|
||||
session: {
|
||||
@@ -88,8 +88,12 @@ describe("chat session sharing menu", () => {
|
||||
members: [],
|
||||
identities: [
|
||||
{ type: "human", id: "profile-vyctor", label: "Vyctor Brzezowski" },
|
||||
// Human identity IDs are opaque (e.g. an inbound SenderId) and
|
||||
// can contain "channel:" as a substring; the recorded type,
|
||||
// not the ID string, must drive presentation.
|
||||
{ type: "human", id: "channel:chn_design", label: "Design" },
|
||||
{ type: "human", id: "discord:channel:operations", label: "Operations" },
|
||||
{ type: "agent", id: "discord:channel:operations", label: "Operations" },
|
||||
{ type: "system", id: "channel:audit", label: "Audit" },
|
||||
],
|
||||
role: "owner",
|
||||
allowedVisibilities: ["shared"],
|
||||
@@ -101,16 +105,21 @@ describe("chat session sharing menu", () => {
|
||||
}),
|
||||
);
|
||||
|
||||
const human = root.querySelector('wa-dropdown-item[value="member:profile-vyctor"]');
|
||||
const channels = [
|
||||
const humans = [
|
||||
root.querySelector('wa-dropdown-item[value="member:profile-vyctor"]'),
|
||||
root.querySelector('wa-dropdown-item[value="member:channel:chn_design"]'),
|
||||
];
|
||||
const nonHumans = [
|
||||
root.querySelector('wa-dropdown-item[value="member:discord:channel:operations"]'),
|
||||
root.querySelector('wa-dropdown-item[value="member:channel:audit"]'),
|
||||
];
|
||||
|
||||
expect(human?.querySelector("openclaw-session-owner-chip")).not.toBeNull();
|
||||
for (const channel of channels) {
|
||||
expect(channel?.querySelector("openclaw-session-owner-chip")).toBeNull();
|
||||
expect(channel?.querySelector(".chat-pane__sharing-channel-icon svg")).not.toBeNull();
|
||||
for (const human of humans) {
|
||||
expect(human?.querySelector("openclaw-session-owner-chip")).not.toBeNull();
|
||||
}
|
||||
for (const nonHuman of nonHumans) {
|
||||
expect(nonHuman?.querySelector("openclaw-session-owner-chip")).toBeNull();
|
||||
expect(nonHuman?.querySelector(".chat-pane__sharing-member-icon svg")).not.toBeNull();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -43,10 +43,6 @@ function sharingIcon(visibility: SessionVisibility): TemplateResult {
|
||||
return visibility === "shared" ? icons.users : icons.lock;
|
||||
}
|
||||
|
||||
function isChannelIdentity(identityId: string): boolean {
|
||||
return identityId.startsWith("channel:") || identityId.includes(":channel:");
|
||||
}
|
||||
|
||||
export function canManageChatSessionSharing(
|
||||
session: Pick<GatewaySessionRow, "sharingRole">,
|
||||
): boolean {
|
||||
@@ -162,7 +158,6 @@ export function renderChatSessionSharing(props: ChatSessionSharingProps) {
|
||||
const disabledReason = members.has(identity.id)
|
||||
? props.memberRemoveDisabledReason
|
||||
: props.memberAddDisabledReason;
|
||||
const channelIdentity = isChannelIdentity(identity.id);
|
||||
return html`
|
||||
<wa-dropdown-item
|
||||
class="session-menu__item chat-pane__sharing-member"
|
||||
@@ -170,18 +165,10 @@ export function renderChatSessionSharing(props: ChatSessionSharingProps) {
|
||||
?disabled=${Boolean(disabledReason)}
|
||||
title=${disabledReason ?? nothing}
|
||||
>
|
||||
<span
|
||||
slot="icon"
|
||||
class="chat-pane__sharing-member-icon ${channelIdentity
|
||||
? "chat-pane__sharing-channel-icon"
|
||||
: ""}"
|
||||
aria-hidden="true"
|
||||
>
|
||||
${channelIdentity
|
||||
? icons.messageSquare
|
||||
: identity.type === "human"
|
||||
? renderSessionOwnerChip(identity, "header")
|
||||
: icons.bot}
|
||||
<span slot="icon" class="chat-pane__sharing-member-icon" aria-hidden="true">
|
||||
${identity.type === "human"
|
||||
? renderSessionOwnerChip(identity, "header")
|
||||
: icons.bot}
|
||||
</span>
|
||||
<span
|
||||
class="chat-pane__sharing-member-label"
|
||||
|
||||
@@ -628,17 +628,6 @@ openclaw-chat-pane {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.chat-pane__sharing-channel-icon {
|
||||
border-radius: var(--radius-full);
|
||||
background: var(--bg-muted);
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.chat-pane__sharing-channel-icon svg {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
.chat-pane__sharing-member-label {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
|
||||
Reference in New Issue
Block a user