from PIL import Image from pathlib import Path from nexus_visual_weaver.provider_runtime import ( NEMOTRON_NANO_REPO_ID, NEMOTRON_PARSE_REPO_ID, OPENBMB_REPO_ID, ProviderJudgeResult, _extract_content, _image_data_url, _post_json, _safe_json_from_text, _safe_provider_payload, _short_error, judge_with_minicpm, judge_with_nemotron, ) RUNTIME_FIXTURE_DIR = Path("tests/fixtures/runtime") def _runtime_fixture_path(name: str) -> Path: RUNTIME_FIXTURE_DIR.mkdir(parents=True, exist_ok=True) return RUNTIME_FIXTURE_DIR / name def test_minicpm_reports_missing_secret(monkeypatch) -> None: monkeypatch.delenv("MINICPM_BASE_URL", raising=False) monkeypatch.delenv("MINICPM_API_KEY", raising=False) monkeypatch.delenv("OPENBMB_API_KEY", raising=False) result = judge_with_minicpm( prompt="gothic couture", image_path=None, scan={"export_gate": "pending"}, wardrobe_summary="boots and lace", ) assert result.status == "missing_secret" assert result.provider_state == "missing secret" assert result.repo_id == "openbmb/MiniCPM-V-4.6" def test_minicpm_blocks_when_artifact_missing(monkeypatch) -> None: monkeypatch.setenv("MINICPM_BASE_URL", "http://127.0.0.1:9") monkeypatch.setenv("MINICPM_API_KEY", "test-token") result = judge_with_minicpm( prompt="gothic couture", image_path="missing.png", scan={"export_gate": "clear"}, wardrobe_summary="boots and lace", ) assert result.status == "no_artifact" assert result.provider_state == "blocked" def test_minicpm_success_with_mocked_post(monkeypatch) -> None: image = _runtime_fixture_path("test-provider-artifact.png") Image.new("RGB", (8, 8), color=(12, 16, 20)).save(image) monkeypatch.setenv("MINICPM_BASE_URL", "http://example.test") monkeypatch.setenv("MINICPM_API_KEY", "test-token") def fake_post(url, token, payload, timeout): assert url == "http://example.test/v1/chat/completions" assert token == "test-token" assert payload["messages"][0]["content"][1]["image_url"]["url"].startswith("data:image/png;base64,") return {"choices": [{"message": {"content": '{"overall_status":"pass","footwear_check":"visible"}'}}]} monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post) try: result = judge_with_minicpm( prompt="gothic couture", image_path=str(image), scan={"export_gate": "clear"}, wardrobe_summary="boots and lace", ) finally: image.unlink(missing_ok=True) assert result.status == "success" assert result.evidence["overall_status"] == "pass" def test_nemotron_reports_missing_secret(monkeypatch) -> None: monkeypatch.delenv("NEMOTRON_BASE_URL", raising=False) monkeypatch.delenv("NEMOTRON_API_KEY", raising=False) monkeypatch.delenv("NVIDIA_API_KEY", raising=False) result = judge_with_nemotron(prompt="brief", run_packet={"id": "nw-test"}) assert result.status == "missing_secret" assert result.provider == "NVIDIA" assert "Nemotron" in result.message # --- _short_error tests --- def test_short_error_prefixes_class_name() -> None: exc = ValueError("something went wrong") result = _short_error(exc) assert result.startswith("ValueError:") assert "something went wrong" in result def test_short_error_truncates_long_messages() -> None: long_message = "x" * 500 exc = RuntimeError(long_message) result = _short_error(exc) assert len(result) <= len("RuntimeError: ") + 360 assert result.endswith("...") def test_short_error_collapses_newlines() -> None: exc = OSError("line one\nline two\nline three") result = _short_error(exc) assert "\n" not in result assert "line one" in result # --- _image_data_url tests --- def test_image_data_url_returns_none_for_none_path() -> None: assert _image_data_url(None) is None def test_image_data_url_returns_none_for_missing_file() -> None: assert _image_data_url("/nonexistent/path/to/image.png") is None def test_image_data_url_encodes_png_as_base64() -> None: image_path = _runtime_fixture_path("test-img-data-url.png") Image.new("RGB", (4, 4), color=(0, 0, 0)).save(image_path) try: result = _image_data_url(str(image_path)) finally: image_path.unlink(missing_ok=True) assert result is not None assert result.startswith("data:image/png;base64,") def test_image_data_url_uses_jpeg_mime_for_jpg() -> None: image_path = _runtime_fixture_path("test-img-data-url.jpg") Image.new("RGB", (4, 4), color=(0, 0, 0)).save(image_path) try: result = _image_data_url(str(image_path)) finally: image_path.unlink(missing_ok=True) assert result is not None assert result.startswith("data:image/jpeg;base64,") def test_image_data_url_rejects_unknown_suffix() -> None: image_path = _runtime_fixture_path("not-an-image.txt") image_path.write_text("not an image", encoding="utf-8") try: assert _image_data_url(str(image_path)) is None finally: image_path.unlink(missing_ok=True) def test_image_data_url_rejects_oversized_file(monkeypatch) -> None: image_path = _runtime_fixture_path("large.png") image_path.write_bytes(b"not actually decoded because size fails") monkeypatch.setattr("nexus_visual_weaver.provider_runtime.MAX_PROVIDER_IMAGE_BYTES", 4) try: assert _image_data_url(str(image_path)) is None finally: image_path.unlink(missing_ok=True) # --- _extract_content tests --- def test_extract_content_returns_string_from_choices() -> None: response = {"choices": [{"message": {"content": "hello world"}}]} assert _extract_content(response) == "hello world" def test_extract_content_returns_empty_for_no_choices() -> None: assert _extract_content({"choices": []}) == "" assert _extract_content({}) == "" def test_extract_content_serializes_non_string_content() -> None: response = {"choices": [{"message": {"content": {"key": "value"}}}]} result = _extract_content(response) assert "key" in result assert "value" in result # --- _safe_json_from_text tests --- def test_safe_json_from_text_parses_valid_json() -> None: text = '{"status": "pass", "score": 0.9}' result = _safe_json_from_text(text) assert result == {"status": "pass", "score": 0.9} def test_safe_json_from_text_returns_empty_dict_for_empty_string() -> None: assert _safe_json_from_text("") == {} assert _safe_json_from_text(" ") == {} def test_safe_json_from_text_falls_back_on_invalid_json() -> None: text = "this is not valid json" result = _safe_json_from_text(text) assert "raw_summary" in result assert "this is not valid json" in result["raw_summary"] def test_safe_json_from_text_extracts_embedded_json() -> None: text = 'Some prefix text {"result": "ok"} trailing text' result = _safe_json_from_text(text) assert result == {"result": "ok"} def test_safe_json_from_text_truncates_fallback_to_1200_chars() -> None: long_text = "not json " + "x" * 2000 result = _safe_json_from_text(long_text) assert "raw_summary" in result assert len(result["raw_summary"]) <= 1200 # --- ProviderJudgeResult.to_dict tests --- def test_provider_judge_result_to_dict_contains_all_fields() -> None: result = ProviderJudgeResult( status="success", provider_state="configured", provider="OpenBMB", repo_id=OPENBMB_REPO_ID, model="MiniCPM-V-4.6", message="judge returned evidence", evidence={"overall_status": "pass"}, latency_seconds=1.23, ) d = result.to_dict() assert d["status"] == "success" assert d["provider_state"] == "configured" assert d["provider"] == "OpenBMB" assert d["repo_id"] == OPENBMB_REPO_ID assert d["model"] == "MiniCPM-V-4.6" assert d["latency_seconds"] == 1.23 assert d["evidence"]["overall_status"] == "pass" # --- nemotron success/failure tests --- def test_nemotron_success_with_mocked_post(monkeypatch) -> None: monkeypatch.setenv("NEMOTRON_BASE_URL", "http://nemotron.test") monkeypatch.setenv("NEMOTRON_API_KEY", "nvidia-token") def fake_post(url, token, payload, timeout): assert "Nemotron" in payload["model"] or "nemotron" in payload["model"] return {"choices": [{"message": {"content": '{"final_claim_status":"pass","structured_parse":"ok"}'}}]} monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post) result = judge_with_nemotron( prompt="gothic couture brief", run_packet={"checkpoint": {"checkpoint_id": "nw-test-123"}}, minicpm_result={"status": "success"}, ) assert result.status == "success" assert result.provider == "NVIDIA" assert result.evidence["final_claim_status"] == "pass" assert result.latency_seconds is not None def test_nemotron_failed_api_call_returns_failed_status(monkeypatch) -> None: import urllib.error monkeypatch.setenv("NEMOTRON_BASE_URL", "http://nemotron.test") monkeypatch.setenv("NEMOTRON_API_KEY", "nvidia-token") def fake_post(url, token, payload, timeout): raise urllib.error.URLError("connection refused") monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post) result = judge_with_nemotron( prompt="brief", run_packet={"id": "nw-fail"}, ) assert result.status == "failed" assert result.provider_state == "failed" assert "URLError" in result.message or "connection" in result.message.lower() assert result.evidence.get("configured") is True def test_minicpm_failed_api_call_returns_failed_status(monkeypatch) -> None: import urllib.error image_path = _runtime_fixture_path("test-minicpm-fail.png") Image.new("RGB", (4, 4), color=(0, 0, 0)).save(image_path) monkeypatch.setenv("MINICPM_BASE_URL", "http://minicpm.test") monkeypatch.setenv("MINICPM_API_KEY", "test-token") def fake_post(url, token, payload, timeout): raise urllib.error.URLError("network unreachable") monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post) try: result = judge_with_minicpm( prompt="gothic couture", image_path=str(image_path), scan={"export_gate": "clear"}, wardrobe_summary="platform boots", ) finally: image_path.unlink(missing_ok=True) assert result.status == "failed" assert result.provider_state == "failed" assert result.provider == "OpenBMB" assert result.evidence.get("configured") is True def test_nemotron_uses_parse_repo_id_for_parse_model(monkeypatch) -> None: monkeypatch.setenv("NEMOTRON_BASE_URL", "http://nemotron.test") monkeypatch.setenv("NEMOTRON_API_KEY", "nvidia-token") monkeypatch.setenv("NEMOTRON_MODEL", "nvidia/NVIDIA-Nemotron-Parse-v1.2") def fake_post(url, token, payload, timeout): return {"choices": [{"message": {"content": "{}"}}]} monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post) result = judge_with_nemotron(prompt="brief", run_packet={}) assert result.repo_id == NEMOTRON_PARSE_REPO_ID def test_nemotron_uses_nano_repo_id_for_non_parse_model(monkeypatch) -> None: monkeypatch.setenv("NEMOTRON_BASE_URL", "http://nemotron.test") monkeypatch.setenv("NEMOTRON_API_KEY", "nvidia-token") monkeypatch.setenv("NEMOTRON_MODEL", "nvidia/NVIDIA-Nemotron-3-Nano-4B-GGUF") def fake_post(url, token, payload, timeout): return {"choices": [{"message": {"content": "{}"}}]} monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post) result = judge_with_nemotron(prompt="brief", run_packet={}) assert result.repo_id == NEMOTRON_NANO_REPO_ID def test_minicpm_uses_openbmb_api_key_as_fallback(monkeypatch) -> None: monkeypatch.setenv("MINICPM_BASE_URL", "http://minicpm.test") monkeypatch.delenv("MINICPM_API_KEY", raising=False) monkeypatch.setenv("OPENBMB_API_KEY", "openbmb-fallback-token") image_path = _runtime_fixture_path("test-openbmb-key.png") Image.new("RGB", (4, 4), color=(0, 0, 0)).save(image_path) captured = {} def fake_post(url, token, payload, timeout): captured["token"] = token return {"choices": [{"message": {"content": '{"status": "ok"}'}}]} monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post) try: result = judge_with_minicpm( prompt="test", image_path=str(image_path), scan={}, wardrobe_summary="", ) finally: image_path.unlink(missing_ok=True) assert result.status == "success" assert captured["token"] == "openbmb-fallback-token" def test_nemotron_uses_nvidia_api_key_as_fallback(monkeypatch) -> None: monkeypatch.setenv("NEMOTRON_BASE_URL", "http://nemotron.test") monkeypatch.delenv("NEMOTRON_API_KEY", raising=False) monkeypatch.setenv("NVIDIA_API_KEY", "nvidia-fallback-token") captured = {} def fake_post(url, token, payload, timeout): captured["token"] = token return {"choices": [{"message": {"content": "{}"}}]} monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post) result = judge_with_nemotron(prompt="brief", run_packet={}) assert result.status == "success" assert captured["token"] == "nvidia-fallback-token" def test_safe_provider_payload_redacts_sensitive_nested_keys() -> None: result = _safe_provider_payload( { "checkpoint": "ok", "HF_TOKEN": "should-not-leak", "nested": {"raw_payload": "hidden", "items": [{"base64_image": "hidden"}, {"safe": "visible"}]}, } ) assert result["checkpoint"] == "ok" assert result["HF_TOKEN"] == "[redacted]" assert result["nested"]["raw_payload"] == "[redacted]" assert result["nested"]["items"][0]["base64_image"] == "[redacted]" assert result["nested"]["items"][1]["safe"] == "visible" def test_nemotron_redacts_run_packet_before_provider_call(monkeypatch) -> None: monkeypatch.setenv("NEMOTRON_BASE_URL", "http://localhost:8001") monkeypatch.setenv("NEMOTRON_API_KEY", "nvidia-token") captured = {} def fake_post(url, token, payload, timeout): captured["content"] = payload["messages"][0]["content"] return {"choices": [{"message": {"content": '{"final_claim_status":"pass"}'}}]} monkeypatch.setattr("nexus_visual_weaver.provider_runtime._post_json", fake_post) result = judge_with_nemotron( prompt="brief", run_packet={"safe": "visible", "api_key": "hidden-key", "nested": {"payload_bytes": "hidden-bytes"}}, minicpm_result={"status": "success", "authorization": "hidden-auth"}, ) assert result.status == "success" assert "visible" in captured["content"] assert "hidden-key" not in captured["content"] assert "hidden-bytes" not in captured["content"] assert "hidden-auth" not in captured["content"] assert "[redacted]" in captured["content"] def test_post_json_rejects_unsupported_url_schemes_before_urlopen(monkeypatch) -> None: called = False def fake_urlopen(*args, **kwargs): nonlocal called called = True raise AssertionError("urlopen should not be called for invalid schemes") monkeypatch.setattr("urllib.request.urlopen", fake_urlopen) for url in ["file:///tmp/payload.json", "ftp://example.test/api", "http:///missing-host"]: try: _post_json(url, "token", {"ok": True}, 1.0) except ValueError as exc: assert "Invalid URL" in str(exc) else: raise AssertionError(f"{url} should have been rejected") assert called is False def test_post_json_rejects_plain_http_non_loopback_before_urlopen(monkeypatch) -> None: called = False def fake_urlopen(*args, **kwargs): nonlocal called called = True raise AssertionError("urlopen should not be called for plaintext remote provider URLs") monkeypatch.setattr("urllib.request.urlopen", fake_urlopen) try: _post_json("http://example.test/v1/chat/completions", "token", {"ok": True}, 1.0) except ValueError as exc: assert "HTTPS" in str(exc) assert "loopback" in str(exc) else: raise AssertionError("remote http provider URL should have been rejected") assert called is False def test_post_json_allows_loopback_http_for_local_tests(monkeypatch) -> None: class FakeResponse: def __enter__(self): return self def __exit__(self, exc_type, exc, tb): return False def read(self): return b'{"ok": true}' def fake_urlopen(request, timeout): assert request.full_url == "http://127.0.0.1:8000/v1/chat/completions" return FakeResponse() monkeypatch.setattr("urllib.request.urlopen", fake_urlopen) assert _post_json("http://127.0.0.1:8000/v1/chat/completions", "token", {"ok": True}, 1.0) == {"ok": True}