spacedrive/scripts/utils/shared.mjs
Ericson "Fogo" Soares 7c90bcb95b
[ENG-1479] AI Prototype (#1845)
* First draft on image labeling

* Fixing execution providers for other OSs

* Better error handling and shutdown

* Working with shallow media processor

* bruh

* Fix warnings

* Now hooked to media processor job

* Link desktop app with libonnxruntime to avoid TLS error during startup

* Be able to change models on runtime
Revert to use labels table instead of tags

* A bug on a model-less inference

* Show AI labels on Inspector
 - Change yolo inference to use half precision
 - Add labels api to core

* Remove LD_PRELOAD

* Fix race condition on model executor shutdown

* Don't load all images in memory moron

* Embeed yolo model in prod build
 - Change yolo model path to new one relative to executable

* Disable volume watcher on linux, it was crashing the app
 - Invalidate labels when they are updated

* Rust fmt

* Minor changes

* Gate onnxruntime linking to the ai-models feature

* Add build script to sd-server to handle onnxruntime linking workaround

* Move AI stuff to its own crate and normalize deps

* Rust fmt

* Don't regenerate labels unless asked to

* Now blazingly fast

* Bad merge

* Fix

* Fix

* Add backend logic to download extra yolo models

* Add models api route
 - Add api call to get available model version
 - Add api call to change the model version

* Improve new model download logic
 - Add frontend to change image labeler model

* Fix new model downloader

* Fix model select width

* invalidate labels count after media_processor generates a new output

* Rename AI crate and first draft on download notifications

* fix types

---------

Co-authored-by: Vítor Vasconcellos <vasconcellos.dev@gmail.com>
Co-authored-by: Brendan Allan <brendonovich@outlook.com>
2023-12-19 09:28:57 +00:00

111 lines
3.3 KiB
JavaScript

import { exec as execCb } from 'node:child_process'
import * as fs from 'node:fs/promises'
import * as path from 'node:path'
import { env } from 'node:process'
import { promisify } from 'node:util'
const exec = promisify(execCb)
const signId = env.APPLE_SIGNING_IDENTITY || '-'
/**
* @param {string} origin
* @param {string} target
* @param {boolean} [rename]
*/
async function link(origin, target, rename) {
const parent = path.dirname(target)
await fs.mkdir(parent, { recursive: true, mode: 0o751 })
await (rename ? fs.rename(origin, target) : fs.symlink(path.relative(parent, origin), target))
}
/**
* Symlink shared libs paths for Linux
* @param {string} root
* @param {string} nativeDeps
* @returns {Promise<void>}
*/
export async function symlinkSharedLibsLinux(root, nativeDeps) {
// rpath=${ORIGIN}/../lib/spacedrive
const targetLib = path.join(root, 'target', 'lib')
const targetShare = path.join(root, 'target', 'share', 'spacedrive')
const targetRPath = path.join(targetLib, 'spacedrive')
const targetModelShare = path.join(targetShare, 'models')
await Promise.all([
...[targetRPath, targetModelShare].map(path => fs.unlink(path).catch(() => {})),
...[targetLib, targetShare].map(path => fs.mkdir(path, { recursive: true })),
])
await link(path.join(nativeDeps, 'lib'), targetRPath)
await link(path.join(nativeDeps, 'models'), targetModelShare)
}
/**
* Symlink shared libs paths for macOS
* @param {string} root
* @param {string} nativeDeps
*/
export async function symlinkSharedLibsMacOS(root, nativeDeps) {
// rpath=@executable_path/../Frameworks/Spacedrive.framework
const targetFrameworks = path.join(root, 'target', 'Frameworks')
// Framework
const framework = path.join(nativeDeps, 'Spacedrive.framework')
// Link Spacedrive.framework to target folder so sd-server can work ootb
await fs.rm(targetFrameworks, { recursive: true }).catch(() => {})
await fs.mkdir(targetFrameworks, { recursive: true })
await link(framework, path.join(targetFrameworks, 'Spacedrive.framework'))
// Sign dylibs (Required for them to work on macOS 13+)
await fs
.readdir(path.join(framework, 'Libraries'), { recursive: true, withFileTypes: true })
.then(files =>
Promise.all(
files
.filter(entry => entry.isFile() && entry.name.endsWith('.dylib'))
.map(entry =>
exec(`codesign -s "${signId}" -f "${path.join(entry.path, entry.name)}"`)
)
)
)
}
/**
* Copy Windows DLLs for tauri build
* @param {string} nativeDeps
* @returns {Promise<Record<string, string>>}
*/
export async function windowsDLLs(nativeDeps) {
return Object.fromEntries(
await fs
.readdir(path.join(nativeDeps, 'bin'), { withFileTypes: true })
.then(files =>
files
.filter(entry => entry.isFile() && entry.name.endsWith(`.dll`))
.map(entry => [path.join(entry.path, entry.name), '.'])
)
)
}
/**
* Symlink shared libs paths for Linux
* @param {string} nativeDeps
* @returns {Promise<Record<string, string>>}
*/
export async function linuxLibs(nativeDeps) {
return Object.fromEntries(
await fs
.readdir(path.join(nativeDeps, 'lib'), { withFileTypes: true })
.then(files =>
Promise.all(
files
.filter(
entry =>
(entry.isFile() || entry.isSymbolicLink()) &&
(entry.name.endsWith('.so') || entry.name.includes('.so.'))
)
.map(entry => [path.join(entry.path, entry.name), '.'])
)
)
)
}