diff --git a/src/ui/assets/provider-logos/copilot-dark.svg b/src/ui/assets/provider-logos/copilot-dark.svg
index d09df805..275b8393 100644
--- a/src/ui/assets/provider-logos/copilot-dark.svg
+++ b/src/ui/assets/provider-logos/copilot-dark.svg
@@ -1 +1 @@
-
+
diff --git a/src/ui/assets/provider-logos/copilot-light.svg b/src/ui/assets/provider-logos/copilot-light.svg
new file mode 100644
index 00000000..b52d96cf
--- /dev/null
+++ b/src/ui/assets/provider-logos/copilot-light.svg
@@ -0,0 +1 @@
+
diff --git a/src/ui/assets/provider-logos/cursor-dark.svg b/src/ui/assets/provider-logos/cursor-dark.svg
index d50421b5..6849fbc3 100644
--- a/src/ui/assets/provider-logos/cursor-dark.svg
+++ b/src/ui/assets/provider-logos/cursor-dark.svg
@@ -1 +1,12 @@
-
+
+
diff --git a/src/ui/assets/provider-logos/cursor-light.svg b/src/ui/assets/provider-logos/cursor-light.svg
new file mode 100644
index 00000000..b054b189
--- /dev/null
+++ b/src/ui/assets/provider-logos/cursor-light.svg
@@ -0,0 +1,12 @@
+
+
diff --git a/src/ui/assets/provider-logos/openai-dark.svg b/src/ui/assets/provider-logos/openai-dark.svg
index 7e19c92d..cd86afb5 100644
--- a/src/ui/assets/provider-logos/openai-dark.svg
+++ b/src/ui/assets/provider-logos/openai-dark.svg
@@ -1 +1,11 @@
-
+
diff --git a/src/ui/assets/provider-logos/openai-light.svg b/src/ui/assets/provider-logos/openai-light.svg
new file mode 100644
index 00000000..a57ca0da
--- /dev/null
+++ b/src/ui/assets/provider-logos/openai-light.svg
@@ -0,0 +1,11 @@
+
diff --git a/src/ui/assets/provider-logos/opencode-dark.svg b/src/ui/assets/provider-logos/opencode-dark.svg
index 62e10df4..0bdfe089 100644
--- a/src/ui/assets/provider-logos/opencode-dark.svg
+++ b/src/ui/assets/provider-logos/opencode-dark.svg
@@ -1 +1 @@
-
+
diff --git a/src/ui/assets/provider-logos/opencode-light.svg b/src/ui/assets/provider-logos/opencode-light.svg
new file mode 100644
index 00000000..8a274375
--- /dev/null
+++ b/src/ui/assets/provider-logos/opencode-light.svg
@@ -0,0 +1 @@
+
diff --git a/src/ui/assets/provider-logos/pi-on-light.svg b/src/ui/assets/provider-logos/pi-on-light.svg
new file mode 100644
index 00000000..5472a94e
--- /dev/null
+++ b/src/ui/assets/provider-logos/pi-on-light.svg
@@ -0,0 +1 @@
+
diff --git a/src/ui/icons.ts b/src/ui/icons.ts
index 8bada413..8fcb11c4 100644
--- a/src/ui/icons.ts
+++ b/src/ui/icons.ts
@@ -34,17 +34,40 @@ export const toolIcons = {
export type ToolIcon = IconNode;
const providerLogos = {
- claude: new URL("./assets/provider-logos/claude.svg", import.meta.url).href,
- codex: new URL("./assets/provider-logos/openai-dark.svg", import.meta.url).href,
- copilot: new URL("./assets/provider-logos/copilot-dark.svg", import.meta.url).href,
- cursor: new URL("./assets/provider-logos/cursor-dark.svg", import.meta.url).href,
- opencode: new URL("./assets/provider-logos/opencode-dark.svg", import.meta.url).href,
- pi: new URL("./assets/provider-logos/pi-on-dark.svg", import.meta.url).href,
+ claude: {
+ light: new URL("./assets/provider-logos/claude.svg", import.meta.url).href,
+ dark: new URL("./assets/provider-logos/claude.svg", import.meta.url).href,
+ },
+ codex: {
+ light: new URL("./assets/provider-logos/openai-light.svg", import.meta.url).href,
+ dark: new URL("./assets/provider-logos/openai-dark.svg", import.meta.url).href,
+ },
+ copilot: {
+ light: new URL("./assets/provider-logos/copilot-light.svg", import.meta.url).href,
+ dark: new URL("./assets/provider-logos/copilot-dark.svg", import.meta.url).href,
+ },
+ cursor: {
+ light: new URL("./assets/provider-logos/cursor-light.svg", import.meta.url).href,
+ dark: new URL("./assets/provider-logos/cursor-dark.svg", import.meta.url).href,
+ },
+ opencode: {
+ light: new URL("./assets/provider-logos/opencode-light.svg", import.meta.url).href,
+ dark: new URL("./assets/provider-logos/opencode-dark.svg", import.meta.url).href,
+ },
+ pi: {
+ light: new URL("./assets/provider-logos/pi-on-light.svg", import.meta.url).href,
+ dark: new URL("./assets/provider-logos/pi-on-dark.svg", import.meta.url).href,
+ },
} as const;
-export function getProviderLogo(name: string): string | undefined {
+export type ProviderLogoTheme = "light" | "dark";
+
+export function getProviderLogo(
+ name: string,
+ theme: ProviderLogoTheme = "dark",
+): string | undefined {
const normalizedName = name.trim().toLowerCase() as keyof typeof providerLogos;
- return providerLogos[normalizedName];
+ return providerLogos[normalizedName]?.[theme];
}
export function renderIcon(icon: ToolIcon, className = "icon-svg"): SVGElement {
diff --git a/src/ui/workspace-app.tsx b/src/ui/workspace-app.tsx
index bc101cb3..27d4f5b8 100644
--- a/src/ui/workspace-app.tsx
+++ b/src/ui/workspace-app.tsx
@@ -12,7 +12,13 @@ import {
type HostContext,
type ToolResultCard,
} from "./card-types.js";
-import { getProviderLogo, renderIcon, toolIcons, type ToolIcon } from "./icons.js";
+import {
+ getProviderLogo,
+ renderIcon,
+ toolIcons,
+ type ProviderLogoTheme,
+ type ToolIcon,
+} from "./icons.js";
import {
getFileChangePathDisplay,
getPatchDisplayParts,
@@ -83,6 +89,7 @@ async function boot(): Promise {
};
app.onhostcontextchanged = (ctx) => {
+ const previousTheme = hostContext?.theme;
hostContext = {
...hostContext,
...ctx,
@@ -90,7 +97,13 @@ async function boot(): Promise {
applyHostContext();
// Workspace details inherit host variables directly. Rebuilding their DOM on
// iframe resize would reset an in-progress instruction preview interaction.
- if (card?.tool !== "open_workspace") renderPayloadIfNeeded();
+ if (card?.tool === "open_workspace") {
+ if (ctx.theme && ctx.theme !== previousTheme) {
+ syncWorkspaceProviderLogos(ctx.theme === "light" ? "light" : "dark");
+ }
+ } else {
+ renderPayloadIfNeeded();
+ }
};
app.onteardown = async () => {
@@ -583,6 +596,9 @@ function renderWorkspacePayload(container: HTMLElement, card: ToolResultCard): v
const providers = card.agentProviders ?? [];
const agents = card.agents ?? [];
+ const providerLogoTheme: ProviderLogoTheme = hostContext?.theme === "light"
+ ? "light"
+ : "dark";
const agentChips: WorkspaceChip[] = agents.map((agent) => {
const name = agent.name ?? "Unnamed agent";
const providerName = agent.provider?.trim();
@@ -594,14 +610,17 @@ function renderWorkspacePayload(container: HTMLElement, card: ToolResultCard): v
].filter((value): value is string => Boolean(value)).join("\n");
return {
label: name,
- logo: providerName ? getProviderLogo(providerName) : undefined,
+ logo: providerName
+ ? getProviderLogo(providerName, providerLogoTheme)
+ : undefined,
+ logoProvider: providerName,
profile: true,
title: title || undefined,
};
});
const providerChips: WorkspaceChip[] = providers.map((provider) => {
const name = provider.id?.trim() || "Unknown provider";
- const logo = getProviderLogo(name);
+ const logo = getProviderLogo(name, providerLogoTheme);
const title = [
provider.model ? `Model: ${provider.model}` : undefined,
provider.effort ? `Effort: ${provider.effort}` : undefined,
@@ -610,6 +629,7 @@ function renderWorkspacePayload(container: HTMLElement, card: ToolResultCard): v
return {
label: name,
logo,
+ logoProvider: logo ? name : undefined,
bareLogo: Boolean(logo),
ariaLabel: name,
title: title || name,
@@ -636,6 +656,7 @@ function renderWorkspacePayload(container: HTMLElement, card: ToolResultCard): v
interface WorkspaceChip {
label: string;
logo?: string;
+ logoProvider?: string;
profile?: boolean;
bareLogo?: boolean;
ariaLabel?: string;
@@ -913,6 +934,7 @@ function renderWorkspaceChips(chips: WorkspaceChip[]): HTMLElement {
? "workspace-agent-profile-logo"
: "workspace-chip-logo";
logo.src = chip.logo;
+ if (chip.logoProvider) logo.dataset.provider = chip.logoProvider;
logo.alt = "";
logo.setAttribute("aria-hidden", "true");
item.append(logo);
@@ -925,6 +947,15 @@ function renderWorkspaceChips(chips: WorkspaceChip[]): HTMLElement {
return list;
}
+function syncWorkspaceProviderLogos(theme: ProviderLogoTheme): void {
+ for (const logo of document.querySelectorAll("img[data-provider]")) {
+ const providerName = logo.dataset.provider;
+ if (!providerName) continue;
+ const src = getProviderLogo(providerName, theme);
+ if (src && logo.src !== src) logo.src = src;
+ }
+}
+
function element(
tag: K,
options: {