docs: Stage 2 SDK data-jcid migration report
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
131
STAGE2_SDK_MIGRATION_REPORT.md
Normal file
131
STAGE2_SDK_MIGRATION_REPORT.md
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
# Stage 2 — SDK data-jcid Migration Report
|
||||||
|
|
||||||
|
## 1. 执行摘要
|
||||||
|
|
||||||
|
- 起始 HEAD: `089f00c3ff6b75125d77f40b2e2dcb664a9ac5bf`
|
||||||
|
- 结束 HEAD: 本阶段未 commit,工作区状态见下
|
||||||
|
- 影响文件:
|
||||||
|
- `src/jiangchang_desktop_sdk/client.py`(主要改动,7 步合计)
|
||||||
|
- `README.md`(新增 v0.2.0 章节)
|
||||||
|
- `STAGE2_SDK_MIGRATION_REPORT.md`(本回执)
|
||||||
|
- 其他例外文件:无(`types.py` / `exceptions.py` 未改)
|
||||||
|
|
||||||
|
## 2. 7 步改动总览
|
||||||
|
|
||||||
|
| 步 | 内容 | 影响范围 |
|
||||||
|
|----|------|---------|
|
||||||
|
| 1 | SELECTOR 常量表 | client.py 顶部新增 36 行 |
|
||||||
|
| 2 | _get_*_locator x4 + 2 处 raise 文案 | client.py 局部 |
|
||||||
|
| 3 | read() | client.py 局部 |
|
||||||
|
| 4 | 9 个私有 helper | client.py 多处 |
|
||||||
|
| 5 | _wait_for_streaming_done | client.py 局部(docstring + 注释) |
|
||||||
|
| 6 | new_task / wait_gateway_ready / send_file | client.py 局部 |
|
||||||
|
| 7 | README + 扫尾 | README.md + 验证 |
|
||||||
|
|
||||||
|
**第 7 步附带**: `ask()` 兜底分支仍残留可执行 `[data-jcid="message"]` / `data-jcid-role`,已改为 `SEL_MESSAGE_ROW` + `data-role`(否则 7.1 可执行代码 grep 无法通过)。
|
||||||
|
|
||||||
|
## 3. 公开 API 兼容性证明
|
||||||
|
|
||||||
|
逐项列出公开 API 改造前后签名,确认一字不差:
|
||||||
|
|
||||||
|
| 方法 | 改前签名 | 改后签名 | 一致? |
|
||||||
|
|------|---------|---------|-------|
|
||||||
|
| ensure_app_running | (self, wait_timeout_s: float = 30.0) -> None | 同左 | ✓ |
|
||||||
|
| bring_to_front | (self) -> None | 同左 | ✓ |
|
||||||
|
| connect | (self, url: Optional[str] = None) -> None | 同左 | ✓ |
|
||||||
|
| launch_app | (self, options: Optional[LaunchOptions] = None) -> None | 同左 | ✓ |
|
||||||
|
| disconnect | (self) -> None | 同左 | ✓ |
|
||||||
|
| is_connected | (self) -> bool | 同左 | ✓ |
|
||||||
|
| get_page | (self) -> Page | 同左 | ✓ |
|
||||||
|
| new_task | (self) -> None | 同左 | ✓ |
|
||||||
|
| wait_gateway_ready | (self, timeout_ms: int = 30000) -> None | 同左 | ✓ |
|
||||||
|
| wait_for_response | (self, timeout: int = 120000) -> None | 同左 | ✓ |
|
||||||
|
| ask | (self, question: str, options: Optional[AskOptions] = None) -> str | 同左 | ✓ |
|
||||||
|
| send_file | (self, file_path: str, message: Optional[str] = None) -> None | 同左(行为变 NotImplementedError) | ✓ |
|
||||||
|
| read | (self) -> List[JiangchangMessage] | 同左 | ✓ |
|
||||||
|
| assert_contains | (self, expected: str, options: Optional[AssertOptions] = None) -> None | 同左 | ✓ |
|
||||||
|
| snapshot | (self, target_dir: str, tag: str = "snapshot") -> dict | 同左 | ✓ |
|
||||||
|
| __enter__ | (self) -> "JiangchangDesktopClient" | 同左 | ✓ |
|
||||||
|
| __exit__ | (self, exc_type, exc_val, exc_tb) -> None | 同左 | ✓ |
|
||||||
|
|
||||||
|
## 4. 临时限制说明
|
||||||
|
|
||||||
|
### send_file
|
||||||
|
- 状态:抛 NotImplementedError
|
||||||
|
- 原因:Electron IPC stage-paths,SDK 无 DOM 入口
|
||||||
|
- 恢复条件:匠厂主仓库暴露 `window.__jc_stage_paths__` 或带 testid 的隐藏 input
|
||||||
|
|
||||||
|
### _gateway_state
|
||||||
|
- 状态:永远返回 'unknown'
|
||||||
|
- 原因:HEAD 上 gateway 状态不暴露 DOM
|
||||||
|
- 行为影响:_wait_for_streaming_done 中 `if gw not in ("running", "unknown")`
|
||||||
|
实质 no-op,但保留以便未来生效
|
||||||
|
- 恢复条件:匠厂在 main / store 暴露 `window.__jc_gateway_state__`
|
||||||
|
|
||||||
|
## 5. 扫尾验证实际输出
|
||||||
|
|
||||||
|
### 5.1 `grep -n 'data-jcid' src/jiangchang_desktop_sdk/client.py`
|
||||||
|
```
|
||||||
|
src/jiangchang_desktop_sdk/client.py:10:3. 每次提问前新建任务(点击侧栏 `data-jcid="new-task-button"`),避免上下文污染。 (模块 docstring 历史描述)
|
||||||
|
src/jiangchang_desktop_sdk/client.py:14: 这些 DOM 节点 **不再带 `data-jcid="message"`**,而是 `data-testid="chat-execution-graph"` (模块 docstring 历史描述)
|
||||||
|
src/jiangchang_desktop_sdk/client.py:18: · **锚点**:`ask()` 发送后等到最后一条 `[data-jcid-role="user"]` 节点(就是我们刚发的 (模块 docstring 历史描述)
|
||||||
|
src/jiangchang_desktop_sdk/client.py:19: 问题)在 DOM 里出现,记住它在 `[data-jcid="message"]` 列表里的 index,作为切片起点; (模块 docstring 历史描述)
|
||||||
|
src/jiangchang_desktop_sdk/client.py:21: · `chat-root[data-jcid-sending] === 'false'` (模块 docstring 历史描述)
|
||||||
|
src/jiangchang_desktop_sdk/client.py:25: · 我们这条 user 之后存在 `[data-jcid-role="assistant"]` 且其内部有 (模块 docstring 历史描述)
|
||||||
|
src/jiangchang_desktop_sdk/client.py:26: `[data-jcid="message-body"]` (模块 docstring 历史描述)
|
||||||
|
src/jiangchang_desktop_sdk/client.py:29:5. read() 严格按 `data-jcid-role` 分类,没有该属性的 DOM 节点不再默认归为 assistant。 (模块 docstring 历史描述)
|
||||||
|
src/jiangchang_desktop_sdk/client.py:526: """返回 `[data-jcid="message"]` 节点列表中最后一条 role=user 的 index;找不到返回 -1。""" (docstring 历史描述)
|
||||||
|
src/jiangchang_desktop_sdk/client.py:561: "streaming": bool, # data-jcid-streaming 属性 (docstring 历史描述)
|
||||||
|
src/jiangchang_desktop_sdk/client.py:610: """chat-root[data-jcid-sending] 的 bool 化;读不到返回 None。""" (docstring 历史描述)
|
||||||
|
src/jiangchang_desktop_sdk/client.py:796: "我们刚发出的 user 节点在 [data-jcid=\"message\"] 列表里的 index"。后续所有 (ask docstring 历史描述)
|
||||||
|
```
|
||||||
|
|
||||||
|
可执行代码(非 docstring / 非 `#` 注释):**0 命中**。
|
||||||
|
|
||||||
|
### 5.2 `grep -n '__jc_sending__' src/jiangchang_desktop_sdk/client.py`
|
||||||
|
```
|
||||||
|
src/jiangchang_desktop_sdk/client.py:22: · `window.__jc_sending__` !== true
|
||||||
|
src/jiangchang_desktop_sdk/client.py:633: """从 window.__jc_sending__ 读取当前 sending 状态;不可用返回 None。"""
|
||||||
|
src/jiangchang_desktop_sdk/client.py:636: val = page.evaluate("() => window.__jc_sending__")
|
||||||
|
src/jiangchang_desktop_sdk/client.py:673: (C)同时 window.__jc_sending__ 不是 true(允许 None / False,以容忍
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.3 import 可用性
|
||||||
|
```
|
||||||
|
import OK
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. 集成验证
|
||||||
|
|
||||||
|
- 是否在本地跑过 README 末尾的 3 步验证流程?
|
||||||
|
- [ ] 跑过 → 结果(pass/fail + 关键输出片段)
|
||||||
|
- [x] 未跑 → 原因:验收环境未启动匠厂客户端 / 本阶段仅完成代码与静态扫尾
|
||||||
|
|
||||||
|
- 是否运行了 platform-kit 自带的任何测试?
|
||||||
|
- [ ] 跑过 → 结果
|
||||||
|
- [x] 未跑 → 原因:本包无针对 desktop_sdk 的自动化集成测试;需实机 CDP
|
||||||
|
|
||||||
|
## 7. 未触及的事项
|
||||||
|
|
||||||
|
- `examples/`、`tools/screencast/`:未在本阶段验证;预期不直接依赖已移除的 data-jcid 选择器
|
||||||
|
- platform-kit stash 中的 `runtime_env.py` 改动:本阶段未碰,仍在 stash(`stash@{0}: wip: claw env var fallback...`)
|
||||||
|
- `D:\AI\jiangchang` 主仓库:未修改
|
||||||
|
- 模块级 / 部分 helper / `ask()` docstring 中 data-jcid 历史措辞:保留,见 §9
|
||||||
|
|
||||||
|
## 8. 自检
|
||||||
|
|
||||||
|
- [x] grep 'data-jcid' 在可执行代码中 → 0 命中
|
||||||
|
- [x] 公开 API 签名表逐项核对一致
|
||||||
|
- [x] send_file 抛 NotImplementedError 而非静默
|
||||||
|
- [x] _gateway_state 含 TODO 注释
|
||||||
|
- [x] README 新增 v0.2.0 章节,无格式错乱
|
||||||
|
- [x] 未触碰 D:\AI\jiangchang 主仓库任何文件
|
||||||
|
- [x] 未触碰 platform-kit 非 client.py / README.md / 本回执 的文件
|
||||||
|
- [ ] git status 显示工作区干净(除本阶段预期修改 + 已有 stash) → 见 §1,未 commit
|
||||||
|
|
||||||
|
## 9. 给验收方的备注
|
||||||
|
|
||||||
|
1. **docstring 历史 data-jcid**: 模块顶 docstring(L10–L29)、`_last_user_node_index`(L526)、`_latest_assistant_after` 内联说明(L561)、`_chat_root_sending`(L610)、`ask()` docstring(L796) 仍描述旧 UI 模型;不影响运行。若需文档一致性,可单独开文档清理 PR。
|
||||||
|
2. **send_file**: 调用即 `NotImplementedError`,无连接检查(按规格整段替换方法体)。
|
||||||
|
3. **wait_gateway_ready**: 仅等待 `SEL_CHAT_PAGE` 可见,不保证 Gateway 进程已 ready。
|
||||||
|
4. **建议验收**: 在已安装 v2.0.17+ 匠厂 + Playwright 环境跑 README 末尾脚本;并确认 `send_file(...)` 按预期抛错。
|
||||||
Reference in New Issue
Block a user