openclaw/scripts/lib/plugin-theme-assets.mts
RoboClaw c94f47ea88
feat(ui): plugin themes can ship light and dark backgrounds (#172627)
* feat(ui): let plugin themes ship light and dark backgrounds

Plugin themes can declare `backgrounds: { light, dark }` in the manifest with
PNG, JPEG, or WebP images up to 512 KiB. The Gateway captures and sniffs them
with the theme's other artwork, serves them through the authenticated
plugin-theme-art route, and the Control UI paints the image for the active
color mode through the existing --app-background-image token. Modes without a
declared image keep the neutral plugin artwork.

Co-authored-by: Patrick-Erichsen <20157849+Patrick-Erichsen@users.noreply.github.com>

* fix(ui): dim plugin theme backgrounds like custom uploads

Plugin background images now carry the same palette-derived dimming a
default-strength custom upload gets, as a theme-colored scrim layer in
--app-background-image, so every surface that paints the token (shell canvas,
session background, Settings sample) stays readable. Full bleed no longer
stacks the bundled-artwork cap on top of that.

Captured background bytes are stored as base64: runtime plugin metadata
snapshots are deep-frozen, and freezing a Buffer throws, which broke plugin
install on a real Gateway.

Co-authored-by: Patrick-Erichsen <20157849+Patrick-Erichsen@users.noreply.github.com>

* test(ui): cover plugin background dimming through its owner

Keep the scrim helper private and assert the published token from
syncThemeBackgroundArtwork in both color modes.

Co-authored-by: Patrick-Erichsen <20157849+Patrick-Erichsen@users.noreply.github.com>

---------

Co-authored-by: Patrick-Erichsen <20157849+Patrick-Erichsen@users.noreply.github.com>
2026-10-15 01:07:25 +00:00

27 lines
870 B
TypeScript

import { normalizeManifestThemes } from "../../src/plugins/manifest-themes.ts";
/** Packaging consumes the same declared paths as manifest discovery. */
export function collectPluginThemeAssetPaths(manifest: Record<string, unknown>): string[] {
if (typeof manifest.id !== "string") {
return [];
}
const normalized = normalizeManifestThemes(manifest.themes, manifest.id);
if (!normalized.ok) {
return [];
}
const paths = new Set<string>();
for (const theme of normalized.themes ?? []) {
paths.add(theme.source);
for (const source of [
...Object.values(theme.icons ?? {}),
...Object.values(theme.hats ?? {}),
...Object.values(theme.backgrounds ?? {}),
]) {
paths.add(source);
}
for (const critter of Object.values(theme.critters ?? {})) {
paths.add(critter.source);
}
}
return [...paths];
}