🔍 核心机关与修改指南
🔌 直连 58080 管家接口 POST /packages/script
把 src/main.py 的源码文本和 pkg.yaml 里的包名直接注册到机器人的 lumina_server。
⏱️ 5秒一次轮询监工 最多轮询 30 次
每隔 5 秒查询一次任务状态,一旦状态不再是 running,立即打印最终状态、标准输出和错误信息。
💻 完整源码与配置内容(共 37 行 · 支持行号定位与一键复制)
| 1 | import json, urllib.request, zipfile, sys, time |
| 2 | |
| 3 | fp = sys.argv[1] |
| 4 | TASK_TIMEOUT = int(sys.argv[2]) if len(sys.argv) > 2 else 120 # 必须 ≥ 技能总时长 |
| 5 | z = zipfile.ZipFile(fp) |
| 6 | # lumina 包根是 src/main.py; script 路径要包级 main.py 内容 |
| 7 | src = z.read("src/main.py").decode() |
| 8 | meta = {} |
| 9 | for line in z.read("cfg/pkg.yaml").decode().splitlines(): |
| 10 | if ":" in line and not line.startswith("#"): |
| 11 | k, v = line.split(":", 1) |
| 12 | meta[k.strip()] = v.strip() |
| 13 | |
| 14 | body = json.dumps({"package_name": meta["package_name"], "script": src, |
| 15 | "version": meta.get("version", "1.0.0"), |
| 16 | "author": meta.get("author", "workshop"), |
| 17 | "description": meta.get("description", "")}).encode() |
| 18 | req = urllib.request.Request("http://127.0.0.1:58080/packages/script", data=body, |
| 19 | headers={"Content-Type": "application/json"}) |
| 20 | r = json.loads(urllib.request.urlopen(req, timeout=15).read()) |
| 21 | print("install:", r.get("pkg_id"), r.get("version")) |
| 22 | |
| 23 | req = urllib.request.Request("http://127.0.0.1:58080/tasks", |
| 24 | data=json.dumps({"pkg_id": meta["package_name"], "timeout": TASK_TIMEOUT}).encode(), |
| 25 | headers={"Content-Type": "application/json"}) |
| 26 | tid = json.loads(urllib.request.urlopen(req, timeout=15).read())["task_id"] |
| 27 | print("task:", tid) |
| 28 | for _ in range(30): |
| 29 | time.sleep(5) |
| 30 | d = json.loads(urllib.request.urlopen(f"http://127.0.0.1:58080/tasks/{tid}", timeout=10).read()) |
| 31 | if d["status"] != "running": |
| 32 | print("final:", d["status"]) |
| 33 | print("stdout:", d["stdout"]) |
| 34 | print("error:", repr(d["error"])[:200]) |
| 35 | break |
| 36 | else: |
| 37 | print("still running...") |