scapkit-computer-use 0.0.3__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.
Files changed (25) hide show
  1. scapkit_computer_use-0.0.3/LICENSE +21 -0
  2. scapkit_computer_use-0.0.3/MANIFEST.in +17 -0
  3. scapkit_computer_use-0.0.3/PKG-INFO +263 -0
  4. scapkit_computer_use-0.0.3/README.md +239 -0
  5. scapkit_computer_use-0.0.3/native_code/osx/include/capture.h +18 -0
  6. scapkit_computer_use-0.0.3/native_code/osx/include/control.h +17 -0
  7. scapkit_computer_use-0.0.3/native_code/osx/include/display.h +7 -0
  8. scapkit_computer_use-0.0.3/native_code/osx/src/capture.m +595 -0
  9. scapkit_computer_use-0.0.3/native_code/osx/src/control.c +276 -0
  10. scapkit_computer_use-0.0.3/native_code/osx/src/display.c +70 -0
  11. scapkit_computer_use-0.0.3/native_code/osx/src/ext.c +50 -0
  12. scapkit_computer_use-0.0.3/pyproject.toml +49 -0
  13. scapkit_computer_use-0.0.3/setup.cfg +4 -0
  14. scapkit_computer_use-0.0.3/setup.py +60 -0
  15. scapkit_computer_use-0.0.3/src/scapkit_computer_use/__init__.py +117 -0
  16. scapkit_computer_use-0.0.3/src/scapkit_computer_use/process.py +539 -0
  17. scapkit_computer_use-0.0.3/src/scapkit_computer_use/py.typed +0 -0
  18. scapkit_computer_use-0.0.3/src/scapkit_computer_use/screen_capture_kit/__init__.py +331 -0
  19. scapkit_computer_use-0.0.3/src/scapkit_computer_use/screen_capture_kit/_scapkit.pyi +212 -0
  20. scapkit_computer_use-0.0.3/src/scapkit_computer_use/screen_capture_kit/keys.py +110 -0
  21. scapkit_computer_use-0.0.3/src/scapkit_computer_use/screen_capture_kit/types.py +64 -0
  22. scapkit_computer_use-0.0.3/src/scapkit_computer_use.egg-info/PKG-INFO +263 -0
  23. scapkit_computer_use-0.0.3/src/scapkit_computer_use.egg-info/SOURCES.txt +23 -0
  24. scapkit_computer_use-0.0.3/src/scapkit_computer_use.egg-info/dependency_links.txt +1 -0
  25. scapkit_computer_use-0.0.3/src/scapkit_computer_use.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kevin Chen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,17 @@
1
+ include LICENSE
2
+ include README.md
3
+ include pyproject.toml
4
+ include setup.py
5
+
6
+ recursive-include native_code/osx *.c *.h *.m
7
+ recursive-include src *.pyi py.typed
8
+
9
+ exclude AGENTS.md
10
+ exclude .gitignore
11
+ prune .venv
12
+ prune .github
13
+ prune .claude
14
+ prune .vscode
15
+ prune tests
16
+ prune build
17
+ prune dist
@@ -0,0 +1,263 @@
1
+ Metadata-Version: 2.4
2
+ Name: scapkit_computer_use
3
+ Version: 0.0.3
4
+ Summary: A Python library for computer use
5
+ Author-email: Kevin Chen <1354016594@qq.com>
6
+ License-Expression: MIT
7
+ Project-URL: Home-page, https://github.com/czf0613/computer_use_py
8
+ Keywords: computer use,automation
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Operating System :: MacOS :: MacOS X
11
+ Classifier: Programming Language :: C
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Programming Language :: Python :: Implementation :: CPython
19
+ Classifier: Programming Language :: Python :: Free Threading :: 2 - Beta
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Dynamic: license-file
24
+
25
+ # scapkit_computer_use
26
+
27
+ 跨平台桌面自动化 Python 库,提供屏幕截图、鼠标控制、键盘输入、剪贴板和 subprocess 操作。
28
+
29
+ 当前支持 macOS;所用 ScreenCaptureKit API 的最低系统版本为 macOS 12.3。
30
+ 官方预编译 wheel 仅提供 macOS 15+ arm64 版本,这不是源码安装的系统或架构限制。
31
+ Windows 目前提供纯 Python subprocess 接口(源码安装);桌面控制扩展仍在开发中。
32
+
33
+ ## 安装
34
+
35
+ 需要 Python >= 3.10;支持 CPython 3.13/3.14 的 free-threaded 构建,通过 PyPI 安装:
36
+
37
+ ```bash
38
+ pip install scapkit_computer_use
39
+ ```
40
+
41
+ 较早的 macOS(12.3+)或 Intel Mac 可从源码构建,需要安装 Xcode Command Line
42
+ Tools,并使用包含 ScreenCaptureKit 的 macOS SDK:
43
+
44
+ ```bash
45
+ pip install --no-binary=scapkit_computer_use scapkit_computer_use
46
+ ```
47
+
48
+ 旧系统和 Intel Mac 的实际运行尚未验证;当前 CI 运行环境为 macOS 15 / 26 arm64。
49
+
50
+ 或使用 [uv](https://github.com/astral-sh/uv):
51
+
52
+ ```bash
53
+ uv add scapkit_computer_use
54
+ ```
55
+
56
+ ## 权限
57
+
58
+ macOS 下需要授予以下系统权限:
59
+
60
+ - **辅助功能 (Accessibility)**:鼠标、键盘控制
61
+ - **屏幕录制 (Screen Recording)**:屏幕截图
62
+
63
+ ```python
64
+ from scapkit_computer_use import check_permission, open_permission_settings
65
+
66
+ if not check_permission("Accessibility"):
67
+ await open_permission_settings("Accessibility")
68
+ ```
69
+
70
+ ## 功能
71
+
72
+ ### 显示器信息
73
+
74
+ 所有坐标和尺寸均使用 **point**(逻辑分辨率),而非物理像素。物理像素 = point × scale_factor。API 中的所有位置参数(鼠标移动、点击等)同样使用 point 坐标。
75
+
76
+ ```python
77
+ from scapkit_computer_use import list_displays
78
+
79
+ displays = list_displays()
80
+ # [{"id": 2, "x": 0, "y": 0, "width": 1920, "height": 1080, "scale_factor": 2.0, "is_main": True}]
81
+ # width/height 为 point 单位,实际物理像素为 1920×2 = 3840, 1080×2 = 2160
82
+ ```
83
+
84
+ ### 鼠标控制
85
+
86
+ ```python
87
+ from scapkit_computer_use import (
88
+ get_mouse_position, move_mouse, move_mouse_relative,
89
+ mouse_click, mouse_scroll, mouse_drag
90
+ )
91
+
92
+ # 获取当前位置
93
+ pos = get_mouse_position() # {"x": 100, "y": 200}
94
+
95
+ # 平滑移动(绝对坐标)
96
+ await move_mouse({"x": 500, "y": 300})
97
+
98
+ # 瞬间移动
99
+ await move_mouse({"x": 500, "y": 300}, smooth=False)
100
+
101
+ # 相对移动(生成 delta 事件,兼容游戏等指针锁定场景)
102
+ await move_mouse_relative({"dx": 100, "dy": 50})
103
+
104
+ # 瞬间相对移动
105
+ await move_mouse_relative({"dx": 100, "dy": 50}, smooth=False)
106
+
107
+ # 点击
108
+ await mouse_click("left")
109
+ await mouse_click("right")
110
+
111
+ # 滚动(方向为内容移动方向)
112
+ await mouse_scroll("down", 3)
113
+ await mouse_scroll("up", 3)
114
+
115
+ # 拖拽到目标位置
116
+ await mouse_drag({"x": 800, "y": 600})
117
+ ```
118
+
119
+ > **注意:** `move_mouse` 使用 `CGWarpMouseCursorPosition`,不会生成鼠标移动的 delta 事件,因此不适用于依赖原始鼠标 delta 的应用(如游戏中的指针锁定)。这类场景请使用 `move_mouse_relative`,它通过 `CGEventCreateMouseEvent` 发送包含 `deltaX/deltaY` 的 `kCGEventMouseMoved` 事件。
120
+
121
+ ### 键盘输入
122
+
123
+ 使用跨平台的按键名称,无需关心底层键码:
124
+
125
+ ```python
126
+ from scapkit_computer_use import keyboard_click, key_combo
127
+
128
+ # 按下并释放一个键
129
+ await keyboard_click("a")
130
+ await keyboard_click("return")
131
+
132
+ # 组合键
133
+ await key_combo("c", {"command"}) # Cmd+C 复制
134
+ await key_combo("v", {"command"}) # Cmd+V 粘贴
135
+ await key_combo("z", {"command", "shift"}) # Cmd+Shift+Z 重做
136
+ ```
137
+
138
+ 支持的按键名称包括:`a`-`z`、`0`-`9`、`return`、`tab`、`space`、`delete`、`escape`、`f1`-`f20`、`up`/`down`/`left`/`right` 等。完整列表见源码 `screen_capture_kit/keys.py`。
139
+
140
+ ### 剪贴板
141
+
142
+ ```python
143
+ from scapkit_computer_use import set_clipboard, get_clipboard, clipboard_paste
144
+
145
+ await set_clipboard("你好世界")
146
+ text = await get_clipboard() # "你好世界"
147
+
148
+ # 直接粘贴到当前输入框(模拟 Cmd+V)
149
+ await clipboard_paste()
150
+ ```
151
+
152
+ ### 屏幕截图
153
+
154
+ 基于 macOS ScreenCaptureKit,支持全分辨率 Retina 截图:
155
+
156
+ ```python
157
+ from scapkit_computer_use import (
158
+ list_displays, start_capture, stop_capture,
159
+ current_frame_jpg, current_frame_bgra
160
+ )
161
+
162
+ displays = list_displays()
163
+ main = next(d for d in displays if d["is_main"])
164
+
165
+ # 启动截图流
166
+ handle = await start_capture(main["id"])
167
+
168
+ # 获取 JPEG 格式(可设置质量 0-100)
169
+ jpg_bytes = await current_frame_jpg(handle, quality=80)
170
+
171
+ # 获取原始 BGRA 像素数据
172
+ frame = await current_frame_bgra(handle)
173
+ # {"data": bytes, "width": 3840, "height": 2160, "bytes_per_row": 15360}
174
+
175
+ # 停止截图
176
+ await stop_capture(handle)
177
+ ```
178
+
179
+ ### 执行 subprocess
180
+
181
+ `run_subprocess()` 是异步函数。可执行文件与参数分开传入;执行 shell 命令时,
182
+ 把 shell 作为可执行文件,并传入 `-c` 或 `/c` 等参数。
183
+
184
+ ```python
185
+ import sys
186
+ from scapkit_computer_use import run_subprocess
187
+
188
+ result = await run_subprocess(
189
+ sys.executable,
190
+ ["-c", "import os; print(os.getenv('EXAMPLE'))"],
191
+ cwd="/path/to/workdir",
192
+ env={"EXAMPLE": "你好"},
193
+ )
194
+ print(result.returncode, result.stdout, result.stderr)
195
+ # 也可以解包:returncode, stdout, stderr = result
196
+
197
+ result = await run_subprocess("/bin/zsh", ["-c", "printf '%s' hello"])
198
+ # Windows 示例:await run_subprocess("cmd.exe", ["/c", "echo hello"])
199
+ ```
200
+
201
+ | 参数 | 含义 |
202
+ | --- | --- |
203
+ | `executable` | 可执行文件名称或路径;名称通过加载后的环境 PATH 查找 |
204
+ | `args=()` | 参数序列,保留空格和特殊字符;不会自动拼接成 shell 命令 |
205
+ | `cwd=None` | 工作目录,默认当前工作目录 |
206
+ | `env=None` | 在 shell 环境上新增或覆盖的变量,均为字符串 |
207
+ | `use_stream=False` | 默认等待退出,返回退出码和两路文本;为 True 时返回运行中的 `SubprocessStream` |
208
+ | `encoding=None` | macOS 默认 UTF-8;Windows 默认控制台输出代码页,无控制台时用系统 OEM 代码页 |
209
+ | `errors="strict"` | 解码错误默认抛异常;可指定 `"replace"` 保留其他可解码内容 |
210
+
211
+ 环境来自重新加载的系统/用户 shell 配置,**不继承当前 Python 进程的环境变量**。
212
+ macOS 读取账户登录 shell 的 login/interactive 配置;Windows 从系统和用户配置构造环境,
213
+ 再执行 cmd AutoRun。调用方传入的 `env` 最后合并。详情见 [进程执行说明](https://github.com/czf0613/computer_use_py/blob/master/docs/subprocess.md)。
214
+
215
+ 流式 stdin 接收字符串,stdout/stderr 支持异步 `read()`、`readline()` 和逐行迭代:
216
+
217
+ ```python
218
+ import asyncio
219
+
220
+ process = await run_subprocess(
221
+ sys.executable, ["-u", "-c", "import sys; print(input()); print('done', file=sys.stderr)"],
222
+ use_stream=True,
223
+ )
224
+
225
+ async def feed():
226
+ process.stdin.write("你好\n")
227
+ await process.stdin.drain()
228
+ process.stdin.close()
229
+
230
+ async def consume(stream):
231
+ async for line in stream:
232
+ print(line, end="")
233
+
234
+ await asyncio.gather(feed(), consume(process.stdout), consume(process.stderr))
235
+ returncode = await process.wait()
236
+ # 或:stdout, stderr = await process.communicate("你好\n")
237
+ ```
238
+
239
+ Windows 程序可能输出 UTF-8、GBK、ANSI 或 UTF-16;无法通用地自动判断。
240
+ 例如使用 `encoding="utf-8"`、`encoding="gbk"` 或 `encoding="utf-16-le"` 明确指定。
241
+ 同一编码用于该进程的三路文本流;跨块中文由增量解码器处理,换行统一为 `\n`。
242
+
243
+ ## 开发
244
+
245
+ ```bash
246
+ # 构建 C 扩展
247
+ uv run setup.py build_ext --inplace
248
+
249
+ # 构建带合成测试支持的扩展,运行不操作桌面的测试
250
+ SCAPKIT_TESTING=1 uv run setup.py build_ext --inplace --force
251
+ uv run pytest tests/test_native_validation.py tests/test_native_arguments.py tests/test_native_capture.py tests/test_capture_lifecycle.py tests/test_async_safety.py tests/test_process.py
252
+ ```
253
+
254
+ 构建环境、并发约定和测试边界见 [开发文档](https://github.com/czf0613/computer_use_py/blob/master/docs/development.md),
255
+ 自动化发布见 [发布文档](https://github.com/czf0613/computer_use_py/blob/master/docs/releasing.md),Codex 接手约定见 [AGENTS.md](https://github.com/czf0613/computer_use_py/blob/master/AGENTS.md),
256
+ 本次质量检查和验证边界见 [审查记录](https://github.com/czf0613/computer_use_py/blob/master/docs/code-review.md)。
257
+
258
+ `stop_capture()` 可以重复调用;停止后的新读帧返回 `None`。启动/停止超时抛出
259
+ `TimeoutError`。多线程读取和停止同一句柄受原生同步保护,但多步键鼠操作需要调用方串行安排。
260
+
261
+ ## 许可证
262
+
263
+ MIT
@@ -0,0 +1,239 @@
1
+ # scapkit_computer_use
2
+
3
+ 跨平台桌面自动化 Python 库,提供屏幕截图、鼠标控制、键盘输入、剪贴板和 subprocess 操作。
4
+
5
+ 当前支持 macOS;所用 ScreenCaptureKit API 的最低系统版本为 macOS 12.3。
6
+ 官方预编译 wheel 仅提供 macOS 15+ arm64 版本,这不是源码安装的系统或架构限制。
7
+ Windows 目前提供纯 Python subprocess 接口(源码安装);桌面控制扩展仍在开发中。
8
+
9
+ ## 安装
10
+
11
+ 需要 Python >= 3.10;支持 CPython 3.13/3.14 的 free-threaded 构建,通过 PyPI 安装:
12
+
13
+ ```bash
14
+ pip install scapkit_computer_use
15
+ ```
16
+
17
+ 较早的 macOS(12.3+)或 Intel Mac 可从源码构建,需要安装 Xcode Command Line
18
+ Tools,并使用包含 ScreenCaptureKit 的 macOS SDK:
19
+
20
+ ```bash
21
+ pip install --no-binary=scapkit_computer_use scapkit_computer_use
22
+ ```
23
+
24
+ 旧系统和 Intel Mac 的实际运行尚未验证;当前 CI 运行环境为 macOS 15 / 26 arm64。
25
+
26
+ 或使用 [uv](https://github.com/astral-sh/uv):
27
+
28
+ ```bash
29
+ uv add scapkit_computer_use
30
+ ```
31
+
32
+ ## 权限
33
+
34
+ macOS 下需要授予以下系统权限:
35
+
36
+ - **辅助功能 (Accessibility)**:鼠标、键盘控制
37
+ - **屏幕录制 (Screen Recording)**:屏幕截图
38
+
39
+ ```python
40
+ from scapkit_computer_use import check_permission, open_permission_settings
41
+
42
+ if not check_permission("Accessibility"):
43
+ await open_permission_settings("Accessibility")
44
+ ```
45
+
46
+ ## 功能
47
+
48
+ ### 显示器信息
49
+
50
+ 所有坐标和尺寸均使用 **point**(逻辑分辨率),而非物理像素。物理像素 = point × scale_factor。API 中的所有位置参数(鼠标移动、点击等)同样使用 point 坐标。
51
+
52
+ ```python
53
+ from scapkit_computer_use import list_displays
54
+
55
+ displays = list_displays()
56
+ # [{"id": 2, "x": 0, "y": 0, "width": 1920, "height": 1080, "scale_factor": 2.0, "is_main": True}]
57
+ # width/height 为 point 单位,实际物理像素为 1920×2 = 3840, 1080×2 = 2160
58
+ ```
59
+
60
+ ### 鼠标控制
61
+
62
+ ```python
63
+ from scapkit_computer_use import (
64
+ get_mouse_position, move_mouse, move_mouse_relative,
65
+ mouse_click, mouse_scroll, mouse_drag
66
+ )
67
+
68
+ # 获取当前位置
69
+ pos = get_mouse_position() # {"x": 100, "y": 200}
70
+
71
+ # 平滑移动(绝对坐标)
72
+ await move_mouse({"x": 500, "y": 300})
73
+
74
+ # 瞬间移动
75
+ await move_mouse({"x": 500, "y": 300}, smooth=False)
76
+
77
+ # 相对移动(生成 delta 事件,兼容游戏等指针锁定场景)
78
+ await move_mouse_relative({"dx": 100, "dy": 50})
79
+
80
+ # 瞬间相对移动
81
+ await move_mouse_relative({"dx": 100, "dy": 50}, smooth=False)
82
+
83
+ # 点击
84
+ await mouse_click("left")
85
+ await mouse_click("right")
86
+
87
+ # 滚动(方向为内容移动方向)
88
+ await mouse_scroll("down", 3)
89
+ await mouse_scroll("up", 3)
90
+
91
+ # 拖拽到目标位置
92
+ await mouse_drag({"x": 800, "y": 600})
93
+ ```
94
+
95
+ > **注意:** `move_mouse` 使用 `CGWarpMouseCursorPosition`,不会生成鼠标移动的 delta 事件,因此不适用于依赖原始鼠标 delta 的应用(如游戏中的指针锁定)。这类场景请使用 `move_mouse_relative`,它通过 `CGEventCreateMouseEvent` 发送包含 `deltaX/deltaY` 的 `kCGEventMouseMoved` 事件。
96
+
97
+ ### 键盘输入
98
+
99
+ 使用跨平台的按键名称,无需关心底层键码:
100
+
101
+ ```python
102
+ from scapkit_computer_use import keyboard_click, key_combo
103
+
104
+ # 按下并释放一个键
105
+ await keyboard_click("a")
106
+ await keyboard_click("return")
107
+
108
+ # 组合键
109
+ await key_combo("c", {"command"}) # Cmd+C 复制
110
+ await key_combo("v", {"command"}) # Cmd+V 粘贴
111
+ await key_combo("z", {"command", "shift"}) # Cmd+Shift+Z 重做
112
+ ```
113
+
114
+ 支持的按键名称包括:`a`-`z`、`0`-`9`、`return`、`tab`、`space`、`delete`、`escape`、`f1`-`f20`、`up`/`down`/`left`/`right` 等。完整列表见源码 `screen_capture_kit/keys.py`。
115
+
116
+ ### 剪贴板
117
+
118
+ ```python
119
+ from scapkit_computer_use import set_clipboard, get_clipboard, clipboard_paste
120
+
121
+ await set_clipboard("你好世界")
122
+ text = await get_clipboard() # "你好世界"
123
+
124
+ # 直接粘贴到当前输入框(模拟 Cmd+V)
125
+ await clipboard_paste()
126
+ ```
127
+
128
+ ### 屏幕截图
129
+
130
+ 基于 macOS ScreenCaptureKit,支持全分辨率 Retina 截图:
131
+
132
+ ```python
133
+ from scapkit_computer_use import (
134
+ list_displays, start_capture, stop_capture,
135
+ current_frame_jpg, current_frame_bgra
136
+ )
137
+
138
+ displays = list_displays()
139
+ main = next(d for d in displays if d["is_main"])
140
+
141
+ # 启动截图流
142
+ handle = await start_capture(main["id"])
143
+
144
+ # 获取 JPEG 格式(可设置质量 0-100)
145
+ jpg_bytes = await current_frame_jpg(handle, quality=80)
146
+
147
+ # 获取原始 BGRA 像素数据
148
+ frame = await current_frame_bgra(handle)
149
+ # {"data": bytes, "width": 3840, "height": 2160, "bytes_per_row": 15360}
150
+
151
+ # 停止截图
152
+ await stop_capture(handle)
153
+ ```
154
+
155
+ ### 执行 subprocess
156
+
157
+ `run_subprocess()` 是异步函数。可执行文件与参数分开传入;执行 shell 命令时,
158
+ 把 shell 作为可执行文件,并传入 `-c` 或 `/c` 等参数。
159
+
160
+ ```python
161
+ import sys
162
+ from scapkit_computer_use import run_subprocess
163
+
164
+ result = await run_subprocess(
165
+ sys.executable,
166
+ ["-c", "import os; print(os.getenv('EXAMPLE'))"],
167
+ cwd="/path/to/workdir",
168
+ env={"EXAMPLE": "你好"},
169
+ )
170
+ print(result.returncode, result.stdout, result.stderr)
171
+ # 也可以解包:returncode, stdout, stderr = result
172
+
173
+ result = await run_subprocess("/bin/zsh", ["-c", "printf '%s' hello"])
174
+ # Windows 示例:await run_subprocess("cmd.exe", ["/c", "echo hello"])
175
+ ```
176
+
177
+ | 参数 | 含义 |
178
+ | --- | --- |
179
+ | `executable` | 可执行文件名称或路径;名称通过加载后的环境 PATH 查找 |
180
+ | `args=()` | 参数序列,保留空格和特殊字符;不会自动拼接成 shell 命令 |
181
+ | `cwd=None` | 工作目录,默认当前工作目录 |
182
+ | `env=None` | 在 shell 环境上新增或覆盖的变量,均为字符串 |
183
+ | `use_stream=False` | 默认等待退出,返回退出码和两路文本;为 True 时返回运行中的 `SubprocessStream` |
184
+ | `encoding=None` | macOS 默认 UTF-8;Windows 默认控制台输出代码页,无控制台时用系统 OEM 代码页 |
185
+ | `errors="strict"` | 解码错误默认抛异常;可指定 `"replace"` 保留其他可解码内容 |
186
+
187
+ 环境来自重新加载的系统/用户 shell 配置,**不继承当前 Python 进程的环境变量**。
188
+ macOS 读取账户登录 shell 的 login/interactive 配置;Windows 从系统和用户配置构造环境,
189
+ 再执行 cmd AutoRun。调用方传入的 `env` 最后合并。详情见 [进程执行说明](https://github.com/czf0613/computer_use_py/blob/master/docs/subprocess.md)。
190
+
191
+ 流式 stdin 接收字符串,stdout/stderr 支持异步 `read()`、`readline()` 和逐行迭代:
192
+
193
+ ```python
194
+ import asyncio
195
+
196
+ process = await run_subprocess(
197
+ sys.executable, ["-u", "-c", "import sys; print(input()); print('done', file=sys.stderr)"],
198
+ use_stream=True,
199
+ )
200
+
201
+ async def feed():
202
+ process.stdin.write("你好\n")
203
+ await process.stdin.drain()
204
+ process.stdin.close()
205
+
206
+ async def consume(stream):
207
+ async for line in stream:
208
+ print(line, end="")
209
+
210
+ await asyncio.gather(feed(), consume(process.stdout), consume(process.stderr))
211
+ returncode = await process.wait()
212
+ # 或:stdout, stderr = await process.communicate("你好\n")
213
+ ```
214
+
215
+ Windows 程序可能输出 UTF-8、GBK、ANSI 或 UTF-16;无法通用地自动判断。
216
+ 例如使用 `encoding="utf-8"`、`encoding="gbk"` 或 `encoding="utf-16-le"` 明确指定。
217
+ 同一编码用于该进程的三路文本流;跨块中文由增量解码器处理,换行统一为 `\n`。
218
+
219
+ ## 开发
220
+
221
+ ```bash
222
+ # 构建 C 扩展
223
+ uv run setup.py build_ext --inplace
224
+
225
+ # 构建带合成测试支持的扩展,运行不操作桌面的测试
226
+ SCAPKIT_TESTING=1 uv run setup.py build_ext --inplace --force
227
+ uv run pytest tests/test_native_validation.py tests/test_native_arguments.py tests/test_native_capture.py tests/test_capture_lifecycle.py tests/test_async_safety.py tests/test_process.py
228
+ ```
229
+
230
+ 构建环境、并发约定和测试边界见 [开发文档](https://github.com/czf0613/computer_use_py/blob/master/docs/development.md),
231
+ 自动化发布见 [发布文档](https://github.com/czf0613/computer_use_py/blob/master/docs/releasing.md),Codex 接手约定见 [AGENTS.md](https://github.com/czf0613/computer_use_py/blob/master/AGENTS.md),
232
+ 本次质量检查和验证边界见 [审查记录](https://github.com/czf0613/computer_use_py/blob/master/docs/code-review.md)。
233
+
234
+ `stop_capture()` 可以重复调用;停止后的新读帧返回 `None`。启动/停止超时抛出
235
+ `TimeoutError`。多线程读取和停止同一句柄受原生同步保护,但多步键鼠操作需要调用方串行安排。
236
+
237
+ ## 许可证
238
+
239
+ MIT
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include <Python.h>
4
+
5
+ PyObject *scapkit_start_capture(PyObject *self, PyObject *args);
6
+
7
+ PyObject *scapkit_stop_capture(PyObject *self, PyObject *args);
8
+
9
+ PyObject *scapkit_current_frame_jpg(PyObject *self, PyObject *args);
10
+
11
+ PyObject *scapkit_current_frame_bgra(PyObject *self, PyObject *args);
12
+
13
+ #ifdef SCAPKIT_TESTING
14
+ PyObject *scapkit_test_capture(PyObject *self, PyObject *args);
15
+ PyObject *scapkit_test_update_frame(PyObject *self, PyObject *args);
16
+ PyObject *scapkit_test_live_frames(PyObject *self, PyObject *args);
17
+ PyObject *scapkit_test_lifecycle_stats(PyObject *self, PyObject *args);
18
+ #endif
@@ -0,0 +1,17 @@
1
+ #pragma once
2
+
3
+ #include <Python.h>
4
+
5
+ PyObject *scapkit_get_mouse_position(PyObject *self, PyObject *args);
6
+
7
+ PyObject *scapkit_move_mouse(PyObject *self, PyObject *args);
8
+
9
+ PyObject *scapkit_move_mouse_relative(PyObject *self, PyObject *args);
10
+
11
+ PyObject *scapkit_mouse_click(PyObject *self, PyObject *args);
12
+
13
+ PyObject *scapkit_mouse_scroll(PyObject *self, PyObject *args);
14
+
15
+ PyObject *scapkit_check_permission(PyObject *self, PyObject *args);
16
+
17
+ PyObject *scapkit_keyboard_click(PyObject *self, PyObject *args);
@@ -0,0 +1,7 @@
1
+ #pragma once
2
+
3
+ #include <Python.h>
4
+
5
+ #define MAX_DISPLAYS 16
6
+
7
+ PyObject *scapkit_list_displays(PyObject *self, PyObject *args);