First upload version 0.0.1

This commit is contained in:
Neyra
2026-02-05 15:27:49 +08:00
commit 8e9b7201ed
4182 changed files with 593136 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
import { EventRelay } from "lifecycle-utils";
export declare class MemoryOrchestrator {
readonly onMemoryReservationRelease: EventRelay<void>;
constructor(getMemoryState: () => {
free: number;
total: number;
unifiedSize: number;
});
reserveMemory(bytes: number): MemoryReservation;
getMemoryState(): Promise<{
free: number;
total: number;
unifiedSize: number;
}>;
}
export declare class MemoryReservation {
private constructor();
get size(): number;
get disposed(): boolean;
[Symbol.dispose](): void;
dispose(): void;
static _create(bytes: number, dispose: () => void): MemoryReservation;
}

View File

@@ -0,0 +1,50 @@
import { EventRelay } from "lifecycle-utils";
export class MemoryOrchestrator {
/** @internal */ _getMemoryState;
/** @internal */ _reservedMemory = 0;
onMemoryReservationRelease = new EventRelay();
constructor(getMemoryState) {
this._getMemoryState = getMemoryState;
}
reserveMemory(bytes) {
this._reservedMemory += bytes;
return MemoryReservation._create(bytes, () => {
this._reservedMemory -= bytes;
this.onMemoryReservationRelease.dispatchEvent();
});
}
async getMemoryState() {
const { free, total, unifiedSize } = this._getMemoryState();
return {
free: Math.max(0, free - this._reservedMemory),
total,
unifiedSize
};
}
}
export class MemoryReservation {
/** @internal */ _size;
/** @internal */ _dispose;
constructor(size, dispose) {
this._size = size;
this._dispose = dispose;
}
get size() {
return this._size;
}
get disposed() {
return this._dispose == null;
}
[Symbol.dispose]() {
this.dispose();
}
dispose() {
if (this._dispose != null)
this._dispose();
this._dispose = null;
}
static _create(bytes, dispose) {
return new MemoryReservation(bytes, dispose);
}
}
//# sourceMappingURL=MemoryOrchestrator.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"MemoryOrchestrator.js","sourceRoot":"","sources":["../../../src/bindings/utils/MemoryOrchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAE3C,MAAM,OAAO,kBAAkB;IAC3B,gBAAgB,CAAkB,eAAe,CAA2D;IAC5G,gBAAgB,CAAS,eAAe,GAAW,CAAC,CAAC;IAErC,0BAA0B,GAAG,IAAI,UAAU,EAAQ,CAAC;IAEpE,YAAmB,cAAwE;QACvF,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC;IAC1C,CAAC;IAEM,aAAa,CAAC,KAAa;QAC9B,IAAI,CAAC,eAAe,IAAI,KAAK,CAAC;QAE9B,OAAO,iBAAiB,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE;YACzC,IAAI,CAAC,eAAe,IAAI,KAAK,CAAC;YAC9B,IAAI,CAAC,0BAA0B,CAAC,aAAa,EAAE,CAAC;QACpD,CAAC,CAAC,CAAC;IACP,CAAC;IAEM,KAAK,CAAC,cAAc;QACvB,MAAM,EAAC,IAAI,EAAE,KAAK,EAAE,WAAW,EAAC,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAE1D,OAAO;YACH,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC;YAC9C,KAAK;YACL,WAAW;SACd,CAAC;IACN,CAAC;CACJ;AAED,MAAM,OAAO,iBAAiB;IAC1B,gBAAgB,CAAkB,KAAK,CAAS;IAChD,gBAAgB,CAAS,QAAQ,CAAsB;IAEvD,YAAoB,IAAY,EAAE,OAAmB;QACjD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC5B,CAAC;IAED,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;IACjC,CAAC;IAEM,CAAC,MAAM,CAAC,OAAO,CAAC;QACnB,IAAI,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;IAEM,OAAO;QACV,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI;YACrB,IAAI,CAAC,QAAQ,EAAE,CAAC;QAEpB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACzB,CAAC;IAEM,MAAM,CAAC,OAAO,CAAC,KAAa,EAAE,OAAmB;QACpD,OAAO,IAAI,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;CACJ"}

View File

@@ -0,0 +1,2 @@
export declare class NoBinaryFoundError extends Error {
}

View File

@@ -0,0 +1,7 @@
export class NoBinaryFoundError extends Error {
/** @internal */
constructor(message = "NoBinaryFoundError") {
super(message);
}
}
//# sourceMappingURL=NoBinaryFoundError.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NoBinaryFoundError.js","sourceRoot":"","sources":["../../../src/bindings/utils/NoBinaryFoundError.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACzC,gBAAgB;IAChB,YAAmB,UAAkB,oBAAoB;QACrD,KAAK,CAAC,OAAO,CAAC,CAAC;IACnB,CAAC;CACJ"}

View File

@@ -0,0 +1,5 @@
/**
* Returns a promise that resolves to true if every promise in the array resolves to true, otherwise false.
* Note that this function will not throw on error and instead will log the error to the console.
*/
export declare function asyncEvery(promises: Promise<boolean>[]): Promise<boolean>;

View File

@@ -0,0 +1,15 @@
import { getConsoleLogPrefix } from "../../utils/getConsoleLogPrefix.js";
/**
* Returns a promise that resolves to true if every promise in the array resolves to true, otherwise false.
* Note that this function will not throw on error and instead will log the error to the console.
*/
export async function asyncEvery(promises) {
try {
return (await Promise.all(promises)).every(Boolean);
}
catch (err) {
console.error(getConsoleLogPrefix(false, false), err);
return false;
}
}
//# sourceMappingURL=asyncEvery.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"asyncEvery.js","sourceRoot":"","sources":["../../../src/bindings/utils/asyncEvery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAC,MAAM,oCAAoC,CAAC;AAEvE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAA4B;IACzD,IAAI,CAAC;QACD,OAAO,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;QAEtD,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC"}

View File

@@ -0,0 +1,5 @@
/**
* Returns a promise that fulfills as soon as any of the promises return `true`.
* Note that this function will not throw on error and instead will log the error to the console.
*/
export declare function asyncSome(promises: Promise<boolean>[]): Promise<boolean>;

View File

@@ -0,0 +1,29 @@
import { getConsoleLogPrefix } from "../../utils/getConsoleLogPrefix.js";
/**
* Returns a promise that fulfills as soon as any of the promises return `true`.
* Note that this function will not throw on error and instead will log the error to the console.
*/
export async function asyncSome(promises) {
if (promises.length === 0)
return Promise.resolve(false);
return new Promise((resolve) => {
let fulfilled = 0;
for (const promise of promises) {
promise
.then((result) => {
if (result)
return void resolve(true);
fulfilled++;
if (fulfilled === promises.length)
resolve(false);
})
.catch((err) => {
console.error(getConsoleLogPrefix(false, false), err);
fulfilled++;
if (fulfilled === promises.length)
resolve(false);
});
}
});
}
//# sourceMappingURL=asyncSome.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"asyncSome.js","sourceRoot":"","sources":["../../../src/bindings/utils/asyncSome.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAC,MAAM,oCAAoC,CAAC;AAEvE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAA4B;IACxD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QACrB,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAElC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3B,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC7B,OAAO;iBACF,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;gBACb,IAAI,MAAM;oBACN,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;gBAE9B,SAAS,EAAE,CAAC;gBACZ,IAAI,SAAS,KAAK,QAAQ,CAAC,MAAM;oBAC7B,OAAO,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACX,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;gBAEtD,SAAS,EAAE,CAAC;gBACZ,IAAI,SAAS,KAAK,QAAQ,CAAC,MAAM;oBAC7B,OAAO,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;QACX,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}

View File

@@ -0,0 +1,6 @@
type BinariesGithubReleaseFile = {
release: "latest" | string;
};
export declare function getBinariesGithubRelease(): Promise<string>;
export declare function setBinariesGithubRelease(release: BinariesGithubReleaseFile["release"]): Promise<void>;
export {};

View File

@@ -0,0 +1,15 @@
import fs from "fs-extra";
import { binariesGithubReleasePath } from "../../config.js";
export async function getBinariesGithubRelease() {
const binariesGithubRelease = await fs.readJson(binariesGithubReleasePath);
return binariesGithubRelease.release;
}
export async function setBinariesGithubRelease(release) {
const binariesGithubReleaseJson = {
release: release
};
await fs.writeJson(binariesGithubReleasePath, binariesGithubReleaseJson, {
spaces: 4
});
}
//# sourceMappingURL=binariesGithubRelease.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"binariesGithubRelease.js","sourceRoot":"","sources":["../../../src/bindings/utils/binariesGithubRelease.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAC,yBAAyB,EAAC,MAAM,iBAAiB,CAAC;AAM1D,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC1C,MAAM,qBAAqB,GAA8B,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;IAEtG,OAAO,qBAAqB,CAAC,OAAO,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,OAA6C;IACxF,MAAM,yBAAyB,GAA8B;QACzD,OAAO,EAAE,OAAO;KACnB,CAAC;IAEF,MAAM,EAAE,CAAC,SAAS,CAAC,yBAAyB,EAAE,yBAAyB,EAAE;QACrE,MAAM,EAAE,CAAC;KACZ,CAAC,CAAC;AACP,CAAC"}

View File

@@ -0,0 +1 @@
export declare function clearAllLocalBuilds(waitForLocks?: boolean): Promise<void>;

View File

@@ -0,0 +1,47 @@
import path from "path";
import fs from "fs-extra";
import { lastBuildInfoJsonPath, llamaLocalBuildBinsDirectory } from "../../config.js";
import { clearTempFolder } from "../../utils/clearTempFolder.js";
import { withLockfile } from "../../utils/withLockfile.js";
import { isLockfileActive } from "../../utils/isLockfileActive.js";
import { getConsoleLogPrefix } from "../../utils/getConsoleLogPrefix.js";
export async function clearAllLocalBuilds(waitForLocks = false) {
async function removeBuilds() {
const itemsToRemove = Array.from(new Set((await fs.readdir(llamaLocalBuildBinsDirectory))
.map((item) => (item.endsWith(".lock")
? item.slice(0, -".lock".length)
: item))
.filter((item) => !item.startsWith("."))));
let hasLocks = false;
const buildRemovals = itemsToRemove.map(async (item) => {
const absolutePath = path.join(llamaLocalBuildBinsDirectory, item);
const pathIsLocked = await isLockfileActive({ resourcePath: absolutePath });
hasLocks ||= pathIsLocked;
if (waitForLocks)
await withLockfile({
resourcePath: absolutePath
}, async () => {
await fs.remove(absolutePath);
});
else if (!pathIsLocked)
await fs.remove(absolutePath);
});
return {
buildRemovals,
hasLocks
};
}
if (await fs.pathExists(llamaLocalBuildBinsDirectory)) {
const { hasLocks, buildRemovals } = await removeBuilds();
if (hasLocks) {
if (waitForLocks)
console.log(getConsoleLogPrefix() + "Some builds are in progress. Waiting for those builds to finish before removing them.");
else
console.log(getConsoleLogPrefix() + "Some builds are in progress. Skipping the removal of those builds.");
}
await Promise.all(buildRemovals);
}
await fs.remove(lastBuildInfoJsonPath);
await clearTempFolder();
}
//# sourceMappingURL=clearAllLocalBuilds.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"clearAllLocalBuilds.js","sourceRoot":"","sources":["../../../src/bindings/utils/clearAllLocalBuilds.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAC,qBAAqB,EAAE,4BAA4B,EAAC,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAC,eAAe,EAAC,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAC,YAAY,EAAC,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAC,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAC,mBAAmB,EAAC,MAAM,oCAAoC,CAAC;AAEvE,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,YAAY,GAAG,KAAK;IAC1D,KAAK,UAAU,YAAY;QACvB,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAC5B,IAAI,GAAG,CACH,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;aAC3C,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACX,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAClB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;YAChC,CAAC,CAAC,IAAI,CACb,CAAC;aACD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAC/C,CACJ,CAAC;QAEF,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,aAAa,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YACnD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,4BAA4B,EAAE,IAAI,CAAC,CAAC;YACnE,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,EAAC,YAAY,EAAE,YAAY,EAAC,CAAC,CAAC;YAE1E,QAAQ,KAAK,YAAY,CAAC;YAE1B,IAAI,YAAY;gBACZ,MAAM,YAAY,CAAC;oBACf,YAAY,EAAE,YAAY;iBAC7B,EAAE,KAAK,IAAI,EAAE;oBACV,MAAM,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;gBAClC,CAAC,CAAC,CAAC;iBACF,IAAI,CAAC,YAAY;gBAClB,MAAM,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,OAAO;YACH,aAAa;YACb,QAAQ;SACX,CAAC;IACN,CAAC;IAED,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,4BAA4B,CAAC,EAAE,CAAC;QACpD,MAAM,EAAC,QAAQ,EAAE,aAAa,EAAC,GAAG,MAAM,YAAY,EAAE,CAAC;QAEvD,IAAI,QAAQ,EAAE,CAAC;YACX,IAAI,YAAY;gBACZ,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,GAAG,uFAAuF,CAAC,CAAC;;gBAE7H,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,GAAG,oEAAoE,CAAC,CAAC;QAClH,CAAC;QAED,MAAM,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;IACvC,MAAM,eAAe,EAAE,CAAC;AAC5B,CAAC"}

View File

@@ -0,0 +1,11 @@
type ClonedLlamaCppRepoTagFile = {
tag: string;
llamaCppGithubRepo: string;
};
export declare function cloneLlamaCppRepo(githubOwner: string, githubRepo: string, tag: string, useBundles?: boolean, progressLogs?: boolean, recursive?: boolean): Promise<void>;
export declare function getClonedLlamaCppRepoReleaseInfo(): Promise<ClonedLlamaCppRepoTagFile | null>;
export declare function isLlamaCppRepoCloned(waitForLock?: boolean): Promise<boolean>;
export declare function ensureLlamaCppRepoIsCloned({ progressLogs }?: {
progressLogs?: boolean;
}): Promise<void>;
export {};

View File

@@ -0,0 +1,166 @@
import path from "path";
import simpleGit from "simple-git";
import chalk from "chalk";
import fs from "fs-extra";
import which from "which";
import { defaultLlamaCppGitHubRepo, defaultLlamaCppRelease, enableRecursiveClone, llamaCppDirectory, llamaCppDirectoryInfoFilePath } from "../../config.js";
import { getGitBundlePathForRelease } from "../../utils/gitReleaseBundles.js";
import { withLockfile } from "../../utils/withLockfile.js";
import { waitForLockfileRelease } from "../../utils/waitForLockfileRelease.js";
import { getConsoleLogPrefix } from "../../utils/getConsoleLogPrefix.js";
import { isLockfileActive } from "../../utils/isLockfileActive.js";
import { isGithubReleaseNeedsResolving, resolveGithubRelease } from "../../utils/resolveGithubRelease.js";
import withStatusLogs from "../../utils/withStatusLogs.js";
import { withProgressLog } from "../../utils/withProgressLog.js";
import { logDistroInstallInstruction } from "./logDistroInstallInstruction.js";
export async function cloneLlamaCppRepo(githubOwner, githubRepo, tag, useBundles = true, progressLogs = true, recursive = enableRecursiveClone) {
const gitBundleForTag = !useBundles ? null : await getGitBundlePathForRelease(githubOwner, githubRepo, tag);
const remoteGitUrl = `https://github.com/${githubOwner}/${githubRepo}.git`;
async function withGitCloneProgress(cloneName, callback) {
if (!progressLogs)
return await callback(simpleGit({}));
const repoText = `${githubOwner}/${githubRepo} (${cloneName})`;
let lastProgress = 0;
let stages = 1;
return await withProgressLog({
loadingText: chalk.bold("Cloning " + repoText),
successText: chalk.blue("Cloned " + repoText),
failText: chalk.blue("Failed to clone " + repoText),
progressFractionDigits: false
}, async (progressUpdater) => {
const gitWithCloneProgress = simpleGit({
progress({ progress }) {
const currentProgress = progress / 100;
if (currentProgress < lastProgress)
stages++;
lastProgress = currentProgress;
progressUpdater.setProgress(currentProgress, stages > 1
? `(Stage ${stages})`
: undefined);
}
});
const res = await callback(gitWithCloneProgress);
progressUpdater.setProgress(1);
return res;
});
}
await withLockfile({
resourcePath: llamaCppDirectory
}, async () => {
await fs.remove(llamaCppDirectory);
await fs.remove(llamaCppDirectoryInfoFilePath);
if (gitBundleForTag != null) {
try {
await withGitCloneProgress("local bundle", async (gitWithCloneProgress) => {
await gitWithCloneProgress.clone(gitBundleForTag, llamaCppDirectory, {
"--quiet": null
});
await simpleGit(llamaCppDirectory).removeRemote("origin");
});
await updateClonedLlamaCppRepoTagFile(githubOwner, githubRepo, tag);
return;
}
catch (err) {
await fs.remove(llamaCppDirectory);
await fs.remove(llamaCppDirectoryInfoFilePath);
if (progressLogs)
console.error(getConsoleLogPrefix() + "Failed to clone git bundle, cloning from GitHub instead", err);
await printCloneErrorHelp(String(err));
}
}
try {
await withGitCloneProgress("GitHub", async (gitWithCloneProgress) => {
await gitWithCloneProgress.clone(remoteGitUrl, llamaCppDirectory, {
"--depth": 1,
"--branch": tag,
...(recursive ? { "--recursive": null } : {}),
"--quiet": null
});
});
await updateClonedLlamaCppRepoTagFile(githubOwner, githubRepo, tag);
}
catch (err) {
await printCloneErrorHelp(String(err));
throw err;
}
});
}
async function printCloneErrorHelp(error) {
// This error happens with some docker images where the current user is different
// from the owner of the files due to mounting a volume.
// In such cases, print a helpful message to help the user resolve the issue.
if (error.toLowerCase().includes("detected dubious ownership in repository"))
console.info("\n" +
getConsoleLogPrefix(true) + chalk.yellow("To fix this issue, try running this command to fix it for the current module directory:") + "\n" +
'git config --global --add safe.directory "' + llamaCppDirectory + '"\n\n' +
chalk.yellow("Or run this command to fix it everywhere:") + "\n" +
'git config --global --add safe.directory "*"');
else if (await which("git", { nothrow: true }) == null) {
console.info("\n" +
getConsoleLogPrefix(true) + chalk.yellow("Git is not installed, please install it first to build llama.cpp"));
await logDistroInstallInstruction("To install git, ", {
linuxPackages: { apt: ["git"], apk: ["git"] },
macOsPackages: { brew: ["git", "git-lfs"] }
});
}
}
export async function getClonedLlamaCppRepoReleaseInfo() {
if (!(await isLlamaCppRepoCloned(false)))
return null;
if (!(await fs.pathExists(llamaCppDirectoryInfoFilePath)))
return null;
try {
const clonedLlamaCppRepoTagJson = await fs.readJson(llamaCppDirectoryInfoFilePath);
return clonedLlamaCppRepoTagJson;
}
catch (err) {
console.error(getConsoleLogPrefix() + "Failed to read llama.cpp tag file", err);
return null;
}
}
export async function isLlamaCppRepoCloned(waitForLock = true) {
if (waitForLock)
await waitForLockfileRelease({ resourcePath: llamaCppDirectory });
else if (await isLockfileActive({ resourcePath: llamaCppDirectory }))
return false;
const [repoGitExists, releaseInfoFileExists] = await Promise.all([
fs.pathExists(path.join(llamaCppDirectory, ".git")),
fs.pathExists(llamaCppDirectoryInfoFilePath)
]);
return repoGitExists && releaseInfoFileExists;
}
export async function ensureLlamaCppRepoIsCloned({ progressLogs = true } = {}) {
if (await isLlamaCppRepoCloned(true))
return;
const [githubOwner, githubRepo] = defaultLlamaCppGitHubRepo.split("/");
if (progressLogs)
console.log(getConsoleLogPrefix() + chalk.blue("Cloning llama.cpp"));
let releaseTag = defaultLlamaCppRelease;
if (isGithubReleaseNeedsResolving(releaseTag)) {
await withStatusLogs({
loading: chalk.blue("Fetching llama.cpp info"),
success: chalk.blue("Fetched llama.cpp info"),
fail: chalk.blue("Failed to fetch llama.cpp info"),
disableLogs: !progressLogs
}, async () => {
releaseTag = await resolveGithubRelease(githubOwner, githubRepo, releaseTag);
});
}
await cloneLlamaCppRepo(githubOwner, githubRepo, releaseTag, true, progressLogs);
}
async function updateClonedLlamaCppRepoTagFile(githubOwner, githubRepo, tag) {
try {
const clonedLlamaCppRepoTagJson = {
tag,
llamaCppGithubRepo: githubOwner + "/" + githubRepo
};
await fs.writeJson(llamaCppDirectoryInfoFilePath, clonedLlamaCppRepoTagJson, {
spaces: 4
});
}
catch (err) {
console.error(getConsoleLogPrefix() + "Failed to write llama.cpp tag file", err);
throw err;
}
}
//# sourceMappingURL=cloneLlamaCppRepo.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
import process from "process";
import { BuildMetadataFile, BuildOptions } from "../types.js";
export declare function compileLlamaCpp(buildOptions: BuildOptions, compileOptions: {
nodeTarget?: string;
updateLastBuildInfo?: boolean;
includeBuildOptionsInBinaryFolderName?: boolean;
ensureLlamaCppRepoIsCloned?: boolean;
downloadCmakeIfNeeded?: boolean;
ignoreWorkarounds?: ("cudaArchitecture" | "reduceParallelBuildThreads" | "singleBuildThread" | "avoidWindowsLlvm")[];
envVars?: typeof process.env;
ciMode?: boolean;
}): Promise<void>;
export declare function getLocalBuildBinaryPath(folderName: string): Promise<string | null>;
export declare function getLocalBuildBinaryBuildMetadata(folderName: string): Promise<BuildMetadataFile>;
export declare function getPrebuiltBinaryPath(buildOptions: BuildOptions, folderName: string): Promise<{
binaryPath: string;
folderName: string;
folderPath: string;
extBackendsPath: string | undefined;
} | null>;
export declare function getPrebuiltBinaryBuildMetadata(folderPath: string, folderName: string): Promise<BuildMetadataFile>;

View File

@@ -0,0 +1,516 @@
import path from "path";
import { fileURLToPath } from "url";
import process from "process";
import os from "os";
import fs from "fs-extra";
import chalk from "chalk";
import which from "which";
import { buildMetadataFileName, documentationPageUrls, llamaCppDirectory, llamaDirectory, llamaLocalBuildBinsDirectory, llamaPrebuiltBinsDirectory, llamaToolchainsDirectory } from "../../config.js";
import { convertBuildOptionsToBuildOptionsJSON } from "../types.js";
import { spawnCommand, SpawnError } from "../../utils/spawnCommand.js";
import { downloadCmakeIfNeeded, fixXpackPermissions, getCmakePath, hasBuiltinCmake } from "../../utils/cmake.js";
import { getConsoleLogPrefix } from "../../utils/getConsoleLogPrefix.js";
import { withLockfile } from "../../utils/withLockfile.js";
import { getModuleVersion } from "../../utils/getModuleVersion.js";
import { ensureLlamaCppRepoIsCloned, isLlamaCppRepoCloned } from "./cloneLlamaCppRepo.js";
import { getBuildFolderNameForBuildOptions } from "./getBuildFolderNameForBuildOptions.js";
import { setLastBuildInfo } from "./lastBuildInfo.js";
import { getPlatform } from "./getPlatform.js";
import { logDistroInstallInstruction } from "./logDistroInstallInstruction.js";
import { testCmakeBinary } from "./testCmakeBinary.js";
import { getCudaNvccPaths } from "./detectAvailableComputeLayers.js";
import { detectWindowsBuildTools } from "./detectBuildTools.js";
import { asyncSome } from "./asyncSome.js";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const buildConfigType = "Release";
const requiresMsvcOnWindowsFlags = ["blas", "cann", "cuda", "hip", "kompute", "musa", "sycl", "opencl"]
.map((backend) => ("GGML_" + backend.toUpperCase()));
export async function compileLlamaCpp(buildOptions, compileOptions) {
const { nodeTarget = process.version, updateLastBuildInfo: updateLastBuildInfoArg = true, includeBuildOptionsInBinaryFolderName = true, ensureLlamaCppRepoIsCloned: ensureLlamaCppRepoIsClonedArg = false, downloadCmakeIfNeeded: downloadCmakeIfNeededArg = false, ignoreWorkarounds = [], envVars = process.env, ciMode = false } = compileOptions;
const platform = getPlatform();
const buildFolderName = await getBuildFolderNameForBuildOptions(buildOptions);
const finalBuildFolderName = includeBuildOptionsInBinaryFolderName
? buildFolderName.withCustomCmakeOptions
: buildFolderName.withoutCustomCmakeOptions;
const useWindowsLlvm = (platform === "win" &&
(buildOptions.gpu === false ||
buildOptions.gpu === "vulkan") &&
!ignoreWorkarounds.includes("avoidWindowsLlvm") &&
!buildOptions.customCmakeOptions.has("CMAKE_TOOLCHAIN_FILE") &&
!requiresMsvcOnWindowsFlags.some((flag) => buildOptions.customCmakeOptions.has(flag)))
? areWindowsBuildToolsCapableForLlvmBuild(await detectWindowsBuildTools())
: false;
const outDirectory = path.join(llamaLocalBuildBinsDirectory, finalBuildFolderName);
let parallelBuildThreads = getParallelBuildThreadsToUse(platform, buildOptions.gpu, ciMode);
if (ignoreWorkarounds.includes("singleBuildThread"))
parallelBuildThreads = 1;
else if (ignoreWorkarounds.includes("reduceParallelBuildThreads"))
parallelBuildThreads = reduceParallelBuildThreads(parallelBuildThreads);
await fs.mkdirp(llamaLocalBuildBinsDirectory);
try {
await withLockfile({
resourcePath: outDirectory
}, async () => {
try {
if (ensureLlamaCppRepoIsClonedArg)
await ensureLlamaCppRepoIsCloned({ progressLogs: buildOptions.progressLogs });
else if (!(await isLlamaCppRepoCloned()))
throw new Error(`"${llamaCppDirectory}" directory does not exist`);
if (downloadCmakeIfNeededArg)
await downloadCmakeIfNeeded(buildOptions.progressLogs);
const cmakePathArgs = await getCmakePathArgs();
const cmakeGeneratorArgs = getCmakeGeneratorArgs(buildOptions.platform, buildOptions.arch, useWindowsLlvm);
const toolchainFile = await getToolchainFileForArch(buildOptions.arch, useWindowsLlvm);
const runtimeVersion = nodeTarget.startsWith("v") ? nodeTarget.slice("v".length) : nodeTarget;
const cmakeCustomOptions = new Map(buildOptions.customCmakeOptions);
const cmakeToolchainOptions = new Map();
if (!cmakeCustomOptions.has("GGML_BUILD_NUMBER"))
cmakeCustomOptions.set("GGML_BUILD_NUMBER", "1");
cmakeCustomOptions.set("CMAKE_CONFIGURATION_TYPES", buildConfigType);
cmakeCustomOptions.set("NLC_CURRENT_PLATFORM", platform + "-" + process.arch);
cmakeCustomOptions.set("NLC_TARGET_PLATFORM", buildOptions.platform + "-" + buildOptions.arch);
cmakeCustomOptions.set("NLC_VARIANT", buildFolderName.binVariant);
if (toolchainFile != null && !cmakeCustomOptions.has("CMAKE_TOOLCHAIN_FILE"))
cmakeToolchainOptions.set("CMAKE_TOOLCHAIN_FILE", toolchainFile);
if (toolchainFile != null &&
buildOptions.gpu === "vulkan" &&
(useWindowsLlvm || (platform === "win" && buildOptions.arch === "arm64")) &&
!cmakeCustomOptions.has("GGML_VULKAN_SHADERS_GEN_TOOLCHAIN"))
cmakeToolchainOptions.set("GGML_VULKAN_SHADERS_GEN_TOOLCHAIN", toolchainFile);
if (buildOptions.gpu === "metal" && process.platform === "darwin" && !cmakeCustomOptions.has("GGML_METAL"))
cmakeCustomOptions.set("GGML_METAL", "1");
else if (!cmakeCustomOptions.has("GGML_METAL"))
cmakeCustomOptions.set("GGML_METAL", "OFF");
if (buildOptions.gpu === "cuda" && !cmakeCustomOptions.has("GGML_CUDA"))
cmakeCustomOptions.set("GGML_CUDA", "1");
if (buildOptions.gpu === "vulkan" && !cmakeCustomOptions.has("GGML_VULKAN"))
cmakeCustomOptions.set("GGML_VULKAN", "1");
if (!cmakeCustomOptions.has("GGML_CCACHE"))
cmakeCustomOptions.set("GGML_CCACHE", "OFF");
// avoid linking to extra libraries that we don't use
{
if (!cmakeCustomOptions.has("LLAMA_CURL") || isCmakeValueOff(cmakeCustomOptions.get("LLAMA_CURL")))
cmakeCustomOptions.set("LLAMA_CURL", "OFF");
if (!cmakeCustomOptions.has("LLAMA_HTTPLIB") || isCmakeValueOff(cmakeCustomOptions.get("LLAMA_HTTPLIB"))) {
cmakeCustomOptions.set("LLAMA_HTTPLIB", "OFF");
if (!cmakeCustomOptions.has("LLAMA_BUILD_BORINGSSL"))
cmakeCustomOptions.set("LLAMA_BUILD_BORINGSSL", "OFF");
if (!cmakeCustomOptions.has("LLAMA_OPENSSL"))
cmakeCustomOptions.set("LLAMA_OPENSSL", "OFF");
}
}
if (buildOptions.platform === "win" && buildOptions.arch === "arm64" && !cmakeCustomOptions.has("GGML_OPENMP"))
cmakeCustomOptions.set("GGML_OPENMP", "OFF");
if (useWindowsLlvm)
cmakeCustomOptions.set("GGML_OPENMP", "OFF");
if (ciMode) {
if (!cmakeCustomOptions.has("GGML_OPENMP"))
cmakeCustomOptions.set("GGML_OPENMP", "OFF");
if (!cmakeCustomOptions.has("GGML_NATIVE") || isCmakeValueOff(cmakeCustomOptions.get("GGML_NATIVE"))) {
cmakeCustomOptions.set("GGML_NATIVE", "OFF");
if (buildOptions.arch === "x64" && !cmakeCustomOptions.has("GGML_CPU_ALL_VARIANTS")) {
cmakeCustomOptions.set("GGML_CPU_ALL_VARIANTS", "ON");
cmakeCustomOptions.set("GGML_BACKEND_DL", "ON");
}
else if (!cmakeCustomOptions.has("GGML_BACKEND_DL"))
cmakeCustomOptions.set("GGML_BACKEND_DL", "ON");
}
}
await fs.remove(outDirectory);
await spawnCommand("npm", [
"run", "-s", "cmake-js-llama", "--", "clean",
"--log-level", "warn",
"--out", path.relative(llamaDirectory, outDirectory),
...cmakePathArgs
], __dirname, envVars, buildOptions.progressLogs);
await spawnCommand("npm", [
"run", "-s", "cmake-js-llama", "--", "compile",
"--log-level", "warn",
"--config", buildConfigType,
"--arch=" + buildOptions.arch,
"--out", path.relative(llamaDirectory, outDirectory),
"--runtime-version=" + runtimeVersion,
"--parallel=" + parallelBuildThreads,
...cmakeGeneratorArgs,
...cmakePathArgs,
...([
...cmakeCustomOptions,
...cmakeToolchainOptions
].map(([key, value]) => "--CD" + key + "=" + value))
], __dirname, envVars, buildOptions.progressLogs);
const compiledResultDirPath = await moveBuildFilesToResultDir(outDirectory);
await fs.writeFile(path.join(compiledResultDirPath, buildMetadataFileName), JSON.stringify({
buildOptions: convertBuildOptionsToBuildOptionsJSON(buildOptions)
}), "utf8");
await fs.writeFile(path.join(outDirectory, "buildDone.status"), "", "utf8");
if (updateLastBuildInfoArg) {
await setLastBuildInfo({
folderName: finalBuildFolderName
});
}
}
finally {
await fixXpackPermissions();
}
});
}
catch (err) {
if (platform === "linux" && await which("make", { nothrow: true }) == null) {
console.info("\n" +
getConsoleLogPrefix(true) +
chalk.yellow('It seems that "make" is not installed in your system. Install it to resolve build issues'));
await logDistroInstallInstruction('To install "make", ', {
linuxPackages: { apt: ["make"], apk: ["make"] },
macOsPackages: { brew: ["make"] }
});
}
else if (platform === "linux" && !(await testCmakeBinary(await getCmakePath()))) {
console.info("\n" +
getConsoleLogPrefix(true) +
chalk.yellow('It seems that the used "cmake" doesn\'t work properly. Install it on your system to resolve build issues'));
await logDistroInstallInstruction('To install "cmake", ', {
linuxPackages: { apt: ["cmake"], apk: ["cmake"] },
macOsPackages: { brew: ["cmake"] }
});
}
else if (platform === "mac" && ((await which("clang", { nothrow: true })) == null || (err instanceof SpawnError &&
err.combinedStd.toLowerCase().includes('"/usr/bin/cc" is not able to compile a simple test program'))))
console.info("\n" +
getConsoleLogPrefix(true) +
chalk.yellow("It seems that Xcode command line tools are not installed in your system. Install it to resolve build issues\n") +
getConsoleLogPrefix(true) +
chalk.yellow('To install Xcode command line tools, run "xcode-select --install"'));
else if (buildOptions.gpu === "cuda") {
if (!ignoreWorkarounds.includes("cudaArchitecture") && (platform === "win" || platform === "linux") &&
err instanceof SpawnError && (err.combinedStd.toLowerCase().includes("CUDA Toolkit not found".toLowerCase()) ||
err.combinedStd.toLowerCase().includes("Failed to detect a default CUDA architecture".toLowerCase()) ||
err.combinedStd.toLowerCase().includes("CMAKE_CUDA_COMPILER-NOTFOUND".toLowerCase()) || (err.combinedStd.toLowerCase().includes("Tell CMake where to find the compiler by setting either the environment".toLowerCase()) &&
err.combinedStd.toLowerCase().includes('variable "CUDACXX" or the CMake cache entry CMAKE_CUDA_COMPILER to the full'.toLowerCase())) || (err.combinedStd.toLowerCase().includes("The CUDA compiler".toLowerCase()) &&
err.combinedStd.toLowerCase().includes("is not able to compile a simple test program".toLowerCase()) &&
err.combinedStd.toLowerCase().includes("nvcc fatal".toLowerCase())))) {
for (const { nvccPath, cudaHomePath } of await getCudaNvccPaths()) {
if (buildOptions.progressLogs)
console.info(getConsoleLogPrefix(true) +
`Trying to compile again with "CUDACXX=${nvccPath}" and "CUDA_PATH=${cudaHomePath}" environment variables`);
try {
return await compileLlamaCpp(buildOptions, {
...compileOptions,
envVars: {
...envVars,
CUDACXX: nvccPath,
"CUDA_PATH": cudaHomePath
},
ignoreWorkarounds: [...ignoreWorkarounds, "cudaArchitecture"]
});
}
catch (err) {
if (buildOptions.progressLogs)
console.error(getConsoleLogPrefix(true, false), err);
}
}
}
else if ((!ignoreWorkarounds.includes("reduceParallelBuildThreads") || !ignoreWorkarounds.includes("singleBuildThread")) &&
(platform === "win" || platform === "linux") &&
err instanceof SpawnError &&
reduceParallelBuildThreads(parallelBuildThreads) !== parallelBuildThreads && (err.combinedStd.toLowerCase().includes("LLVM error : out of memory".toLowerCase()) ||
err.combinedStd.toLowerCase().includes("compiler is out of heap space".toLowerCase()))) {
if (buildOptions.progressLogs) {
if (ignoreWorkarounds.includes("reduceParallelBuildThreads"))
console.info(getConsoleLogPrefix(true) + "Trying to compile again with a single build thread");
else
console.info(getConsoleLogPrefix(true) + "Trying to compile again with reduced parallel build threads");
}
try {
return await compileLlamaCpp(buildOptions, {
...compileOptions,
ignoreWorkarounds: [
...ignoreWorkarounds,
ignoreWorkarounds.includes("reduceParallelBuildThreads")
? "singleBuildThread"
: "reduceParallelBuildThreads"
]
});
}
catch (err) {
if (buildOptions.progressLogs)
console.error(getConsoleLogPrefix(true, false), err);
}
}
console.info("\n" +
getConsoleLogPrefix(true) +
chalk.yellow("To resolve errors related to CUDA compilation, see the CUDA guide: ") +
documentationPageUrls.CUDA);
}
else if (buildOptions.gpu === "vulkan")
console.info("\n" +
getConsoleLogPrefix(true) +
chalk.yellow("To resolve errors related to Vulkan compilation, see the Vulkan guide: ") +
documentationPageUrls.Vulkan);
else if (useWindowsLlvm && !ciMode) {
if (buildOptions.progressLogs)
console.info(getConsoleLogPrefix(true) + "Trying to compile again without LLVM");
try {
return await compileLlamaCpp(buildOptions, {
...compileOptions,
ignoreWorkarounds: [...ignoreWorkarounds, "avoidWindowsLlvm"]
});
}
catch (err) {
if (buildOptions.progressLogs)
console.error(getConsoleLogPrefix(true, false), err);
}
}
throw err;
}
}
export async function getLocalBuildBinaryPath(folderName) {
const binaryPath = path.join(llamaLocalBuildBinsDirectory, folderName, buildConfigType, "llama-addon.node");
const buildMetadataFilePath = path.join(llamaLocalBuildBinsDirectory, folderName, buildConfigType, buildMetadataFileName);
const buildDoneStatusPath = path.join(llamaLocalBuildBinsDirectory, folderName, "buildDone.status");
const [binaryExists, buildMetadataExists, buildDoneStatusExists] = await Promise.all([
fs.pathExists(binaryPath),
fs.pathExists(buildMetadataFilePath),
fs.pathExists(buildDoneStatusPath)
]);
if (binaryExists && buildMetadataExists && buildDoneStatusExists)
return binaryPath;
return null;
}
export async function getLocalBuildBinaryBuildMetadata(folderName) {
const buildMetadataFilePath = path.join(llamaLocalBuildBinsDirectory, folderName, buildConfigType, buildMetadataFileName);
if (!(await fs.pathExists(buildMetadataFilePath)))
throw new Error(`Could not find build metadata file for local build "${folderName}"`);
const buildMetadata = await fs.readJson(buildMetadataFilePath);
return buildMetadata;
}
export async function getPrebuiltBinaryPath(buildOptions, folderName) {
const localPrebuiltBinaryDirectoryPath = path.join(llamaPrebuiltBinsDirectory, folderName);
const binaryPath = await resolvePrebuiltBinaryPath(localPrebuiltBinaryDirectoryPath);
if (binaryPath != null)
return {
binaryPath,
folderName,
folderPath: localPrebuiltBinaryDirectoryPath,
extBackendsPath: undefined
};
const packagePrebuiltBinariesDirectoryPath = await getPrebuiltBinariesPackageDirectoryForBuildOptions(buildOptions);
if (packagePrebuiltBinariesDirectoryPath == null)
return null;
const prebuiltBinariesDirPath = typeof packagePrebuiltBinariesDirectoryPath === "string"
? packagePrebuiltBinariesDirectoryPath
: packagePrebuiltBinariesDirectoryPath.binsDir;
const prebuiltBinariesExtDirPath = typeof packagePrebuiltBinariesDirectoryPath === "string"
? undefined
: packagePrebuiltBinariesDirectoryPath.extBinsDir;
const packagePrebuiltBinaryDirectoryPath = path.join(prebuiltBinariesDirPath, folderName);
const extPackagePrebuiltBinaryDirectoryPath = prebuiltBinariesExtDirPath == null
? undefined
: path.join(prebuiltBinariesExtDirPath, folderName);
const binaryPathFromPackage = await resolvePrebuiltBinaryPath(packagePrebuiltBinaryDirectoryPath);
if (binaryPathFromPackage != null)
return {
binaryPath: binaryPathFromPackage,
folderName,
folderPath: packagePrebuiltBinaryDirectoryPath,
extBackendsPath: extPackagePrebuiltBinaryDirectoryPath
};
return null;
}
export async function getPrebuiltBinaryBuildMetadata(folderPath, folderName) {
const buildMetadataFilePath = path.join(folderPath, buildMetadataFileName);
if (!(await fs.pathExists(buildMetadataFilePath)))
throw new Error(`Could not find build metadata file for prebuilt build "${folderName}"`);
const buildMetadata = await fs.readJson(buildMetadataFilePath);
return buildMetadata;
}
async function moveBuildFilesToResultDir(outDirectory, canCreateReleaseDir = false) {
const binFilesDirPaths = [
path.join(outDirectory, "bin"),
path.join(outDirectory, "llama.cpp", "bin")
];
const compiledResultDirPath = path.join(outDirectory, buildConfigType);
if (!await fs.pathExists(compiledResultDirPath)) {
if (canCreateReleaseDir) {
if (await asyncSome(binFilesDirPaths.map((dirPath) => fs.pathExists(dirPath))))
await fs.ensureDir(compiledResultDirPath);
else
throw new Error(`Could not find ${buildConfigType} directory or any other output directory`);
}
else
throw new Error(`Could not find ${buildConfigType} directory`);
}
for (const binFilesDirPath of binFilesDirPaths) {
if (await fs.pathExists(binFilesDirPath)) {
const itemNames = await fs.readdir(binFilesDirPath);
await Promise.all(itemNames.map((itemName) => (fs.copy(path.join(binFilesDirPath, itemName), path.join(compiledResultDirPath, itemName), {
overwrite: false
}))));
}
}
await applyResultDirFixes(compiledResultDirPath, path.join(outDirectory, "_temp"));
return compiledResultDirPath;
}
async function applyResultDirFixes(resultDirPath, tempDirPath) {
const releaseDirPath = path.join(resultDirPath, buildConfigType);
if (await fs.pathExists(releaseDirPath)) {
await fs.remove(tempDirPath);
await fs.move(releaseDirPath, tempDirPath);
const itemNames = await fs.readdir(tempDirPath);
await Promise.all(itemNames.map((itemName) => (fs.move(path.join(tempDirPath, itemName), path.join(resultDirPath, itemName), {
overwrite: true
}))));
await fs.remove(tempDirPath);
}
// the vulkan-shaders-gen binary is not needed at runtime
const vulkanShadersGenBinary = path.join(resultDirPath, getPlatform() === "win"
? "vulkan-shaders-gen.exe"
: "vulkan-shaders-gen");
await fs.remove(vulkanShadersGenBinary);
}
async function resolvePrebuiltBinaryPath(prebuiltBinaryDirectoryPath) {
const binaryPath = path.join(prebuiltBinaryDirectoryPath, "llama-addon.node");
const buildMetadataFilePath = path.join(prebuiltBinaryDirectoryPath, buildMetadataFileName);
const [binaryExists, buildMetadataExists] = await Promise.all([
fs.pathExists(binaryPath),
fs.pathExists(buildMetadataFilePath)
]);
if (binaryExists && buildMetadataExists)
return binaryPath;
return null;
}
function getPrebuiltBinariesPackageDirectoryForBuildOptions(buildOptions) {
async function getBinariesPathFromModules(moduleImport) {
try {
const [binariesModule, currentModuleVersion] = await Promise.all([
moduleImport(),
getModuleVersion()
]);
const { binsDir, packageVersion } = binariesModule?.getBinsDir?.() ?? {};
if (binsDir == null || packageVersion !== currentModuleVersion)
return null;
return binsDir;
}
catch (err) {
return null;
}
}
async function getBinariesPathFromModulesWithExtModule(moduleImport, extModuleImport) {
const [moduleBinsDir, extModuleBinsDir] = await Promise.all([
getBinariesPathFromModules(moduleImport),
getBinariesPathFromModules(extModuleImport)
]);
if (moduleBinsDir == null)
return null;
else if (extModuleBinsDir == null)
return moduleBinsDir;
return {
binsDir: moduleBinsDir,
extBinsDir: extModuleBinsDir
};
}
/* eslint-disable import/no-unresolved */
if (buildOptions.platform === "mac") {
if (buildOptions.arch === "arm64" && buildOptions.gpu === "metal")
// @ts-ignore
return getBinariesPathFromModules(() => import("@node-llama-cpp/mac-arm64-metal"));
else if (buildOptions.arch === "x64" && buildOptions.gpu === false)
// @ts-ignore
return getBinariesPathFromModules(() => import("@node-llama-cpp/mac-x64"));
}
else if (buildOptions.platform === "linux") {
if (buildOptions.arch === "x64") {
if (buildOptions.gpu === "cuda")
return getBinariesPathFromModulesWithExtModule(
// @ts-ignore
() => import("@node-llama-cpp/linux-x64-cuda"),
// @ts-ignore
() => import("@node-llama-cpp/linux-x64-cuda-ext"));
else if (buildOptions.gpu === "vulkan")
// @ts-ignore
return getBinariesPathFromModules(() => import("@node-llama-cpp/linux-x64-vulkan"));
else if (buildOptions.gpu === false)
// @ts-ignore
return getBinariesPathFromModules(() => import("@node-llama-cpp/linux-x64"));
}
else if (buildOptions.arch === "arm64")
// @ts-ignore
return getBinariesPathFromModules(() => import("@node-llama-cpp/linux-arm64"));
else if (buildOptions.arch === "arm")
// @ts-ignore
return getBinariesPathFromModules(() => import("@node-llama-cpp/linux-armv7l"));
}
else if (buildOptions.platform === "win") {
if (buildOptions.arch === "x64") {
if (buildOptions.gpu === "cuda")
return getBinariesPathFromModulesWithExtModule(
// @ts-ignore
() => import("@node-llama-cpp/win-x64-cuda"),
// @ts-ignore
() => import("@node-llama-cpp/win-x64-cuda-ext"));
else if (buildOptions.gpu === "vulkan")
// @ts-ignore
return getBinariesPathFromModules(() => import("@node-llama-cpp/win-x64-vulkan"));
else if (buildOptions.gpu === false)
// @ts-ignore
return getBinariesPathFromModules(() => import("@node-llama-cpp/win-x64"));
}
else if (buildOptions.arch === "arm64")
// @ts-ignore
return getBinariesPathFromModules(() => import("@node-llama-cpp/win-arm64"));
}
/* eslint-enable import/no-unresolved */
return null;
}
async function getCmakePathArgs() {
if (await hasBuiltinCmake())
return [];
const cmakePath = await getCmakePath();
if (cmakePath == null)
return [];
return ["--cmake-path", cmakePath];
}
async function getToolchainFileForArch(targetArch, windowsLlvmSupport = false) {
let toolchainPrefix = "";
if (process.platform === "win32" && process.arch === "arm64") {
// a toolchain is needed to cross-compile to arm64 on Windows, and to compile on arm64 on Windows
}
else if (process.platform === "win32" && process.arch === "x64" && targetArch === "x64" && windowsLlvmSupport) {
toolchainPrefix = "llvm.";
}
else if (process.arch === targetArch)
return null;
const platform = process.platform;
const hostArch = process.arch;
const toolchainFilename = `${toolchainPrefix}${platform}.host-${hostArch}.target-${targetArch}.cmake`;
const filePath = path.join(llamaToolchainsDirectory, toolchainFilename);
if (await fs.pathExists(filePath))
return path.resolve(filePath);
return null;
}
function getCmakeGeneratorArgs(targetPlatform, targetArch, windowsLlvmSupport) {
if (targetPlatform === "win" && targetArch === "arm64")
return ["--generator", "Ninja Multi-Config"];
else if (windowsLlvmSupport && targetPlatform === "win" && process.arch === "x64" && targetArch === "x64")
return ["--generator", "Ninja Multi-Config"];
return [];
}
function getParallelBuildThreadsToUse(platform, gpu, ciMode = false) {
const cpuCount = os.cpus().length;
if (ciMode && platform === "win" && gpu === "cuda" && cpuCount === 4)
return 3; // workaround for `compiler is out of heap space` error on GitHub Actions on Windows when building with CUDA
if (cpuCount <= 4)
return cpuCount;
if (platform === "mac" && process.arch === "arm64")
return cpuCount - 1;
return cpuCount - 2;
}
function reduceParallelBuildThreads(originalParallelBuildThreads) {
return Math.max(1, Math.round(originalParallelBuildThreads / 2));
}
function isCmakeValueOff(value) {
return value === "OFF" || value === "0";
}
function areWindowsBuildToolsCapableForLlvmBuild(detectedBuildTools) {
return detectedBuildTools.hasLlvm && detectedBuildTools.hasNinja && detectedBuildTools.hasLibExe;
}
//# sourceMappingURL=compileLLamaCpp.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,18 @@
import { BinaryPlatform } from "./getPlatform.js";
export declare function detectAvailableComputeLayers({ platform }?: {
platform?: BinaryPlatform;
}): Promise<{
cuda: {
hasNvidiaDriver: boolean;
hasCudaRuntime: boolean;
};
vulkan: boolean;
metal: boolean;
}>;
export declare function getCudaNvccPaths({ platform }?: {
platform?: BinaryPlatform;
}): Promise<{
nvccPath: string;
cudaHomePath: string;
}[]>;
export declare function getWindowsProgramFilesPaths(): Promise<string[]>;

View File

@@ -0,0 +1,311 @@
import process from "process";
import path from "path";
import fs from "fs-extra";
import semver from "semver";
import { getConsoleLogPrefix } from "../../utils/getConsoleLogPrefix.js";
import { getPlatform } from "./getPlatform.js";
import { hasFileInPath } from "./hasFileInPath.js";
import { asyncSome } from "./asyncSome.js";
import { asyncEvery } from "./asyncEvery.js";
export async function detectAvailableComputeLayers({ platform = getPlatform() } = {}) {
const [cuda, vulkan, metal] = await Promise.all([
detectCudaSupport({ platform }),
detectVulkanSupport({ platform }),
detectMetalSupport({ platform })
]);
return {
cuda,
vulkan,
metal
};
}
async function detectCudaSupport({ platform }) {
if (platform === "win") {
const librarySearchPaths = (await getCudaInstallationPaths({ platform }))
.flatMap((cudaInstallationPath) => [cudaInstallationPath, path.join(cudaInstallationPath, "bin")]);
const windir = getWindir();
const [hasNvidiaDriver, hasCudaRuntime] = await Promise.all([
asyncSome([
hasFileInPath("nvml.dll"),
fs.pathExists(path.join(windir, "System32", "nvml.dll"))
]),
asyncEvery([
asyncSome([
hasFileInPath("cudart64_110.dll", librarySearchPaths),
hasFileInPath("cudart64_11.dll", librarySearchPaths),
hasFileInPath("cudart64_12.dll", librarySearchPaths),
hasFileInPath("cudart64_13.dll", librarySearchPaths) // for when the next version comes out
]),
asyncSome([
hasFileInPath("cublas64_11.dll", librarySearchPaths),
hasFileInPath("cublas64_12.dll", librarySearchPaths),
hasFileInPath("cublas64_13.dll", librarySearchPaths) // for when the next version comes out
]),
asyncSome([
hasFileInPath("cublasLt64_11.dll", librarySearchPaths),
hasFileInPath("cublasLt64_12.dll", librarySearchPaths),
hasFileInPath("cublasLt64_13.dll", librarySearchPaths) // for when the next version comes out
])
])
]);
return {
hasNvidiaDriver,
hasCudaRuntime
};
}
else if (platform === "linux") {
const cudaLibraryPaths = await getLinuxCudaLibraryPaths();
const librarySearchPaths = [
process.env.LD_LIBRARY_PATH,
process.env.CUDA_PATH,
"/usr/lib",
"/usr/lib64",
"/usr/lib/x86_64-linux-gnu",
"/usr/lib/aarch64-linux-gnu",
"/usr/lib/armv7l-linux-gnu",
...cudaLibraryPaths
];
const [hasNvidiaDriver, hasCudaRuntime] = await Promise.all([
asyncSome([
hasFileInPath("libnvidia-ml.so", librarySearchPaths),
hasFileInPath("libnvidia-ml.so.1", librarySearchPaths)
]),
asyncEvery([
asyncSome([
hasFileInPath("libcuda.so", librarySearchPaths),
hasFileInPath("libcuda.so.1", librarySearchPaths)
]),
asyncSome([
hasFileInPath("libcudart.so", librarySearchPaths),
hasFileInPath("libcudart.so.11", librarySearchPaths),
hasFileInPath("libcudart.so.12", librarySearchPaths),
hasFileInPath("libcudart.so.13", librarySearchPaths) // for when the next version comes out
]),
asyncSome([
hasFileInPath("libcublas.so", librarySearchPaths),
hasFileInPath("libcublas.so.11", librarySearchPaths),
hasFileInPath("libcublas.so.12", librarySearchPaths),
hasFileInPath("libcublas.so.13", librarySearchPaths) // for when the next version comes out
]),
asyncSome([
hasFileInPath("libcublasLt.so", librarySearchPaths),
hasFileInPath("libcublasLt.so.11", librarySearchPaths),
hasFileInPath("libcublasLt.so.12", librarySearchPaths),
hasFileInPath("libcublasLt.so.13", librarySearchPaths) // for when the next version comes out
])
])
]);
return {
hasNvidiaDriver,
hasCudaRuntime
};
}
return {
hasNvidiaDriver: false,
hasCudaRuntime: false
};
}
async function detectVulkanSupport({ platform }) {
if (platform === "win") {
const windir = getWindir();
return await asyncSome([
hasFileInPath("vulkan-1.dll"),
fs.pathExists(path.join(windir, "System32", "vulkan-1.dll")),
fs.pathExists(path.join(windir, "SysWOW64", "vulkan-1.dll"))
]);
}
else if (platform === "linux") {
const librarySearchPaths = [
process.env.LD_LIBRARY_PATH,
"/usr/lib",
"/usr/lib64",
"/usr/lib/x86_64-linux-gnu",
"/usr/lib/aarch64-linux-gnu",
"/usr/lib/armv7l-linux-gnu",
(process.env.PREFIX != null && process.env.PREFIX?.toLowerCase()?.includes?.("termux"))
? `${process.env.PREFIX}/usr/lib`
: undefined
];
return await asyncSome([
hasFileInPath("libvulkan.so", librarySearchPaths),
hasFileInPath("libvulkan.so.1", librarySearchPaths)
]);
}
else if (platform === "mac") {
return await asyncSome([
hasFileInPath("libvulkan.dylib"),
hasFileInPath("libvulkan.dylib.1")
]);
}
return false;
}
async function detectMetalSupport({ platform }) {
return platform === "mac";
}
async function getLinuxCudaLibraryPaths() {
const res = [];
try {
for (const cudaInstallationPath of await getCudaInstallationPaths({ platform: "linux" })) {
const cudaTargetsFolder = `${cudaInstallationPath}/targets`;
if (!(await fs.pathExists(cudaTargetsFolder)))
continue;
for (const cudaTargetFolderName of await fs.readdir(cudaTargetsFolder)) {
res.push(`${cudaTargetsFolder}/${cudaTargetFolderName}/lib`, `${cudaTargetsFolder}/${cudaTargetFolderName}/lib/stubs`);
}
}
}
catch (err) {
console.error(getConsoleLogPrefix() + 'Failed to search "/usr/local/" for CUDA library paths', err);
}
return res;
}
async function getCudaInstallationPaths({ platform }) {
if (platform === "win") {
try {
const programFilesPaths = await getWindowsProgramFilesPaths();
const potentialCudaInstallationsContainerPaths = programFilesPaths
.map((programFilesPath) => `${programFilesPath}/NVIDIA GPU Computing Toolkit/CUDA`);
const cudaInstallationsContainerPaths = (await Promise.all(potentialCudaInstallationsContainerPaths.map(async (potentialCudaInstallationsContainerPath) => {
if (await fs.pathExists(potentialCudaInstallationsContainerPath))
return potentialCudaInstallationsContainerPath;
return null;
}))).filter((path) => path != null);
const potentialCudaInstallations = (await Promise.all(cudaInstallationsContainerPaths.map(async (cudaInstallationsContainerPath) => {
const cudaFolderPrefix = "v";
return (await fs.pathExists(cudaInstallationsContainerPath)
? await fs.readdir(cudaInstallationsContainerPath)
: [])
.filter((installationFolderName) => installationFolderName.toLowerCase()
.startsWith(cudaFolderPrefix))
.sort((a, b) => {
const aVersion = a.slice(cudaFolderPrefix.length);
const bVersion = b.slice(cudaFolderPrefix.length);
try {
const aVersionValid = semver.valid(semver.coerce(aVersion));
const bVersionValid = semver.valid(semver.coerce(bVersion));
if (aVersionValid && bVersionValid)
return semver.compare(aVersionValid, bVersionValid);
else if (aVersionValid)
return -1;
else if (bVersionValid)
return 1;
else
return 0;
}
catch (err) {
return 0;
}
})
.reverse()
.map((installationFolderName) => `${cudaInstallationsContainerPath}/${installationFolderName}`);
}))).flat();
if (process.env.CUDA_PATH != null && process.env.CUDA_PATH !== "")
potentialCudaInstallations.unshift(process.env.CUDA_PATH);
return (await Promise.all(potentialCudaInstallations.map(async (cudaFolder) => {
if (await fs.pathExists(cudaFolder))
return cudaFolder;
return null;
}))).filter((cudaFolder) => cudaFolder != null);
}
catch (err) {
console.error(getConsoleLogPrefix() + 'Failed to search "Program Files" for CUDA installations', err);
}
return [];
}
else if (platform === "linux") {
const res = [];
try {
const usrLocal = "/usr/local";
const cudaFolderPrefix = "cuda-";
const potentialCudaFolders = (await fs.pathExists(usrLocal)
? await fs.readdir(usrLocal)
: [])
.filter((usrLocalFolderName) => usrLocalFolderName.toLowerCase().startsWith(cudaFolderPrefix))
.sort((a, b) => {
const aVersion = a.slice(cudaFolderPrefix.length);
const bVersion = b.slice(cudaFolderPrefix.length);
try {
const aVersionValid = semver.valid(semver.coerce(aVersion));
const bVersionValid = semver.valid(semver.coerce(bVersion));
if (aVersionValid && bVersionValid)
return semver.compare(aVersionValid, bVersionValid);
else if (aVersionValid)
return -1;
else if (bVersionValid)
return 1;
else
return 0;
}
catch (err) {
return 0;
}
})
.reverse()
.map((usrLocalFolderName) => `${usrLocal}/${usrLocalFolderName}`);
potentialCudaFolders.unshift(`${usrLocal}/cuda`);
if (process.env.CUDA_PATH != null && process.env.CUDA_PATH !== "")
potentialCudaFolders.unshift(process.env.CUDA_PATH);
for (const cudaFolder of potentialCudaFolders) {
const cudaTargetsFolder = `${cudaFolder}/targets`;
if (!(await fs.pathExists(cudaTargetsFolder)))
continue;
res.push(cudaFolder);
}
}
catch (err) {
console.error(getConsoleLogPrefix() + 'Failed to search "/usr/local/" for CUDA installations', err);
}
return res;
}
return [];
}
export async function getCudaNvccPaths({ platform = getPlatform() } = {}) {
const cudaInstallationPaths = await getCudaInstallationPaths({ platform });
const nvccPotentialPaths = cudaInstallationPaths
.map((cudaInstallationPath) => {
if (platform === "win")
return {
nvccPath: path.join(cudaInstallationPath, "bin", "nvcc.exe"),
cudaHomePath: cudaInstallationPath
};
return {
nvccPath: path.join(cudaInstallationPath, "bin", "nvcc"),
cudaHomePath: cudaInstallationPath
};
});
try {
const resolvedPaths = await Promise.all(nvccPotentialPaths.map(async ({ nvccPath, cudaHomePath }) => {
if (await fs.pathExists(nvccPath))
return { nvccPath, cudaHomePath };
return null;
}));
return resolvedPaths.filter((resolvedPath) => resolvedPath != null);
}
catch (err) {
console.error(getConsoleLogPrefix() + `Failed to search for "nvcc${platform === "win" ? ".exe" : ""}" in CUDA installation paths`, err);
}
return [];
}
function getWindir() {
return process.env.windir || process.env.WINDIR || process.env.SystemRoot || process.env.systemroot || process.env.SYSTEMROOT ||
"C:\\Windows";
}
export async function getWindowsProgramFilesPaths() {
const potentialPaths = await Promise.all([
process.env["ProgramFiles(Arm)"],
process.env.ProgramFiles,
process.env["ProgramFiles(x86)"],
`${process.env.SystemDrive ?? "C:"}\\Program Files (Arm)`,
`${process.env.SystemDrive ?? "C:"}\\Program Files`,
`${process.env.SystemDrive ?? "C:"}\\Program Files (x86)`
]
.map(async (programFilesPath) => {
if (programFilesPath == null)
return null;
if (await fs.pathExists(programFilesPath))
return programFilesPath;
return null;
}));
return Array.from(new Set(potentialPaths.filter((potentialPath) => potentialPath != null)));
}
//# sourceMappingURL=detectAvailableComputeLayers.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
/**
* On platforms other than Windows, this function will return an empty array
* @returns Visual Studio edition installation paths - the paths are ordered from the most recent version to the oldest
*/
export declare function getWindowsVisualStudioEditionPaths(): Promise<{
vsEditionPaths: string[];
programFilesPaths: string[];
}>;
export declare function detectWindowsBuildTools(targetArch?: typeof process.arch): Promise<{
hasCmake: boolean;
hasNinja: boolean;
hasLlvm: boolean;
hasLibExe: boolean;
}>;

View File

@@ -0,0 +1,149 @@
import path from "path";
import fs from "fs-extra";
import { getWindowsProgramFilesPaths } from "./detectAvailableComputeLayers.js";
import { asyncSome } from "./asyncSome.js";
import { asyncEvery } from "./asyncEvery.js";
import { getPlatform } from "./getPlatform.js";
/**
* On platforms other than Windows, this function will return an empty array
* @returns Visual Studio edition installation paths - the paths are ordered from the most recent version to the oldest
*/
export async function getWindowsVisualStudioEditionPaths() {
const platform = getPlatform();
if (platform !== "win")
return {
vsEditionPaths: [],
programFilesPaths: []
};
const programFilesPaths = await getWindowsProgramFilesPaths();
const potentialVisualStudioPaths = programFilesPaths
.map((programFilesPath) => `${programFilesPath}/Microsoft Visual Studio`);
const versionPaths = (await Promise.all(potentialVisualStudioPaths.map(async (vsPath) => {
if (await fs.pathExists(vsPath)) {
const versions = await fs.readdir(vsPath, { withFileTypes: true });
return versions
.filter((dirent) => dirent.isDirectory())
.map((dirent) => dirent.name)
.sort((a, b) => {
const aNumber = parseInt(a);
const bNumber = parseInt(b);
if (Number.isFinite(aNumber) && Number.isFinite(bNumber))
return bNumber - aNumber;
else if (Number.isFinite(aNumber))
return -1;
else if (Number.isFinite(bNumber))
return 1;
return 0;
})
.map((version) => path.join(vsPath, version));
}
return [];
}))).flat();
const vsEditionPaths = (await Promise.all(versionPaths.map(async (versionPath) => {
const editions = await fs.readdir(versionPath, { withFileTypes: true });
return editions
.filter((dirent) => dirent.isDirectory())
.map((edition) => path.join(versionPath, edition.name));
}))).flat();
return {
vsEditionPaths,
programFilesPaths
};
}
export async function detectWindowsBuildTools(targetArch = process.arch) {
try {
const currentArch = process.arch;
const { vsEditionPaths, programFilesPaths } = await getWindowsVisualStudioEditionPaths();
if (vsEditionPaths.length === 0 && programFilesPaths.length === 0)
return {
hasCmake: false,
hasNinja: false,
hasLlvm: false,
hasLibExe: false
};
const programDataPaths = [
process.env["ProgramData"]
].filter((programDataPath) => programDataPath != null);
const msvcPaths = (await Promise.all(vsEditionPaths.map(async (editionPath) => {
const msvcVersionsPath = path.join(editionPath, "VC", "Tools", "MSVC");
if (await fs.pathExists(msvcVersionsPath)) {
const msvcVersions = await fs.readdir(msvcVersionsPath);
return msvcVersions
.sort((a, b) => {
const aNumber = parseInt(a);
const bNumber = parseInt(b);
if (Number.isFinite(aNumber) && Number.isFinite(bNumber))
return bNumber - aNumber;
else if (Number.isFinite(aNumber))
return -1;
else if (Number.isFinite(bNumber))
return 1;
return 0;
})
.map((msvcVersion) => path.join(msvcVersionsPath, msvcVersion));
}
return [];
}))).flat();
const potentialCmakePaths = [
...programFilesPaths.map((programFilesPath) => path.join(programFilesPath, "CMake", "bin", "cmake.exe")),
...vsEditionPaths.map((editionPath) => (path.join(editionPath, "Common7", "IDE", "CommonExtensions", "Microsoft", "CMake", "CMake", "bin", "cmake.exe")))
];
const potentialNinjaPaths = [
...programDataPaths.map((programDataPath) => path.join(programDataPath, "chocolatey", "bin", "ninja.exe")),
...vsEditionPaths.map((editionPath) => (path.join(editionPath, "Common7", "IDE", "CommonExtensions", "Microsoft", "CMake", "Ninja", "ninja.exe")))
];
const potentialLlvmPaths = [
...programFilesPaths.map((programFilesPath) => path.join(programFilesPath, "LLVM", "bin")),
...vsEditionPaths.map((editionPath) => {
if (currentArch === "x64")
return path.join(editionPath, "VC", "Tools", "Llvm", "x64", "bin");
else if (currentArch === "arm64")
return path.join(editionPath, "VC", "Tools", "Llvm", "ARM64", "bin");
return path.join(editionPath, "VC", "Tools", "Llvm", "bin");
})
];
const potentialLibExePaths = msvcPaths.map((msvcPath) => {
const hostArchDirName = currentArch === "x64"
? "Hostx64"
: currentArch === "arm64"
? "Hostarm64"
: "_";
const targetArchDirName = targetArch === "x64"
? "x64"
: targetArch === "arm64"
? "arm64"
: "_";
return path.join(msvcPath, "bin", hostArchDirName, targetArchDirName, "lib.exe");
});
const [hasCmake, hasNinja, hasLibExe, hasLlvm] = await Promise.all([
asyncSome(potentialCmakePaths.map((cmakePath) => fs.pathExists(cmakePath))),
asyncSome(potentialNinjaPaths.map((ninjaPath) => fs.pathExists(ninjaPath))),
asyncSome(potentialLibExePaths.map((libExePath) => fs.pathExists(libExePath))),
asyncSome(potentialLlvmPaths.map((llvmPath) => isLlvmPathValid(llvmPath)))
]);
return {
hasCmake,
hasNinja,
hasLlvm,
hasLibExe
};
}
catch (err) {
return {
hasCmake: false,
hasNinja: false,
hasLlvm: false,
hasLibExe: false
};
}
}
async function isLlvmPathValid(llvmPath) {
if (!(await fs.pathExists(llvmPath)))
return false;
return await asyncEvery([
fs.pathExists(path.join(llvmPath, "clang.exe")),
fs.pathExists(path.join(llvmPath, "clang++.exe")),
fs.pathExists(path.join(llvmPath, "llvm-rc.exe"))
]);
}
//# sourceMappingURL=detectBuildTools.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
import { BinaryPlatform } from "./getPlatform.js";
export declare function detectGlibc({ platform }: {
platform: BinaryPlatform;
}): Promise<boolean>;

View File

@@ -0,0 +1,46 @@
import process from "process";
import { asyncEvery } from "./asyncEvery.js";
import { asyncSome } from "./asyncSome.js";
import { hasFileInPath } from "./hasFileInPath.js";
export async function detectGlibc({ platform }) {
if (platform === "linux") {
const librarySearchPaths = [
process.env.LD_LIBRARY_PATH,
"/lib",
"/lib64",
"/usr/lib",
"/usr/lib64",
"/usr/lib/x86_64-linux-gnu",
"/usr/lib/aarch64-linux-gnu",
"/usr/lib/armv7l-linux-gnu"
];
return await asyncEvery([
asyncSome([
hasFileInPath("libc.so", librarySearchPaths),
hasFileInPath("libc.so.5", librarySearchPaths),
hasFileInPath("libc.so.6", librarySearchPaths),
hasFileInPath("libc.so.7", librarySearchPaths) // for when the next version comes out
]),
asyncSome([
hasFileInPath("ld-linux.so", librarySearchPaths),
hasFileInPath("ld-linux.so.1", librarySearchPaths),
hasFileInPath("ld-linux.so.2", librarySearchPaths),
hasFileInPath("ld-linux.so.3", librarySearchPaths), // for when the next version comes out
hasFileInPath("ld-linux-x86-64.so", librarySearchPaths),
hasFileInPath("ld-linux-x86-64.so.1", librarySearchPaths),
hasFileInPath("ld-linux-x86-64.so.2", librarySearchPaths),
hasFileInPath("ld-linux-x86-64.so.3", librarySearchPaths), // for when the next version comes out
hasFileInPath("ld-linux-aarch64.so", librarySearchPaths),
hasFileInPath("ld-linux-aarch64.so.1", librarySearchPaths),
hasFileInPath("ld-linux-aarch64.so.2", librarySearchPaths),
hasFileInPath("ld-linux-aarch64.so.3", librarySearchPaths), // for when the next version comes out
hasFileInPath("ld-linux-armv7l.so", librarySearchPaths),
hasFileInPath("ld-linux-armv7l.so.1", librarySearchPaths),
hasFileInPath("ld-linux-armv7l.so.2", librarySearchPaths),
hasFileInPath("ld-linux-armv7l.so.3", librarySearchPaths) // for when the next version comes out
])
]);
}
return false;
}
//# sourceMappingURL=detectGlibc.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"detectGlibc.js","sourceRoot":"","sources":["../../../src/bindings/utils/detectGlibc.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,EAC9B,QAAQ,EAGX;IACG,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACvB,MAAM,kBAAkB,GAAG;YACvB,OAAO,CAAC,GAAG,CAAC,eAAe;YAC3B,MAAM;YACN,QAAQ;YACR,UAAU;YACV,YAAY;YACZ,2BAA2B;YAC3B,4BAA4B;YAC5B,2BAA2B;SAC9B,CAAC;QAEF,OAAO,MAAM,UAAU,CAAC;YACpB,SAAS,CAAC;gBACN,aAAa,CAAC,SAAS,EAAE,kBAAkB,CAAC;gBAC5C,aAAa,CAAC,WAAW,EAAE,kBAAkB,CAAC;gBAC9C,aAAa,CAAC,WAAW,EAAE,kBAAkB,CAAC;gBAC9C,aAAa,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC,sCAAsC;aACxF,CAAC;YACF,SAAS,CAAC;gBACN,aAAa,CAAC,aAAa,EAAE,kBAAkB,CAAC;gBAChD,aAAa,CAAC,eAAe,EAAE,kBAAkB,CAAC;gBAClD,aAAa,CAAC,eAAe,EAAE,kBAAkB,CAAC;gBAClD,aAAa,CAAC,eAAe,EAAE,kBAAkB,CAAC,EAAE,sCAAsC;gBAC1F,aAAa,CAAC,oBAAoB,EAAE,kBAAkB,CAAC;gBACvD,aAAa,CAAC,sBAAsB,EAAE,kBAAkB,CAAC;gBACzD,aAAa,CAAC,sBAAsB,EAAE,kBAAkB,CAAC;gBACzD,aAAa,CAAC,sBAAsB,EAAE,kBAAkB,CAAC,EAAE,sCAAsC;gBACjG,aAAa,CAAC,qBAAqB,EAAE,kBAAkB,CAAC;gBACxD,aAAa,CAAC,uBAAuB,EAAE,kBAAkB,CAAC;gBAC1D,aAAa,CAAC,uBAAuB,EAAE,kBAAkB,CAAC;gBAC1D,aAAa,CAAC,uBAAuB,EAAE,kBAAkB,CAAC,EAAE,sCAAsC;gBAClG,aAAa,CAAC,oBAAoB,EAAE,kBAAkB,CAAC;gBACvD,aAAa,CAAC,sBAAsB,EAAE,kBAAkB,CAAC;gBACzD,aAAa,CAAC,sBAAsB,EAAE,kBAAkB,CAAC;gBACzD,aAAa,CAAC,sBAAsB,EAAE,kBAAkB,CAAC,CAAC,sCAAsC;aACnG,CAAC;SACL,CAAC,CAAC;IACP,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC"}

View File

@@ -0,0 +1,9 @@
import process from "process";
import { BuildGpu } from "../types.js";
import { BinaryPlatform } from "./getPlatform.js";
export declare function getBestComputeLayersAvailable(): Promise<(false | "metal" | "cuda" | "vulkan")[]>;
export declare function detectBestComputeLayersAvailable({ platform, arch, hasCudaWithStaticBinaryBuild }?: {
platform?: BinaryPlatform;
arch?: typeof process.arch;
hasCudaWithStaticBinaryBuild?: boolean;
}): Promise<BuildGpu[]>;

View File

@@ -0,0 +1,29 @@
import process from "process";
import { getPlatform } from "./getPlatform.js";
import { detectAvailableComputeLayers } from "./detectAvailableComputeLayers.js";
let bestComputeLayersAvailablePromise = null;
export async function getBestComputeLayersAvailable() {
if (bestComputeLayersAvailablePromise != null) {
try {
return await bestComputeLayersAvailablePromise;
}
catch (err) { }
}
bestComputeLayersAvailablePromise = detectBestComputeLayersAvailable();
return await bestComputeLayersAvailablePromise;
}
export async function detectBestComputeLayersAvailable({ platform = getPlatform(), arch = process.arch, hasCudaWithStaticBinaryBuild = false } = {}) {
if (platform === "mac" && arch === "arm64")
return ["metal"];
const res = [];
const availableComputeLayers = await detectAvailableComputeLayers({
platform
});
if (availableComputeLayers.cuda.hasNvidiaDriver && (availableComputeLayers.cuda.hasCudaRuntime || hasCudaWithStaticBinaryBuild))
res.push("cuda");
if (availableComputeLayers.vulkan)
res.push("vulkan");
res.push(false);
return res;
}
//# sourceMappingURL=getBestComputeLayersAvailable.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getBestComputeLayersAvailable.js","sourceRoot":"","sources":["../../../src/bindings/utils/getBestComputeLayersAvailable.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAiB,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAC,4BAA4B,EAAC,MAAM,mCAAmC,CAAC;AAE/E,IAAI,iCAAiC,GAA+D,IAAI,CAAC;AACzG,MAAM,CAAC,KAAK,UAAU,6BAA6B;IAC/C,IAAI,iCAAiC,IAAI,IAAI,EAAE,CAAC;QAC5C,IAAI,CAAC;YACD,OAAO,MAAM,iCAAiC,CAAC;QACnD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC,CAAA,CAAC;IACpB,CAAC;IAED,iCAAiC,GAAG,gCAAgC,EAAE,CAAC;IACvE,OAAO,MAAM,iCAAiC,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gCAAgC,CAAC,EACnD,QAAQ,GAAG,WAAW,EAAE,EACxB,IAAI,GAAG,OAAO,CAAC,IAAI,EACnB,4BAA4B,GAAG,KAAK,KAKpC,EAAE;IACF,IAAI,QAAQ,KAAK,KAAK,IAAI,IAAI,KAAK,OAAO;QACtC,OAAO,CAAC,OAAO,CAAC,CAAC;IAErB,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,MAAM,sBAAsB,GAAG,MAAM,4BAA4B,CAAC;QAC9D,QAAQ;KACX,CAAC,CAAC;IAEH,IAAI,sBAAsB,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,cAAc,IAAI,4BAA4B,CAAC;QAC3H,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAErB,IAAI,sBAAsB,CAAC,MAAM;QAC7B,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEvB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEhB,OAAO,GAAG,CAAC;AACf,CAAC"}

View File

@@ -0,0 +1,6 @@
import { BuildOptions } from "../types.js";
export declare function getBuildFolderNameForBuildOptions(buildOptions: BuildOptions): Promise<{
withoutCustomCmakeOptions: string;
withCustomCmakeOptions: string;
binVariant: string;
}>;

View File

@@ -0,0 +1,105 @@
import { hashString } from "../../utils/hashString.js";
import { builtinLlamaCppGitHubRepo, builtinLlamaCppRelease } from "../../config.js";
export async function getBuildFolderNameForBuildOptions(buildOptions) {
const nameParts = [buildOptions.platform, buildOptions.arch];
const binParts = [];
if (buildOptions.gpu !== false) {
nameParts.push(makeStringSafeForPathName(buildOptions.gpu));
binParts.push(makeStringSafeForPathName(buildOptions.gpu.toLowerCase()));
}
if (buildOptions.llamaCpp.repo !== builtinLlamaCppGitHubRepo || buildOptions.llamaCpp.release !== builtinLlamaCppRelease) {
const releaseFolderNamePart = await getFolderNamePartForRelease(buildOptions.llamaCpp.repo, buildOptions.llamaCpp.release);
nameParts.push("release-" + releaseFolderNamePart);
binParts.push(releaseFolderNamePart.replaceAll(" ", "_"));
}
else if (buildOptions.llamaCpp.release !== "latest")
binParts.push(buildOptions.llamaCpp.release);
if (buildOptions.customCmakeOptions.size === 0) {
const name = nameParts.join("-");
return {
withoutCustomCmakeOptions: name,
withCustomCmakeOptions: name,
binVariant: binParts.join(".")
};
}
const cmakeOptionKeys = [...buildOptions.customCmakeOptions.keys()];
cmakeOptionKeys.sort();
const cmakeOptionStringsArray = [];
for (const key of cmakeOptionKeys) {
if (key === "")
continue;
cmakeOptionStringsArray.push(`${encodeURIComponent(key)}=${encodeURIComponent(buildOptions.customCmakeOptions.get(key))}`);
}
const nameWithoutCustomCmakeOptions = nameParts.join("-");
if (cmakeOptionStringsArray.length === 0) {
return {
withoutCustomCmakeOptions: nameWithoutCustomCmakeOptions,
withCustomCmakeOptions: nameWithoutCustomCmakeOptions,
binVariant: binParts.join(".")
};
}
const cmakeOptionsHash = await hashString(cmakeOptionStringsArray.join(";"));
nameParts.push(cmakeOptionsHash);
binParts.push(cmakeOptionsHash.slice(0, 8));
const nameWithCustomCmakeOptions = nameParts.join("-");
return {
withoutCustomCmakeOptions: nameWithoutCustomCmakeOptions,
withCustomCmakeOptions: nameWithCustomCmakeOptions,
binVariant: binParts.join(".")
};
}
async function getFolderNamePartForRelease(repo, release) {
const resParts = [];
let shouldHash = false;
if (repo !== builtinLlamaCppGitHubRepo) {
const [owner, name] = repo.split("/");
if (containsUnsafeCharacters(String(owner)) || containsUnsafeCharacters(String(name))) {
shouldHash = true;
resParts.push(encodeURIComponent(String(owner)) + " " + encodeURIComponent(String(name)));
}
else
resParts.push(String(owner) + " " + String(name));
}
if (containsUnsafeCharacters(release)) {
shouldHash = true;
resParts.push(encodeURIComponent(release));
}
else
resParts.push(release);
const res = resParts.join(" ");
if (shouldHash)
return await hashString(res);
return res;
}
function makeStringSafeForPathName(str) {
let res = "";
for (const char of str) {
if (isCharacterSafe(char))
res += char;
else
res += "_" + char.codePointAt(0).toString(32) + "_";
}
return res;
}
function containsUnsafeCharacters(str) {
for (const char of str) {
if (!isCharacterSafe(char))
return true;
}
return false;
}
function isCharacterSafe(char) {
const unicodeNumber = char.codePointAt(0);
if (unicodeNumber == null)
return false;
if (unicodeNumber >= "a".codePointAt(0) && unicodeNumber <= "z".codePointAt(0))
return true;
else if (unicodeNumber >= "A".codePointAt(0) && unicodeNumber <= "Z".codePointAt(0))
return true;
else if (unicodeNumber >= "0".codePointAt(0) && unicodeNumber <= "9".codePointAt(0))
return true;
else if (char === "-" || char === "_" || char === ".")
return true;
return false;
}
//# sourceMappingURL=getBuildFolderNameForBuildOptions.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getBuildFolderNameForBuildOptions.js","sourceRoot":"","sources":["../../../src/bindings/utils/getBuildFolderNameForBuildOptions.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1 @@
export declare function getCanUsePrebuiltBinaries(): Promise<boolean>;

View File

@@ -0,0 +1,8 @@
import { builtinLlamaCppGitHubRepo, builtinLlamaCppRelease } from "../../config.js";
import { getClonedLlamaCppRepoReleaseInfo } from "./cloneLlamaCppRepo.js";
export async function getCanUsePrebuiltBinaries() {
const clonedLlamaCppRepoReleaseInfo = await getClonedLlamaCppRepoReleaseInfo();
return clonedLlamaCppRepoReleaseInfo == null || (clonedLlamaCppRepoReleaseInfo.tag === builtinLlamaCppRelease &&
clonedLlamaCppRepoReleaseInfo.llamaCppGithubRepo === builtinLlamaCppGitHubRepo);
}
//# sourceMappingURL=getCanUsePrebuiltBinaries.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getCanUsePrebuiltBinaries.js","sourceRoot":"","sources":["../../../src/bindings/utils/getCanUsePrebuiltBinaries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,yBAAyB,EAAE,sBAAsB,EAAC,MAAM,iBAAiB,CAAC;AAClF,OAAO,EAAC,gCAAgC,EAAC,MAAM,wBAAwB,CAAC;AAExE,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC3C,MAAM,6BAA6B,GAAG,MAAM,gCAAgC,EAAE,CAAC;IAE/E,OAAO,6BAA6B,IAAI,IAAI,IAAI,CAC5C,6BAA6B,CAAC,GAAG,KAAK,sBAAsB;QAC5D,6BAA6B,CAAC,kBAAkB,KAAK,yBAAyB,CACjF,CAAC;AACN,CAAC"}

View File

@@ -0,0 +1,2 @@
import { LlamaOptions } from "../getLlama.js";
export declare function getExampleUsageCodeOfGetLlama(getLlamaOptions: LlamaOptions | "lastBuild" | undefined, prefix?: string, wrapWithSeparators?: boolean): string;

View File

@@ -0,0 +1,21 @@
import chalk from "chalk";
import stripAnsi from "strip-ansi";
import { prettyPrintObject } from "../../utils/prettyPrintObject.js";
import { getLlamaFunctionName } from "../getLlama.js";
export function getExampleUsageCodeOfGetLlama(getLlamaOptions, prefix = "", wrapWithSeparators = true) {
let res = prefix + [
chalk.magenta.italic("import "), chalk.whiteBright("{"), chalk.yellow(getLlamaFunctionName), chalk.whiteBright("} "),
chalk.magenta.italic("from "), chalk.green("\"node-llama-cpp\""), chalk.whiteBright(";"),
"\n\n",
chalk.magenta.italic("const "), chalk.whiteBright("llama "), chalk.whiteBright("= "), chalk.magenta.italic("await "), chalk.yellow(getLlamaFunctionName), chalk.whiteBright("("),
getLlamaOptions === undefined ? "" : prettyPrintObject(getLlamaOptions),
chalk.whiteBright(")"), chalk.whiteBright(";")
].join(prefix);
if (wrapWithSeparators) {
const longestLineLength = res.split("\n")
.reduce((max, line) => Math.max(max, stripAnsi(line).length), 0);
res = chalk.blue("-".repeat(longestLineLength)) + "\n" + res + "\n" + chalk.blue("-".repeat(longestLineLength));
}
return res;
}
//# sourceMappingURL=getExampleUsageCodeOfGetLlama.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getExampleUsageCodeOfGetLlama.js","sourceRoot":"","sources":["../../../src/bindings/utils/getExampleUsageCodeOfGetLlama.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAC,oBAAoB,EAAe,MAAM,gBAAgB,CAAC;AAElE,MAAM,UAAU,6BAA6B,CAAC,eAAuD,EAAE,SAAiB,EAAE,EAAE,qBAA8B,IAAI;IAC1J,IAAI,GAAG,GAAG,MAAM,GAAG;QACf,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC;QACpH,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC;QACxF,MAAM;QACN,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC;QAChL,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,eAAe,CAAC;QACvE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC;KACjD,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEf,IAAI,kBAAkB,EAAE,CAAC;QACrB,MAAM,iBAAiB,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;aACpC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QACrE,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACpH,CAAC;IAED,OAAO,GAAG,CAAC;AACf,CAAC"}

View File

@@ -0,0 +1,12 @@
import process from "process";
import { BuildGpu } from "../types.js";
import { LlamaOptions } from "../getLlama.js";
import { BinaryPlatform } from "./getPlatform.js";
export declare function getGpuTypesToUseForOption(gpu: Required<LlamaOptions>["gpu"], { platform, arch }?: {
platform?: BinaryPlatform;
arch?: typeof process.arch;
}): Promise<BuildGpu[]>;
export declare function resolveValidGpuOptionForPlatform(gpu: BuildGpu | "auto", { platform, arch }: {
platform: BinaryPlatform;
arch: typeof process.arch;
}): false | "metal" | "cuda" | "vulkan" | "auto";

View File

@@ -0,0 +1,39 @@
import process from "process";
import { buildGpuOptions } from "../types.js";
import { getPlatform } from "./getPlatform.js";
import { getBestComputeLayersAvailable } from "./getBestComputeLayersAvailable.js";
export async function getGpuTypesToUseForOption(gpu, { platform = getPlatform(), arch = process.arch } = {}) {
const resolvedGpuOption = typeof gpu === "object"
? gpu.type
: gpu;
function withExcludedGpuTypesRemoved(gpuTypes) {
const resolvedExcludeTypes = typeof gpu === "object"
? new Set(gpu.exclude ?? [])
: new Set();
return gpuTypes.filter((gpuType) => !resolvedExcludeTypes.has(gpuType));
}
const resolvedGpu = resolveValidGpuOptionForPlatform(resolvedGpuOption, {
platform,
arch
});
if (resolvedGpu === "auto") {
if (arch === process.arch)
return withExcludedGpuTypesRemoved(await getBestComputeLayersAvailable());
return withExcludedGpuTypesRemoved([false]);
}
return withExcludedGpuTypesRemoved([resolvedGpu]);
}
export function resolveValidGpuOptionForPlatform(gpu, { platform, arch }) {
if (gpu == null)
return "auto";
else if (platform === "mac") {
if (arch !== "x64" && gpu === "cuda")
return "auto";
}
else if (gpu === "metal")
return "auto";
if (buildGpuOptions.includes(gpu))
return gpu;
return "auto";
}
//# sourceMappingURL=getGpuTypesToUseForOption.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getGpuTypesToUseForOption.js","sourceRoot":"","sources":["../../../src/bindings/utils/getGpuTypesToUseForOption.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAW,eAAe,EAAC,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAiB,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAC,6BAA6B,EAAC,MAAM,oCAAoC,CAAC;AAEjF,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,GAAkC,EAAE,EAChF,QAAQ,GAAG,WAAW,EAAE,EACxB,IAAI,GAAG,OAAO,CAAC,IAAI,KAInB,EAAE;IACF,MAAM,iBAAiB,GAAG,OAAO,GAAG,KAAK,QAAQ;QAC7C,CAAC,CAAC,GAAG,CAAC,IAAI;QACV,CAAC,CAAC,GAAG,CAAC;IAEV,SAAS,2BAA2B,CAAC,QAAoB;QACrD,MAAM,oBAAoB,GAAG,OAAO,GAAG,KAAK,QAAQ;YAChD,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;YAC5B,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC;QAEhB,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,WAAW,GAAG,gCAAgC,CAAC,iBAAiB,EAAE;QACpE,QAAQ;QACR,IAAI;KACP,CAAC,CAAC;IAEH,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,OAAO,CAAC,IAAI;YACrB,OAAO,2BAA2B,CAAC,MAAM,6BAA6B,EAAE,CAAC,CAAC;QAE9E,OAAO,2BAA2B,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,2BAA2B,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,gCAAgC,CAAC,GAAsB,EAAE,EACrE,QAAQ,EACR,IAAI,EAIP;IACG,IAAI,GAAG,IAAI,IAAI;QACX,OAAO,MAAM,CAAC;SACb,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;QAC1B,IAAI,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM;YAChC,OAAO,MAAM,CAAC;IACtB,CAAC;SAAM,IAAI,GAAG,KAAK,OAAO;QACtB,OAAO,MAAM,CAAC;IAElB,IAAI,eAAe,CAAC,QAAQ,CAAC,GAAuC,CAAC;QACjE,OAAO,GAAG,CAAC;IAEf,OAAO,MAAM,CAAC;AAClB,CAAC"}

View File

@@ -0,0 +1,9 @@
export type LinuxDistroInfo = Awaited<ReturnType<typeof getLinuxDistroInfo>>;
export declare function getLinuxDistroInfo(): Promise<{
name: string;
id: string;
version: string;
versionCodename: string;
prettyName: string;
}>;
export declare function isDistroAlpineLinux(linuxDistroInfo: LinuxDistroInfo): Promise<boolean>;

View File

@@ -0,0 +1,46 @@
import fs from "fs-extra";
const osReleasePaths = [
"/etc/os-release",
"/usr/lib/os-release"
];
export async function getLinuxDistroInfo() {
const osReleaseInfo = await getOsReleaseInfo();
return {
name: osReleaseInfo.get("name") ?? "",
id: osReleaseInfo.get("id") ?? "",
version: osReleaseInfo.get("version_id") ?? osReleaseInfo.get("version") ?? "",
versionCodename: osReleaseInfo.get("version_codename") ?? "",
prettyName: osReleaseInfo.get("pretty_name") ?? ""
};
}
export async function isDistroAlpineLinux(linuxDistroInfo) {
return linuxDistroInfo.id === "alpine" || linuxDistroInfo.name.toLowerCase().startsWith("alpine") ||
linuxDistroInfo.prettyName.toLowerCase().startsWith("alpine");
}
async function getOsReleaseInfo() {
for (const osReleasePath of osReleasePaths) {
try {
if (!(await fs.pathExists(osReleasePath)))
continue;
const osReleaseFile = await fs.readFile(osReleasePath, "utf8");
const res = new Map();
for (const line of osReleaseFile.split("\n")) {
const equalsSignIndex = line.indexOf("=");
// ignore lines with no key
if (equalsSignIndex < 1)
continue;
const key = line.slice(0, equalsSignIndex).toLowerCase();
let value = line.slice(equalsSignIndex + 1);
if (value.startsWith('"') && value.endsWith('"'))
value = value.slice(1, -1);
res.set(key, value);
}
return res;
}
catch (err) {
continue;
}
}
return new Map();
}
//# sourceMappingURL=getLinuxDistroInfo.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getLinuxDistroInfo.js","sourceRoot":"","sources":["../../../src/bindings/utils/getLinuxDistroInfo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAE1B,MAAM,cAAc,GAAG;IACnB,iBAAiB;IACjB,qBAAqB;CACf,CAAC;AAGX,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACpC,MAAM,aAAa,GAAG,MAAM,gBAAgB,EAAE,CAAC;IAE/C,OAAO;QACH,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE;QACrC,EAAE,EAAE,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;QACjC,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE;QAC9E,eAAe,EAAE,aAAa,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,EAAE;QAC5D,UAAU,EAAE,aAAa,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE;KACrD,CAAC;AACN,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,eAAgC;IACtE,OAAO,eAAe,CAAC,EAAE,KAAK,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAC7F,eAAe,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AACtE,CAAC;AAED,KAAK,UAAU,gBAAgB;IAC3B,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;QACzC,IAAI,CAAC;YACD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;gBACrC,SAAS;YAEb,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;YAE/D,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;YACtC,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3C,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAE1C,2BAA2B;gBAC3B,IAAI,eAAe,GAAG,CAAC;oBACnB,SAAS;gBAEb,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC;gBACzD,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;gBAE5C,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;oBAC5C,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBAE/B,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACxB,CAAC;YAED,OAAO,GAAG,CAAC;QACf,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,SAAS;QACb,CAAC;IACL,CAAC;IAED,OAAO,IAAI,GAAG,EAAkB,CAAC;AACrC,CAAC"}

View File

@@ -0,0 +1,13 @@
import { LlamaGpuType } from "../types.js";
/**
* Get the list of GPU types that can be used with `getLlama` on the current machine.
*
* When passing `"supported"`, only the GPU types that have the
* necessary libraries and drivers installed on the current machine will be returned.
* All of these GPU types have prebuilt binaries for the current platform and architecture.
*
* When passing `"allValid"`, all GPU types that are compatible with the current OS and architecture will be returned.
* Some of these GPU types may not have prebuilt binaries for the current platform and architecture,
* as some of them are inadvisable for the current machine (like CUDA on an x64 Mac machine).
*/
export declare function getLlamaGpuTypes(include: "supported" | "allValid"): Promise<LlamaGpuType[]>;

View File

@@ -0,0 +1,34 @@
import process from "process";
import { getGpuTypesToUseForOption } from "./getGpuTypesToUseForOption.js";
import { getPlatform } from "./getPlatform.js";
/**
* Get the list of GPU types that can be used with `getLlama` on the current machine.
*
* When passing `"supported"`, only the GPU types that have the
* necessary libraries and drivers installed on the current machine will be returned.
* All of these GPU types have prebuilt binaries for the current platform and architecture.
*
* When passing `"allValid"`, all GPU types that are compatible with the current OS and architecture will be returned.
* Some of these GPU types may not have prebuilt binaries for the current platform and architecture,
* as some of them are inadvisable for the current machine (like CUDA on an x64 Mac machine).
*/
export async function getLlamaGpuTypes(include) {
const platform = getPlatform();
const arch = process.arch;
if (include === "supported") {
const gpuTypes = new Set(await getGpuTypesToUseForOption("auto"));
if (platform === "win" && arch !== "x64")
gpuTypes.delete("vulkan"); // no Vulkan prebuilt binary yet due to incomplete support for arm64
return [...gpuTypes];
}
const res = [];
// Metal is not properly supported by llama.cpp on x64 Mac machines
if (platform === "mac" && arch === "arm64")
res.push("metal");
else
res.push("cuda");
res.push("vulkan");
res.push(false);
return res;
}
//# sourceMappingURL=getLlamaGpuTypes.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getLlamaGpuTypes.js","sourceRoot":"","sources":["../../../src/bindings/utils/getLlamaGpuTypes.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAC,yBAAyB,EAAC,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAE7C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAiC;IACpE,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAE1B,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC;QAElE,IAAI,QAAQ,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK;YACpC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,oEAAoE;QAEnG,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,GAAG,GAAmB,EAAE,CAAC;IAE/B,mEAAmE;IACnE,IAAI,QAAQ,KAAK,KAAK,IAAI,IAAI,KAAK,OAAO;QACtC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;;QAElB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAErB,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEhB,OAAO,GAAG,CAAC;AACf,CAAC"}

View File

@@ -0,0 +1,5 @@
import { Llama } from "../Llama.js";
/**
* This is used to access various methods in the addon side without actually using a backend
*/
export declare function getLlamaWithoutBackend(): Promise<Llama>;

View File

@@ -0,0 +1,40 @@
import { withLock } from "lifecycle-utils";
import { getLlamaForOptions } from "../getLlama.js";
import { LlamaLogLevel } from "../types.js";
let sharedLlamaWithoutBackend = null;
/**
* This is used to access various methods in the addon side without actually using a backend
*/
export async function getLlamaWithoutBackend() {
if (sharedLlamaWithoutBackend != null)
return sharedLlamaWithoutBackend;
return await withLock([getLlamaWithoutBackend, "loadAddon"], async () => {
if (sharedLlamaWithoutBackend != null)
return sharedLlamaWithoutBackend;
try {
sharedLlamaWithoutBackend = await getLlamaForOptions({
gpu: false,
progressLogs: false,
logLevel: LlamaLogLevel.error,
build: "never",
usePrebuiltBinaries: true,
vramPadding: 0
}, {
skipLlamaInit: true
});
}
catch (err) {
sharedLlamaWithoutBackend = await getLlamaForOptions({
progressLogs: false,
logLevel: LlamaLogLevel.error,
build: "never",
usePrebuiltBinaries: true,
vramPadding: 0
}, {
skipLlamaInit: true
});
}
return sharedLlamaWithoutBackend;
});
}
//# sourceMappingURL=getLlamaWithoutBackend.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getLlamaWithoutBackend.js","sourceRoot":"","sources":["../../../src/bindings/utils/getLlamaWithoutBackend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAC,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAC;AAG1C,IAAI,yBAAyB,GAAiB,IAAI,CAAC;AAEnD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB;IACxC,IAAI,yBAAyB,IAAI,IAAI;QACjC,OAAO,yBAAyB,CAAC;IAErC,OAAO,MAAM,QAAQ,CAAC,CAAC,sBAAsB,EAAE,WAAW,CAAC,EAAE,KAAK,IAAI,EAAE;QACpE,IAAI,yBAAyB,IAAI,IAAI;YACjC,OAAO,yBAAyB,CAAC;QAErC,IAAI,CAAC;YACD,yBAAyB,GAAG,MAAM,kBAAkB,CAAC;gBACjD,GAAG,EAAE,KAAK;gBACV,YAAY,EAAE,KAAK;gBACnB,QAAQ,EAAE,aAAa,CAAC,KAAK;gBAC7B,KAAK,EAAE,OAAO;gBACd,mBAAmB,EAAE,IAAI;gBACzB,WAAW,EAAE,CAAC;aACjB,EAAE;gBACC,aAAa,EAAE,IAAI;aACtB,CAAC,CAAC;QACP,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,yBAAyB,GAAG,MAAM,kBAAkB,CAAC;gBACjD,YAAY,EAAE,KAAK;gBACnB,QAAQ,EAAE,aAAa,CAAC,KAAK;gBAC7B,KAAK,EAAE,OAAO;gBACd,mBAAmB,EAAE,IAAI;gBACzB,WAAW,EAAE,CAAC;aACjB,EAAE;gBACC,aAAa,EAAE,IAAI;aACtB,CAAC,CAAC;QACP,CAAC;QAED,OAAO,yBAAyB,CAAC;IACrC,CAAC,CAAC,CAAC;AACP,CAAC"}

View File

@@ -0,0 +1,2 @@
export declare function getPlatform(): "aix" | "freebsd" | "haiku" | "linux" | "openbsd" | "sunos" | "netbsd" | "win" | "mac";
export type BinaryPlatform = ReturnType<typeof getPlatform>;

View File

@@ -0,0 +1,15 @@
import process from "process";
export function getPlatform() {
switch (process.platform) {
case "win32":
case "cygwin":
return "win";
case "linux":
case "android":
return "linux";
case "darwin":
return "mac";
}
return process.platform;
}
//# sourceMappingURL=getPlatform.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getPlatform.js","sourceRoot":"","sources":["../../../src/bindings/utils/getPlatform.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,MAAM,UAAU,WAAW;IACvB,QAAQ,OAAO,CAAC,QAAQ,EAAE,CAAC;QACvB,KAAK,OAAO,CAAC;QACb,KAAK,QAAQ;YACT,OAAO,KAAK,CAAC;QAEjB,KAAK,OAAO,CAAC;QACb,KAAK,SAAS;YACV,OAAO,OAAO,CAAC;QAEnB,KAAK,QAAQ;YACT,OAAO,KAAK,CAAC;IACrB,CAAC;IAED,OAAO,OAAO,CAAC,QAAQ,CAAC;AAC5B,CAAC"}

View File

@@ -0,0 +1,5 @@
export declare function getPlatformInfo(): Promise<{
name: string;
version: string;
}>;
export type BinaryPlatformInfo = Awaited<ReturnType<typeof getPlatformInfo>>;

View File

@@ -0,0 +1,28 @@
import os from "os";
import { getPlatform } from "./getPlatform.js";
import { getLinuxDistroInfo } from "./getLinuxDistroInfo.js";
export async function getPlatformInfo() {
const currentPlatform = getPlatform();
if (currentPlatform === "mac")
return {
name: "macOS",
version: os.release()
};
else if (currentPlatform === "linux") {
const linuxDistroInfo = await getLinuxDistroInfo();
return {
name: linuxDistroInfo.name,
version: linuxDistroInfo.version
};
}
else if (currentPlatform === "win")
return {
name: "Windows",
version: os.release()
};
return {
name: "Unknown",
version: os.release()
};
}
//# sourceMappingURL=getPlatformInfo.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getPlatformInfo.js","sourceRoot":"","sources":["../../../src/bindings/utils/getPlatformInfo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAC,kBAAkB,EAAC,MAAM,yBAAyB,CAAC;AAE3D,MAAM,CAAC,KAAK,UAAU,eAAe;IACjC,MAAM,eAAe,GAAG,WAAW,EAAE,CAAC;IAEtC,IAAI,eAAe,KAAK,KAAK;QACzB,OAAO;YACH,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE;SACxB,CAAC;SACD,IAAI,eAAe,KAAK,OAAO,EAAE,CAAC;QACnC,MAAM,eAAe,GAAG,MAAM,kBAAkB,EAAE,CAAC;QAEnD,OAAO;YACH,IAAI,EAAE,eAAe,CAAC,IAAI;YAC1B,OAAO,EAAE,eAAe,CAAC,OAAO;SACnC,CAAC;IACN,CAAC;SAAM,IAAI,eAAe,KAAK,KAAK;QAChC,OAAO;YACH,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE;SACxB,CAAC;IAEN,OAAO;QACH,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE;KACxB,CAAC;AACN,CAAC"}

View File

@@ -0,0 +1,3 @@
export declare function hasBuildingFromSourceDependenciesInstalled(): Promise<boolean>;
export declare function hasGit(): Promise<boolean>;
export declare function hasNpm(): Promise<boolean>;

View File

@@ -0,0 +1,27 @@
import which from "which";
import { asyncEvery } from "./asyncEvery.js";
export async function hasBuildingFromSourceDependenciesInstalled() {
return await asyncEvery([
hasGit(),
hasNpm()
]);
}
export async function hasGit() {
try {
const resolvedPath = await which("git");
return resolvedPath !== "";
}
catch (err) {
return false;
}
}
export async function hasNpm() {
try {
const resolvedPath = await which("npm");
return resolvedPath !== "";
}
catch (err) {
return false;
}
}
//# sourceMappingURL=hasBuildingFromSourceDependenciesInstalled.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"hasBuildingFromSourceDependenciesInstalled.js","sourceRoot":"","sources":["../../../src/bindings/utils/hasBuildingFromSourceDependenciesInstalled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,0CAA0C;IAC5D,OAAO,MAAM,UAAU,CAAC;QACpB,MAAM,EAAE;QACR,MAAM,EAAE;KACX,CAAC,CAAC;AACP,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM;IACxB,IAAI,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;QACxC,OAAO,YAAY,KAAK,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM;IACxB,IAAI,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;QACxC,OAAO,YAAY,KAAK,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC"}

View File

@@ -0,0 +1,2 @@
export declare function hasFileInPath(fileToSearch: string, additionalSearchPaths?: (string | null | undefined)[]): Promise<boolean>;
export declare function resolveFileLocationInPath(fileToSearch: string, additionalSearchPaths?: (string | null | undefined)[]): Promise<string[]>;

View File

@@ -0,0 +1,34 @@
import path from "path";
import fs from "fs-extra";
import { asyncSome } from "./asyncSome.js";
export async function hasFileInPath(fileToSearch, additionalSearchPaths = []) {
const searchPaths = resolveSearchPaths(additionalSearchPaths);
return await asyncSome(searchPaths.map(async (searchPath) => {
return fs.pathExists(path.join(searchPath, fileToSearch));
}));
}
export async function resolveFileLocationInPath(fileToSearch, additionalSearchPaths = []) {
const searchPaths = resolveSearchPaths(additionalSearchPaths);
const foundPaths = await Promise.all(searchPaths.map(async (searchPath) => {
const filePath = path.join(searchPath, fileToSearch);
if (await fs.pathExists(filePath))
return filePath;
return null;
}));
return foundPaths.filter((filePath) => filePath != null);
}
function resolveSearchPaths(additionalSearchPaths) {
return [
// Windows checks the cwd before the path
...(process.platform === "win32"
? [process.cwd()]
: []),
...((process.env.PATH || "").split(path.delimiter)),
...(additionalSearchPaths.flatMap((searchPath) => (searchPath || "").split(path.delimiter)))
]
.map((pathPart) => ((pathPart.length >= 2 && pathPart.startsWith('"') && pathPart.endsWith('"'))
? pathPart.slice(1, -1)
: pathPart))
.filter((pathPart) => pathPart.length > 0);
}
//# sourceMappingURL=hasFileInPath.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"hasFileInPath.js","sourceRoot":"","sources":["../../../src/bindings/utils/hasFileInPath.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,YAAoB,EAAE,wBAAuD,EAAE;IAC/G,MAAM,WAAW,GAAG,kBAAkB,CAAC,qBAAqB,CAAC,CAAC;IAE9D,OAAO,MAAM,SAAS,CAClB,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE;QACjC,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CACL,CAAC;AACN,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,YAAoB,EAAE,wBAAuD,EAAE;IAC3H,MAAM,WAAW,GAAG,kBAAkB,CAAC,qBAAqB,CAAC,CAAC;IAE9D,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QACrD,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;YAC7B,OAAO,QAAQ,CAAC;QAEpB,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC,CACL,CAAC;IAEF,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAsB,EAAE,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC;AACjF,CAAC;AAGD,SAAS,kBAAkB,CAAC,qBAAoD;IAC5E,OAAO;QACH,yCAAyC;QACzC,GAAG,CACC,OAAO,CAAC,QAAQ,KAAK,OAAO;YACxB,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACjB,CAAC,CAAC,EAAE,CACX;QACD,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnD,GAAG,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;KAC/F;SACI,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CACf,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACxE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACvB,CAAC,CAAC,QAAQ,CACjB,CAAC;SACD,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACnD,CAAC"}

View File

@@ -0,0 +1,6 @@
type LastBuildInfo = {
folderName: string;
};
export declare function getLastBuildInfo(): Promise<LastBuildInfo | null>;
export declare function setLastBuildInfo(buildInfo: LastBuildInfo): Promise<void>;
export {};

View File

@@ -0,0 +1,17 @@
import fs from "fs-extra";
import { lastBuildInfoJsonPath } from "../../config.js";
export async function getLastBuildInfo() {
try {
const buildInfo = await fs.readJson(lastBuildInfoJsonPath);
return buildInfo;
}
catch (err) {
return null;
}
}
export async function setLastBuildInfo(buildInfo) {
await fs.writeJson(lastBuildInfoJsonPath, buildInfo, {
spaces: 4
});
}
//# sourceMappingURL=lastBuildInfo.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"lastBuildInfo.js","sourceRoot":"","sources":["../../../src/bindings/utils/lastBuildInfo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAC,qBAAqB,EAAC,MAAM,iBAAiB,CAAC;AAMtD,MAAM,CAAC,KAAK,UAAU,gBAAgB;IAClC,IAAI,CAAC;QACD,MAAM,SAAS,GAAkB,MAAM,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC;QAE1E,OAAO,SAAS,CAAC;IACrB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,SAAwB;IAC3D,MAAM,EAAE,CAAC,SAAS,CAAC,qBAAqB,EAAE,SAAS,EAAE;QACjD,MAAM,EAAE,CAAC;KACZ,CAAC,CAAC;AACP,CAAC"}

View File

@@ -0,0 +1,2 @@
import { BuildOptions } from "../types.js";
export declare function logBinaryUsageExampleToConsole(buildOptions: BuildOptions, specifyGpuType: boolean, showLatestBuildUsageExample?: boolean): void;

View File

@@ -0,0 +1,22 @@
import { removeUndefinedFields } from "../../utils/removeNullFields.js";
import { getExampleUsageCodeOfGetLlama } from "./getExampleUsageCodeOfGetLlama.js";
export function logBinaryUsageExampleToConsole(buildOptions, specifyGpuType, showLatestBuildUsageExample = true) {
console.log("To use the binary you've just built, use this code:");
const llamaOptions = removeUndefinedFields({
gpu: specifyGpuType
? buildOptions.gpu
: undefined,
cmakeOptions: buildOptions.customCmakeOptions.size === 0
? undefined
: Object.fromEntries([...buildOptions.customCmakeOptions.entries()].sort(([keyA], [keyB]) => keyA.localeCompare(keyB)))
});
console.log(getExampleUsageCodeOfGetLlama(Object.keys(llamaOptions).length === 0
? undefined
: llamaOptions));
if (showLatestBuildUsageExample) {
console.log();
console.log("To always use the latest binary you build using a CLI command, use this code:");
console.log(getExampleUsageCodeOfGetLlama("lastBuild"));
}
}
//# sourceMappingURL=logBinaryUsageExampleToConsole.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"logBinaryUsageExampleToConsole.js","sourceRoot":"","sources":["../../../src/bindings/utils/logBinaryUsageExampleToConsole.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,qBAAqB,EAAC,MAAM,iCAAiC,CAAC;AAEtE,OAAO,EAAC,6BAA6B,EAAC,MAAM,oCAAoC,CAAC;AAEjF,MAAM,UAAU,8BAA8B,CAC1C,YAA0B,EAAE,cAAuB,EAAE,8BAAuC,IAAI;IAEhG,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;IACnE,MAAM,YAAY,GAAiB,qBAAqB,CAAC;QACrD,GAAG,EAAE,cAAc;YACf,CAAC,CAAC,YAAY,CAAC,GAAG;YAClB,CAAC,CAAC,SAAS;QACf,YAAY,EAAE,YAAY,CAAC,kBAAkB,CAAC,IAAI,KAAK,CAAC;YACpD,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,MAAM,CAAC,WAAW,CAChB,CAAC,GAAG,YAAY,CAAC,kBAAkB,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CACpG;KACR,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CACP,6BAA6B,CACzB,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,KAAK,CAAC;QAClC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,YAAY,CACrB,CACJ,CAAC;IAEF,IAAI,2BAA2B,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,+EAA+E,CAAC,CAAC;QAC7F,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,WAAW,CAAC,CAAC,CAAC;IAC5D,CAAC;AACL,CAAC"}

View File

@@ -0,0 +1,14 @@
type DistroPackages = {
linuxPackages?: {
apt?: string[];
apk?: string[];
};
macOsPackages?: {
brew?: string[];
};
};
export declare function logDistroInstallInstruction(prefixText: string, distroPackages: DistroPackages, { forceLogPrefix }?: {
forceLogPrefix?: boolean;
}): Promise<void>;
export declare function getDistroInstallInstruction({ linuxPackages, macOsPackages }: DistroPackages): Promise<string | null>;
export {};

View File

@@ -0,0 +1,48 @@
import which from "which";
import chalk from "chalk";
import { getConsoleLogPrefix } from "../../utils/getConsoleLogPrefix.js";
import { getPlatform } from "./getPlatform.js";
export async function logDistroInstallInstruction(prefixText, distroPackages, { forceLogPrefix = false } = {}) {
const instruction = await getDistroInstallInstruction(distroPackages);
if (instruction == null)
return;
console.info(getConsoleLogPrefix(forceLogPrefix) + chalk.yellow(prefixText + instruction));
}
export async function getDistroInstallInstruction({ linuxPackages, macOsPackages }) {
const platform = getPlatform();
if (platform === "linux") {
if (linuxPackages == null)
return null;
if (linuxPackages.apt != null && linuxPackages.apt.length > 0) {
const [sudoPath, aptPath] = await Promise.all([
which("sudo", { nothrow: true }),
which("apt", { nothrow: true })
]);
if (aptPath != null) {
const aptCommand = (sudoPath != null ? "sudo " : "") + "apt";
return 'you can run "' + aptCommand + " update && " + aptCommand + " install -y " + linuxPackages.apt.join(" ") + '"';
}
}
if (linuxPackages.apk != null && linuxPackages.apk.length > 0) {
const [sudoPath, apkPath] = await Promise.all([
which("sudo", { nothrow: true }),
which("apk", { nothrow: true })
]);
if (apkPath != null)
return 'you can run "' + (sudoPath != null ? "sudo " : "") + "apk add " + linuxPackages.apk.join(" ") + '"';
}
return null;
}
else if (platform === "mac") {
if (macOsPackages == null)
return null;
if (macOsPackages.brew != null && macOsPackages.brew.length > 0) {
const brewPath = await which("brew", { nothrow: true });
if (brewPath != null)
return 'you can run "brew install ' + macOsPackages.brew.join(" ") + '"';
}
return null;
}
return null;
}
//# sourceMappingURL=logDistroInstallInstruction.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"logDistroInstallInstruction.js","sourceRoot":"","sources":["../../../src/bindings/utils/logDistroInstallInstruction.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1 @@
export declare function resolveActualBindingBinaryPath(binaryPath: string): Promise<string>;

View File

@@ -0,0 +1,18 @@
import path from "path";
import fs from "fs-extra";
import { runningInElectron } from "../../utils/runtime.js";
export async function resolveActualBindingBinaryPath(binaryPath) {
const absolutePath = path.resolve(binaryPath);
if (!runningInElectron)
return absolutePath;
const fixedAsarPath = absolutePath.replace(".asar" + path.sep, ".asar.unpacked" + path.sep);
try {
if (await fs.pathExists(fixedAsarPath))
return fixedAsarPath;
return absolutePath;
}
catch (err) {
return absolutePath;
}
}
//# sourceMappingURL=resolveActualBindingBinaryPath.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"resolveActualBindingBinaryPath.js","sourceRoot":"","sources":["../../../src/bindings/utils/resolveActualBindingBinaryPath.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAC,iBAAiB,EAAC,MAAM,wBAAwB,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAC,UAAkB;IACnE,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC9C,IAAI,CAAC,iBAAiB;QAClB,OAAO,YAAY,CAAC;IAExB,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5F,IAAI,CAAC;QACD,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC;YAClC,OAAO,aAAa,CAAC;QAEzB,OAAO,YAAY,CAAC;IACxB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,OAAO,YAAY,CAAC;IACxB,CAAC;AACL,CAAC"}

View File

@@ -0,0 +1 @@
export declare function resolveCustomCmakeOptions(customCmakeOptions?: Record<string, string>): Map<string, string>;

View File

@@ -0,0 +1,43 @@
import process from "process";
import { customCmakeOptionsEnvVarPrefix } from "../../config.js";
export function resolveCustomCmakeOptions(customCmakeOptions) {
const newCustomCmakeOptions = customCmakeOptions == null
? new Map()
: new Map(Object.entries(customCmakeOptions));
if (process.env.GGML_METAL === "1")
newCustomCmakeOptions.set("GGML_METAL", "1");
if (process.env.GGML_METAL_EMBED_LIBRARY === "1")
newCustomCmakeOptions.set("GGML_METAL_EMBED_LIBRARY", "1");
if (process.env.GGML_CUDA === "1")
newCustomCmakeOptions.set("GGML_CUDA", "1");
if (process.env.GGML_VULKAN === "1")
newCustomCmakeOptions.set("GGML_VULKAN", "1");
if (process.env.GGML_OPENBLAS === "1")
newCustomCmakeOptions.set("GGML_OPENBLAS", "1");
if (process.env.GGML_BLAS_VENDOR != null)
newCustomCmakeOptions.set("GGML_BLAS_VENDOR", process.env.GGML_BLAS_VENDOR);
if (process.env.GGML_CUDA_FORCE_DMMV != null)
newCustomCmakeOptions.set("GGML_CUDA_FORCE_DMMV", process.env.GGML_CUDA_FORCE_DMMV);
if (process.env.GGML_CUDA_DMMV_X != null)
newCustomCmakeOptions.set("GGML_CUDA_DMMV_X", process.env.GGML_CUDA_DMMV_X);
if (process.env.GGML_CUDA_MMV_Y != null)
newCustomCmakeOptions.set("GGML_CUDA_MMV_Y", process.env.GGML_CUDA_MMV_Y);
if (process.env.GGML_CUDA_F16 != null)
newCustomCmakeOptions.set("GGML_CUDA_F16", process.env.GGML_CUDA_F16);
if (process.env.GGML_CUDA_KQUANTS_ITER != null)
newCustomCmakeOptions.set("GGML_CUDA_KQUANTS_ITER", process.env.GGML_CUDA_KQUANTS_ITER);
if (process.env.GGML_CUDA_PEER_MAX_BATCH_SIZE != null)
newCustomCmakeOptions.set("GGML_CUDA_PEER_MAX_BATCH_SIZE", process.env.GGML_CUDA_PEER_MAX_BATCH_SIZE);
if (process.env.GGML_HIPBLAS === "1")
newCustomCmakeOptions.set("GGML_HIPBLAS", "1");
for (const key in process.env) {
if (key.startsWith(customCmakeOptionsEnvVarPrefix) && key !== customCmakeOptionsEnvVarPrefix) {
const option = key.slice(customCmakeOptionsEnvVarPrefix.length);
const value = process.env[key];
newCustomCmakeOptions.set(option, value);
}
}
newCustomCmakeOptions.delete("");
return newCustomCmakeOptions;
}
//# sourceMappingURL=resolveCustomCmakeOptions.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"resolveCustomCmakeOptions.js","sourceRoot":"","sources":["../../../src/bindings/utils/resolveCustomCmakeOptions.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,2 @@
import { BuildGpu } from "../types.js";
export declare function testBindingBinary(bindingBinaryPath: string, extBackendsPath: string | undefined, gpu: BuildGpu, testTimeout?: number, pipeOutputOnNode?: boolean): Promise<boolean>;

View File

@@ -0,0 +1,269 @@
import { fork } from "node:child_process";
import { fileURLToPath } from "url";
import { createRequire } from "module";
import path from "path";
import { getConsoleLogPrefix } from "../../utils/getConsoleLogPrefix.js";
import { runningInBun, runningInElectron } from "../../utils/runtime.js";
import { LlamaLogLevelToAddonLogLevel } from "../Llama.js";
import { defaultBindingTestLogLevel, newGithubIssueUrl } from "../../config.js";
import { getPlatform } from "./getPlatform.js";
const require = createRequire(import.meta.url);
const __filename = fileURLToPath(import.meta.url);
const detectedFileName = path.basename(__filename);
const expectedFileName = "testBindingBinary";
export async function testBindingBinary(bindingBinaryPath, extBackendsPath, gpu, testTimeout = 1000 * 60 * 5, pipeOutputOnNode = false) {
if (!detectedFileName.startsWith(expectedFileName)) {
console.warn(getConsoleLogPrefix() +
`"${expectedFileName}.js" file is not independent, so testing a binding binary with the current system ` +
"prior to importing it cannot be done.\n" +
getConsoleLogPrefix() +
"Assuming the test passed with the risk that the process may crash due to an incompatible binary.\n" +
getConsoleLogPrefix() +
'To resolve this issue, make sure that "node-llama-cpp" is not bundled together with other code and is imported as an external module with its original file structure.');
return true;
}
try {
const runningInsideSnapOnLinux = getPlatform() === "linux" && process.env.SNAP != null;
if (runningInsideSnapOnLinux && !runningInBun && !runningInElectron) {
const nodeSea = await import("node:sea");
if (nodeSea.isSea()) {
console.warn(getConsoleLogPrefix() +
"node SEA is detected, so testing a binding binary with the current system prior to importing it cannot be done.\n" +
getConsoleLogPrefix() +
"Assuming the test passed with the risk that the process may crash due to an incompatible binary.\n" +
getConsoleLogPrefix() +
"If this is an issue in your case, " +
"please open an issue on GitHub with the details of the environment where this happens: " + newGithubIssueUrl);
return true;
}
}
}
catch (err) {
// do nothing
}
async function getForkFunction() {
if (runningInElectron) {
try {
const { utilityProcess } = await import("electron");
return {
type: "electron",
fork: utilityProcess.fork.bind(utilityProcess)
};
}
catch (err) {
// do nothing
}
}
return {
type: "node",
fork
};
}
const forkFunction = await getForkFunction();
function createTestProcess({ onMessage, onExit }) {
if (forkFunction.type === "electron") {
let exited = false;
const subProcess = forkFunction.fork(__filename, [], {
env: {
...process.env,
TEST_BINDING_CP: "true"
}
});
function cleanupElectronFork() {
if (subProcess.pid != null || !exited) {
subProcess.kill();
exited = true;
}
process.off("exit", cleanupElectronFork);
}
process.on("exit", cleanupElectronFork);
subProcess.on("message", onMessage);
subProcess.on("exit", (code) => {
exited = true;
cleanupElectronFork();
onExit(code);
});
return {
sendMessage: (message) => subProcess.postMessage(message),
killProcess: cleanupElectronFork,
pipeMessages: () => void 0
};
}
let pipeSet = false;
const subProcess = forkFunction.fork(__filename, [], {
detached: false,
silent: true,
stdio: pipeOutputOnNode
? ["ignore", "pipe", "pipe", "ipc"]
: ["ignore", "ignore", "ignore", "ipc"],
env: {
...process.env,
TEST_BINDING_CP: "true"
}
});
function cleanupNodeFork() {
subProcess.stdout?.off("data", onStdout);
subProcess.stderr?.off("data", onStderr);
if (subProcess.exitCode == null)
subProcess.kill("SIGKILL");
process.off("exit", cleanupNodeFork);
}
process.on("exit", cleanupNodeFork);
subProcess.on("message", onMessage);
subProcess.on("exit", (code) => {
cleanupNodeFork();
onExit(code ?? -1);
});
if (subProcess.killed || subProcess.exitCode != null) {
cleanupNodeFork();
onExit(subProcess.exitCode ?? -1);
}
function onStdout(data) {
if (!pipeSet)
return;
process.stdout.write(data);
}
function onStderr(data) {
if (!pipeSet)
return;
process.stderr.write(data);
}
if (pipeOutputOnNode) {
subProcess.stdout?.on("data", onStdout);
subProcess.stderr?.on("data", onStderr);
}
function pipeMessages() {
if (!pipeOutputOnNode || pipeSet)
return;
pipeSet = true;
}
return {
sendMessage: (message) => subProcess.send(message),
killProcess: cleanupNodeFork,
pipeMessages
};
}
let testPassed = false;
let forkSucceeded = false;
let timeoutHandle = null;
let subProcess = undefined;
let testFinished = false;
function cleanup() {
testFinished = true;
if (timeoutHandle != null)
clearTimeout(timeoutHandle);
subProcess?.killProcess();
}
return Promise.race([
new Promise((_, reject) => {
timeoutHandle = setTimeout(() => {
reject(new Error("Binding binary load test timed out"));
cleanup();
}, testTimeout);
}),
new Promise((resolve, reject) => {
function done() {
if (!forkSucceeded)
reject(new Error(`Binding binary test failed to run a test process via file "${__filename}"`));
else
resolve(testPassed);
cleanup();
}
subProcess = createTestProcess({
onMessage(message) {
if (message.type === "ready") {
forkSucceeded = true;
subProcess.sendMessage({
type: "start",
bindingBinaryPath,
extBackendsPath,
gpu
});
}
else if (message.type === "loaded") {
subProcess.pipeMessages(); // only start piping error logs if the binary loaded successfully
subProcess.sendMessage({
type: "test",
bindingBinaryPath,
extBackendsPath,
gpu
});
}
else if (message.type === "done") {
testPassed = true;
subProcess.sendMessage({ type: "exit" });
}
},
onExit(code) {
if (code !== 0)
testPassed = false;
done();
}
});
if (testFinished)
subProcess.killProcess();
})
]);
}
if (process.env.TEST_BINDING_CP === "true" && (process.parentPort != null || process.send != null)) {
let binding;
const sendMessage = process.parentPort != null
? (message) => process.parentPort.postMessage(message)
: (message) => process.send(message);
const onMessage = async (message) => {
if (message.type === "start") {
try {
binding = require(message.bindingBinaryPath);
const errorLogLevel = LlamaLogLevelToAddonLogLevel.get(defaultBindingTestLogLevel);
if (errorLogLevel != null)
binding.setLoggerLogLevel(errorLogLevel);
sendMessage({ type: "loaded" });
}
catch (err) {
console.error(err);
process.exit(1);
}
}
else if (message.type === "test") {
try {
if (binding == null)
throw new Error("Binding binary is not loaded");
binding.loadBackends();
let loadedGpu = binding.getGpuType();
if (loadedGpu == null || (loadedGpu === false && message.gpu !== false)) {
const backendsPath = path.dirname(path.resolve(message.bindingBinaryPath));
const fallbackBackendsDir = path.join(path.resolve(message.extBackendsPath ?? backendsPath), "fallback");
binding.loadBackends(backendsPath);
loadedGpu = binding.getGpuType();
if (loadedGpu == null || (loadedGpu === false && message.gpu !== false))
binding.loadBackends(fallbackBackendsDir);
}
await binding.init();
binding.getGpuVramInfo();
binding.getGpuDeviceInfo();
const gpuType = binding.getGpuType();
void gpuType;
if (gpuType !== message.gpu)
throw new Error("Binary GPU type mismatch. " +
`Expected: ${message.gpu}, got: ${gpuType}. ` + (message.gpu === "cuda"
? "May be due to a linker issue, ensure you don't have multiple conflicting CUDA installations."
: "May be due to a linker issue, ensure the native dependencies are not broken."));
binding.ensureGpuDeviceIsSupported();
sendMessage({ type: "done" });
}
catch (err) {
console.error(err);
process.exit(1);
}
}
else if (message.type === "exit") {
process.exit(0);
}
};
if (process.parentPort != null)
process.parentPort.on("message", (message) => onMessage(message.data));
else
process.on("message", onMessage);
sendMessage({ type: "ready" });
}
//# sourceMappingURL=testBindingBinary.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
import process from "process";
export declare function testCmakeBinary(cmakeBinaryPath?: string, { cwd, env }?: {
cwd?: string;
env?: typeof process.env;
}): Promise<boolean>;

View File

@@ -0,0 +1,32 @@
import process from "process";
import { execFile } from "node:child_process";
import path from "path";
import { fileURLToPath } from "url";
import fs from "fs-extra";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
export async function testCmakeBinary(cmakeBinaryPath, { cwd = __dirname, env = process.env } = {}) {
if (cmakeBinaryPath == null || !(await fs.pathExists(cmakeBinaryPath)))
return false;
return new Promise((resolve, reject) => {
const child = execFile(cmakeBinaryPath, ["--version"], {
cwd,
env,
windowsHide: true
});
child.on("exit", (code) => {
if (code == 0)
resolve(true);
else
reject(false);
});
child.on("error", reject);
child.on("disconnect", () => resolve(false));
child.on("close", (code) => {
if (code == 0)
resolve(true);
else
resolve(false);
});
});
}
//# sourceMappingURL=testCmakeBinary.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"testCmakeBinary.js","sourceRoot":"","sources":["../../../src/bindings/utils/testCmakeBinary.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAC,QAAQ,EAAC,MAAM,oBAAoB,CAAC;AAC5C,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAC,aAAa,EAAC,MAAM,KAAK,CAAC;AAClC,OAAO,EAAE,MAAM,UAAU,CAAC;AAE1B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE/D,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,eAAwB,EAAE,EAC5D,GAAG,GAAG,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,KAGlC,EAAE;IACF,IAAI,eAAe,IAAI,IAAI,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;QAClE,OAAO,KAAK,CAAC;IAEjB,OAAO,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC5C,MAAM,KAAK,GAAG,QAAQ,CAAC,eAAe,EAAE,CAAC,WAAW,CAAC,EAAE;YACnD,GAAG;YACH,GAAG;YACH,WAAW,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACtB,IAAI,IAAI,IAAI,CAAC;gBACT,OAAO,CAAC,IAAI,CAAC,CAAC;;gBAEd,MAAM,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7C,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACvB,IAAI,IAAI,IAAI,CAAC;gBACT,OAAO,CAAC,IAAI,CAAC,CAAC;;gBAEd,OAAO,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC"}