mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
[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:
24 files changed
+281
-3
No files matched your search
@@ -716,8 +716,12 @@ pub struct PluginInterface {
|
||||
pub composer_icon_url: Option<String>,
|
||||
/// Local logo path, resolved from the installed plugin package.
|
||||
pub logo: Option<AbsolutePathBuf>,
|
||||
/// Local dark-mode logo path, resolved from the installed plugin package.
|
||||
pub logo_dark: Option<AbsolutePathBuf>,
|
||||
/// Remote logo URL from the plugin catalog.
|
||||
pub logo_url: Option<String>,
|
||||
/// Remote dark-mode logo URL from the plugin catalog.
|
||||
pub logo_url_dark: Option<String>,
|
||||
/// Local screenshot paths, resolved from the installed plugin package.
|
||||
pub screenshots: Vec<AbsolutePathBuf>,
|
||||
/// Remote screenshot URLs from the plugin catalog.
|
||||
|
||||
@@ -2938,6 +2938,13 @@ fn plugin_interface_serializes_local_paths_and_remote_urls_separately() {
|
||||
};
|
||||
let composer_icon = AbsolutePathBuf::try_from(PathBuf::from(composer_icon)).unwrap();
|
||||
let composer_icon_json = composer_icon.as_path().display().to_string();
|
||||
let logo_dark = if cfg!(windows) {
|
||||
r"C:\plugins\linear\logo-dark.png"
|
||||
} else {
|
||||
"/plugins/linear/logo-dark.png"
|
||||
};
|
||||
let logo_dark = AbsolutePathBuf::try_from(PathBuf::from(logo_dark)).unwrap();
|
||||
let logo_dark_json = logo_dark.as_path().display().to_string();
|
||||
|
||||
let interface = PluginInterface {
|
||||
display_name: Some("Linear".to_string()),
|
||||
@@ -2954,7 +2961,9 @@ fn plugin_interface_serializes_local_paths_and_remote_urls_separately() {
|
||||
composer_icon: Some(composer_icon),
|
||||
composer_icon_url: Some("https://example.com/linear/icon.png".to_string()),
|
||||
logo: None,
|
||||
logo_dark: Some(logo_dark),
|
||||
logo_url: Some("https://example.com/linear/logo.png".to_string()),
|
||||
logo_url_dark: Some("https://example.com/linear/logo-dark.png".to_string()),
|
||||
screenshots: Vec::new(),
|
||||
screenshot_urls: vec!["https://example.com/linear/screenshot.png".to_string()],
|
||||
};
|
||||
@@ -2976,7 +2985,9 @@ fn plugin_interface_serializes_local_paths_and_remote_urls_separately() {
|
||||
"composerIcon": composer_icon_json,
|
||||
"composerIconUrl": "https://example.com/linear/icon.png",
|
||||
"logo": null,
|
||||
"logoDark": logo_dark_json,
|
||||
"logoUrl": "https://example.com/linear/logo.png",
|
||||
"logoUrlDark": "https://example.com/linear/logo-dark.png",
|
||||
"screenshots": [],
|
||||
"screenshotUrls": ["https://example.com/linear/screenshot.png"],
|
||||
}),
|
||||
|
||||
Reference in new issue
Block a user