Files
skill-template/tools/ui_inspector/kit_wake.py
chendelian 46bc573777
All checks were successful
技能自动化发布 / release (push) Successful in 10s
Release v1.0.66: table default_sort_json for data management
2026-08-02 12:17:55 +08:00

193 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""调用 jiangchang_desktop_wake(只调不复制注入逻辑)。
- 主窗 WeWorkWindow → ``ensure_ui_ready("wecom")``
- 搜索浮层 SearchResultWindow2 → ``ensure_ui_ready("wecom_search")``
未安装 kit 时降级为跳过,不阻断采集。
"""
from __future__ import annotations
import time
from typing import Any, Optional
_CACHE_TTL_SEC = 45.0
# profile -> cache
_caches: dict[str, dict[str, Any]] = {}
_PROFILE_WECOM = "wecom"
_PROFILE_WECOM_SEARCH = "wecom_search"
_THRESHOLDS = {
_PROFILE_WECOM: 80,
_PROFILE_WECOM_SEARCH: 20,
}
def resolve_wake_profile(*, class_name: str = "", title: str = "") -> Optional[str]:
"""返回应调用的 kit profile id;非企微相关则 None。"""
cls = (class_name or "").strip()
title = title or ""
if cls == "SearchResultWindow2":
return _PROFILE_WECOM_SEARCH
if cls == "WeWorkWindow":
return _PROFILE_WECOM
if "WeWork" in cls and ("企业微信" in title or "WeCom" in title or "wecom" in title.lower()):
return _PROFILE_WECOM
return None
def looks_like_wecom(*, class_name: str = "", title: str = "") -> bool:
return resolve_wake_profile(class_name=class_name, title=title) is not None
def kit_available() -> bool:
try:
from jiangchang_desktop_wake import ensure_ui_ready # noqa: F401
return True
except ImportError:
return False
def auto_ensure_if_wecom(
*,
class_name: str = "",
title: str = "",
hwnd: Optional[int] = None,
force: bool = False,
findall_hint: Optional[int] = None,
) -> dict[str, Any]:
"""若目标像企微主窗/搜索浮层则静默 ensure;否则跳过。"""
profile = resolve_wake_profile(class_name=class_name, title=title)
if profile is None:
return {
"applicable": False,
"skipped": True,
"reason": "not_wecom",
"available": kit_available(),
}
warm_min = int(_THRESHOLDS.get(profile, 80))
cache = _caches.setdefault(
profile, {"t": 0.0, "warm": False, "hwnd": 0, "findall": 0}
)
now = time.monotonic()
hint = int(findall_hint) if findall_hint is not None else -1
if (
not force
and cache.get("warm")
and (now - float(cache.get("t") or 0.0)) < _CACHE_TTL_SEC
and (hint < 0 or hint >= warm_min)
):
return {
"applicable": True,
"available": True,
"skipped": True,
"reason": "cache_warm",
"ok": True,
"warm": True,
"wake_applied": False,
"findall": int(cache.get("findall") or 0),
"hwnd": int(cache.get("hwnd") or 0),
"profile": profile,
}
try:
from jiangchang_desktop_wake import ensure_ui_ready
from jiangchang_desktop_wake.errors import DesktopWakeError
except ImportError:
return {
"applicable": True,
"available": False,
"skipped": True,
"reason": "kit_not_installed",
"ok": False,
"profile": profile,
"hint": "请安装 jiangchang-platform-kit>=1.2.6(含 wecom_search)后再采企微",
}
t0 = time.perf_counter()
try:
result = ensure_ui_ready(
profile,
hwnd=int(hwnd) if hwnd else None,
raise_on_cold=True,
)
except DesktopWakeError as exc:
raw = (getattr(exc, "code", None) or "").strip()
code = raw[6:] if raw.startswith("ERROR:") else (raw or "WAKE_FAILED")
return {
"applicable": True,
"available": True,
"skipped": False,
"ok": False,
"warm": False,
"wake_applied": False,
"error_code": code,
"message": str(getattr(exc, "message", None) or exc),
"elapsed_ms": int(round((time.perf_counter() - t0) * 1000)),
"profile": profile,
}
except Exception as exc:
return {
"applicable": True,
"available": True,
"skipped": False,
"ok": False,
"warm": False,
"error_code": "ENSURE_EXCEPTION",
"message": f"{type(exc).__name__}: {exc}",
"elapsed_ms": int(round((time.perf_counter() - t0) * 1000)),
"profile": profile,
}
after = result.probe_after
findall = int(after.findall_count) if after is not None else 0
report = {
"applicable": True,
"available": True,
"skipped": False,
"ok": bool(result.warm),
"warm": bool(result.warm),
"wake_applied": bool(result.wake_applied),
"findall": findall,
"hwnd": int(result.hwnd) if result.hwnd else 0,
"elapsed_ms": int(round((time.perf_counter() - t0) * 1000)),
"profile": profile,
"markers_found": list(after.markers_found) if after is not None else [],
}
if result.warm:
cache["t"] = now
cache["warm"] = True
cache["hwnd"] = report["hwnd"]
cache["findall"] = findall
else:
cache["warm"] = False
return report
def format_kit_wake_line(report: Optional[dict[str, Any]]) -> str:
if not report:
return "kit_wake: (none)"
if not report.get("applicable"):
return "kit_wake: n/a (非企微)"
if report.get("reason") == "kit_not_installed":
return "kit_wake: 未安装 platform-kit(企微可能冷树)"
prof = report.get("profile") or "?"
if report.get("skipped") and report.get("reason") == "cache_warm":
return (
f"kit_wake[{prof}]: cache warm=True findall={report.get('findall')} "
f"hwnd={report.get('hwnd')}"
)
if report.get("ok"):
return (
f"kit_wake[{prof}]: warm={report.get('warm')} "
f"wake_applied={report.get('wake_applied')} "
f"findall={report.get('findall')} elapsed_ms={report.get('elapsed_ms')}"
)
return (
f"kit_wake[{prof}]: FAILED code={report.get('error_code')} "
f"msg={report.get('message')}"
)