feat(template): 升级 desktop E2E 模板到本系列最佳实践
基于 disburse-payroll-icbc 实战经验沉淀,让所有未来新 skill 复制模板后直接 享受本系列全部改进: - record_screencast.py.sample: · 字幕脚本改用 "step: N/X" 模式 + ASCII 关键词锚(避免编码问题) · 展示三元组 (keyword, text, duration) 用法(依赖 platform-kit subtitle.py) · 加 TEST_FILE_NAME / MUSIC_SUBDIR 切换常量 · 文档说明绕开 SDK ask() / send_file 的最佳实践 - test_desktop_smoke.py.sample: · docstring 加"何时用此模板 / 何时改用 _with_attachment"指引 · 标注已知 SDK 限制(ask() user_idx<0 / send_file NotImplementedError) - test_desktop_smoke_with_attachment.py.sample(新增): · 完整附件场景模板,import jiangchang_desktop_sdk.e2e_helpers 6 个 API · 7 步 step: N/7 模式,跟 record_screencast.py.sample 字幕脚本对齐 · 占位符 SKILL_SLUG / PROMPT / EXPECTED_KEYWORDS_IN_REPLY - README.md: 追加 3 节 · 模板选择指南(纯问答 vs 附件场景) · 已知 SDK 坑(send_file / ask / 字幕关键词 / bring_to_front) · 录屏新能力(activate_window / monitor_index / 字幕三元组) - conftest.py: 同步到支持新版 platform-kit src/ 布局的 SDK 路径推断 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3,14 +3,21 @@
|
||||
Screencast 录制入口(模板)。
|
||||
|
||||
启用方式:
|
||||
复制为 record_screencast.py,修改 SKILL_SLUG 和 SUBTITLE_SCRIPT,然后运行:
|
||||
python tests/desktop/record_screencast.py
|
||||
1. 复制为 record_screencast.py
|
||||
2. 修改 SKILL_SLUG 和 SUBTITLE_SCRIPT
|
||||
3. 决定 test_file 指向哪个测试(默认 test_desktop_smoke.py;
|
||||
有附件场景的用 test_desktop_smoke_with_attachment.py)
|
||||
4. 运行:python tests/desktop/record_screencast.py
|
||||
|
||||
依赖:
|
||||
1. pip install mss
|
||||
2. 系统已安装 ffmpeg 并在 PATH 中
|
||||
3. jiangchang-platform-kit 在本机可推断路径(见 _bootstrap 逻辑)
|
||||
3. jiangchang-platform-kit 可推断路径(见 _bootstrap 逻辑)
|
||||
4. MEDIA_ASSETS_ROOT 环境变量指向 media-assets 仓库(或使用默认路径)
|
||||
|
||||
平台 kit v?? 之后 run_screencast 自动激活并最大化匠厂窗口、支持指定显示器、
|
||||
字幕支持每条独立时长。本模板已经利用这些能力,新 skill 复制后无需再内嵌
|
||||
ctypes 激活代码。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -22,9 +29,9 @@ from pathlib import Path
|
||||
def _bootstrap_screencast() -> None:
|
||||
"""将 jiangchang-platform-kit/tools 加入 sys.path,使 screencast 包可导入。"""
|
||||
here = Path(__file__).resolve()
|
||||
skill_root = here.parents[2] # tests/desktop → tests → skill_root
|
||||
workspace_root = skill_root.parent # skill_root → workspace
|
||||
open_claw_root = workspace_root.parent # workspace → OpenClaw
|
||||
skill_root = here.parents[2]
|
||||
workspace_root = skill_root.parent
|
||||
open_claw_root = workspace_root.parent
|
||||
|
||||
candidates = [
|
||||
workspace_root / "jiangchang-platform-kit" / "tools",
|
||||
@@ -43,7 +50,8 @@ def _bootstrap_screencast() -> None:
|
||||
|
||||
raise RuntimeError(
|
||||
"找不到 jiangchang-platform-kit/tools/screencast。\n"
|
||||
"请设置 JIANGCHANG_KIT_ROOT 环境变量,或将 platform-kit 放在 workspace 同级目录。"
|
||||
"请设置 JIANGCHANG_KIT_ROOT 环境变量,或将 platform-kit 放在 workspace "
|
||||
"同级目录。"
|
||||
)
|
||||
|
||||
|
||||
@@ -52,25 +60,48 @@ _bootstrap_screencast()
|
||||
from screencast import run_screencast # noqa: E402
|
||||
|
||||
# ============================================================
|
||||
# ↓↓↓ 复制后只需修改这两处 ↓↓↓
|
||||
# ↓↓↓ 复制后只需修改下面这些 ↓↓↓
|
||||
# ============================================================
|
||||
|
||||
SKILL_SLUG = "your-skill-slug" # 替换为本技能 slug
|
||||
|
||||
# 字幕脚本设计要点(来自 disburse-payroll-icbc 实战经验):
|
||||
# 1. **关键词全用 ASCII**:保险起见绕开 Windows cp936/UTF-8 编码偶发问题。
|
||||
# 虽然 platform-kit 已修了 subprocess 编码,ASCII 关键词仍是最稳的。
|
||||
# 2. **用 "step: N/X" 模式作触发锚**:在测试代码里加 _logger.info("step: 1/5 ...")
|
||||
# 日志作为字幕触发点,能精确控制字幕出现时机,比依赖 SDK 内部日志更可靠。
|
||||
# 3. **关键词每条只触发一次**,所以"step: 1/" 这种唯一前缀比"准备数据"更稳。
|
||||
# 4. **三元组支持每条独立时长**:(关键词, 文案, 显示秒数);
|
||||
# long wait 场景可以让某条字幕停留更久(如 30s)覆盖中间无日志输出的等待期。
|
||||
SUBTITLE_SCRIPT = [
|
||||
# (pytest stdout 中出现的关键词, 字幕显示文案)
|
||||
("ensure_app_running", "正在启动匠厂智能体平台..."),
|
||||
("wait_gateway_ready", "网关就绪,准备发起任务"),
|
||||
("ask(", "向助手发送指令..."),
|
||||
("PASSED", "任务完成"),
|
||||
# (keyword, text) 二元组用默认时长(5s)
|
||||
("ensure_app_running", "启动匠厂智能体平台"),
|
||||
("wait_gateway_ready", "网关就绪"),
|
||||
("step: 1/", "准备测试数据"),
|
||||
("step: 2/", "执行技能操作"),
|
||||
# (keyword, text, duration) 三元组指定独立时长
|
||||
("step: 3/", "技能在后端持续执行,请稍候...", 30.0),
|
||||
("step: 4/", "结果汇总返回"),
|
||||
("PASSED", "测试通过 ✓"),
|
||||
]
|
||||
|
||||
# 测试文件选择(按需切换):
|
||||
# - test_desktop_smoke.py: 纯问答 skill 用这个
|
||||
# - test_desktop_smoke_with_attachment.py: 需要上传附件的 skill 用这个
|
||||
TEST_FILE_NAME = "test_desktop_smoke.py"
|
||||
|
||||
# 音乐子目录(按 skill 风格选):
|
||||
# - "music/corporate": 商务严肃(金融、办公场景)
|
||||
# - "music/calm": 舒缓(流程演示、配置类)
|
||||
# - "music/upbeat": 活力(成功汇报、营销视频)
|
||||
# - "music"(默认): 三个子目录混选
|
||||
MUSIC_SUBDIR = "music/corporate"
|
||||
|
||||
# ============================================================
|
||||
|
||||
if __name__ == "__main__":
|
||||
_here = Path(__file__).resolve()
|
||||
skill_root = _here.parents[2]
|
||||
test_file = str(_here.parent / "test_desktop_smoke.py")
|
||||
test_file = str(_here.parent / TEST_FILE_NAME)
|
||||
output_dir = str(_here.parent / "artifacts" / "recordings")
|
||||
|
||||
run_screencast(
|
||||
@@ -78,4 +109,8 @@ if __name__ == "__main__":
|
||||
subtitle_script=SUBTITLE_SCRIPT,
|
||||
pytest_args=[test_file, "-v", "-s"],
|
||||
output_dir=output_dir,
|
||||
music_subdir=MUSIC_SUBDIR,
|
||||
# platform-kit 自动激活+最大化窗口(Windows ctypes / 其他系统协议),
|
||||
# 想关掉传 activate_window=False
|
||||
# monitor_index=1 显式录主屏(多显示器场景推荐)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user