mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-08-06 09:36:21 +00:00
fix: fix @nousresearch/ui version, update to npm 12
This commit is contained in:
4
.github/workflows/deploy-site.yml
vendored
4
.github/workflows/deploy-site.yml
vendored
@@ -69,6 +69,10 @@ jobs:
|
||||
cache: npm
|
||||
cache-dependency-path: website/package-lock.json
|
||||
|
||||
- name: grab npm 12
|
||||
run: |
|
||||
npm i -g npm@12
|
||||
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
4
.github/workflows/docs-site-checks.yml
vendored
4
.github/workflows/docs-site-checks.yml
vendored
@@ -19,6 +19,10 @@ jobs:
|
||||
cache: npm
|
||||
cache-dependency-path: website/package-lock.json
|
||||
|
||||
- name: grab npm 12
|
||||
run: |
|
||||
npm i -g npm@12
|
||||
|
||||
- name: Install website dependencies
|
||||
uses: ./.github/actions/retry
|
||||
with:
|
||||
|
||||
15
.github/workflows/e2e-desktop.yml
vendored
15
.github/workflows/e2e-desktop.yml
vendored
@@ -41,6 +41,11 @@ jobs:
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
|
||||
- name: grab npm 12
|
||||
run: |
|
||||
npm i -g npm@12
|
||||
|
||||
# Full npm ci (not --ignore-scripts): electron's postinstall
|
||||
# downloads the binary we launch, and node-pty's native build is
|
||||
# needed for the terminal pane.
|
||||
@@ -56,7 +61,7 @@ jobs:
|
||||
# fetching a manifest from raw.githubusercontent.com on EVERY job —
|
||||
# a transient fetch failure fails the whole job (2026-07-28 slice-5
|
||||
# incident). Pinned, the binary downloads directly; no manifest hop.
|
||||
version: "0.9.28"
|
||||
version: '0.9.28'
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
pyproject.toml
|
||||
@@ -106,11 +111,11 @@ jobs:
|
||||
npx playwright test --reporter=list
|
||||
fi
|
||||
env:
|
||||
CI: "true"
|
||||
CI: 'true'
|
||||
# Ensure no real API keys leak into the test env.
|
||||
OPENROUTER_API_KEY: ""
|
||||
OPENAI_API_KEY: ""
|
||||
NOUS_API_KEY: ""
|
||||
OPENROUTER_API_KEY: ''
|
||||
OPENAI_API_KEY: ''
|
||||
NOUS_API_KEY: ''
|
||||
|
||||
# ── Save updated baselines to cache (main only) ───────────────────
|
||||
- name: Save updated baselines to cache
|
||||
|
||||
4
.github/workflows/js-autofix.yml
vendored
4
.github/workflows/js-autofix.yml
vendored
@@ -70,6 +70,10 @@ jobs:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
|
||||
- name: grab npm 12
|
||||
run: |
|
||||
npm i -g npm@12
|
||||
|
||||
# --ignore-scripts: eslint only needs TS sources + eslint packages.
|
||||
- uses: ./.github/actions/retry
|
||||
with:
|
||||
|
||||
10
.github/workflows/js-tests.yml
vendored
10
.github/workflows/js-tests.yml
vendored
@@ -17,6 +17,11 @@ jobs:
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
|
||||
- name: grab npm 12
|
||||
run: |
|
||||
npm i -g npm@12
|
||||
|
||||
- uses: ./.github/actions/retry
|
||||
with:
|
||||
command: npm ci --ignore-scripts
|
||||
@@ -63,6 +68,11 @@ jobs:
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
|
||||
- name: grab npm 12
|
||||
run: |
|
||||
npm i -g npm@12
|
||||
|
||||
- uses: ./.github/actions/retry
|
||||
with:
|
||||
command: npm ci
|
||||
|
||||
4
.npmrc
4
.npmrc
@@ -45,3 +45,7 @@ min-release-age-exclude[]=vite
|
||||
min-release-age-exclude[]=rolldown
|
||||
min-release-age-exclude[]=@rolldown/*
|
||||
min-release-age-exclude[]=@oxc-project/types
|
||||
|
||||
# ink needs
|
||||
min-release-age-exclude[]=lightningcss
|
||||
min-release-age-exclude[]=postcss
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"fix": "npm run lint:fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nous-research/ui": "0.16.0",
|
||||
"@nous-research/ui": "0.18.2",
|
||||
"@tailwindcss/typography": "0.5.20",
|
||||
"@tailwindcss/vite": "4.3.3",
|
||||
"@tauri-apps/api": "2.11.1",
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
"@icons-pack/react-simple-icons": "13.11.1",
|
||||
"@lezer/highlight": "1.2.3",
|
||||
"@nanostores/react": "1.1.0",
|
||||
"@nous-research/ui": "0.16.0",
|
||||
"@nous-research/ui": "0.18.2",
|
||||
"@streamdown/code": "1.1.1",
|
||||
"@tabler/icons-react": "3.44.0",
|
||||
"@tailwindcss/typography": "0.5.20",
|
||||
|
||||
152
nix/desktop.nix
152
nix/desktop.nix
@@ -17,18 +17,6 @@
|
||||
...
|
||||
}:
|
||||
let
|
||||
# apps/shared ships as a file: workspace dep of apps/desktop, so its
|
||||
# source must be in the filtered src tree too.
|
||||
npm = hermesNpmLib.mkNpmPassthru {
|
||||
dirs = [
|
||||
"apps/desktop"
|
||||
"apps/shared"
|
||||
];
|
||||
};
|
||||
|
||||
packageJson = builtins.fromJSON (builtins.readFile (npm.src + "/apps/desktop/package.json"));
|
||||
version = packageJson.version;
|
||||
|
||||
electronHeaders = pkgs.fetchurl {
|
||||
url = "https://artifacts.electronjs.org/headers/dist/v${electron.version}/node-v${electron.version}-headers.tar.gz";
|
||||
sha256 = "sha256-f8bSbLRmtbP93CJAvEBs+sHWDZ1xP2bcpLhC1EnOmZU=";
|
||||
@@ -54,99 +42,101 @@ let
|
||||
throw "hermes-desktop: unsupported host arch for node-pty staging";
|
||||
|
||||
# Build the renderer (dist/ + electron/ + package.json).
|
||||
renderer = pkgs.buildNpmPackage (
|
||||
npm
|
||||
// {
|
||||
pname = "hermes-desktop-renderer";
|
||||
inherit version;
|
||||
doCheck = true;
|
||||
renderer = hermesNpmLib.buildNpmPackage {
|
||||
dirs = [
|
||||
"apps/desktop"
|
||||
"apps/shared"
|
||||
];
|
||||
pname = "hermes-desktop-renderer";
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
doCheck = true;
|
||||
|
||||
mkdir -p apps/desktop/build
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
patchShebangs .
|
||||
mkdir -p apps/desktop/build
|
||||
|
||||
pushd apps/desktop
|
||||
# typecheck :3
|
||||
npm exec tsc -b
|
||||
patchShebangs .
|
||||
|
||||
# build the renderer bundle
|
||||
# vite's emptyOutDir wipes dist/ on every run
|
||||
# so it has to be first
|
||||
npm exec vite build
|
||||
pushd apps/desktop
|
||||
# typecheck :3
|
||||
npm exec -- tsc -b
|
||||
|
||||
# build the electron bundle
|
||||
node scripts/bundle-electron-main.mjs
|
||||
# build the renderer bundle
|
||||
# vite's emptyOutDir wipes dist/ on every run
|
||||
# so it has to be first
|
||||
npm exec -- vite build
|
||||
|
||||
# Compile node-pty against Electron's actual ABI (the nixpkgs
|
||||
# `electron` we ship). Headers come from a pinned fetchurl input
|
||||
# since the sandbox has no network here, so node-gyp's
|
||||
# normal --disturl download path can't run.
|
||||
mkdir -p "$TMPDIR/electron-headers"
|
||||
tar -xzf ${electronHeaders} -C "$TMPDIR/electron-headers" --strip-components=1
|
||||
# build the electron bundle
|
||||
node scripts/bundle-electron-main.mjs
|
||||
|
||||
npm rebuild node-pty \
|
||||
--build-from-source \
|
||||
--runtime=electron \
|
||||
--target=${electron.version} \
|
||||
--nodedir="$TMPDIR/electron-headers" \
|
||||
--disturl="" \
|
||||
--offline
|
||||
# Compile node-pty against Electron's actual ABI (the nixpkgs
|
||||
# `electron` we ship). Headers come from a pinned fetchurl input
|
||||
# since the sandbox has no network here, so node-gyp's
|
||||
# normal --disturl download path can't run.
|
||||
mkdir -p "$TMPDIR/electron-headers"
|
||||
tar -xzf ${electronHeaders} -C "$TMPDIR/electron-headers" --strip-components=1
|
||||
|
||||
# Target platform/arch come from stdenv.hostPlatform, not the
|
||||
# build host's own process.platform/arch.
|
||||
node scripts/stage-native-deps.mjs ${targetPlatform} ${targetArch}
|
||||
popd
|
||||
${lib.getExe hermesNpmLib.node-gyp} rebuild \
|
||||
--directory=../../node_modules/node-pty \
|
||||
--build-from-source \
|
||||
--runtime=electron \
|
||||
--target=${electron.version} \
|
||||
--nodedir="$TMPDIR/electron-headers" \
|
||||
--disturl="" \
|
||||
--offline
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
# Target platform/arch come from stdenv.hostPlatform, not the
|
||||
# build host's own process.platform/arch.
|
||||
node scripts/stage-native-deps.mjs ${targetPlatform} ${targetArch}
|
||||
popd
|
||||
|
||||
checkPhase = ''
|
||||
runHook preCheck
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
pushd apps/desktop
|
||||
checkPhase = ''
|
||||
runHook preCheck
|
||||
|
||||
npm run postbuild
|
||||
pushd apps/desktop
|
||||
|
||||
# validate staged node-pty native binary is present.
|
||||
STAGED_PTY_NODE="./dist/node_modules/node-pty/build/Release/pty.node"
|
||||
npm run postbuild
|
||||
|
||||
if [ ! -f "$STAGED_PTY_NODE" ]; then
|
||||
echo "FATAL: Missing staged node-pty native binary at $STAGED_PTY_NODE"
|
||||
echo "node-pty must be compiled natively"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
popd
|
||||
# validate staged node-pty native binary is present.
|
||||
STAGED_PTY_NODE="./dist/node_modules/node-pty/build/Release/pty.node"
|
||||
|
||||
runHook postCheck
|
||||
'';
|
||||
if [ ! -f "$STAGED_PTY_NODE" ]; then
|
||||
echo "FATAL: Missing staged node-pty native binary at $STAGED_PTY_NODE"
|
||||
echo "node-pty must be compiled natively"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
popd
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out
|
||||
# vite writes to apps/desktop/dist/ (we cd'd there in buildPhase).
|
||||
# stage-native-deps.mjs stages node-pty into dist/node_modules/node-pty,
|
||||
# so copying dist/ wholesale carries the native dep along with the
|
||||
# esbuild bundle that require()s it. apps/desktop/build was created
|
||||
# before the cd.
|
||||
cp -rn apps/desktop/dist $out/
|
||||
runHook postCheck
|
||||
'';
|
||||
|
||||
echo '{"schemaVersion":1,"commit":"nix-dummy-commit","branch":"nix","dirty":false,"source":"nix"}' > $out/install-stamp.json
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out
|
||||
# vite writes to apps/desktop/dist/ (we cd'd there in buildPhase).
|
||||
# stage-native-deps.mjs stages node-pty into dist/node_modules/node-pty,
|
||||
# so copying dist/ wholesale carries the native dep along with the
|
||||
# esbuild bundle that require()s it. apps/desktop/build was created
|
||||
# before the cd.
|
||||
cp -rn apps/desktop/dist $out/
|
||||
|
||||
cp -n apps/desktop/package.json $out/
|
||||
runHook postInstall
|
||||
'';
|
||||
}
|
||||
);
|
||||
echo '{"schemaVersion":1,"commit":"nix-dummy-commit","branch":"nix","dirty":false,"source":"nix"}' > $out/install-stamp.json
|
||||
|
||||
cp -n apps/desktop/package.json $out/
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
in
|
||||
|
||||
# Electron wrapper: nixpkgs' electron binary pointed at the renderer dir.
|
||||
stdenv.mkDerivation {
|
||||
pname = "hermes-desktop";
|
||||
inherit version;
|
||||
inherit (renderer) version;
|
||||
|
||||
dontUnpack = true;
|
||||
dontBuild = true;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
makeWrapper,
|
||||
callPackage,
|
||||
python312,
|
||||
nodejs_26,
|
||||
electron,
|
||||
ripgrep,
|
||||
git,
|
||||
@@ -39,7 +38,6 @@
|
||||
extraDependencyGroups ? [ ],
|
||||
}:
|
||||
let
|
||||
nodejs = nodejs_26;
|
||||
mkHermesVenv =
|
||||
extraDependencyGroups:
|
||||
callPackage ./python.nix {
|
||||
@@ -51,7 +49,7 @@ let
|
||||
hermesVenv = (mkHermesVenv extraDependencyGroups).venv;
|
||||
|
||||
hermesNpmLib = callPackage ./lib.nix {
|
||||
inherit npm-lockfile-fix nodejs;
|
||||
inherit npm-lockfile-fix;
|
||||
};
|
||||
|
||||
hermesTui = callPackage ./tui.nix {
|
||||
@@ -97,7 +95,7 @@ let
|
||||
};
|
||||
|
||||
runtimeDeps = [
|
||||
nodejs
|
||||
hermesNpmLib.nodejs
|
||||
ripgrep
|
||||
git
|
||||
openssh
|
||||
@@ -195,7 +193,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
--set HERMES_WEB_DIST $out/share/hermes-agent/web_dist \
|
||||
--set HERMES_TUI_DIR $out/ui-tui \
|
||||
--set HERMES_PYTHON ${hermesVenv}/bin/python3 \
|
||||
--set HERMES_NODE ${lib.getExe nodejs}${
|
||||
--set HERMES_NODE ${lib.getExe hermesNpmLib.nodejs}${
|
||||
# Fold the line continuation INTO the optionalString: a bare
|
||||
# `\` on the line above an empty expansion would dangle onto a
|
||||
# blank line, ending the makeWrapper command early and running
|
||||
|
||||
172
nix/lib.nix
172
nix/lib.nix
@@ -18,13 +18,46 @@
|
||||
# root to update the lockfile, then `npm ci` if the lockfile changed.
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
npm-lockfile-fix,
|
||||
nodejs,
|
||||
importNpmLock,
|
||||
writeShellScriptBin,
|
||||
writeShellScript,
|
||||
coreutils,
|
||||
callPackage,
|
||||
nodejs_26,
|
||||
symlinkJoin,
|
||||
buildNpmPackage,
|
||||
runCommand,
|
||||
}:
|
||||
let
|
||||
repoRoot = ./..;
|
||||
|
||||
npm12 = callPackage ./npm-12-0-2.nix { };
|
||||
node_gyp_11_4_0 = callPackage ./node-gyp-11-4-0.nix { };
|
||||
nodejs_26_npm_12 = symlinkJoin {
|
||||
name = "nodejs-26-npm-12";
|
||||
paths = [
|
||||
npm12
|
||||
nodejs_26
|
||||
];
|
||||
inherit (nodejs_26) meta passthru;
|
||||
};
|
||||
|
||||
nodejs = nodejs_26_npm_12;
|
||||
|
||||
# Patched hook: just a new derivation that copies and patches the script
|
||||
patchedNpmConfigHook = runCommand "npm-config-hook-patched" { } ''
|
||||
mkdir -p $out/nix-support
|
||||
# Copy all support files from the original hook
|
||||
cp -r ${importNpmLock.npmConfigHook}/nix-support/* $out/nix-support/
|
||||
|
||||
# Change the node gyp config var to avoid the warning with npm12
|
||||
# Replace the node-gyp path with the newer one that supports the new config var
|
||||
substituteInPlace $out/nix-support/setup-hook \
|
||||
--replace-fail 'npm_config_nodedir' 'npm_package_config_node_gyp_nodedir' \
|
||||
--replace-fail 'npm_config_node_gyp' 'npm_config_node_gyp=${node_gyp_11_4_0}/bin/node-gyp'
|
||||
'';
|
||||
|
||||
# ── npm workspace discovery ────────────────────────────────────────
|
||||
# Single source of truth: the `workspaces` field of the root
|
||||
# package.json. Everything below (workspace package.json discovery,
|
||||
@@ -62,7 +95,9 @@ let
|
||||
# Top-level directory of each workspace member, deduplicated. Used to
|
||||
# exclude JS/TS workspace trees from the Python source filter. E.g.
|
||||
# apps/desktop + apps/shared + ui-tui + web → [ "apps" "ui-tui" "web" ].
|
||||
jsWorkspaceTopDirs = lib.unique (map (d: builtins.head (lib.splitString "/" d)) workspaceMemberDirs);
|
||||
jsWorkspaceTopDirs = lib.unique (
|
||||
map (d: builtins.head (lib.splitString "/" d)) workspaceMemberDirs
|
||||
);
|
||||
|
||||
# ── Source filters for reducing rebuild scope ──────────────────────
|
||||
# Changing a .tsx/.mjs file should NOT trigger a Python venv rebuild,
|
||||
@@ -82,8 +117,7 @@ let
|
||||
# JS/TS workspace directories — derived from the npm workspaces
|
||||
# so a new workspace member is excluded from the Python source
|
||||
# without touching this list.
|
||||
jsWorkspaceTopDirs
|
||||
++ [
|
||||
jsWorkspaceTopDirs ++ [
|
||||
# Documentation
|
||||
"docs"
|
||||
"website"
|
||||
@@ -173,7 +207,9 @@ let
|
||||
# resolves each package from the lockfile's own `integrity` hashes, so the
|
||||
# lockfile is the single source of truth — no separate dependency hash to
|
||||
# keep in sync with it.
|
||||
npmDeps = pkgs.importNpmLock.importNpmLock { npmRoot = npmDepsSrc; };
|
||||
npmDeps = importNpmLock.importNpmLock {
|
||||
npmRoot = npmDepsSrc;
|
||||
};
|
||||
|
||||
# Build a per-package npm source: workspace resolution files + the
|
||||
# package's own directory tree(s). Source ROOT is always the repo
|
||||
@@ -188,16 +224,70 @@ let
|
||||
lib.fileset.unions (map (d: repoRoot + "/${d}") dirs)
|
||||
);
|
||||
};
|
||||
|
||||
# Returns a buildNpmPackage-compatible function.
|
||||
|
||||
# `dirs` is the single source of truth for what the package contains:
|
||||
# its first entry is the package's own folder (→ packageJsonPath), and
|
||||
# all entries scope the filtered src. Packages that import source from
|
||||
# another workspace member (file: deps) must list that member's dir too,
|
||||
# e.g. apps/desktop depends on apps/shared.
|
||||
#
|
||||
# Usage:
|
||||
# hermesNpmLib.buildNpmPackage {
|
||||
# dirs = [ "apps/desktop" "apps/shared" ];
|
||||
# buildPhase = '' ... '';
|
||||
# installPhase = '' ... '';
|
||||
# }
|
||||
customBuildNpmPackage =
|
||||
{ dirs, ... }@attrs:
|
||||
let
|
||||
# The package's own folder is the first dir; it carries the
|
||||
# package.json that buildNpmPackage reads.
|
||||
folder = builtins.head dirs;
|
||||
|
||||
# Read package.json from the repo (the filtered src is a store path, but we can read the original)
|
||||
packageJson = builtins.fromJSON (builtins.readFile (repoRoot + "/${folder}/package.json"));
|
||||
defaultPname = packageJson.name or "unknown";
|
||||
defaultVersion = packageJson.version or "0.0.0";
|
||||
|
||||
common = {
|
||||
inherit nodejs npmDeps;
|
||||
# No sourceRoot — the workspace root (with the single package-lock.json)
|
||||
# is auto-detected as sourceRoot by nix. npmRoot stays at "."
|
||||
# so npmConfigHook finds the lockfile there.
|
||||
src = mkNpmSrc dirs;
|
||||
npmConfigHook = patchedNpmConfigHook;
|
||||
npmRoot = ".";
|
||||
ELECTRON_SKIP_BINARY_DOWNLOAD = 1;
|
||||
passthru = {
|
||||
packageJsonPath = "${folder}/package.json";
|
||||
};
|
||||
};
|
||||
|
||||
# Remove `dirs` from the passed attrs (buildNpmPackage doesn't need it)
|
||||
attrsWithoutDirs = removeAttrs attrs [ "dirs" ];
|
||||
|
||||
finalAttrs =
|
||||
common
|
||||
// attrsWithoutDirs
|
||||
// {
|
||||
pname = attrs.pname or defaultPname;
|
||||
version = attrs.version or defaultVersion;
|
||||
};
|
||||
in
|
||||
buildNpmPackage finalAttrs;
|
||||
in
|
||||
{
|
||||
inherit pythonSrc;
|
||||
inherit pythonSrc nodejs;
|
||||
node-gyp = node_gyp_11_4_0;
|
||||
|
||||
# Regenerate the shared root lockfile from scratch and verify all npm
|
||||
# packages still build. Exposed as a runnable package — `nix run
|
||||
# .#update-npm-lockfile` — so it's actually usable, unlike a bin buried
|
||||
# in a build sandbox's PATH. All workspace packages share one lockfile,
|
||||
# so there's a single script (not one per package).
|
||||
updateNpmLockfile = pkgs.writeShellScriptBin "update-npm-lockfile" ''
|
||||
updateNpmLockfile = writeShellScriptBin "update-npm-lockfile" ''
|
||||
set -euo pipefail
|
||||
# DEBUG=1 nix run .#update-npm-lockfile — trace every command
|
||||
[ -n "''${DEBUG:-}" ] && set -x
|
||||
@@ -206,9 +296,9 @@ in
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
rm -rf node_modules/
|
||||
${pkgs.lib.getExe' nodejs "npm"} cache clean --force
|
||||
CI=true ${pkgs.lib.getExe' nodejs "npm"} install --workspaces
|
||||
${pkgs.lib.getExe npm-lockfile-fix} ./package-lock.json
|
||||
${lib.getExe' nodejs "npm"} cache clean --force
|
||||
CI=true ${lib.getExe' nodejs "npm"} install --workspaces
|
||||
${lib.getExe npm-lockfile-fix} ./package-lock.json
|
||||
|
||||
# importNpmLock reads hashes from the lockfile itself — rebuild every
|
||||
# npm package to verify the new lockfile resolves offline.
|
||||
@@ -216,53 +306,7 @@ in
|
||||
echo "Lockfile updated and all npm packages built."
|
||||
'';
|
||||
|
||||
# Returns a buildNpmPackage-compatible attrs set that provides:
|
||||
# src, npmDeps, npmRoot — filtered workspace source + importNpmLock dep set
|
||||
# npmConfigHook — importNpmLock's offline `npm install` hook
|
||||
# passthru.packageJsonPath — relative path to this workspace's package.json
|
||||
# nodejs — fixed nodejs version for all packages we use in the repo
|
||||
#
|
||||
# `dirs` is the single source of truth for what the package contains:
|
||||
# its first entry is the package's own folder (→ packageJsonPath), and
|
||||
# all entries scope the filtered src. Packages that import source from
|
||||
# another workspace member (file: deps) must list that member's dir too,
|
||||
# e.g. apps/desktop depends on apps/shared.
|
||||
#
|
||||
# Usage:
|
||||
# npm = hermesNpmLib.mkNpmPassthru { dirs = [ "ui-tui" ]; };
|
||||
# npm = hermesNpmLib.mkNpmPassthru { dirs = [ "apps/desktop" "apps/shared" ]; };
|
||||
# pkgs.buildNpmPackage (npm // {
|
||||
# pname = "hermes-tui";
|
||||
# inherit version;
|
||||
# buildPhase = '' ... '';
|
||||
# installPhase = '' ... '';
|
||||
# })
|
||||
mkNpmPassthru =
|
||||
{ dirs }:
|
||||
let
|
||||
# The package's own folder is the first dir; it carries the
|
||||
# package.json that buildNpmPackage reads.
|
||||
folder = builtins.head dirs;
|
||||
# No sourceRoot — the workspace root (with the single package-lock.json)
|
||||
# is auto-detected as sourceRoot by nix. npmRoot stays at "."
|
||||
# so npmConfigHook finds the lockfile there.
|
||||
in
|
||||
{
|
||||
inherit nodejs npmDeps;
|
||||
src = mkNpmSrc dirs;
|
||||
# importNpmLock's hook installs the rewritten lockfile (every `resolved`
|
||||
# rewritten to a /nix/store file: path) into the unpacked workspace and
|
||||
# runs `npm install` offline, so every workspace member's dependencies
|
||||
# resolve without network access.
|
||||
npmConfigHook = pkgs.importNpmLock.npmConfigHook;
|
||||
npmRoot = ".";
|
||||
|
||||
ELECTRON_SKIP_BINARY_DOWNLOAD = 1;
|
||||
|
||||
passthru = {
|
||||
packageJsonPath = "${folder}/package.json";
|
||||
};
|
||||
};
|
||||
buildNpmPackage = customBuildNpmPackage;
|
||||
|
||||
# Single devshell hook for all npm workspace packages.
|
||||
#
|
||||
@@ -272,23 +316,23 @@ in
|
||||
# 2. If the lockfile changed, runs `npm ci`
|
||||
mkNpmDevShellHook =
|
||||
packageJsonPaths:
|
||||
pkgs.writeShellScript "npm-dev-hook" ''
|
||||
writeShellScript "npm-dev-hook" ''
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
|
||||
# Stamp all workspace package.jsons into one file.
|
||||
STAMP_DIR=".nix-stamps"
|
||||
STAMP="$STAMP_DIR/npm-package-jsons"
|
||||
STAMP_VALUE=$(
|
||||
${pkgs.coreutils}/bin/sha256sum ${
|
||||
pkgs.lib.concatMapStringsSep " " (p: "\"$REPO_ROOT/${p}\"") packageJsonPaths
|
||||
} 2>/dev/null | ${pkgs.coreutils}/bin/sort | ${pkgs.coreutils}/bin/sha256sum | awk '{print $1}'
|
||||
${coreutils}/bin/sha256sum ${
|
||||
lib.concatMapStringsSep " " (p: "\"$REPO_ROOT/${p}\"") packageJsonPaths
|
||||
} 2>/dev/null | ${coreutils}/bin/sort | ${coreutils}/bin/sha256sum | awk '{print $1}'
|
||||
)
|
||||
|
||||
PKG_CHANGED=false
|
||||
if [ ! -f "$STAMP" ] || [ "$(cat "$STAMP")" != "$STAMP_VALUE" ]; then
|
||||
PKG_CHANGED=true
|
||||
echo "npm: package.json changed, updating lockfile..."
|
||||
( cd "$REPO_ROOT" && ${pkgs.lib.getExe' nodejs "npm"} i --package-lock-only --silent --no-fund --no-audit 2>/dev/null )
|
||||
( cd "$REPO_ROOT" && ${lib.getExe' nodejs "npm"} i --package-lock-only --silent --no-fund --no-audit 2>/dev/null )
|
||||
mkdir -p "$STAMP_DIR"
|
||||
echo "$STAMP_VALUE" > "$STAMP"
|
||||
fi
|
||||
@@ -299,7 +343,7 @@ in
|
||||
LOCK_STAMP_VALUE=$(sha256sum "$REPO_ROOT/package-lock.json" 2>/dev/null | awk '{print $1}')
|
||||
if [ ! -f "$LOCK_STAMP" ] || [ "$(cat "$LOCK_STAMP")" != "$LOCK_STAMP_VALUE" ]; then
|
||||
echo "npm: package-lock.json changed, running npm ci..."
|
||||
( cd "$REPO_ROOT" && CI=true ${pkgs.lib.getExe' nodejs "npm"} ci --silent --no-fund --no-audit 2>/dev/null )
|
||||
( cd "$REPO_ROOT" && CI=true ${lib.getExe' nodejs "npm"} ci --silent --no-fund --no-audit 2>/dev/null )
|
||||
mkdir -p "$STAMP_DIR"
|
||||
echo "$LOCK_STAMP_VALUE" > "$LOCK_STAMP"
|
||||
fi
|
||||
|
||||
5246
nix/node-gyp-11-4-0-package-lock.json
generated
Normal file
5246
nix/node-gyp-11-4-0-package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
40
nix/node-gyp-11-4-0.nix
Normal file
40
nix/node-gyp-11-4-0.nix
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
buildNpmPackage,
|
||||
fetchFromGitHub,
|
||||
nodejs,
|
||||
lib,
|
||||
}:
|
||||
|
||||
let
|
||||
node-gyp-11_4_0 = buildNpmPackage rec {
|
||||
pname = "node-gyp";
|
||||
version = "11.4.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "nodejs";
|
||||
repo = "node-gyp";
|
||||
rev = "refs/tags/v${version}";
|
||||
hash = "sha256-VtomUV+0kTp34IuS0D0dR4ZMWpk4Ptpk1CBP8rdW2a4=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
ln -s ${./node-gyp-11-4-0-package-lock.json} package-lock.json
|
||||
'';
|
||||
|
||||
npmDepsHash = "sha256-P25m02VxIXkPD7rYI2Wki9+levrtNg2xk8pU+nEUXsE=";
|
||||
|
||||
npmDepsFetcherVersion = 2;
|
||||
|
||||
dontNpmBuild = true;
|
||||
|
||||
makeWrapperArgs = [ "--set npm_config_nodedir ${nodejs}" ];
|
||||
|
||||
meta = {
|
||||
description = "Node.js native addon build tool";
|
||||
homepage = "https://github.com/nodejs/node-gyp";
|
||||
license = lib.licenses.mit;
|
||||
mainProgram = "node-gyp";
|
||||
};
|
||||
};
|
||||
in
|
||||
node-gyp-11_4_0
|
||||
29
nix/npm-12-0-2.nix
Normal file
29
nix/npm-12-0-2.nix
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
stdenv,
|
||||
makeWrapper,
|
||||
fetchurl,
|
||||
nodejs_26,
|
||||
}:
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "npm";
|
||||
version = "12.0.2";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://registry.npmjs.org/npm/-/npm-${version}.tgz";
|
||||
hash = "sha256-XbuGxx0HoZV/LpBzQJLdali9zZ68LY1ByhxuaiHTZOE=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
dontBuild = true;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/lib/npm12
|
||||
cp -r . $out/lib/npm12/
|
||||
mkdir -p $out/bin
|
||||
|
||||
makeWrapper ${nodejs_26}/bin/node $out/bin/npm \
|
||||
--add-flags "$out/lib/npm12/bin/npm-cli.js"
|
||||
makeWrapper ${nodejs_26}/bin/node $out/bin/npx \
|
||||
--add-flags "$out/lib/npm12/bin/npx-cli.js"
|
||||
'';
|
||||
}
|
||||
@@ -45,6 +45,10 @@
|
||||
in
|
||||
{
|
||||
packages = {
|
||||
node-gyp =
|
||||
(pkgs.callPackage ./lib.nix {
|
||||
inherit (pkgs) npm-lockfile-fix;
|
||||
}).node-gyp;
|
||||
default = full;
|
||||
|
||||
inherit minimal;
|
||||
|
||||
23
nix/tui.nix
23
nix/tui.nix
@@ -1,19 +1,10 @@
|
||||
# nix/tui.nix — Hermes TUI (Ink/React) compiled with tsc and bundled
|
||||
{ pkgs, hermesNpmLib, ... }:
|
||||
let
|
||||
npm = hermesNpmLib.mkNpmPassthru {
|
||||
dirs = [
|
||||
"ui-tui"
|
||||
"apps/shared"
|
||||
];
|
||||
};
|
||||
|
||||
packageJson = builtins.fromJSON (builtins.readFile (npm.src + "/ui-tui/package.json"));
|
||||
version = packageJson.version;
|
||||
in
|
||||
pkgs.buildNpmPackage (npm // {
|
||||
pname = "hermes-tui";
|
||||
inherit version;
|
||||
{ hermesNpmLib, ... }:
|
||||
hermesNpmLib.buildNpmPackage {
|
||||
dirs = [
|
||||
"ui-tui"
|
||||
"apps/shared"
|
||||
];
|
||||
|
||||
doCheck = false;
|
||||
|
||||
@@ -35,4 +26,4 @@ pkgs.buildNpmPackage (npm // {
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
})
|
||||
}
|
||||
|
||||
26
nix/web.nix
26
nix/web.nix
@@ -1,21 +1,13 @@
|
||||
# nix/web.nix — Hermes Web Dashboard (Vite/React) frontend build
|
||||
{ pkgs, hermesNpmLib, ... }:
|
||||
let
|
||||
# @hermes/shared ships as a file: workspace dep of web, so its source
|
||||
# must be in the filtered src tree too.
|
||||
npm = hermesNpmLib.mkNpmPassthru {
|
||||
dirs = [
|
||||
"web"
|
||||
"apps/shared"
|
||||
];
|
||||
};
|
||||
{ hermesNpmLib, ... }:
|
||||
hermesNpmLib.buildNpmPackage {
|
||||
dirs = [
|
||||
"web"
|
||||
|
||||
packageJson = builtins.fromJSON (builtins.readFile (npm.src + "/web/package.json"));
|
||||
version = packageJson.version;
|
||||
in
|
||||
pkgs.buildNpmPackage (npm // {
|
||||
pname = "hermes-web";
|
||||
inherit version;
|
||||
# @hermes/shared ships as a file: workspace dep of web, so its source
|
||||
# must be in the filtered src tree too.
|
||||
"apps/shared"
|
||||
];
|
||||
|
||||
doCheck = false;
|
||||
|
||||
@@ -38,4 +30,4 @@ pkgs.buildNpmPackage (npm // {
|
||||
cp -r web/dist $out
|
||||
runHook postInstall
|
||||
'';
|
||||
})
|
||||
}
|
||||
|
||||
3929
package-lock.json
generated
3929
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -54,7 +54,7 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0",
|
||||
"npm": "<11.10.0 || >=12.0.0"
|
||||
"npm": ">=12.0.0"
|
||||
},
|
||||
"allowScripts": {
|
||||
"unicode-animations": false,
|
||||
|
||||
@@ -22,13 +22,17 @@
|
||||
"@hermes/ink": "file:./packages/hermes-ink",
|
||||
"@hermes/shared": "file:../apps/shared",
|
||||
"@nanostores/react": "1.1.0",
|
||||
"ink": "6.8.0",
|
||||
"ink-text-input": "6.0.0",
|
||||
"nanostores": "1.4.0",
|
||||
"react": "19.2.7",
|
||||
"undici": "6.27.0",
|
||||
"unicode-animations": "1.0.3"
|
||||
},
|
||||
"overrides": {
|
||||
"ink-text-input": {
|
||||
"ink": "npm:@hermes/ink@0.0.1"
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "22.20.1",
|
||||
"@types/react": "19.2.17",
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@hermes/shared": "file:../apps/shared",
|
||||
"@nous-research/ui": "0.16.0",
|
||||
"@nous-research/ui": "0.18.2",
|
||||
"@observablehq/plot": "0.6.17",
|
||||
"@react-three/fiber": "9.6.1",
|
||||
"@tailwindcss/vite": "4.3.3",
|
||||
|
||||
Reference in New Issue
Block a user