#!/usr/bin/env python3 """列出可執行的議題。輸入:open.json agents.json tabs.json owner/repo 阻擋關係只認 Gitea 原生 issue dependencies(tea api),不看議題內文。""" import os, json, re, subprocess, sys open_issues = json.load(open(sys.argv[1])) agents = json.load(open(sys.argv[2])) tabs = json.load(open(sys.argv[3])) repo = sys.argv[4] def find(o, k): if isinstance(o, dict): if k in o: return o[k] for v in o.values(): r = find(v, k) if r is not None: return r elif isinstance(o, list): for v in o: r = find(v, k) if r is not None: return r def labels(i): return [l.strip() for l in (i.get("labels") or "").split() if l.strip()] if isinstance(i.get("labels"), str) else [l["name"] for l in i.get("labels") or []] # Herdr 裡活著的 agent:名稱 issue-N,或掛在標籤 #N 的 tab 上 running = set() for a in find(agents, "agents") or []: m = re.fullmatch(r"issue-(\d+)", str(a.get("name") or "")) if m: running.add(m.group(1)) agent_tabs = {a.get("tab_id") for a in find(agents, "agents") or []} for t in find(tabs, "tabs") or []: m = re.fullmatch(r"#(\d+)", str(t.get("label") or "")) if m and t.get("tab_id") in agent_tabs: running.add(m.group(1)) def open_blockers(n): """擋住 #n 的 open 依賴。tea api 遇到 HTTP 錯誤仍 exit 0,所以回應不是陣列就當失敗,整個停下。""" raw = subprocess.run(["tea", "api", "--login", os.environ["HERDR_ISSUE_LOGIN"], "--repo", repo, f"/repos/{{owner}}/{{repo}}/issues/{n}/dependencies"], capture_output=True, text=True).stdout try: d = json.loads(raw) except Exception: d = None if not isinstance(d, list): sys.exit(f"gitea: 讀取 #{n} 的依賴失敗:{raw.strip()[:300]}") out = [] for i in d: if i.get("state") != "open": continue r = (i.get("repository") or {}).get("full_name", "") out.append(("#" if r in ("", repo) else r + "#") + str(i["number"])) return out def spec(i): return next((l for l in labels(i) if l.startswith("規格/#") or l.startswith("總覽/#")), "") runnable, stale = [], [] for i in sorted(open_issues, key=lambda x: int(x["index"])): ls = labels(i) if "ready-for-agent" not in ls: continue if "類型/規格" in ls or "類型/總覽" in ls: continue n = i["index"] if n in running: continue if "in-progress" in ls: stale.append(n); continue if open_blockers(n): continue runnable.append((n, spec(i), i["title"])) if runnable: print(f"可執行({len(runnable)}):編號\t規格\t標題") for n, s, t in runnable: print(f"#{n}\t{s}\t{t}") else: print("目前沒有可執行的議題。") print() print("Herdr 執行中:" + (" ".join(f"#{n}" for n in sorted(running, key=int)) or "無")) if stale: print("掛 in-progress 但沒有 agent(需處理,重跑 start 會接續):" + " ".join(f"#{n}" for n in stale))