Skip to content

v7.81.0

Choose a tag to compare

@github-actions github-actions released this 16 Oct 17:07
· 1956 commits to main since this release
216d543

Pairs with engine-service-v0.1.160 (REQUIRED_ENGINE_VERSION unchanged). The plugin installs the CLI (RDR-228 Phase 2): a session with no CLI is asked one question (local, cloud, CLI only or not now), and the setup tool builds the CLI with nx self install --bootstrap and sets up the chosen service in the background.

Added

  • nx self install --bootstrap installs the CLI for the first time from a throwaway uv environment (RDR-228 Phase 2 Step 1, nexus-sv2wx.14). uv tool run --python 3.12 --from conexus==<version> nx self install --bootstrap builds one generation from the package index at the version of the nx running it, points current at it and writes the shims, with a receipt that lists no extras. It does not run uv cache prune, which the plain command runs at its end (23.4 GiB removed from a developer's cache in the CA-3 test). The flag is the only way into this path: without it a throwaway environment and a development checkout refuse with the same message as before. With a complete install present (current pointing at a generation with a receipt and the shims in place, or a uv tool install) the flag refuses in one line naming the plain nx self install and changes nothing; it also refuses, naming the generation, when current names a directory whose receipt is missing or unreadable. A run that died after its build or after the flip, which leaves a receipted generation with no current or with no shims, is finished by running the same command again, with no rebuild, when the generation is at the running version and its interpreter answers the shim lookup; any other leftover is replaced by a fresh build. The Windows generation flip no longer fails over a current whose target is gone: it skips recording that target as previous. It refuses before building, naming the file, when nx or another shim name in the bin directory is a program that is not nexus's (not a nexus shim and not a symlink into the uv tool tree). A failed build names re-running the same bootstrap command, not nx self install. It takes neither --version nor --extras.

  • nx-mcp registers two tools, setup and setup_status, and the plugin's stand-in server offers the same two (RDR-228 Phase 2 Step 3, nexus-sv2wx.16). setup takes mode (local, cli-only or not-now) and, for local, autostart (false unless given), starts the plugin's setup process (conexus/launch/nx_setup.py) and returns at once with the stage, how long that stage usually takes and the earliest time to ask again; setup_status reports the stage, the log path and the next step. The real server registers them in every session, 46 tools where there were 44. When a usable service is already set up setup starts nothing and setup_status says nothing is missing; when none is found the server's instructions say what is missing and what fixes it, and that the user decides. "Usable" is whether the storage clients' own endpoint resolution succeeds, so a saved service_url with no resolvable token is not usable. A last run that failed, was interrupted, ended with nx doctor problems or could not detach is reported even when a service answers. Every returned text that mentions a recorded run shows its mode and autostart, and every text that tells the model to call setup says to ask the user first. The launcher hands the real server the setup process's path in NX_SETUP_SCRIPT; without it the tools start nothing and answer with the terminal commands (nx init). The real server starts the setup process without a Windows job object (run_bounded(contained=False)), so the build it detaches survives the call. NX_SETUP_SCRIPT is accepted only as an absolute path to a file named nx_setup.py. A managed service ("cloud") is refused until its credentials page exists. Neither tool is auto-approved, so each call can prompt the user. The stand-in's tools of the same names took no argument in the plugin release before this one, installed nothing and carried other descriptions.

  • The plugin's session-start hook puts the one question and reports eight states, /conexus:setup is the way back, and setup repairs a CLI that cannot start (RDR-228 Phase 2 Step 4, nexus-sv2wx.17). The hook reports the first of: a setup run is live; the CLI is found and cannot start; the CLI resolves and a service is usable (nothing); a run was interrupted; the last run failed; no CLI (Local, CLI only or Not now, sizes shown, and for Local whether to start at login); a provisioned local service is down; no service is set up. Nothing is installed without a setup call, and every text that suggests one tells the model to ask the user first. The user's choice is honoured: a "not now" answer, or a recorded CLI-only run, makes the "service is down" and "no service is set up" lines one quiet line naming /conexus:setup that asks nothing, and "not now" does the same for the report of a stale failed or interrupted run (a live run and a CLI that cannot start are never quieted). /conexus:setup calls setup_status and setup and has no nx shell line; with a CLI older than this release it gives nx self install then nx upgrade as text.

    • A CLI that is found and cannot start (for example a generation whose Python uv pruned) is no longer a failed server. The launcher checks the files, starts nothing, and serves the stand-in, which says "Nexus is installed but cannot start; setup repairs it". On POSIX a gone home in pyvenv.cfg is not enough by itself (the interpreter can still start through the venv's bin/python link); it counts beside a python* link that points nowhere, which is what a uv prune leaves, and a script whose own shebang names a missing interpreter counts alone. nx self install --bootstrap now treats a current generation, and a legacy uv tool install conexus tree (the README's own install path), whose Python is gone as not installed, so the repair has something to run (before, it refused with "already installed"); a broken current generation is repaired even beside a working legacy tree.
    • A usable service is the CLI's definition (nexus-9i4d4 item 9): the plugin's check returns what resolve_service_endpoint() does, so a saved address with no token is not a service. The hook's file reads (the setup status, its error record and the lease) retry a Windows sharing violation for at most 30 ms together, where the setup process's own reads wait two seconds. A hand-edited config.yml with the credentials in flow style (credentials: {service_url: ..., service_token: ...}) is read as the CLI reads it, and a lease just past its time to live is kept while its owner process is alive, so a laptop that slept is not told the service is down (the CLI also asks the port to answer /health; the plugin makes no network request, so an owner that is alive and wedged reads as usable to the hook and not to the CLI; setup grants no such grace, so it starts the service instead of skipping the step).
    • While the stand-in is still running after a repair, setup_status asks again whether the CLI can start. A run in progress is reported as it is and the "installed but cannot start, ask first" offer is not repeated over it; while the CLI still cannot start, any other recorded state (a done from an earlier setup included) keeps the statement and the repair offer, with the record after it; once the CLI can start, it reports the record and the reconnect step once. It asks the same when no CLI was found at start, so a done from an earlier setup on a machine whose install has since been removed reads as "not installed" and the question is put again, not as a finished setup. A missing setup process in the cannot-start mode says "cannot start" and gives the repair command, not "not installed".
    • The choice shows what it takes on disk (2.4 GB for Local, 1.6 GB for CLI only) beside the download sizes, in both servers' setup description and in the no-service notice; /conexus:setup checks that the nexus server is connected (/mcp) before it says the CLI is older.
  • Mode cloud of setup opens a local credentials page for the service address, token and tenant (RDR-228 Phase 2 Step 5, nexus-sv2wx.18). The setup process serves one small page on 127.0.0.1 (a port the system picks, a random one-time path) from the start of the run while the CLI builds, and asks the system to open an owner-only file that sends the browser to it, so the token reaches the config file without passing through the model, the conversation or a tool argument. The page has three fields. A managed user holds a mint credential, a token bound to one tenant that mints short-lived data tokens (mint_token and mint_tenant); a static service token is the self-hosted case; the tenant is required for the first and unused for the second. The check needs /version to answer 200 (/health is not used), then sends the token to GET /v1/_whoami: 401 refuses it, 200 is a static token, 403 is a mint credential, which is proved with its tenant by minting one data token (POST /v1/data-tokens/mint, 60 seconds): 200 accepts, 403 says the token belongs to another tenant, 429 says to try again. This is what the engine does on a local and a self-hosted service and what research-37 measured at the managed edge for /health and /version; how the managed edge answers the two /v1 routes with a right credential is not measured here. A redirect is never followed, no proxy is used, and the whole check ends after 20 seconds. Accepted credentials are held in memory and saved after the build with nx config set mint_tenant and mint_token --stdin for a mint credential or service_token --stdin for a static token, then service_url last (a token with no address is inert), never both kinds. A run that ends with credentials accepted and not completely saved says they are discarded and that setup must be called again. A run that resumes one which saved its credentials and then failed at a later step opens no page. Replacing a saved credential is nx config init in a terminal: the real server's setup starts nothing while a service answers, and a saved address with a token resolves as one. Saving one kind first removes a saved credential of the other kind with the new nx config unset, since the CLI prefers a static service_token. No verdict repeats the tenant as typed. Status values for the step are exactly "waiting for credentials", "page not loaded" (after 2 minutes, or at once when the system could not be asked to open the page), "credentials rejected, waiting for another try", "credentials accepted", "credentials saved" and "timed out" (the listener closes at 10 minutes and the run ends failed; during a build the status says to wait for the run to end). The page serves at most 16 connections at a time, each of which must finish its request within 5 seconds; a 17th connection shuts down the oldest one whose request is not yet read and takes its place (a connection past its read, such as a check in progress, is never shut down; if every one is, the 17th is closed), so sockets that drip bytes or reconnect the moment they are closed do not lock a right request out. The page refuses a POST that names another origin, asks for exclusive use of its address on Windows and tightens the setup directory to owner-only. An http:// address to a host that is not this machine is accepted; the page says before any submit, in a static note, that such an address sends the token unencrypted (the check sends it the moment the button is pressed), and warns again after the check. A stale setup lock is not reclaimed while the pid in status.json or the pid of the build the run was waiting on names a live process. In that state setup_status and a refused setup both say the heartbeat stopped but process N (or its build) is still running, and to wait and call setup_status again; neither tells the model to call setup again. The Cloud choice now appears in the one question's table, the setup tool's descriptions on both servers, the session-start hook and /conexus:setup, all saying address, token and tenant. The opener file is also deleted when the listener closes without a load and by the next run's start after a kill (nexus-9i4d4 items 5 and 10). nx config init asks which kind of credential you hold, hides the token as it is typed, saves only that kind's keys, and asks the tenant of a mint token that comes from NX_MINT_TOKEN. New nx config unset KEY removes a saved credential from the config file.

  • nx doctor has a "Plugin setup" row for the plugin's setup status (RDR-228 Day 2, nexus-sv2wx.19). It reads status.json, the lock heartbeat and status.error in setup/ under the config directory and names setup.log. Not applicable (green) where no setup has run, so a new box shows no warning; green and naming the stage while a run is live (the setup process runs nx doctor itself while it holds its lock); a warning with the failure line and the log path when the last run failed; a warning that calling setup again resumes when a run was interrupted (status running, heartbeat older than 60 seconds or no lock), which a stale lock or a log with no status file also counts as. When no other row in the same nx doctor run is a failure or a warning (the managed deployment's "storage cannot be probed from here" row does not count), a warning about the last run (failed, verify failed, interrupted) is shown as information ("the last setup run ended , and every other row of this sweep is fine") so a box fixed by hand does not warn until setup is called again. The row looks in the directory the setup script writes, NEXUS_CONFIG_DIR, then NX_CONFIG_DIR, then ~/.config/nexus. tests/fixtures/setup_status_format.json pins the format for both the plugin script's tests and the row's.

Fixed

  • nx init refuses up front on a Windows machine with Smart App Control on, and nx doctor reports its state (nexus-f9bgu.57). Smart App Control blocks the unsigned PostgreSQL bundle and the unsigned Python that uv installs, so a local install cannot work there. nx init used to download the bundle and then fail with a bare [WinError 4551]. It now stops before the download and says why, with a link to the install guide's Smart App Control section. A new Windows-only nx doctor row, "Smart App Control", reads the state from the registry: on fails in local mode and warns in cloud mode, evaluation warns because Windows can switch it on later, and off passes. On the measured Windows 11 Home machine with Smart App Control on, Windows also blocked nx.exe itself at install, so there neither the refusal nor the row can run. Nothing changes on macOS and Linux.
  • After a CLI-only setup the nexus server no longer suggests nx init (Sam, 2026-10-16; nexus-sv2wx.24). The server's embedder notice ("running with the default 384-dim embedder ... Run nx init to upgrade") is left out once setup finished in mode cli-only, as the setup notice already is; nx doctor still reports it.
  • The start-at-login service reads its settings from the config directory it was installed for (nexus-sv2wx.24, found by the macOS validation). The autostart unit runs nx daemon service start --foreground --config-dir <dir> and sets no NEXUS_CONFIG_DIR, so the supervisor read the embedding choice and the Voyage key from ~/.config/nexus while using <dir> for everything else. An install whose config lives elsewhere, with a Voyage key in ~/.config/nexus, started a Voyage-only engine that refused the first store. The flag is now exported as NEXUS_CONFIG_DIR before any read.
  • A CLI whose Python uv pruned is found as one that cannot start when uv wrote its scripts as sh polyglots (nexus-sv2wx.20, found by the setup journey on macOS). uv writes #!/bin/sh and an exec line instead of a shebang when the install path is longer than 127 characters or holds a space. The cannot-start check read only a shebang, so the setup hook did not report state 2, the launcher started the shell, and nx_hook_shim.py passed on its exit 126 as the hook's result at SessionStart. The check now reads the interpreter named on the second line, and the shim decides before it starts nx-hook, so such a hook exits 0 with one "could not start" line, as it does for a shebang. The CLI's own copy of the rule (self_cmd._generation_interpreter_gone) reads the same line, so nx self install --bootstrap and the plugin still agree.
  • setup's first build on Linux no longer downloads CUDA torch, and the first session after it starts no upgrade (nexus-sv2wx.20, found by the offline setup journey). The throwaway uv environment that runs nx self install --bootstrap pulled PyPI's CUDA torch with 14 nvidia-* packages and triton, about 4.5 GB; the build now names the CPU build through UV_TORCH_BACKEND=cpu (NX_TORCH_BACKEND wins and nothing else does, as for the generation itself; the CPU build is fetched from PyTorch's CPU index, a second host beside the package index). That needs a uv whose uv tool run takes --torch-backend: with uv 0.12.24 a first build from an empty cache held CPU torch and no nvidia-* or triton package (2.4 GB); uv 0.8.0 has no such option and ignores the variable. A build writes the version-lockstep marker with the version it installed once nx --version of the CLI it left reports exactly that version (otherwise it logs and writes none), and the lockstep hook treats a CLI that cannot start as absent, so neither a fresh setup nor a repair is followed by a dispatched upgrade.