feat(core): Preliminary changes for subagent model routing. (#16035)

This commit is contained in:
joshualitt
2026-01-07 13:21:10 -08:00
committed by GitHub
parent 17b3eb730a
commit a1dd19738e
12 changed files with 200 additions and 15 deletions
@@ -577,6 +577,81 @@ describe('ModelConfigService', () => {
});
});
describe('runtime overrides', () => {
it('should resolve a simple runtime-registered override', () => {
const config: ModelConfigServiceConfig = {
aliases: {},
overrides: [],
};
const service = new ModelConfigService(config);
service.registerRuntimeModelOverride({
match: { model: 'gemini-pro' },
modelConfig: {
generateContentConfig: {
temperature: 0.99,
},
},
});
const resolved = service.getResolvedConfig({ model: 'gemini-pro' });
expect(resolved.model).toBe('gemini-pro');
expect(resolved.generateContentConfig.temperature).toBe(0.99);
});
it('should prioritize runtime overrides over default overrides when they have the same specificity', () => {
const config: ModelConfigServiceConfig = {
aliases: {},
overrides: [
{
match: { model: 'gemini-pro' },
modelConfig: { generateContentConfig: { temperature: 0.1 } },
},
],
};
const service = new ModelConfigService(config);
service.registerRuntimeModelOverride({
match: { model: 'gemini-pro' },
modelConfig: { generateContentConfig: { temperature: 0.9 } },
});
const resolved = service.getResolvedConfig({ model: 'gemini-pro' });
// Runtime overrides are appended after overrides/customOverrides, so they should win.
expect(resolved.generateContentConfig.temperature).toBe(0.9);
});
it('should still respect specificity with runtime overrides', () => {
const config: ModelConfigServiceConfig = {
aliases: {},
overrides: [],
};
const service = new ModelConfigService(config);
// Register a more specific runtime override
service.registerRuntimeModelOverride({
match: { model: 'gemini-pro', overrideScope: 'my-agent' },
modelConfig: { generateContentConfig: { temperature: 0.1 } },
});
// Register a less specific runtime override later
service.registerRuntimeModelOverride({
match: { model: 'gemini-pro' },
modelConfig: { generateContentConfig: { temperature: 0.9 } },
});
const resolved = service.getResolvedConfig({
model: 'gemini-pro',
overrideScope: 'my-agent',
});
// Specificity should win over order
expect(resolved.generateContentConfig.temperature).toBe(0.1);
});
});
describe('custom aliases', () => {
it('should resolve a custom alias', () => {
const config: ModelConfigServiceConfig = {
@@ -65,6 +65,7 @@ export interface _ResolvedModelConfig {
export class ModelConfigService {
private readonly runtimeAliases: Record<string, ModelConfigAlias> = {};
private readonly runtimeOverrides: ModelConfigOverride[] = [];
// TODO(12597): Process config to build a typed alias hierarchy.
constructor(private readonly config: ModelConfigServiceConfig) {}
@@ -73,6 +74,10 @@ export class ModelConfigService {
this.runtimeAliases[aliasName] = alias;
}
registerRuntimeModelOverride(override: ModelConfigOverride): void {
this.runtimeOverrides.push(override);
}
private resolveAlias(
aliasName: string,
aliases: Record<string, ModelConfigAlias>,
@@ -123,7 +128,11 @@ export class ModelConfigService {
...customAliases,
...this.runtimeAliases,
};
const allOverrides = [...overrides, ...customOverrides];
const allOverrides = [
...overrides,
...customOverrides,
...this.runtimeOverrides,
];
let baseModel: string | undefined = context.model;
let resolvedConfig: GenerateContentConfig = {};