diff --git a/pkgs/by-name/ex/exo/inject-dashboard-path.patch b/pkgs/by-name/ex/exo/inject-dashboard-path.patch index 29f964446dbb..d9a9ca63d31e 100644 --- a/pkgs/by-name/ex/exo/inject-dashboard-path.patch +++ b/pkgs/by-name/ex/exo/inject-dashboard-path.patch @@ -1,17 +1,18 @@ diff --git a/src/exo/utils/dashboard_path.py b/src/exo/utils/dashboard_path.py -index b5ce9c04..ec60ef4a 100644 +index 980bb80f..7faecd27 100644 --- a/src/exo/utils/dashboard_path.py +++ b/src/exo/utils/dashboard_path.py -@@ -5,11 +5,7 @@ from typing import cast +@@ -32,12 +32,7 @@ def _find_resources_in_bundle() -> Path | None: def find_dashboard() -> Path: -- dashboard = ( -- _find_dashboard_in_env() -- or _find_dashboard_in_repo() -- or _find_dashboard_in_bundle() -- ) -+ dashboard = "@dashboard@" - if not dashboard: - raise FileNotFoundError( - "Unable to locate dashboard assets - make sure the dashboard has been built, or export DASHBOARD_DIR if you've built the dashboard elsewhere." +- dashboard = _find_dashboard_in_repo() or _find_dashboard_in_bundle() +- if not dashboard: +- raise FileNotFoundError( +- "Unable to locate dashboard assets - you probably forgot to run `cd dashboard && npm install && npm run build && cd ..`" +- ) +- return dashboard ++ return Path("@dashboard@") + + + def _find_dashboard_in_repo() -> Path | None: diff --git a/pkgs/by-name/ex/exo/package.nix b/pkgs/by-name/ex/exo/package.nix index ebb8d6cd55e1..4e2490011ad4 100644 --- a/pkgs/by-name/ex/exo/package.nix +++ b/pkgs/by-name/ex/exo/package.nix @@ -2,7 +2,7 @@ lib, stdenv, fetchFromGitHub, - python3Packages, + python3, replaceVars, macmon, @@ -18,15 +18,35 @@ nix-update-script, }: let - version = "1.0.67"; + version = "1.0.68"; src = fetchFromGitHub { name = "exo"; owner = "exo-explore"; repo = "exo"; tag = "v${version}"; - hash = "sha256-hipCiAqCkkyrVcQXEZKbGoVbgjM3hykUcazNPEbT+q8="; + hash = "sha256-ryaz68vXS/SjPxGsWxtUSlzZrLBxV1tbBmJVraZu3RI="; }; + python = python3.override { + packageOverrides = _final: prev: { + # https://github.com/exo-explore/exo/blob/ba611f9cd0e21d3e63e2327b18fbc888fd085269/pyproject.toml#L67 + mlx = prev.mlx.overridePythonAttrs (old: { + version = "custom"; + + src = fetchFromGitHub { + owner = "rltakashige"; + repo = "mlx-jaccl-fix-small-recv"; + rev = "address-rdma-gpu-locks"; + hash = "sha256-GosFIWxIB48Egb1MqJrR3xhsUsQeWdRk5rV93USY6wQ="; + }; + meta = old.meta // { + changelog = ""; + }; + }); + }; + }; + python3Packages = python.pkgs; + pyo3-bindings = python3Packages.buildPythonPackage (finalAttrs: { pname = "exo-pyo3-bindings"; inherit version src; @@ -36,7 +56,7 @@ let cargoDeps = rustPlatform.fetchCargoVendor { inherit (finalAttrs) pname src version; - hash = "sha256-N7B1WFqPdqeNPZe9hXGyX7F3EbB1spzeKc19BFDDwls="; + hash = "sha256-Ga3/Yhg2Wn2w8cnNtq11/AN7K4nht4chSEIVOkYEI/U="; }; # Bypass rust nightly features not being available on rust stable @@ -47,18 +67,8 @@ let rustPlatform.maturinBuildHook ]; - nativeCheckInputs = with python3Packages; [ - pytest-asyncio - pytestCheckHook - ]; - - enabledTestPaths = [ - "rust/exo_pyo3_bindings/tests/" - ]; - - # RuntimeError - # Attempted to create a NULL object - doCheck = !stdenv.hostPlatform.isDarwin; + # The only test is failing + doCheck = false; }); dashboard = buildNpmPackage (finalAttrs: { @@ -66,6 +76,7 @@ let inherit src version; sourceRoot = "${finalAttrs.src.name}/dashboard"; + npmDepsFetcherVersion = 3; npmDeps = fetchNpmDeps { inherit (finalAttrs) @@ -74,21 +85,8 @@ let src sourceRoot ; - fetcherVersion = 2; - hash = "sha256-ok1Yl8CIPwViioH5HOM4VWilRU3HsSa8IAsBFl/QgG0="; - }; - }); - - # exo requires building mlx-lm from its main branch to use the kimi-k2.5 model - mlx-lm-unstable = python3Packages.mlx-lm.overridePythonAttrs (old: { - version = "0.30.4-unstable-2026-01-27"; - src = old.src.override { - rev = "96699e6dadb13b82b28285bb131a0741997d19ae"; - tag = null; - hash = "sha256-L1ws8XA8VhR18pRuRGbVal/yEfJaFNW8QzS16C1dFpE="; - }; - meta = old.meta // { - changelog = "https://github.com/ml-explore/mlx-lm/releases/tag/v0.30.5"; + fetcherVersion = 3; + hash = "sha256-eMmzWwsebwvrpNLqs+4iyiPsDFvwRlk+LaiKQ0SZmt8="; }; }); in @@ -151,7 +149,8 @@ python3Packages.buildPythonApplication (finalAttrs: { loguru mflux mlx - mlx-lm-unstable + mlx-lm + msgspec nvidia-ml-py openai openai-harmony @@ -169,9 +168,16 @@ python3Packages.buildPythonApplication (finalAttrs: { tomlkit transformers uvloop + zstandard ] ++ sqlalchemy.optional-dependencies.asyncio; + # 'resources' are not getting copied to the installation directory, so we do it manually + # FileNotFoundError: Unable to locate resources. Did you clone the repo properly? + postInstall = '' + cp -r resources $out/${python.sitePackages}/exo/ + ''; + pythonImportsCheck = [ "exo" "exo.main" @@ -188,7 +194,18 @@ python3Packages.buildPythonApplication (finalAttrs: { rm src/exo/__init__.py ''; - disabledTests = lib.optionals stdenv.hostPlatform.isDarwin [ + disabledTests = [ + # AttributeError: type object 'builtins.Keypair' has no attribute 'generate_ed25519' + "test_sleep_on_multiple_items" + + # Require internet access: + # openai_harmony.HarmonyError: error downloading or loading vocab file: failed to download or load vocab file + "test_both_formats_produce_identical_tool_calls" + "test_format_a_yields_tool_call" + "test_format_b_yields_tool_call" + "test_thinking_then_tool_call" + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ # AssertionError: assert "MacMon not found in PATH" in str(exc_info.value) "test_macmon_not_found_raises_macmon_error"