From 2d3c041338e47c77c8f6a6d1895cced7bd52d1fc Mon Sep 17 00:00:00 2001 From: ethernet Date: Thu, 30 Apr 2026 13:22:30 -0400 Subject: [PATCH] change(nix): dedupe nix lockfile checking scripts in ci (#18000) * change(nix): dedupe nix lockfile checking scripts in ci * feat(nix): make .#fix-lockfiles run --apply if no args passed * fix(nix): use same nodejs version everywhere & small lints - prevent lockfile thrashing while using nix :3 - use lib.getExe instead of raw /bin/ paths - use inputs'.self instead of passing system in manually * fix(nix): update lock files yet again (hopefully for the last time) * fix(nix): align indentation of collision check echo --------- Co-authored-by: Hermes Agent --- .github/workflows/nix-lockfile-check.yml | 76 ------------------- .github/workflows/nix-lockfile-fix.yml | 4 +- .github/workflows/nix.yml | 82 ++++++++++++++++++++ nix/checks.nix | 6 +- nix/devShell.nix | 37 ++++----- nix/hermes-agent.nix | 95 +++++++++++++----------- nix/lib.nix | 25 ++++--- nix/tui.nix | 2 +- nix/web.nix | 6 +- ui-tui/package-lock.json | 41 ++++++---- 10 files changed, 203 insertions(+), 171 deletions(-) delete mode 100644 .github/workflows/nix-lockfile-check.yml diff --git a/.github/workflows/nix-lockfile-check.yml b/.github/workflows/nix-lockfile-check.yml deleted file mode 100644 index da82826ce9..0000000000 --- a/.github/workflows/nix-lockfile-check.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Nix Lockfile Check - -on: - pull_request: - workflow_dispatch: - -permissions: - contents: read - pull-requests: write - -concurrency: - group: nix-lockfile-check-${{ github.ref }} - cancel-in-progress: true - -jobs: - nix-lockfile-check: - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - - uses: ./.github/actions/nix-setup - with: - cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - - - name: Resolve head SHA - id: sha - shell: bash - run: | - FULL="${{ github.event.pull_request.head.sha || github.sha }}" - echo "full=$FULL" >> "$GITHUB_OUTPUT" - echo "short=${FULL:0:7}" >> "$GITHUB_OUTPUT" - - - name: Check lockfile hashes - id: check - continue-on-error: true - env: - LINK_SHA: ${{ steps.sha.outputs.full }} - run: nix run .#fix-lockfiles -- --check - - - name: Fail if check crashed without reporting - if: steps.check.outputs.stale != 'true' && steps.check.outputs.stale != 'false' - run: | - echo "::error::fix-lockfiles exited without reporting stale status — likely an infrastructure or script failure" - exit 1 - - - name: Post sticky PR comment (stale) - if: steps.check.outputs.stale == 'true' && github.event_name == 'pull_request' - uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1 - with: - header: nix-lockfile-check - message: | - ### ⚠️ npm lockfile hash out of date - - Checked against commit [`${{ steps.sha.outputs.short }}`](${{ github.server_url }}/${{ github.repository }}/commit/${{ steps.sha.outputs.full }}) (PR head at check time). - - The `hash = "sha256-..."` line in these nix files no longer matches the committed `package-lock.json`: - - ${{ steps.check.outputs.report }} - - #### Apply the fix - - - [ ] **Apply lockfile fix** — tick to push a commit with the correct hashes to this PR branch - - Or [run the Nix Lockfile Fix workflow](${{ github.server_url }}/${{ github.repository }}/actions/workflows/nix-lockfile-fix.yml) manually (pass PR `#${{ github.event.pull_request.number }}`) - - Or locally: `nix run .#fix-lockfiles -- --apply` and commit the diff - - - name: Clear sticky PR comment (resolved) - if: steps.check.outputs.stale == 'false' && github.event_name == 'pull_request' - uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1 - with: - header: nix-lockfile-check - delete: true - - - name: Fail if stale - if: steps.check.outputs.stale == 'true' - run: exit 1 diff --git a/.github/workflows/nix-lockfile-fix.yml b/.github/workflows/nix-lockfile-fix.yml index 2682f8b504..b5e02c341b 100644 --- a/.github/workflows/nix-lockfile-fix.yml +++ b/.github/workflows/nix-lockfile-fix.yml @@ -28,7 +28,7 @@ concurrency: jobs: # ── Auto-fix on main ─────────────────────────────────────────────── # Fires when a push to main touches package.json or package-lock.json - # in ui-tui/ or web/. Runs fix-lockfiles --apply and pushes the hash + # in ui-tui/ or web/. Runs fix-lockfiles and pushes the hash # update commit directly to main so Nix builds never stay broken. # # Safety invariants: @@ -207,7 +207,7 @@ jobs: - name: Apply lockfile hashes id: apply - run: nix run .#fix-lockfiles -- --apply + run: nix run .#fix-lockfiles - name: Commit & push if: steps.apply.outputs.changed == 'true' diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index f0d5bf719e..9a8f45a7c1 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -7,6 +7,7 @@ on: permissions: contents: read + pull-requests: write concurrency: group: nix-${{ github.ref }} @@ -24,12 +25,93 @@ jobs: - uses: ./.github/actions/nix-setup with: cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + + - name: Resolve head SHA + if: github.event_name == 'pull_request' + id: sha + shell: bash + run: | + FULL="${{ github.event.pull_request.head.sha || github.sha }}" + echo "full=$FULL" >> "$GITHUB_OUTPUT" + echo "short=${FULL:0:7}" >> "$GITHUB_OUTPUT" + - name: Check flake + id: flake if: runner.os == 'Linux' + continue-on-error: true run: nix flake check --print-build-logs + - name: Build package + id: build if: runner.os == 'Linux' + continue-on-error: true run: nix build --print-build-logs + + # When the real Nix build fails, run a targeted diagnostic to see if + # the failure is specifically a stale npm lockfile hash in one of the + # known npm subpackages (tui / web). This avoids surfacing a generic + # "build failed" message when the fix is a single known command. + - name: Diagnose npm lockfile hashes + id: hash_check + if: (steps.flake.outcome == 'failure' || steps.build.outcome == 'failure') && runner.os == 'Linux' + continue-on-error: true + env: + LINK_SHA: ${{ steps.sha.outputs.full }} + run: nix run .#fix-lockfiles -- --check + + # If fix-lockfiles itself crashes (infrastructure blip, cache throttle, + # etc.) it won't set stale=true/false. Treat that as a distinct failure + # mode rather than silently ignoring it. + - name: Fail if hash check crashed without reporting + if: steps.hash_check.outcome == 'failure' && steps.hash_check.outputs.stale != 'true' && steps.hash_check.outputs.stale != 'false' + run: | + echo "::error::fix-lockfiles exited without reporting stale status — likely an infrastructure or script failure" + exit 1 + + - name: Post sticky PR comment (stale hashes) + if: steps.hash_check.outputs.stale == 'true' && github.event_name == 'pull_request' + uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1 + with: + header: nix-lockfile-check + message: | + ### ⚠️ npm lockfile hash out of date + + Checked against commit [`${{ steps.sha.outputs.short }}`](${{ github.server_url }}/${{ github.repository }}/commit/${{ steps.sha.outputs.full }}) (PR head at check time). + + The `hash = "sha256-..."` line in these nix files no longer matches the committed `package-lock.json`: + + ${{ steps.hash_check.outputs.report }} + + #### Apply the fix + + - [ ] **Apply lockfile fix** — tick to push a commit with the correct hashes to this PR branch + - Or [run the Nix Lockfile Fix workflow](${{ github.server_url }}/${{ github.repository }}/actions/workflows/nix-lockfile-fix.yml) manually (pass PR `#${{ github.event.pull_request.number }}`) + - Or locally: `nix run .#fix-lockfiles` and commit the diff + + # Clear the sticky comment when either the build passed outright (no + # hash check needed) or the hash check explicitly returned stale=false + # (build failed for a non-hash reason). + - name: Clear sticky PR comment (resolved) + if: | + github.event_name == 'pull_request' && + runner.os == 'Linux' && + (steps.hash_check.outputs.stale == 'false' || + (steps.flake.outcome == 'success' && steps.build.outcome == 'success')) + uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1 + with: + header: nix-lockfile-check + delete: true + + - name: Final fail if build or flake failed + if: steps.flake.outcome == 'failure' || steps.build.outcome == 'failure' + run: | + if [ "${{ steps.hash_check.outputs.stale }}" == "true" ]; then + echo "::error::Nix build failed due to stale npm lockfile hash. Run: nix run .#fix-lockfiles" + else + echo "::error::Nix build/flake check failed. See logs above." + fi + exit 1 + - name: Evaluate flake (macOS) if: runner.os == 'macOS' run: nix flake show --json > /dev/null diff --git a/nix/checks.nix b/nix/checks.nix index bb8801a0b8..8adb56628d 100644 --- a/nix/checks.nix +++ b/nix/checks.nix @@ -4,9 +4,9 @@ # transitive deps like onnxruntime that lack compatible wheels on # aarch64-darwin. The package and devShell still work on macOS. { inputs, ... }: { - perSystem = { pkgs, system, lib, ... }: + perSystem = { pkgs, lib, self', ... }: let - hermes-agent = inputs.self.packages.${system}.default; + hermes-agent = self'.packages.default; hermesVenv = hermes-agent.hermesVenv; configMergeScript = pkgs.callPackage ./configMergeScript.nix { }; @@ -51,7 +51,7 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2) failMsg = lib.concatMapStringsSep "\n" (r: " - ${r.sys}") failures; in pkgs.runCommand "hermes-cross-eval" { } ( if failures != [] then - builtins.throw "Package fails to evaluate on:\n${failMsg}" + throw "Package fails to evaluate on:\n${failMsg}" else '' echo "PASS: package evaluates on all ${toString (builtins.length targetSystems)} platforms" mkdir -p $out diff --git a/nix/devShell.nix b/nix/devShell.nix index d0d56e40b0..82b0dc1fc8 100644 --- a/nix/devShell.nix +++ b/nix/devShell.nix @@ -1,29 +1,30 @@ # nix/devShell.nix — Dev shell that delegates setup to each package # -# Each package in inputsFrom exposes passthru.devShellHook — a bash snippet +# Each package in inputsFrom might expose passthru.devShellHook — a bash snippet # with stamp-checked setup logic. This file collects and runs them all. -{ inputs, ... }: { - perSystem = { pkgs, system, ... }: +{ ... }: +{ + perSystem = + { pkgs, self', ... }: let - hermes-agent = inputs.self.packages.${system}.default; - hermes-tui = inputs.self.packages.${system}.tui; - hermes-web = inputs.self.packages.${system}.web; - packages = [ hermes-agent hermes-tui hermes-web ]; - in { + packages = builtins.attrValues self'.packages; + in + { devShells.default = pkgs.mkShell { inputsFrom = packages; packages = with pkgs; [ - python312 uv nodejs_22 ripgrep git openssh ffmpeg + uv ]; - - shellHook = let - hooks = map (p: p.passthru.devShellHook or "") packages; - combined = pkgs.lib.concatStringsSep "\n" (builtins.filter (h: h != "") hooks); - in '' - echo "Hermes Agent dev shell" - ${combined} - echo "Ready. Run 'hermes' to start." - ''; + shellHook = + let + hooks = map (p: p.passthru.devShellHook or "") packages; + combined = pkgs.lib.concatStringsSep "\n" (builtins.filter (h: h != "") hooks); + in + '' + echo "Hermes Agent dev shell" + ${combined} + echo "Ready. Run 'hermes' to start." + ''; }; }; } diff --git a/nix/hermes-agent.nix b/nix/hermes-agent.nix index 886bb1aadb..c3bde20c81 100644 --- a/nix/hermes-agent.nix +++ b/nix/hermes-agent.nix @@ -27,12 +27,13 @@ extraPythonPackages ? [ ], }: let + nodejs = nodejs_22; hermesVenv = callPackage ./python.nix { inherit uv2nix pyproject-nix pyproject-build-systems; }; hermesNpmLib = callPackage ./lib.nix { - inherit npm-lockfile-fix; + inherit npm-lockfile-fix nodejs; }; hermesTui = callPackage ./tui.nix { @@ -57,7 +58,7 @@ let }; runtimeDeps = [ - nodejs_22 + nodejs ripgrep git openssh @@ -82,10 +83,49 @@ let builtins.hashString "sha256" (builtins.readFile ../uv.lock) else "none"; + checkPackageCollisions = '' + import pathlib, sys, re + + def canonical(name): + return re.sub(r'[-_.]+', '-', name).lower() + + # Collect core venv package names + core = set() + venv_sp = pathlib.Path('${hermesVenv}/${sitePackagesPath}') + for di in venv_sp.glob('*.dist-info'): + meta = di / 'METADATA' + if meta.exists(): + for line in meta.read_text().splitlines(): + if line.startswith('Name:'): + core.add(canonical(line.split(':', 1)[1].strip())) + break + + # Check each extra package for collisions + extras_dirs = [${lib.concatMapStringsSep ", " (p: "'${toString p}'") allExtraPythonPackages}] + for edir in extras_dirs: + sp = pathlib.Path(edir) / '${sitePackagesPath}' + if not sp.exists(): + continue + for di in sp.glob('*.dist-info'): + meta = di / 'METADATA' + if not meta.exists(): + continue + for line in meta.read_text().splitlines(): + if line.startswith('Name:'): + pkg = canonical(line.split(':', 1)[1].strip()) + if pkg in core: + print(f'ERROR: plugin package \"{pkg}\" collides with a package in hermes sealed venv', file=sys.stderr) + print(f' from: {di}', file=sys.stderr) + print(f' Remove this dependency from extraPythonPackages.', file=sys.stderr) + sys.exit(1) + break + + print('No collisions found.') + ''; in stdenv.mkDerivation { pname = "hermes-agent"; - version = (builtins.fromTOML (builtins.readFile ../pyproject.toml)).project.version; + version = (fromTOML (builtins.readFile ../pyproject.toml)).project.version; dontUnpack = true; dontBuild = true; @@ -111,7 +151,7 @@ stdenv.mkDerivation { --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 ${nodejs_22}/bin/node \ + --set HERMES_NODE ${lib.getExe nodejs} \ ${lib.optionalString (rev != null) ''--set HERMES_REVISION ${rev} \''} ${lib.optionalString (extraPythonPackages != [ ]) ''--suffix PYTHONPATH : "${pythonPath}"''} '') @@ -124,45 +164,7 @@ stdenv.mkDerivation { ${lib.optionalString (extraPythonPackages != [ ]) '' echo "=== Checking for plugin/core package collisions ===" - ${hermesVenv}/bin/python3 -c " -import pathlib, sys, re - -def canonical(name): - return re.sub(r'[-_.]+', '-', name).lower() - -# Collect core venv package names -core = set() -venv_sp = pathlib.Path('${hermesVenv}/${sitePackagesPath}') -for di in venv_sp.glob('*.dist-info'): - meta = di / 'METADATA' - if meta.exists(): - for line in meta.read_text().splitlines(): - if line.startswith('Name:'): - core.add(canonical(line.split(':', 1)[1].strip())) - break - -# Check each extra package for collisions -extras_dirs = [${lib.concatMapStringsSep ", " (p: "'${toString p}'") allExtraPythonPackages}] -for edir in extras_dirs: - sp = pathlib.Path(edir) / '${sitePackagesPath}' - if not sp.exists(): - continue - for di in sp.glob('*.dist-info'): - meta = di / 'METADATA' - if not meta.exists(): - continue - for line in meta.read_text().splitlines(): - if line.startswith('Name:'): - pkg = canonical(line.split(':', 1)[1].strip()) - if pkg in core: - print(f'ERROR: plugin package \"{pkg}\" collides with a package in hermes sealed venv', file=sys.stderr) - print(f' from: {di}', file=sys.stderr) - print(f' Remove this dependency from extraPythonPackages.', file=sys.stderr) - sys.exit(1) - break - -print('No collisions found.') - " + ${hermesVenv}/bin/python3 -c "${checkPackageCollisions}" echo "=== No collisions ===" ''} @@ -170,7 +172,12 @@ print('No collisions found.') ''; passthru = { - inherit hermesTui hermesWeb hermesNpmLib hermesVenv; + inherit + hermesTui + hermesWeb + hermesNpmLib + hermesVenv + ; devShellHook = '' STAMP=".nix-stamps/hermes-agent" diff --git a/nix/lib.nix b/nix/lib.nix index 5a08a7a53f..3740ef1057 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -1,11 +1,16 @@ # nix/lib.nix — Shared helpers for nix stuff -{ pkgs, npm-lockfile-fix }: +{ + pkgs, + npm-lockfile-fix, + nodejs, +}: { # Returns a buildNpmPackage-compatible attrs set that provides: - # patchPhase — ensures lockfile has exactly one trailing newline - # nativeBuildInputs — [ updateLockfileScript ] (list, prepend with ++ for more) + # patchPhase — ensures lockfile has exactly one trailing newline + # nativeBuildInputs — [ updateLockfileScript ] (list, prepend with ++ for more) # passthru.devShellHook — stamp-checked npm install + hash auto-update # passthru.npmLockfile — metadata for mkFixLockfiles + # nodejs — fixed nodejs version for all packages we use in the repo # # NOTE: npmConfigHook runs `diff` between the source lockfile and the # npm-deps cache lockfile. fetchNpmDeps preserves whatever trailing @@ -24,6 +29,7 @@ nixFile ? "nix/${attr}.nix", # defaults to nix/.nix }: { + inherit nodejs; patchPhase = '' runHook prePatch # Normalize trailing newlines so source and npm-deps always match, @@ -56,8 +62,8 @@ cd "$REPO_ROOT/${folder}" rm -rf node_modules/ - npm cache clean --force - CI=true npm install + ${pkgs.lib.getExe' nodejs "npm"} cache clean --force + CI=true ${pkgs.lib.getExe' nodejs "npm"} install ${pkgs.lib.getExe npm-lockfile-fix} ./package-lock.json NIX_FILE="$REPO_ROOT/${nixFile}" @@ -83,7 +89,7 @@ STAMP_VALUE="$(_hermes_npm_stamp)" if [ ! -f "$STAMP" ] || [ "$(cat "$STAMP")" != "$STAMP_VALUE" ]; then echo "${pname}: installing npm dependencies..." - ( cd ${folder} && CI=true npm install --silent --no-fund --no-audit 2>/dev/null ) + ( cd ${folder} && CI=true ${pkgs.lib.getExe' nodejs "npm"} install --silent --no-fund --no-audit 2>/dev/null ) # Auto-update the nix hash so it stays in sync with the lockfile echo "${pname}: prefetching npm deps..." @@ -92,7 +98,7 @@ sed -i "s|hash = \"sha256-[A-Za-z0-9+/=]+\"|hash = \"$NEW_HASH\";|" "$NIX_FILE" echo "${pname}: updated hash to $NEW_HASH" else - echo "${pname}: warning: prefetch failed, run 'nix run .#fix-lockfiles -- --apply' manually" >&2 + echo "${pname}: warning: prefetch failed, run 'nix run .#fix-lockfiles' manually" >&2 fi mkdir -p .nix-stamps @@ -112,6 +118,7 @@ # Invocations: # fix-lockfiles --check # exit 1 if any hash is stale # fix-lockfiles --apply # rewrite stale hashes in place + # fix-lockfiles # alias of --apply # Writes machine-readable fields (stale, changed, report) to $GITHUB_OUTPUT # when set, so CI workflows can post a sticky PR comment directly. mkFixLockfiles = @@ -124,7 +131,7 @@ in pkgs.writeShellScriptBin "fix-lockfiles" '' set -uox pipefail - MODE="''${1:---check}" + MODE="''${1:---apply}" case "$MODE" in --check|--apply) ;; -h|--help) @@ -222,7 +229,7 @@ if [ "$STALE" -eq 1 ] && [ "$MODE" = "--check" ]; then echo echo "Stale lockfile hashes detected. Run:" - echo " nix run .#fix-lockfiles -- --apply" + echo " nix run .#fix-lockfiles" exit 1 fi diff --git a/nix/tui.nix b/nix/tui.nix index 4d27dde798..7453fa2673 100644 --- a/nix/tui.nix +++ b/nix/tui.nix @@ -4,7 +4,7 @@ let src = ../ui-tui; npmDeps = pkgs.fetchNpmDeps { inherit src; - hash = "sha256-a/HGI9OgVcTnZrMXA7xFMGnFoVxyHe95fulVz+WNYB0="; + hash = "sha256-Chz+NW9NXqboXHOa6PKwf5bhAkkcFtKNhvKWwg2XSPc="; }; npm = hermesNpmLib.mkNpmPassthru { folder = "ui-tui"; attr = "tui"; pname = "hermes-tui"; }; diff --git a/nix/web.nix b/nix/web.nix index 7084a04c8e..a5793dff7a 100644 --- a/nix/web.nix +++ b/nix/web.nix @@ -8,11 +8,13 @@ let }; npm = hermesNpmLib.mkNpmPassthru { folder = "web"; attr = "web"; pname = "hermes-web"; }; + + packageJson = builtins.fromJSON (builtins.readFile (src + "/package.json")); + version = packageJson.version; in pkgs.buildNpmPackage (npm // { pname = "hermes-web"; - version = "0.0.0"; - inherit src npmDeps; + inherit src npmDeps version; doCheck = false; diff --git a/ui-tui/package-lock.json b/ui-tui/package-lock.json index 2efd64fe40..017e9913bd 100644 --- a/ui-tui/package-lock.json +++ b/ui-tui/package-lock.json @@ -124,7 +124,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -502,6 +501,31 @@ "node": ">=6.9.0" } }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", @@ -1676,7 +1700,6 @@ "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.19.0" } @@ -1687,7 +1710,6 @@ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -1698,7 +1720,6 @@ "integrity": "sha512-eSkwoemjo76bdXl2MYqtxg51HNwUSkWfODUOQ3PaTLZGh9uIWWFZIjyjaJnex7wXDu+TRx+ATsnSxdN9YWfRTQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.58.1", @@ -1728,7 +1749,6 @@ "integrity": "sha512-gGkiNMPqerb2cJSVcruigx9eHBlLG14fSdPdqMoOcBfh+vvn4iCq2C8MzUB89PrxOXk0y3GZ1yIWb9aOzL93bw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.58.1", "@typescript-eslint/types": "8.58.1", @@ -2046,7 +2066,6 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2449,7 +2468,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -3185,7 +3203,6 @@ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3317,7 +3334,6 @@ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -4226,7 +4242,6 @@ "resolved": "https://registry.npmjs.org/ink-text-input/-/ink-text-input-6.0.0.tgz", "integrity": "sha512-Fw64n7Yha5deb1rHY137zHTAbSTNelUKuB5Kkk2HACXEtwIHBCf9OH2tP/LQ9fRYTl1F0dZgbW0zPnZk6FA9Lw==", "license": "MIT", - "peer": true, "dependencies": { "chalk": "^5.3.0", "type-fest": "^4.18.2" @@ -5663,7 +5678,6 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -5773,7 +5787,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.5.tgz", "integrity": "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -6598,7 +6611,6 @@ "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" @@ -6725,7 +6737,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6835,7 +6846,6 @@ "integrity": "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", @@ -7251,7 +7261,6 @@ "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" }