feat(account-manager): add list-json API for cross-skill orchestration

This commit is contained in:
2026-04-04 18:36:39 +08:00
parent 35f4758da2
commit 0a599b5fac

View File

@@ -586,6 +586,48 @@ def cmd_get(account_id):
print(_runtime_paths_debug_text(), file=sys.stderr) print(_runtime_paths_debug_text(), file=sys.stderr)
def cmd_list_json(platform_input: str, limit: int = 200) -> None:
"""
跨技能接口stdout 仅输出一行 JSON 数组,元素结构与 get 单条一致。
平台可为 all/全部 或各平台中文名/英文键;按 updated_at 倒序,最多 limit 条(上限 500
"""
get_skill_logger().info("list_json filter=%r limit=%s", platform_input, limit)
init_db()
raw = (platform_input or "all").strip()
if not raw or raw.lower() == "all" or raw == "全部":
key = "all"
else:
key = resolve_platform_key(raw)
if not key:
print("ERROR:INVALID_PLATFORM_LIST_JSON 无法识别的平台名称。")
print("支持:" + _platform_list_cn_for_help())
return
lim = max(1, min(int(limit), 500))
conn = get_conn()
try:
cur = conn.cursor()
if key == "all":
cur.execute(
"SELECT id FROM accounts ORDER BY updated_at DESC, id DESC LIMIT ?",
(lim,),
)
else:
cur.execute(
"SELECT id FROM accounts WHERE platform = ? "
"ORDER BY updated_at DESC, id DESC LIMIT ?",
(key, lim),
)
ids = [r[0] for r in cur.fetchall()]
finally:
conn.close()
out = []
for aid in ids:
acc = get_account_by_id(aid)
if acc:
out.append(acc)
print(json.dumps(out, ensure_ascii=False))
def cmd_pick_logged_in(platform_input: str): def cmd_pick_logged_in(platform_input: str):
""" """
机器可读跨技能接口查询指定平台下「已登录」的一条账号login_status=1按 last_login_at 优先)。 机器可读跨技能接口查询指定平台下「已登录」的一条账号login_status=1按 last_login_at 优先)。
@@ -629,6 +671,60 @@ def cmd_pick_logged_in(platform_input: str):
print(json.dumps(acc, ensure_ascii=False)) print(json.dumps(acc, ensure_ascii=False))
def cmd_pick_web(platform_input: str):
"""
供 llm-manager 等:取该平台用于网页自动化的账号候选。
优先 login_status=1与 pick-logged-in 一致);若无,则取该平台 updated_at 最新的一条,
便于「已 add 未标登录」时仍打开 profile在浏览器内登录后继续任务。
成功stdout 仅一行 JSON与 get 一致);失败:首行 ERROR:。
"""
get_skill_logger().info("pick_web platform_input=%r", platform_input)
key = resolve_platform_key((platform_input or "").strip())
if not key:
print("ERROR:INVALID_PLATFORM 无法识别的平台名称。")
print("支持:" + _platform_list_cn_for_help())
return
init_db()
conn = get_conn()
try:
cur = conn.cursor()
cur.execute(
"""
SELECT id FROM accounts
WHERE platform = ? AND login_status = 1
ORDER BY (last_login_at IS NULL), last_login_at DESC
LIMIT 1
""",
(key,),
)
row = cur.fetchone()
if not row:
cur.execute(
"""
SELECT id FROM accounts
WHERE platform = ?
ORDER BY updated_at DESC, id DESC
LIMIT 1
""",
(key,),
)
row = cur.fetchone()
finally:
conn.close()
if not row:
print("ERROR:NO_ACCOUNT 该平台在账号库中没有任何记录,请先执行 add。")
return
acc = get_account_by_id(row[0])
if not acc:
print("ERROR:ACCOUNT_NOT_FOUND")
print(_runtime_paths_debug_text(), file=sys.stderr)
return
print(json.dumps(acc, ensure_ascii=False))
def cmd_add(platform_input: str, phone: str): def cmd_add(platform_input: str, phone: str):
"""添加账号platform 可为中文展示名或英文键;手机号必填;同平台下同手机号不可重复。""" """添加账号platform 可为中文展示名或英文键;手机号必填;同平台下同手机号不可重复。"""
log = get_skill_logger() log = get_skill_logger()
@@ -1371,13 +1467,42 @@ def _mark_login_status(account_id, success: bool):
conn.close() conn.close()
def cmd_set_login_status(account_id_str: str, status_str: str) -> None:
"""
跨技能机器接口:回写 accounts.login_status。
成功stdout 首行 OK:SET_LOGIN_STATUS 或 OK:CLEARED_LOGIN_STATUS进程退出码 0。
失败stdout 首行 ERROR:...,退出码 1。
"""
aid_s = (account_id_str or "").strip()
st_s = (status_str or "").strip()
if not aid_s.isdigit():
print("ERROR:INVALID_ACCOUNT_ID")
sys.exit(1)
if st_s not in ("0", "1"):
print("ERROR:INVALID_STATUS 须为 0 或 1")
sys.exit(1)
aid = int(aid_s)
init_db()
if get_account_by_id(aid) is None:
get_skill_logger().warning("set_login_status_not_found account_id=%r", aid)
print("ERROR:ACCOUNT_NOT_FOUND")
sys.exit(1)
ok = st_s == "1"
_mark_login_status(aid, ok)
get_skill_logger().info("set_login_status account_id=%s success=%s", aid, ok)
print("OK:SET_LOGIN_STATUS" if ok else "OK:CLEARED_LOGIN_STATUS")
def _cli_print_full_usage() -> None: def _cli_print_full_usage() -> None:
"""总览(未带子命令或需要完整说明时)。""" """总览(未带子命令或需要完整说明时)。"""
print("用法概览(将 main.py 换为你的路径):") print("用法概览(将 main.py 换为你的路径):")
print(" python main.py add <平台中文名> <手机号>") print(" python main.py add <平台中文名> <手机号>")
print(" python main.py list [平台|all|全部]") print(" python main.py list [平台|all|全部]")
print(" python main.py pick-logged-in <平台> # 跨技能用:输出一行 JSON 或 ERROR") print(" python main.py pick-logged-in <平台> # 跨技能用:仅已登录账号,一行 JSON 或 ERROR")
print(" python main.py pick-web <平台> # 跨技能用:优先已登录,否则最新一条账号")
print(" python main.py list-json <平台|all> [--limit N] # 跨技能用:一行 JSON 数组,元素同 get")
print(" python main.py get <id>") print(" python main.py get <id>")
print(" python main.py set-login-status <id> <0|1> # 跨技能回写登录态")
print(" python main.py open <id>") print(" python main.py open <id>")
print(" python main.py login <id>") print(" python main.py login <id>")
print(" python main.py delete id <id>") print(" python main.py delete id <id>")
@@ -1456,6 +1581,30 @@ if __name__ == "__main__":
_cli_fail_need_account_id("get") _cli_fail_need_account_id("get")
sys.exit(1) sys.exit(1)
cmd_get(sys.argv[2]) cmd_get(sys.argv[2])
elif cmd == "set-login-status":
if len(sys.argv) < 4:
print("ERROR:CLI_SET_LOGIN_STATUS_MISSING_ARGS")
print("用法python main.py set-login-status <account_id> <0|1>")
print("说明:供 llm-manager 等脚本回写登录态;成功时 stdout 首行以 OK: 开头。")
sys.exit(1)
cmd_set_login_status(sys.argv[2], sys.argv[3])
elif cmd == "list-json":
if len(sys.argv) < 3:
print("ERROR:CLI_LIST_JSON_MISSING_PLATFORM")
print("用法python main.py list-json <平台|all|全部> [--limit N]")
print("说明:跨技能编排;成功时 stdout 仅一行 JSON 数组(元素与 get 一致)。")
sys.exit(1)
av = sys.argv[2:]
platform_arg = av[0]
lim = 200
if "--limit" in av:
i = av.index("--limit")
if i + 1 < len(av):
try:
lim = int(av[i + 1])
except ValueError:
pass
cmd_list_json(platform_arg, limit=lim)
elif cmd == "pick-logged-in": elif cmd == "pick-logged-in":
if len(sys.argv) < 3: if len(sys.argv) < 3:
print("ERROR:CLI_PICK_LOGGED_IN_MISSING_ARGS") print("ERROR:CLI_PICK_LOGGED_IN_MISSING_ARGS")
@@ -1463,6 +1612,13 @@ if __name__ == "__main__":
print("说明:供 llm-manager 等技能查询该平台已登录账号;成功时 stdout 仅一行 JSON。") print("说明:供 llm-manager 等技能查询该平台已登录账号;成功时 stdout 仅一行 JSON。")
sys.exit(1) sys.exit(1)
cmd_pick_logged_in(sys.argv[2]) cmd_pick_logged_in(sys.argv[2])
elif cmd == "pick-web":
if len(sys.argv) < 3:
print("ERROR:CLI_PICK_WEB_MISSING_ARGS")
print("用法python main.py pick-web <平台中文名或英文键>")
print("说明:供 llm-manager 等;优先已登录账号,否则返回该平台最新一条账号(未登录也可用于打开浏览器登录)。")
sys.exit(1)
cmd_pick_web(sys.argv[2])
elif cmd == "open": elif cmd == "open":
if len(sys.argv) < 3: if len(sys.argv) < 3:
_cli_fail_need_account_id("open") _cli_fail_need_account_id("open")