diff --git a/src/renderer/src/assets/images/apps/ling.png b/src/renderer/src/assets/images/apps/ling.png new file mode 100644 index 0000000000..22ab70692b Binary files /dev/null and b/src/renderer/src/assets/images/apps/ling.png differ diff --git a/src/renderer/src/assets/images/models/ling.png b/src/renderer/src/assets/images/models/ling.png new file mode 100644 index 0000000000..22ab70692b Binary files /dev/null and b/src/renderer/src/assets/images/models/ling.png differ diff --git a/src/renderer/src/config/__test__/reasoning.test.ts b/src/renderer/src/config/__test__/reasoning.test.ts index 96fad861f3..e9f4bb7b73 100644 --- a/src/renderer/src/config/__test__/reasoning.test.ts +++ b/src/renderer/src/config/__test__/reasoning.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, vi } from 'vitest' -import { isDoubaoSeedAfter251015, isDoubaoThinkingAutoModel } from '../models/reasoning' +import { isDoubaoSeedAfter251015, isDoubaoThinkingAutoModel, isLingReasoningModel } from '../models/reasoning' // FIXME: Idk why it's imported. Maybe circular dependency somewhere vi.mock('@renderer/services/AssistantService.ts', () => ({ @@ -164,3 +164,60 @@ describe('Doubao Models', () => { }) }) }) +describe('Ling Models', () => { + describe('isLingReasoningModel', () => { + it('should return false for ling variants', () => { + expect( + isLingReasoningModel({ + id: 'ling-1t', + name: '', + provider: '', + group: '' + }) + ).toBe(false) + expect( + isLingReasoningModel({ + id: 'ling-flash-2.0', + name: '', + provider: '', + group: '' + }) + ).toBe(false) + expect( + isLingReasoningModel({ + id: 'ling-mini-2.0', + name: '', + provider: '', + group: '' + }) + ).toBe(false) + }) + + it('should return true for ring variants', () => { + expect( + isLingReasoningModel({ + id: 'ring-1t', + name: '', + provider: '', + group: '' + }) + ).toBe(true) + expect( + isLingReasoningModel({ + id: 'ring-flash-2.0', + name: '', + provider: '', + group: '' + }) + ).toBe(true) + expect( + isLingReasoningModel({ + id: 'ring-mini-2.0', + name: '', + provider: '', + group: '' + }) + ).toBe(true) + }) + }) +}) diff --git a/src/renderer/src/config/minapps.ts b/src/renderer/src/config/minapps.ts index 1d1a269e7c..3174e22057 100644 --- a/src/renderer/src/config/minapps.ts +++ b/src/renderer/src/config/minapps.ts @@ -25,6 +25,7 @@ import GrokXAppLogo from '@renderer/assets/images/apps/grok-x.png?url' import KimiAppLogo from '@renderer/assets/images/apps/kimi.webp?url' import LambdaChatLogo from '@renderer/assets/images/apps/lambdachat.webp?url' import LeChatLogo from '@renderer/assets/images/apps/lechat.png?url' +import LingAppLogo from '@renderer/assets/images/apps/ling.png?url' import LongCatAppLogo from '@renderer/assets/images/apps/longcat.svg?url' import MetasoAppLogo from '@renderer/assets/images/apps/metaso.webp?url' import MonicaLogo from '@renderer/assets/images/apps/monica.webp?url' @@ -460,6 +461,16 @@ const ORIGIN_DEFAULT_MIN_APPS: MinAppType[] = [ logo: LongCatAppLogo, url: 'https://longcat.chat/', bodered: true + }, + { + id: 'ling', + name: i18n.t('minapps.ant-ling'), + url: 'https://ling.tbox.cn/chat', + logo: LingAppLogo, + bodered: true, + style: { + padding: 6 + } } ] diff --git a/src/renderer/src/config/models/logo.ts b/src/renderer/src/config/models/logo.ts index ef8cc87125..9e1ef2ce21 100644 --- a/src/renderer/src/config/models/logo.ts +++ b/src/renderer/src/config/models/logo.ts @@ -84,6 +84,7 @@ import JinaModelLogo from '@renderer/assets/images/models/jina.png' import JinaModelLogoDark from '@renderer/assets/images/models/jina_dark.png' import KeLingModelLogo from '@renderer/assets/images/models/keling.png' import KeLingModelLogoDark from '@renderer/assets/images/models/keling_dark.png' +import LingModelLogo from '@renderer/assets/images/models/ling.png' import LlamaModelLogo from '@renderer/assets/images/models/llama.png' import LlamaModelLogoDark from '@renderer/assets/images/models/llama_dark.png' import LLavaModelLogo from '@renderer/assets/images/models/llava.png' @@ -289,6 +290,8 @@ export function getModelLogoById(modelId: string): string | undefined { zhipu: isLight ? ZhipuModelLogo : ZhipuModelLogoDark, longcat: LongCatAppLogo, bytedance: BytedanceModelLogo, + ling: LingModelLogo, + ring: LingModelLogo, '(V_1|V_1_TURBO|V_2|V_2A|V_2_TURBO|DESCRIBE|UPSCALE)': IdeogramModelLogo } as const satisfies Record diff --git a/src/renderer/src/config/models/reasoning.ts b/src/renderer/src/config/models/reasoning.ts index c3134b1f7d..455ec08d64 100644 --- a/src/renderer/src/config/models/reasoning.ts +++ b/src/renderer/src/config/models/reasoning.ts @@ -424,6 +424,14 @@ export const isDeepSeekHybridInferenceModel = (model: Model) => { return /deepseek-v3(?:\.\d|-\d)(?:(\.|-)\w+)?$/.test(modelId) || modelId.includes('deepseek-chat-v3.1') } +export const isLingReasoningModel = (model?: Model): boolean => { + if (!model) { + return false + } + const modelId = getLowerBaseModelName(model.id, '/') + return ['ring-1t', 'ring-mini', 'ring-flash'].some((id) => modelId.includes(id)) +} + export const isSupportedThinkingTokenDeepSeekModel = isDeepSeekHybridInferenceModel export const isZhipuReasoningModel = (model?: Model): boolean => { @@ -475,6 +483,7 @@ export function isReasoningModel(model?: Model): boolean { isZhipuReasoningModel(model) || isStepReasoningModel(model) || isDeepSeekHybridInferenceModel(model) || + isLingReasoningModel(model) || modelId.includes('magistral') || modelId.includes('minimax-m1') || modelId.includes('pangu-pro-moe') || diff --git a/src/renderer/src/config/models/tooluse.ts b/src/renderer/src/config/models/tooluse.ts index f1f27e0fd7..e2d2ffc7c6 100644 --- a/src/renderer/src/config/models/tooluse.ts +++ b/src/renderer/src/config/models/tooluse.ts @@ -25,7 +25,9 @@ export const FUNCTION_CALLING_MODELS = [ 'gemini(?:-[\\w-]+)?', // 提前排除了gemini的嵌入模型 'grok-3(?:-[\\w-]+)?', 'doubao-seed-1[.-]6(?:-[\\w-]+)?', - 'kimi-k2(?:-[\\w-]+)?' + 'kimi-k2(?:-[\\w-]+)?', + 'ling-\\w+(?:-[\\w-]+)?', + 'ring-\\w+(?:-[\\w-]+)?' ] const FUNCTION_CALLING_EXCLUDED_MODELS = [ diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 84ef5a9911..e49eb7fa72 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -1804,6 +1804,7 @@ "title": "MinApp" }, "minapps": { + "ant-ling": "Ant Ling", "baichuan": "Baichuan", "baidu-ai-search": "Baidu AI Search", "chatglm": "ChatGLM", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index b4c0864b58..e63264127e 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -1804,6 +1804,7 @@ "title": "小程序" }, "minapps": { + "ant-ling": "蚂蚁百灵", "baichuan": "百小应", "baidu-ai-search": "百度AI搜索", "chatglm": "智谱清言", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 749ee263cd..074b935b34 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -1804,6 +1804,7 @@ "title": "小工具" }, "minapps": { + "ant-ling": "Ant Ling", "baichuan": "百小應", "baidu-ai-search": "百度AI搜索", "chatglm": "智譜清言", diff --git a/src/renderer/src/i18n/translate/el-gr.json b/src/renderer/src/i18n/translate/el-gr.json index 1d5e2ea085..569820776c 100644 --- a/src/renderer/src/i18n/translate/el-gr.json +++ b/src/renderer/src/i18n/translate/el-gr.json @@ -1804,6 +1804,7 @@ "title": "Μικρόπρογραμμα" }, "minapps": { + "ant-ling": "Ant Ling", "baichuan": "Baichuan", "baidu-ai-search": "Baidu AI Search", "chatglm": "ChatGLM", diff --git a/src/renderer/src/i18n/translate/es-es.json b/src/renderer/src/i18n/translate/es-es.json index dec0ef59e5..96fdbf5127 100644 --- a/src/renderer/src/i18n/translate/es-es.json +++ b/src/renderer/src/i18n/translate/es-es.json @@ -1804,6 +1804,7 @@ "title": "Mini programa" }, "minapps": { + "ant-ling": "Ant Ling", "baichuan": "Baichuan", "baidu-ai-search": "Baidu AI Search", "chatglm": "ChatGLM", diff --git a/src/renderer/src/i18n/translate/fr-fr.json b/src/renderer/src/i18n/translate/fr-fr.json index 1f26564f5a..add50fb202 100644 --- a/src/renderer/src/i18n/translate/fr-fr.json +++ b/src/renderer/src/i18n/translate/fr-fr.json @@ -1804,6 +1804,7 @@ "title": "Mini-programme" }, "minapps": { + "ant-ling": "Ant Ling", "baichuan": "Baichuan", "baidu-ai-search": "Baidu AI Search", "chatglm": "ChatGLM", diff --git a/src/renderer/src/i18n/translate/ja-jp.json b/src/renderer/src/i18n/translate/ja-jp.json index aae0fdb3cd..154a69edf5 100644 --- a/src/renderer/src/i18n/translate/ja-jp.json +++ b/src/renderer/src/i18n/translate/ja-jp.json @@ -1804,6 +1804,7 @@ "title": "ミニアプリ" }, "minapps": { + "ant-ling": "Ant Ling", "baichuan": "百小應", "baidu-ai-search": "百度AI検索", "chatglm": "ChatGLM", diff --git a/src/renderer/src/i18n/translate/pt-pt.json b/src/renderer/src/i18n/translate/pt-pt.json index f534e7beab..75faafe889 100644 --- a/src/renderer/src/i18n/translate/pt-pt.json +++ b/src/renderer/src/i18n/translate/pt-pt.json @@ -1804,6 +1804,7 @@ "title": "Pequeno aplicativo" }, "minapps": { + "ant-ling": "Ant Ling", "baichuan": "Baichuan", "baidu-ai-search": "Baidu AI Search", "chatglm": "ChatGLM", diff --git a/src/renderer/src/i18n/translate/ru-ru.json b/src/renderer/src/i18n/translate/ru-ru.json index 04d8fde189..4b56b7b0da 100644 --- a/src/renderer/src/i18n/translate/ru-ru.json +++ b/src/renderer/src/i18n/translate/ru-ru.json @@ -1804,6 +1804,7 @@ "title": "Встроенные приложения" }, "minapps": { + "ant-ling": "Ant Ling", "baichuan": "Байчжан", "baidu-ai-search": "Baidu AI Search", "chatglm": "ChatGLM", diff --git a/src/renderer/src/store/migrate.ts b/src/renderer/src/store/migrate.ts index 09dd9cb9c9..78dee1489a 100644 --- a/src/renderer/src/store/migrate.ts +++ b/src/renderer/src/store/migrate.ts @@ -2683,6 +2683,15 @@ const migrateConfig = { logger.error('migrate 163 error', error as Error) return state } + }, + '164': (state: RootState) => { + try { + addMiniApp(state, 'ling') + return state + } catch (error) { + logger.error('migrate 164 error', error as Error) + return state + } } }