UNPKG

node-llama-cpp

Version:

Run AI models locally on your machine with node.js bindings for llama.cpp. Enforce a JSON schema on the model output on the generation level

132 lines 7.15 kB
import path from "path"; import fs from "fs-extra"; import simpleGit from "simple-git"; import { currentReleaseGitBundlePath, builtinLlamaCppGitHubRepo, llamaCppDirectory, enableRecursiveClone } from "../config.js"; import { getBinariesGithubRelease } from "../bindings/utils/binariesGithubRelease.js"; import { isGithubReleaseNeedsResolving } from "./resolveGithubRelease.js"; export async function unshallowAndSquashCurrentRepoAndSaveItAsReleaseBundle() { if (enableRecursiveClone) await unshallowAndSquashCurrentRepoWithSubmodulesAndSaveItAsReleaseBundle(); else await unshallowAndSquashCurrentRepoWithoutSubmodulesAndSaveItAsReleaseBundle(); } async function unshallowAndSquashCurrentRepoWithoutSubmodulesAndSaveItAsReleaseBundle() { if (!(await fs.pathExists(llamaCppDirectory))) throw new Error("llama.cpp directory does not exist"); if (await fs.pathExists(currentReleaseGitBundlePath)) await fs.remove(currentReleaseGitBundlePath); await simpleGit(llamaCppDirectory).addConfig("user.name", "node-llama-cpp-ci"); await simpleGit(llamaCppDirectory).addConfig("user.email", "node-llama-cpp-ci@node-llama-cpp-ci.node-llama-cpp-ci"); const currentBranch = await getCurrentTagOrBranch(); await simpleGit(llamaCppDirectory).fetch(["--unshallow"]); const lastCommit = await simpleGit(llamaCppDirectory).log(["-1"]); const lastCommitMessage = lastCommit?.all?.[0]?.message; const newCommitMessage = "## SQUASHED ##\n\n" + (lastCommitMessage ?? ""); const newCommitSha = await simpleGit(llamaCppDirectory).raw(["commit-tree", "HEAD^{tree}", "-m", newCommitMessage]); await simpleGit(llamaCppDirectory).reset(["--hard", newCommitSha.trim()]); const tags = await simpleGit(llamaCppDirectory).tags(); for (const tag of tags.all) { await simpleGit(llamaCppDirectory).tag(["--delete", tag]); } const branches = await simpleGit(llamaCppDirectory).branch(); for (const branch of branches.all) { try { await simpleGit(llamaCppDirectory).branch(["--delete", branch]); } catch (err) { // If the branch is not found, it's fine // this happens as when there are no branches git returnes an output saying so, and `simpleGit` parses it as a branch, // so the list may contain branches that do not exist. // Right now, the non-existent branch name returned called `(no`, but I wouldn't want to rely on this specific text, // as this is a bug in `simpleGit`. } } if (currentBranch != null) await simpleGit(llamaCppDirectory).tag([currentBranch]); await simpleGit(llamaCppDirectory).raw(["gc", "--aggressive", "--prune=all"]); await simpleGit(llamaCppDirectory).raw(["bundle", "create", currentReleaseGitBundlePath, "HEAD"]); } async function unshallowAndSquashCurrentRepoWithSubmodulesAndSaveItAsReleaseBundle() { if (!(await fs.pathExists(llamaCppDirectory))) throw new Error("llama.cpp directory does not exist"); if (await fs.pathExists(currentReleaseGitBundlePath)) await fs.remove(currentReleaseGitBundlePath); const currentBranch = await getCurrentTagOrBranch(); const lastCommit = await simpleGit(llamaCppDirectory).log(["-1"]); const lastCommitMessage = lastCommit?.all?.[0]?.message; const newCommitMessage = "## SQUASHED ##\n\n" + (lastCommitMessage ?? ""); const currentRemoteUrl = (await simpleGit(llamaCppDirectory).listRemote(["--get-url", "origin"])).trim(); await deleteFilesRecursively(llamaCppDirectory, [".git", ".gitmodules"]); await simpleGit(llamaCppDirectory).init(); await simpleGit(llamaCppDirectory).addConfig("user.name", "node-llama-cpp-ci"); await simpleGit(llamaCppDirectory).addConfig("user.email", "node-llama-cpp-ci@node-llama-cpp-ci.node-llama-cpp-ci"); await simpleGit(llamaCppDirectory).addRemote("origin", currentRemoteUrl); await simpleGit(llamaCppDirectory).add([ "--force", ...(await getAllFilePaths(llamaCppDirectory, (fileName) => fileName !== ".gitignore")) ]); await simpleGit(llamaCppDirectory).commit(newCommitMessage); await simpleGit(llamaCppDirectory).add([ "--force", ...(await getAllFilePaths(llamaCppDirectory, (fileName) => fileName === ".gitignore")) ]); await simpleGit(llamaCppDirectory).commit(newCommitMessage); await simpleGit(llamaCppDirectory).branch(["-M", "master"]); const newCommitSha = await simpleGit(llamaCppDirectory).raw(["commit-tree", "HEAD^{tree}", "-m", newCommitMessage]); await simpleGit(llamaCppDirectory).reset(["--hard", newCommitSha.trim()]); if (currentBranch != null) await simpleGit(llamaCppDirectory).tag([currentBranch]); await simpleGit(llamaCppDirectory).raw(["gc", "--aggressive", "--prune=all"]); await simpleGit(llamaCppDirectory).raw(["bundle", "create", currentReleaseGitBundlePath, "HEAD"]); } export async function getGitBundlePathForRelease(githubOwner, githubRepo, release) { const [builtinGithubOwner, builtinGithubRepo] = builtinLlamaCppGitHubRepo.split("/"); if (githubOwner !== builtinGithubOwner || githubRepo !== builtinGithubRepo) return null; const currentBundleRelease = await getBinariesGithubRelease(); if (isGithubReleaseNeedsResolving(currentBundleRelease)) return null; if (currentBundleRelease !== release) return null; if (!(await fs.pathExists(currentReleaseGitBundlePath))) return null; return currentReleaseGitBundlePath; } async function getCurrentTagOrBranch() { const branch = await simpleGit(llamaCppDirectory).revparse(["--abbrev-ref", "HEAD"]); if (branch !== "HEAD") return branch; const tags = await simpleGit(llamaCppDirectory).tag(["--points-at", "HEAD"]); const tagArray = tags.split("\n").filter(Boolean); if (tagArray.length > 0) return tagArray[0]; return null; } async function deleteFilesRecursively(folderPath, deleteFileOrFolderNames) { await Promise.all((await fs.readdir(folderPath)) .map(async (item) => { const itemPath = path.join(folderPath, item); if (deleteFileOrFolderNames.includes(item)) { // deleting a ".git" folder fails, so we rename it first const tempNewPath = path.join(folderPath, item + ".deleteme"); await fs.move(itemPath, tempNewPath); await fs.remove(tempNewPath); } else if ((await fs.stat(itemPath)).isDirectory()) await deleteFilesRecursively(itemPath, deleteFileOrFolderNames); })); } async function getAllFilePaths(folderPath, includePath) { return (await Promise.all((await fs.readdir(folderPath)) .map(async (item) => { const itemPath = path.join(folderPath, item); const isDirectory = (await fs.stat(itemPath)).isDirectory(); if (isDirectory) return await getAllFilePaths(itemPath, includePath); else if (includePath(item)) return [itemPath]; return []; }))) .flat(); } //# sourceMappingURL=gitReleaseBundles.js.map