feat(routing): honor models.for via metadata modelFor

This commit is contained in:
William Valentin
2026-02-17 10:38:56 -08:00
parent 2007c0c060
commit d67cfa64a6
3 changed files with 121 additions and 8 deletions
+34 -1
View File
@@ -44,6 +44,34 @@ function buildProviderConfigMap(config: Config): Partial<Record<ModelProvider, M
return providerConfigs;
}
function tierFromUseCase(config: Config, useCaseRaw: unknown): ModelTier | undefined {
if (typeof useCaseRaw !== 'string') {
return undefined;
}
const normalized = useCaseRaw.trim().toLowerCase();
if (!normalized) {
return undefined;
}
const mappings: Array<{ tier: ModelTier; tags: string[] | undefined }> = [
{ tier: 'fast', tags: config.models.fast?.for },
{ tier: 'default', tags: config.models.default.for },
{ tier: 'complex', tags: config.models.complex?.for },
{ tier: 'local', tags: config.models.local?.for },
];
for (const { tier, tags } of mappings) {
if (!tags || tags.length === 0) {
continue;
}
if (tags.some((tag) => tag.trim().toLowerCase() === normalized)) {
return tier;
}
}
return undefined;
}
/**
* Create the unified message handler for the channel registry.
* Each channel+sender pair gets its own AgentOrchestrator backed by a persistent session.
@@ -83,6 +111,7 @@ export function createMessageRouter(deps: {
// Cron job tier wins over agent config tier
const tierFromMetadata = metadata?.modelTier as ModelTier | undefined;
const tierFromUseCaseMetadata = tierFromUseCase(deps.config, metadata?.modelFor);
// Include agent config name in cache key so different agents aren't shared
let skillOverride = metadata?.skillOverride as string | undefined;
@@ -100,8 +129,9 @@ export function createMessageRouter(deps: {
// Read per-session model tier override (persisted in SQLite)
const sessionTierOverride = session.getConfig('modelTier') as ModelTier | undefined;
// Resolution chain: metadata (cron) → session override agent config global default
// Resolution chain: metadata (explicit tier) → metadata modelFor -> session override -> agent config -> global default
const effectiveTier = tierFromMetadata
?? tierFromUseCaseMetadata
?? sessionTierOverride
?? agentConfig?.modelTier
?? deps.config.agents.primary_tier
@@ -766,9 +796,12 @@ export function createMessageRouter(deps: {
let effectiveTier: string = deps.config.agents.primary_tier ?? 'default';
const session = deps.sessionManager.getSession(msg.channel, msg.senderId);
const sessionTierOverride = session.getConfig('modelTier');
const tierFromUseCaseMetadata = tierFromUseCase(deps.config, msg.metadata?.modelFor);
if (msg.metadata?.modelTier) {
effectiveTier = msg.metadata.modelTier as string;
} else if (tierFromUseCaseMetadata) {
effectiveTier = tierFromUseCaseMetadata;
} else if (sessionTierOverride) {
effectiveTier = sessionTierOverride;
} else if (deps.agentRouter && deps.agentConfigRegistry) {