Skip to content

Commit c4e140d

Browse files
committed
Add clear-then-type field entry (Playwright fill idiom)
1 parent cc7cd78 commit c4e140d

15 files changed

Lines changed: 297 additions & 2 deletions

File tree

README/WHATS_NEW_zh-CN.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# 本次更新 — AutoControl
22

3+
## 本次更新 (2026-06-23) — 清空再输入字段
4+
5+
可靠地设定文本字段的值(Playwright 的 `fill` 惯用法)。完整参考:[`docs/source/Zh/doc/new_features/v117_features_doc.rst`](../docs/source/Zh/doc/new_features/v117_features_doc.rst)
6+
7+
- **`set_field_text` / `plan_field_set`**(`AC_set_field_text`):先前没有单一的「聚焦 → 清空 → 设值」基本元件,且 `write` 对 emoji/CJK 会抛异常。本功能清空字段(全选 + 删除)后再输入文本——可选择通过剪贴板(`paste=True`),这是 `write` 无法处理之 Unicode 的安全途径。`modifier` 为平台命令键(`ctrl`/`command`)。纯计划 + 可注入 sink、确定。
8+
39
## 本次更新 (2026-06-22) — 多路径点鼠标手势
410

511
让指针沿着路径点折线移动或拖曳。完整参考:[`docs/source/Zh/doc/new_features/v116_features_doc.rst`](../docs/source/Zh/doc/new_features/v116_features_doc.rst)

README/WHATS_NEW_zh-TW.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# 本次更新 — AutoControl
22

3+
## 本次更新 (2026-06-23) — 清空再輸入欄位
4+
5+
可靠地設定文字欄位的值(Playwright 的 `fill` 慣用法)。完整參考:[`docs/source/Zh/doc/new_features/v117_features_doc.rst`](../docs/source/Zh/doc/new_features/v117_features_doc.rst)
6+
7+
- **`set_field_text` / `plan_field_set`**(`AC_set_field_text`):先前沒有單一的「聚焦 → 清空 → 設值」基本元件,且 `write` 對 emoji/CJK 會拋例外。本功能清空欄位(全選 + 刪除)後再輸入文字——可選擇透過剪貼簿(`paste=True`),這是 `write` 無法處理之 Unicode 的安全途徑。`modifier` 為平台指令鍵(`ctrl`/`command`)。純計畫 + 可注入 sink、具決定性。
8+
39
## 本次更新 (2026-06-22) — 多路徑點滑鼠手勢
410

511
讓指標沿著路徑點折線移動或拖曳。完整參考:[`docs/source/Zh/doc/new_features/v116_features_doc.rst`](../docs/source/Zh/doc/new_features/v116_features_doc.rst)

WHATS_NEW.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# What's New — AutoControl
22

3+
## What's new (2026-06-23) — Clear-Then-Type Field Entry
4+
5+
Reliably set a text field's value (the Playwright `fill` idiom). Full reference: [`docs/source/Eng/doc/new_features/v117_features_doc.rst`](docs/source/Eng/doc/new_features/v117_features_doc.rst).
6+
7+
- **`set_field_text` / `plan_field_set`** (`AC_set_field_text`): there was no single "focus → clear → set value" primitive, and `write` raises on emoji/CJK. This clears the field (select-all + delete) then enters the text — optionally via the clipboard (`paste=True`) which is the Unicode-safe path `write` can't do. `modifier` is the platform command key (`ctrl`/`command`). Pure-planning + injectable sink, deterministic.
8+
39
## What's new (2026-06-22) — Multi-Waypoint Mouse Gestures
410

511
Move or drag the pointer through a polyline of waypoints. Full reference: [`docs/source/Eng/doc/new_features/v116_features_doc.rst`](docs/source/Eng/doc/new_features/v116_features_doc.rst).
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
Clear-Then-Type Field Entry
2+
===========================
3+
4+
Setting a field's value reliably means *clearing* whatever is there first, then
5+
entering the new text — otherwise automation appends to or corrupts the existing
6+
content. The framework has ``write`` (types, but raises on emoji / CJK / chars
7+
outside the layout table) and ``set_clipboard`` / ``hotkey`` separately, but no
8+
single "focus → clear → set value" primitive and no paste strategy for text that
9+
``write`` cannot type. This adds the Playwright ``fill`` idiom.
10+
11+
:func:`plan_field_set` builds the deterministic op-plan (pure, unit-testable);
12+
:func:`set_field_text` dispatches it through an injectable ``sink`` so it is
13+
tested without real input. Imports no ``PySide6``.
14+
15+
Headless API
16+
------------
17+
18+
.. code-block:: python
19+
20+
from je_auto_control import set_field_text, plan_field_set
21+
22+
set_field_text("new value") # select-all, delete, type
23+
set_field_text("café 🚀", paste=True) # via clipboard (Unicode-safe)
24+
set_field_text("appended", clear="none") # no clear, just type
25+
set_field_text("", paste=True, modifier="command") # macOS
26+
27+
plan_field_set("hi")
28+
# [{'op': 'hotkey', 'keys': ['ctrl', 'a']},
29+
# {'op': 'key', 'key': 'delete'},
30+
# {'op': 'type', 'text': 'hi'}]
31+
32+
``clear`` is ``"select_all"`` (the ``modifier``+A then Delete clear) or
33+
``"none"``. ``paste=True`` enters the text through the clipboard (``modifier``+V)
34+
— the reliable path for Unicode / emoji / CJK that ``write`` cannot type — rather
35+
than typing key by key. ``modifier`` is the platform command key (``"ctrl"``; use
36+
``"command"`` on macOS). An unknown ``clear`` mode raises ``ValueError``.
37+
38+
Executor commands
39+
-----------------
40+
41+
``AC_set_field_text`` takes ``text`` plus ``clear`` / ``paste`` / ``modifier`` and
42+
returns ``{ops, plan}``. It is exposed as the MCP tool ``ac_set_field_text`` and
43+
as a Script Builder command under **Keyboard**.

docs/source/Eng/eng_index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ Comprehensive guides for all AutoControl features.
139139
doc/new_features/v114_features_doc
140140
doc/new_features/v115_features_doc
141141
doc/new_features/v116_features_doc
142+
doc/new_features/v117_features_doc
142143
doc/ocr_backends/ocr_backends_doc
143144
doc/observability/observability_doc
144145
doc/operations_layer/operations_layer_doc
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
清空再輸入欄位
2+
==============
3+
4+
可靠地設定欄位值,必須先*清空*既有內容再輸入新文字——否則自動化會附加到或破壞既有內容。框架分別有 ``write``
5+
(可輸入,但對 emoji / CJK / 不在版面表內的字元會拋例外)與 ``set_clipboard`` / ``hotkey``,但沒有單一的
6+
「聚焦 → 清空 → 設值」基本元件,也沒有可輸入 ``write`` 無法處理之文字的貼上策略。本功能加入 Playwright 的
7+
``fill`` 慣用法。
8+
9+
:func:`plan_field_set` 建立決定性的操作計畫(純函式、可單元測試);:func:`set_field_text` 透過可注入的 ``sink``
10+
派發,因此可在無真實輸入下測試。不匯入 ``PySide6``。
11+
12+
無頭 API
13+
--------
14+
15+
.. code-block:: python
16+
17+
from je_auto_control import set_field_text, plan_field_set
18+
19+
set_field_text("new value") # 全選、刪除、輸入
20+
set_field_text("café 🚀", paste=True) # 透過剪貼簿(Unicode 安全)
21+
set_field_text("appended", clear="none") # 不清空,直接輸入
22+
set_field_text("", paste=True, modifier="command") # macOS
23+
24+
plan_field_set("hi")
25+
# [{'op': 'hotkey', 'keys': ['ctrl', 'a']},
26+
# {'op': 'key', 'key': 'delete'},
27+
# {'op': 'type', 'text': 'hi'}]
28+
29+
``clear`` 為 ``"select_all"``(``modifier``+A 再 Delete 的清空)或 ``"none"``。``paste=True`` 透過剪貼簿
30+
(``modifier``+V)輸入文字——這是 ``write`` 無法輸入之 Unicode / emoji / CJK 的可靠途徑——而非逐鍵輸入。
31+
``modifier`` 為平台指令鍵(``"ctrl"``;macOS 用 ``"command"``)。未知的 ``clear`` 模式會拋出 ``ValueError``。
32+
33+
執行器命令
34+
----------
35+
36+
``AC_set_field_text`` 接受 ``text`` 以及 ``clear`` / ``paste`` / ``modifier``,並回傳 ``{ops, plan}``。它以
37+
MCP 工具 ``ac_set_field_text`` 以及 Script Builder 中 **Keyboard** 分類下的命令提供。

docs/source/Zh/zh_index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ AutoControl 所有功能的完整使用指南。
139139
doc/new_features/v114_features_doc
140140
doc/new_features/v115_features_doc
141141
doc/new_features/v116_features_doc
142+
doc/new_features/v117_features_doc
142143
doc/ocr_backends/ocr_backends_doc
143144
doc/observability/observability_doc
144145
doc/operations_layer/operations_layer_doc

je_auto_control/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@
255255
from je_auto_control.utils.mouse_path import (
256256
drag_path, move_along_path, path_easings, plan_path,
257257
)
258+
# Clear-then-type a text field (Playwright `fill` idiom; paste for Unicode)
259+
from je_auto_control.utils.field_entry import plan_field_set, set_field_text
258260
# CI workflow annotations (GitHub Actions)
259261
from je_auto_control.utils.ci_annotations import (
260262
emit_annotations, format_annotation,
@@ -1029,6 +1031,8 @@ def start_autocontrol_gui(*args, **kwargs):
10291031
"move_along_path",
10301032
"drag_path",
10311033
"path_easings",
1034+
"plan_field_set",
1035+
"set_field_text",
10321036
"emit_annotations", "format_annotation",
10331037
"ClipboardHistory", "default_clipboard_history",
10341038
"analyze_heal_log", "heal_stats", "scan_secrets",

je_auto_control/gui/script_builder/command_schema.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,18 @@ def _add_keyboard_specs(specs: List[CommandSpec]) -> None:
162162
),
163163
description="Type text with randomized per-key delays.",
164164
))
165+
specs.append(CommandSpec(
166+
"AC_set_field_text", "Keyboard", "Set Field Text",
167+
fields=(
168+
FieldSpec("text", FieldType.STRING, placeholder="new value"),
169+
FieldSpec("clear", FieldType.ENUM, choices=("select_all", "none"),
170+
optional=True, default="select_all"),
171+
FieldSpec("paste", FieldType.BOOL, optional=True, default=False),
172+
FieldSpec("modifier", FieldType.STRING, optional=True,
173+
default="ctrl", placeholder="ctrl | command"),
174+
),
175+
description="Clear the focused field then enter text (paste for Unicode).",
176+
))
165177
specs.append(CommandSpec(
166178
"AC_hotkey", "Keyboard", "Hotkey",
167179
fields=(

je_auto_control/utils/executor/action_executor.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3092,6 +3092,14 @@ def _drag_path(waypoints: Any, button: str = "mouse_left",
30923092
per_segment_steps=int(per_segment_steps))
30933093

30943094

3095+
def _set_field_text(text: str, clear: str = "select_all", paste: Any = False,
3096+
modifier: str = "ctrl") -> Dict[str, Any]:
3097+
"""Adapter: clear the focused field and enter text."""
3098+
from je_auto_control.utils.field_entry import set_field_text
3099+
return set_field_text(text, clear=clear, paste=bool(paste),
3100+
modifier=modifier)
3101+
3102+
30953103
def _cas_put(name: str, key: str, value: Any,
30963104
expected_version: Any = None) -> Dict[str, Any]:
30973105
"""Adapter: optimistic put into a named versioned store."""
@@ -4789,6 +4797,7 @@ def __init__(self):
47894797
"AC_checksum_digit": _checksum_digit,
47904798
"AC_move_along_path": _move_along_path,
47914799
"AC_drag_path": _drag_path,
4800+
"AC_set_field_text": _set_field_text,
47924801
"AC_detect_drift": _detect_drift,
47934802
"AC_categorical_drift": _categorical_drift,
47944803
"AC_diff_rows": _diff_rows,

0 commit comments

Comments
 (0)