feat(desktop-wake): add WeCom UIA warm-tree and ship n2-wake in 1.2.3
All checks were successful
Publish Python Package to Gitea / publish (push) Successful in 29s
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>
This commit is contained in:
156
src/jiangchang_desktop_wake/__main__.py
Normal file
156
src/jiangchang_desktop_wake/__main__.py
Normal file
@@ -0,0 +1,156 @@
|
||||
"""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())
|
||||
Reference in New Issue
Block a user