fix(teams): preserve explicit provider during relaunch

This commit is contained in:
777genius 2026-04-21 17:16:49 +03:00
parent 1db7e501a0
commit 7374108a71
2 changed files with 152 additions and 2 deletions

View file

@ -1490,12 +1490,15 @@ async function handleLaunchTeam(
if (payload.model !== undefined && typeof payload.model !== 'string') {
return { success: false, error: 'model must be a string' };
}
const providerId =
const explicitProviderId =
payload.providerId === 'codex'
? 'codex'
: payload.providerId === 'gemini'
? 'gemini'
: 'anthropic';
: payload.providerId === 'anthropic'
? 'anthropic'
: undefined;
const providerId = explicitProviderId ?? 'anthropic';
const providerBackendValidation = parseOptionalProviderBackendId(
payload.providerBackendId,
providerId

View file

@ -849,6 +849,153 @@ describe('TeamProvisioningService prepare/auth behavior', () => {
});
});
it('builds Anthropic launch identity with exact max effort and resolved fast mode', () => {
const svc = new TeamProvisioningService();
const launchIdentity = (svc as any).buildProviderModelLaunchIdentity({
request: {
providerId: 'anthropic',
model: 'claude-opus-4-6',
effort: 'max',
fastMode: 'on',
limitContext: true,
},
facts: {
defaultModel: 'opus[1m]',
modelIds: new Set(['claude-opus-4-6']),
modelCatalog: {
schemaVersion: 1,
providerId: 'anthropic',
source: 'anthropic-models-api',
status: 'ready',
fetchedAt: '2026-04-21T00:00:00.000Z',
staleAt: '2026-04-21T00:01:00.000Z',
defaultModelId: 'opus',
defaultLaunchModel: 'opus[1m]',
models: [
{
id: 'claude-opus-4-6',
launchModel: 'claude-opus-4-6',
displayName: 'Opus 4.6',
hidden: false,
supportedReasoningEfforts: ['low', 'medium', 'high', 'max'],
defaultReasoningEffort: 'high',
supportsFastMode: true,
inputModalities: ['text', 'image'],
supportsPersonality: false,
isDefault: false,
upgrade: false,
source: 'anthropic-models-api',
},
],
diagnostics: {
configReadState: 'ready',
appServerState: 'healthy',
},
},
runtimeCapabilities: {
modelCatalog: { dynamic: true, source: 'anthropic-models-api' },
reasoningEffort: {
supported: true,
values: ['low', 'medium', 'high', 'max'],
configPassthrough: true,
},
fastMode: {
supported: true,
available: true,
reason: null,
source: 'runtime',
},
},
},
});
expect(launchIdentity).toMatchObject({
providerId: 'anthropic',
selectedModel: 'claude-opus-4-6',
selectedModelKind: 'explicit',
resolvedLaunchModel: 'claude-opus-4-6',
selectedEffort: 'max',
resolvedEffort: 'max',
selectedFastMode: 'on',
resolvedFastMode: true,
fastResolutionReason: null,
});
});
it('rejects Anthropic max and fast when the exact resolved launch model does not support them', () => {
const svc = new TeamProvisioningService();
const facts = {
defaultModel: 'opus[1m]',
modelIds: new Set(['opus[1m]']),
modelCatalog: {
schemaVersion: 1,
providerId: 'anthropic',
source: 'anthropic-models-api',
status: 'ready',
fetchedAt: '2026-04-21T00:00:00.000Z',
staleAt: '2026-04-21T00:01:00.000Z',
defaultModelId: 'opus',
defaultLaunchModel: 'opus[1m]',
models: [
{
id: 'opus[1m]',
launchModel: 'opus[1m]',
displayName: 'Opus 4.7 (1M)',
hidden: false,
supportedReasoningEfforts: [],
defaultReasoningEffort: null,
supportsFastMode: false,
inputModalities: ['text', 'image'],
supportsPersonality: false,
isDefault: true,
upgrade: false,
source: 'anthropic-models-api',
},
],
diagnostics: {
configReadState: 'ready',
appServerState: 'healthy',
},
},
runtimeCapabilities: {
modelCatalog: { dynamic: true, source: 'anthropic-models-api' },
reasoningEffort: {
supported: true,
values: ['low', 'medium', 'high', 'max'],
configPassthrough: true,
},
fastMode: {
supported: true,
available: true,
reason: null,
source: 'runtime',
},
},
};
expect(() =>
(svc as any).validateRuntimeLaunchSelection({
actorLabel: 'Team lead',
providerId: 'anthropic',
model: 'opus',
effort: 'max',
limitContext: false,
facts,
})
).toThrow('does not support it in the current runtime');
expect(() =>
(svc as any).validateRuntimeLaunchSelection({
actorLabel: 'Team lead',
providerId: 'anthropic',
model: 'opus',
fastMode: 'on',
limitContext: false,
facts,
})
).toThrow('enables Anthropic Fast mode');
});
it('emits a lead-message refresh after provisioning reaches ready', async () => {
const svc = new TeamProvisioningService();
const emitter = vi.fn();