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:
+8
-5
@@ -5,6 +5,7 @@
|
|||||||
nodejs_22,
|
nodejs_22,
|
||||||
python3,
|
python3,
|
||||||
makeWrapper,
|
makeWrapper,
|
||||||
|
autoPatchelfHook,
|
||||||
# node-pty needs libuv headers on Linux
|
# node-pty needs libuv headers on Linux
|
||||||
libuv,
|
libuv,
|
||||||
# Exposed so downstream flakes that follow a different nixpkgs revision
|
# Exposed so downstream flakes that follow a different nixpkgs revision
|
||||||
@@ -59,10 +60,13 @@ buildNpmPackage rec {
|
|||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
python3 # for node-gyp (node-pty compilation)
|
python3 # for node-gyp (node-pty compilation)
|
||||||
makeWrapper
|
makeWrapper
|
||||||
|
] ++ lib.optionals stdenv.hostPlatform.isLinux [
|
||||||
|
autoPatchelfHook
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs = lib.optionals stdenv.hostPlatform.isLinux [
|
buildInputs = lib.optionals stdenv.hostPlatform.isLinux [
|
||||||
libuv
|
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
|
# Don't use the default npm build hook — we need a custom build sequence
|
||||||
@@ -71,10 +75,9 @@ buildNpmPackage rec {
|
|||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
runHook preBuild
|
runHook preBuild
|
||||||
|
|
||||||
# Rebuild only node-pty (native addon for terminal emulation).
|
# Rebuild only node-pty (native addon for terminal emulation). The sherpa
|
||||||
# Speech-related native modules (sherpa-onnx, onnxruntime-node) are
|
# speech runtime ships prebuilt platform packages and is copied into the
|
||||||
# intentionally left unbuilt — they're lazily loaded and gracefully
|
# daemon closure by scripts/trace-daemon.mjs.
|
||||||
# degrade when unavailable.
|
|
||||||
npm rebuild node-pty
|
npm rebuild node-pty
|
||||||
|
|
||||||
# Build all server packages in dependency order (defined in package.json)
|
# 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
|
# Compute the daemon's runtime closure by static module-graph tracing
|
||||||
# (@vercel/nft from supervisor-entrypoint.js, cli/dist/index.js, and the
|
# (@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
|
# 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
|
# truth for what the daemon needs at $out — auditable in plain JS, no
|
||||||
# npm hoisting / .bin / workspace-symlink footguns.
|
# npm hoisting / .bin / workspace-symlink footguns.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
// Emit the set of files the daemon and CLI need at runtime, computed by
|
// 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
|
// Used by nix/package.nix's installPhase to materialize $out/lib/paseo
|
||||||
// with only the bytes the daemon actually loads — no Expo, RN, Metro,
|
// with only the bytes the daemon actually loads — no Expo, RN, Metro,
|
||||||
// Electron, ML stacks, or other non-daemon workspace bloat.
|
// Electron, ML stacks, or other non-daemon workspace bloat.
|
||||||
@@ -15,16 +15,27 @@
|
|||||||
import { nodeFileTrace } from "@vercel/nft";
|
import { nodeFileTrace } from "@vercel/nft";
|
||||||
import { glob } from "node:fs/promises";
|
import { glob } from "node:fs/promises";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
import { pathToFileURL } from "node:url";
|
||||||
|
|
||||||
const REPO_ROOT = path.resolve(import.meta.dirname, "..");
|
const REPO_ROOT = path.resolve(import.meta.dirname, "..");
|
||||||
|
|
||||||
// Three entry points. The terminal worker is forked into its own Node
|
const { sherpaPlatformPackageName } = await import(
|
||||||
// process and has its own require tree (node-pty, etc.) — nft does not
|
pathToFileURL(
|
||||||
// follow fork boundaries, so it must be traced separately.
|
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 = [
|
const entries = [
|
||||||
"packages/cli/dist/index.js",
|
"packages/cli/dist/index.js",
|
||||||
"packages/server/dist/scripts/supervisor-entrypoint.js",
|
"packages/server/dist/scripts/supervisor-entrypoint.js",
|
||||||
"packages/server/dist/server/terminal/terminal-worker-process.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
|
// 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
|
// the Nix derivation builds for one platform at a time and ships only
|
||||||
// its own binaries.
|
// its own binaries.
|
||||||
`node_modules/node-pty/prebuilds/${process.platform}-${process.arch}/**`,
|
`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.
|
// Trace.
|
||||||
const { fileList, warnings } = await nodeFileTrace(entries, {
|
const { fileList, warnings } = await nodeFileTrace(entries, {
|
||||||
base: REPO_ROOT,
|
base: REPO_ROOT,
|
||||||
// Tolerate the conditional / dynamic patterns we already audited:
|
// Tolerate the conditional / dynamic patterns we already audited:
|
||||||
// sherpa-onnx-${platform}-${arch} package resolution (sherpa is
|
// sherpa-onnx-${platform}-${arch} package resolution (the host package
|
||||||
// intentionally not built in the Nix sandbox; voice features degrade
|
// is copied explicitly above), and a handful of test-only requires that
|
||||||
// gracefully when unavailable), and a handful of test-only requires
|
// get tree-shaken out by tsc.
|
||||||
// that get tree-shaken out by tsc.
|
|
||||||
ignore: [
|
ignore: [
|
||||||
// Cross-platform native packages for the sherpa speech runtime;
|
// 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-*/**",
|
"sherpa-onnx-*/**",
|
||||||
// Platform-specific clipboard variants; only the host's variant
|
// Platform-specific clipboard variants; only the host's variant
|
||||||
// is needed at runtime, and the package's index.js resolver picks
|
// is needed at runtime, and the package's index.js resolver picks
|
||||||
|
|||||||
Reference in New Issue
Block a user