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:
@@ -62,10 +62,13 @@ describe('TelegramAdapter', () => {
|
||||
|
||||
// .use() for auth middleware
|
||||
expect(mockUse).toHaveBeenCalledTimes(1);
|
||||
// .command() for /start and /reset
|
||||
expect(mockCommand).toHaveBeenCalledTimes(2);
|
||||
// .command() for /start, /reset, /model, /local, /cloud
|
||||
expect(mockCommand).toHaveBeenCalledTimes(5);
|
||||
expect(mockCommand.mock.calls[0][0]).toBe('start');
|
||||
expect(mockCommand.mock.calls[1][0]).toBe('reset');
|
||||
expect(mockCommand.mock.calls[2][0]).toBe('model');
|
||||
expect(mockCommand.mock.calls[3][0]).toBe('local');
|
||||
expect(mockCommand.mock.calls[4][0]).toBe('cloud');
|
||||
// .on('message:text', ...) for text handler
|
||||
expect(mockOn).toHaveBeenCalledWith('message:text', expect.any(Function));
|
||||
// .start() to begin long polling
|
||||
|
||||
@@ -163,6 +163,52 @@ export class TelegramAdapter implements ChannelAdapter {
|
||||
await ctx.reply('Conversation reset.');
|
||||
});
|
||||
|
||||
this.bot.command('model', async (ctx) => {
|
||||
if (!this.messageHandler) return;
|
||||
|
||||
const args = ctx.message?.text?.replace(/^\/model\s*/, '').trim() ?? '';
|
||||
|
||||
this.messageHandler({
|
||||
id: String(ctx.message?.message_id ?? Date.now()),
|
||||
channel: 'telegram',
|
||||
senderId: String(ctx.chat.id),
|
||||
senderName: ctx.from?.first_name,
|
||||
text: `/model ${args}`.trim(),
|
||||
timestamp: Date.now(),
|
||||
metadata: {
|
||||
isCommand: true,
|
||||
command: 'model',
|
||||
commandArgs: args || undefined,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
this.bot.command('local', async (ctx) => {
|
||||
if (!this.messageHandler) return;
|
||||
this.messageHandler({
|
||||
id: String(ctx.message?.message_id ?? Date.now()),
|
||||
channel: 'telegram',
|
||||
senderId: String(ctx.chat.id),
|
||||
senderName: ctx.from?.first_name,
|
||||
text: '/model local',
|
||||
timestamp: Date.now(),
|
||||
metadata: { isCommand: true, command: 'model', commandArgs: 'local' },
|
||||
});
|
||||
});
|
||||
|
||||
this.bot.command('cloud', async (ctx) => {
|
||||
if (!this.messageHandler) return;
|
||||
this.messageHandler({
|
||||
id: String(ctx.message?.message_id ?? Date.now()),
|
||||
channel: 'telegram',
|
||||
senderId: String(ctx.chat.id),
|
||||
senderName: ctx.from?.first_name,
|
||||
text: '/model default',
|
||||
timestamp: Date.now(),
|
||||
metadata: { isCommand: true, command: 'model', commandArgs: 'default' },
|
||||
});
|
||||
});
|
||||
|
||||
// ── Text message handler ──
|
||||
|
||||
this.bot.on('message:text', async (ctx) => {
|
||||
|
||||
Reference in New Issue
Block a user