agromatrix: add shared-memory review api and crawl4ai robustness

This commit is contained in:
NODA1 System
2026-02-21 13:05:18 +01:00
parent 01bfa97783
commit 68ac8fa355
4 changed files with 319 additions and 5 deletions

View File

@@ -0,0 +1,114 @@
#!/usr/bin/env python3
import argparse
import json
import sys
import urllib.error
import urllib.request
TINY_PNG_DATA_URL = (
"data:image/png;base64,"
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8Xw8AAoMBgQhP2YkAAAAASUVORK5CYII="
)
def http_json(method: str, url: str, payload=None):
data = None
headers = {}
if payload is not None:
data = json.dumps(payload).encode("utf-8")
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
try:
with urllib.request.urlopen(req, timeout=60) as resp:
body = resp.read().decode("utf-8", errors="replace")
return resp.status, json.loads(body) if body else {}
except urllib.error.HTTPError as e:
body = e.read().decode("utf-8", errors="replace")
try:
parsed = json.loads(body) if body else {}
except Exception:
parsed = {"raw": body}
return e.code, parsed
def check(cond: bool, label: str, details: str = "") -> bool:
prefix = "PASS" if cond else "FAIL"
tail = f" :: {details}" if details else ""
print(f"[{prefix}] {label}{tail}")
return cond
def main() -> int:
parser = argparse.ArgumentParser(description="AgroMatrix regression smoke checks")
parser.add_argument("--base-url", default="http://127.0.0.1:9102")
parser.add_argument("--agent-id", default="agromatrix")
parser.add_argument("--chat-id", default="smoke-agromatrix")
parser.add_argument("--user-id", default="smoke-user")
parser.add_argument("--skip-review-404", action="store_true")
args = parser.parse_args()
ok_all = True
status, health = http_json("GET", f"{args.base_url}/health")
ok_all &= check(status == 200 and health.get("status") == "ok", "health", str(health))
numeric_payload = {
"prompt": "напиши мені яка сума була витрачена на добрива",
"metadata": {
"channel": "telegram",
"chat_id": args.chat_id,
"user_id": args.user_id,
"user_name": "smoke",
},
}
status, infer_num = http_json("POST", f"{args.base_url}/v1/agents/{args.agent_id}/infer", numeric_payload)
resp_text = str(infer_num.get("response") or "")
numeric_guard = (
"Не можу підтвердити точне число" in resp_text
or "value + unit + source" in resp_text
or "source(sheet,row)" in resp_text
)
ok_all &= check(status == 200 and numeric_guard, "numeric_contract_guard", resp_text[:180])
plant_payload = {
"prompt": "Що це за рослина на фото?",
"images": [TINY_PNG_DATA_URL],
"metadata": {
"channel": "telegram",
"chat_id": args.chat_id,
"user_id": args.user_id,
"user_name": "smoke",
},
}
status, infer_plant = http_json("POST", f"{args.base_url}/v1/agents/{args.agent_id}/infer", plant_payload)
plant_text = str(infer_plant.get("response") or "")
plant_ok = (
"Не впевнений" in plant_text
or "Надішли" in plant_text
or "канд" in plant_text.lower()
)
ok_all &= check(status == 200 and plant_ok, "deterministic_plant_response", plant_text[:180])
status, pending = http_json("GET", f"{args.base_url}/v1/agromatrix/shared-memory/pending")
pending_shape = isinstance(pending, dict) and isinstance(pending.get("items"), list)
ok_all &= check(status == 200 and pending_shape, "shared_pending_endpoint", f"total={pending.get('total')}")
if not args.skip_review_404:
status, review = http_json(
"POST",
f"{args.base_url}/v1/agromatrix/shared-memory/review",
{
"point_id": "11111111-1111-1111-1111-111111111111",
"approve": False,
"reviewer": "smoke",
"note": "nonexistent id check",
},
)
ok_all &= check(status == 404, "shared_review_not_found_contract", str(review))
return 0 if ok_all else 1
if __name__ == "__main__":
sys.exit(main())