Skip to content

Commit

Permalink
feat: local engine management (#4334)
Browse files Browse the repository at this point in the history
* feat: local engine management

* chore: move remote engine into engine page instead extension page

* chore: set default engine from extension

* chore: update endpoint update engine

* chore: update event onEngineUpdate

* chore: filter out engine download

* chore: update version env

* chore: select default engine variant base on user device specs

* chore: symlink engine variants

* chore: rolldown.config in mjs format

* chore: binary codesign

* fix: download state in footer bar and variant status

* chore: update yarn.lock

* fix: rimraf failure

* fix: setup-node@v3 for built-in cache

* fix: cov pipeline

* fix: build syntax

* chore: fix build step

* fix: create engines folder on launch

* chore: update ui delete engine variant with modal confirmation

* chore: fix linter

* chore: add installing progress for Local Engine download

* chore: wording

---------

Co-authored-by: Louis <[email protected]>
  • Loading branch information
urmauur and louis-jan authored Dec 30, 2024
1 parent bd0e525 commit a6a0cb3
Show file tree
Hide file tree
Showing 38 changed files with 1,962 additions and 418 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/jan-electron-linter-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,16 @@ jobs:
- uses: actions/checkout@v3
with:
ref: ${{ github.base_ref }}
- name: Use Node.js v20.9.0
- name: Use Node.js 20.x
uses: actions/setup-node@v3
with:
node-version: v20.9.0
node-version: 20

- name: Install dependencies
run: |
yarn
make build-joi
yarn build:core
yarn build:joi
yarn
- name: Run test coverage
run: yarn test:coverage
Expand Down Expand Up @@ -187,7 +187,7 @@ jobs:
fetch-depth: 0

- name: Installing node
uses: actions/setup-node@v1
uses: actions/setup-node@v3
with:
node-version: 20

Expand Down
1 change: 1 addition & 0 deletions core/src/browser/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export enum ExtensionTypeEnum {
Model = 'model',
SystemMonitoring = 'systemMonitoring',
HuggingFace = 'huggingFace',
Engine = 'engine',
}

export interface ExtensionType {
Expand Down
91 changes: 91 additions & 0 deletions core/src/browser/extensions/enginesManagement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import {
InferenceEngine,
Engines,
EngineVariant,
EngineReleased,
DefaultEngineVariant,
} from '../../types'
import { BaseExtension, ExtensionTypeEnum } from '../extension'

/**
* Engine management extension. Persists and retrieves engine management.
* @abstract
* @extends BaseExtension
*/
export abstract class EngineManagementExtension extends BaseExtension {
type(): ExtensionTypeEnum | undefined {
return ExtensionTypeEnum.Engine
}

/**
* @returns A Promise that resolves to an object of list engines.
*/
abstract getEngines(): Promise<Engines>

/**
* @param name - Inference engine name.
* @returns A Promise that resolves to an array of installed engine.
*/
abstract getInstalledEngines(name: InferenceEngine): Promise<EngineVariant[]>

/**
* @param name - Inference engine name.
* @param version - Version of the engine.
* @param platform - Optional to sort by operating system. macOS, linux, windows.
* @returns A Promise that resolves to an array of latest released engine by version.
*/
abstract getReleasedEnginesByVersion(
name: InferenceEngine,
version: string,
platform?: string
): Promise<EngineReleased[]>

/**
* @param name - Inference engine name.
* @param platform - Optional to sort by operating system. macOS, linux, windows.
* @returns A Promise that resolves to an array of latest released engine.
*/
abstract getLatestReleasedEngine(
name: InferenceEngine,
platform?: string
): Promise<EngineReleased[]>

/**
* @param name - Inference engine name.
* @returns A Promise that resolves to intall of engine.
*/
abstract installEngine(
name: InferenceEngine,
engineConfig: { variant: string; version?: string }
): Promise<{ messages: string }>

/**
* @param name - Inference engine name.
* @returns A Promise that resolves to unintall of engine.
*/
abstract uninstallEngine(
name: InferenceEngine,
engineConfig: { variant: string; version: string }
): Promise<{ messages: string }>

/**
* @param name - Inference engine name.
* @returns A Promise that resolves to an object of default engine.
*/
abstract getDefaultEngineVariant(name: InferenceEngine): Promise<DefaultEngineVariant>

/**
* @body variant - string
* @body version - string
* @returns A Promise that resolves to set default engine.
*/
abstract setDefaultEngineVariant(
name: InferenceEngine,
engineConfig: { variant: string; version: string }
): Promise<{ messages: string }>

/**
* @returns A Promise that resolves to update engine.
*/
abstract updateEngine(name: InferenceEngine): Promise<{ messages: string }>
}
5 changes: 5 additions & 0 deletions core/src/browser/extensions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,8 @@ export { ModelExtension } from './model'
* Base AI Engines.
*/
export * from './engines'

/**
* Engines Management
*/
export * from './enginesManagement'
28 changes: 28 additions & 0 deletions core/src/types/engine/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { InferenceEngine } from '../../types'

export type Engines = {
[key in InferenceEngine]: EngineVariant[]
}

export type EngineVariant = {
engine: InferenceEngine
name: string
version: string
}

export type DefaultEngineVariant = {
engine: InferenceEngine
variant: string
version: string
}

export type EngineReleased = {
created_at: string
download_count: number
name: string
size: number
}

export enum EngineEvent {
OnEngineUpdate = 'OnEngineUpdate',
}
1 change: 1 addition & 0 deletions core/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './huggingface'
export * from './miscellaneous'
export * from './api'
export * from './setting'
export * from './engine'
5 changes: 5 additions & 0 deletions extensions/engine-management-extension/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
}
47 changes: 47 additions & 0 deletions extensions/engine-management-extension/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "@janhq/engine-management-extension",
"productName": "Engine Management",
"version": "1.0.0",
"description": "Extension for managing engines and their configurations",
"main": "dist/index.js",
"node": "dist/node/index.cjs.js",
"author": "Jan <[email protected]>",
"license": "MIT",
"scripts": {
"test": "jest",
"build": "rolldown -c rolldown.config.mjs",
"build:publish": "rimraf *.tgz --glob || true && yarn build && ../../.github/scripts/auto-sign.sh && npm pack && cpx *.tgz ../../pre-install"
},
"exports": {
".": "./dist/index.js",
"./main": "./dist/module.js"
},
"devDependencies": {
"@rollup/plugin-replace": "^6.0.2",
"cpx": "^1.5.0",
"rimraf": "^3.0.2",
"rolldown": "^1.0.0-beta.1",
"ts-loader": "^9.5.0",
"typescript": "^5.3.3",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4"
},
"dependencies": {
"@janhq/core": "../../core/package.tgz",
"cpu-instructions": "^0.0.13",
"ky": "^1.7.2",
"p-queue": "^8.0.1"
},
"bundledDependencies": [
"cpu-instructions",
"@janhq/core"
],
"engines": {
"node": ">=18.0.0"
},
"files": [
"dist/*",
"package.json",
"README.md"
]
}
45 changes: 45 additions & 0 deletions extensions/engine-management-extension/rolldown.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { defineConfig } from 'rolldown'
import replace from '@rollup/plugin-replace'
import pkgJson from './package.json' with { type: 'json' }

export default defineConfig([
{
input: 'src/index.ts',
output: {
format: 'esm',
file: 'dist/index.js',
},
plugins: [
replace({
NODE: JSON.stringify(`${pkgJson.name}/${pkgJson.node}`),
API_URL: JSON.stringify('http://127.0.0.1:39291'),
SOCKET_URL: JSON.stringify('ws://127.0.0.1:39291'),
CORTEX_ENGINE_VERSION: JSON.stringify('v0.1.42'),
}),
],
},
{
input: 'src/node/index.ts',
external: ['@janhq/core/node'],
output: {
format: 'cjs',
file: 'dist/node/index.cjs.js',
},
plugins: [
replace({
CORTEX_ENGINE_VERSION: JSON.stringify('v0.1.42'),
}),
],
},
{
input: 'src/node/cpuInfo.ts',
output: {
format: 'cjs',
file: 'dist/node/cpuInfo.js',
},
external: ['cpu-instructions'],
resolve: {
extensions: ['.ts', '.js', '.svg'],
},
},
])
16 changes: 16 additions & 0 deletions extensions/engine-management-extension/src/@types/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export {}
declare global {
declare const API_URL: string
declare const CORTEX_ENGINE_VERSION: string
declare const SOCKET_URL: string
declare const NODE: string

interface Core {
api: APIFunctions
events: EventEmitter
}
interface Window {
core?: Core | undefined
electronAPI?: any | undefined
}
}
10 changes: 10 additions & 0 deletions extensions/engine-management-extension/src/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Custom Engine Error
*/
export class EngineError extends Error {
message: string
constructor(message: string) {
super()
this.message = message
}
}
Loading

0 comments on commit a6a0cb3

Please sign in to comment.