chore: Extension should have product name in manifest (#2675)
* chore: Extension should have product name in manifest * chore: typo
This commit is contained in:
parent
d93d74c86b
commit
b19234ed71
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -202,7 +202,7 @@ const Advanced = () => {
|
||||
</h6>
|
||||
</div>
|
||||
<p className="leading-relaxed">
|
||||
Enable experimental features that may be unstable tested.
|
||||
Enable experimental features that may be untested and unstable.
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
|
||||
@ -46,7 +46,7 @@ const ExtensionItem: React.FC<Props> = ({ 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<Props> = ({ 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()
|
||||
|
||||
@ -85,14 +85,10 @@ const ExtensionCatalog = () => {
|
||||
>
|
||||
<div className="w-4/5 flex-shrink-0 space-y-1.5">
|
||||
<div className="flex items-center gap-x-2">
|
||||
<h6 className="text-sm font-semibold capitalize">
|
||||
{formatExtensionsName(
|
||||
item.name ?? item.description ?? ''
|
||||
)}
|
||||
<h6 className="text-sm font-semibold">
|
||||
{item.productName ?? formatExtensionsName(item.name)} v
|
||||
{item.version}
|
||||
</h6>
|
||||
<p className="whitespace-pre-wrap text-sm font-semibold leading-relaxed ">
|
||||
v{item.version}
|
||||
</p>
|
||||
</div>
|
||||
<p className="whitespace-pre-wrap leading-relaxed ">
|
||||
{item.description}
|
||||
@ -110,7 +106,7 @@ const ExtensionCatalog = () => {
|
||||
</h6>
|
||||
</div>
|
||||
<p className="whitespace-pre-wrap leading-relaxed ">
|
||||
Select a extension file to install (.tgz)
|
||||
Select an extension file to install (.tgz)
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@ -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<Props> = ({ setting, extension = false }) => {
|
||||
const SettingItem: React.FC<Props> = ({ name, setting }) => {
|
||||
const [selectedSetting, setSelectedSetting] = useAtom(selectedSettingAtom)
|
||||
const isActive = selectedSetting === setting
|
||||
|
||||
@ -28,7 +26,7 @@ const SettingItem: React.FC<Props> = ({ setting, extension = false }) => {
|
||||
onClick={onSettingItemClick}
|
||||
>
|
||||
<span className={twMerge(isActive && 'relative z-10', 'capitalize')}>
|
||||
{extension ? formatExtensionsName(setting) : setting}
|
||||
{name}
|
||||
</span>
|
||||
|
||||
{isActive && (
|
||||
|
||||
@ -11,11 +11,13 @@ import { janSettingScreenAtom } from '@/helpers/atoms/Setting.atom'
|
||||
|
||||
const SettingMenu: React.FC = () => {
|
||||
const settingScreens = useAtomValue(janSettingScreenAtom)
|
||||
const [extensionHasSettings, setExtensionHasSettings] = useState<string[]>([])
|
||||
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 = () => {
|
||||
<ScrollArea className="h-full w-full">
|
||||
<div className="flex-shrink-0 px-6 py-4 font-medium">
|
||||
{settingScreens.map((settingScreen) => (
|
||||
<SettingItem key={settingScreen} setting={settingScreen} />
|
||||
<SettingItem
|
||||
key={settingScreen}
|
||||
name={settingScreen}
|
||||
setting={settingScreen}
|
||||
/>
|
||||
))}
|
||||
|
||||
{extensionHasSettings.length > 0 && (
|
||||
@ -49,11 +58,11 @@ const SettingMenu: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{extensionHasSettings.map((extensionName: string) => (
|
||||
{extensionHasSettings.map((item) => (
|
||||
<SettingItem
|
||||
key={extensionName}
|
||||
setting={extensionName}
|
||||
extension={true}
|
||||
key={item.name}
|
||||
name={item.name ?? item.setting}
|
||||
setting={item.setting}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user