feat: add per-cron-job model tier selection
Allow cron jobs to specify a `model_tier` field that controls which LLM tier handles the job, without needing separate agent configs. Precedence: cron job model_tier > agent config > global primary_tier > 'default'. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@ import type { Tool } from '../tools/types.js';
|
||||
import { createMediaSendTool } from '../tools/index.js';
|
||||
import { createSandboxedShellTool, createSandboxedProcessStartTool, SandboxManager } from '../sandbox/index.js';
|
||||
import type { Config } from '../config/index.js';
|
||||
import { ModelRouter } from '../models/index.js';
|
||||
import { ModelRouter, type ModelTier } from '../models/index.js';
|
||||
import { ToolRegistry, ToolExecutor } from '../tools/index.js';
|
||||
import { SessionManager } from '../session/index.js';
|
||||
import { AgentConfigRegistry, AgentRouter } from '../agents/index.js';
|
||||
@@ -40,15 +40,19 @@ export function createMessageRouter(deps: {
|
||||
// Cache agents by session ID + agent config name to avoid recreating on every message
|
||||
const agents = new Map<string, { orchestrator: AgentOrchestrator; collector: OutboundAttachmentCollector }>();
|
||||
|
||||
function getOrCreateAgent(channel: string, senderId: string): { orchestrator: AgentOrchestrator; collector: OutboundAttachmentCollector } {
|
||||
function getOrCreateAgent(channel: string, senderId: string, metadata?: Record<string, unknown>): { orchestrator: AgentOrchestrator; collector: OutboundAttachmentCollector } {
|
||||
// Resolve agent config name via routing (sender → channel → default fallback)
|
||||
const agentConfigName = deps.agentRouter?.resolve(channel, senderId);
|
||||
const agentConfig = agentConfigName ? deps.agentConfigRegistry?.get(agentConfigName) : undefined;
|
||||
|
||||
// Cron job tier wins over agent config tier
|
||||
const tierFromMetadata = metadata?.modelTier as ModelTier | undefined;
|
||||
|
||||
// Include agent config name in cache key so different agents aren't shared
|
||||
const sessionId = agentConfigName
|
||||
const baseSid = agentConfigName
|
||||
? `${channel}:${senderId}:${agentConfigName}`
|
||||
: `${channel}:${senderId}`;
|
||||
const sessionId = tierFromMetadata ? `${baseSid}:${tierFromMetadata}` : baseSid;
|
||||
|
||||
let entry = agents.get(sessionId);
|
||||
if (!entry) {
|
||||
@@ -56,7 +60,7 @@ export function createMessageRouter(deps: {
|
||||
|
||||
// Use agent config overrides where available, falling back to global config
|
||||
const effectiveSystemPrompt = agentConfig?.systemPrompt ?? deps.systemPrompt;
|
||||
const effectiveTier = agentConfig?.modelTier ?? deps.config.agents.primary_tier ?? 'default';
|
||||
const effectiveTier = tierFromMetadata ?? agentConfig?.modelTier ?? deps.config.agents.primary_tier ?? 'default';
|
||||
const effectiveProvider = deps.config.models.default.provider;
|
||||
|
||||
const delegationConfig: DelegationConfig = {
|
||||
@@ -156,7 +160,7 @@ export function createMessageRouter(deps: {
|
||||
}
|
||||
|
||||
const handler = async (msg: InboundMessage, reply: (response: OutboundMessage) => Promise<void>): Promise<void> => {
|
||||
const { orchestrator: agent, collector } = getOrCreateAgent(msg.channel, msg.senderId);
|
||||
const { orchestrator: agent, collector } = getOrCreateAgent(msg.channel, msg.senderId, msg.metadata);
|
||||
|
||||
// Handle special commands
|
||||
if (msg.metadata?.isCommand) {
|
||||
|
||||
Reference in New Issue
Block a user