feat: implement model persistence with per-session overrides
- Add session_config SQLite table for per-session settings - Update routing to support session override → agent config → global default resolution chain - Upgrade WebChat SessionBridge from NativeAgent to AgentOrchestrator - Add /model, /local, /cloud commands to Telegram adapter - Add /model command to WebChat gateway handlers - Clear session overrides on /reset command - Pass memoryStore and config through to SessionBridge - Add comprehensive tests for all new functionality Fixes model persistence bug where TUI model changes didn't affect WebChat/Telegram sessions. Now: - TUI /model sets global default (persists across restarts, affects all new sessions) - WebChat/Telegram /model sets session override (only that conversation, cleared on /reset) - WebChat sessions gain AgentOrchestrator features (delegation, compaction, memory)
This commit is contained in:
+55
-1
@@ -58,9 +58,18 @@ export function createMessageRouter(deps: {
|
||||
if (!entry) {
|
||||
const session = deps.sessionManager.getSession(channel, senderId);
|
||||
|
||||
// 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
|
||||
const effectiveTier = tierFromMetadata
|
||||
?? sessionTierOverride
|
||||
?? agentConfig?.modelTier
|
||||
?? deps.config.agents.primary_tier
|
||||
?? 'default';
|
||||
|
||||
// Use agent config overrides where available, falling back to global config
|
||||
const effectiveSystemPrompt = agentConfig?.systemPrompt ?? deps.systemPrompt;
|
||||
const effectiveTier = tierFromMetadata ?? agentConfig?.modelTier ?? deps.config.agents.primary_tier ?? 'default';
|
||||
const effectiveProvider = deps.config.models.default.provider;
|
||||
|
||||
const delegationConfig: DelegationConfig = {
|
||||
@@ -166,6 +175,46 @@ export function createMessageRouter(deps: {
|
||||
if (msg.metadata?.isCommand) {
|
||||
if (msg.metadata.command === 'reset') {
|
||||
agent.reset();
|
||||
// Clear per-session config overrides
|
||||
const session = deps.sessionManager.getSession(msg.channel, msg.senderId);
|
||||
session.deleteConfig('modelTier');
|
||||
return;
|
||||
}
|
||||
if (msg.metadata.command === 'model') {
|
||||
const modelArg = msg.metadata.commandArgs as string | undefined;
|
||||
const session = deps.sessionManager.getSession(msg.channel, msg.senderId);
|
||||
|
||||
if (!modelArg) {
|
||||
// Show current model tier
|
||||
const currentTier = agent.getModelTier();
|
||||
const sessionOverride = session.getConfig('modelTier');
|
||||
const available = deps.modelRouter.getAvailableTiers();
|
||||
const labels = deps.modelRouter.getAllLabels();
|
||||
const lines = [`Active tier: ${currentTier}${sessionOverride ? ' (session override)' : ''}`];
|
||||
for (const tier of available) {
|
||||
const label = labels[tier] ?? 'unknown';
|
||||
const marker = tier === currentTier ? ' ←' : '';
|
||||
lines.push(` ${tier}: ${label}${marker}`);
|
||||
}
|
||||
await reply({ text: lines.join('\n'), replyTo: msg.id });
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate tier
|
||||
const validTiers = deps.modelRouter.getAvailableTiers();
|
||||
if (!validTiers.includes(modelArg as ModelTier)) {
|
||||
await reply({ text: `Model tier not available: ${modelArg}`, replyTo: msg.id });
|
||||
return;
|
||||
}
|
||||
|
||||
// Persist to session config
|
||||
session.setConfig('modelTier', modelArg);
|
||||
|
||||
// Update the orchestrator's agent tier
|
||||
agent.setModelTier(modelArg as ModelTier);
|
||||
|
||||
const label = deps.modelRouter.getLabel(modelArg as ModelTier);
|
||||
await reply({ text: `Switched to model: ${modelArg} (${label})`, replyTo: msg.id });
|
||||
return;
|
||||
}
|
||||
if (msg.metadata.command === 'compact') {
|
||||
@@ -215,8 +264,13 @@ export function createMessageRouter(deps: {
|
||||
try {
|
||||
// Determine if the active model supports native audio input
|
||||
let effectiveTier: string = deps.config.agents.primary_tier ?? 'default';
|
||||
const session = deps.sessionManager.getSession(msg.channel, msg.senderId);
|
||||
const sessionTierOverride = session.getConfig('modelTier');
|
||||
|
||||
if (msg.metadata?.modelTier) {
|
||||
effectiveTier = msg.metadata.modelTier as string;
|
||||
} else if (sessionTierOverride) {
|
||||
effectiveTier = sessionTierOverride;
|
||||
} else if (deps.agentRouter && deps.agentConfigRegistry) {
|
||||
const agentName = deps.agentRouter.resolve(msg.channel, msg.senderId);
|
||||
if (agentName) {
|
||||
|
||||
Reference in New Issue
Block a user