feat: prepare 2.2.0 with UI and execution fixes

Add dark theme, richer Markdown and readable plugin results.
Improve Android input evidence, response integrity and diagnostics.
Unify lifecycle, guidance receipts and evidence sources across clients.
Keep direct action dispatch without an added AI quota approval layer.
Align version metadata at 2.2.0 and bundle Helper 1.2.2.

Validation: 3063 backend tests before the version bump; 44 after.
Frontend: 317 tests and production build passed.
This commit is contained in:
chenmingxuan committed 2026-10-26 00:44:13 +08:00
1 parent 83bcfd54d5
commit fac4ccb760
146 files changed
+5689 -2033

No files matched your search

+80
View File
@@ -0,0 +1,80 @@
"""Keep editable values separate from accessibility hints and visual labels."""
from typing import Any
def _boolean(node: dict, *keys: str) -> bool | None:
for key in keys:
value = node.get(key)
if isinstance(value, bool):
return value
if isinstance(value, str) and value.lower() in {"true", "false"}:
return value.lower() == "true"
return None
def input_state(node: dict[str, Any]) -> dict[str, Any]:
"""Return value evidence only for an actual editable node, never OCR text.
Equality with a hint is ambiguous on older backends: an application can
legitimately contain that exact value. Only an explicit showing-hint flag
proves that nonempty text is a placeholder.
"""
editable = _boolean(node, "editable", "isEditable")
class_name = str(node.get("class") or node.get("className") or "").lower()
if editable is None and "edittext" in class_name:
editable = True
if editable is not True:
return {}
hint = str(node.get("hint") or node.get("hintText") or node.get("hint-text") or "")
showing = _boolean(node, "showing_hint", "showing-hint-text", "isShowingHintText", "is_hint")
raw = node.get("text")
value = raw if isinstance(raw, str) else None
if showing is True:
hint = hint or value or ""
value = ""
status = "empty"
elif value is None:
status = "unknown"
elif not value:
status = "empty"
elif hint and value == hint and showing is not False:
value = None
status = "unknown"
else:
status = "present"
return {
"editable": True,
"input_value": value,
"input_value_state": status,
"hint": hint,
"showing_hint": showing,
"focused": _boolean(node, "focused"),
"password": _boolean(node, "password"),
}
def verify_input(elements: list[dict], target: dict | None = None) -> str:
"""Verify value presence against a fresh tree, without returning its value.
Resource identity wins over focus. Unidentifiable, masked, or unsupported
inputs remain unknown; visual text elsewhere cannot establish input success.
"""
candidates = []
target = target or {}
resource_id = target.get("target_resource_id")
for element in elements:
state = input_state(element) if "input_value_state" not in element else element
if not state:
continue
if resource_id:
if (element.get("resource_id") or element.get("resource-id")) == resource_id:
candidates.append(state)
elif state.get("focused") is True:
candidates.append(state)
if len(candidates) != 1:
return "unknown"
state = candidates[0]
if state.get("password") is True and state.get("input_value_state") != "empty":
return "unknown"
return str(state["input_value_state"])