From f28d8830840cde142c759d7ab6fd48105b1dc5d7 Mon Sep 17 00:00:00 2001 From: Operator & Codex Date: Wed, 29 Apr 2026 00:11:18 +0200 Subject: [PATCH] Expose deepseek-chat in Telegram picker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Build: pass | Tests: FAIL — Tests 1 failed | 2028 passed (2029) --- src/telegram-commands.test.ts | 69 +++++++++++++++++++++++++++++++++++ src/telegram-commands.ts | 26 +++++++++++++ 2 files changed, 95 insertions(+) diff --git a/src/telegram-commands.test.ts b/src/telegram-commands.test.ts index 20f85dc..f1276fb 100644 --- a/src/telegram-commands.test.ts +++ b/src/telegram-commands.test.ts @@ -1,6 +1,7 @@ import { describe, it, expect, beforeEach } from 'vitest'; import { + augmentPickerModels, getTtsModeForChat, setTtsModeForChat, clearTtsOverride, @@ -108,3 +109,71 @@ describe('command context', () => { }).not.toThrow(); }); }); + +describe('augmentPickerModels', () => { + it('adds deepseek-chat for the DeepSeek picker when catalog only has v4 models', () => { + const models = augmentPickerModels('deepseek', [ + { + id: 'deepseek-v4-flash', + provider: 'deepseek', + parent: null, + name: 'deepseek-v4-flash', + context_length: null, + pricing_in: null, + pricing_out: null, + free_tier: false, + }, + { + id: 'deepseek-v4-pro', + provider: 'deepseek', + parent: null, + name: 'deepseek-v4-pro', + context_length: null, + pricing_in: null, + pricing_out: null, + free_tier: false, + }, + ]); + + expect(models.map((m) => m.id)).toEqual([ + 'deepseek-chat', + 'deepseek-v4-flash', + 'deepseek-v4-pro', + ]); + }); + + it('does not duplicate deepseek-chat when it is already present', () => { + const models = augmentPickerModels('deepseek', [ + { + id: 'deepseek-chat', + provider: 'deepseek', + parent: null, + name: 'deepseek-chat', + context_length: null, + pricing_in: null, + pricing_out: null, + free_tier: false, + }, + ]); + + expect(models).toHaveLength(1); + expect(models[0]?.id).toBe('deepseek-chat'); + }); + + it('leaves non-DeepSeek providers unchanged', () => { + const models = augmentPickerModels('openrouter', [ + { + id: 'openai/o3', + provider: 'openrouter', + parent: 'openai', + name: 'openai/o3', + context_length: null, + pricing_in: null, + pricing_out: null, + free_tier: false, + }, + ]); + + expect(models.map((m) => m.id)).toEqual(['openai/o3']); + }); +}); diff --git a/src/telegram-commands.ts b/src/telegram-commands.ts index d351979..feb340a 100644 --- a/src/telegram-commands.ts +++ b/src/telegram-commands.ts @@ -102,6 +102,7 @@ import { getModelCatalogSubProviderBuckets, getFreeModels, } from './model-catalog.js'; +import type { ModelEntry } from './model-catalog.js'; const modelHashMap = new Map(); @@ -115,6 +116,30 @@ function registerModelHash(id: string): string { return hash; } +export function augmentPickerModels( + provider: string, + models: ModelEntry[], +): ModelEntry[] { + if (provider !== 'deepseek') return models; + + const hasLegacyAlias = models.some((m) => m.id === 'deepseek-chat'); + if (hasLegacyAlias) return models; + + return [ + { + id: 'deepseek-chat', + provider: 'deepseek', + parent: null, + name: 'deepseek-chat', + context_length: null, + pricing_in: null, + pricing_out: null, + free_tier: false, + }, + ...models, + ]; +} + export interface CommandContext { queue: GroupQueue; registeredGroups: () => Record; @@ -2491,6 +2516,7 @@ export async function handleModelCallback( await ctxArg.answerCallbackQuery({ text: 'Database error' }); return; } + models = augmentPickerModels(provider, models); const kb = new InlineKeyboard(); for (const m of models.slice(0, 8)) { const hash = registerModelHash(m.id);