use-computer-cli 0.3.1__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/PKG-INFO +1 -1
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/pyproject.toml +1 -1
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/runner.py +1 -1
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/selectors.py +11 -6
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_blind_spots.py +15 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/.gitignore +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/LICENSE +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/README.md +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/__init__.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/accessibility/__init__.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/accessibility/atspi.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/accessibility/ax.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/accessibility/base.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/accessibility/roles.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/accessibility/uia.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/actions.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/backends/__init__.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/backends/base.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/backends/local.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/backends/vnc.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/cli.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/compare.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/config.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/coordinates.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/errors.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/keys.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/prune.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/render.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/skill/SKILL.md +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/skill/__init__.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/tree.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/__init__.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/conftest.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/fake_backend.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/fake_provider.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_atspi_hint.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_backends.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_cli.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_compare.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_config.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_config_init.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_coordinates.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_elements.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_keys.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_prune.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_render.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_runner.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_selectors.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_skill.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_skill_is_true.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_trusting_a_result.py +0 -0
- {use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/tests/test_which_window.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: use-computer-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Execute input on a screen for computer-use agents: move, click, drag, scroll, type, key, screenshot.
|
|
5
5
|
Project-URL: Homepage, https://github.com/applica-software-guru/use-computer
|
|
6
6
|
Author: Bruno Fortunato
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "use-computer-cli"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.2"
|
|
8
8
|
description = "Execute input on a screen for computer-use agents: move, click, drag, scroll, type, key, screenshot."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -681,7 +681,7 @@ class Session:
|
|
|
681
681
|
|
|
682
682
|
# On the raw snapshot, before anything of ours removes a child: a region hidden by our
|
|
683
683
|
# own pruning is not a region the platform failed to describe.
|
|
684
|
-
root = mark_unexposed(root)
|
|
684
|
+
root = mark_unexposed(root, depth)
|
|
685
685
|
exposed_children = bool(root.children)
|
|
686
686
|
|
|
687
687
|
if action.of is not None:
|
|
@@ -182,7 +182,7 @@ def active_window(entries: Sequence[WindowInfo]) -> WindowInfo:
|
|
|
182
182
|
)
|
|
183
183
|
|
|
184
184
|
|
|
185
|
-
def mark_unexposed(node: UINode) -> UINode:
|
|
185
|
+
def mark_unexposed(node: UINode, depth_limit: int | None = None) -> UINode:
|
|
186
186
|
"""Say where a node's children do not account for the node's own area.
|
|
187
187
|
|
|
188
188
|
A tree can be rich, correct, and silent about the only region that matters. Measured in GNOME
|
|
@@ -195,13 +195,15 @@ def mark_unexposed(node: UINode) -> UINode:
|
|
|
195
195
|
served worst, because an agent could not tell it from a window that exposes everything.
|
|
196
196
|
|
|
197
197
|
This runs on the **raw** snapshot, before pruning: a region hidden by our own pruning is not a
|
|
198
|
-
region the platform failed to describe.
|
|
198
|
+
region the platform failed to describe. For the same reason ``depth_limit`` is honoured -- at
|
|
199
|
+
the depth the snapshot stopped at, every node looks childless, and marking there would report
|
|
200
|
+
the caller's own limit as a property of the application.
|
|
199
201
|
"""
|
|
200
|
-
marked, _ = _mark(node)
|
|
202
|
+
marked, _ = _mark(node, depth_limit)
|
|
201
203
|
return marked
|
|
202
204
|
|
|
203
205
|
|
|
204
|
-
def _mark(node: UINode) -> tuple[UINode, bool]:
|
|
206
|
+
def _mark(node: UINode, depth_limit: int | None, depth: int = 0) -> tuple[UINode, bool]:
|
|
205
207
|
"""Mark this subtree, and say whether anything in it carries a mark.
|
|
206
208
|
|
|
207
209
|
Only the **innermost** node is marked. A canvas nested three panels deep would otherwise be
|
|
@@ -211,11 +213,14 @@ def _mark(node: UINode) -> tuple[UINode, bool]:
|
|
|
211
213
|
children = []
|
|
212
214
|
deeper = False
|
|
213
215
|
for child in node.children:
|
|
214
|
-
marked, found = _mark(child)
|
|
216
|
+
marked, found = _mark(child, depth_limit, depth + 1)
|
|
215
217
|
children.append(marked)
|
|
216
218
|
deeper = deeper or found
|
|
217
219
|
kids = tuple(children)
|
|
218
|
-
|
|
220
|
+
# A node whose children were cut by the caller's own `--depth` has no evidence either way:
|
|
221
|
+
# saying the platform describes nothing there would be BUG-011 in a second place.
|
|
222
|
+
truncated_here = depth_limit is not None and depth >= depth_limit - 1
|
|
223
|
+
region = None if deeper or truncated_here else _blind_spot(node, kids)
|
|
219
224
|
return (
|
|
220
225
|
node.model_copy(update={"children": kids, "unexposed": region}),
|
|
221
226
|
deeper or region is not None,
|
|
@@ -7,6 +7,8 @@ because the provider worked and returned plenty.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
from collections.abc import Iterator
|
|
11
|
+
|
|
10
12
|
from tests.fake_provider import node
|
|
11
13
|
from use_computer.render import TREE_LEGEND
|
|
12
14
|
from use_computer.render import tree as render_tree
|
|
@@ -155,3 +157,16 @@ def test_the_marker_is_rendered_and_the_legend_explains_it() -> None:
|
|
|
155
157
|
text = render_tree(mark_unexposed(drawing_window()))
|
|
156
158
|
assert "?unexposed" in TREE_LEGEND
|
|
157
159
|
assert "?unexposed 163,106 1757x885" in text
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def test_a_depth_limit_does_not_manufacture_a_blind_spot() -> None:
|
|
163
|
+
# At the depth the snapshot stopped at every node looks childless. Marking there would report
|
|
164
|
+
# the caller's own limit as a property of the application -- the same mistake as BUG-011.
|
|
165
|
+
marked = mark_unexposed(drawing_window(), depth_limit=2)
|
|
166
|
+
assert all(found.unexposed is None for found in _every(marked))
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _every(node: UINode) -> Iterator[UINode]:
|
|
170
|
+
yield node
|
|
171
|
+
for child in node.children:
|
|
172
|
+
yield from _every(child)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{use_computer_cli-0.3.1 → use_computer_cli-0.3.2}/src/use_computer/accessibility/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|