From 7cdee429eca2923acdd21454c1731e3623bd46ef Mon Sep 17 00:00:00 2001 From: 777genius Date: Wed, 22 Apr 2026 20:16:27 +0300 Subject: [PATCH] fix(team): avoid leaking lead backend into mixed member summary --- src/renderer/utils/memberRuntimeSummary.ts | 17 +++++++++--- .../utils/memberRuntimeSummary.test.ts | 27 ++++++++++++++++++- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/renderer/utils/memberRuntimeSummary.ts b/src/renderer/utils/memberRuntimeSummary.ts index e0d46594..f0c3353a 100644 --- a/src/renderer/utils/memberRuntimeSummary.ts +++ b/src/renderer/utils/memberRuntimeSummary.ts @@ -45,14 +45,25 @@ export function resolveMemberRuntimeSummary( spawnEntry: MemberSpawnStatusEntry | undefined, runtimeEntry?: TeamAgentRuntimeEntry ): string | undefined { + const memberProviderBackendId = (member as ResolvedTeamMember & { providerBackendId?: string }) + .providerBackendId; const configuredProvider: TeamProviderId = member.providerId ?? launchParams?.providerId ?? 'anthropic'; - const configuredModel = member.model?.trim() || launchParams?.model?.trim() || ''; - const configuredEffort = member.effort ?? launchParams?.effort; + const inheritsLeadRuntimeDefaults = + member.providerId == null || + launchParams?.providerId == null || + member.providerId === launchParams.providerId; + const configuredModel = + member.model?.trim() || (inheritsLeadRuntimeDefaults ? launchParams?.model?.trim() || '' : ''); + const configuredEffort = + member.effort ?? (inheritsLeadRuntimeDefaults ? launchParams?.effort : undefined); const runtimeModel = spawnEntry?.runtimeModel?.trim() || runtimeEntry?.runtimeModel?.trim(); + const configuredProviderBackendId = + memberProviderBackendId ?? + (inheritsLeadRuntimeDefaults ? launchParams?.providerBackendId : undefined); const backendLabel = normalizeMemberBackendLabel( configuredProvider, - formatTeamProviderBackendLabel(configuredProvider, launchParams?.providerBackendId) + formatTeamProviderBackendLabel(configuredProvider, configuredProviderBackendId) ); const memorySuffix = typeof runtimeEntry?.rssBytes === 'number' && runtimeEntry.rssBytes > 0 diff --git a/test/renderer/utils/memberRuntimeSummary.test.ts b/test/renderer/utils/memberRuntimeSummary.test.ts index dac0984a..f8b2b0b3 100644 --- a/test/renderer/utils/memberRuntimeSummary.test.ts +++ b/test/renderer/utils/memberRuntimeSummary.test.ts @@ -4,7 +4,9 @@ import { resolveMemberRuntimeSummary } from '@renderer/utils/memberRuntimeSummar import type { MemberSpawnStatusEntry, ResolvedTeamMember } from '@shared/types'; -function createMember(overrides: Partial = {}): ResolvedTeamMember { +type TestResolvedTeamMember = ResolvedTeamMember & { providerBackendId?: string }; + +function createMember(overrides: Partial = {}): TestResolvedTeamMember { return { name: 'alice', agentId: 'alice@test-team', @@ -118,4 +120,27 @@ describe('resolveMemberRuntimeSummary', () => { ) ).toBe('5.4 Mini · Medium · Codex'); }); + + it('does not leak the lead backend label into OpenCode side-lane members', () => { + const member = createMember({ + providerId: 'opencode', + providerBackendId: undefined, + model: 'opencode/nemotron-3-super-free', + effort: undefined, + }); + + expect( + resolveMemberRuntimeSummary( + member, + { + providerId: 'codex', + providerBackendId: 'codex-native', + model: 'gpt-5.4', + effort: 'medium', + limitContext: false, + }, + undefined + ) + ).toBe('nemotron-3-super-free · via OpenCode'); + }); });