diff --git a/docker/Dockerfile b/docker/Dockerfile index b15709a..47bf95c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -39,7 +39,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y \ # Install nodejs WORKDIR /tmp -RUN curl -sL https://deb.nodesource.com/setup_23.x -o nodesource_setup.sh && \ +RUN curl -sL https://deb.nodesource.com/setup_24.x -o nodesource_setup.sh && \ bash nodesource_setup.sh && \ apt-get update && \ apt-get install -y nodejs && \ diff --git a/extensions_built_in/sd_trainer/SDTrainer.py b/extensions_built_in/sd_trainer/SDTrainer.py index 563616a..d525372 100644 --- a/extensions_built_in/sd_trainer/SDTrainer.py +++ b/extensions_built_in/sd_trainer/SDTrainer.py @@ -927,7 +927,7 @@ class SDTrainer(BaseSDTrainProcess): pred = t0 # handle velocity equiv loss if set. This scales t0 loss to match velocity of flowmatchhing loss if self.train_config.t0_velocity_equiv_weight: - velocity_equiv_weight = (1.0 / torch.clamp(tv, min=0.1) ** 2) + velocity_equiv_weight = (1.0 / torch.clamp(tv, min=0.01) ** 2) local_loss_scale = velocity_equiv_weight if self.train_config.do_fft_loss: @@ -936,7 +936,7 @@ class SDTrainer(BaseSDTrainProcess): pred_mag = torch.fft.rfft2(t0.float(), norm="ortho").abs() fft_loss = F.mse_loss(pred_mag, target_mag, reduction="none") if self.train_config.do_fft_velocity_equiv_weight: - velocity_equiv_weight = (1.0 / torch.clamp(tv, min=0.1) ** 2) + velocity_equiv_weight = (1.0 / torch.clamp(tv, min=0.01) ** 2) fft_loss = fft_loss * velocity_equiv_weight fft_loss = fft_loss.mean() self.additional_logs['loss/fft'] = fft_loss.item() diff --git a/manager/doctor.py b/manager/doctor.py index 554c7e2..a3f2608 100644 --- a/manager/doctor.py +++ b/manager/doctor.py @@ -119,7 +119,14 @@ def run_doctor(): _check("torch sees gpu", False, "could not query") node_exe, node_major = nodejs.have_usable_node() - if node_exe: + if node_exe and node_exe == nodejs.local_node_exe() and nodejs.local_node_stale(): + _check( + "node", + False, + "%s (v%s) is behind pinned v%s (manager sync reinstalls it)" + % (node_exe, node_major, nodejs.NODE_VERSION), + ) + elif node_exe: _check("node", True, "%s (v%s)" % (node_exe, node_major)) else: _check( diff --git a/manager/nodejs.py b/manager/nodejs.py index c31f95e..be43a83 100644 --- a/manager/nodejs.py +++ b/manager/nodejs.py @@ -27,7 +27,7 @@ from .util import ( NODE_DIR = os.path.join(REPO_ROOT, ".node") # Node 24 is the current LTS line. -NODE_VERSION = "24.11.1" +NODE_VERSION = "24.22.1" MIN_NODE_MAJOR = 20 UI_DIR = os.path.join(REPO_ROOT, "ui") @@ -44,7 +44,8 @@ def local_node_exe(): def _node_info(exe): - """(major, arch) for a node executable, e.g. (24, 'x64'), or (None, None).""" + """(version, major, arch) for a node executable, e.g. ('24.22.1', 24, 'x64'), + or (None, None, None).""" try: out = subprocess.run( [exe, "-p", "process.version + ' ' + process.arch"], @@ -53,11 +54,12 @@ def _node_info(exe): timeout=15, ) if out.returncode != 0: - return None, None - version, arch = out.stdout.decode().strip().split() # v24.11.1 x64 - return int(version.lstrip("v").split(".")[0]), arch + return None, None, None + version, arch = out.stdout.decode().strip().split() # v24.22.1 x64 + version = version.lstrip("v") + return version, int(version.split(".")[0]), arch except (OSError, subprocess.TimeoutExpired, ValueError): - return None, None + return None, None, None def _usable_major(exe): @@ -68,7 +70,7 @@ def _usable_major(exe): so a native ARM64 node loads the UI but dies on the first DB call. The x64 node runs under emulation on ARM hosts. """ - major, arch = _node_info(exe) + _, major, arch = _node_info(exe) if major is None or major < MIN_NODE_MAJOR: return None if IS_WINDOWS and arch != "x64": @@ -110,14 +112,30 @@ def have_usable_node(): return None, None +def local_node_stale(): + """True when the portable copy exists but isn't the pinned NODE_VERSION.""" + local = local_node_exe() + if not os.path.isfile(local): + return False + version, _, _ = _node_info(local) + return version != NODE_VERSION + + def ensure_node(detection, dry_run=False): exe, major = have_usable_node() - if exe: + if exe == local_node_exe() and local_node_stale(): + # the portable copy is ours to keep current (security releases) + version, _, _ = _node_info(exe) + info( + "Portable Node.js v%s at %s is behind the pinned v%s — reinstalling." + % (version, NODE_DIR, NODE_VERSION) + ) + elif exe: ok("Node.js v%d found (%s)." % (major, exe)) return False system = which("node") if system: - _, arch = _node_info(system) + _, _, arch = _node_info(system) if IS_WINDOWS and arch and arch != "x64": info( "System Node.js is %s but the UI needs an x64 node on Windows " diff --git a/version.py b/version.py index a331834..e7d4575 100644 --- a/version.py +++ b/version.py @@ -1 +1 @@ -VERSION = "0.13.35" +VERSION = "0.13.36"