Metadata-Version: 2.4
Name: dailo-devtools
Version: 0.1.0
Summary: 通过代劳 DevTools 调试单台 Android 设备的 Python API 与 CLI
License-Expression: MIT
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: playwright<2,>=1.58
Requires-Dist: aiohttp<4,>=3.14
Dynamic: license-file

# DevTools

```sh
pip install dailo-devtools
dailo-dev install
dailo-dev serve --connection connection.json
dailo-dev exec --code "from dailo import text; print(text())"
dailo-dev exec --file main.py --config account.json
```

服务复用一条 WebRTC 连接，仅使用 DataChannel，截图按需获取，不持续传输视频。连接文件从设备开发入口取得，勿提交 Git。也可使用 `async with dailo_devtools.Device(connection)` 调用 `execute`、`run_file`、`inspect`、`screenshot`、`cancel`。默认会话30分钟；持久凭据在Python运行前时间不足时重新准入，授权覆盖本次执行、30秒停止收尾和10秒传输，合计最多7天。正式任务使用自己的执行期限。持久凭据支持断线后自动重新准入，中断操作不重放；`dailo-dev reconnect` / `Device.reconnect()` 可主动重连。

`serve` 的 `status` / `cancel` 不触发重连；其他命令在连接失败时先自动重新准入。前检先请求设备状态，再读取服务状态和 `sessionId`，避免用重连前的 `closed` 快照判定当前连接；原设备线程是否退出仍以原生运行计数为准。

长期 `serve` 和长脚本使用持久连接凭据。已配对桌面设备配置为 `{"baseUrl":"实际平台地址","deviceId":"准入返回的公开设备ID","desktopControllerCapability":"控制端凭据"}`；地址与设备 ID 取正式 App 的准入结果，每次重连通过平台公开接口取得新会话。PC 本地控制端口与 `android-local-*` 列表 ID 不提供此准入合同，不能填入该配置。

连接文件也可写为 `{"url":"App 复制的 DevTools 链接"}`，仅用于一次建连。链接中的入场 capability 已消费后不能用于重连，URL 分支不使用 recoveryCapability；断线或到期需从 App 重新获取链接。入场有效期和已建立会话的有效期分别计算，不能把短入场期限当作会话期限。

`log()` 按产生顺序实时保存到本机，每条文字及 PNG 落盘后才确认接收。连接文件可设 `"logDirectory":"D:/my-project/output/logs"` 指定根目录；默认位于用户缓存目录。Python 终态返回 `logDirectory`（请求目录）和 `logsPath`（该目录的 `logs.json`），不再返回 `logs` 数组。`exec` 和原始 Python `request` 使用同一流程；日志事件不会提前完成执行请求。

`from dailo_devtools import read_logs; entries = read_logs(result['logDirectory'])` 读取图文清单；每项保留完整文字，`image.path` 指向原 PNG。也可用 `dailo-dev logs D:/output/logs/请求ID` 离线查看，无需启动服务或重新连接设备。自然结束、脚本失败和取消回执均保存 `execution.json`（stdout、stderr、错误栈及日志路径）。日志清单与 PNG 不依赖终态回执；断线的 `interruption.json` 同样给出路径，仅标记结果未确认。只保证已经落盘的图文，连接失效时未交付的帧不能补造。

Python执行超时后发送停止请求，保留原响应并最多等待30秒完成清理；返回的stdout、stderr、错误栈与图文保存到该请求目录的`execution.json`。停止未响应时关闭旧通道，下一次重新连接；不能把发送停止当作运行已退出。

CLI外层HTTP预算为设备预算+30秒停止收尾+10秒传输余量。升级Playwright后重新运行`dailo-dev install`；安装和服务使用同一个`PLAYWRIGHT_BROWSERS_PATH`，可指定共享目录，避免Store内外缓存视图不同。

`exec --code` 与 `exec --file` 均自动上传仓库 Python 模块和 `assets/`，可使用 `--config`、`--assets`。内联代码默认属于当前目录，也可用 `--directory` 指定。复用仓库的设备工作目录，下载和写入的文件会保留；每次运行刷新源码导入和字节码，停止后重跑也生效，并移除已删除的模块、资源。

请求按16KiB分片发送，缓冲超过64KiB时等待通道释放，避免多图或大资源堵满发送队列。发送超时或失败关闭旧通道，Python结果记为未确认；下一次调用重新准入，不重放请求。

相同资源不重写，更新资源先移除旧文件，避免破坏已加载原生库的内存映射。原生库内容更新后需重启设备上的 Dailo 应用再运行。

信令断开时立即关闭旧DataChannel，并保存请求目录的interruption.json，标记结果未确认。status的activeRun为空仅表示宿主已结束等待，不能作为原设备线程已退出或脚本成功的依据。
