129 lines
4.6 KiB
Python
Executable File
129 lines
4.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
import argparse
|
||
import json
|
||
import os
|
||
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, headers=None):
|
||
data = None
|
||
req_headers = dict(headers or {})
|
||
if payload is not None:
|
||
data = json.dumps(payload).encode("utf-8")
|
||
req_headers.setdefault("Content-Type", "application/json")
|
||
req = urllib.request.Request(url, data=data, headers=req_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")
|
||
parser.add_argument(
|
||
"--mentor-token",
|
||
default=(
|
||
os.getenv("AGROMATRIX_REVIEW_BEARER_TOKEN")
|
||
or (os.getenv("AGROMATRIX_REVIEW_BEARER_TOKENS", "").split(",")[0].strip())
|
||
or ""
|
||
),
|
||
)
|
||
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:
|
||
req_headers = {}
|
||
if args.mentor_token:
|
||
req_headers["Authorization"] = f"Bearer {args.mentor_token}"
|
||
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",
|
||
},
|
||
headers=req_headers,
|
||
)
|
||
expected = 404 if args.mentor_token else 401
|
||
ok_all &= check(status == expected, "shared_review_not_found_contract", str(review))
|
||
|
||
return 0 if ok_all else 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|