diff --git a/core/src/browser/extension.ts b/core/src/browser/extension.ts index b27afe023..18a6e4491 100644 --- a/core/src/browser/extension.ts +++ b/core/src/browser/extension.ts @@ -40,7 +40,10 @@ export abstract class BaseExtension implements ExtensionType { protected settingFileName = 'settings.json' /** @type {string} Name of the extension. */ - name?: string + name: string + + /** @type {string} Product Name of the extension. */ + productName?: string /** @type {string} The URL of the extension to load. */ url: string @@ -56,12 +59,14 @@ export abstract class BaseExtension implements ExtensionType { constructor( url: string, - name?: string, + name: string, + productName?: string, active?: boolean, description?: string, version?: string ) { this.name = name + this.productName = productName this.url = url this.active = active this.description = description diff --git a/core/src/node/extension/extension.ts b/core/src/node/extension/extension.ts index 8780b3ffe..849f2d5f2 100644 --- a/core/src/node/extension/extension.ts +++ b/core/src/node/extension/extension.ts @@ -11,6 +11,7 @@ export default class Extension { * @property {string} origin Original specification provided to fetch the package. * @property {Object} installOptions Options provided to pacote when fetching the manifest. * @property {name} name The name of the extension as defined in the manifest. + * @property {name} productName The display name of the extension as defined in the manifest. * @property {string} url Electron URL where the package can be accessed. * @property {string} version Version of the package as defined in the manifest. * @property {string} main The entry point as defined in the main entry of the manifest. @@ -19,6 +20,7 @@ export default class Extension { origin?: string installOptions: any name?: string + productName?: string url?: string version?: string main?: string @@ -42,7 +44,7 @@ export default class Extension { const Arborist = require('@npmcli/arborist') const defaultOpts = { version: false, - fullMetadata: false, + fullMetadata: true, Arborist, } @@ -77,6 +79,7 @@ export default class Extension { return pacote.manifest(this.specifier, this.installOptions).then((mnf) => { // set the Package properties based on the it's manifest this.name = mnf.name + this.productName = mnf.productName as string | undefined this.version = mnf.version this.main = mnf.main this.description = mnf.description diff --git a/extensions/assistant-extension/package.json b/extensions/assistant-extension/package.json index f7fde7f78..a76763244 100644 --- a/extensions/assistant-extension/package.json +++ b/extensions/assistant-extension/package.json @@ -1,5 +1,6 @@ { "name": "@janhq/assistant-extension", + "productName": "Jan Assistant Extension", "version": "1.0.1", "description": "This extension enables assistants, including Jan, a default assistant that can call all downloaded models", "main": "dist/index.js", diff --git a/extensions/conversational-extension/package.json b/extensions/conversational-extension/package.json index a803320f5..712a9883c 100644 --- a/extensions/conversational-extension/package.json +++ b/extensions/conversational-extension/package.json @@ -1,5 +1,6 @@ { "name": "@janhq/conversational-extension", + "productName": "Conversational Extension", "version": "1.0.0", "description": "This extension enables conversations and state persistence via your filesystem", "main": "dist/index.js", diff --git a/extensions/huggingface-extension/package.json b/extensions/huggingface-extension/package.json index e71dc7406..234b806d8 100644 --- a/extensions/huggingface-extension/package.json +++ b/extensions/huggingface-extension/package.json @@ -1,5 +1,6 @@ { "name": "@janhq/huggingface-extension", + "productName": "HuggingFace Extension", "version": "1.0.0", "description": "Hugging Face extension for converting HF models to GGUF", "main": "dist/index.js", diff --git a/extensions/inference-groq-extension/package.json b/extensions/inference-groq-extension/package.json index 78efd3552..8d70d1d9f 100644 --- a/extensions/inference-groq-extension/package.json +++ b/extensions/inference-groq-extension/package.json @@ -1,5 +1,6 @@ { "name": "@janhq/inference-groq-extension", + "productName": "Groq Inference Engine Extension", "version": "1.0.0", "description": "This extension enables fast Groq chat completion API calls", "main": "dist/index.js", diff --git a/extensions/inference-mistral-extension/package.json b/extensions/inference-mistral-extension/package.json index 33834738e..c1de1f959 100644 --- a/extensions/inference-mistral-extension/package.json +++ b/extensions/inference-mistral-extension/package.json @@ -1,5 +1,6 @@ { "name": "@janhq/inference-mistral-extension", + "productName": "Mistral AI Inference Engine Extension", "version": "1.0.0", "description": "This extension enables Mistral chat completion API calls", "main": "dist/index.js", diff --git a/extensions/inference-nitro-extension/package.json b/extensions/inference-nitro-extension/package.json index 4ea1446ac..78558b1c3 100644 --- a/extensions/inference-nitro-extension/package.json +++ b/extensions/inference-nitro-extension/package.json @@ -1,5 +1,6 @@ { "name": "@janhq/inference-nitro-extension", + "productName": "Nitro Inference Engine Extension", "version": "1.0.0", "description": "This extension embeds Nitro, a lightweight (3mb) inference engine written in C++. See https://nitro.jan.ai.\nUse this setting if you encounter errors related to **CUDA toolkit** during application execution.", "main": "dist/index.js", diff --git a/extensions/inference-openai-extension/package.json b/extensions/inference-openai-extension/package.json index 7b112a8fb..3435a5346 100644 --- a/extensions/inference-openai-extension/package.json +++ b/extensions/inference-openai-extension/package.json @@ -1,5 +1,6 @@ { "name": "@janhq/inference-openai-extension", + "productName": "OpenAI Inference Engine Extension", "version": "1.0.0", "description": "This extension enables OpenAI chat completion API calls", "main": "dist/index.js", diff --git a/extensions/inference-triton-trtllm-extension/package.json b/extensions/inference-triton-trtllm-extension/package.json index bb97f15c5..9ce8f11a9 100644 --- a/extensions/inference-triton-trtllm-extension/package.json +++ b/extensions/inference-triton-trtllm-extension/package.json @@ -1,5 +1,6 @@ { "name": "@janhq/inference-triton-trt-llm-extension", + "productName": "Triton-TRT-LLM Inference Engine Extension", "version": "1.0.0", "description": "This extension enables Nvidia's TensorRT-LLM as an inference engine option", "main": "dist/index.js", diff --git a/extensions/model-extension/package.json b/extensions/model-extension/package.json index 5f53ff513..c6b659322 100644 --- a/extensions/model-extension/package.json +++ b/extensions/model-extension/package.json @@ -1,5 +1,6 @@ { "name": "@janhq/model-extension", + "productName": "Model Management Extension", "version": "1.0.30", "description": "Model Management Extension provides model exploration and seamless downloads", "main": "dist/index.js", diff --git a/extensions/monitoring-extension/package.json b/extensions/monitoring-extension/package.json index 3cbb14dab..c320db2ba 100644 --- a/extensions/monitoring-extension/package.json +++ b/extensions/monitoring-extension/package.json @@ -1,5 +1,6 @@ { "name": "@janhq/monitoring-extension", + "productName": "System Monitoring Extension", "version": "1.0.10", "description": "This extension provides system health and OS level data", "main": "dist/index.js", diff --git a/extensions/tensorrt-llm-extension/package.json b/extensions/tensorrt-llm-extension/package.json index d1cb93f58..9e21e2571 100644 --- a/extensions/tensorrt-llm-extension/package.json +++ b/extensions/tensorrt-llm-extension/package.json @@ -1,5 +1,6 @@ { "name": "@janhq/tensorrt-llm-extension", + "productName": "TensorRT-LLM Inference Engine Extension", "version": "0.0.3", "description": "This extension enables Nvidia's TensorRT-LLM for the fastest GPU acceleration. See the [setup guide](https://jan.ai/guides/providers/tensorrt-llm/) for next steps.", "main": "dist/index.js", diff --git a/web/extension/Extension.ts b/web/extension/Extension.ts index f91d16a08..9438238ca 100644 --- a/web/extension/Extension.ts +++ b/web/extension/Extension.ts @@ -3,7 +3,10 @@ */ class Extension { /** @type {string} Name of the extension. */ - name?: string + name: string + + /** @type {string} Product name of the extension. */ + productName?: string /** @type {string} The URL of the extension to load. */ url: string @@ -19,12 +22,14 @@ class Extension { constructor( url: string, - name?: string, + name: string, + productName?: string, active?: boolean, description?: string, version?: string ) { this.name = name + this.productName = productName this.url = url this.active = active this.description = description diff --git a/web/extension/ExtensionManager.ts b/web/extension/ExtensionManager.ts index 42bca79bf..aa1a7674b 100644 --- a/web/extension/ExtensionManager.ts +++ b/web/extension/ExtensionManager.ts @@ -106,6 +106,7 @@ export class ExtensionManager { new Extension( ext.url, ext.name, + ext.productName, ext.active, ext.description, ext.version @@ -135,10 +136,11 @@ export class ExtensionManager { extensionClass.default.prototype ) { this.register( - extension.name ?? extension.url, + extension.name, new extensionClass.default( extension.url, extension.name, + extension.productName, extension.active, extension.description, extension.version diff --git a/web/screens/Settings/Advanced/index.tsx b/web/screens/Settings/Advanced/index.tsx index a9773cd76..4376c2deb 100644 --- a/web/screens/Settings/Advanced/index.tsx +++ b/web/screens/Settings/Advanced/index.tsx @@ -202,7 +202,7 @@ const Advanced = () => {

- Enable experimental features that may be unstable tested. + Enable experimental features that may be untested and unstable.

= ({ item }) => { useEffect(() => { const getExtensionInstallationState = async () => { - const extension = extensionManager.getByName(item.name ?? '') + const extension = extensionManager.getByName(item.name) if (!extension) return if (typeof extension?.installationState === 'function') { @@ -59,13 +59,13 @@ const ExtensionItem: React.FC = ({ item }) => { }, [item.name, isInstalling]) useEffect(() => { - const extension = extensionManager.getByName(item.name ?? '') + const extension = extensionManager.getByName(item.name) if (!extension) return setCompatibility(extension.compatibility()) }, [setCompatibility, item.name]) const onInstallClick = useCallback(async () => { - const extension = extensionManager.getByName(item.name ?? '') + const extension = extensionManager.getByName(item.name) if (!extension) return await extension.install() diff --git a/web/screens/Settings/CoreExtensions/index.tsx b/web/screens/Settings/CoreExtensions/index.tsx index f0d0892a6..5a5361c21 100644 --- a/web/screens/Settings/CoreExtensions/index.tsx +++ b/web/screens/Settings/CoreExtensions/index.tsx @@ -85,14 +85,10 @@ const ExtensionCatalog = () => { >
-
- {formatExtensionsName( - item.name ?? item.description ?? '' - )} +
+ {item.productName ?? formatExtensionsName(item.name)} v + {item.version}
-

- v{item.version} -

{item.description} @@ -110,7 +106,7 @@ const ExtensionCatalog = () => {

- Select a extension file to install (.tgz) + Select an extension file to install (.tgz)

diff --git a/web/screens/Settings/SettingMenu/SettingItem/index.tsx b/web/screens/Settings/SettingMenu/SettingItem/index.tsx index 3a941b9cc..4949f3390 100644 --- a/web/screens/Settings/SettingMenu/SettingItem/index.tsx +++ b/web/screens/Settings/SettingMenu/SettingItem/index.tsx @@ -5,16 +5,14 @@ import { useAtom } from 'jotai' import { twMerge } from 'tailwind-merge' -import { formatExtensionsName } from '@/utils/converter' - import { selectedSettingAtom } from '@/helpers/atoms/Setting.atom' type Props = { + name: string setting: string - extension?: boolean } -const SettingItem: React.FC = ({ setting, extension = false }) => { +const SettingItem: React.FC = ({ name, setting }) => { const [selectedSetting, setSelectedSetting] = useAtom(selectedSettingAtom) const isActive = selectedSetting === setting @@ -28,7 +26,7 @@ const SettingItem: React.FC = ({ setting, extension = false }) => { onClick={onSettingItemClick} > - {extension ? formatExtensionsName(setting) : setting} + {name} {isActive && ( diff --git a/web/screens/Settings/SettingMenu/index.tsx b/web/screens/Settings/SettingMenu/index.tsx index 36f686498..879af1953 100644 --- a/web/screens/Settings/SettingMenu/index.tsx +++ b/web/screens/Settings/SettingMenu/index.tsx @@ -11,11 +11,13 @@ import { janSettingScreenAtom } from '@/helpers/atoms/Setting.atom' const SettingMenu: React.FC = () => { const settingScreens = useAtomValue(janSettingScreenAtom) - const [extensionHasSettings, setExtensionHasSettings] = useState([]) + const [extensionHasSettings, setExtensionHasSettings] = useState< + { name?: string; setting: string }[] + >([]) useEffect(() => { const getAllSettings = async () => { - const extensionsMenu: string[] = [] + const extensionsMenu: { name?: string; setting: string }[] = [] const extensions = extensionManager.getAll() for (const extension of extensions) { if (typeof extension.getSettings === 'function') { @@ -24,7 +26,10 @@ const SettingMenu: React.FC = () => { (settings && settings.length > 0) || (await extension.installationState()) !== 'NotRequired' ) { - extensionsMenu.push(extension.name ?? extension.url) + extensionsMenu.push({ + name: extension.productName, + setting: extension.name, + }) } } } @@ -38,7 +43,11 @@ const SettingMenu: React.FC = () => {
{settingScreens.map((settingScreen) => ( - + ))} {extensionHasSettings.length > 0 && ( @@ -49,11 +58,11 @@ const SettingMenu: React.FC = () => {
)} - {extensionHasSettings.map((extensionName: string) => ( + {extensionHasSettings.map((item) => ( ))}