"""Run a non-persistent Agent Loop test with synthetic business data.""" from __future__ import annotations import shlex from pathlib import Path import paramiko ROOT = Path(__file__).resolve().parents[1] def config() -> dict[str, str]: result: dict[str, str] = {} for raw in (ROOT / "server-deploy.conf").read_text(encoding="utf-8-sig").splitlines(): line = raw.strip() if line and not line.startswith("#") and "=" in line: key, value = line.split("=", 1) result[key.strip()] = value.strip() return result def main() -> int: settings = config() client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) options = { "hostname": settings["SERVER_HOST"], "port": int(settings.get("SERVER_PORT", "22")), "username": settings["SERVER_USER"], "timeout": 20, "banner_timeout": 20, "auth_timeout": 20, } if settings.get("SERVER_KEYFILE"): options["key_filename"] = settings["SERVER_KEYFILE"] else: options["password"] = settings["SERVER_PASSWORD"] client.connect(**options) synthetic_test = r''' import json from services import assistant_model model = assistant_model.configuration() skill = { "instructions": "对虚构测试项目执行证据约束核查,只验证工具调用链。", "methods": { "synthetic-financial-leasing/SKILL.md": "读取数据卡证据,检查负债口径、现金流是否齐备及租赁物覆盖率;不得作审批决定。" }, "allowed_tools": ["read_project_snapshot", "read_checks", "read_method"], } snapshot = { "id": "snapshot-synthetic-safe", "project_id": "SAFE-SYNTHETIC-TEST", "values": { "financial.total_liabilities": 100, "due_diligence.liabilities": 90, "lease.total_value": 120, "facility.amount": 100, "cashflow.net_operating": None, }, "sources": { "financial.total_liabilities": [{"id": "ev-safe-1", "source": "synthetic_finance", "value": 100}], "due_diligence.liabilities": [{"id": "ev-safe-2", "source": "synthetic_due_diligence", "value": 90}], "lease.total_value": [{"id": "ev-safe-3", "source": "synthetic_asset", "value": 120}], "facility.amount": [{"id": "ev-safe-4", "source": "synthetic_facility", "value": 100}], "cashflow.net_operating": [{"id": "ev-safe-5", "source": "synthetic_cashflow", "value": None}], }, "documents": [], } checks = [ {"code": "synthetic.liability.consistency", "title": "负债口径差异", "result": "issue", "evidence_ids": ["ev-safe-1", "ev-safe-2"], "fields": ["financial.total_liabilities", "due_diligence.liabilities"], "suggested_action": "核实负债差异"}, {"code": "synthetic.cashflow.missing", "title": "现金流缺失", "result": "unknown", "evidence_ids": ["ev-safe-5"], "fields": ["cashflow.net_operating"], "suggested_action": "补充现金流数据"}, ] rules = [{"id": "rule-synthetic", "name": "虚构测试规则", "version": "1.0.0", "natural_language": "现金流缺失时提示补充,不作审批结论"}] result, trace = assistant_model.invoke( skill, snapshot, checks, rules, "读取全部授权事实、检查与方法,返回可追溯建议。", [], model, {"timeout_seconds": 120, "max_tool_calls": 12}, ) print(json.dumps({ "status": "passed", "endpoint": model["endpoint"], "model": trace["model"], "engine": trace["engine"], "tool_calls": trace["tool_calls"], "tools_read": trace["tools_read"], "finding_count": len(result["findings"]), "evidence_bound": all(item["evidence_ids"] for item in result["findings"] if item["result"] in ("pass", "issue")), "requirement_response_present": bool(result["requirement_response"]), }, ensure_ascii=True)) ''' encoded = synthetic_test.encode("utf-8").hex() code = "exec(bytes.fromhex(" + repr(encoded) + ").decode('utf-8'))" command = "docker exec mini-openclaw python -c " + shlex.quote(code) _, stdout, stderr = client.exec_command(command, timeout=180) output = stdout.read().decode("utf-8", errors="replace") error = stderr.read().decode("utf-8", errors="replace") status = stdout.channel.recv_exit_status() client.close() if status: raise RuntimeError(error.strip() or output.strip() or f"remote exit {status}") print(output.strip()) return 0 if __name__ == "__main__": raise SystemExit(main())