feat(mcp): tool search_organisations (résolution nom -> id)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
# src/mcp/queries.py
|
||||
import re
|
||||
|
||||
from src.mcp.serialization import (
|
||||
to_json_records, # noqa: F401 (utilisé aux tâches suivantes)
|
||||
)
|
||||
from src.utils.data import DF_ACHETEURS, DF_TITULAIRES
|
||||
from src.utils.search import search_org
|
||||
|
||||
PAGE_SIZE = 50
|
||||
TOP_N = 10
|
||||
ORG_FRAMES = {"acheteur": DF_ACHETEURS, "titulaire": DF_TITULAIRES}
|
||||
|
||||
|
||||
def _extract_plain_text(html_str: str) -> str:
|
||||
"""Extract plain text from HTML link, e.g. '<a...>123</a>' -> '123'."""
|
||||
match = re.search(r">([^<]+)<", html_str)
|
||||
return match.group(1) if match else html_str
|
||||
|
||||
|
||||
def search_organisations(
|
||||
query: str, org_type: str = "acheteur", limite: int = 20
|
||||
) -> list[dict]:
|
||||
"""Recherche des organisations par nom, résout un nom -> id."""
|
||||
if org_type not in ORG_FRAMES:
|
||||
raise ValueError(
|
||||
f"type invalide: {org_type!r} (attendu 'acheteur' ou 'titulaire')"
|
||||
)
|
||||
df = search_org(ORG_FRAMES[org_type], query, org_type, track=False).head(limite)
|
||||
return [
|
||||
{
|
||||
"id": _extract_plain_text(r[f"{org_type}_id"]),
|
||||
"nom": _extract_plain_text(r[f"{org_type}_nom"]),
|
||||
"departement": r.get("Département"),
|
||||
}
|
||||
for r in df.to_dicts()
|
||||
]
|
||||
@@ -1,4 +1,7 @@
|
||||
import pytest
|
||||
|
||||
import src.utils.search as search_mod
|
||||
from src.mcp.queries import search_organisations
|
||||
from src.utils.data import DF_ACHETEURS
|
||||
from src.utils.search import search_org
|
||||
|
||||
@@ -19,3 +22,20 @@ def test_search_org_track_true_calls_track_search(monkeypatch):
|
||||
search_org(DF_ACHETEURS, "ACHETEUR", "acheteur", track=True)
|
||||
|
||||
assert calls == [("ACHETEUR", "home_page_search")]
|
||||
|
||||
|
||||
def test_search_organisations_finds_known_acheteur():
|
||||
result = search_organisations("ACHETEUR", "acheteur")
|
||||
assert any(r["id"] == "123" for r in result)
|
||||
first = next(r for r in result if r["id"] == "123")
|
||||
assert set(first.keys()) == {"id", "nom", "departement"}
|
||||
|
||||
|
||||
def test_search_organisations_invalid_type_raises():
|
||||
with pytest.raises(ValueError):
|
||||
search_organisations("x", "autre")
|
||||
|
||||
|
||||
def test_search_organisations_respects_limite():
|
||||
result = search_organisations("ACHETEUR", "acheteur", limite=1)
|
||||
assert len(result) <= 1
|
||||
|
||||
Reference in New Issue
Block a user