Make every identity editable: agent and operator names plus avatars

- Migration 049: avatar_emoji/avatar_color on agents and employees
- updateAgent accepts a new name (mention-name validated) and avatar;
  new updateEmployeeProfile renames the operator and sets their avatar
- Avatars are emoji-on-color tiles (renderer CSP blocks remote images);
  an AvatarDirectoryContext built from the snapshot lets the shared
  Avatar component honor custom looks at every call site - chat rows,
  conversation list, org chart, office card, sidebar - without
  threading props through pages
- Team edit dialog gains Name + avatar editor (CEO included); the
  sidebar foot opens an Edit-profile dialog for the operator
- e2e: rename an agent to a new mention handle with an emoji avatar,
  edit the operator profile, both verified in the live shell
This commit is contained in:
ZacharyZhang-NY committed 2026-07-08 21:33:23 -04:00
1 parent 86aa6fdb29
commit e55b8b85b0
20 files changed
+377 -31

No files matched your search

+19 -3
View File
@@ -85,6 +85,22 @@ test("onboards, hires, and creates work in the Electron shell", async () => {
expect(hiredAgent.workspaceId).toBe(hiredAgent.primaryWorkspaceId);
expect(hiredAgent.heartbeatEnabled).toBe(true);
expect(hiredAgent.heartbeatIntervalSec).toBe(120);
// The operator can rename any agent and give it a custom avatar.
await page.getByRole("button", { name: "Edit Alex Chen" }).click();
await page.locator(".modal").getByLabel("Name", { exact: true }).fill("Alex Turing");
await page.getByLabel("Avatar emoji").fill("🚀");
await page.locator(".modal").getByRole("button", { name: "Save" }).click();
await expect(page.getByText("Alex Turing").first()).toBeVisible();
await expect(page.locator(".table-row", { hasText: "Alex Turing" }).locator(".avatar", { hasText: "🚀" })).toBeVisible();
// The operator edits their own name and avatar from the sidebar foot.
await page.getByRole("button", { name: "Edit profile" }).click();
await page.locator(".modal").getByLabel("Name", { exact: true }).fill("Dana Zhang");
await page.getByLabel("Avatar emoji").fill("🎯");
await page.locator(".modal").getByRole("button", { name: "Save" }).click();
await expect(page.getByRole("button", { name: "Edit profile" })).toContainText("Dana Zhang");
await expect(page.getByRole("button", { name: "Edit profile" }).locator(".avatar")).toContainText("🎯");
await page.getByRole("button", { name: "Work", exact: true }).click();
await page.getByRole("button", { name: "New task" }).click();
await page.getByLabel("Title").fill("Production deploy");
@@ -158,12 +174,12 @@ test("onboards, hires, and creates work in the Electron shell", async () => {
await page.getByRole("button", { name: "Office" }).click();
await expect(page.locator("canvas")).toBeVisible();
// @mention with canonical handle in chat
// @mention with canonical handle in chat (the renamed agent resolves).
await page.getByRole("button", { name: "Messages" }).click();
await page.getByText("general").first().click();
await page.getByRole("textbox", { name: "Message" }).fill("@alexchen what is the status?");
await page.getByRole("textbox", { name: "Message" }).fill("@alexturing what is the status?");
await page.getByRole("button", { name: "Send" }).click();
await expect(page.getByText("Alex Chen").first()).toBeVisible();
await expect(page.getByText("Alex Turing").first()).toBeVisible();
await verifyPagesDoNotOverflow(page);
} finally {