agent-ecosystem/test/renderer/components/team/dialogs/launchDialogPrefill.test.ts

407 lines
11 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { resolveLaunchDialogPrefill } from '@renderer/components/team/dialogs/launchDialogPrefill';
import type { ResolvedTeamMember, TeamCreateRequest, TeamProviderId } from '@shared/types';
function createStoredModelGetter(models: Partial<Record<TeamProviderId, string>>) {
return (providerId: TeamProviderId): string => models[providerId] ?? '';
}
describe('resolveLaunchDialogPrefill', () => {
it('prefills from the current lead runtime before localStorage defaults', () => {
const members = [
{
name: 'team-lead',
agentType: 'team-lead',
providerId: 'codex',
model: 'gpt-5.4',
effort: 'medium',
},
{
name: 'alice',
agentType: 'reviewer',
providerId: 'codex',
model: 'gpt-5.4-mini',
effort: 'medium',
},
] as ResolvedTeamMember[];
const result = resolveLaunchDialogPrefill({
members,
savedRequest: null,
previousLaunchParams: {
providerId: 'codex',
model: 'gpt-5.4',
effort: 'medium',
},
multimodelEnabled: true,
storedProviderId: 'anthropic',
storedEffort: 'medium',
storedFastMode: 'inherit',
storedLimitContext: false,
getStoredModel: createStoredModelGetter({
anthropic: 'haiku',
codex: 'gpt-5.4',
}),
});
expect(result).toEqual({
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'gpt-5.4',
effort: 'medium',
fastMode: 'inherit',
limitContext: false,
});
});
it('prefers the current lead runtime over a stale saved request', () => {
const members = [
{
name: 'team-lead',
agentType: 'team-lead',
providerId: 'codex',
model: 'gpt-5.4',
effort: 'medium',
},
] as ResolvedTeamMember[];
const savedRequest = {
teamName: 'vector-room-2',
cwd: '/Users/test/project',
providerId: 'anthropic',
model: 'haiku',
effort: 'low',
members: [],
} as TeamCreateRequest;
const result = resolveLaunchDialogPrefill({
members,
savedRequest,
previousLaunchParams: undefined,
multimodelEnabled: true,
storedProviderId: 'anthropic',
storedEffort: 'medium',
storedFastMode: 'inherit',
storedLimitContext: false,
getStoredModel: createStoredModelGetter({
anthropic: 'haiku',
codex: 'gpt-5.4',
}),
});
expect(result).toEqual({
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'gpt-5.4',
effort: 'medium',
fastMode: 'inherit',
limitContext: false,
});
});
it('falls back to previous launch params when the current team snapshot is unavailable', () => {
const result = resolveLaunchDialogPrefill({
members: [],
savedRequest: null,
previousLaunchParams: {
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'gpt-5.3-codex',
effort: 'high',
},
multimodelEnabled: true,
storedProviderId: 'anthropic',
storedEffort: 'medium',
storedFastMode: 'inherit',
storedLimitContext: false,
getStoredModel: createStoredModelGetter({
anthropic: 'haiku',
codex: 'gpt-5.4',
}),
});
expect(result).toEqual({
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'gpt-5.3-codex',
effort: 'high',
fastMode: 'inherit',
limitContext: false,
});
});
it('falls back to a saved request backend lane when no previous launch params exist', () => {
const result = resolveLaunchDialogPrefill({
members: [],
savedRequest: {
teamName: 'vector-room-2',
cwd: '/Users/test/project',
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'gpt-5.4',
effort: 'medium',
members: [],
} as TeamCreateRequest,
previousLaunchParams: undefined,
multimodelEnabled: true,
storedProviderId: 'anthropic',
storedEffort: 'medium',
storedFastMode: 'inherit',
storedLimitContext: false,
getStoredModel: createStoredModelGetter({
anthropic: 'haiku',
codex: 'gpt-5.4',
}),
});
expect(result).toEqual({
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'gpt-5.4',
effort: 'medium',
fastMode: 'inherit',
limitContext: false,
});
});
it('defaults new Codex launch flows to codex-native when no backend was persisted', () => {
const result = resolveLaunchDialogPrefill({
members: [
{
name: 'team-lead',
agentType: 'team-lead',
providerId: 'codex',
model: 'gpt-5.4',
effort: 'medium',
},
] as ResolvedTeamMember[],
savedRequest: null,
previousLaunchParams: undefined,
multimodelEnabled: true,
storedProviderId: 'codex',
storedEffort: 'medium',
storedFastMode: 'inherit',
storedLimitContext: false,
getStoredModel: createStoredModelGetter({
codex: 'gpt-5.4',
}),
});
expect(result).toEqual({
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'gpt-5.4',
effort: 'medium',
fastMode: 'inherit',
limitContext: false,
});
});
it('does not carry a frozen Gemini model into an Anthropic fallback', () => {
const members = [
{
name: 'team-lead',
agentType: 'team-lead',
providerId: 'gemini',
model: 'gemini-2.5-flash-lite',
effort: 'medium',
},
] as ResolvedTeamMember[];
const result = resolveLaunchDialogPrefill({
members,
savedRequest: null,
previousLaunchParams: undefined,
multimodelEnabled: true,
storedProviderId: 'anthropic',
storedEffort: 'medium',
storedFastMode: 'inherit',
storedLimitContext: false,
getStoredModel: createStoredModelGetter({
anthropic: 'haiku',
codex: 'gpt-5.4',
}),
});
expect(result).toEqual({
providerId: 'anthropic',
providerBackendId: undefined,
model: 'haiku',
effort: 'medium',
fastMode: 'inherit',
limitContext: false,
});
});
it('preserves OpenCode relaunch runtime instead of collapsing it to Anthropic', () => {
const result = resolveLaunchDialogPrefill({
members: [],
savedRequest: null,
previousLaunchParams: {
providerId: 'opencode',
model: 'openrouter/moonshotai/kimi-k2',
effort: 'medium',
},
multimodelEnabled: true,
storedProviderId: 'anthropic',
storedEffort: 'medium',
storedFastMode: 'inherit',
storedLimitContext: false,
getStoredModel: createStoredModelGetter({
anthropic: 'haiku',
opencode: 'openai/gpt-5.4',
}),
});
expect(result).toEqual({
providerId: 'opencode',
providerBackendId: undefined,
model: 'openrouter/moonshotai/kimi-k2',
effort: 'medium',
fastMode: 'inherit',
limitContext: false,
});
});
it('prefers per-team launch params for limitContext over stale global storage', () => {
const result = resolveLaunchDialogPrefill({
members: [],
savedRequest: null,
previousLaunchParams: {
providerId: 'anthropic',
model: 'opus[1m][1m]',
effort: 'high',
limitContext: true,
},
multimodelEnabled: true,
storedProviderId: 'anthropic',
storedEffort: 'medium',
storedFastMode: 'inherit',
storedLimitContext: false,
getStoredModel: createStoredModelGetter({
anthropic: 'haiku',
}),
});
expect(result).toEqual({
providerId: 'anthropic',
providerBackendId: undefined,
model: 'opus',
effort: 'high',
fastMode: 'inherit',
limitContext: true,
});
});
it('does not carry a stale Codex backend into an Anthropic lead prefill', () => {
const members = [
{
name: 'team-lead',
agentType: 'team-lead',
providerId: 'anthropic',
model: 'haiku',
effort: 'low',
},
] as ResolvedTeamMember[];
const result = resolveLaunchDialogPrefill({
members,
savedRequest: {
teamName: 'signal-ops-22',
cwd: '/Users/test/project',
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'gpt-5.5',
effort: 'medium',
members: [],
} as TeamCreateRequest,
previousLaunchParams: {
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'gpt-5.5',
effort: 'medium',
limitContext: false,
},
multimodelEnabled: true,
storedProviderId: 'codex',
storedEffort: 'medium',
storedFastMode: 'inherit',
storedLimitContext: false,
getStoredModel: createStoredModelGetter({
anthropic: 'sonnet',
codex: 'gpt-5.4',
}),
});
expect(result).toEqual({
providerId: 'anthropic',
providerBackendId: undefined,
model: 'haiku',
effort: 'low',
fastMode: 'inherit',
limitContext: false,
});
});
it('preserves literal [1m] suffixes for non-anthropic providers', () => {
const result = resolveLaunchDialogPrefill({
members: [],
savedRequest: null,
previousLaunchParams: {
providerId: 'codex',
model: 'custom-model[1m]',
effort: 'medium',
},
multimodelEnabled: true,
storedProviderId: 'anthropic',
storedEffort: 'medium',
storedFastMode: 'inherit',
storedLimitContext: false,
getStoredModel: createStoredModelGetter({
anthropic: 'haiku',
codex: 'gpt-5.4',
}),
});
expect(result).toEqual({
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'custom-model[1m]',
effort: 'medium',
fastMode: 'inherit',
limitContext: false,
});
});
it('preserves literal [1m] suffixes for non-anthropic providers', () => {
const result = resolveLaunchDialogPrefill({
members: [],
savedRequest: null,
previousLaunchParams: {
providerId: 'codex',
model: 'custom-model[1m]',
effort: 'medium',
},
multimodelEnabled: true,
storedProviderId: 'anthropic',
storedEffort: 'medium',
storedFastMode: 'inherit',
storedLimitContext: false,
getStoredModel: createStoredModelGetter({
anthropic: 'haiku',
codex: 'gpt-5.4',
}),
});
expect(result).toEqual({
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'custom-model[1m]',
effort: 'medium',
fastMode: 'inherit',
limitContext: false,
});
});
});