From f797e90d79a926cd92ba835bbc9510c45f238fb5 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Tue, 22 Jul 2025 15:52:54 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=80=20feat:=20`moonshotai/kimi`=20Cont?= =?UTF-8?q?ext=20and=20OpenRouter=20Endpoint=20Token=20Config=20(#8604)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat: Enhance agent initialization with endpoint token configuration and round max context tokens * feat: recognize moonshot/kimi model context window * chore: remove unused i18n key --- api/server/services/Endpoints/agents/agent.js | 4 +- .../services/Endpoints/custom/initialize.js | 3 +- api/utils/tokens.js | 9 +++- api/utils/tokens.spec.js | 42 +++++++++++++++++++ client/src/locales/en/translation.json | 3 +- 5 files changed, 55 insertions(+), 6 deletions(-) diff --git a/api/server/services/Endpoints/agents/agent.js b/api/server/services/Endpoints/agents/agent.js index 3af2170d5c..a64ce97e78 100644 --- a/api/server/services/Endpoints/agents/agent.js +++ b/api/server/services/Endpoints/agents/agent.js @@ -131,7 +131,7 @@ const initializeAgent = async ({ ); const agentMaxContextTokens = optionalChainWithEmptyCheck( maxContextTokens, - getModelMaxTokens(tokensModel, providerEndpointMap[provider]), + getModelMaxTokens(tokensModel, providerEndpointMap[provider], options.endpointTokenConfig), 4096, ); @@ -191,7 +191,7 @@ const initializeAgent = async ({ resendFiles, toolContextMap, useLegacyContent: !!options.useLegacyContent, - maxContextTokens: (agentMaxContextTokens - maxTokens) * 0.9, + maxContextTokens: Math.round((agentMaxContextTokens - maxTokens) * 0.9), }; }; diff --git a/api/server/services/Endpoints/custom/initialize.js b/api/server/services/Endpoints/custom/initialize.js index 58da9f10dd..d2b7549699 100644 --- a/api/server/services/Endpoints/custom/initialize.js +++ b/api/server/services/Endpoints/custom/initialize.js @@ -141,8 +141,9 @@ const initializeClient = async ({ req, res, endpointOption, optionsOnly, overrid const options = getOpenAIConfig(apiKey, clientOptions, endpoint); if (options != null) { options.useLegacyContent = true; + options.endpointTokenConfig = endpointTokenConfig; } - if (!customOptions.streamRate) { + if (!clientOptions.streamRate) { return options; } options.llmConfig.callbacks = [ diff --git a/api/utils/tokens.js b/api/utils/tokens.js index a8363db182..a35f18a51b 100644 --- a/api/utils/tokens.js +++ b/api/utils/tokens.js @@ -226,7 +226,14 @@ const xAIModels = { 'grok-4': 256000, // 256K context }; -const aggregateModels = { ...openAIModels, ...googleModels, ...bedrockModels, ...xAIModels }; +const aggregateModels = { + ...openAIModels, + ...googleModels, + ...bedrockModels, + ...xAIModels, + // misc. + kimi: 131000, +}; const maxTokensMap = { [EModelEndpoint.azureOpenAI]: openAIModels, diff --git a/api/utils/tokens.spec.js b/api/utils/tokens.spec.js index 8a2e8ed11d..2d4f051584 100644 --- a/api/utils/tokens.spec.js +++ b/api/utils/tokens.spec.js @@ -714,3 +714,45 @@ describe('Claude Model Tests', () => { }); }); }); + +describe('Kimi Model Tests', () => { + describe('getModelMaxTokens', () => { + test('should return correct tokens for Kimi models', () => { + expect(getModelMaxTokens('kimi')).toBe(131000); + expect(getModelMaxTokens('kimi-k2')).toBe(131000); + expect(getModelMaxTokens('kimi-vl')).toBe(131000); + }); + + test('should return correct tokens for Kimi models with provider prefix', () => { + expect(getModelMaxTokens('moonshotai/kimi-k2')).toBe(131000); + expect(getModelMaxTokens('moonshotai/kimi')).toBe(131000); + expect(getModelMaxTokens('moonshotai/kimi-vl')).toBe(131000); + }); + + test('should handle partial matches for Kimi models', () => { + expect(getModelMaxTokens('kimi-k2-latest')).toBe(131000); + expect(getModelMaxTokens('kimi-vl-preview')).toBe(131000); + expect(getModelMaxTokens('kimi-2024')).toBe(131000); + }); + }); + + describe('matchModelName', () => { + test('should match exact Kimi model names', () => { + expect(matchModelName('kimi')).toBe('kimi'); + expect(matchModelName('kimi-k2')).toBe('kimi'); + expect(matchModelName('kimi-vl')).toBe('kimi'); + }); + + test('should match Kimi model variations with provider prefix', () => { + expect(matchModelName('moonshotai/kimi')).toBe('kimi'); + expect(matchModelName('moonshotai/kimi-k2')).toBe('kimi'); + expect(matchModelName('moonshotai/kimi-vl')).toBe('kimi'); + }); + + test('should match Kimi model variations with suffixes', () => { + expect(matchModelName('kimi-k2-latest')).toBe('kimi'); + expect(matchModelName('kimi-vl-preview')).toBe('kimi'); + expect(matchModelName('kimi-2024')).toBe('kimi'); + }); + }); +}); diff --git a/client/src/locales/en/translation.json b/client/src/locales/en/translation.json index def5f5a431..79d6bc4dcf 100644 --- a/client/src/locales/en/translation.json +++ b/client/src/locales/en/translation.json @@ -466,7 +466,6 @@ "com_nav_send_message": "Send message", "com_nav_setting_account": "Account", "com_nav_setting_balance": "Balance", - "com_nav_setting_beta": "Beta features", "com_nav_setting_chat": "Chat", "com_nav_setting_data": "Data controls", "com_nav_setting_general": "General", @@ -1090,4 +1089,4 @@ "com_ui_yes": "Yes", "com_ui_zoom": "Zoom", "com_user_message": "You" -} \ No newline at end of file +}