- EXECUTION_BOARD: record vNext.1 release gate completion, remote43 binary swap, fresh 3-layer acceptance status - VNEXT_COMPLETION_CHECKLIST: upgrade to 'conditionally complete (vNext.1)', update all checklists - add vnext_fresh_acceptance.py: standalone fresh 3-layer acceptance probe script
117 lines
4.1 KiB
Python
117 lines
4.1 KiB
Python
#!/usr/bin/env python3
|
|
"""vNext.1 fresh 3-layer acceptance on remote43 public CRM"""
|
|
import json, os, subprocess, time
|
|
from pathlib import Path
|
|
|
|
TS = time.strftime("%Y%m%d_%H%M%S")
|
|
ART = Path(os.environ.get("ARTIFACT_DIR", f"artifacts/fresh-vnext1-acceptance/{TS}"))
|
|
if not ART.is_absolute():
|
|
ART = Path(os.getcwd()) / ART
|
|
ART.mkdir(parents=True, exist_ok=True)
|
|
|
|
CRM = os.environ.get("CRM_BASE", "https://sub.tksea.top/portal-admin-api")
|
|
AKEY = os.environ.get("OPENAI_ZHONGZHUAN_API_KEY", "")
|
|
MMKEY = os.environ.get("MINIMAX_53HK_API_KEY", "")
|
|
DSKEY = os.environ.get("DEEPSEEK_OFFICIAL_API_KEY", "")
|
|
CTOKEN = os.environ.get("CRM_ADMIN_TOKEN", "")
|
|
|
|
log = open(ART / "run.log", "w")
|
|
|
|
def L(msg):
|
|
print(msg)
|
|
log.write(msg + "\n")
|
|
log.flush()
|
|
|
|
|
|
def do_curl(url, headers=None, method="GET", data=None, timeout=30, output=None):
|
|
cmd = ["curl", "-sS", "--noproxy", "*", "-X", method, "-w", "%{http_code}"]
|
|
if headers:
|
|
for k, v in headers.items():
|
|
cmd += ["-H", f"{k}: {v}"]
|
|
if data:
|
|
cmd += ["-d", data]
|
|
if output:
|
|
cmd += ["-o", str(output)]
|
|
cmd.append(url)
|
|
try:
|
|
r = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
|
|
return r.stdout.strip(), r.stderr
|
|
except subprocess.TimeoutExpired:
|
|
return "timeout", ""
|
|
|
|
|
|
L(f"vNext.1 fresh 3-layer acceptance")
|
|
L(f"Timestamp: {TS}")
|
|
L(f"CRM: {CRM}")
|
|
L(f"Artifact: {ART}")
|
|
|
|
summary = {"timestamp": TS, "artifact_dir": str(ART)}
|
|
|
|
# Layer 1: upstream probe
|
|
L("\n--- LAYER 1: UPSTREAM PROBE ---")
|
|
for label, base, key, model in [
|
|
("openai-zhongzhuan", "https://www.openai-proxy.org", AKEY, "gpt-5.4"),
|
|
("minimax-53hk", "https://api.minimax.chat", MMKEY, "MiniMax-M3"),
|
|
("deepseek-official", "https://api.deepseek.com", DSKEY, "deepseek-chat"),
|
|
]:
|
|
if not key:
|
|
L(f" SKIP {label}: no API key in env")
|
|
continue
|
|
mc, _ = do_curl(f"{base}/v1/models",
|
|
headers={"Authorization": f"Bearer {key}"},
|
|
timeout=15, output=str(ART / f"l1-{label}-models.body.json"))
|
|
L(f" {label} models -> HTTP {mc}")
|
|
|
|
payload = json.dumps({"model": model, "messages": [{"role": "user", "content": "ping"}]})
|
|
cc, _ = do_curl(f"{base}/v1/chat/completions",
|
|
method="POST",
|
|
headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
|
|
data=payload, timeout=30,
|
|
output=str(ART / f"l1-{label}-chat.body.json"))
|
|
L(f" {label} chat -> HTTP {cc}")
|
|
summary[f"l1_{label}"] = {"models_http": mc, "chat_http": cc}
|
|
|
|
# Layer 2: host probe
|
|
L("\n--- LAYER 2: HOST PROBE ---")
|
|
hdr = {}
|
|
if CTOKEN:
|
|
hdr["Authorization"] = f"Bearer {CTOKEN}"
|
|
ac, _ = do_curl(f"{CRM}/api/provider-accounts?limit=10",
|
|
headers=hdr, timeout=15,
|
|
output=str(ART / "l2-accounts.body.json"))
|
|
L(f" accounts -> HTTP {ac}")
|
|
|
|
acct_count = 0
|
|
p = ART / "l2-accounts.body.json"
|
|
if p.stat().st_size > 10:
|
|
try:
|
|
d = json.load(open(p))
|
|
acct_count = len(d.get("accounts", d.get("data", [])))
|
|
except json.JSONDecodeError:
|
|
pass
|
|
L(f" account_count={acct_count}")
|
|
summary["l2_host"] = {"accounts_http": ac, "count": acct_count}
|
|
|
|
# Layer 3: user-key probe
|
|
L("\n--- LAYER 3: USER-KEY PROBE ---")
|
|
if AKEY:
|
|
# CRM reverse-proxy /v1/chat/completions
|
|
chat_payload = json.dumps({"model": "gpt-5.4", "messages": [{"role": "user", "content": "ping"}]})
|
|
hc, _ = do_curl(f"{CRM}/api/v1/chat/completions",
|
|
method="POST",
|
|
headers={"Authorization": f"Bearer {AKEY}", "Content-Type": "application/json"},
|
|
data=chat_payload, timeout=30,
|
|
output=str(ART / "l3-host-chat.body.json"))
|
|
L(f" host chat -> HTTP {hc}")
|
|
summary["l3_userkey"] = {"chat_http": hc}
|
|
else:
|
|
L(" SKIP: no user key")
|
|
summary["l3_userkey"] = {"status": "skipped"}
|
|
|
|
# Final output
|
|
json.dump(summary, open(ART / "99-summary.json", "w"), ensure_ascii=False, indent=2)
|
|
L(f"\n=== FINAL SUMMARY ===")
|
|
L(json.dumps(summary, ensure_ascii=False, indent=2))
|
|
L(f"\nArtifact path: {ART}")
|
|
log.close()
|