426e9eeabd
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Waiting to run
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Waiting to run
Build Agent Image / build-and-push (push) Waiting to run
Chat shell gestures / Chat shell gesture + parity e2e (push) Waiting to run
Cloud Gateway Discord / Test (push) Waiting to run
Cloud Gateway Webhook / Test (push) Waiting to run
Cloud Tests / lint-and-types (push) Waiting to run
Cloud Tests / unit-tests (push) Waiting to run
Cloud Tests / integration-tests (push) Waiting to run
Cloud Tests / e2e-tests (push) Blocked by required conditions
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Apps Worker (Product 2) / Determine environment (push) Waiting to run
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Blocked by required conditions
Deploy Eliza Provisioning Worker / Determine environment (push) Waiting to run
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Blocked by required conditions
Dev Smoke / Classify changed paths (push) Waiting to run
Dev Smoke / bun run dev onboarding chat (push) Blocked by required conditions
Dev Smoke / Vite HMR dependency-level smoke (push) Blocked by required conditions
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Waiting to run
Publish @elizaos/example-code / check_npm (push) Waiting to run
Publish @elizaos/example-code / publish_npm (push) Blocked by required conditions
Publish @elizaos/plugin-elizacloud / verify_version (push) Waiting to run
Publish @elizaos/plugin-elizacloud / publish_npm (push) Blocked by required conditions
Sandbox Live Smoke / Sandbox live smoke (push) Waiting to run
Snap Build & Test / Build Snap (amd64) (push) Waiting to run
Snap Build & Test / Build Snap (arm64) (push) Waiting to run
supply-chain / sbom (push) Waiting to run
supply-chain / vulnerability-scan (push) Waiting to run
Build, Push & Deploy to Phala Cloud / build-and-push (push) Waiting to run
Test Packaging / Validate Packaging Configs (push) Waiting to run
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Waiting to run
Test Packaging / Pack & Test JS Tarballs (push) Waiting to run
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Waiting to run
UI Fixture E2E / ui-fixture-e2e (push) Waiting to run
UI Fixture E2E / fixture-e2e (push) Waiting to run
UI Story Gate / story-gate (push) Waiting to run
vault-ci / test (macos-latest) (push) Waiting to run
vault-ci / test (ubuntu-latest) (push) Waiting to run
vault-ci / test (windows-latest) (push) Waiting to run
vault-ci / app-core wiring tests (push) Waiting to run
verify-patches / verify patches/CHECKSUMS.sha256 (push) Waiting to run
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Waiting to run
Voice Benchmark Smoke / voice bench smoke summary (push) Blocked by required conditions
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Waiting to run
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Waiting to run
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Waiting to run
Test Packaging / Build & Test PyPI Package (push) Waiting to run
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
345 lines
14 KiB
JavaScript
345 lines
14 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* patch-llama-cpp-capacitor.mjs
|
|
*
|
|
* Bun v1.3.x has been observed to mis-apply patches that touch deeply-nested
|
|
* directories inside cached packages (related bugs:
|
|
* - https://github.com/oven-sh/bun/issues/13330
|
|
* - https://github.com/oven-sh/bun/issues/13770).
|
|
*
|
|
* This script applies patches/llama-cpp-capacitor@0.1.5.patch using the
|
|
* system `patch` utility instead, targeting all installed
|
|
* llama-cpp-capacitor copies in node_modules.
|
|
*
|
|
* The patch rewrites android/build.gradle (per-ABI MTP lib dirs, riscv64
|
|
* added to abiFilters), android/src/main/CMakeLists.txt (drop vendored
|
|
* llama.cpp sources, link against MTP .so via the Eliza JNI bridge) and
|
|
* android/src/main/java/.../LlamaCpp.java (riscv64 library mapping and
|
|
* MTP dependency preload). It also repairs partially-applied installs so a
|
|
* half-patched package cannot silently reach Android CI.
|
|
*/
|
|
|
|
import { spawnSync } from "node:child_process";
|
|
import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { dirname, join, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
const nodeModulesDir = join(repoRoot, "node_modules");
|
|
const bunCacheDir = join(nodeModulesDir, ".bun");
|
|
const patchFile = join(repoRoot, "patches", "llama-cpp-capacitor@0.1.5.patch");
|
|
|
|
if (!existsSync(nodeModulesDir)) {
|
|
process.exit(0);
|
|
}
|
|
|
|
if (!existsSync(patchFile)) {
|
|
console.warn("[patch-llama-cpp-capacitor] Patch file not found — skipping.");
|
|
process.exit(0);
|
|
}
|
|
|
|
// Check that `patch` is available on PATH.
|
|
const patchCheck = spawnSync("patch", ["--version"], { encoding: "utf8" });
|
|
if (patchCheck.status !== 0 && patchCheck.error) {
|
|
console.warn(
|
|
"[patch-llama-cpp-capacitor] `patch` utility not found — skipping.",
|
|
);
|
|
process.exit(0);
|
|
}
|
|
|
|
// Discover every installed llama-cpp-capacitor copy: the top-level
|
|
// node_modules entry (used at build time by the Android app) and every
|
|
// per-hash bun cache copy. Bun's installer does not always hardlink the
|
|
// top-level copy back to the cache, so we must patch both.
|
|
const candidates = [];
|
|
const topLevel = join(nodeModulesDir, "llama-cpp-capacitor");
|
|
if (existsSync(topLevel)) {
|
|
candidates.push({ label: "node_modules/llama-cpp-capacitor", dir: topLevel });
|
|
}
|
|
if (existsSync(bunCacheDir)) {
|
|
for (const entry of readdirSync(bunCacheDir)) {
|
|
if (!entry.startsWith("llama-cpp-capacitor@0.1.5")) continue;
|
|
const pkgDir = join(
|
|
bunCacheDir,
|
|
entry,
|
|
"node_modules",
|
|
"llama-cpp-capacitor",
|
|
);
|
|
if (existsSync(pkgDir)) {
|
|
candidates.push({ label: `node_modules/.bun/${entry}`, dir: pkgDir });
|
|
}
|
|
}
|
|
}
|
|
|
|
let patched = 0;
|
|
let skipped = 0;
|
|
let repaired = 0;
|
|
let failed = 0;
|
|
|
|
function writeIfChanged(filePath, current, next) {
|
|
if (next === current) return false;
|
|
writeFileSync(filePath, next);
|
|
return true;
|
|
}
|
|
|
|
function ensureGradleMtpContract(pkgDir) {
|
|
const gradlePath = join(pkgDir, "android", "build.gradle");
|
|
if (!existsSync(gradlePath)) return false;
|
|
const current = readFileSync(gradlePath, "utf8");
|
|
let next = current;
|
|
|
|
const mtpHelpers =
|
|
`def resolveElizaRepoRoot = { ->\n` +
|
|
` return rootProject.projectDir.toPath().resolve('../../../..').normalize().toFile().absolutePath\n` +
|
|
`}\n` +
|
|
`\n` +
|
|
`// Per-ABI resolver for the MTP cross-compile output produced by\n` +
|
|
`// \`packages/app-core/scripts/build-llama-cpp-mtp.mjs\` and\n` +
|
|
`// \`packages/app-core/scripts/aosp/compile-libllama.mjs\`. Each ABI has\n` +
|
|
`// its own gradle property (\`eliza.mtp.android.libdir.<abi>\`) and env\n` +
|
|
`// var (\`ELIZA_MTP_ANDROID_LIBDIR_<ABI>\`). For arm64-v8a the legacy\n` +
|
|
`// unsuffixed names are still honored for backwards compatibility.\n` +
|
|
`// riscv64 has no Vulkan path yet (Wave 2 ships CPU-only), so only the\n` +
|
|
`// \`cpu\` backend is searched on that ABI.\n` +
|
|
`def resolveElizaMtpAndroidLibDir = { String abi ->\n` +
|
|
` def propSuffix = abi == 'arm64-v8a' ? '' : ".\${abi}"\n` +
|
|
` def envSuffix = abi == 'arm64-v8a' ? '' : "_\${abi.replace('-', '_').toUpperCase()}"\n` +
|
|
` def fromProp = project.findProperty("eliza.mtp.android.libdir\${propSuffix}")\n` +
|
|
` if (fromProp) return fromProp.toString()\n` +
|
|
` def fromEnv = System.getenv("ELIZA_MTP_ANDROID_LIBDIR\${envSuffix}")\n` +
|
|
` if (fromEnv) return fromEnv\n` +
|
|
` def stateDir = System.getenv('ELIZA_STATE_DIR') ?: "\${System.getProperty('user.home')}/.eliza"\n` +
|
|
` def abiToken = [\n` +
|
|
` 'arm64-v8a': 'android-arm64',\n` +
|
|
` 'x86_64' : 'android-x86_64',\n` +
|
|
` 'riscv64' : 'android-riscv64',\n` +
|
|
` ][abi]\n` +
|
|
` if (abiToken == null) return ''\n` +
|
|
` def backends = abi == 'riscv64' ? ['cpu'] : ['vulkan', 'cpu']\n` +
|
|
` def candidates = backends.collect { backend ->\n` +
|
|
` "\${stateDir}/local-inference/bin/mtp/\${abiToken}-\${backend}"\n` +
|
|
` }\n` +
|
|
` return candidates.find { new File(it).isDirectory() } ?: ''\n` +
|
|
`}\n` +
|
|
`\n` +
|
|
`def resolveElizaSkipMtpAndroidLib = { ->\n` +
|
|
` // The retired llama-cpp-capacitor Android module is dropped from the\n` +
|
|
` // gradle build by default (run-mobile-build dropRetiredLlamaCppFromAndroidGradle),\n` +
|
|
` // so its CMake never runs and there is no stub. If it is explicitly\n` +
|
|
` // re-included (ELIZA_ANDROID_INCLUDE_LLAMA_CPP_CAPACITOR=1) build the real\n` +
|
|
` // MTP lib — never a no-op stub.\n` +
|
|
` return false\n` +
|
|
`}\n`;
|
|
|
|
// Self-heal duplicate helper blocks. An older non-idempotent version of
|
|
// this patch appended a fresh helper copy on every install/build cycle, so
|
|
// the file accumulated many duplicate top-level `def`s — duplicate
|
|
// script-level closures crash Gradle's Groovy resolver with a
|
|
// GradleResolveVisitor NPE ("source is null") and break every Android
|
|
// build. If we see more than one copy, collapse the entire region between
|
|
// the ext{} block and `buildscript {` back to a single canonical block.
|
|
const repoRootCount = (next.match(/def resolveElizaRepoRoot\b/g) || [])
|
|
.length;
|
|
if (repoRootCount > 1) {
|
|
next = next.replace(
|
|
/(ext\s*\{[\s\S]*?\n\}\n)[\s\S]*?(\nbuildscript \{)/,
|
|
`$1\n${mtpHelpers}$2`,
|
|
);
|
|
} else if (!next.includes("def resolveElizaRepoRoot")) {
|
|
next = next.replace(/(ext\s*\{[\s\S]*?\n\}\n)/, `$1\n${mtpHelpers}\n`);
|
|
} else if (
|
|
!next.includes("def resolveElizaMtpAndroidLibDir = { String abi ->") ||
|
|
!next.includes("def resolveElizaSkipMtpAndroidLib")
|
|
) {
|
|
next = next.replace(
|
|
/def resolveElizaRepoRoot = \{ ->[\s\S]*?\n\}\n\nbuildscript \{/,
|
|
`${mtpHelpers}\nbuildscript {`,
|
|
);
|
|
}
|
|
|
|
next = next
|
|
.replace(
|
|
/rootProject\.projectDir\.toPath\(\)\.resolve\('\.\.\/\.\.\/\.\.'\)/g,
|
|
"rootProject.projectDir.toPath().resolve('../../../..')",
|
|
)
|
|
.replace(
|
|
/namespace\s+"ai\.annadata\.plugin\.capacitor"/g,
|
|
'namespace = "ai.annadata.plugin.capacitor"',
|
|
)
|
|
.replace(
|
|
/getDefaultProguardFile\('proguard-android\.txt'\)/g,
|
|
"getDefaultProguardFile('proguard-android-optimize.txt')",
|
|
)
|
|
.replace(/\bversion "3\.22\.1"/g, 'version = "3.22.1"')
|
|
.replace(/\bndkVersion "29\.0\.13113456"/g, 'ndkVersion = "29.0.13113456"')
|
|
.replace(/\babortOnError false/g, "abortOnError = false")
|
|
.replace(
|
|
/abiFilters 'arm64-v8a'(?!,)/g,
|
|
"abiFilters 'arm64-v8a', 'riscv64'",
|
|
);
|
|
|
|
const cmakeArgsBlock =
|
|
`\n\n externalNativeBuild {\n` +
|
|
` cmake {\n` +
|
|
` arguments "-DELIZA_REPO_ROOT=\${resolveElizaRepoRoot()}",\n` +
|
|
` "-DELIZA_MTP_ANDROID_LIBDIR_ARM64_V8A=\${resolveElizaMtpAndroidLibDir('arm64-v8a')}",\n` +
|
|
` "-DELIZA_MTP_ANDROID_LIBDIR_RISCV64=\${resolveElizaMtpAndroidLibDir('riscv64')}",\n` +
|
|
` "-DELIZA_SKIP_MTP_ANDROID_LIB=\${resolveElizaSkipMtpAndroidLib() ? 'ON' : 'OFF'}"\n` +
|
|
` }\n` +
|
|
` }`;
|
|
|
|
if (!next.includes("-DELIZA_REPO_ROOT=")) {
|
|
next = next.replace(
|
|
/(\n\s*ndk\s*\{\s*\n\s*abiFilters 'arm64-v8a'(?:,\s*'riscv64')?\s*\n\s*\})/,
|
|
`$1${cmakeArgsBlock}`,
|
|
);
|
|
} else if (!next.includes("-DELIZA_MTP_ANDROID_LIBDIR_ARM64_V8A=")) {
|
|
next = next.replace(
|
|
/"-DELIZA_MTP_ANDROID_LIBDIR=\$\{resolveElizaMtpAndroidLibDir\(\)\}",?\n\s*(?:"-DELIZA_SKIP_MTP_ANDROID_LIB=\$\{resolveElizaSkipMtpAndroidLib\(\) \? 'ON' : 'OFF'\}")?/,
|
|
`"-DELIZA_MTP_ANDROID_LIBDIR_ARM64_V8A=\${resolveElizaMtpAndroidLibDir('arm64-v8a')}",\n "-DELIZA_MTP_ANDROID_LIBDIR_RISCV64=\${resolveElizaMtpAndroidLibDir('riscv64')}",\n "-DELIZA_SKIP_MTP_ANDROID_LIB=\${resolveElizaSkipMtpAndroidLib() ? 'ON' : 'OFF'}"`,
|
|
);
|
|
} else if (!next.includes("-DELIZA_SKIP_MTP_ANDROID_LIB=")) {
|
|
next = next.replace(
|
|
/("-DELIZA_MTP_ANDROID_LIBDIR_RISCV64=\$\{resolveElizaMtpAndroidLibDir\('riscv64'\)\}")/,
|
|
`$1,\n "-DELIZA_SKIP_MTP_ANDROID_LIB=\${resolveElizaSkipMtpAndroidLib() ? 'ON' : 'OFF'}"`,
|
|
);
|
|
}
|
|
|
|
return writeIfChanged(gradlePath, current, next);
|
|
}
|
|
|
|
function ensureCmakeMtpContract(pkgDir) {
|
|
const cmakePath = join(pkgDir, "android", "src", "main", "CMakeLists.txt");
|
|
if (!existsSync(cmakePath)) return false;
|
|
const current = readFileSync(cmakePath, "utf8");
|
|
let next = current.replace(
|
|
/\$\{ELIZA_REPO_ROOT\}\/packages\/native-plugins\/llama\/android\/eliza-mtp-jni\.cpp/g,
|
|
"$" +
|
|
"{ELIZA_REPO_ROOT}/packages/native/plugins/llama/android/eliza-mtp-jni.cpp",
|
|
);
|
|
|
|
if (
|
|
next.includes("ELIZA_REPO_ROOT is required") &&
|
|
!next.includes("ELIZA_SKIP_MTP_ANDROID_LIB")
|
|
) {
|
|
const smokeLibraryBlock =
|
|
`\noption(ELIZA_SKIP_MTP_ANDROID_LIB "Build a minimal JNI library for Android smoke builds without MTP libs" OFF)\n` +
|
|
`\n` +
|
|
`find_library(LOG_LIB log)\n` +
|
|
`find_library(ANDROID_LIB android)\n` +
|
|
`\n` +
|
|
`if(ELIZA_SKIP_MTP_ANDROID_LIB)\n` +
|
|
` if(ANDROID_ABI STREQUAL "riscv64")\n` +
|
|
` set(ELIZA_SMOKE_OUTPUT_NAME "llama-cpp-riscv64")\n` +
|
|
` else()\n` +
|
|
` set(ELIZA_SMOKE_OUTPUT_NAME "llama-cpp-arm64")\n` +
|
|
` endif()\n` +
|
|
` file(WRITE "\${CMAKE_CURRENT_BINARY_DIR}/eliza-mtp-smoke.cpp" "extern \\"C\\" int eliza_mtp_smoke() { return 0; }\\n")\n` +
|
|
` add_library(\${ELIZA_SMOKE_OUTPUT_NAME} SHARED "\${CMAKE_CURRENT_BINARY_DIR}/eliza-mtp-smoke.cpp")\n` +
|
|
` target_link_libraries(\${ELIZA_SMOKE_OUTPUT_NAME} PRIVATE \${LOG_LIB} \${ANDROID_LIB})\n` +
|
|
` set_target_properties(\n` +
|
|
` \${ELIZA_SMOKE_OUTPUT_NAME}\n` +
|
|
` PROPERTIES\n` +
|
|
` OUTPUT_NAME "\${ELIZA_SMOKE_OUTPUT_NAME}"\n` +
|
|
` LIBRARY_OUTPUT_DIRECTORY "\${CMAKE_CURRENT_SOURCE_DIR}/jniLibs/\${ANDROID_ABI}"\n` +
|
|
` )\n` +
|
|
` message(STATUS "Building Eliza MTP JNI smoke library for Android \${ANDROID_ABI}")\n` +
|
|
` return()\n` +
|
|
`endif()\n`;
|
|
next = next.replace(
|
|
/(set\(CMAKE_CXX_STANDARD_REQUIRED ON\)\n)/,
|
|
`$1${smokeLibraryBlock}`,
|
|
);
|
|
}
|
|
|
|
if (
|
|
next.includes("ELIZA_REPO_ROOT is required") &&
|
|
!next.includes("packages/native/plugins/llama")
|
|
) {
|
|
throw new Error(
|
|
"[patch-llama-cpp-capacitor] patched CMake still points at the old native plugin path",
|
|
);
|
|
}
|
|
|
|
return writeIfChanged(cmakePath, current, next);
|
|
}
|
|
|
|
function repairPatchedPackage(pkgDir) {
|
|
let changed = false;
|
|
changed = ensureGradleMtpContract(pkgDir) || changed;
|
|
changed = ensureCmakeMtpContract(pkgDir) || changed;
|
|
return changed;
|
|
}
|
|
|
|
function isPatchAlreadyApplied(pkgDir) {
|
|
const cmakePath = join(pkgDir, "android", "src", "main", "CMakeLists.txt");
|
|
const gradlePath = join(pkgDir, "android", "build.gradle");
|
|
if (
|
|
existsSync(cmakePath) &&
|
|
readFileSync(cmakePath, "utf8").includes("llama-cpp-capacitor-eliza-mtp")
|
|
) {
|
|
return true;
|
|
}
|
|
return (
|
|
existsSync(gradlePath) &&
|
|
readFileSync(gradlePath, "utf8").includes("'arm64-v8a', 'riscv64'")
|
|
);
|
|
}
|
|
|
|
for (const { label, dir: pkgDir } of candidates) {
|
|
if (isPatchAlreadyApplied(pkgDir)) {
|
|
skipped++;
|
|
} else {
|
|
// Apply with --forward to skip already-applied hunks, --batch to never
|
|
// prompt interactively. Exit 0 = all hunks applied, exit 1 = some hunks
|
|
// already applied (acceptable), exit 2+ = real error.
|
|
const result = spawnSync(
|
|
"patch",
|
|
["-p1", "--batch", "--forward", "-i", patchFile],
|
|
{ cwd: pkgDir, encoding: "utf8" },
|
|
);
|
|
|
|
if (result.status === 0 || result.status === 1) {
|
|
patched++;
|
|
} else if (process.platform === "win32") {
|
|
// Windows CI ships GNU patch 2.5.9 from Strawberry Perl
|
|
// (C:\Strawberry\c\bin\patch.exe), which aborts with an internal
|
|
// assertion ("patch.c, Line 354, Expression: hunk") on these hunks
|
|
// instead of applying them. This patch only rewrites Android build
|
|
// files (build.gradle / CMakeLists / LlamaCpp.java) that are never
|
|
// built on Windows, so a failed apply here is not fatal — the
|
|
// string-based repair below still runs and Windows never consumes the
|
|
// Android artifacts. Treat it as a skip so `bun install` stays green.
|
|
skipped++;
|
|
console.warn(
|
|
`[patch-llama-cpp-capacitor] \`patch\` failed on Windows for ${label}; Android build files are not consumed here, continuing.`,
|
|
);
|
|
} else {
|
|
failed++;
|
|
console.error(
|
|
`[patch-llama-cpp-capacitor] Failed to patch ${label}:\n${result.stderr}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
try {
|
|
if (repairPatchedPackage(pkgDir)) repaired++;
|
|
} catch (error) {
|
|
failed++;
|
|
console.error(error instanceof Error ? error.message : String(error));
|
|
}
|
|
}
|
|
|
|
// Never fail the install on Windows: the only artifacts this script touches
|
|
// are Android build files, which are not built on Windows, and the Strawberry
|
|
// Perl `patch.exe` there is prone to aborting on otherwise-valid hunks.
|
|
if (failed > 0 && process.platform !== "win32") {
|
|
process.exitCode = 1;
|
|
}
|
|
|
|
if (patched > 0 || skipped > 0 || repaired > 0 || failed > 0) {
|
|
console.log(
|
|
`[patch-llama-cpp-capacitor] patched=${patched} already-applied=${skipped} repaired=${repaired} failed=${failed}`,
|
|
);
|
|
}
|