From 34f9a2c141f85d8afe2f930e62a02baebce8dc4d Mon Sep 17 00:00:00 2001 From: chendelian <116870791@qq.com> Date: Mon, 18 May 2026 16:05:16 +0800 Subject: [PATCH] docs: Stage 2 SDK data-jcid migration report Co-authored-by: Cursor --- STAGE2_SDK_MIGRATION_REPORT.md | 131 +++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 STAGE2_SDK_MIGRATION_REPORT.md diff --git a/STAGE2_SDK_MIGRATION_REPORT.md b/STAGE2_SDK_MIGRATION_REPORT.md new file mode 100644 index 0000000..e519cc2 --- /dev/null +++ b/STAGE2_SDK_MIGRATION_REPORT.md @@ -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(...)` 按预期抛错。