Before submitting
Area
apps/web
Steps to reproduce
- Open the web app at app.t3.codes (no local/primary backend — connect only via T3 Connect to a remote host, or SSH/Tailscale to a remote host).
- Enable Sidebar V2.
- Create any thread and send at least one message.
- Look at the sidebar thread row — the provider icon (e.g. OpenCode/Codex) is missing.
- Confirm the remote host's server config reports providers correctly (
providers array in the WebSocket snapshot message contains instanceId, driver, enabled: true for all configured providers, and the thread's modelSelection.instanceId matches one of them).
Expected behavior
The provider icon should render in Sidebar V2 thread rows for threads running on any connected environment, matching the icon shown in the model picker / composer.
Actual behavior
The icon is absent. The row's provider <span> (pointer-events-none ml-auto inline-flex shrink-0 items-center gap-1) is empty, and the hover tooltip also omits the provider line.
Impact
Minor bug or occasional failure
Root cause
apps/web/src/components/SidebarV2.tsx (default SidebarV2 component) builds providerEntryByInstanceId from primaryServerProvidersAtom:
const serverProviders = useAtomValue(primaryServerProvidersAtom);
const providerEntryByInstanceId = useMemo(
() => new Map(
deriveProviderInstanceEntries(serverProviders).map(
(entry) => [entry.instanceId as string, entry] as const,
),
),
[serverProviders],
);
primaryServerProvidersAtom only contains providers from the PrimaryConnectionTarget environment. On app.t3.codes with no local backend there is no primary target, so the list is empty and no icons render. On the desktop app it appears to work only because the local primary server exposes default provider instances whose instanceIds happen to match threads running on the remote environment.
This affects every non-primary connection type: RelayConnectionTarget (T3 Connect), BearerConnectionTarget (pairing URL/WSL), and SshConnectionTarget (SSH/Tailscale).
Proposed fix
Read providers from all connected environments via the already-imported environmentServerConfigsAtom instead of primaryServerProvidersAtom:
- const serverProviders = useAtomValue(primaryServerProvidersAtom);
+ const serverConfigs = useAtomValue(environmentServerConfigsAtom);
const providerEntryByInstanceId = useMemo(
- () => new Map(
- deriveProviderInstanceEntries(serverProviders).map(
- (entry) => [entry.instanceId as string, entry] as const,
- ),
- ),
- [serverProviders],
+ () => {
+ const map = new Map<string, ProviderInstanceEntry>();
+ for (const [, config] of serverConfigs) {
+ for (const entry of deriveProviderInstanceEntries(config.providers)) {
+ map.set(entry.instanceId as string, entry);
+ }
+ }
+ return map;
+ },
+ [serverConfigs],
);
Reference implementation: ashraftown/t3code@a45c6ddc7 (branch fix/provider-icon-per-env).
Before submitting
Area
apps/web
Steps to reproduce
providersarray in the WebSocketsnapshotmessage containsinstanceId,driver,enabled: truefor all configured providers, and the thread'smodelSelection.instanceIdmatches one of them).Expected behavior
The provider icon should render in Sidebar V2 thread rows for threads running on any connected environment, matching the icon shown in the model picker / composer.
Actual behavior
The icon is absent. The row's provider
<span>(pointer-events-none ml-auto inline-flex shrink-0 items-center gap-1) is empty, and the hover tooltip also omits the provider line.Impact
Minor bug or occasional failure
Root cause
apps/web/src/components/SidebarV2.tsx(defaultSidebarV2component) buildsproviderEntryByInstanceIdfromprimaryServerProvidersAtom:primaryServerProvidersAtomonly contains providers from thePrimaryConnectionTargetenvironment. On app.t3.codes with no local backend there is no primary target, so the list is empty and no icons render. On the desktop app it appears to work only because the local primary server exposes default provider instances whoseinstanceIds happen to match threads running on the remote environment.This affects every non-primary connection type:
RelayConnectionTarget(T3 Connect),BearerConnectionTarget(pairing URL/WSL), andSshConnectionTarget(SSH/Tailscale).Proposed fix
Read providers from all connected environments via the already-imported
environmentServerConfigsAtominstead ofprimaryServerProvidersAtom:Reference implementation:
ashraftown/t3code@a45c6ddc7(branchfix/provider-icon-per-env).