mirror of
https://github.com/vxcontrol/pentagi.git
synced 2026-08-24 20:16:30 +00:00
test(e2e): serve default providers the id the backend actually sends
The resolver builds default provider configs without an ID, so gqlgen marshals the bare number 0 for every one of them. The cassette handed each a distinct string id instead, which left `ProviderConfig.keyFields`'s id-0 branch — the one that stops those un-normalisable defaults collapsing onto a single cache entry — unexercised by any test. Serve id 0 and the plain provider name, give each default a distinguishable model so a collapse is observable, and pin the cache contract directly: with the keyFields branch removed the new test reads anthropic's default as openai's. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c8314c4213
commit
a51e36fdc7
@@ -16,14 +16,14 @@ import { baseQueries, baseRest } from './base.ts';
|
||||
|
||||
const T = '2026-01-15T09:00:00Z';
|
||||
|
||||
const agentConfig = (): AgentConfigFragmentFragment =>
|
||||
const agentConfig = (model = 'e2e-model'): AgentConfigFragmentFragment =>
|
||||
entity('AgentConfig', {
|
||||
extraBody: null,
|
||||
frequencyPenalty: null,
|
||||
maxLength: null,
|
||||
maxTokens: null,
|
||||
minLength: null,
|
||||
model: 'e2e-model',
|
||||
model,
|
||||
presencePenalty: null,
|
||||
price: null,
|
||||
reasoning: null,
|
||||
@@ -33,29 +33,35 @@ const agentConfig = (): AgentConfigFragmentFragment =>
|
||||
topP: null,
|
||||
});
|
||||
|
||||
const agentsConfig = (): AgentsConfigFragmentFragment =>
|
||||
const agentsConfig = (model?: string): AgentsConfigFragmentFragment =>
|
||||
entity('AgentsConfig', {
|
||||
adviser: agentConfig(),
|
||||
assistant: agentConfig(),
|
||||
coder: agentConfig(),
|
||||
enricher: agentConfig(),
|
||||
generator: agentConfig(),
|
||||
installer: agentConfig(),
|
||||
pentester: agentConfig(),
|
||||
primaryAgent: agentConfig(),
|
||||
refiner: agentConfig(),
|
||||
reflector: agentConfig(),
|
||||
searcher: agentConfig(),
|
||||
simple: agentConfig(),
|
||||
simpleJson: agentConfig(),
|
||||
adviser: agentConfig(model),
|
||||
assistant: agentConfig(model),
|
||||
coder: agentConfig(model),
|
||||
enricher: agentConfig(model),
|
||||
generator: agentConfig(model),
|
||||
installer: agentConfig(model),
|
||||
pentester: agentConfig(model),
|
||||
primaryAgent: agentConfig(model),
|
||||
refiner: agentConfig(model),
|
||||
reflector: agentConfig(model),
|
||||
searcher: agentConfig(model),
|
||||
simple: agentConfig(model),
|
||||
simpleJson: agentConfig(model),
|
||||
});
|
||||
|
||||
const defaultConfig = (id: string, type: ProviderType): ProviderConfigFragmentFragment =>
|
||||
/**
|
||||
* Defaults are not database rows: the resolver builds them without an ID, so the wire carries the
|
||||
* bare number `0` for every one. `ProviderConfig.keyFields`'s id-0 branch exists for that shape, and
|
||||
* a distinct string id here leaves it unexercised.
|
||||
*/
|
||||
const defaultConfig = (type: ProviderType): ProviderConfigFragmentFragment =>
|
||||
entity('ProviderConfig', {
|
||||
agents: agentsConfig(),
|
||||
// Distinct per type, so two defaults collapsing onto one cache entry is observable.
|
||||
agents: agentsConfig(`e2e-${type}-model`),
|
||||
createdAt: T,
|
||||
id,
|
||||
name: `default-${type}`,
|
||||
id: 0 as unknown as string,
|
||||
name: type,
|
||||
type,
|
||||
updatedAt: T,
|
||||
});
|
||||
@@ -63,7 +69,7 @@ const defaultConfig = (id: string, type: ProviderType): ProviderConfigFragmentFr
|
||||
const noProviders: ResultOf<typeof SettingsProvidersDocument> = {
|
||||
settingsProviders: entity('ProvidersConfig', {
|
||||
default: entity('DefaultProvidersConfig', {
|
||||
anthropic: defaultConfig('default-anthropic', ProviderType.Anthropic),
|
||||
anthropic: defaultConfig(ProviderType.Anthropic),
|
||||
bedrock: null,
|
||||
custom: null,
|
||||
deepseek: null,
|
||||
@@ -72,7 +78,7 @@ const noProviders: ResultOf<typeof SettingsProvidersDocument> = {
|
||||
kimi: null,
|
||||
minimax: null,
|
||||
ollama: null,
|
||||
openai: defaultConfig('default-openai', ProviderType.Openai),
|
||||
openai: defaultConfig(ProviderType.Openai),
|
||||
qwen: null,
|
||||
}),
|
||||
enabled: entity('ProvidersReadinessStatus', {
|
||||
@@ -120,7 +126,7 @@ export const settingsProvidersCassette = (override: Cassette = {}): Cassette =>
|
||||
const populatedProviders: ResultOf<typeof SettingsProvidersDocument> = {
|
||||
settingsProviders: entity('ProvidersConfig', {
|
||||
default: entity('DefaultProvidersConfig', {
|
||||
anthropic: defaultConfig('default-anthropic', ProviderType.Anthropic),
|
||||
anthropic: defaultConfig(ProviderType.Anthropic),
|
||||
bedrock: null,
|
||||
custom: null,
|
||||
deepseek: null,
|
||||
@@ -129,7 +135,7 @@ const populatedProviders: ResultOf<typeof SettingsProvidersDocument> = {
|
||||
kimi: null,
|
||||
minimax: null,
|
||||
ollama: null,
|
||||
openai: defaultConfig('default-openai', ProviderType.Openai),
|
||||
openai: defaultConfig(ProviderType.Openai),
|
||||
qwen: null,
|
||||
}),
|
||||
enabled: entity('ProvidersReadinessStatus', {
|
||||
|
||||
@@ -284,3 +284,52 @@ describe('streaming assistant-log link (createStreamingLink)', () => {
|
||||
expect(emitted).toEqual([{ somethingElse: { id: '1' } }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ProviderConfig cache identity', () => {
|
||||
const PROVIDERS = gql`
|
||||
query P {
|
||||
settingsProviders {
|
||||
default {
|
||||
anthropic {
|
||||
id
|
||||
name
|
||||
type
|
||||
}
|
||||
openai {
|
||||
id
|
||||
name
|
||||
type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// The resolver builds default providers without an ID, so every one of them arrives as id 0.
|
||||
// Normalising on that shared id would collapse them onto a single cache entry and the last
|
||||
// write would win — the create form then seeds one provider type from another's defaults.
|
||||
it('keeps two defaults apart even though both carry id 0', () => {
|
||||
const cache = createCache();
|
||||
|
||||
cache.writeQuery({
|
||||
data: {
|
||||
settingsProviders: {
|
||||
__typename: 'ProvidersConfig',
|
||||
default: {
|
||||
__typename: 'DefaultProvidersConfig',
|
||||
anthropic: { __typename: 'ProviderConfig', id: 0, name: 'anthropic', type: 'anthropic' },
|
||||
openai: { __typename: 'ProviderConfig', id: 0, name: 'openai', type: 'openai' },
|
||||
},
|
||||
},
|
||||
},
|
||||
query: PROVIDERS,
|
||||
});
|
||||
|
||||
const read = cache.readQuery<{
|
||||
settingsProviders: { default: { anthropic: { name: string }; openai: { name: string } } };
|
||||
}>({ query: PROVIDERS });
|
||||
|
||||
expect(read?.settingsProviders.default.anthropic.name).toBe('anthropic');
|
||||
expect(read?.settingsProviders.default.openai.name).toBe('openai');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user