Some checks failed
CI / test (push) Failing after 12s
将 settlement.py 的 settle_campaign_sessions 函数吸收为 ExplorationSessionRepository.expire_running_sessions 方法。删除浅模块 settlement.py(30 行,接口宽如实现),会话生命周期操作集中在 repository。 - 新增 ExplorationSessionRepository.expire_running_sessions(campaign_id) - 更新 campaigns.py 和 campaign_runner.py 两个调用点 - 删除 backend/agenteval/exploration/settlement.py - 所有测试通过,行为不变
135 lines
4.4 KiB
Python
135 lines
4.4 KiB
Python
"""One-shot ops script: register the agenteval-patrol cron job on the OpenClaw
|
||
gateway via its WS RPC protocol, authenticating through the trusted-proxy
|
||
network (x-forwarded-user). Run inside the agenteval container."""
|
||
|
||
import base64
|
||
import json
|
||
import os
|
||
import socket
|
||
import struct
|
||
import sys
|
||
|
||
HOST, PORT = "openclaw-eval", 18789
|
||
|
||
|
||
def recv_exact(s, n):
|
||
buf = b""
|
||
while len(buf) < n:
|
||
chunk = s.recv(n - len(buf))
|
||
if not chunk:
|
||
raise ConnectionError("closed")
|
||
buf += chunk
|
||
return buf
|
||
|
||
|
||
def read_frame(s):
|
||
b1, b2 = recv_exact(s, 2)
|
||
length = b2 & 0x7F
|
||
if length == 126:
|
||
length = struct.unpack(">H", recv_exact(s, 2))[0]
|
||
elif length == 127:
|
||
length = struct.unpack(">Q", recv_exact(s, 8))[0]
|
||
return recv_exact(s, length).decode()
|
||
|
||
|
||
def send_text(s, payload):
|
||
data = payload.encode()
|
||
mask = os.urandom(4)
|
||
header = b"\x81"
|
||
n = len(data)
|
||
if n < 126:
|
||
header += bytes([0x80 | n])
|
||
elif n < 65536:
|
||
header += bytes([0x80 | 126]) + struct.pack(">H", n)
|
||
else:
|
||
header += bytes([0x80 | 127]) + struct.pack(">Q", n)
|
||
masked = bytes(d ^ mask[i % 4] for i, d in enumerate(data))
|
||
s.sendall(header + mask + masked)
|
||
|
||
|
||
def rpc(s, rid, method, params):
|
||
send_text(s, json.dumps({"type": "req", "id": rid, "method": method, "params": params}))
|
||
while True:
|
||
msg = json.loads(read_frame(s))
|
||
if msg.get("type") == "res" and msg.get("id") == rid:
|
||
return msg
|
||
print("note:", json.dumps(msg)[:200])
|
||
|
||
|
||
def main(action):
|
||
s = socket.create_connection((HOST, PORT), timeout=15)
|
||
key = base64.b64encode(os.urandom(16)).decode()
|
||
req = (
|
||
f"GET / HTTP/1.1\r\nHost: {HOST}:{PORT}\r\nUpgrade: websocket\r\n"
|
||
f"Connection: Upgrade\r\nSec-WebSocket-Key: {key}\r\nSec-WebSocket-Version: 13\r\n"
|
||
f"Origin: http://192.168.8.145:8001\r\n"
|
||
f"x-forwarded-user: agenteval\r\n\r\n"
|
||
)
|
||
s.sendall(req.encode())
|
||
resp = b""
|
||
while b"\r\n\r\n" not in resp:
|
||
resp += s.recv(4096)
|
||
status = resp.split(b"\r\n")[0].decode()
|
||
print("UPGRADE:", status)
|
||
if "101" not in status:
|
||
sys.exit(1)
|
||
|
||
challenge = json.loads(read_frame(s))
|
||
print("CHALLENGE:", json.dumps(challenge)[:300])
|
||
|
||
connect_params = {
|
||
"minProtocol": 4,
|
||
"maxProtocol": 4,
|
||
"client": {"id": "openclaw-control-ui", "version": "0.0.1", "platform": "linux", "mode": "ui"},
|
||
"role": "operator",
|
||
"scopes": ["operator.read", "operator.write", "operator.admin"],
|
||
"caps": [],
|
||
"commands": [],
|
||
"permissions": {},
|
||
"auth": {},
|
||
"locale": "zh-CN",
|
||
"userAgent": "agenteval-ops/0.0.1",
|
||
}
|
||
res = rpc(s, "c1", "connect", connect_params)
|
||
print("CONNECT:", json.dumps(res)[:400])
|
||
if not res.get("ok"):
|
||
sys.exit(2)
|
||
|
||
if action == "list":
|
||
res = rpc(s, "c2", "cron.list", {"includeDisabled": True})
|
||
print("CRON.LIST:", json.dumps(res, ensure_ascii=False)[:1200])
|
||
elif action == "add":
|
||
params = {
|
||
"name": "agenteval-patrol",
|
||
"description": "AgentEvalTool 常驻巡检:每小时按 agenteval-patrol skill 闭环巡检探索",
|
||
"enabled": True,
|
||
"agentId": "main",
|
||
"schedule": {"kind": "cron", "expr": "0 * * * *", "tz": "Asia/Shanghai"},
|
||
"sessionTarget": "isolated",
|
||
"wakeMode": "now",
|
||
"payload": {
|
||
"kind": "agentTurn",
|
||
"message": (
|
||
"使用 agenteval-patrol skill 执行一次完整巡检闭环:调用巡检 API,"
|
||
"研判新结果与预算余量,按规则派发/驱动探索会话并提交体验记录,"
|
||
"收到 409 立即收敛,最后汇报本轮巡检结果。"
|
||
),
|
||
},
|
||
"delivery": {"mode": "none"},
|
||
}
|
||
res = rpc(s, "c2", "cron.add", params)
|
||
print("CRON.ADD:", json.dumps(res, ensure_ascii=False)[:1200])
|
||
elif action == "run":
|
||
job_id = sys.argv[2]
|
||
res = rpc(s, "c2", "cron.run", {"id": job_id})
|
||
print("CRON.RUN:", json.dumps(res, ensure_ascii=False)[:1200])
|
||
elif action == "runs":
|
||
job_id = sys.argv[2]
|
||
res = rpc(s, "c2", "cron.runs", {"id": job_id})
|
||
print("CRON.RUNS:", json.dumps(res, ensure_ascii=False)[:2000])
|
||
s.close()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main(sys.argv[1] if len(sys.argv) > 1 else "list")
|