chore: add google gemini and deepseek as new supported remote engine providers (#4596)

* chore: add google gemini and deepseek as new supported remote engine providers

* chore: add logos

* chore: fallback default error message on empty

* chore: update open router models

* chore: typo fix

* chore: remove unusable queen vl
This commit is contained in:
Louis 2025-02-06 20:52:42 +07:00 committed by GitHub
parent ca220d18a6
commit a87bbd2840
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 267 additions and 46 deletions

View File

@ -6,6 +6,8 @@ import groq from './resources/groq.json' with { type: 'json' }
import martian from './resources/martian.json' with { type: 'json' }
import mistral from './resources/mistral.json' with { type: 'json' }
import nvidia from './resources/nvidia.json' with { type: 'json' }
import deepseek from './resources/deepseek.json' with { type: 'json' }
import googleGemini from './resources/google_gemini.json' with { type: 'json' }
import anthropicModels from './models/anthropic.json' with { type: 'json' }
import cohereModels from './models/cohere.json' with { type: 'json' }
@ -15,6 +17,8 @@ import groqModels from './models/groq.json' with { type: 'json' }
import martianModels from './models/martian.json' with { type: 'json' }
import mistralModels from './models/mistral.json' with { type: 'json' }
import nvidiaModels from './models/nvidia.json' with { type: 'json' }
import deepseekModels from './models/deepseek.json' with { type: 'json' }
import googleGeminiModels from './models/google_gemini.json' with { type: 'json' }
const engines = [
anthropic,
@ -25,6 +29,8 @@ const engines = [
mistral,
martian,
nvidia,
deepseek,
googleGemini,
]
const models = [
...anthropicModels,
@ -35,5 +41,7 @@ const models = [
...mistralModels,
...martianModels,
...nvidiaModels,
...deepseekModels,
...googleGeminiModels,
]
export { engines, models }

View File

@ -0,0 +1,28 @@
[
{
"model": "deepseek-chat",
"object": "model",
"name": "DeepSeek Chat",
"version": "1.0",
"description": "The deepseek-chat model has been upgraded to DeepSeek-V3. deepseek-reasoner points to the new model DeepSeek-R1",
"inference_params": {
"max_tokens": 8192,
"temperature": 0.6,
"stream": true
},
"engine": "deepseek"
},
{
"model": "deepseek-reasoner",
"object": "model",
"name": "DeepSeek R1",
"version": "1.0",
"description": "CoT (Chain of Thought) is the reasoning content deepseek-reasoner gives before output the final answer. For details, please refer to Reasoning Model.",
"inference_params": {
"max_tokens": 8192,
"temperature": 0.6,
"stream": true
},
"engine": "deepseek"
}
]

View File

@ -0,0 +1,67 @@
[
{
"model": "gemini-2.0-flash",
"object": "model",
"name": "Gemini 2.0 Flash",
"version": "1.0",
"description": "Gemini 2.0 Flash delivers next-gen features and improved capabilities, including superior speed, native tool use, multimodal generation, and a 1M token context window.",
"inference_params": {
"max_tokens": 8192,
"temperature": 0.6,
"stream": true
},
"engine": "google_gemini"
},
{
"model": "gemini-2.0-flash-lite-preview",
"object": "model",
"name": "Gemini 2.0 Flash-Lite Preview",
"version": "1.0",
"description": "A Gemini 2.0 Flash model optimized for cost efficiency and low latency.",
"inference_params": {
"max_tokens": 8192,
"temperature": 0.6,
"stream": true
},
"engine": "google_gemini"
},
{
"model": "gemini-1.5-flash",
"object": "model",
"name": "Gemini 1.5 Flash",
"version": "1.0",
"description": "Gemini 1.5 Flash is a fast and versatile multimodal model for scaling across diverse tasks.",
"inference_params": {
"max_tokens": 8192,
"temperature": 0.6,
"stream": true
},
"engine": "google_gemini"
},
{
"model": "gemini-1.5-flash-8b",
"object": "model",
"name": "Gemini 1.5 Flash-8B",
"version": "1.0",
"description": "Gemini 1.5 Flash-8B is a small model designed for lower intelligence tasks.",
"inference_params": {
"max_tokens": 8192,
"temperature": 0.6,
"stream": true
},
"engine": "google_gemini"
},
{
"model": "gemini-1.5-pro",
"object": "model",
"name": "Gemini 1.5 Pro",
"version": "1.0",
"description": "Gemini 1.5 Pro is a mid-size multimodal model that is optimized for a wide-range of reasoning tasks. 1.5 Pro can process large amounts of data at once, including 2 hours of video, 19 hours of audio, codebases with 60,000 lines of code, or 2,000 pages of text. ",
"inference_params": {
"max_tokens": 8192,
"temperature": 0.6,
"stream": true
},
"engine": "google_gemini"
}
]

View File

@ -82,7 +82,6 @@
"max_tokens": 100000,
"temperature": 1,
"top_p": 1,
"stream": true,
"frequency_penalty": 0,
"presence_penalty": 0
},

View File

@ -1,16 +1,61 @@
[
{
"model": "open-router-auto",
"model": "deepseek/deepseek-r1:free",
"object": "model",
"name": "OpenRouter",
"name": "DeepSeek: R1",
"version": "1.0",
"description": " OpenRouter scouts for the lowest prices and best latencies/throughputs across dozens of providers, and lets you choose how to prioritize them.",
"description": "OpenRouter scouts for the lowest prices and best latencies/throughputs across dozens of providers, and lets you choose how to prioritize them.",
"inference_params": {
"max_tokens": 128000,
"temperature": 0.7,
"top_p": 0.95,
"frequency_penalty": 0,
"presence_penalty": 0
"presence_penalty": 0,
"stream": true
},
"engine": "openrouter"
},
{
"model": "deepseek/deepseek-r1-distill-llama-70b:free",
"object": "model",
"name": "DeepSeek: R1 Distill Llama 70B",
"version": "1.0",
"description": " OpenRouter scouts for the lowest prices and best latencies/throughputs across dozens of providers, and lets you choose how to prioritize them.",
"inference_params": {
"temperature": 0.7,
"top_p": 0.95,
"frequency_penalty": 0,
"presence_penalty": 0,
"stream": true
},
"engine": "openrouter"
},
{
"model": "deepseek/deepseek-r1-distill-llama-70b:free",
"object": "model",
"name": "DeepSeek: R1 Distill Llama 70B",
"version": "1.0",
"description": "OpenRouter scouts for the lowest prices and best latencies/throughputs across dozens of providers, and lets you choose how to prioritize them.",
"inference_params": {
"temperature": 0.7,
"top_p": 0.95,
"frequency_penalty": 0,
"presence_penalty": 0,
"stream": true
},
"engine": "openrouter"
},
{
"model": "meta-llama/llama-3.1-405b-instruct:free",
"object": "model",
"name": "Meta: Llama 3.1 405B Instruct",
"version": "1.0",
"description": "OpenRouter scouts for the lowest prices and best latencies/throughputs across dozens of providers, and lets you choose how to prioritize them.",
"inference_params": {
"temperature": 0.7,
"top_p": 0.95,
"frequency_penalty": 0,
"presence_penalty": 0,
"stream": true
},
"engine": "openrouter"
}

View File

@ -1,5 +1,5 @@
{
"id": "@janhq/inference-anthropic-extension",
"id": "anthropic",
"type": "remote",
"engine": "anthropic",
"url": "https://console.anthropic.com/settings/keys",

View File

@ -1,5 +1,5 @@
{
"id": "@janhq/inference-cohere-extension",
"id": "cohere",
"type": "remote",
"engine": "cohere",
"url": "https://dashboard.cohere.com/api-keys",

View File

@ -0,0 +1,23 @@
{
"id": "deepseek",
"type": "remote",
"engine": "deepseek",
"url": "https://platform.deepseek.com/api_keys",
"api_key": "",
"metadata": {
"get_models_url": "https://api.deepseek.com/models",
"header_template": "Authorization: Bearer {{api_key}}",
"transform_req": {
"chat_completions": {
"url": "https://api.deepseek.com/chat/completions",
"template": "{ {% set first = true %} {% for key, value in input_request %} {% if key == \"messages\" or key == \"temperature\" or key == \"store\" or key == \"max_tokens\" or key == \"stream\" or key == \"presence_penalty\" or key == \"metadata\" or key == \"frequency_penalty\" or key == \"tools\" or key == \"tool_choice\" or key == \"logprobs\" or key == \"top_logprobs\" or key == \"logit_bias\" or key == \"n\" or key == \"modalities\" or key == \"prediction\" or key == \"response_format\" or key == \"service_tier\" or key == \"model\" or key == \"seed\" or key == \"stop\" or key == \"stream_options\" or key == \"top_p\" or key == \"parallel_tool_calls\" or key == \"user\" %} {% if not first %},{% endif %} \"{{ key }}\": {{ tojson(value) }} {% set first = false %} {% endif %} {% endfor %} }"
}
},
"transform_resp": {
"chat_completions": {
"template": "{ {% set first = true %} {% for key, value in input_request %} {% if key == \"choices\" or key == \"created\" or key == \"model\" or key == \"service_tier\" or key == \"system_fingerprint\" or key == \"stream\" or key == \"object\" or key == \"usage\" %} {% if not first %},{% endif %} \"{{ key }}\": {{ tojson(value) }} {% set first = false %} {% endif %} {% endfor %} }"
}
},
"explore_models_url": "https://api-docs.deepseek.com/quick_start/pricing"
}
}

View File

@ -0,0 +1,23 @@
{
"id": "google_gemini",
"type": "remote",
"engine": "google_gemini",
"url": "https://aistudio.google.com/apikey",
"api_key": "",
"metadata": {
"get_models_url": "https://generativelanguage.googleapis.com/v1beta/models",
"header_template": "Authorization: Bearer {{api_key}}",
"transform_req": {
"chat_completions": {
"url": "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions",
"template": "{ {% set first = true %} {% for key, value in input_request %} {% if key == \"messages\" or key == \"temperature\" or key == \"store\" or key == \"max_tokens\" or key == \"stream\" or key == \"presence_penalty\" or key == \"metadata\" or key == \"frequency_penalty\" or key == \"tools\" or key == \"tool_choice\" or key == \"logprobs\" or key == \"top_logprobs\" or key == \"logit_bias\" or key == \"n\" or key == \"modalities\" or key == \"prediction\" or key == \"response_format\" or key == \"service_tier\" or key == \"model\" or key == \"seed\" or key == \"stop\" or key == \"stream_options\" or key == \"top_p\" or key == \"parallel_tool_calls\" or key == \"user\" %} {% if not first %},{% endif %} \"{{ key }}\": {{ tojson(value) }} {% set first = false %} {% endif %} {% endfor %} }"
}
},
"transform_resp": {
"chat_completions": {
"template": "{ {% set first = true %} {% for key, value in input_request %} {% if key == \"choices\" or key == \"created\" or key == \"model\" or key == \"service_tier\" or key == \"system_fingerprint\" or key == \"stream\" or key == \"object\" or key == \"usage\" %} {% if not first %},{% endif %} \"{{ key }}\": {{ tojson(value) }} {% set first = false %} {% endif %} {% endfor %} }"
}
},
"explore_models_url": "https://ai.google.dev/gemini-api/docs/models/gemini"
}
}

View File

@ -1,5 +1,5 @@
{
"id": "@janhq/inference-groq-extension",
"id": "groq",
"type": "remote",
"engine": "groq",
"url": "https://console.groq.com/keys",

View File

@ -1,5 +1,5 @@
{
"id": "@janhq/inference-martian-extension",
"id": "martian",
"type": "remote",
"engine": "martian",
"url": "https://withmartian.com/dashboard",

View File

@ -1,5 +1,5 @@
{
"id": "@janhq/inference-mistral-extension",
"id": "mistral",
"type": "remote",
"engine": "mistral",
"url": "https://console.mistral.ai/api-keys/",

View File

@ -1,5 +1,5 @@
{
"id": "@janhq/inference-nvidia-extension",
"id": "nvidia",
"type": "remote",
"engine": "nvidia",
"url": "https://org.ngc.nvidia.com/setup/personal-keys",

View File

@ -1,5 +1,5 @@
{
"id": "@janhq/inference-openai-extension",
"id": "openai",
"type": "remote",
"engine": "openai",
"url": "https://platform.openai.com/account/api-keys",
@ -10,7 +10,7 @@
"transform_req": {
"chat_completions": {
"url": "https://api.openai.com/v1/chat/completions",
"template": "{ {% set first = true %} {% for key, value in input_request %} {% if key == \"model\" or key == \"temperature\" or key == \"store\" or key == \"messages\" or key == \"stream\" or key == \"presence_penalty\" or key == \"metadata\" or key == \"frequency_penalty\" or key == \"tools\" or key == \"tool_choice\" or key == \"logprobs\" or key == \"top_logprobs\" or key == \"logit_bias\" or key == \"n\" or key == \"modalities\" or key == \"prediction\" or key == \"response_format\" or key == \"service_tier\" or key == \"seed\" or key == \"stream_options\" or key == \"top_p\" or key == \"parallel_tool_calls\" or key == \"user\" or key == \"max_tokens\" or ((input_request.model == \"o1\" or input_request.model == \"o1-preview\" or input_request.model == \"o1-mini\" or input_request.model == \"o3\" or input_request.model == \"o3-mini\") and (key == \"stop\")) %} {% if not first %} , {% endif %} {% if key == \"messages\" and (input_request.model == \"o1\" or input_request.model == \"o1-preview\" or input_request.model == \"o1-mini\") and input_request.messages.0.role == \"system\" %} \"messages\": [{% for message in input_request.messages %} {% if not loop.is_first %} { \"role\": \"{{ message.role }}\", \"content\": \"{{ message.content }}\" } {% if not loop.is_last %} , {% endif %} {% endif %} {% endfor %}] {% else if key == \"max_tokens\" and (input_request.model == \"o1\" or input_request.model == \"o1-preview\" or input_request.model == \"o1-mini\" or input_request.model == \"o3\" or input_request.model == \"o3-mini\") %} \"max_completion_tokens\": {{ tojson(value) }} {% else %} \"{{ key }}\": {{ tojson(value) }} {% set first = false %} {% endif %} {% endif %} {% endfor %} }"
"template": "{ {% set first = true %} {% for key, value in input_request %} {% if key == \"model\" or key == \"temperature\" or key == \"store\" or key == \"messages\" or key == \"stream\" or key == \"presence_penalty\" or key == \"metadata\" or key == \"frequency_penalty\" or key == \"tools\" or key == \"tool_choice\" or key == \"logprobs\" or key == \"top_logprobs\" or key == \"logit_bias\" or key == \"n\" or key == \"modalities\" or key == \"prediction\" or key == \"response_format\" or key == \"service_tier\" or key == \"seed\" or key == \"stream_options\" or key == \"top_p\" or key == \"parallel_tool_calls\" or key == \"user\" or key == \"max_tokens\" or ((input_request.model == \"o1\" or input_request.model == \"o1-preview\" or input_request.model == \"o1-mini\" or input_request.model == \"o3\" or input_request.model == \"o3-mini\") and (key == \"stop\")) %} {% if not first %} , {% endif %} {% if key == \"messages\" and (input_request.model == \"o1\" or input_request.model == \"o1-preview\" or input_request.model == \"o1-mini\") and input_request.messages.0.role == \"system\" %} \"messages\": [{% for message in input_request.messages %} {% if not loop.is_first %} { \"role\": \"{{ message.role }}\", \"content\": \"{{ message.content }}\" } {% if not loop.is_last %} , {% endif %} {% endif %} {% endfor %}] {% else if key == \"max_tokens\" and (input_request.model == \"o1\" or input_request.model == \"o1-preview\" or input_request.model == \"o1-mini\" or input_request.model == \"o3\" or input_request.model == \"o3-mini\") %} \"max_completion_tokens\": {{ tojson(value) }} {% set first = false %} {% else %} \"{{ key }}\": {{ tojson(value) }} {% set first = false %} {% endif %} {% endif %} {% endfor %} }"
}
},
"transform_resp": {

View File

@ -1,5 +1,5 @@
{
"id": "@janhq/inference-openrouter-extension",
"id": "openrouter",
"type": "remote",
"engine": "openrouter",
"url": "https://openrouter.ai/keys",
@ -10,7 +10,7 @@
"transform_req": {
"chat_completions": {
"url": "https://openrouter.ai/api/v1/chat/completions",
"template": "{ {% set first = true %} {% for key, value in input_request %} {% if key == \"messages\" or key == \"temperature\" or key == \"store\" or key == \"max_tokens\" or key == \"stream\" or key == \"presence_penalty\" or key == \"metadata\" or key == \"frequency_penalty\" or key == \"tools\" or key == \"tool_choice\" or key == \"logprobs\" or key == \"top_logprobs\" or key == \"logit_bias\" or key == \"n\" or key == \"modalities\" or key == \"prediction\" or key == \"response_format\" or key == \"service_tier\" or key == \"seed\" or key == \"stop\" or key == \"stream_options\" or key == \"top_p\" or key == \"parallel_tool_calls\" or key == \"user\" %} {% if not first %},{% endif %} \"{{ key }}\": {{ tojson(value) }} {% set first = false %} {% endif %} {% endfor %} }"
"template": "{ {% set first = true %} {% for key, value in input_request %} {% if key == \"messages\" or key == \"temperature\" or key == \"store\" or key == \"max_tokens\" or key == \"stream\" or key == \"presence_penalty\" or key == \"metadata\" or key == \"frequency_penalty\" or key == \"tools\" or key == \"tool_choice\" or key == \"logprobs\" or key == \"top_logprobs\" or key == \"logit_bias\" or key == \"n\" or key == \"modalities\" or key == \"prediction\" or key == \"response_format\" or key == \"service_tier\" or key == \"model\" or key == \"seed\" or key == \"stop\" or key == \"stream_options\" or key == \"top_p\" or key == \"parallel_tool_calls\" or key == \"user\" %} {% if not first %},{% endif %} \"{{ key }}\": {{ tojson(value) }} {% set first = false %} {% endif %} {% endfor %} }"
}
},
"transform_resp": {

View File

@ -89,6 +89,9 @@ const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
{message?.content[0]?.text?.value && (
<AutoLink text={message?.content[0]?.text?.value} />
)}
{!message?.content[0]?.text?.value && (
<span>Something went wrong. Please try again.</span>
)}
</>
)}
</p>

View File

@ -42,7 +42,7 @@ import useUpdateModelParameters from '@/hooks/useUpdateModelParameters'
import { formatDownloadPercentage, toGibibytes } from '@/utils/converter'
import { manualRecommendationModel } from '@/utils/model'
import { getLogoEngine } from '@/utils/modelEngine'
import { getLogoEngine, getTitleByEngine } from '@/utils/modelEngine'
import { activeAssistantAtom } from '@/helpers/atoms/Assistant.atom'
import {
@ -252,18 +252,13 @@ const ModelDropdown = ({
],
})
const defaultContextLength = Math.min(
8192,
model?.settings.ctx_len ?? 8192
)
const contextLength = model?.settings.ctx_len
? Math.min(8192, model?.settings.ctx_len ?? 8192)
: undefined
const overriddenParameters = {
ctx_len: model?.settings.ctx_len ? defaultContextLength : undefined,
max_tokens: defaultContextLength
? Math.min(
model?.parameters.max_tokens ?? 8192,
defaultContextLength
)
ctx_len: contextLength,
max_tokens: contextLength
? Math.min(model?.parameters.max_tokens ?? 8192, contextLength)
: model?.parameters.max_tokens,
}
@ -434,7 +429,7 @@ const ModelDropdown = ({
/>
)}
<h6 className="font-medium capitalize text-[hsla(var(--text-secondary))]">
{engine.name}
{getTitleByEngine(engine.name)}
</h6>
</div>
<div className="-mr-2 flex gap-1">

View File

@ -82,24 +82,18 @@ export const useCreateNewThread = () => {
}
// Default context length is 8192
const defaultContextLength = Math.min(
8192,
defaultModel?.settings?.ctx_len ?? 8192
)
const contextLength = defaultModel?.settings?.ctx_len
? Math.min(8192, defaultModel?.settings?.ctx_len)
: undefined
const overriddenSettings = {
ctx_len: defaultModel?.settings?.ctx_len
? Math.min(8192, defaultModel?.settings?.ctx_len)
: undefined,
ctx_len: contextLength,
}
// Use ctx length by default
const overriddenParameters = {
max_tokens: defaultContextLength
? Math.min(
defaultModel?.parameters?.max_tokens ?? 8192,
defaultContextLength
)
max_tokens: contextLength
? Math.min(defaultModel?.parameters?.max_tokens ?? 8192, contextLength)
: defaultModel?.parameters?.max_tokens,
}

View File

@ -196,7 +196,10 @@ export default function useSendChatMessage() {
}
updateThread(updatedThread)
if (!isResend) {
if (
!isResend &&
(newMessage.content.length || newMessage.attachments?.length)
) {
// Add message
const createdMessage = await extensionManager
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 56.2 41.4" style="enable-background:new 0 0 56.2 41.4;" xml:space="preserve">
<style type="text/css">
.st0{fill:#4D6BFE;}
</style>
<desc>Created with Pixso.</desc>
<path id="path_00000023980838171174838950000018388351879808150157_" class="st0" d="M55.6,3.5C55,3.2,54.8,3.7,54.4,4
c-0.1,0.1-0.2,0.2-0.3,0.3c-0.9,0.9-1.9,1.5-3.2,1.5c-1.9-0.1-3.6,0.5-5.1,2c-0.3-1.8-1.3-2.9-2.9-3.6c-0.8-0.4-1.7-0.7-2.2-1.5
c-0.4-0.6-0.5-1.2-0.7-1.8c-0.1-0.4-0.3-0.8-0.7-0.8c-0.5-0.1-0.7,0.3-0.8,0.6c-0.7,1.3-1,2.8-1,4.3c0.1,3.4,1.5,6,4.3,7.9
c0.3,0.2,0.4,0.4,0.3,0.8c-0.2,0.7-0.4,1.3-0.6,1.9c-0.1,0.4-0.3,0.5-0.8,0.3c-1.5-0.6-2.9-1.6-4.1-2.8c-2-1.9-3.8-4.1-6.1-5.8
C30,7,29.4,6.7,28.9,6.3c-2.3-2.2,0.3-4.1,0.9-4.3C30.4,1.8,30,1,28,1c-2,0-3.9,0.7-6.3,1.6c-0.3,0.1-0.7,0.2-1.1,0.3
c-2.2-0.4-4.4-0.5-6.8-0.2C9.4,3.2,5.9,5.3,3.3,8.8C0.2,13.1-0.5,18,0.4,23.1c0.9,5.3,3.7,9.8,7.9,13.2c4.4,3.6,9.4,5.3,15.1,5
c3.5-0.2,7.3-0.7,11.7-4.4c1.1,0.5,2.3,0.8,4.2,0.9c1.5,0.1,2.9-0.1,4-0.3c1.7-0.4,1.6-2,1-2.3c-5-2.4-3.9-1.4-4.9-2.2
c2.6-3,6.4-6.2,7.9-16.4c0.1-0.8,0-1.3,0-2c0-0.4,0.1-0.6,0.5-0.6c1.3-0.1,2.5-0.5,3.6-1.1c3.3-1.8,4.6-4.7,4.9-8.2
C56.2,4.3,56.2,3.8,55.6,3.5z M27.1,35.1c-4.9-3.8-7.3-5.1-8.2-5.1c-0.9,0.1-0.8,1.1-0.5,1.8c0.2,0.7,0.5,1.1,0.9,1.7
c0.3,0.4,0.4,1-0.3,1.4c-1.6,1-4.3-0.3-4.4-0.4c-3.2-1.9-5.9-4.4-7.7-7.7c-1.8-3.3-2.9-6.8-3-10.5c0-0.9,0.2-1.2,1.1-1.4
c1.2-0.2,2.4-0.3,3.6-0.1c5,0.7,9.2,3,12.8,6.5c2,2,3.6,4.4,5.2,6.8c1.7,2.5,3.5,4.9,5.8,6.8c0.8,0.7,1.5,1.2,2.1,1.6
C32.4,36.8,29.3,36.8,27.1,35.1z M29.5,20c0-0.4,0.3-0.7,0.7-0.7c0.1,0,0.2,0,0.2,0c0.1,0,0.2,0.1,0.3,0.2c0.1,0.1,0.2,0.3,0.2,0.5
c0,0.4-0.3,0.7-0.7,0.7C29.8,20.8,29.5,20.4,29.5,20z M36.7,23.8c-0.5,0.2-0.9,0.4-1.4,0.4c-0.7,0-1.5-0.2-1.9-0.6
c-0.6-0.5-1.1-0.8-1.3-1.8c-0.1-0.4,0-1,0-1.4c0.2-0.8,0-1.3-0.6-1.7c-0.4-0.4-1-0.5-1.6-0.5c-0.2,0-0.4-0.1-0.6-0.2
c-0.3-0.1-0.5-0.4-0.3-0.8c0.1-0.1,0.4-0.4,0.4-0.5c0.8-0.5,1.8-0.3,2.7,0c0.8,0.3,1.4,1,2.3,1.8c0.9,1.1,1.1,1.3,1.6,2.1
c0.4,0.6,0.8,1.3,1,2C37.5,23.2,37.3,23.6,36.7,23.8z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M16 8.016A8.522 8.522 0 008.016 16h-.032A8.521 8.521 0 000 8.016v-.032A8.521 8.521 0 007.984 0h.032A8.522 8.522 0 0016 7.984v.032z" fill="url(#prefix__paint0_radial_980_20147)"/><defs><radialGradient id="prefix__paint0_radial_980_20147" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(16.1326 5.4553 -43.70045 129.2322 1.588 6.503)"><stop offset=".067" stop-color="#9168C0"/><stop offset=".343" stop-color="#5684D1"/><stop offset=".672" stop-color="#1BA1E3"/></radialGradient></defs></svg>

After

Width:  |  Height:  |  Size: 599 B

View File

@ -124,13 +124,13 @@ const ModalAddRemoteEngine = () => {
<div className="space-y-2">
<label htmlFor="chatCmpletionsUrl" className="font-semibold">
{renderLabel(
'API Endpoint URL',
'Chat Completions URL',
false,
`The URL where Jan sends requests to access the AI provider's API.`
)}
</label>
<Input
placeholder="Enter API Endpoint URL"
placeholder="Enter Chat Completions Endpoint URL"
{...register('chatCmpletionsUrl')}
/>
{errors.chatCmpletionsUrl && (

View File

@ -1,6 +1,6 @@
import { Engines, InferenceEngine } from '@janhq/core'
export const getLogoEngine = (engine: InferenceEngine) => {
export const getLogoEngine = (engine: InferenceEngine | string) => {
switch (engine) {
case InferenceEngine.nitro:
case InferenceEngine.cortex_llamacpp:
@ -28,6 +28,11 @@ export const getLogoEngine = (engine: InferenceEngine) => {
return 'images/ModelProvider/cohere.svg'
case InferenceEngine.nvidia:
return 'images/ModelProvider/nvidia.svg'
// MARK: Deprecating InferenceEngine enum - as it's dynamically provided by the backend
case 'google_gemini':
return 'images/ModelProvider/google-gemini.svg'
case 'deepseek':
return 'images/ModelProvider/deepseek.svg'
default:
return undefined
}
@ -44,7 +49,7 @@ export const isLocalEngine = (engines?: Engines, engine?: string) => {
return engines[engine as InferenceEngine]?.[0]?.type === 'local'
}
export const getTitleByEngine = (engine: InferenceEngine) => {
export const getTitleByEngine = (engine: InferenceEngine | string) => {
switch (engine) {
case InferenceEngine.nitro:
case InferenceEngine.cortex_llamacpp:
@ -59,6 +64,8 @@ export const getTitleByEngine = (engine: InferenceEngine) => {
return 'OpenAI'
case InferenceEngine.openrouter:
return 'OpenRouter'
case 'google_gemini':
return 'Google Gemini'
default:
return engine.charAt(0).toUpperCase() + engine.slice(1)
}