[plugins] Add dark-mode logo metadata (#29488)

Adds additive dark-mode plugin logo metadata across manifests, remote
catalogs, and the app-server protocol while keeping uninstalled Git
listings free of synthetic local paths.

Supersedes #28945. This replacement uses an upstream branch so trusted
CI can use the repository-provided remote Bazel configuration.

## Current state

Plugin interfaces expose only the default logo asset. Clients therefore
cannot select a dedicated dark-mode logo even when a plugin provides
one.

## What this PR changes

- Adds nullable `logoDark` and `logoUrlDark` fields to
`PluginInterface`.
- Resolves local `interface.logoDark` assets and maps remote
`logo_url_dark` values.
- Removes path-backed interface assets, including `logoDark`, from
uninstalled Git fallback listings until the plugin has a real local
root.
- Updates the bundled plugin validator and manifest reference.
- Regenerates the app-server JSON schemas and TypeScript types.

Local manifests expose `interface.logoDark` as a package-relative asset
path. Remote catalog responses expose `logo_url_dark`. These values map
into separate app-server fields so clients can preserve local-path and
remote-URL handling.

## Risk

The fields are additive and nullable, so existing clients retain their
current logo behavior. The main risks are an incomplete mapping path or
exposing a synthetic local path for an uninstalled Git plugin.
Local-manifest, remote-catalog, fallback-listing, protocol
serialization, and app-server integration tests cover those paths.

Spiciness: 2/5

## Testing

- `just write-app-server-schema`
- `just fmt`
- Regression test first failed with `logo_dark` resolved to
`/assets/logo-dark.png`, then passed after the fallback-listing fix.
- `just test -p codex-core-plugins` (267 tests passed)
- `just test -p codex-app-server 'suite::v2::plugin'` (114 tests passed)
- `just test -p codex-app-server-protocol -p codex-core-plugins -p
codex-plugin -p codex-skills` (517 tests passed before the follow-up)
- `just test -p codex-tui plugin` (47 tests passed)
- Validated a local plugin manifest containing `interface.logoDark` with
the bundled validator.

## Manual verification

Create a local plugin with both `interface.logo` and
`interface.logoDark`, then call `plugin/list` or `plugin/read`. Confirm
the response contains separate `logo` and `logoDark` paths. For a remote
catalog entry, confirm `logoUrlDark` is populated from `logo_url_dark`.
For an uninstalled Git marketplace entry, confirm path-backed interface
assets remain absent until installation.

Issue: N/A - coordinated maintainer change.
This commit is contained in:
Drew
2026-06-22 16:01:27 -07:00
committed by GitHub
Unverified
parent 7ce84e64d8
commit 2c351cb864
24 changed files with 281 additions and 3 deletions
+4
View File
@@ -53,6 +53,7 @@ pub struct PluginManifestInterface<Resource> {
pub brand_color: Option<String>,
pub composer_icon: Option<Resource>,
pub logo: Option<Resource>,
pub logo_dark: Option<Resource>,
pub screenshots: Vec<Resource>,
}
@@ -72,6 +73,7 @@ impl<Resource> Default for PluginManifestInterface<Resource> {
brand_color: None,
composer_icon: None,
logo: None,
logo_dark: None,
screenshots: Vec::new(),
}
}
@@ -141,6 +143,7 @@ impl<Resource> PluginManifest<Resource> {
brand_color,
composer_icon,
logo,
logo_dark,
screenshots,
} = interface;
Some(PluginManifestInterface {
@@ -157,6 +160,7 @@ impl<Resource> PluginManifest<Resource> {
brand_color,
composer_icon: composer_icon.map(&mut map).transpose()?,
logo: logo.map(&mut map).transpose()?,
logo_dark: logo_dark.map(&mut map).transpose()?,
screenshots: screenshots
.into_iter()
.map(&mut map)