From 6c433808469c47c3c7412a7778bb8cbc4ac1d666 Mon Sep 17 00:00:00 2001 From: Artem Rootman <4586640+artemrootman@users.noreply.github.com> Date: Tue, 28 Apr 2026 11:26:52 +0000 Subject: [PATCH] fix(team): propagate cross-provider member args to lead subprocess * fix(team): propagate cross-provider member args to lead subprocess When a team has an anthropic lead and codex teammates, the lead was launched without --settings {"codex":{"forced_login_method":"chatgpt"}}. buildInheritedCliFlags in the lead had nothing to pass to the codex teammate, which started without knowing the required auth method and crashed with "no CODEX_API_KEY or OPENAI_API_KEY configured". Adds buildCrossProviderMemberArgs that collects provider launch args for member providers that differ from the primary, and merges them into the lead's launch args so they propagate to teammates via buildInheritedCliFlags. * fix: log cross-provider env resolution failures instead of silently swallowing --- .../services/team/TeamProvisioningService.ts | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/main/services/team/TeamProvisioningService.ts b/src/main/services/team/TeamProvisioningService.ts index 4bf1deb7..0225c311 100644 --- a/src/main/services/team/TeamProvisioningService.ts +++ b/src/main/services/team/TeamProvisioningService.ts @@ -12947,6 +12947,16 @@ export class TeamProvisioningService { } launchArgs.push(...parseCliArgs(request.extraCliArgs)); launchArgs.push(...providerArgs); + // When the lead uses a different provider than some teammates (e.g., anthropic lead + // with codex teammates), the lead needs the teammate provider's launch args so they + // can be inherited by the teammate subprocess via buildInheritedCliFlags. + // Without this, a codex teammate spawned from an anthropic lead has no way to learn + // about the required forced_login_method (chatgpt/api) and fails to start. + const crossProviderMemberArgs = await this.buildCrossProviderMemberArgs( + resolvedProviderId, + effectiveMemberSpecs + ); + launchArgs.push(...crossProviderMemberArgs); const finalLaunchArgs = mergeJsonSettingsArgs(launchArgs); const runtimeWarning = buildRuntimeLaunchWarning(request, shellEnv, { geminiRuntimeAuth, @@ -21417,6 +21427,37 @@ export class TeamProvisioningService { }; } + private async buildCrossProviderMemberArgs( + primaryProviderId: TeamProviderId, + memberSpecs: TeamCreateRequest['members'] + ): Promise { + const crossProviderIds = new Set(); + for (const member of memberSpecs) { + const memberId = resolveTeamProviderId( + normalizeTeamMemberProviderId(member.providerId) ?? primaryProviderId + ); + if (memberId !== primaryProviderId) { + crossProviderIds.add(memberId); + } + } + const args: string[] = []; + for (const providerId of crossProviderIds) { + try { + const env = await this.buildProvisioningEnv(providerId); + if (env.providerArgs) { + args.push(...env.providerArgs); + } + } catch (error) { + console.error( + `[TeamProvisioningService] Failed to build cross-provider args for provider "${providerId}"`, + error + ); + // Best-effort: don't block launch if cross-provider env resolution fails + } + } + return args; + } + private async resolveControlApiBaseUrl(): Promise { if (!this.controlApiBaseUrlResolver) { return null;