All checks were successful
Publish Python Package to Gitea / publish (push) Successful in 29s
Expose ensure_ui_ready via DuiLib GetAccessible inject path; package x86 native helpers for host/skill consumers. Co-authored-by: Cursor <cursoragent@cursor.com>
157 lines
4.3 KiB
Python
157 lines
4.3 KiB
Python
"""CLI:python -m jiangchang_desktop_wake <probe|inject|wake|ensure|profiles>"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import json
|
||
import sys
|
||
|
||
|
||
def _print_json(obj) -> None:
|
||
print(json.dumps(obj, ensure_ascii=False, indent=2))
|
||
|
||
|
||
def main(argv: list[str] | None = None) -> int:
|
||
parser = argparse.ArgumentParser(
|
||
prog="python -m jiangchang_desktop_wake",
|
||
description="桌面 UIA Provider 暖树(probe / inject / wake / ensure)",
|
||
)
|
||
sub = parser.add_subparsers(dest="cmd", required=True)
|
||
|
||
p_profiles = sub.add_parser("profiles", help="列出内置 profile")
|
||
p_profiles.set_defaults(func=_cmd_profiles)
|
||
|
||
p_probe = sub.add_parser("probe", help="探测冷/暖")
|
||
p_probe.add_argument("--profile", default="wecom")
|
||
p_probe.add_argument("--hwnd", type=lambda s: int(s, 0), default=None)
|
||
p_probe.set_defaults(func=_cmd_probe)
|
||
|
||
p_inject = sub.add_parser(
|
||
"inject",
|
||
help="阶段 B:安全注入探针(不挂钩;成功看 inject_ok + ui_responsive)",
|
||
)
|
||
p_inject.add_argument("--profile", default="wecom")
|
||
p_inject.add_argument("--hwnd", type=lambda s: int(s, 0), default=None)
|
||
p_inject.set_defaults(func=_cmd_inject)
|
||
|
||
p_c2 = sub.add_parser(
|
||
"c2",
|
||
help="阶段 C2:SPI + 注入 + WakeProvider,再 probe(冲暖树)",
|
||
)
|
||
p_c2.add_argument("--profile", default="wecom")
|
||
p_c2.add_argument("--hwnd", type=lambda s: int(s, 0), default=None)
|
||
p_c2.set_defaults(func=_cmd_c2)
|
||
|
||
p_wake = sub.add_parser("wake", help="仅跑唤醒策略(不强制成功)")
|
||
p_wake.add_argument("--profile", default="wecom")
|
||
p_wake.add_argument("--hwnd", type=lambda s: int(s, 0), default=None)
|
||
p_wake.set_defaults(func=_cmd_wake)
|
||
|
||
p_ensure = sub.add_parser(
|
||
"ensure",
|
||
help="probe→wake→probe;wecom 主路径为 n2-wake(DuiLib 暖树)",
|
||
)
|
||
p_ensure.add_argument("--profile", default="wecom")
|
||
p_ensure.add_argument("--hwnd", type=lambda s: int(s, 0), default=None)
|
||
p_ensure.add_argument(
|
||
"--no-raise",
|
||
action="store_true",
|
||
help="仍冷也 exit 0,只打印 JSON",
|
||
)
|
||
p_ensure.set_defaults(func=_cmd_ensure)
|
||
|
||
args = parser.parse_args(argv)
|
||
try:
|
||
return int(args.func(args))
|
||
except Exception as exc:
|
||
print(str(exc), file=sys.stderr)
|
||
return 1
|
||
|
||
|
||
def _cmd_profiles(_args) -> int:
|
||
from .profiles import list_profiles, load_profile
|
||
|
||
out = []
|
||
for pid in list_profiles():
|
||
p = load_profile(pid)
|
||
out.append(
|
||
{
|
||
"id": p.id,
|
||
"description": p.description,
|
||
"window_class": p.window_class,
|
||
"warm_min_findall": p.warm_min_findall,
|
||
"warm_markers": p.warm_markers,
|
||
"wake_strategies": p.wake_strategies,
|
||
}
|
||
)
|
||
_print_json(out)
|
||
return 0
|
||
|
||
|
||
def _cmd_probe(args) -> int:
|
||
from .probe import probe
|
||
|
||
r = probe(args.profile, hwnd=args.hwnd)
|
||
_print_json(r.to_dict())
|
||
return 0 if r.warm else 2
|
||
|
||
|
||
def _cmd_inject(args) -> int:
|
||
from .inject import inject_probe
|
||
|
||
r = inject_probe(args.profile, hwnd=args.hwnd)
|
||
_print_json(r)
|
||
if r.get("inject_ok") and r.get("ui_responsive"):
|
||
return 0
|
||
if r.get("inject_ok") and not r.get("ui_responsive"):
|
||
return 6
|
||
return 5
|
||
|
||
|
||
def _cmd_c2(args) -> int:
|
||
from .c2 import wake_c2
|
||
|
||
r = wake_c2(args.profile, hwnd=args.hwnd)
|
||
_print_json(r)
|
||
if r.get("warm"):
|
||
return 0
|
||
if r.get("ui_responsive") is False:
|
||
return 6
|
||
return 4
|
||
|
||
|
||
def _cmd_wake(args) -> int:
|
||
from .probe import probe
|
||
from .wake import wake
|
||
|
||
steps = wake(args.profile, hwnd=args.hwnd)
|
||
after = probe(args.profile, hwnd=args.hwnd)
|
||
_print_json(
|
||
{
|
||
"steps": [s.to_dict() for s in steps],
|
||
"probe_after": after.to_dict(),
|
||
}
|
||
)
|
||
return 0 if after.warm else 2
|
||
|
||
|
||
def _cmd_ensure(args) -> int:
|
||
from .ensure import ensure_ui_ready
|
||
from .errors import DesktopWakeError
|
||
|
||
try:
|
||
r = ensure_ui_ready(
|
||
args.profile,
|
||
hwnd=args.hwnd,
|
||
raise_on_cold=not args.no_raise,
|
||
)
|
||
except DesktopWakeError as exc:
|
||
print(str(exc), file=sys.stderr)
|
||
return 1
|
||
_print_json(r.to_dict())
|
||
return 0 if r.warm else 2
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(main())
|