From 4dd816b6b0550c5f529244416ba6a0db72fbc81e Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 18 Aug 2026 16:27:59 +0000 Subject: [PATCH 1/7] build(nooa): install nooa from PyPI instead of a git pin nooa 0.0.9 is the first release carrying the callable `@strategy(llm=...)` support that Experimentalist's `coder.py` depends on, so the workspace no longer needs to pin a commit past v0.0.8. The tag contains the commit that was pinned (51 ahead, 0 behind). Declare `nooa>=0.0.9` on the three plugins that use it rather than a bare `nooa`. The bare requirement was only safe while `[tool.uv.sources]` overrode it inside this workspace; once these plugins ship in a wheel it would resolve to 0.0.8, install cleanly, and then fail at the call site. The smoke-agent task image installed nooa by git URL too. Its guard test asserted a 40-hex revision matching the root pin, so it now compares the image's version specifier against the plugin's own instead -- the point of the test is that image and plugin resolve the same range. Re-stamping the content-addressed image tag moves the rendered-task-tree hash with it. `tools/check_nooa_import_surface.py` walks the plugins' nooa imports against the installed package, so a floor bump that drops or renames a symbol is one command rather than an import error deep into an agent run. Signed-off-by: Cursor Agent Co-authored-by: Aditya Pandey --- plugins/nemo-eval-author/pyproject.toml | 2 +- plugins/nemo-experimentalist/AGENTS.md | 13 ++- .../smoke-agent/dataset/_shared/Dockerfile | 4 +- .../dataset/task-template/task.toml | 2 +- .../examples/tau3-nooa-agent/pyproject.toml | 5 +- .../examples/tau3-nooa-agent/uv.lock | 10 +- .../framework-skills/nooa/SKILL.md | 17 ++-- plugins/nemo-experimentalist/pyproject.toml | 2 +- .../test_smoke_agent_assets.py | 30 ++++-- plugins/nemo-insights/pyproject.toml | 2 +- pyproject.toml | 4 - third_party/requirements-main.txt | 7 +- tools/check_nooa_import_surface.py | 97 +++++++++++++++++++ uv.lock | 14 ++- 14 files changed, 160 insertions(+), 49 deletions(-) create mode 100644 tools/check_nooa_import_surface.py diff --git a/plugins/nemo-eval-author/pyproject.toml b/plugins/nemo-eval-author/pyproject.toml index ac544ba5cf..9a621d6bde 100644 --- a/plugins/nemo-eval-author/pyproject.toml +++ b/plugins/nemo-eval-author/pyproject.toml @@ -10,7 +10,7 @@ dependencies = [ "pydantic>=2", # Harbor 0.18 provides the discovery APIs used by this plugin. "harbor>=0.18", - "nooa", + "nooa>=0.0.9", "nemo-experimentalist-plugin", "nemo-insights-plugin", "nemo-platform", diff --git a/plugins/nemo-experimentalist/AGENTS.md b/plugins/nemo-experimentalist/AGENTS.md index 62522c968e..b12b46e88c 100644 --- a/plugins/nemo-experimentalist/AGENTS.md +++ b/plugins/nemo-experimentalist/AGENTS.md @@ -109,13 +109,12 @@ instead of restoring Curator imports, configuration, or aliases. The obsolete Configure Platform services, trace storage, and Insights analysis according to the Platform documentation; this repository does not own a service, scheduler, or testbed setup. -- `nooa` is pinned to an immutable public GitHub revision in the workspace root - `pyproject.toml` under `[tool.uv.sources]`; this plugin's `pyproject.toml` only - declares the dependency. It is a commit rather than a tag because the callable - `@strategy(llm=...)` support this plugin depends on landed after `v0.0.8`. - Update the root pin, the matching pin in - `examples/tau3-nooa-agent/pyproject.toml`, the revision quoted in - `framework-skills/nooa/SKILL.md`, and both lock files together. Keep the +- `nooa` comes from PyPI. This plugin's `pyproject.toml` declares the floor + (`nooa>=0.0.9`), which is the first release carrying the callable + `@strategy(llm=...)` support the components depend on. When raising the floor, + move it in this plugin, `nemo-insights`, `nemo-eval-author`, and + `examples/tau3-nooa-agent/pyproject.toml`, update the tag quoted in + `framework-skills/nooa/SKILL.md`, and relock both lock files together. Keep the Platform-supplied Insights plugin separate. - This branch uses merged Platform PR 718 contracts only. After the Platform handoff lands, rebase and repin before adopting any new Platform testbed or diff --git a/plugins/nemo-experimentalist/examples/smoke-agent/dataset/_shared/Dockerfile b/plugins/nemo-experimentalist/examples/smoke-agent/dataset/_shared/Dockerfile index cf662d509c..1e13fb9309 100644 --- a/plugins/nemo-experimentalist/examples/smoke-agent/dataset/_shared/Dockerfile +++ b/plugins/nemo-experimentalist/examples/smoke-agent/dataset/_shared/Dockerfile @@ -17,9 +17,9 @@ RUN apt-get update \ COPY --from=ghcr.io/astral-sh/uv:0.9.14 /uv /bin/uv # `uv pip install --system` rather than `uv sync`: there is no project here, just -# one pinned dependency going into the image's own interpreter. +# one dependency going into the image's own interpreter. RUN uv pip install --system --no-cache \ - "nooa[tracing] @ git+https://github.com/NVIDIA-NeMo/labs-OO-Agents.git@6e0274dd03f883254a084cfb9f871ea580e03434" + "nooa[tracing]>=0.0.9" WORKDIR /app RUN groupadd --gid 10001 smoke-agent \ diff --git a/plugins/nemo-experimentalist/examples/smoke-agent/dataset/task-template/task.toml b/plugins/nemo-experimentalist/examples/smoke-agent/dataset/task-template/task.toml index 3aba473205..e01e424ff2 100644 --- a/plugins/nemo-experimentalist/examples/smoke-agent/dataset/task-template/task.toml +++ b/plugins/nemo-experimentalist/examples/smoke-agent/dataset/task-template/task.toml @@ -23,6 +23,6 @@ timeout_sec = 60.0 [environment] # Set by scripts/build_image.py; a test asserts it matches the current content # hash of the Dockerfile and records file. Tasks ship no environment/ directory. -docker_image = "smoke-agent-env:sha-3f3415c0dbf2" +docker_image = "smoke-agent-env:sha-280bb8c6026b" cpus = 1 memory_mb = 1024 diff --git a/plugins/nemo-experimentalist/examples/tau3-nooa-agent/pyproject.toml b/plugins/nemo-experimentalist/examples/tau3-nooa-agent/pyproject.toml index d7ae79e24e..40c7431c14 100644 --- a/plugins/nemo-experimentalist/examples/tau3-nooa-agent/pyproject.toml +++ b/plugins/nemo-experimentalist/examples/tau3-nooa-agent/pyproject.toml @@ -9,10 +9,7 @@ readme = "README.md" requires-python = ">=3.12,<3.14" dependencies = [ "mcp==1.25.0", - "nooa[tracing]", + "nooa[tracing]>=0.0.9", "opentelemetry-exporter-otlp-proto-http", "orjson==3.11.9", ] -[tool.uv.sources] -# Keep in step with the workspace root pin. -nooa = { git = "https://github.com/NVIDIA-NeMo/labs-OO-Agents.git", rev = "6e0274dd03f883254a084cfb9f871ea580e03434" } diff --git a/plugins/nemo-experimentalist/examples/tau3-nooa-agent/uv.lock b/plugins/nemo-experimentalist/examples/tau3-nooa-agent/uv.lock index dc5edc698f..938798866e 100644 --- a/plugins/nemo-experimentalist/examples/tau3-nooa-agent/uv.lock +++ b/plugins/nemo-experimentalist/examples/tau3-nooa-agent/uv.lock @@ -730,21 +730,25 @@ dependencies = [ [package.metadata] requires-dist = [ { name = "mcp", specifier = "==1.25.0" }, - { name = "nooa", extras = ["tracing"], git = "https://github.com/NVIDIA-NeMo/labs-OO-Agents.git?rev=6e0274dd03f883254a084cfb9f871ea580e03434" }, + { name = "nooa", extras = ["tracing"], specifier = ">=0.0.9" }, { name = "opentelemetry-exporter-otlp-proto-http" }, { name = "orjson", specifier = "==3.11.9" }, ] [[package]] name = "nooa" -version = "0.0.9.dev46" -source = { git = "https://github.com/NVIDIA-NeMo/labs-OO-Agents.git?rev=6e0274dd03f883254a084cfb9f871ea580e03434#6e0274dd03f883254a084cfb9f871ea580e03434" } +version = "0.0.9" +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, { name = "litellm" }, { name = "openinference-instrumentation-litellm" }, { name = "pydantic" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/34/6f/c4e3ea70b373f72f98c12d23fd61f8525462bcecb4a969b58fbb67092699/nooa-0.0.9.tar.gz", hash = "sha256:c7a90ffb5b54094180efcb845e74a00c4182766745245f4258e613f9c12cb522", size = 3315964, upload-time = "2026-08-18T15:00:15.26Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/27/11b2754bc31994244418d0a55447f20bc0efbd9d2573802db13c7ca367b5/nooa-0.0.9-py3-none-any.whl", hash = "sha256:60b64663f34a47aec206137035d62e816c1147484bb74a8a4700a47d1a10b60c", size = 1104654, upload-time = "2026-08-18T15:00:13.588Z" }, +] [package.optional-dependencies] tracing = [ diff --git a/plugins/nemo-experimentalist/framework-skills/nooa/SKILL.md b/plugins/nemo-experimentalist/framework-skills/nooa/SKILL.md index 85a6bc9d91..53cae54c8f 100644 --- a/plugins/nemo-experimentalist/framework-skills/nooa/SKILL.md +++ b/plugins/nemo-experimentalist/framework-skills/nooa/SKILL.md @@ -4,25 +4,24 @@ name: nooa description: Build, modify, debug, or optimize agents using NVIDIA-labs OO Agents (NOOA). Use for nooa.Agent subclasses, ellipsis generation methods, CodeAct or Predict strategies, ShellTools, Skill/TextSkill, context and persistence, MCP, tracing, middleware, channels, or trace analysis. -compatibility: Python >= 3.12,<3.14; uv; nooa at the revision pinned in the workspace root pyproject.toml +compatibility: Python >= 3.12,<3.14; uv; nooa at the version floor declared by this plugin metadata: upstream: https://github.com/NVIDIA-NeMo/labs-OO-Agents - revision: 6e0274dd03f883254a084cfb9f871ea580e03434 + version: ">=0.0.9" --- # NVIDIA-labs OO Agents (NOOA) -Use the `nooa` package and namespace this repository pins. The revision is set in -the workspace root `pyproject.toml` under `[tool.uv.sources]` — the plugin's own -`pyproject.toml` declares `nooa` without one. +Use the `nooa` package and namespace. It comes from PyPI, and the plugin's own +`pyproject.toml` declares the version floor. -For detailed framework guidance, consult the skills at the immutable upstream -revision this repository pins: -https://github.com/NVIDIA-NeMo/labs-OO-Agents/tree/6e0274dd03f883254a084cfb9f871ea580e03434/skills +For detailed framework guidance, consult the skills at the upstream tag that +matches the floor: +https://github.com/NVIDIA-NeMo/labs-OO-Agents/tree/v0.0.9/skills -Before changing framework behavior, inspect the pinned implementation or the +Before changing framework behavior, inspect the installed implementation or the matching upstream skill instead of guessing. In Experimentalist: - Call `super().__init__()` before attaching tools or skills. diff --git a/plugins/nemo-experimentalist/pyproject.toml b/plugins/nemo-experimentalist/pyproject.toml index ba16ec7552..b3513afe85 100644 --- a/plugins/nemo-experimentalist/pyproject.toml +++ b/plugins/nemo-experimentalist/pyproject.toml @@ -13,7 +13,7 @@ dependencies = [ "nemo-evaluator-sdk", "opentelemetry-proto>=1.42.1", "protobuf>=6.0.0", - "nooa", + "nooa>=0.0.9", "pyyaml>=6.0.3", "nemo-eval-author-plugin", "nemo-insights-plugin", diff --git a/plugins/nemo-experimentalist/tests/experimentalist/test_smoke_agent_assets.py b/plugins/nemo-experimentalist/tests/experimentalist/test_smoke_agent_assets.py index 3462184d6c..c77c098327 100644 --- a/plugins/nemo-experimentalist/tests/experimentalist/test_smoke_agent_assets.py +++ b/plugins/nemo-experimentalist/tests/experimentalist/test_smoke_agent_assets.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -"""Keep the smoke agent's task image, its NOOA pin, and its verifier honest. +"""Keep the smoke agent's task image, its NOOA version range, and its verifier honest. No Docker here on purpose: the image tag is a content hash, so a forgotten rebuild is a string comparison rather than something only a container run can @@ -24,12 +24,18 @@ _EXAMPLE_DIR = Path(__file__).resolve().parents[2] / "examples" / "smoke-agent" _SHARED = _EXAMPLE_DIR / "dataset" / "_shared" _HASHED = ("Dockerfile", "records.json") -_RENDERED_TASK_TREE_SHA256 = "d8d4face3d4aa0f5697faaea2bd6146a73573290910c216146a3753ced4b7906" +_RENDERED_TASK_TREE_SHA256 = "246b50d218d80fec7b030f93347cebe2f9b2563bb4d4d71103cf5f282e80d41a" -def _root_nooa_rev() -> str: - data = tomllib.loads((_REPO_ROOT / "pyproject.toml").read_text(encoding="utf-8")) - return data["tool"]["uv"]["sources"]["nooa"]["rev"] +def _plugin_nooa_specifier() -> str: + """Return the version specifier the plugin declares for nooa, e.g. ">=0.0.9".""" + plugin_pyproject = Path(__file__).resolve().parents[2] / "pyproject.toml" + data = tomllib.loads(plugin_pyproject.read_text(encoding="utf-8")) + for dep in data["project"]["dependencies"]: + found = re.fullmatch(r"nooa(?:\[[^\]]*\])?\s*(?P.+)", dep.strip()) + if found: + return found.group("spec").strip() + raise AssertionError("the plugin must declare a versioned nooa dependency") def _expected_tag() -> str: @@ -180,14 +186,18 @@ def test_verifier_does_not_echo_answers() -> None: assert forbidden not in code, f"{forbidden} publishes ground truth to the trial log" -def test_dockerfile_nooa_rev_matches_workspace() -> None: - """Check that the task image uses the workspace's NOOA revision.""" +def test_dockerfile_nooa_version_matches_the_plugin() -> None: + """Check that the task image resolves the same NOOA range as the plugin. + + The agent under test runs inside this image, so a floor that drifts from the + plugin's own lets the two pick up different NOOA releases. + """ dockerfile_path = _SHARED / "Dockerfile" if not dockerfile_path.is_file(): return # Task 4 creates it. - found = re.search(r"labs-OO-Agents\.git@([0-9a-f]{40})", dockerfile_path.read_text(encoding="utf-8")) - assert found is not None, "Dockerfile must pin NOOA to an explicit revision" - assert found.group(1) == _root_nooa_rev() + found = re.search(r"nooa\[[^\]]*\]\s*(?P[<>=!~][^\"']+)", dockerfile_path.read_text(encoding="utf-8")) + assert found is not None, "Dockerfile must constrain NOOA to a version range" + assert found.group("spec").strip() == _plugin_nooa_specifier() def test_task_image_runs_as_a_non_root_user() -> None: diff --git a/plugins/nemo-insights/pyproject.toml b/plugins/nemo-insights/pyproject.toml index be8ee879be..55c6532c83 100644 --- a/plugins/nemo-insights/pyproject.toml +++ b/plugins/nemo-insights/pyproject.toml @@ -11,7 +11,7 @@ dependencies = [ "httpx", "nemo-platform", "nemo-platform-plugin", - "nooa", + "nooa>=0.0.9", "opentelemetry-exporter-otlp>=1.42.1", "opentelemetry-sdk>=1.42.1", "pydantic>=2.12.0", diff --git a/pyproject.toml b/pyproject.toml index f0d5ac7811..0d73b39f92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -395,10 +395,6 @@ nemo-platform-plugin = { workspace = true } nemo-insights-plugin = { workspace = true } nemo-eval-author-plugin = { workspace = true } nemo-experimentalist-plugin = { workspace = true } -# Not published to PyPI yet, so this pins an immutable public commit. It is a commit -# rather than a tag because the callable `@strategy(llm=...)` support this plugin now -# depends on landed after v0.0.8; move back to a tag once one ships that contains it. -nooa = { git = "https://github.com/NVIDIA-NeMo/labs-OO-Agents.git", rev = "6e0274dd03f883254a084cfb9f871ea580e03434" } # Temporary until Fabric 0.2.0 publishes (mid-Aug): pin the monorepo SHA that lands # FABRIC-167 (Hermes MCP discover + preserve mcp.servers.*.env). Override every diff --git a/third_party/requirements-main.txt b/third_party/requirements-main.txt index 03929e6597..b74d1804a3 100644 --- a/third_party/requirements-main.txt +++ b/third_party/requirements-main.txt @@ -18,6 +18,7 @@ -e ./packages/nemo_evaluator_sdk ; (platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') # via # nemo-evaluator-plugin + # nemo-experimentalist-plugin # nemo-optimization-plugin -e ./packages/nemo_platform ; (platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') # via @@ -1778,7 +1779,9 @@ nltk==3.10.2 ; (platform_machine == 'arm64' and sys_platform == 'darwin') or (pl --hash=sha256:2c7ccacb765c5e26b0cb60fb1b57080af522c6924d12a714a243305ba3637412 \ --hash=sha256:fcfd80fb77931868cea8357573c79838b8abc609942ef9914d1c9f6070d4645c # via rouge-score -nooa @ git+https://github.com/NVIDIA-NeMo/labs-OO-Agents.git@6e0274dd03f883254a084cfb9f871ea580e03434 ; (platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') +nooa==0.0.9 ; (platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') \ + --hash=sha256:60b64663f34a47aec206137035d62e816c1147484bb74a8a4700a47d1a10b60c \ + --hash=sha256:c7a90ffb5b54094180efcb845e74a00c4182766745245f4258e613f9c12cb522 # via # nemo-eval-author-plugin # nemo-experimentalist-plugin @@ -1946,6 +1949,7 @@ opentelemetry-api==1.43.0 ; (platform_machine == 'arm64' and sys_platform == 'da # opentelemetry-processor-baggage # opentelemetry-sdk # opentelemetry-semantic-conventions + # wandb opentelemetry-distro==0.64b0 ; (platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') \ --hash=sha256:8a19716899854245b4028650ec1cca12d89f9be41571bbffe9e539cd55d2fd96 \ --hash=sha256:ce97b6cedfcf03dc54035c422485412eda63250e094f4bd63ef57d017d823f3c @@ -2681,6 +2685,7 @@ pyyaml==6.0.3 ; (platform_machine == 'arm64' and sys_platform == 'darwin') or (p # nemo-anonymizer-plugin # nemo-auditor-plugin # nemo-deployments-plugin + # nemo-eval-author-plugin # nemo-experimentalist-plugin # nemo-insights-plugin # nemo-optimization-plugin diff --git a/tools/check_nooa_import_surface.py b/tools/check_nooa_import_surface.py new file mode 100644 index 0000000000..29f2006580 --- /dev/null +++ b/tools/check_nooa_import_surface.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Check that the installed `nooa` provides every symbol the plugins import. + +`nooa` is a pre-1.0 dependency that moved from a git pin to a PyPI floor, so a +resolver is free to pick up a release that dropped or renamed something the +plugins reach for. Import errors from that surface only appear when the specific +module is first imported, which for agent components can be deep into a run. +This walks the imports statically instead and reports the whole gap at once. + + uv run python tools/check_nooa_import_surface.py + +Exits non-zero when something is missing. This checks names, not behaviour -- +a symbol that kept its name but changed semantics still needs the test suites. +""" + +import argparse +import ast +import importlib +import pathlib +import sys + +PLUGIN_SOURCE_ROOTS = ( + "plugins/nemo-insights/src", + "plugins/nemo-experimentalist/src", + "plugins/nemo-eval-author/src", +) + + +def collect_imports(roots: tuple[str, ...], repo_root: pathlib.Path) -> dict[str, set[str]]: + """Map each imported `nooa` module to the set of names taken from it.""" + imported: dict[str, set[str]] = {} + for root in roots: + for path in sorted((repo_root / root).rglob("*.py")): + try: + tree = ast.parse(path.read_text(encoding="utf-8")) + except SyntaxError as exc: + print(f"warning: skipping {path} ({exc})", file=sys.stderr) + continue + for node in ast.walk(tree): + if isinstance(node, ast.ImportFrom): + if node.level == 0 and node.module and node.module.split(".")[0] == "nooa": + imported.setdefault(node.module, set()).update(alias.name for alias in node.names) + elif isinstance(node, ast.Import): + for alias in node.names: + if alias.name.split(".")[0] == "nooa": + imported.setdefault(alias.name, set()) + return imported + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--repo-root", + type=pathlib.Path, + default=pathlib.Path(__file__).resolve().parent.parent, + help="Repository root (defaults to the parent of tools/).", + ) + args = parser.parse_args() + + try: + nooa = importlib.import_module("nooa") + except ImportError as exc: + print(f"FAIL: cannot import nooa: {exc}") + print("Install the workspace first: uv sync --all-packages") + return 1 + + version = getattr(nooa, "__version__", "unknown") + imported = collect_imports(PLUGIN_SOURCE_ROOTS, args.repo_root) + print(f"installed nooa: {version}") + print(f"checking {sum(len(v) for v in imported.values())} names across {len(imported)} modules") + + missing: list[str] = [] + for module_name in sorted(imported): + try: + module = importlib.import_module(module_name) + except ImportError as exc: + missing.append(f"{module_name} (module missing: {exc})") + continue + for symbol in sorted(imported[module_name]): + if symbol != "*" and not hasattr(module, symbol): + missing.append(f"{module_name}.{symbol}") + + if missing: + print(f"\nFAIL: {len(missing)} missing:") + for item in missing: + print(f" - {item}") + return 1 + + print("\nOK: every imported nooa name resolves.") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/uv.lock b/uv.lock index 24df3a62d2..319fffe6df 100644 --- a/uv.lock +++ b/uv.lock @@ -4369,7 +4369,7 @@ requires-dist = [ { name = "nemo-insights-plugin", editable = "plugins/nemo-insights" }, { name = "nemo-platform", editable = "packages/nemo_platform" }, { name = "nemo-platform-plugin", editable = "packages/nemo_platform_plugin" }, - { name = "nooa", git = "https://github.com/NVIDIA-NeMo/labs-OO-Agents.git?rev=6e0274dd03f883254a084cfb9f871ea580e03434" }, + { name = "nooa", specifier = ">=0.0.9" }, { name = "pydantic", specifier = ">=2" }, { name = "pyyaml", specifier = ">=6.0.3" }, { name = "tomlkit", specifier = ">=0.13.3" }, @@ -4517,7 +4517,7 @@ requires-dist = [ { name = "nemo-insights-plugin", editable = "plugins/nemo-insights" }, { name = "nemo-platform", editable = "packages/nemo_platform" }, { name = "nemo-platform-plugin", editable = "packages/nemo_platform_plugin" }, - { name = "nooa", git = "https://github.com/NVIDIA-NeMo/labs-OO-Agents.git?rev=6e0274dd03f883254a084cfb9f871ea580e03434" }, + { name = "nooa", specifier = ">=0.0.9" }, { name = "opentelemetry-proto", specifier = ">=1.42.1" }, { name = "protobuf", specifier = ">=6.0.0" }, { name = "pydantic", specifier = ">=2" }, @@ -4689,7 +4689,7 @@ requires-dist = [ { name = "httpx" }, { name = "nemo-platform", editable = "packages/nemo_platform" }, { name = "nemo-platform-plugin", editable = "packages/nemo_platform_plugin" }, - { name = "nooa", git = "https://github.com/NVIDIA-NeMo/labs-OO-Agents.git?rev=6e0274dd03f883254a084cfb9f871ea580e03434" }, + { name = "nooa", specifier = ">=0.0.9" }, { name = "opentelemetry-exporter-otlp", specifier = ">=1.42.1" }, { name = "opentelemetry-sdk", specifier = ">=1.42.1" }, { name = "pydantic", specifier = ">=2.12.0" }, @@ -8137,14 +8137,18 @@ wheels = [ [[package]] name = "nooa" -version = "0.0.9.dev46" -source = { git = "https://github.com/NVIDIA-NeMo/labs-OO-Agents.git?rev=6e0274dd03f883254a084cfb9f871ea580e03434#6e0274dd03f883254a084cfb9f871ea580e03434" } +version = "0.0.9" +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "litellm", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "openinference-instrumentation-litellm", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "pydantic", extra = ["email"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/34/6f/c4e3ea70b373f72f98c12d23fd61f8525462bcecb4a969b58fbb67092699/nooa-0.0.9.tar.gz", hash = "sha256:c7a90ffb5b54094180efcb845e74a00c4182766745245f4258e613f9c12cb522", size = 3315964, upload-time = "2026-08-18T15:00:15.26Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/27/11b2754bc31994244418d0a55447f20bc0efbd9d2573802db13c7ca367b5/nooa-0.0.9-py3-none-any.whl", hash = "sha256:60b64663f34a47aec206137035d62e816c1147484bb74a8a4700a47d1a10b60c", size = 1104654, upload-time = "2026-08-18T15:00:13.588Z" }, +] [[package]] name = "nox" From 6fbfdc76edccdfd5c1aa6c64afcf250169a33035 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 18 Aug 2026 16:33:40 +0000 Subject: [PATCH 2/7] feat(packaging): ship insights, experimentalist, and eval-author in [all] `uv tool install nemo-platform[all]` did not install these three plugins. `[all]` resolves to `[services]` -> `[plugins]`, and `[plugins]` is generated by `make vendor` from `[tool.bundle-package]`, which had no entry for them. They were only ever reachable through the root `enabled-plugins` group, so local syncs and container images had them while the published wheel did not. Adding the bundle entries is the whole change; `make vendor` regenerates the three extras, grows `[plugins]` from ten to thirteen, and inherits the entry points. Nothing pinned these plugins out on purpose -- the blocker was `nooa`, which only reached PyPI as of 0.0.9. Verified against a wheel built from this branch and installed into a clean venv: `nemo agents --help` lists analyst, eval-author, and experimentalist, `nemo insights` is present, and `nemo agents experimentalist components` resolves every component. The build hook rewrites the Experimentalist <-> Eval Author cycle into intra-wheel extras, so no unresolvable workspace name reaches Requires-Dist. Signed-off-by: Cursor Agent Co-authored-by: Aditya Pandey --- packages/nemo_platform/pyproject.toml | 78 +++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/packages/nemo_platform/pyproject.toml b/packages/nemo_platform/pyproject.toml index b3c8887a56..a17ffd3b14 100644 --- a/packages/nemo_platform/pyproject.toml +++ b/packages/nemo_platform/pyproject.toml @@ -280,6 +280,18 @@ nemo-data-designer-plugin = [ "pandas", ] +# Generated from [tool.bundle-package]; do not edit by hand. +nemo-eval-author-plugin = [ + "pydantic>=2", + "harbor>=0.18", + "nooa>=0.0.9", + "nemo-experimentalist-plugin", + "nemo-insights-plugin", + "nemo-platform-plugin", + "pyyaml>=6.0.3", + "tomlkit>=0.13.3", +] + # Generated from [tool.bundle-package]; do not edit by hand. nemo-evaluator-plugin = [ "cloudpickle>=3.1.1", @@ -309,6 +321,22 @@ nemo-evaluator-sdk = [ "nemo-fabric>=0.1.1,<0.3.0", ] +# Generated from [tool.bundle-package]; do not edit by hand. +nemo-experimentalist-plugin = [ + "pydantic>=2", + "httpx", + "harbor>=0.16", + "nemo-evaluator-sdk", + "opentelemetry-proto>=1.42.1", + "protobuf>=6.0.0", + "nooa>=0.0.9", + "pyyaml>=6.0.3", + "nemo-eval-author-plugin", + "nemo-insights-plugin", + "nemo-platform-plugin", + "tomlkit>=0.13.3", +] + # Generated from [tool.bundle-package]; do not edit by hand. nemo-guardrails-plugin = [ "nemo-platform-plugin", @@ -319,6 +347,20 @@ nemo-guardrails-plugin = [ "langchain-openai>=1.3.5", ] +# Generated from [tool.bundle-package]; do not edit by hand. +nemo-insights-plugin = [ + "fastapi>=0.115", + "httpx", + "nemo-platform-plugin", + "nooa>=0.0.9", + "opentelemetry-exporter-otlp>=1.42.1", + "opentelemetry-sdk>=1.42.1", + "pydantic>=2.12.0", + "pyyaml>=6.0.3", + "typer>=0.20.0", + "tzdata==2026.2", +] + # Generated from [tool.bundle-package]; do not edit by hand. nemo-optimization-plugin = [ "nemo-platform-plugin", @@ -437,8 +479,11 @@ plugins = [ "nemo-platform[nemo-anonymizer-plugin]", "nemo-platform[nemo-auditor-plugin]", "nemo-platform[nemo-data-designer-plugin]", + "nemo-platform[nemo-eval-author-plugin]", "nemo-platform[nemo-evaluator-plugin]", + "nemo-platform[nemo-experimentalist-plugin]", "nemo-platform[nemo-guardrails-plugin]", + "nemo-platform[nemo-insights-plugin]", "nemo-platform[nemo-optimization-plugin]", "nemo-platform[nemo-safe-synthesizer-plugin]", "nemo-platform[nemo-switchyard]", @@ -511,6 +556,13 @@ anonymizer = "nemo_anonymizer_plugin.cli:AnonymizerCLI" auditor = "nemo_auditor.cli:AuditorPluginCLI" data-designer = "nemo_data_designer_plugin.cli.main:DataDesignerCLI" evaluator = "nemo_evaluator.cli:EvaluatorPluginCLI" +insights = "nemo_insights_plugin.cli:InsightsCLI" + +# Generated from [tool.bundle-package]; do not edit this table by hand. +[project.entry-points."nemo.cli.agents"] +eval-author = "nemo_eval_author_plugin.cli:EvalAuthorCLI" +experimentalist = "nemo_experimentalist_plugin.cli:ExperimentalistCLI" +analyst = "nemo_insights_plugin.analyst.cli:AnalystCLI" # Generated from [tool.bundle-package]; do not edit this table by hand. [project.entry-points."nemo.client_provider"] @@ -519,11 +571,25 @@ platform = "nmp.common.client_factory:PlatformNemoClientProvider" # Generated from [tool.bundle-package]; do not edit this table by hand. [project.entry-points."nemo.controllers"] agents-deployment = "nemo_agents_plugin.runner.controller:AgentDeploymentController" +insights-analysis = "nemo_insights_plugin.controller:InsightsAnalysisController" # Generated from [tool.bundle-package]; do not edit this table by hand. [project.entry-points."nemo.docs"] auditor = "nemo_auditor.docs:get_docs_path" +# Generated from [tool.bundle-package]; do not edit this table by hand. +[project.entry-points."nemo.experimentalist.components"] +"strategy.evolutionary" = "nemo_experimentalist_plugin.experimentalist.strategies.evolutionary" +"builder.code-edit" = "nemo_experimentalist_plugin.experimentalist.components.coder" +"builder.import" = "nemo_experimentalist_plugin.experimentalist.components.importer" +"selector.pareto-diversity" = "nemo_experimentalist_plugin.experimentalist.components.selector" +"proposer.code-change" = "nemo_experimentalist_plugin.experimentalist.components.proposer" +"terminator.convergence" = "nemo_experimentalist_plugin.experimentalist.components.terminator" +"root-cause-analyzer.trace" = "nemo_experimentalist_plugin.experimentalist.components.analyzer" +"trajectory-scorer.goal-tree" = "nemo_experimentalist_plugin.experimentalist.components.trace_scorer" +"outcome-evaluator.harbor-native" = "nemo_experimentalist_plugin.experimentalist.components.evaluator.harbor_native" +"outcome-evaluator.harbor-runner" = "nemo_experimentalist_plugin.experimentalist.components.evaluator.harbor_evaluator" + # Generated from [tool.bundle-package]; do not edit this table by hand. [project.entry-points."nemo.functions"] "anonymizer.preview" = "nemo_anonymizer_plugin.functions.preview:PreviewFunction" @@ -546,6 +612,7 @@ nemo-switchyard = "nemo_switchyard.middleware:SwitchyardMiddleware" "data-designer.create" = "nemo_data_designer_plugin.jobs.create:CreateJob" "evaluator.evaluate" = "nemo_evaluator.jobs.evaluate:EvaluateJob" "evaluator.agent-evaluate" = "nemo_evaluator.jobs.agent_evaluate:AgentEvalJob" +"insights.analyze-job" = "nemo_insights_plugin.jobs.analyze:AnalyzeJob" # Generated from [tool.bundle-package]; do not edit this table by hand. [project.entry-points."nemo.optimization.backends"] @@ -560,6 +627,7 @@ auditor = "nemo_auditor.sdk:auditor_sdk_resources" data_designer = "nemo_data_designer_plugin.sdk.resources:data_designer_sdk_resources" evaluator = "nemo_evaluator.sdk.resources:evaluator_sdk_resources" safe_synthesizer = "nemo_safe_synthesizer_plugin.sdk.resources:safe_synthesizer_sdk_resources" +insights = "nemo_insights_plugin.sdk:insights_sdk_resources" # Generated from [tool.bundle-package]; do not edit this table by hand. [project.entry-points."nemo.sdk_provider"] @@ -577,6 +645,7 @@ anonymizer = "nemo_anonymizer_plugin.service:AnonymizerService" auditor = "nemo_auditor.service:AuditorPluginService" data-designer = "nemo_data_designer_plugin.service:DataDesignerService" evaluator = "nemo_evaluator.service:EvaluatorPluginService" +insights = "nemo_insights_plugin.service:InsightsService" # Generated from [tool.bundle-package]; do not edit this table by hand. [project.entry-points."nemo.skills"] @@ -588,6 +657,8 @@ anonymizer = "nemo_anonymizer_plugin.skills:get_skills_path" guardrails = "nemo_guardrails_plugin.skills:get_skills_path" platform = "nemo_platform.skills:skills_dir" safe-synthesizer = "nemo_safe_synthesizer_plugin.skills:get_skills_path" +experimentalist = "nemo_experimentalist_plugin.skills:skills_dir" +insights = "nemo_insights_plugin.skills:skills_dir" [tool.uv.sources] nemo-platform-sdk = { workspace = true } nemo-platform-ext = { workspace = true } @@ -639,7 +710,14 @@ nemo-agents-plugin = { source = "../../plugins/nemo-agents/src/nemo_agents_plugi nemo-anonymizer-plugin = { source = "../../plugins/nemo-anonymizer/src/nemo_anonymizer_plugin", module = "nemo_anonymizer_plugin", inherit = { "entry-points" = ["nemo.*"] } } nemo-auditor-plugin = { source = "../../plugins/nemo-auditor/src/nemo_auditor", module = "nemo_auditor", inherit = { "entry-points" = ["nemo.*"] } } nemo-data-designer-plugin = { source = "../../plugins/nemo-data-designer/src/nemo_data_designer_plugin", module = "nemo_data_designer_plugin", inherit = { "entry-points" = ["nemo.*"] } } +# Eval Author, Experimentalist, and Insights ship together: Experimentalist imports +# EvalAuthor and EvalAuthorConfig at module scope, Eval Author still borrows +# Experimentalist helpers, and both read the Insights profile contract. Bundling all +# three into one distribution collapses that dependency cycle into intra-wheel extras. +nemo-eval-author-plugin = { source = "../../plugins/nemo-eval-author/src/nemo_eval_author_plugin", module = "nemo_eval_author_plugin", inherit = { "entry-points" = ["nemo.*"] } } nemo-evaluator-plugin = { source = "../../plugins/nemo-evaluator/src/nemo_evaluator", module = "nemo_evaluator", inherit = { "entry-points" = ["nemo.*"] } } +nemo-experimentalist-plugin = { source = "../../plugins/nemo-experimentalist/src/nemo_experimentalist_plugin", module = "nemo_experimentalist_plugin", inherit = { "entry-points" = ["nemo.*"] } } +nemo-insights-plugin = { source = "../../plugins/nemo-insights/src/nemo_insights_plugin", module = "nemo_insights_plugin", inherit = { "entry-points" = ["nemo.*"] } } # Required by agents.optimize (OptimizeJob lives here; agents plugin imports it at router setup). nemo-optimization-plugin = { source = "../../plugins/nemo-optimization/src/nemo_optimization", module = "nemo_optimization", inherit = { "entry-points" = ["nemo.*"] } } nemo-guardrails-plugin = { source = "../../plugins/nemo-guardrails/src/nemo_guardrails_plugin", module = "nemo_guardrails_plugin", inherit = { "entry-points" = ["nemo.*"] } } From e508c37a2f7ac7d50b5d2e029e49acd7fb7e1197 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 18 Aug 2026 16:37:24 +0000 Subject: [PATCH 3/7] build: relock after the wrapper gained the three plugin extras `make vendor` added the extras but the root lock still described the old `nemo-platform[all]` closure, so the uv.lock drift check failed. Signed-off-by: Cursor Agent Co-authored-by: Aditya Pandey --- uv.lock | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 140 insertions(+), 1 deletion(-) diff --git a/uv.lock b/uv.lock index 319fffe6df..f2083e7599 100644 --- a/uv.lock +++ b/uv.lock @@ -4837,6 +4837,7 @@ all = [ { name = "garak-api", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "greenlet", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "gunicorn", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "harbor", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "httpx", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "hvac", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "kubernetes", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -4851,9 +4852,12 @@ all = [ { name = "nemo-agents-example-calculator", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-anonymizer", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-auditor-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-eval-author-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-evaluator-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-experimentalist-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-fabric", extra = ["claude", "codex", "deepagents", "relay"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-fabric-adapters-hermes", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-insights-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-optimization-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-platform-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-platform-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -4863,6 +4867,7 @@ all = [ { name = "nmp-auth", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nmp-common", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nmp-guardrails", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nooa", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "numpy", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nvidia-nat-atif", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nvidia-nat-config-optimizer", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -4880,6 +4885,7 @@ all = [ { name = "opentelemetry-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "optuna", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "pandas", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "protobuf", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "psycopg2-binary", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "pydantic", extra = ["email"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "pydantic-settings", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -4893,8 +4899,10 @@ all = [ { name = "streaming-form-data", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "switchyard-vendored", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "tenacity", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "tomlkit", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "typer", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "types-aioboto3", extra = ["s3"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "tzdata", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "urllib3", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "uvicorn", extra = ["standard"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "wasmtime", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -5119,6 +5127,16 @@ nemo-data-designer-plugin = [ { name = "nemo-platform-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "pandas", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] +nemo-eval-author-plugin = [ + { name = "harbor", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-experimentalist-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-insights-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-platform-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nooa", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "pydantic", extra = ["email"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "pyyaml", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "tomlkit", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, +] nemo-evaluator-plugin = [ { name = "cloudpickle", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-evaluator-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -5144,6 +5162,20 @@ nemo-evaluator-sdk = [ { name = "rouge-score", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "sacrebleu", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] +nemo-experimentalist-plugin = [ + { name = "harbor", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "httpx", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-eval-author-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-evaluator-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-insights-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-platform-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nooa", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "opentelemetry-proto", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "protobuf", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "pydantic", extra = ["email"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "pyyaml", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "tomlkit", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, +] nemo-guardrails-plugin = [ { name = "langchain", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "langchain-community", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -5152,6 +5184,18 @@ nemo-guardrails-plugin = [ { name = "nemo-platform-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemoguardrails", extra = ["tracing"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] +nemo-insights-plugin = [ + { name = "fastapi", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "httpx", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-platform-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nooa", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "opentelemetry-exporter-otlp", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "opentelemetry-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "pydantic", extra = ["email"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "pyyaml", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "typer", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "tzdata", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, +] nemo-optimization-plugin = [ { name = "matplotlib", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-evaluator-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -5261,6 +5305,7 @@ plugins = [ { name = "fsspec", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "garak-api", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "gunicorn", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "harbor", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "httpx", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "langchain", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "langchain-aws", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -5270,14 +5315,18 @@ plugins = [ { name = "matplotlib", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-agents-example-calculator", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-anonymizer", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-eval-author-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-evaluator-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-experimentalist-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-fabric", extra = ["claude", "codex", "deepagents", "relay"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-fabric-adapters-hermes", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-insights-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-optimization-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-platform-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-platform-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-safe-synthesizer", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemoguardrails", extra = ["tracing"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nooa", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "numpy", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nvidia-nat-atif", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nvidia-nat-config-optimizer", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -5285,8 +5334,12 @@ plugins = [ { name = "nvidia-nat-eval", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nvidia-nat-langchain", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nvidia-nat-opentelemetry", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "opentelemetry-exporter-otlp", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "opentelemetry-proto", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "opentelemetry-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "optuna", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "pandas", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "protobuf", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "pydantic", extra = ["email"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "pydantic-settings", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "python-multipart", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -5294,7 +5347,9 @@ plugins = [ { name = "requests", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "rich", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "switchyard-vendored", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "tomlkit", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "typer", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "tzdata", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "uvicorn", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] secrets-service = [ @@ -5326,6 +5381,7 @@ services = [ { name = "garak-api", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "greenlet", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "gunicorn", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "harbor", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "httpx", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "hvac", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "kubernetes", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -5340,9 +5396,12 @@ services = [ { name = "nemo-agents-example-calculator", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-anonymizer", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-auditor-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-eval-author-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-evaluator-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-experimentalist-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-fabric", extra = ["claude", "codex", "deepagents", "relay"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-fabric-adapters-hermes", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nemo-insights-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-optimization-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-platform-plugin", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nemo-platform-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -5352,6 +5411,7 @@ services = [ { name = "nmp-auth", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nmp-common", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nmp-guardrails", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nooa", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "numpy", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nvidia-nat-atif", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "nvidia-nat-config-optimizer", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -5369,6 +5429,7 @@ services = [ { name = "opentelemetry-sdk", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "optuna", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "pandas", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "protobuf", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "psycopg2-binary", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "pydantic", extra = ["email"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "pydantic-settings", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -5382,8 +5443,10 @@ services = [ { name = "streaming-form-data", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "switchyard-vendored", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "tenacity", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "tomlkit", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "typer", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "types-aioboto3", extra = ["s3"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "tzdata", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "urllib3", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "uvicorn", extra = ["standard"], marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, { name = "wasmtime", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, @@ -5503,6 +5566,7 @@ requires-dist = [ { name = "fastapi", marker = "extra == 'all'" }, { name = "fastapi", marker = "extra == 'all'", specifier = ">=0.100.0" }, { name = "fastapi", marker = "extra == 'all'", specifier = ">=0.109.0" }, + { name = "fastapi", marker = "extra == 'all'", specifier = ">=0.115" }, { name = "fastapi", marker = "extra == 'all'", specifier = ">=0.115.5,<1.0.0" }, { name = "fastapi", marker = "extra == 'all'", specifier = ">=0.115.8" }, { name = "fastapi", marker = "extra == 'core-service'", specifier = ">=0.100.0" }, @@ -5516,14 +5580,17 @@ requires-dist = [ { name = "fastapi", marker = "extra == 'models-service'", specifier = ">=0.115.8" }, { name = "fastapi", marker = "extra == 'nemo-anonymizer-plugin'" }, { name = "fastapi", marker = "extra == 'nemo-data-designer-plugin'" }, + { name = "fastapi", marker = "extra == 'nemo-insights-plugin'", specifier = ">=0.115" }, { name = "fastapi", marker = "extra == 'nemo-platform-plugin'", specifier = ">=0.115.4" }, { name = "fastapi", marker = "extra == 'nemo-safe-synthesizer-plugin'", specifier = ">=0.115.8" }, { name = "fastapi", marker = "extra == 'plugins'" }, + { name = "fastapi", marker = "extra == 'plugins'", specifier = ">=0.115" }, { name = "fastapi", marker = "extra == 'plugins'", specifier = ">=0.115.8" }, { name = "fastapi", marker = "extra == 'secrets-service'", specifier = ">=0.115.8" }, { name = "fastapi", marker = "extra == 'services'" }, { name = "fastapi", marker = "extra == 'services'", specifier = ">=0.100.0" }, { name = "fastapi", marker = "extra == 'services'", specifier = ">=0.109.0" }, + { name = "fastapi", marker = "extra == 'services'", specifier = ">=0.115" }, { name = "fastapi", marker = "extra == 'services'", specifier = ">=0.115.5,<1.0.0" }, { name = "fastapi", marker = "extra == 'services'", specifier = ">=0.115.8" }, { name = "fastapi", extras = ["standard"], marker = "extra == 'all'", specifier = ">=0.115.4" }, @@ -5556,6 +5623,15 @@ requires-dist = [ { name = "gunicorn", marker = "extra == 'nemo-safe-synthesizer-plugin'", specifier = ">=23.0.0" }, { name = "gunicorn", marker = "extra == 'plugins'", specifier = ">=23.0.0" }, { name = "gunicorn", marker = "extra == 'services'", specifier = ">=23.0.0" }, + { name = "harbor", marker = "extra == 'all'", specifier = ">=0.16" }, + { name = "harbor", marker = "extra == 'all'", specifier = ">=0.18" }, + { name = "harbor", marker = "extra == 'nemo-eval-author-plugin'", specifier = ">=0.18" }, + { name = "harbor", marker = "extra == 'nemo-experimentalist-plugin'", specifier = ">=0.16" }, + { name = "harbor", marker = "extra == 'plugins'", specifier = ">=0.16" }, + { name = "harbor", marker = "extra == 'plugins'", specifier = ">=0.18" }, + { name = "harbor", marker = "extra == 'services'", specifier = ">=0.16" }, + { name = "harbor", marker = "extra == 'services'", specifier = ">=0.18" }, + { name = "httpx", marker = "extra == 'all'" }, { name = "httpx", marker = "extra == 'all'", specifier = ">=0.27.0" }, { name = "httpx", marker = "extra == 'all'", specifier = ">=0.27.2" }, { name = "httpx", marker = "extra == 'auditor-service'", specifier = ">=0.28.1,<1.0.0" }, @@ -5567,10 +5643,14 @@ requires-dist = [ { name = "httpx", marker = "extra == 'nemo-auditor-plugin'", specifier = ">=0.27" }, { name = "httpx", marker = "extra == 'nemo-data-designer-plugin'", specifier = ">=0.27" }, { name = "httpx", marker = "extra == 'nemo-evaluator-sdk'", specifier = ">=0.27.0,<1" }, + { name = "httpx", marker = "extra == 'nemo-experimentalist-plugin'" }, + { name = "httpx", marker = "extra == 'nemo-insights-plugin'" }, { name = "httpx", marker = "extra == 'nemo-platform-sdk'", specifier = ">=0.23.0,<1" }, { name = "httpx", marker = "extra == 'nemo-safe-synthesizer-plugin'", specifier = ">=0.27.2" }, + { name = "httpx", marker = "extra == 'plugins'" }, { name = "httpx", marker = "extra == 'plugins'", specifier = ">=0.27" }, { name = "httpx", marker = "extra == 'plugins'", specifier = ">=0.27.2" }, + { name = "httpx", marker = "extra == 'services'" }, { name = "httpx", marker = "extra == 'services'", specifier = ">=0.27.0" }, { name = "httpx", marker = "extra == 'services'", specifier = ">=0.27.2" }, { name = "httpx", marker = "extra == 'switchyard-vendored'", specifier = ">=0.28.1,<1.0" }, @@ -5639,11 +5719,20 @@ requires-dist = [ { name = "nemo-auditor-plugin", marker = "extra == 'all'", editable = "plugins/nemo-auditor" }, { name = "nemo-auditor-plugin", marker = "extra == 'platform-seed-service'", editable = "plugins/nemo-auditor" }, { name = "nemo-auditor-plugin", marker = "extra == 'services'", editable = "plugins/nemo-auditor" }, + { name = "nemo-eval-author-plugin", marker = "extra == 'all'", editable = "plugins/nemo-eval-author" }, + { name = "nemo-eval-author-plugin", marker = "extra == 'nemo-experimentalist-plugin'", editable = "plugins/nemo-eval-author" }, + { name = "nemo-eval-author-plugin", marker = "extra == 'plugins'", editable = "plugins/nemo-eval-author" }, + { name = "nemo-eval-author-plugin", marker = "extra == 'services'", editable = "plugins/nemo-eval-author" }, { name = "nemo-evaluator-sdk", marker = "extra == 'all'", editable = "packages/nemo_evaluator_sdk" }, { name = "nemo-evaluator-sdk", marker = "extra == 'nemo-evaluator-plugin'", editable = "packages/nemo_evaluator_sdk" }, + { name = "nemo-evaluator-sdk", marker = "extra == 'nemo-experimentalist-plugin'", editable = "packages/nemo_evaluator_sdk" }, { name = "nemo-evaluator-sdk", marker = "extra == 'nemo-optimization-plugin'", editable = "packages/nemo_evaluator_sdk" }, { name = "nemo-evaluator-sdk", marker = "extra == 'plugins'", editable = "packages/nemo_evaluator_sdk" }, { name = "nemo-evaluator-sdk", marker = "extra == 'services'", editable = "packages/nemo_evaluator_sdk" }, + { name = "nemo-experimentalist-plugin", marker = "extra == 'all'", editable = "plugins/nemo-experimentalist" }, + { name = "nemo-experimentalist-plugin", marker = "extra == 'nemo-eval-author-plugin'", editable = "plugins/nemo-experimentalist" }, + { name = "nemo-experimentalist-plugin", marker = "extra == 'plugins'", editable = "plugins/nemo-experimentalist" }, + { name = "nemo-experimentalist-plugin", marker = "extra == 'services'", editable = "plugins/nemo-experimentalist" }, { name = "nemo-fabric", marker = "extra == 'nemo-evaluator-sdk'", git = "https://github.com/NVIDIA/NeMo-Fabric.git?rev=e7353383024523179be6a009ef16dea223bea8c0" }, { name = "nemo-fabric", extras = ["claude", "codex", "deepagents", "relay"], marker = "extra == 'all'", git = "https://github.com/NVIDIA/NeMo-Fabric.git?rev=e7353383024523179be6a009ef16dea223bea8c0" }, { name = "nemo-fabric", extras = ["claude", "codex", "deepagents", "relay"], marker = "extra == 'nemo-agents-plugin'", git = "https://github.com/NVIDIA/NeMo-Fabric.git?rev=e7353383024523179be6a009ef16dea223bea8c0" }, @@ -5653,6 +5742,11 @@ requires-dist = [ { name = "nemo-fabric-adapters-hermes", marker = "python_full_version < '3.14' and extra == 'nemo-agents-plugin'", git = "https://github.com/NVIDIA/NeMo-Fabric.git?subdirectory=adapters%2Fhermes&rev=e7353383024523179be6a009ef16dea223bea8c0" }, { name = "nemo-fabric-adapters-hermes", marker = "python_full_version < '3.14' and extra == 'plugins'", git = "https://github.com/NVIDIA/NeMo-Fabric.git?subdirectory=adapters%2Fhermes&rev=e7353383024523179be6a009ef16dea223bea8c0" }, { name = "nemo-fabric-adapters-hermes", marker = "python_full_version < '3.14' and extra == 'services'", git = "https://github.com/NVIDIA/NeMo-Fabric.git?subdirectory=adapters%2Fhermes&rev=e7353383024523179be6a009ef16dea223bea8c0" }, + { name = "nemo-insights-plugin", marker = "extra == 'all'", editable = "plugins/nemo-insights" }, + { name = "nemo-insights-plugin", marker = "extra == 'nemo-eval-author-plugin'", editable = "plugins/nemo-insights" }, + { name = "nemo-insights-plugin", marker = "extra == 'nemo-experimentalist-plugin'", editable = "plugins/nemo-insights" }, + { name = "nemo-insights-plugin", marker = "extra == 'plugins'", editable = "plugins/nemo-insights" }, + { name = "nemo-insights-plugin", marker = "extra == 'services'", editable = "plugins/nemo-insights" }, { name = "nemo-optimization-plugin", marker = "extra == 'all'", editable = "plugins/nemo-optimization" }, { name = "nemo-optimization-plugin", marker = "extra == 'nemo-agents-plugin'", editable = "plugins/nemo-optimization" }, { name = "nemo-optimization-plugin", marker = "extra == 'plugins'", editable = "plugins/nemo-optimization" }, @@ -5667,8 +5761,11 @@ requires-dist = [ { name = "nemo-platform-plugin", marker = "extra == 'nemo-anonymizer-plugin'", editable = "packages/nemo_platform_plugin" }, { name = "nemo-platform-plugin", marker = "extra == 'nemo-auditor-plugin'", editable = "packages/nemo_platform_plugin" }, { name = "nemo-platform-plugin", marker = "extra == 'nemo-data-designer-plugin'", editable = "packages/nemo_platform_plugin" }, + { name = "nemo-platform-plugin", marker = "extra == 'nemo-eval-author-plugin'", editable = "packages/nemo_platform_plugin" }, { name = "nemo-platform-plugin", marker = "extra == 'nemo-evaluator-plugin'", editable = "packages/nemo_platform_plugin" }, + { name = "nemo-platform-plugin", marker = "extra == 'nemo-experimentalist-plugin'", editable = "packages/nemo_platform_plugin" }, { name = "nemo-platform-plugin", marker = "extra == 'nemo-guardrails-plugin'", editable = "packages/nemo_platform_plugin" }, + { name = "nemo-platform-plugin", marker = "extra == 'nemo-insights-plugin'", editable = "packages/nemo_platform_plugin" }, { name = "nemo-platform-plugin", marker = "extra == 'nemo-optimization-plugin'", editable = "packages/nemo_platform_plugin" }, { name = "nemo-platform-plugin", marker = "extra == 'nemo-platform-sdk'", editable = "packages/nemo_platform_plugin" }, { name = "nemo-platform-plugin", marker = "extra == 'nemo-safe-synthesizer-plugin'", editable = "packages/nemo_platform_plugin" }, @@ -5722,6 +5819,12 @@ requires-dist = [ { name = "nmp-guardrails", marker = "extra == 'all'", editable = "services/guardrails" }, { name = "nmp-guardrails", marker = "extra == 'platform-seed-service'", editable = "services/guardrails" }, { name = "nmp-guardrails", marker = "extra == 'services'", editable = "services/guardrails" }, + { name = "nooa", marker = "extra == 'all'", specifier = ">=0.0.9" }, + { name = "nooa", marker = "extra == 'nemo-eval-author-plugin'", specifier = ">=0.0.9" }, + { name = "nooa", marker = "extra == 'nemo-experimentalist-plugin'", specifier = ">=0.0.9" }, + { name = "nooa", marker = "extra == 'nemo-insights-plugin'", specifier = ">=0.0.9" }, + { name = "nooa", marker = "extra == 'plugins'", specifier = ">=0.0.9" }, + { name = "nooa", marker = "extra == 'services'", specifier = ">=0.0.9" }, { name = "numpy", marker = "extra == 'all'", specifier = ">=1.26.0" }, { name = "numpy", marker = "extra == 'nemo-optimization-plugin'", specifier = ">=1.26.0" }, { name = "numpy", marker = "extra == 'plugins'", specifier = ">=1.26.0" }, @@ -5765,8 +5868,12 @@ requires-dist = [ { name = "opentelemetry-distro", marker = "extra == 'guardrails-service'", specifier = ">=0.64b0" }, { name = "opentelemetry-distro", marker = "extra == 'services'", specifier = ">=0.64b0" }, { name = "opentelemetry-exporter-otlp", marker = "extra == 'all'", specifier = ">=1.22.0" }, + { name = "opentelemetry-exporter-otlp", marker = "extra == 'all'", specifier = ">=1.42.1" }, { name = "opentelemetry-exporter-otlp", marker = "extra == 'guardrails-service'", specifier = ">=1.22.0" }, + { name = "opentelemetry-exporter-otlp", marker = "extra == 'nemo-insights-plugin'", specifier = ">=1.42.1" }, + { name = "opentelemetry-exporter-otlp", marker = "extra == 'plugins'", specifier = ">=1.42.1" }, { name = "opentelemetry-exporter-otlp", marker = "extra == 'services'", specifier = ">=1.22.0" }, + { name = "opentelemetry-exporter-otlp", marker = "extra == 'services'", specifier = ">=1.42.1" }, { name = "opentelemetry-exporter-otlp-proto-grpc", marker = "extra == 'nmp-common'", specifier = ">=1.38.0" }, { name = "opentelemetry-exporter-otlp-proto-http", marker = "extra == 'nmp-common'", specifier = ">=1.38.0" }, { name = "opentelemetry-exporter-prometheus", marker = "extra == 'nmp-common'", specifier = ">=0.64b0" }, @@ -5786,15 +5893,23 @@ requires-dist = [ { name = "opentelemetry-processor-baggage", marker = "extra == 'nmp-common'", specifier = ">=0.64b0" }, { name = "opentelemetry-proto", marker = "extra == 'all'", specifier = ">=1.27.0" }, { name = "opentelemetry-proto", marker = "extra == 'all'", specifier = ">=1.28.2" }, + { name = "opentelemetry-proto", marker = "extra == 'all'", specifier = ">=1.42.1" }, { name = "opentelemetry-proto", marker = "extra == 'core-service'", specifier = ">=1.28.2" }, { name = "opentelemetry-proto", marker = "extra == 'files-service'", specifier = ">=1.28.2" }, { name = "opentelemetry-proto", marker = "extra == 'intake-service'", specifier = ">=1.27.0" }, + { name = "opentelemetry-proto", marker = "extra == 'nemo-experimentalist-plugin'", specifier = ">=1.42.1" }, + { name = "opentelemetry-proto", marker = "extra == 'plugins'", specifier = ">=1.42.1" }, { name = "opentelemetry-proto", marker = "extra == 'services'", specifier = ">=1.27.0" }, { name = "opentelemetry-proto", marker = "extra == 'services'", specifier = ">=1.28.2" }, + { name = "opentelemetry-proto", marker = "extra == 'services'", specifier = ">=1.42.1" }, { name = "opentelemetry-sdk", marker = "extra == 'all'", specifier = ">=1.27.0,<2.0.0" }, + { name = "opentelemetry-sdk", marker = "extra == 'all'", specifier = ">=1.42.1" }, { name = "opentelemetry-sdk", marker = "extra == 'guardrails-service'", specifier = ">=1.27.0,<2.0.0" }, + { name = "opentelemetry-sdk", marker = "extra == 'nemo-insights-plugin'", specifier = ">=1.42.1" }, { name = "opentelemetry-sdk", marker = "extra == 'nmp-common'", specifier = ">=1.38.0" }, + { name = "opentelemetry-sdk", marker = "extra == 'plugins'", specifier = ">=1.42.1" }, { name = "opentelemetry-sdk", marker = "extra == 'services'", specifier = ">=1.27.0,<2.0.0" }, + { name = "opentelemetry-sdk", marker = "extra == 'services'", specifier = ">=1.42.1" }, { name = "optuna", marker = "extra == 'all'", specifier = ">=4.0.0" }, { name = "optuna", marker = "extra == 'nemo-optimization-plugin'", specifier = ">=4.0.0" }, { name = "optuna", marker = "extra == 'plugins'", specifier = ">=4.0.0" }, @@ -5813,6 +5928,10 @@ requires-dist = [ { name = "prometheus-client", marker = "extra == 'nmp-common'", specifier = ">=0.23.0" }, { name = "prometheus-fastapi-instrumentator", marker = "extra == 'nmp-common'", specifier = ">=8.0.2" }, { name = "prompt-toolkit", marker = "extra == 'nemo-platform-sdk'", specifier = ">=3.0.0" }, + { name = "protobuf", marker = "extra == 'all'", specifier = ">=6.0.0" }, + { name = "protobuf", marker = "extra == 'nemo-experimentalist-plugin'", specifier = ">=6.0.0" }, + { name = "protobuf", marker = "extra == 'plugins'", specifier = ">=6.0.0" }, + { name = "protobuf", marker = "extra == 'services'", specifier = ">=6.0.0" }, { name = "psutil", marker = "extra == 'nemo-platform-sdk'", specifier = ">=5.9.0" }, { name = "psycopg2-binary", marker = "extra == 'all'", specifier = ">=2.9.10" }, { name = "psycopg2-binary", marker = "extra == 'core-service'", specifier = ">=2.9.10" }, @@ -5836,12 +5955,16 @@ requires-dist = [ { name = "pydantic", marker = "extra == 'jobs-service'", specifier = ">=2.10.6" }, { name = "pydantic", marker = "extra == 'models-service'", specifier = ">=2.10.6" }, { name = "pydantic", marker = "extra == 'nemo-auditor-plugin'", specifier = ">=2.10.6" }, + { name = "pydantic", marker = "extra == 'nemo-eval-author-plugin'", specifier = ">=2" }, { name = "pydantic", marker = "extra == 'nemo-evaluator-plugin'", specifier = ">=2.12.0" }, { name = "pydantic", marker = "extra == 'nemo-evaluator-sdk'", specifier = ">=2.10.6" }, + { name = "pydantic", marker = "extra == 'nemo-experimentalist-plugin'", specifier = ">=2" }, + { name = "pydantic", marker = "extra == 'nemo-insights-plugin'", specifier = ">=2.12.0" }, { name = "pydantic", marker = "extra == 'nemo-optimization-plugin'", specifier = ">=2.10.6" }, { name = "pydantic", marker = "extra == 'nemo-platform-plugin'", specifier = ">=2.12.0" }, { name = "pydantic", marker = "extra == 'nemo-platform-sdk'", specifier = ">=2.0.0,<3" }, { name = "pydantic", marker = "extra == 'nmp-common'", specifier = ">=2.10.3" }, + { name = "pydantic", marker = "extra == 'plugins'", specifier = ">=2" }, { name = "pydantic", marker = "extra == 'plugins'", specifier = ">=2.10.6" }, { name = "pydantic", marker = "extra == 'plugins'", specifier = ">=2.12.0" }, { name = "pydantic", marker = "extra == 'services'", specifier = ">=2.0.0" }, @@ -5891,6 +6014,7 @@ requires-dist = [ { name = "python-multipart", marker = "extra == 'services'", specifier = "~=0.0.9" }, { name = "pyyaml", marker = "extra == 'all'", specifier = ">=6.0.0" }, { name = "pyyaml", marker = "extra == 'all'", specifier = ">=6.0.2" }, + { name = "pyyaml", marker = "extra == 'all'", specifier = ">=6.0.3" }, { name = "pyyaml", marker = "extra == 'auditor-service'", specifier = ">=6.0.2" }, { name = "pyyaml", marker = "extra == 'auth-service'", specifier = ">=6.0.0" }, { name = "pyyaml", marker = "extra == 'core-service'", specifier = ">=6.0.0" }, @@ -5902,14 +6026,19 @@ requires-dist = [ { name = "pyyaml", marker = "extra == 'nemo-agents-plugin'", specifier = ">=6.0" }, { name = "pyyaml", marker = "extra == 'nemo-anonymizer-plugin'", specifier = ">=6.0.2" }, { name = "pyyaml", marker = "extra == 'nemo-auditor-plugin'", specifier = ">=6.0.2" }, + { name = "pyyaml", marker = "extra == 'nemo-eval-author-plugin'", specifier = ">=6.0.3" }, + { name = "pyyaml", marker = "extra == 'nemo-experimentalist-plugin'", specifier = ">=6.0.3" }, + { name = "pyyaml", marker = "extra == 'nemo-insights-plugin'", specifier = ">=6.0.3" }, { name = "pyyaml", marker = "extra == 'nemo-optimization-plugin'", specifier = ">=6.0" }, { name = "pyyaml", marker = "extra == 'nemo-platform-plugin'", specifier = ">=6.0.2" }, { name = "pyyaml", marker = "extra == 'nemo-platform-sdk'", specifier = ">=6.0.0" }, { name = "pyyaml", marker = "extra == 'nmp-common'", specifier = ">=6.0.2" }, { name = "pyyaml", marker = "extra == 'plugins'", specifier = ">=6.0" }, { name = "pyyaml", marker = "extra == 'plugins'", specifier = ">=6.0.2" }, + { name = "pyyaml", marker = "extra == 'plugins'", specifier = ">=6.0.3" }, { name = "pyyaml", marker = "extra == 'services'", specifier = ">=6.0.0" }, { name = "pyyaml", marker = "extra == 'services'", specifier = ">=6.0.2" }, + { name = "pyyaml", marker = "extra == 'services'", specifier = ">=6.0.3" }, { name = "ragas", marker = "extra == 'nemo-evaluator-sdk'", specifier = "==0.4.3" }, { name = "requests", marker = "extra == 'all'", specifier = ">=2.31.0" }, { name = "requests", marker = "extra == 'auditor-service'", specifier = ">=2.32.3,<3.0.0" }, @@ -5951,11 +6080,17 @@ requires-dist = [ { name = "tenacity", marker = "extra == 'core-service'", specifier = ">=8.5.0" }, { name = "tenacity", marker = "extra == 'models-service'", specifier = ">=8.5.0" }, { name = "tenacity", marker = "extra == 'services'", specifier = ">=8.5.0" }, + { name = "tomlkit", marker = "extra == 'all'", specifier = ">=0.13.3" }, + { name = "tomlkit", marker = "extra == 'nemo-eval-author-plugin'", specifier = ">=0.13.3" }, + { name = "tomlkit", marker = "extra == 'nemo-experimentalist-plugin'", specifier = ">=0.13.3" }, + { name = "tomlkit", marker = "extra == 'plugins'", specifier = ">=0.13.3" }, + { name = "tomlkit", marker = "extra == 'services'", specifier = ">=0.13.3" }, { name = "typer", marker = "extra == 'all'", specifier = ">=0.9.0" }, { name = "typer", marker = "extra == 'all'", specifier = ">=0.12.5" }, { name = "typer", marker = "extra == 'all'", specifier = ">=0.20.0" }, { name = "typer", marker = "extra == 'nemo-auditor-plugin'", specifier = ">=0.20.0" }, { name = "typer", marker = "extra == 'nemo-evaluator-plugin'", specifier = ">=0.20.0" }, + { name = "typer", marker = "extra == 'nemo-insights-plugin'", specifier = ">=0.20.0" }, { name = "typer", marker = "extra == 'nemo-optimization-plugin'", specifier = ">=0.12.5" }, { name = "typer", marker = "extra == 'nemo-platform-plugin'", specifier = ">=0.20.0,<0.26" }, { name = "typer", marker = "extra == 'nemo-platform-sdk'", specifier = ">=0.20.0" }, @@ -5971,6 +6106,10 @@ requires-dist = [ { name = "types-aioboto3", extras = ["s3"], marker = "extra == 'files-service'", specifier = ">=15.5.0" }, { name = "types-aioboto3", extras = ["s3"], marker = "extra == 'services'", specifier = ">=15.5.0" }, { name = "typing-extensions", marker = "extra == 'nemo-platform-sdk'", specifier = ">=4.14,<5" }, + { name = "tzdata", marker = "extra == 'all'", specifier = "==2026.2" }, + { name = "tzdata", marker = "extra == 'nemo-insights-plugin'", specifier = "==2026.2" }, + { name = "tzdata", marker = "extra == 'plugins'", specifier = "==2026.2" }, + { name = "tzdata", marker = "extra == 'services'", specifier = "==2026.2" }, { name = "urllib3", marker = "extra == 'all'", specifier = ">=2.7.0" }, { name = "urllib3", marker = "extra == 'core-service'", specifier = ">=2.7.0" }, { name = "urllib3", marker = "extra == 'models-service'", specifier = ">=2.7.0" }, @@ -6010,7 +6149,7 @@ requires-dist = [ { name = "yara-python", marker = "extra == 'guardrails-service'", specifier = "==4.5.1" }, { name = "yara-python", marker = "extra == 'services'", specifier = "==4.5.1" }, ] -provides-extras = ["aiohttp", "all", "auditor-service", "auth-service", "core-service", "data-designer-nemo", "entities-service", "files-service", "guardrails-service", "hello-world-service", "inference-gateway-service", "intake-service", "jobs-service", "models-service", "nemo-agents-example-calculator", "nemo-agents-plugin", "nemo-anonymizer-plugin", "nemo-auditor-plugin", "nemo-data-designer-plugin", "nemo-evaluator-plugin", "nemo-evaluator-sdk", "nemo-guardrails-plugin", "nemo-optimization-plugin", "nemo-platform-plugin", "nemo-platform-sdk", "nemo-safe-synthesizer-plugin", "nemo-switchyard", "nmp-common", "platform-seed-service", "plugins", "secrets-service", "services", "studio-service", "switchyard-vendored"] +provides-extras = ["aiohttp", "all", "auditor-service", "auth-service", "core-service", "data-designer-nemo", "entities-service", "files-service", "guardrails-service", "hello-world-service", "inference-gateway-service", "intake-service", "jobs-service", "models-service", "nemo-agents-example-calculator", "nemo-agents-plugin", "nemo-anonymizer-plugin", "nemo-auditor-plugin", "nemo-data-designer-plugin", "nemo-eval-author-plugin", "nemo-evaluator-plugin", "nemo-evaluator-sdk", "nemo-experimentalist-plugin", "nemo-guardrails-plugin", "nemo-insights-plugin", "nemo-optimization-plugin", "nemo-platform-plugin", "nemo-platform-sdk", "nemo-safe-synthesizer-plugin", "nemo-switchyard", "nmp-common", "platform-seed-service", "plugins", "secrets-service", "services", "studio-service", "switchyard-vendored"] [[package]] name = "nemo-platform-ext" From 9227a678481a66f87b744b95c18dc1c160355aa3 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 18 Aug 2026 16:43:10 +0000 Subject: [PATCH 4/7] test(experimentalist): allow the wrapper to co-advertise the skills entry point Bundling the plugin into `nemo-platform` means a source checkout has two distributions advertising `experimentalist` in `nemo.skills`: the editable plugin and the wrapper. Every other bundled plugin -- agents, anonymizer, auditor, data-designer, evaluator, guardrails, safe-synthesizer -- has had two entries all along, so the old `len(eps) == 1` assertion was really asserting "not bundled yet" rather than anything about the skills contract. Assert what matters instead: at least one provider, all providers naming the same target, and that target loading to a callable whose directory holds the skills. That absorbs the `terminator` check from the sibling test, which was covering the same ground through a direct import. Signed-off-by: Cursor Agent Co-authored-by: Aditya Pandey --- .../tests/test_skills_entry_point.py | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/plugins/nemo-experimentalist/tests/test_skills_entry_point.py b/plugins/nemo-experimentalist/tests/test_skills_entry_point.py index 0483d97b06..b49a7cd296 100644 --- a/plugins/nemo-experimentalist/tests/test_skills_entry_point.py +++ b/plugins/nemo-experimentalist/tests/test_skills_entry_point.py @@ -5,26 +5,26 @@ from __future__ import annotations +from importlib.metadata import entry_points from pathlib import Path -def test_skills_dir_contains_terminator() -> None: - from nemo_experimentalist_plugin.skills import skills_dir - - terminator = skills_dir() / "terminator" - assert terminator.is_dir(), ( - f"Expected 'terminator' subdir under {skills_dir()!r} — got {list(skills_dir().iterdir())}" - ) +def test_entry_point_resolves_to_the_skills_dir() -> None: + """The nemo.skills entry-point must resolve to a skills_dir holding our skills. + In a source checkout two distributions advertise this name -- the plugin itself + and the `nemo-platform` wrapper that bundles it -- so the guarantee is that every + provider agrees on one target, not that only one provider exists. + """ + eps = [ep for ep in entry_points(group="nemo.skills") if ep.name == "experimentalist"] + assert eps, "no 'experimentalist' entry-point in the nemo.skills group" + assert len({ep.value for ep in eps}) == 1, f"providers disagree on the target: {eps}" -def test_entry_point_loads_skills_dir() -> None: - """The nemo.skills entry-point must resolve to our skills_dir function.""" - from importlib.metadata import entry_points + skills_dir = eps[0].load() + assert callable(skills_dir), f"entry-point did not resolve to a callable: {skills_dir!r}" - eps = [ep for ep in entry_points(group="nemo.skills") if ep.name == "experimentalist"] - assert len(eps) == 1, f"Expected exactly one 'experimentalist' entry-point, got {eps}" - loaded = eps[0].load() - assert callable(loaded), f"Entry-point did not resolve to a callable: {loaded!r}" - result = loaded() - assert isinstance(result, Path), f"skills_dir() returned {result!r} (not Path)" - assert result.is_dir(), f"skills_dir() returned {result!r} which is not a directory" + resolved = skills_dir() + assert isinstance(resolved, Path), f"skills_dir() returned {resolved!r} (not Path)" + assert (resolved / "terminator").is_dir(), ( + f"expected a 'terminator' subdir under {resolved!r} -- got {list(resolved.iterdir())}" + ) From 52217472ddc840f086673f2a243739d19db606b1 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 18 Aug 2026 20:05:30 +0000 Subject: [PATCH 5/7] chore: drop the nooa import-surface checker It was scaffolding for the 0.0.9 migration and has already served that purpose. Nothing runs it: no CI job, no pre-commit hook, no Makefile target. The three plugin suites import these modules for real, so a nooa release that drops or renames a symbol fails there anyway, and fails on behaviour changes this script could never see. Signed-off-by: Cursor Agent Co-authored-by: Aditya Pandey --- tools/check_nooa_import_surface.py | 97 ------------------------------ 1 file changed, 97 deletions(-) delete mode 100644 tools/check_nooa_import_surface.py diff --git a/tools/check_nooa_import_surface.py b/tools/check_nooa_import_surface.py deleted file mode 100644 index 29f2006580..0000000000 --- a/tools/check_nooa_import_surface.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python3 -# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -"""Check that the installed `nooa` provides every symbol the plugins import. - -`nooa` is a pre-1.0 dependency that moved from a git pin to a PyPI floor, so a -resolver is free to pick up a release that dropped or renamed something the -plugins reach for. Import errors from that surface only appear when the specific -module is first imported, which for agent components can be deep into a run. -This walks the imports statically instead and reports the whole gap at once. - - uv run python tools/check_nooa_import_surface.py - -Exits non-zero when something is missing. This checks names, not behaviour -- -a symbol that kept its name but changed semantics still needs the test suites. -""" - -import argparse -import ast -import importlib -import pathlib -import sys - -PLUGIN_SOURCE_ROOTS = ( - "plugins/nemo-insights/src", - "plugins/nemo-experimentalist/src", - "plugins/nemo-eval-author/src", -) - - -def collect_imports(roots: tuple[str, ...], repo_root: pathlib.Path) -> dict[str, set[str]]: - """Map each imported `nooa` module to the set of names taken from it.""" - imported: dict[str, set[str]] = {} - for root in roots: - for path in sorted((repo_root / root).rglob("*.py")): - try: - tree = ast.parse(path.read_text(encoding="utf-8")) - except SyntaxError as exc: - print(f"warning: skipping {path} ({exc})", file=sys.stderr) - continue - for node in ast.walk(tree): - if isinstance(node, ast.ImportFrom): - if node.level == 0 and node.module and node.module.split(".")[0] == "nooa": - imported.setdefault(node.module, set()).update(alias.name for alias in node.names) - elif isinstance(node, ast.Import): - for alias in node.names: - if alias.name.split(".")[0] == "nooa": - imported.setdefault(alias.name, set()) - return imported - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument( - "--repo-root", - type=pathlib.Path, - default=pathlib.Path(__file__).resolve().parent.parent, - help="Repository root (defaults to the parent of tools/).", - ) - args = parser.parse_args() - - try: - nooa = importlib.import_module("nooa") - except ImportError as exc: - print(f"FAIL: cannot import nooa: {exc}") - print("Install the workspace first: uv sync --all-packages") - return 1 - - version = getattr(nooa, "__version__", "unknown") - imported = collect_imports(PLUGIN_SOURCE_ROOTS, args.repo_root) - print(f"installed nooa: {version}") - print(f"checking {sum(len(v) for v in imported.values())} names across {len(imported)} modules") - - missing: list[str] = [] - for module_name in sorted(imported): - try: - module = importlib.import_module(module_name) - except ImportError as exc: - missing.append(f"{module_name} (module missing: {exc})") - continue - for symbol in sorted(imported[module_name]): - if symbol != "*" and not hasattr(module, symbol): - missing.append(f"{module_name}.{symbol}") - - if missing: - print(f"\nFAIL: {len(missing)} missing:") - for item in missing: - print(f" - {item}") - return 1 - - print("\nOK: every imported nooa name resolves.") - return 0 - - -if __name__ == "__main__": - sys.exit(main()) From e8efb557cf79b5f89091e57cc1617052b5732b4b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 18 Aug 2026 20:14:54 +0000 Subject: [PATCH 6/7] fix(experimentalist): pin the smoke-agent image to one nooa release The line this replaced installed nooa from an immutable commit SHA, and swapping it for `>=0.0.9` quietly gave up reproducibility in the one place that cannot afford it. This image's tag is `sha256(Dockerfile, records.json)`, so a range lets the installed nooa drift while the tag stays fixed -- the "container quietly running against stale data" that build_image.py says the content-addressed tag exists to prevent. An exact pin restores the coupling: bumping nooa changes the Dockerfile bytes, so the tag moves with it. It also matches the repo's only other Dockerfile dependency, `nvidia-nat[most]==...`. The guard test compared the image's specifier string against the plugin's, which forbids exactly this pin. It now checks the two properties that matter -- the image names one `==` version, and the plugin's range accepts it -- via `packaging` rather than regex, so extras and whitespace are the parser's problem. Both failure modes were confirmed to fail loudly. Hash-checked installs were considered and skipped. That needs nooa's whole transitive closure pinned in an image-local artifact, regenerated on every floor bump, to protect a fixture that is never published and whose tests skip by default. Signed-off-by: Cursor Agent Co-authored-by: Aditya Pandey --- .../smoke-agent/dataset/_shared/Dockerfile | 4 +- .../dataset/task-template/task.toml | 2 +- .../test_smoke_agent_assets.py | 51 +++++++++++++------ 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/plugins/nemo-experimentalist/examples/smoke-agent/dataset/_shared/Dockerfile b/plugins/nemo-experimentalist/examples/smoke-agent/dataset/_shared/Dockerfile index 1e13fb9309..89093d8a21 100644 --- a/plugins/nemo-experimentalist/examples/smoke-agent/dataset/_shared/Dockerfile +++ b/plugins/nemo-experimentalist/examples/smoke-agent/dataset/_shared/Dockerfile @@ -17,9 +17,9 @@ RUN apt-get update \ COPY --from=ghcr.io/astral-sh/uv:0.9.14 /uv /bin/uv # `uv pip install --system` rather than `uv sync`: there is no project here, just -# one dependency going into the image's own interpreter. +# one pinned dependency going into the image's own interpreter. RUN uv pip install --system --no-cache \ - "nooa[tracing]>=0.0.9" + "nooa[tracing]==0.0.9" WORKDIR /app RUN groupadd --gid 10001 smoke-agent \ diff --git a/plugins/nemo-experimentalist/examples/smoke-agent/dataset/task-template/task.toml b/plugins/nemo-experimentalist/examples/smoke-agent/dataset/task-template/task.toml index e01e424ff2..fb0ea6d8e8 100644 --- a/plugins/nemo-experimentalist/examples/smoke-agent/dataset/task-template/task.toml +++ b/plugins/nemo-experimentalist/examples/smoke-agent/dataset/task-template/task.toml @@ -23,6 +23,6 @@ timeout_sec = 60.0 [environment] # Set by scripts/build_image.py; a test asserts it matches the current content # hash of the Dockerfile and records file. Tasks ship no environment/ directory. -docker_image = "smoke-agent-env:sha-280bb8c6026b" +docker_image = "smoke-agent-env:sha-effb361c1cea" cpus = 1 memory_mb = 1024 diff --git a/plugins/nemo-experimentalist/tests/experimentalist/test_smoke_agent_assets.py b/plugins/nemo-experimentalist/tests/experimentalist/test_smoke_agent_assets.py index c77c098327..3579a8607e 100644 --- a/plugins/nemo-experimentalist/tests/experimentalist/test_smoke_agent_assets.py +++ b/plugins/nemo-experimentalist/tests/experimentalist/test_smoke_agent_assets.py @@ -17,25 +17,38 @@ import shutil import sys import tomllib +from collections.abc import Iterable from pathlib import Path from typing import Any +from packaging.requirements import InvalidRequirement, Requirement +from packaging.specifiers import SpecifierSet +from packaging.utils import canonicalize_name + _REPO_ROOT = Path(__file__).resolve().parents[4] _EXAMPLE_DIR = Path(__file__).resolve().parents[2] / "examples" / "smoke-agent" _SHARED = _EXAMPLE_DIR / "dataset" / "_shared" _HASHED = ("Dockerfile", "records.json") -_RENDERED_TASK_TREE_SHA256 = "246b50d218d80fec7b030f93347cebe2f9b2563bb4d4d71103cf5f282e80d41a" +_RENDERED_TASK_TREE_SHA256 = "f46c78735a97e31185ce9b17250c9d97389cd8e8068590e2a658e54db4e95308" + +def _nooa_requirement(candidates: Iterable[str]) -> Requirement: + """Return the nooa requirement among *candidates*, skipping anything unparseable.""" + for candidate in candidates: + try: + requirement = Requirement(candidate) + except InvalidRequirement: + continue + if canonicalize_name(requirement.name) == "nooa": + return requirement + raise AssertionError("no nooa requirement found") -def _plugin_nooa_specifier() -> str: - """Return the version specifier the plugin declares for nooa, e.g. ">=0.0.9".""" + +def _plugin_nooa_specifier() -> SpecifierSet: + """Return the nooa version range the plugin declares for itself.""" plugin_pyproject = Path(__file__).resolve().parents[2] / "pyproject.toml" data = tomllib.loads(plugin_pyproject.read_text(encoding="utf-8")) - for dep in data["project"]["dependencies"]: - found = re.fullmatch(r"nooa(?:\[[^\]]*\])?\s*(?P.+)", dep.strip()) - if found: - return found.group("spec").strip() - raise AssertionError("the plugin must declare a versioned nooa dependency") + return _nooa_requirement(data["project"]["dependencies"]).specifier def _expected_tag() -> str: @@ -186,18 +199,26 @@ def test_verifier_does_not_echo_answers() -> None: assert forbidden not in code, f"{forbidden} publishes ground truth to the trial log" -def test_dockerfile_nooa_version_matches_the_plugin() -> None: - """Check that the task image resolves the same NOOA range as the plugin. +def test_dockerfile_pins_one_nooa_the_plugin_accepts() -> None: + """Check that the task image pins a single NOOA release from the plugin's range. - The agent under test runs inside this image, so a floor that drifts from the - plugin's own lets the two pick up different NOOA releases. + The tag is a hash of this Dockerfile, so a version range would let the installed + NOOA drift while the tag stayed put -- exactly the stale-content case the + content-addressed tag exists to catch. The pin also has to satisfy the plugin's + own range, or the agent under test runs against a different framework build. """ dockerfile_path = _SHARED / "Dockerfile" if not dockerfile_path.is_file(): return # Task 4 creates it. - found = re.search(r"nooa\[[^\]]*\]\s*(?P[<>=!~][^\"']+)", dockerfile_path.read_text(encoding="utf-8")) - assert found is not None, "Dockerfile must constrain NOOA to a version range" - assert found.group("spec").strip() == _plugin_nooa_specifier() + # Requirements reach `uv pip install` as double-quoted arguments. + quoted = dockerfile_path.read_text(encoding="utf-8").split('"')[1::2] + pins = [spec for spec in _nooa_requirement(quoted).specifier if spec.operator == "=="] + + assert len(pins) == 1, f"Dockerfile must pin NOOA to one exact version, got {pins}" + plugin_range = _plugin_nooa_specifier() + assert pins[0].version in plugin_range, ( + f"image pins nooa=={pins[0].version}, which the plugin's {plugin_range} rejects" + ) def test_task_image_runs_as_a_non_root_user() -> None: From b3ef7119ecf537cc1927691b9874c45758040328 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 18 Aug 2026 20:15:30 +0000 Subject: [PATCH 7/7] docs: the smoke-agent test module pins nooa again, not a range Signed-off-by: Cursor Agent Co-authored-by: Aditya Pandey --- .../tests/experimentalist/test_smoke_agent_assets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/nemo-experimentalist/tests/experimentalist/test_smoke_agent_assets.py b/plugins/nemo-experimentalist/tests/experimentalist/test_smoke_agent_assets.py index 3579a8607e..b4e31bebbb 100644 --- a/plugins/nemo-experimentalist/tests/experimentalist/test_smoke_agent_assets.py +++ b/plugins/nemo-experimentalist/tests/experimentalist/test_smoke_agent_assets.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -"""Keep the smoke agent's task image, its NOOA version range, and its verifier honest. +"""Keep the smoke agent's task image, its NOOA pin, and its verifier honest. No Docker here on purpose: the image tag is a content hash, so a forgotten rebuild is a string comparison rather than something only a container run can