Skip to content

feat(workhub): show provider icons consistently with regular conversations - #6100

Open
ggbdpq wants to merge 8 commits into
apache:mainfrom
ggbdpq:fix/workhub-provider-icons
Open

ggbdpq wants to merge 8 commits into
apache:mainfrom
ggbdpq:fix/workhub-provider-icons

Conversation

@ggbdpq

@ggbdpq ggbdpq commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Regular chat supplies renderProviderMark to the shared Composer, so its model switcher shows each provider's brand mark; WorkHub never passed it, so the same configured models lost their visual identifier on the WorkHub surface (the compact wheel stays as #5444 designed).

The provider brand marks now live in the connection-settings feature beside GenericProviderMark, which already owns provider UI. The composition root (composition/legacy-desktop-region.tsx) takes that public export and injects it into both the legacy shell's composer and WorkHubRoot, so the renderer entry (app.tsx) stays exactly as it was: no new import and no change to its permanently guarded entry budget. app-shell.tsx and the two settings consumers read the same public export.

The vendored brand SVGs are referenced with new URL(..., import.meta.url) instead of static imports because eight src/main/__tests__ files import the connection-settings barrel and the main tsc graph has no SVG loader. Vite resolves the same asset URLs at renderer build time, and the existing CSS-mask rendering keeps currentColor theming for the monochrome marks.

renderer-architecture.json is regenerated with --write: the legacy file set and the AppShell closure lose the moved module, the priced app.tsx import is gone, and the new public export is admitted as a root-symbol use of this same change. The strict-base comparison against fresh upstream/main passes and is a net debt reduction.

A WorkHubComposer render test pins the mark beside the model switcher, and a source-wiring test pins both hops from the composition adapter to the composer.

Verification

Check Result
check:architecture --base upstream/main --strict-base pass; app.tsx budget unchanged (5 import declarations / 6 specifiers / 172 tokens)
Architecture checker self-tests 168 pass / 0 fail
New render + source-wiring tests 2 pass / 0 fail
Affected main tests (6 files, incl. the connection-settings barrel consumers) 34 pass / 0 fail
build:renderer (Vite resolution of the new URL assets) pass
biome check --write on the changed files clean
check:asf-headers pass

AI use

The original commits carry a Generated-by: GLM-5.3-Flash (ZCode) trailer; the zero-debt rewiring commit carries Generated-by: DeepSeek Harness (dsh). This PR description was written with AI assistance.

Checklist

…tions

Regular chat supplies renderProviderMark to the shared Composer, so its
model switcher shows the provider's brand mark; WorkHub never passed it,
so the same configured models lost their visual identifier on the WorkHub
surface (the compact wheel stays as apache#5444 designed).

Thread the injector from the renderer entry through the composition root
into WorkHubRoot - the SVG library stays in the legacy root zone, out of
the main-process test build (the same principle that keeps it out of
@maka/ui), and the architecture ledger is re-priced for app.tsx's one
added import.

A WorkHubComposer render test pins the mark beside the model switcher so
the passthrough cannot be narrowed away silently.

Fixes apache#6095

Generated-by: GLM-5.3-Flash (ZCode)
@github-actions github-actions Bot added the effort/M Under 500 readable lines label Oct 14, 2026

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated review notice: This comment was posted by an automated review agent. It is not an independent human review and does not replace one.

At fd51dc5c8e0634971668e0ee46ede159a6a6b8da, one P2 issue prevents the current change from passing CI: apps/desktop/src/renderer/app.tsx:25 adds a dependency and increases the permanently guarded renderer-entry budget. The strict check against the actual base reports dependency count 5→6, import declarations 5→6, import specifiers 6→7, a new dependency on ./settings/provider-brand-marks, and token count 172→196. Regenerating the current ledger does not authorize those increases. I reproduced the same five failures locally; the current CI test run fails there, while the base's CI run passes the architecture check. Preserve the existing entry budget and rerun the strict comparison, rather than relying on the plain regenerated-ledger check.

The provider-icon premise is supported by the production call chain and a browser reproduction, not merely the issue description. Regular chat already supplies the existing ProviderBrandMark implementation; the previous WorkHubRoot omits it. The new callback reaches the existing WorkHubComposer without adding another model-selection authority or new icon assets. Six real-Chromium runs using the existing WorkHubRoot stories, with the same provider renderer supplied as in production, pass for docked, expanded-conversation and progress-composer states in light and dark themes. The existing OpenAI SVG paints at approximately 16 px with the theme's foreground color. Replacing only WorkHubRoot with the exact base implementation causes the docked model-menu icon assertion to fail after the story's interaction assertions complete. These runs exercise the real controller/root and existing story services, not the Electron App entry or a live provider.

In the unified menu, the icons appear on model options, not on the menu trigger. The injected callback also supplies an icon to the compact wheel's trigger; the wheel options and selection behavior are unchanged. The new component test alone does not verify root wiring because WorkHubComposer already forwarded this prop before the PR.

The normal build, four Desktop type configurations, production renderer build, all 168 WorkHub tests, inventory and formatting pass. No additional verified P0–P3 issue was found.

There are no protocol changes against the author's base, which remains at epoch 220. Main advanced to abb2deca during validation; its guarded App entry and the reviewed wiring are unchanged. The source merge is clean and retains main's epoch 222, but that merged result was not built or tested. GitHub reports the PR as mergeable with its test check failed and the overall state BLOCKED. Any feature approval remains a maintainer decision after the CI failure is fixed.

Comment thread apps/desktop/src/renderer/app.tsx Outdated
Two review-hardening fixes on the WorkHub provider-mark wiring:

- The render test feeds the prop itself, so deleting the
  WorkHubRoot-to-Composer passthrough would have kept it green. A
  source-wiring assertion (main-startup-lifetime precedent) now pins
  both hops: the composition adapter must pass its supplier into
  WorkHubRoot, and the root must forward it to the composer.
- renderProviderMark is required on AppShell and WorkHubRoot - their
  only caller is the adapter, so the optional prop only allowed the
  silent no-icons degradation this PR fixes to return unnoticed.

The app.tsx rootDebt repricing stays: the checker leaves no legal
alternative supplier (composition-to-legacy imports are forbidden
outside the hardcoded app-shell edge, and a feature-to-legacy edge
would pull 20+ svg imports into the main-process test graph), so the
entry-budget increase needs a maintainer ruling - raised on the
review thread with the full evidence chain.

Generated-by: GLM-5.3-Flash (ZCode)

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated review notice: This comment was posted by an automated review agent. It is not an independent human review and does not replace one.

Incremental review from fd51dc5c to 0c855867721f8412ae6ab7febd4217342d93d9fa. The new commit makes renderProviderMark required on AppShell and WorkHubRoot, which have one caller each. It also adds a source-wiring test that pins both hops from the composition adapter to the composer. Both changes look correct, and I found no new issue.

Still open: P2, the app.tsx entry budget. The test job on this head still fails at check-renderer-architecture.mjs --base 8686793e… --strict-base. That is the same failure as before. The commit message explains why the author sees no legal alternative supplier and asks for a maintainer ruling on the budget increase. This PR cannot merge until a maintainer either accepts the repricing or chooses a different wiring and CI turns green.

@ggbdpq

ggbdpq commented Oct 18, 2026

Copy link
Copy Markdown
Contributor Author

@liugddx gentle ping — this PR has been carrying an open architecture ruling since Oct 14 (thread PRRT_kwDOSpfFGs6sQWmR): the strict-base failure on app.tsx's entry budget cannot be resolved in code. We verified the checker leaves no legal zero-debt supplier for the WorkHub provider mark — composition cannot import legacy, the feature-declarable edge would drag 20+ static svg imports into the svg-loader-less main test graph, and app-shell.tsx itself sits under the same legacyAppShell.files ratchet. The direction is yours: accept the minimal entry-budget increase (+1 import edge, 172→196 tokens), or we ablate the WorkHub mark to keep the ratchet frozen. Happy to execute either.

…s feature

check:architecture --strict-base failed on apache#6100 because src/renderer/app.tsx
is a permanent root entry budget: importing ProviderBrandMark there added one
dependency path, one import declaration, one specifier and 24 non-trivia
tokens. The composition adapter cannot import src/renderer/settings either,
and a feature cannot grow a new edge into legacy renderer code.

Move ProviderBrandMark next to GenericProviderMark in the feature that owns
provider UI, export it from the public entry, and let the composition root
inject that feature export into both the legacy shell and WorkHubRoot. app.tsx
returns to <AppShell /> unchanged. The vendored brand SVGs are now referenced
with new URL(..., import.meta.url) instead of static imports: eight main
process test files import the connection-settings barrel, and the main tsc
graph has no SVG loader; Vite resolves the same asset URLs at renderer build
time and the CSS mask keeps currentColor theming.

The ledger shrinks: app-shell drops the priced legacy import, the settings
closure no longer carries provider-brand-marks, and the feature public entry
records the new root symbol uses admitted by this same change.

Verified:
- node apps/desktop/scripts/check-renderer-architecture.mjs --base upstream/main --strict-base
- node --test apps/desktop/scripts/check-renderer-architecture.test.mjs (168 pass)
- node --test dist/main/__tests__/workhub-composer-provider-mark.test.js (2 pass)
- npm --prefix apps/desktop run build:renderer (Vite asset resolution ok)
- npx @biomejs/biome check --write <changed files> (clean)
- npm run check:asf-headers (pass)

Generated-by: DeepSeek Harness (dsh)
…mark move

`npm run astryx:surface-inventory` flagged the generated path list as stale
after `provider-brand-marks.tsx` moved into the connection-settings feature:
the file keeps no Astryx JSX, so only its path row moves between the settings
and feature sections.

Verified with `npm run astryx:surface-inventory`.

Generated-by: DeepSeek Harness (dsh)
The story mounted `WorkHubRoot` without the now-required `renderProviderMark`,
so the Storybook typecheck failed on `stories/workhub.stories.tsx`. Supply the
same feature-owned mark the composition root injects in production, so the
story keeps rendering the real brand icons.

Verified: `tsc -p apps/desktop/tsconfig.storybook.json --noEmit` exit 0;
biome clean.

Generated-by: DeepSeek Harness (dsh)
Knip flagged `GenericProviderMark` after `provider-brand-marks.tsx` moved into
the feature and started importing its sibling module directly. Nothing else
consumes the barrel export.

Verified: `npx knip --workspace apps/desktop` and
`check:architecture --base upstream/main --strict-base` pass.

Generated-by: DeepSeek Harness (dsh)
…r-icons

The renderer-architecture ledger conflicted because main repriced it too; the
merged tree wins by regenerating it with `check-renderer-architecture.mjs
--write`, and the Astryx surface inventory is regenerated for main's new
renderer files. strict-base against the merged main passes.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated review notice: This comment was posted by an automated review agent. It is not an independent human review and does not replace one.

Incremental review from fd51dc5c8e0634971668e0ee46ede159a6a6b8da to 4f87090724acb417b325cac14dbe09b24364ff98. The author added five commits (0c85586, ef69369, 324c1d7, f727a2d, 27e34bc) and merged main twice; the head's merge base is current main 57cde86b. I separated main's changes from the author's by comparing the old PR diff (against ecd4dba8) with the new PR diff (against 57cde86b).

Prior findings:

  • P2, renderer-entry budget / CI failure: fixed. apps/desktop/src/renderer/app.tsx is no longer changed. The provider mark is now wired only in composition/legacy-desktop-region.tsx. provider-brand-marks.tsx moves into features/connection-settings and is exported from that barrel, so app-shell.tsx shrinks (import declarations 34->33, specifiers 43->42). Run locally, check-renderer-architecture.mjs --base 57cde86b --strict-base passes; it only reports, without ratcheting, the new AppShell-closure uses of ProviderBrandMark in general-settings-page and provider-display. CI's strict-base step also passes on this head.
  • Prior note that the component test did not cover root wiring: addressed. WorkHubRoot's renderProviderMark prop is now required, so the type checker forces both the composition root and the story to supply it. A second test also pins the forwarding in source.

New changes reviewed:

  • The 24 provider SVG imports became new URL('../../assets/...', import.meta.url).href. This matches the existing feature-module convention (external-agent-settings, module-hub). In the production renderer bundle, the small SVGs are still inlined as data URIs and localai.svg (111 KB) is still emitted as a hashed asset, so runtime behavior is unchanged.
  • Removing the GenericProviderMark barrel export leaves no dangling importers: typecheck and Knip pass in CI. provider-brand-marks.tsx now imports it directly.
  • The Astryx surface inventory and the architecture ledger are updated consistently with the move.

New findings: no P0-P3 issues found.

Validation: on the head, the root npm run build passes, including the production renderer build, the renderer-entry output check and the third-party notices check. Local tsc --noEmit passes for tsconfig.main, renderer and storybook. Of the main-process tests, the 2 new provider-mark tests pass, and all 175 tests across the 21 WorkHub test files pass. Locally, tsconfig.preload reports TS2339 in src/preload/runtime-host-session-catalog.ts, a file this PR does not touch. CI's Typecheck step passes on the same head, so this is a local environment artifact and not PR-caused.

Protocol/epoch: no protocol files are touched; no epoch impact.

CI/mergeability: the test check passes on 4f870907 (run), including strict architecture, Typecheck, Knip, Storybook smoke and the affected workspace tests. The known event-wait-manager Retry-After flake did not occur. GitHub reports the PR as MERGEABLE, with merge state BLOCKED, presumably pending required review. Feature approval remains a maintainer decision.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/M Under 500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants