Skip to content

Commit a6a0cb3

Browse files
urmauurlouis-jan
andauthored
feat: local engine management (#4334)
* 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]>
1 parent bd0e525 commit a6a0cb3

File tree

38 files changed

+1962
-418
lines changed

38 files changed

+1962
-418
lines changed

.github/workflows/jan-electron-linter-and-test.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,16 @@ jobs:
4444
- uses: actions/checkout@v3
4545
with:
4646
ref: ${{ github.base_ref }}
47-
- name: Use Node.js v20.9.0
47+
- name: Use Node.js 20.x
4848
uses: actions/setup-node@v3
4949
with:
50-
node-version: v20.9.0
50+
node-version: 20
5151

5252
- name: Install dependencies
5353
run: |
54-
yarn
54+
make build-joi
5555
yarn build:core
56-
yarn build:joi
56+
yarn
5757
5858
- name: Run test coverage
5959
run: yarn test:coverage
@@ -187,7 +187,7 @@ jobs:
187187
fetch-depth: 0
188188

189189
- name: Installing node
190-
uses: actions/setup-node@v1
190+
uses: actions/setup-node@v3
191191
with:
192192
node-version: 20
193193

core/src/browser/extension.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export enum ExtensionTypeEnum {
1111
Model = 'model',
1212
SystemMonitoring = 'systemMonitoring',
1313
HuggingFace = 'huggingFace',
14+
Engine = 'engine',
1415
}
1516

1617
export interface ExtensionType {
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import {
2+
InferenceEngine,
3+
Engines,
4+
EngineVariant,
5+
EngineReleased,
6+
DefaultEngineVariant,
7+
} from '../../types'
8+
import { BaseExtension, ExtensionTypeEnum } from '../extension'
9+
10+
/**
11+
* Engine management extension. Persists and retrieves engine management.
12+
* @abstract
13+
* @extends BaseExtension
14+
*/
15+
export abstract class EngineManagementExtension extends BaseExtension {
16+
type(): ExtensionTypeEnum | undefined {
17+
return ExtensionTypeEnum.Engine
18+
}
19+
20+
/**
21+
* @returns A Promise that resolves to an object of list engines.
22+
*/
23+
abstract getEngines(): Promise<Engines>
24+
25+
/**
26+
* @param name - Inference engine name.
27+
* @returns A Promise that resolves to an array of installed engine.
28+
*/
29+
abstract getInstalledEngines(name: InferenceEngine): Promise<EngineVariant[]>
30+
31+
/**
32+
* @param name - Inference engine name.
33+
* @param version - Version of the engine.
34+
* @param platform - Optional to sort by operating system. macOS, linux, windows.
35+
* @returns A Promise that resolves to an array of latest released engine by version.
36+
*/
37+
abstract getReleasedEnginesByVersion(
38+
name: InferenceEngine,
39+
version: string,
40+
platform?: string
41+
): Promise<EngineReleased[]>
42+
43+
/**
44+
* @param name - Inference engine name.
45+
* @param platform - Optional to sort by operating system. macOS, linux, windows.
46+
* @returns A Promise that resolves to an array of latest released engine.
47+
*/
48+
abstract getLatestReleasedEngine(
49+
name: InferenceEngine,
50+
platform?: string
51+
): Promise<EngineReleased[]>
52+
53+
/**
54+
* @param name - Inference engine name.
55+
* @returns A Promise that resolves to intall of engine.
56+
*/
57+
abstract installEngine(
58+
name: InferenceEngine,
59+
engineConfig: { variant: string; version?: string }
60+
): Promise<{ messages: string }>
61+
62+
/**
63+
* @param name - Inference engine name.
64+
* @returns A Promise that resolves to unintall of engine.
65+
*/
66+
abstract uninstallEngine(
67+
name: InferenceEngine,
68+
engineConfig: { variant: string; version: string }
69+
): Promise<{ messages: string }>
70+
71+
/**
72+
* @param name - Inference engine name.
73+
* @returns A Promise that resolves to an object of default engine.
74+
*/
75+
abstract getDefaultEngineVariant(name: InferenceEngine): Promise<DefaultEngineVariant>
76+
77+
/**
78+
* @body variant - string
79+
* @body version - string
80+
* @returns A Promise that resolves to set default engine.
81+
*/
82+
abstract setDefaultEngineVariant(
83+
name: InferenceEngine,
84+
engineConfig: { variant: string; version: string }
85+
): Promise<{ messages: string }>
86+
87+
/**
88+
* @returns A Promise that resolves to update engine.
89+
*/
90+
abstract updateEngine(name: InferenceEngine): Promise<{ messages: string }>
91+
}

core/src/browser/extensions/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,8 @@ export { ModelExtension } from './model'
2828
* Base AI Engines.
2929
*/
3030
export * from './engines'
31+
32+
/**
33+
* Engines Management
34+
*/
35+
export * from './enginesManagement'

core/src/types/engine/index.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { InferenceEngine } from '../../types'
2+
3+
export type Engines = {
4+
[key in InferenceEngine]: EngineVariant[]
5+
}
6+
7+
export type EngineVariant = {
8+
engine: InferenceEngine
9+
name: string
10+
version: string
11+
}
12+
13+
export type DefaultEngineVariant = {
14+
engine: InferenceEngine
15+
variant: string
16+
version: string
17+
}
18+
19+
export type EngineReleased = {
20+
created_at: string
21+
download_count: number
22+
name: string
23+
size: number
24+
}
25+
26+
export enum EngineEvent {
27+
OnEngineUpdate = 'OnEngineUpdate',
28+
}

core/src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ export * from './huggingface'
1010
export * from './miscellaneous'
1111
export * from './api'
1212
export * from './setting'
13+
export * from './engine'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/** @type {import('ts-jest').JestConfigWithTsJest} */
2+
module.exports = {
3+
preset: 'ts-jest',
4+
testEnvironment: 'node',
5+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"name": "@janhq/engine-management-extension",
3+
"productName": "Engine Management",
4+
"version": "1.0.0",
5+
"description": "Extension for managing engines and their configurations",
6+
"main": "dist/index.js",
7+
"node": "dist/node/index.cjs.js",
8+
"author": "Jan <[email protected]>",
9+
"license": "MIT",
10+
"scripts": {
11+
"test": "jest",
12+
"build": "rolldown -c rolldown.config.mjs",
13+
"build:publish": "rimraf *.tgz --glob || true && yarn build && ../../.github/scripts/auto-sign.sh && npm pack && cpx *.tgz ../../pre-install"
14+
},
15+
"exports": {
16+
".": "./dist/index.js",
17+
"./main": "./dist/module.js"
18+
},
19+
"devDependencies": {
20+
"@rollup/plugin-replace": "^6.0.2",
21+
"cpx": "^1.5.0",
22+
"rimraf": "^3.0.2",
23+
"rolldown": "^1.0.0-beta.1",
24+
"ts-loader": "^9.5.0",
25+
"typescript": "^5.3.3",
26+
"webpack": "^5.88.2",
27+
"webpack-cli": "^5.1.4"
28+
},
29+
"dependencies": {
30+
"@janhq/core": "../../core/package.tgz",
31+
"cpu-instructions": "^0.0.13",
32+
"ky": "^1.7.2",
33+
"p-queue": "^8.0.1"
34+
},
35+
"bundledDependencies": [
36+
"cpu-instructions",
37+
"@janhq/core"
38+
],
39+
"engines": {
40+
"node": ">=18.0.0"
41+
},
42+
"files": [
43+
"dist/*",
44+
"package.json",
45+
"README.md"
46+
]
47+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { defineConfig } from 'rolldown'
2+
import replace from '@rollup/plugin-replace'
3+
import pkgJson from './package.json' with { type: 'json' }
4+
5+
export default defineConfig([
6+
{
7+
input: 'src/index.ts',
8+
output: {
9+
format: 'esm',
10+
file: 'dist/index.js',
11+
},
12+
plugins: [
13+
replace({
14+
NODE: JSON.stringify(`${pkgJson.name}/${pkgJson.node}`),
15+
API_URL: JSON.stringify('http://127.0.0.1:39291'),
16+
SOCKET_URL: JSON.stringify('ws://127.0.0.1:39291'),
17+
CORTEX_ENGINE_VERSION: JSON.stringify('v0.1.42'),
18+
}),
19+
],
20+
},
21+
{
22+
input: 'src/node/index.ts',
23+
external: ['@janhq/core/node'],
24+
output: {
25+
format: 'cjs',
26+
file: 'dist/node/index.cjs.js',
27+
},
28+
plugins: [
29+
replace({
30+
CORTEX_ENGINE_VERSION: JSON.stringify('v0.1.42'),
31+
}),
32+
],
33+
},
34+
{
35+
input: 'src/node/cpuInfo.ts',
36+
output: {
37+
format: 'cjs',
38+
file: 'dist/node/cpuInfo.js',
39+
},
40+
external: ['cpu-instructions'],
41+
resolve: {
42+
extensions: ['.ts', '.js', '.svg'],
43+
},
44+
},
45+
])
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export {}
2+
declare global {
3+
declare const API_URL: string
4+
declare const CORTEX_ENGINE_VERSION: string
5+
declare const SOCKET_URL: string
6+
declare const NODE: string
7+
8+
interface Core {
9+
api: APIFunctions
10+
events: EventEmitter
11+
}
12+
interface Window {
13+
core?: Core | undefined
14+
electronAPI?: any | undefined
15+
}
16+
}

0 commit comments

Comments
 (0)