Skip to content

Fix custom provider icons in the model picker and Model Pad - #102

Merged
sambitcreate merged 7 commits into
mainfrom
cursor/custom-provider-icons-53cb
Sep 11, 2026
Merged

Fix custom provider icons in the model picker and Model Pad#102
sambitcreate merged 7 commits into
mainfrom
cursor/custom-provider-icons-53cb

Conversation

@sambitcreate

@sambitcreate sambitcreate commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Summary

Fix custom provider artwork disappearing from the model picker and Model Pad.

  • Recovers valid oversized stored PNG payloads during provider save by routing them back through native normalization instead of silently dropping them.
  • Validates the re-encoded PNG against the renderer's bounded artwork contract before persistence.
  • Preserves user-supplied PNG colors rather than converting them into monochrome masks; bundled provider glyphs remain theme-aware.
  • Shows custom artwork on the Model Pad puck with a semantic, theme-resolved foreground for bundled monochrome marks.
  • Bounds responsive Model Pad animation settling so infinite animations cannot hang hosted Electron tests.

Electron's getSize() and toPNG() already default to a 1.0 scale factor; explicit 1x arguments were removed because they were not the effective fix. The save-time recovery path is the behavior that restores previously oversized artwork.

Validation

  • Exact-head CI is green at 391923f6, including the full verification and deterministic Electron E2E gates; the release-consumer contract is green.
  • Real Electron E2E saves a valid oversized PNG through providers:save, verifies a decodable bounded persisted PNG, relaunches, and confirms the artwork survives.
  • Focused provider-artwork tests, type-check, and lint pass locally at the current head.
  • Three repeated artwork-persistence and responsive-layout Electron runs passed during readiness hardening.

Review status

  • Rebased on current main, no merge commits, GitHub mergeable.
  • Pullfrog is green and all review threads are resolved. Late causality feedback was addressed, and the scheduled-profile Electron helper was made deterministic at 391923f6 after it exposed the only failed rerun.

cursoragent and others added 4 commits September 9, 2026 13:56
Encode saved provider artwork at 1x so the display validator keeps it, recover oversize PNGs on save, theme custom marks like bundled logos, and put the icon on the Model Pad puck.

Co-authored-by: Sambit Biswas <sambitcreate@users.noreply.github.com>
Lock the save path to persistable artwork recovery, recover a real 65px PNG, and tighten picker/pad source scans so they cannot match the wrong branch.

Co-authored-by: Sambit Biswas <sambitcreate@users.noreply.github.com>
Narrow slug before passing it to ThemedProviderMark so type-check accepts mark as a string.

Co-authored-by: Sambit Biswas <sambitcreate@users.noreply.github.com>
@sambitcreate

Copy link
Copy Markdown
Owner Author

Readiness hardening pushed at 8492109a after two independent adversarial reviews:

  • preserve custom provider PNG artwork in original color instead of converting it to an alpha mask
  • replace the Model Pad puck's hard-coded foreground with a resolved appearance token
  • add a real Electron regression that saves a valid 128 px PNG through providers:save, verifies a decodable bounded 64 px result, relaunches, and confirms exact persistence
  • bound Model Pad animation settling and ignore infinite animations in responsive E2E

Local verification:

  • focused provider/UI/appearance tests: 46 passed
  • Model Pad suite: 60 passed
  • remote artwork projection + picker: 35 passed
  • type-check, E2E type-check, lint, production build: passed
  • provider-artwork and responsive Model Pad Electron E2E: 6/6 passed across 3 repeats each

Keeping the PR in draft until hosted exact-head CI is green.

@sambitcreate

Copy link
Copy Markdown
Owner Author

Hosted follow-up at fa526bee: the first exact-head E2E run reached the final 390×456 case as the test's global 90-second budget expired; the automatic retry completed the unchanged matrix in 24 seconds. I gave this exhaustive 24-state responsive case an explicit bounded 180-second budget without relaxing any geometry or reachability assertion.

Local verification after the change: E2E type-check and lint passed; the complete responsive Model Pad case passed 3/3 (1.2m).

@sambitcreate
sambitcreate marked this pull request as ready for review September 11, 2026 02:05

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — one informational note inline, plus a description nitpick.

Reviewed changes

  • Artwork persistenceparseProvider now persists through the new persistableProviderArtwork, which keeps contract-valid PNG artwork and re-encodes oversize payloads; the encoder re-validates its own output and fails closed.
  • Picker / Model Pad renderingProviderIcon is refactored onto a shared ThemedProviderMark for bundled marks (custom artwork still renders as an original-color <img>), and the Model Pad puck now renders the active model's provider icon.
  • Knob theming — new --model-pad-knob-foreground token resolved from foregroundForFill("#FFFFFF", scheme) with static fallbacks, applied to .model-pad-knob and its confirmed state.
  • Coverage — new source-reading provider-artwork suite registered in test, test:coverage, and test:slash-commands, expanded composer/picker/display tests, a new Electron E2E that saves a 128px PNG, relaunches, and asserts a bounded 64px persisted result, and a bounded Model Pad responsive case.

ℹ️ Nitpicks

  • The PR description still says custom marks render "with the same currentColor mask as bundled logos," but the final code renders them as an original-color <img> and .papercuts/troubleshooting.md documents that reversal. Worth updating so the merge record matches the implementation.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using DeepSeek Flash𝕏

Comment thread main/services/provider-artwork.ts Outdated
@sambitcreate

Copy link
Copy Markdown
Owner Author

Addressed the late review at 0e31ee99: removed the no-op explicit getSize(1) / toPNG({ scaleFactor: 1 }) changes, rewrote the source contract and E2E naming to credit the actual save-time recovery, and corrected the PR/papercut narrative. Focused artwork tests, type-check, and lint pass locally; fresh exact-head CI is running.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • Reverted the no-op 1x encode path — removed PIXEL_SCALE and the explicit getSize(PIXEL_SCALE) / toPNG({ scaleFactor: PIXEL_SCALE }) arguments, restoring the base getSize() / toPNG() calls; createFromBuffer(source.bytes, { scaleFactor: 1 }) is unchanged from base.
  • Retargeted provider-artwork.test.ts — dropped the assertions on the removed encode arguments and now pins the post-encode normalizeProviderArtwork check plus the persistStoredProviderArtwork recovery wiring.
  • Corrected the narrative.papercuts/troubleshooting.md now credits save-time recovery instead of the Electron-default 1x arguments, and the artwork E2E is renamed from Retina to Oversized.

Verification at this head: focused provider-artwork suites 7/7 pass, tsc --noEmit and type-check:e2e clean. The prior review's inline thread on the no-op encode is resolved, and the PR description now matches the implementation.

Pullfrog  | View workflow run | Using DeepSeek Flash𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Reviewed the single commit added since the prior Pullfrog review (391923f6), a test-only stabilization of the Assistant/Scheduled E2E.

  • Stabilized scheduled-search cleanup — the E2E now clears the controlled scheduled-task search through the native HTMLInputElement.value setter plus a bubbling input event instead of an empty Playwright fill("").
  • Documented the quirk — a papercut records that empty fill("") can leave a controlled search unchanged on hosted Electron and points at the native-setter workaround.

The replacement is the canonical React controlled-input workaround: Playwright's fill for input[type=search] selects the value and calls document.execCommand("insertText", false, value), where an empty string can be a no-op; calling the prototype setter bypasses React's per-node value tracker so the dispatched input event registers as a real change. The follow-up toHaveValue("") and No matching tasks assertions still prove React state cleared, so the workaround cannot mask a product regression. npm run type-check:e2e is clean at this head; the deterministic Electron E2E was still running when this review was written.

Pullfrog  | View workflow run | Using DeepSeek Flash𝕏

@sambitcreate
sambitcreate merged commit 97e89d6 into main Sep 11, 2026
6 checks passed
@sambitcreate
sambitcreate deleted the cursor/custom-provider-icons-53cb branch September 11, 2026 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants