import pytest from aiatlas.connectors.labs.cohere import BLOG, DOCS, CohereConnector, blog_items from aiatlas.sdk.facts import Target from tests.conftest import claims_of, entity_names, extract_from_fixture, fixture_path @pytest.fixture def connector() -> CohereConnector: return CohereConnector() async def test_models(connector): facts = await extract_from_fixture(connector, Target(url=f"{DOCS}.md", doc_type="model_docs", key="models"), fixture_path("cohere", "models.md"), content_type="text/markdown") models = entity_names(facts, "model") assert len(models) >= 40 and {"command-a-plus-05-2026", "embed-v4.0", "rerank-v4.0-pro", "parse-v5.0", "cohere-transcribe-03-2026", "tiny-aya-global"} <= models a_plus = claims_of(facts, "command-a-plus-05-2026") assert a_plus["context_length"] == 128_000 and a_plus["max_output_tokens"] == 64_000 and a_plus["status"] == "active" assert a_plus["modalities"] == ["image", "text"] and a_plus["vision"] is True and a_plus["family"] == "Command" and a_plus["is_moe"] is True # canonical, sorted a_plus_ref = next(e for e in facts.entities if e.name == "command-a-plus-05-2026") assert a_plus_ref.family is not None and a_plus_ref.family.entity_type == "model_family" and a_plus_ref.family.name == "Command" assert a_plus["foundry_model_id"] == "coherelabs-command-a-plus-05-2026-w4a4" r = claims_of(facts, "command-r-03-2024") assert r["status"] == "deprecated" and r["deprecation_date"] == "2025-09-15" embed = claims_of(facts, "embed-v4.0") assert embed["context_length"] == 128_000 and 1536 in embed["embedding_dimensions"] and embed["modalities_output"] == ["embedding"] north = claims_of(facts, "north-small-translate-1-0") assert north["parameter_count"] == 218_000_000_000 and north["active_parameter_count"] == 25_000_000_000 and north["is_moe"] is True assert claims_of(facts, "rerank-v3.5")["bedrock_model_id"] == "cohere.rerank-v3-5:0" transcribe = claims_of(facts, "cohere-transcribe-03-2026") assert transcribe["openness"] == "open-weights" and transcribe["openness_raw"] == "open-source" and transcribe["weights_available"] is True # prose "open source" → canonical category assert claims_of(facts, "command-a-reasoning-08-2025")["reasoning"] is True # alias rows fold into the model they point at plus = next(e for e in facts.entities if e.name == "command-r-plus-04-2024") assert "command-r-plus" in plus.aliases and "command-r-plus" not in models assert plus.identifiers == {"cohere_model_id": "command-r-plus-04-2024"} plus_claims = claims_of(facts, "command-r-plus-04-2024") assert plus_claims["api_aliases"] == ["command-r-plus"] and plus_claims["api_alias"] == "command-r-plus" # always a list + first for compat assert sum(r.predicate == "available_through" for r in facts.relations) >= 30 async def test_blog(connector): facts = await extract_from_fixture(connector, Target(url=BLOG, doc_type="listing", key="blog"), fixture_path("cohere", "blog.html")) events = {e.source_url: e for e in facts.events} assert len(events) >= 20 north = events[f"{BLOG}/north-small-translate"] assert north.summary.startswith("Cohere: Introducing North Small Translate") and north.effective_at.date().isoformat() == "2026-09-10" assert north.category == "release" and north.meta["categories"] == ["Product Launch"] assert events[f"{BLOG}/command-a-plus"].effective_at.date().isoformat() == "2026-05-20" assert all(e.effective_at is not None for e in facts.events) assert any(t.needs_llm for t in facts.targets) def test_blog_items_direct(): items = blog_items(fixture_path("cohere", "blog.html").read_bytes()) assert items[0].url == f"{BLOG}/north-small-translate" and items[0].published_at is not None assert all(not it.url.startswith(f"{BLOG}/tag/") for it in items)