feat(web): add Aider and Trae CLI brand icons, refresh Pi mark (#2956)
Some checks failed
visual-baseline / Capture visual baselines (push) Waiting to run
actionlint / Lint GitHub Actions workflows (push) Failing after 1s
ci / Detect CI change scopes (push) Successful in 0s
landing-page-ci / Validate landing page (push) Failing after 1s
landing-page-deploy / Deploy landing page (push) Has been skipped
nix-check / build (push) Failing after 2s
ci / Validate Nix flake (push) Has been skipped
ci / Preflight (push) Failing after 1s
ci / Workspace unit tests (push) Failing after 1s
ci / Daemon workspace tests (push) Failing after 1s
ci / Web workspace tests (push) Failing after 2s
ci / Browser tests (push) Failing after 2s
ci / Build workspaces (push) Failing after 1s
ci / Validate workspace (push) Failing after 0s
ci / Runtime trace (push) Has been skipped

AgentIcon fell back to an initial-letter pill for Aider and Trae CLI
because neither id was registered in ICON_EXT and no asset shipped. Add
the bundled brand marks so both agents render their real logo:

- aider.png — Aider's published avatar, downscaled to 96px (~2.6KB).
- trae-cli.png — Trae's app icon, downscaled to 96px (~2.3KB). Keyed on
  the `trae-cli` runtime id so the file and ICON_EXT entry match exactly.

Both vendors only publish rasterised marks, so they follow the existing
PNG-fallback path used for Devin.

Pi shipped a stale single-glyph silhouette in MONO_ICONS. Replace it
with the current dark-tile mark (white glyph on #09090b) and drop it
from MONO_ICONS — the tile has baked colors, so CSS-mask rendering with
currentColor would flatten it to a solid square. It now renders through
<img> like the other color-baked brands.

Adds AgentIcon test coverage for all three.
This commit is contained in:
MrBeanDev 2026-05-26 11:44:15 +05:30 committed by GitHub
parent a6c01af2c2
commit fc53feccd9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 28 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="#1c1b1a" fill-rule="evenodd" viewBox="0 0 24 24"><path d="M8.341 24c-.53 0-.841-.308-.841-.824v-.271c0-.514.248-.755.708-.926l1.025-.343c.708-.271.954-.583.954-1.303V3.667c0-.72-.246-1.029-.954-1.303L8.2 2.02c-.46-.171-.701-.408-.701-.926v-.27C7.5.309 7.818 0 8.348 0h6.968c.531 0 .85.309.85.824v.271c0 .514-.249.755-.709.926l-1.031.34c-.743.272-.992.583-.992 1.303v16.664c0 .72.249 1.028.992 1.303l1.024.342c.46.172.708.408.708.926v.272c0 .515-.318.824-.85.824L8.342 24z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800"><rect width="800" height="800" rx="120" fill="#09090b"/><path fill="#fff" fill-rule="evenodd" d="M165.29 165.29H517.36V400H400V517.36H282.65V634.72H165.29ZM282.65 282.65V400H400V282.65Z"/><path fill="#fff" d="M517.36 400H634.72V634.72H517.36Z"/></svg>

Before

Width:  |  Height:  |  Size: 526 B

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -29,6 +29,8 @@ const ICON_EXT: Record<string, 'svg' | 'png'> = {
kiro: 'svg',
kilo: 'svg',
vibe: 'svg',
aider: 'png',
'trae-cli': 'png',
devin: 'png',
};
@ -45,7 +47,6 @@ const MONO_ICONS = new Set([
'opencode',
'hermes',
'mimo',
'pi',
'kilo',
'grok-build',
]);

View file

@ -47,6 +47,31 @@ describe('AgentIcon', () => {
expect(markup).toContain('src="/agent-icons/devin.png"');
});
it('renders Aider as a PNG (Aider only ships a rasterised avatar)', () => {
const markup = renderToStaticMarkup(<AgentIcon id="aider" size={24} />);
expect(markup).toContain('src="/agent-icons/aider.png"');
expect(markup).not.toContain('agent-icon-fallback');
});
it('renders Trae CLI as a PNG keyed on the trae-cli runtime id', () => {
// The daemon runtime def id is `trae-cli`, so the icon file and the
// ICON_EXT key must match that id exactly (not a bare `trae`).
const markup = renderToStaticMarkup(<AgentIcon id="trae-cli" size={24} />);
expect(markup).toContain('src="/agent-icons/trae-cli.png"');
expect(markup).not.toContain('agent-icon-fallback');
});
it('renders Pi as a color-baked <img>, not a CSS mask', () => {
// pi.svg is a dark tile (#09090b) with a white glyph — baked colors, so
// masking it with `currentColor` would flatten it to a solid square.
const markup = renderToStaticMarkup(<AgentIcon id="pi" size={24} />);
expect(markup).toContain('src="/agent-icons/pi.svg"');
expect(markup).not.toContain('agent-icon-mono');
});
it('renders monochrome SVGs as a CSS-masked <span> so they pick up theme color', () => {
// cursor-agent.svg ships with `fill="currentColor"` and would lose its
// ink under a dark theme if loaded through `<img>` (which would make