mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
fix(nix): package local speech worker (#1587)
* fix(nix): package local speech worker * fix(nix): reuse sherpa package helper * fix(nix): patch sherpa-onnx prebuilt binaries for NixOS libstdc++ The prebuilt sherpa-onnx-linux-x64 .so files link against libstdc++.so.6 which is not on the NixOS library path. Add autoPatchelfHook to fix ELF RPATHs and stdenv.cc.cc.lib to provide the C++ runtime, resolving the "Failed to load model because protobuf parsing failed" SIGABRT at speech worker startup.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
nodejs_22,
|
||||
python3,
|
||||
makeWrapper,
|
||||
autoPatchelfHook,
|
||||
# node-pty needs libuv headers on Linux
|
||||
libuv,
|
||||
# Exposed so downstream flakes that follow a different nixpkgs revision
|
||||
@@ -59,10 +60,13 @@ buildNpmPackage rec {
|
||||
nativeBuildInputs = [
|
||||
python3 # for node-gyp (node-pty compilation)
|
||||
makeWrapper
|
||||
] ++ lib.optionals stdenv.hostPlatform.isLinux [
|
||||
autoPatchelfHook
|
||||
];
|
||||
|
||||
buildInputs = lib.optionals stdenv.hostPlatform.isLinux [
|
||||
libuv
|
||||
stdenv.cc.cc.lib # libstdc++ for sherpa-onnx prebuilt binaries
|
||||
];
|
||||
|
||||
# Don't use the default npm build hook — we need a custom build sequence
|
||||
@@ -71,10 +75,9 @@ buildNpmPackage rec {
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
# Rebuild only node-pty (native addon for terminal emulation).
|
||||
# Speech-related native modules (sherpa-onnx, onnxruntime-node) are
|
||||
# intentionally left unbuilt — they're lazily loaded and gracefully
|
||||
# degrade when unavailable.
|
||||
# Rebuild only node-pty (native addon for terminal emulation). The sherpa
|
||||
# speech runtime ships prebuilt platform packages and is copied into the
|
||||
# daemon closure by scripts/trace-daemon.mjs.
|
||||
npm rebuild node-pty
|
||||
|
||||
# Build all server packages in dependency order (defined in package.json)
|
||||
@@ -89,7 +92,7 @@ buildNpmPackage rec {
|
||||
|
||||
# Compute the daemon's runtime closure by static module-graph tracing
|
||||
# (@vercel/nft from supervisor-entrypoint.js, cli/dist/index.js, and the
|
||||
# forked terminal-worker-process.js) plus an explicit list of non-JS
|
||||
# forked terminal/speech worker processes) plus an explicit list of non-JS
|
||||
# assets read at runtime. The trace script is the single source of
|
||||
# truth for what the daemon needs at $out — auditable in plain JS, no
|
||||
# npm hoisting / .bin / workspace-symlink footguns.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
// Emit the set of files the daemon and CLI need at runtime, computed by
|
||||
// static module-graph tracing (@vercel/nft) from the three entry points.
|
||||
// static module-graph tracing (@vercel/nft) from the daemon entry points.
|
||||
// Used by nix/package.nix's installPhase to materialize $out/lib/paseo
|
||||
// with only the bytes the daemon actually loads — no Expo, RN, Metro,
|
||||
// Electron, ML stacks, or other non-daemon workspace bloat.
|
||||
@@ -15,16 +15,27 @@
|
||||
import { nodeFileTrace } from "@vercel/nft";
|
||||
import { glob } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
|
||||
const REPO_ROOT = path.resolve(import.meta.dirname, "..");
|
||||
|
||||
// Three entry points. The terminal worker is forked into its own Node
|
||||
// process and has its own require tree (node-pty, etc.) — nft does not
|
||||
// follow fork boundaries, so it must be traced separately.
|
||||
const { sherpaPlatformPackageName } = await import(
|
||||
pathToFileURL(
|
||||
path.join(
|
||||
REPO_ROOT,
|
||||
"packages/server/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.js",
|
||||
),
|
||||
).href
|
||||
);
|
||||
|
||||
// Daemon entry points. Workers forked into their own Node processes have
|
||||
// independent require trees; nft does not follow fork boundaries, so trace
|
||||
// them separately.
|
||||
const entries = [
|
||||
"packages/cli/dist/index.js",
|
||||
"packages/server/dist/scripts/supervisor-entrypoint.js",
|
||||
"packages/server/dist/server/terminal/terminal-worker-process.js",
|
||||
"packages/server/dist/server/server/speech/providers/local/worker-process.js",
|
||||
];
|
||||
|
||||
// Files read at runtime via fs APIs rather than `require`. nft only
|
||||
@@ -44,19 +55,22 @@ const additionalInputs = [
|
||||
// the Nix derivation builds for one platform at a time and ships only
|
||||
// its own binaries.
|
||||
`node_modules/node-pty/prebuilds/${process.platform}-${process.arch}/**`,
|
||||
// sherpa-onnx-node dynamically resolves a platform-specific native package.
|
||||
// Copy the wrapper plus the host platform package explicitly.
|
||||
"node_modules/sherpa-onnx-node/**",
|
||||
`node_modules/${sherpaPlatformPackageName()}/**`,
|
||||
];
|
||||
|
||||
// Trace.
|
||||
const { fileList, warnings } = await nodeFileTrace(entries, {
|
||||
base: REPO_ROOT,
|
||||
// Tolerate the conditional / dynamic patterns we already audited:
|
||||
// sherpa-onnx-${platform}-${arch} package resolution (sherpa is
|
||||
// intentionally not built in the Nix sandbox; voice features degrade
|
||||
// gracefully when unavailable), and a handful of test-only requires
|
||||
// that get tree-shaken out by tsc.
|
||||
// sherpa-onnx-${platform}-${arch} package resolution (the host package
|
||||
// is copied explicitly above), and a handful of test-only requires that
|
||||
// get tree-shaken out by tsc.
|
||||
ignore: [
|
||||
// Cross-platform native packages for the sherpa speech runtime;
|
||||
// unsupported in the Nix build, lazily loaded when present.
|
||||
// only the host platform package is needed at runtime.
|
||||
"sherpa-onnx-*/**",
|
||||
// Platform-specific clipboard variants; only the host's variant
|
||||
// is needed at runtime, and the package's index.js resolver picks
|
||||
|
||||
Reference in New Issue
Block a user