Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: better hardware setting #4471

Open
wants to merge 11 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/src/browser/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
SystemMonitoring = 'systemMonitoring',
HuggingFace = 'huggingFace',
Engine = 'engine',
Hardware = 'hardware',
}

export interface ExtensionType {
Expand Down Expand Up @@ -103,7 +104,7 @@
* @property {Array} platform
*/
compatibility(): Compatibility | undefined {
return undefined

Check warning on line 107 in core/src/browser/extension.ts

View workflow job for this annotation

GitHub Actions / coverage-check

107 line is not covered with tests
}

/**
Expand All @@ -111,8 +112,8 @@
* @param models
*/
async registerModels(models: Model[]): Promise<void> {
for (const model of models) {
ModelManager.instance().register(model)

Check warning on line 116 in core/src/browser/extension.ts

View workflow job for this annotation

GitHub Actions / coverage-check

115-116 lines are not covered with tests
}
}

Expand All @@ -123,8 +124,8 @@
*/
async registerSettings(settings: SettingComponentProps[]): Promise<void> {
if (!this.name) {
console.error('Extension name is not defined')
return

Check warning on line 128 in core/src/browser/extension.ts

View workflow job for this annotation

GitHub Actions / coverage-check

127-128 lines are not covered with tests
}

const extensionSettingFolderPath = await joinPath([
Expand All @@ -142,18 +143,18 @@

// Persists new settings
if (await fs.existsSync(settingFilePath)) {
const oldSettings = JSON.parse(await fs.readFileSync(settingFilePath, 'utf-8'))
settings.forEach((setting) => {

Check warning on line 147 in core/src/browser/extension.ts

View workflow job for this annotation

GitHub Actions / coverage-check

146-147 lines are not covered with tests
// Keep setting value
if (setting.controllerProps && Array.isArray(oldSettings))
setting.controllerProps.value = oldSettings.find(
(e: any) => e.key === setting.key

Check warning on line 151 in core/src/browser/extension.ts

View workflow job for this annotation

GitHub Actions / coverage-check

149-151 lines are not covered with tests
)?.controllerProps?.value
})
}
await fs.writeFileSync(settingFilePath, JSON.stringify(settings, null, 2))
} catch (err) {
console.error(err)

Check warning on line 157 in core/src/browser/extension.ts

View workflow job for this annotation

GitHub Actions / coverage-check

157 line is not covered with tests
}
}

Expand Down Expand Up @@ -197,23 +198,23 @@
* @returns
*/
async getSettings(): Promise<SettingComponentProps[]> {
if (!this.name) return []

Check warning on line 201 in core/src/browser/extension.ts

View workflow job for this annotation

GitHub Actions / coverage-check

201 line is not covered with tests

const settingPath = await joinPath([

Check warning on line 203 in core/src/browser/extension.ts

View workflow job for this annotation

GitHub Actions / coverage-check

203 line is not covered with tests
await getJanDataFolderPath(),
this.settingFolderName,
this.name,
this.settingFileName,
])

try {
if (!(await fs.existsSync(settingPath))) return []
const content = await fs.readFileSync(settingPath, 'utf-8')
const settings: SettingComponentProps[] = JSON.parse(content)
return settings

Check warning on line 214 in core/src/browser/extension.ts

View workflow job for this annotation

GitHub Actions / coverage-check

210-214 lines are not covered with tests
} catch (err) {
console.warn(err)
return []

Check warning on line 217 in core/src/browser/extension.ts

View workflow job for this annotation

GitHub Actions / coverage-check

216-217 lines are not covered with tests
}
}

Expand Down
26 changes: 26 additions & 0 deletions core/src/browser/extensions/hardwareManagement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { HardwareInformation } from '../../types'
import { BaseExtension, ExtensionTypeEnum } from '../extension'

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

/**
* @returns A Promise that resolves to an object of list hardware.
*/
abstract getHardware(): Promise<HardwareInformation>

/**
* @returns A Promise that resolves to an object of set active gpus.
*/
abstract setAvtiveGpu(data: { gpus: number[] }): Promise<{
message: string
activated_gpus: number[]
}>
}
5 changes: 5 additions & 0 deletions core/src/browser/extensions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ export * from './engines'
* Engines Management
*/
export * from './enginesManagement'

/**
* Hardware Management
*/
export * from './hardwareManagement'
54 changes: 54 additions & 0 deletions core/src/types/hardware/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
export type Cpu = {
arch: string
cores: number
instructions: string[]
model: string
}

export type GpuAdditionalInformation = {
compute_cap: string
driver_version: string
}

export type Gpu = {
activated: boolean
additional_information: GpuAdditionalInformation
free_vram: number
id: string
name: string
total_vram: number
uuid: string
version: string
}

export type Os = {
name: string
version: string
}

export type Power = {
battery_life: number
charging_status: string
is_power_saving: boolean
}

export type Ram = {
available: number
total: number
type: string
}

export type Storage = {
available: number
total: number
type: string
}

export type HardwareInformation = {
cpu: Cpu
gpus: Gpu[]
os: Os
power: Power
ram: Ram
storage: Storage
}
1 change: 1 addition & 0 deletions core/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './miscellaneous'
export * from './api'
export * from './setting'
export * from './engine'
export * from './hardware'
5 changes: 5 additions & 0 deletions extensions/hardware-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',
}
48 changes: 48 additions & 0 deletions extensions/hardware-management-extension/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "@janhq/hardware-management-extension",
"productName": "Hardware Management",
"version": "1.0.0",
"description": "Manages Better Hardware settings.",
"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",
"codesign:darwin": "../../.github/scripts/auto-sign.sh",
"codesign:win32:linux": "echo 'No codesigning required'",
"codesign": "run-script-os",
"build:publish": "rimraf *.tgz --glob || true && yarn build && yarn codesign && npm pack && cpx *.tgz ../../pre-install"
},
"exports": {
".": "./dist/index.js",
"./main": "./dist/module.js"
},
"devDependencies": {
"cpx": "^1.5.0",
"rimraf": "^3.0.2",
"rolldown": "^1.0.0-beta.1",
"run-script-os": "^1.1.6",
"ts-loader": "^9.5.0",
"typescript": "^5.3.3"
},
"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"
],
"hardwares": {
"node": ">=18.0.0"
},
"files": [
"dist/*",
"package.json",
"README.md"
]
}
17 changes: 17 additions & 0 deletions extensions/hardware-management-extension/rolldown.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { defineConfig } from 'rolldown'
import pkgJson from './package.json' with { type: 'json' }

export default defineConfig([
{
input: 'src/index.ts',
output: {
format: 'esm',
file: 'dist/index.js',
},
define: {
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'),
},
},
])
12 changes: 12 additions & 0 deletions extensions/hardware-management-extension/src/@types/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
declare const API_URL: string
declare const SOCKET_URL: string
declare const NODE: string

interface Core {
api: APIFunctions
events: EventEmitter
}
interface Window {
core?: Core | undefined
electronAPI?: any | undefined
}
67 changes: 67 additions & 0 deletions extensions/hardware-management-extension/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
executeOnMain,
HardwareManagementExtension,
HardwareInformation,
} from '@janhq/core'
import ky from 'ky'
import PQueue from 'p-queue'

/**
* JSONHardwareManagementExtension is a HardwareManagementExtension implementation that provides
* functionality for managing engines.
*/
export default class JSONHardwareManagementExtension extends HardwareManagementExtension {
queue = new PQueue({ concurrency: 1 })

/**
* Called when the extension is loaded.
*/
async onLoad() {
// Run Healthcheck
this.queue.add(() => this.healthz())
}

/**
* Called when the extension is unloaded.
*/
onUnload() {}

/**
* Do health check on cortex.cpp
* @returns
*/
async healthz(): Promise<void> {
return ky
.get(`${API_URL}/healthz`, {
retry: { limit: 20, delay: () => 500, methods: ['get'] },
})
.then(() => {})
}

/**
* @returns A Promise that resolves to an object of hardware.
*/
async getHardware(): Promise<HardwareInformation> {
return this.queue.add(() =>
ky
.get(`${API_URL}/v1/hardware`)
.json<HardwareInformation>()
.then((e) => e)
) as Promise<HardwareInformation>
}

/**
* @returns A Promise that resolves to an object of set gpu activate.
*/
async setAvtiveGpu(data: { gpus: number[] }): Promise<{
message: string
activated_gpus: number[]
}> {
return this.queue.add(() =>
ky.post(`${API_URL}/v1/hardware/activate`, { json: data }).then((e) => e)
) as Promise<{
message: string
activated_gpus: number[]
}>
}
}
16 changes: 16 additions & 0 deletions extensions/hardware-management-extension/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "es2016",
"module": "ES6",
"moduleResolution": "node",
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": false,
"skipLibCheck": true,
"rootDir": "./src",
"resolveJsonModule": true
},
"include": ["./src"],
"exclude": ["src/**/*.test.ts", "rolldown.config.mjs"]
}
51 changes: 39 additions & 12 deletions extensions/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -509,61 +509,71 @@ __metadata:

"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension":
version: 0.1.10
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=7dd866&locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension"
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=fa62e1&locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension"
dependencies:
rxjs: "npm:^7.8.1"
ulidx: "npm:^2.3.0"
checksum: 10c0/da0eed6e552ce2ff6f52a087e6e221101c3d0c03d92820840ee80c3ca1a17317a66525cb5bf59b6c1e8bd2e36e54763008f97e13000ae339dac49f5682fcfa65
checksum: 10c0/dad09c52d9545aae4deb82d2fc40b1ae810b8bcf950877cee9578b26948c8aac0aca4cfdee49aaf6df3f88ee176033bbafcd365b81489a1085ace4e693dda898
languageName: node
linkType: hard

"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension":
version: 0.1.10
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=7dd866&locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension"
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=fa62e1&locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension"
dependencies:
rxjs: "npm:^7.8.1"
ulidx: "npm:^2.3.0"
checksum: 10c0/da0eed6e552ce2ff6f52a087e6e221101c3d0c03d92820840ee80c3ca1a17317a66525cb5bf59b6c1e8bd2e36e54763008f97e13000ae339dac49f5682fcfa65
checksum: 10c0/dad09c52d9545aae4deb82d2fc40b1ae810b8bcf950877cee9578b26948c8aac0aca4cfdee49aaf6df3f88ee176033bbafcd365b81489a1085ace4e693dda898
languageName: node
linkType: hard

"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fengine-management-extension%40workspace%3Aengine-management-extension":
version: 0.1.10
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=7dd866&locator=%40janhq%2Fengine-management-extension%40workspace%3Aengine-management-extension"
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=fa62e1&locator=%40janhq%2Fengine-management-extension%40workspace%3Aengine-management-extension"
dependencies:
rxjs: "npm:^7.8.1"
ulidx: "npm:^2.3.0"
checksum: 10c0/da0eed6e552ce2ff6f52a087e6e221101c3d0c03d92820840ee80c3ca1a17317a66525cb5bf59b6c1e8bd2e36e54763008f97e13000ae339dac49f5682fcfa65
checksum: 10c0/dad09c52d9545aae4deb82d2fc40b1ae810b8bcf950877cee9578b26948c8aac0aca4cfdee49aaf6df3f88ee176033bbafcd365b81489a1085ace4e693dda898
languageName: node
linkType: hard

"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fhardware-management-extension%40workspace%3Ahardware-management-extension":
version: 0.1.10
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=fa62e1&locator=%40janhq%2Fhardware-management-extension%40workspace%3Ahardware-management-extension"
dependencies:
rxjs: "npm:^7.8.1"
ulidx: "npm:^2.3.0"
checksum: 10c0/dad09c52d9545aae4deb82d2fc40b1ae810b8bcf950877cee9578b26948c8aac0aca4cfdee49aaf6df3f88ee176033bbafcd365b81489a1085ace4e693dda898
languageName: node
linkType: hard

"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Finference-cortex-extension%40workspace%3Ainference-cortex-extension":
version: 0.1.10
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=7dd866&locator=%40janhq%2Finference-cortex-extension%40workspace%3Ainference-cortex-extension"
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=fa62e1&locator=%40janhq%2Finference-cortex-extension%40workspace%3Ainference-cortex-extension"
dependencies:
rxjs: "npm:^7.8.1"
ulidx: "npm:^2.3.0"
checksum: 10c0/da0eed6e552ce2ff6f52a087e6e221101c3d0c03d92820840ee80c3ca1a17317a66525cb5bf59b6c1e8bd2e36e54763008f97e13000ae339dac49f5682fcfa65
checksum: 10c0/dad09c52d9545aae4deb82d2fc40b1ae810b8bcf950877cee9578b26948c8aac0aca4cfdee49aaf6df3f88ee176033bbafcd365b81489a1085ace4e693dda898
languageName: node
linkType: hard

"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fmodel-extension%40workspace%3Amodel-extension":
version: 0.1.10
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=7dd866&locator=%40janhq%2Fmodel-extension%40workspace%3Amodel-extension"
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=fa62e1&locator=%40janhq%2Fmodel-extension%40workspace%3Amodel-extension"
dependencies:
rxjs: "npm:^7.8.1"
ulidx: "npm:^2.3.0"
checksum: 10c0/da0eed6e552ce2ff6f52a087e6e221101c3d0c03d92820840ee80c3ca1a17317a66525cb5bf59b6c1e8bd2e36e54763008f97e13000ae339dac49f5682fcfa65
checksum: 10c0/dad09c52d9545aae4deb82d2fc40b1ae810b8bcf950877cee9578b26948c8aac0aca4cfdee49aaf6df3f88ee176033bbafcd365b81489a1085ace4e693dda898
languageName: node
linkType: hard

"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fmonitoring-extension%40workspace%3Amonitoring-extension":
version: 0.1.10
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=7dd866&locator=%40janhq%2Fmonitoring-extension%40workspace%3Amonitoring-extension"
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=fa62e1&locator=%40janhq%2Fmonitoring-extension%40workspace%3Amonitoring-extension"
dependencies:
rxjs: "npm:^7.8.1"
ulidx: "npm:^2.3.0"
checksum: 10c0/da0eed6e552ce2ff6f52a087e6e221101c3d0c03d92820840ee80c3ca1a17317a66525cb5bf59b6c1e8bd2e36e54763008f97e13000ae339dac49f5682fcfa65
checksum: 10c0/dad09c52d9545aae4deb82d2fc40b1ae810b8bcf950877cee9578b26948c8aac0aca4cfdee49aaf6df3f88ee176033bbafcd365b81489a1085ace4e693dda898
languageName: node
linkType: hard

Expand All @@ -584,6 +594,23 @@ __metadata:
languageName: unknown
linkType: soft

"@janhq/hardware-management-extension@workspace:hardware-management-extension":
version: 0.0.0-use.local
resolution: "@janhq/hardware-management-extension@workspace:hardware-management-extension"
dependencies:
"@janhq/core": ../../core/package.tgz
cpu-instructions: "npm:^0.0.13"
cpx: "npm:^1.5.0"
ky: "npm:^1.7.2"
p-queue: "npm:^8.0.1"
rimraf: "npm:^3.0.2"
rolldown: "npm:^1.0.0-beta.1"
run-script-os: "npm:^1.1.6"
ts-loader: "npm:^9.5.0"
typescript: "npm:^5.3.3"
languageName: unknown
linkType: soft

"@janhq/inference-cortex-extension@workspace:inference-cortex-extension":
version: 0.0.0-use.local
resolution: "@janhq/inference-cortex-extension@workspace:inference-cortex-extension"
Expand Down
Loading
Loading