chore: auto release commit (2026-07-03 18:50:07)
All checks were successful
技能自动化发布 / release (push) Successful in 6s
All checks were successful
技能自动化发布 / release (push) Successful in 6s
This commit is contained in:
@@ -37,17 +37,22 @@ scripts/service/<domain>_adapter/
|
||||
base.py # 数据契约(dataclass)+ AdapterBase 接口
|
||||
mock.py # 离线仿真,给 CI/单测
|
||||
real_api.py # 真实系统 API
|
||||
sim_rpa.py # 仿真平台 RPA
|
||||
sim_rpa.py # 薄仿真平台 RPA adapter(委托 *_playwright.py)
|
||||
real_rpa.py # 真实系统 RPA(占位,谨慎实现)
|
||||
|
||||
scripts/service/
|
||||
<platform>_playwright.py # RPA 主流程(厚);与薄 sim_rpa.py 并列
|
||||
account_client.py # account-manager subprocess 唯一封装
|
||||
browser_session.py # async persistent context 启动
|
||||
```
|
||||
|
||||
模板示例(均在 `examples/`,**不在** `scripts/`):
|
||||
|
||||
- **仿真浏览器 RPA 完整案例**:`examples/simulator_browser_rpa/` — mock + simulator_rpa + sandbox 页面 + adapter 分层 + 测试
|
||||
- **真实浏览器 RPA 完整案例**:`examples/real_browser_rpa/` — 登录/验证码/滚动采集
|
||||
- **仿真浏览器 RPA 完整案例**:`examples/simulator_browser_rpa/` — async mock + simulator_rpa + `simulator_playwright.py` + sandbox 页面 + adapter 分层 + 测试
|
||||
- **真实浏览器 RPA 完整案例**:`examples/real_browser_rpa/` — 登录/验证码/滚动采集 + `account_client.py`
|
||||
- **真实 API / 仿真 API**:`examples/real_api/`、`examples/simulator_api/` — 当前为规划占位,尚未沉淀可复制实现
|
||||
|
||||
复制 adapter 分层时,以 `examples/simulator_browser_rpa/scripts/service/adapter/` 为权威参考,在新技能中创建 `scripts/service/<domain>_adapter/` 并按 README copy map 选择性复制。
|
||||
复制 adapter 分层时,以修正后的 `examples/simulator_browser_rpa/`(薄 adapter + `simulator_playwright.py`)与 `examples/real_browser_rpa/scripts/service/account_client.py` 为权威参考,在新技能中创建 `scripts/service/<domain>_adapter/` 并按 README copy map 选择性复制。
|
||||
|
||||
> 先判断属于四象限哪一种(`real_browser_rpa` / `real_api` / `simulator_browser_rpa` / `simulator_api`),再读对应 `examples/*/README.md`。示例是**参考架构与边界**,不是业务代码原样复制。
|
||||
|
||||
@@ -93,7 +98,7 @@ def get_adapter():
|
||||
|
||||
1. 在 `SKILL.md` 的 `metadata.openclaw.dependencies.required` 声明。
|
||||
2. **普通兄弟技能调用**,优先走统一 **`service.sibling_bridge`**(`call_sibling_json`),**不要**在 `task_service.py`、`task_rpa.py` 等业务流程文件中到处散落 `subprocess.run`。
|
||||
3. **account-manager 账号/租约能力**是例外:可参考 `examples/real_browser_rpa/scripts/service/account_client.py`,封装为**单一** `account_client.py`;允许在该文件内部集中通过 subprocess 调 account-manager CLI。
|
||||
3. **account-manager 账号/租约能力**是例外:可参考 `examples/real_browser_rpa/scripts/service/account_client.py` 与 `examples/simulator_browser_rpa/scripts/service/account_client.py`,封装为**单一** `account_client.py`;允许在该文件内部集中通过 subprocess 调 account-manager CLI。**禁止** import `rpa_helpers` 等 account-manager 内部模块;`simulator_rpa` 与 `real_rpa` 均走同一 `pick_web_account` / `release_lease` 模式。
|
||||
4. **不允许**直接 `import account-manager` 的内部 Python 模块(如 `service/`、`util/`、`db/`)。
|
||||
5. **pick lease 后必须 `finally release lease`**;进程被 kill 后可能残留 lease,需在运维文档说明排查方式(查 account-manager lease 列表 / 手动释放)。
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ OPENCLAW_TEST_TARGET=mock # mock | simulator_rpa | real_api | real_
|
||||
TARGET_BASE_URL=https://sandbox.jc2009.com
|
||||
|
||||
# ── 默认账号(仅非敏感标识;密码走 account-manager)──
|
||||
# 浏览器 RPA simulator_rpa 联调账号来自 account-manager(platform + profile_dir),不是此处的 DEFAULT_LOGIN_ID
|
||||
DEFAULT_LOGIN_ID=04110001
|
||||
|
||||
# ── 浏览器 / RPA ──
|
||||
|
||||
@@ -80,11 +80,13 @@
|
||||
你不应该直接在这个仓库里开发业务,而应该:
|
||||
|
||||
0. 按 [`NAMING.md`](NAMING.md) 确定 slug(`{verb}-{noun-phrase}-{platform}`)
|
||||
1. 复制这个目录
|
||||
2. 改成新 skill 的目录名(与 slug 一致)
|
||||
1. **优先**用 [`tools/scaffold_skill.ps1`](../tools/scaffold_skill.ps1) 创建新目录(见 [`tools/README.md`](../tools/README.md))
|
||||
2. 在新目录内 `git init` 并绑定**本技能**远端(**不得**保留模板 `.git`)
|
||||
3. 把占位内容替换掉
|
||||
4. 再开始写业务逻辑
|
||||
|
||||
> **Git 红线**:禁止资源管理器整文件夹复制后保留模板 `.git`;`git remote -v` 必须指向新技能仓库,不能仍是 skill-template。
|
||||
|
||||
## 2. 新 skill 的标准目录结构
|
||||
|
||||
复制模板后,你应该保留下面这套结构:
|
||||
@@ -168,10 +170,13 @@ scripts/
|
||||
- `examples/real_browser_rpa/scripts/service/task_rpa.py`
|
||||
- `examples/real_browser_rpa/scripts/service/account_client.py`
|
||||
- 若是 **仿真浏览器 RPA**(自有 sandbox、表单批量提交、可控 DOM),**必须先读** `examples/simulator_browser_rpa/README.md`,再按需复制到 `scripts/service/`:
|
||||
- `examples/simulator_browser_rpa/scripts/service/browser_session.py`
|
||||
- `examples/simulator_browser_rpa/scripts/service/adapter/`
|
||||
- `examples/simulator_browser_rpa/scripts/service/task_service.py`
|
||||
- `examples/simulator_browser_rpa/scripts/service/browser_session.py`(async)
|
||||
- `examples/simulator_browser_rpa/scripts/service/account_client.py`(subprocess,对齐 `real_browser_rpa`)
|
||||
- `examples/simulator_browser_rpa/scripts/service/simulator_playwright.py`(RPA 主流程,复制后改名为 `<platform>_playwright.py`)
|
||||
- `examples/simulator_browser_rpa/scripts/service/adapter/`(薄 `simulator_rpa` + mock)
|
||||
- `examples/simulator_browser_rpa/scripts/service/task_service.py`(async 编排)
|
||||
- `sandbox/demo_app.html` 仅留在 examples,不进入生产 skill
|
||||
- **禁止**:`rpa_helpers`、sync Playwright 用于完整技能 RPA 主路径、`task_service` 散落 account-manager subprocess
|
||||
3. **只用共享库,不在 skill 里重写反反爬**:
|
||||
```python
|
||||
from jiangchang_skill_core import config
|
||||
@@ -244,12 +249,52 @@ release workflow 会对 `scripts/` 下的 Python 源码做加密/打包。当前
|
||||
|
||||
### 第一步:复制模板并改目录名
|
||||
|
||||
例如你要开发 `your-skill-slug`(或 `disburse-payroll-icbc` 一类领域 skill):
|
||||
例如你要开发 `disburse-payroll-icbc` 一类领域 skill(目录名 = slug):
|
||||
|
||||
1. 复制 `skill-template`
|
||||
2. 新目录改成与 `slug` 一致的名称(如 `your-skill-slug`)
|
||||
3. 初始化为独立 git 仓库
|
||||
4. 关联它自己的远端仓库
|
||||
#### 推荐方式(首选)
|
||||
|
||||
在 **skill-template 仓库根目录**执行:
|
||||
|
||||
```powershell
|
||||
.\tools\scaffold_skill.ps1 -Slug disburse-payroll-icbc -Destination D:\OpenClaw\client-gdcm\disburse-payroll-icbc
|
||||
cd D:\OpenClaw\client-gdcm\disburse-payroll-icbc
|
||||
git init
|
||||
git remote add origin <你的新技能 Gitea/Git 仓库 URL>
|
||||
git remote -v # 确认 origin 不是 skill-template
|
||||
```
|
||||
|
||||
跨平台可用 `python tools/scaffold_skill.py --slug ... --destination ...`(见 [`tools/README.md`](../tools/README.md))。
|
||||
|
||||
脚手架会排除 `.git`、缓存与 `.env`,并删除 `.openclaw-skill-template` 标记;**不会**自动 `git init`。
|
||||
|
||||
#### 禁止方式
|
||||
|
||||
| 做法 | 后果 |
|
||||
|------|------|
|
||||
| ❌ 资源管理器整文件夹复制后不做 Git 清理 | 隐藏 `.git` 被带走,push 串到 template |
|
||||
| ❌ 保留模板 `.git` 只改 `remote url` | 历史、分支、对象库仍属 template |
|
||||
| ❌ 未删 `.git` 就 `git init` | 嵌套/混乱仓库,难以排查 |
|
||||
|
||||
#### 若已手工复制(补救)
|
||||
|
||||
```powershell
|
||||
cd <新技能目录>
|
||||
Remove-Item -Recurse -Force .git
|
||||
Remove-Item -Recurse -Force .pytest_cache -ErrorAction SilentlyContinue
|
||||
Remove-Item -Force .openclaw-skill-template -ErrorAction SilentlyContinue
|
||||
git init
|
||||
git remote add origin <新技能仓库 URL>
|
||||
git remote -v
|
||||
```
|
||||
|
||||
#### AI / 编程代理复制红线
|
||||
|
||||
| 禁止 | 说明 |
|
||||
|------|------|
|
||||
| 保留模板 `.git` | 必须先 `Remove-Item -Recurse -Force .git` 再 `git init` |
|
||||
| `origin` 仍指向 skill-template | 复制后必须 `git remote -v` 自检 |
|
||||
| 保留 `.openclaw-skill-template` | 仅 template 源仓库可有;业务技能不得保留 |
|
||||
| 复制 `.pytest_cache` / `__pycache__` | 用 scaffold 已排除;手工复制应删 |
|
||||
|
||||
目录名要和 skill slug 对齐,后面很多地方都依赖这个命名。
|
||||
|
||||
@@ -699,6 +744,9 @@ uses: client-jiangchang/jiangchang-platform-kit/.github/workflows/reusable-relea
|
||||
- [ ] 源码/文档/配置为 **UTF-8 without BOM**(Python 文件不得含 `U+FEFF`)
|
||||
- [ ] 没有新增默认必跑测试访问真实网络或浏览器
|
||||
- [ ] 如有 integration 测试需求,已写在 `tests/integration/` 下并保持 `.sample` 后缀
|
||||
- [ ] 本仓库**不是** skill-template 的误复制(根目录**无** `.openclaw-skill-template`)
|
||||
- [ ] `git remote -v` 指向**本技能**远端,URL 不含 skill-template 仓库名
|
||||
- [ ] `git log` 首条提交属于本技能(非模板历史)
|
||||
|
||||
## 17. 常见错误
|
||||
|
||||
@@ -758,12 +806,12 @@ uses: client-jiangchang/jiangchang-platform-kit/.github/workflows/reusable-relea
|
||||
|
||||
表现:
|
||||
|
||||
- slug 形如 `amazon-download-settlement-report`
|
||||
- slug 形如 `erp-download-settlement-report`(平台段错误地放在最前)
|
||||
- 语义校验或 `test_slug_naming` 失败
|
||||
|
||||
要改:
|
||||
|
||||
- 动词放首段,平台放末段,例如 `download-settlement-report-amazon`
|
||||
- 动词放首段,平台放末段,例如 `download-settlement-report-erp`
|
||||
- 见 [`NAMING.md`](NAMING.md)
|
||||
|
||||
### 错误 6:noun 段过长导致超 48 字符
|
||||
@@ -789,6 +837,25 @@ uses: client-jiangchang/jiangchang-platform-kit/.github/workflows/reusable-relea
|
||||
- `SKILL.md` 的 `metadata.openclaw.slug`
|
||||
- `scripts/util/constants.py` 的 `SKILL_SLUG`
|
||||
|
||||
### 错误 8:复制模板时带走了 `.git`
|
||||
|
||||
表现:
|
||||
|
||||
- `git remote -v` 仍显示 skill-template 的 origin
|
||||
- push 到错误仓库,或 log 里全是模板历史
|
||||
- 新技能目录里仍有 `.openclaw-skill-template`
|
||||
|
||||
修复:
|
||||
|
||||
```powershell
|
||||
Remove-Item -Recurse -Force .git
|
||||
Remove-Item -Force .openclaw-skill-template -ErrorAction SilentlyContinue
|
||||
git init
|
||||
git remote add origin <新技能仓库 URL>
|
||||
```
|
||||
|
||||
以后复制请优先用 `tools/scaffold_skill.ps1`(见 [`tools/README.md`](../tools/README.md))。
|
||||
|
||||
## 18. 推荐开发顺序总结
|
||||
|
||||
如果让一个新人照着做,我建议他按这个顺序:
|
||||
|
||||
@@ -165,10 +165,11 @@ slug **末段 platform** 与 `account-manager` 中的 `platform_key` **语义对
|
||||
## 9. 复制新技能流程
|
||||
|
||||
1. **先定 slug** — 按本文规范拟定 `{verb}-{noun-phrase}-{platform}`,确认在白名单内且 ≤ 48 字符
|
||||
2. **复制目录** — 将 `skill-template` 复制为新目录,**目录名 = slug**
|
||||
2. **复制目录** — **推荐** [`tools/scaffold_skill.ps1`](../tools/scaffold_skill.ps1)(`-Slug` 与目录名一致);勿整包复制带走 `.git`
|
||||
2.5. **清理 Git(若未用 scaffold)** — 删除 `.git`、`.openclaw-skill-template`、`.pytest_cache`;再 `git init` 与 `git remote add origin`
|
||||
3. **全局替换** — `your-skill-slug` → 新 slug;更新 `SKILL.md`、`constants.py`、文档中的占位
|
||||
4. **填写 REQUIREMENTS** — 完成 [`REQUIREMENTS.md`](REQUIREMENTS.md) §0 技能标识
|
||||
5. **开发 & 自检** — `python tests/run_tests.py -v`,含 slug 语义测试
|
||||
5. **开发 & 自检** — `python tests/run_tests.py -v`,含 slug 语义测试;`git remote -v` 确认非 template
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -11,5 +11,7 @@
|
||||
7. [`CONFIG.md`](CONFIG.md) — `.env` 规范与 bootstrap 机制
|
||||
8. [`RUNTIME.md`](RUNTIME.md) — 共享 runtime、数据路径、发布打包与编码约定
|
||||
|
||||
脚手架与 Git 防串库:[`../tools/README.md`](../tools/README.md)(`scaffold_skill.ps1`)。
|
||||
|
||||
Agent 调用契约见 [`../references/CLI.md`](../references/CLI.md)、[`../references/SCHEMA.md`](../references/SCHEMA.md)。
|
||||
用户市场说明见根目录 [`README.md`](../README.md),不要写进本目录。
|
||||
|
||||
@@ -138,7 +138,7 @@ from jiangchang_skill_core.rpa.stealth import stealth_enabled, STEALTH_INIT_SCRI
|
||||
- `examples/real_browser_rpa/scripts/service/task_rpa.py` — RPA 主流程
|
||||
- `examples/real_browser_rpa/scripts/service/account_client.py` — account-manager CLI 封装
|
||||
|
||||
仿真浏览器 RPA 的 adapter 分层权威参考见 `examples/simulator_browser_rpa/scripts/service/adapter/`,**不能**替代真实浏览器 RPA 规范。
|
||||
仿真浏览器 RPA 的 adapter 分层权威参考见 `examples/simulator_browser_rpa/`(含 async `simulator_playwright.py`、薄 `simulator_rpa` adapter、`account_client.py` subprocess),**不能**替代真实浏览器 RPA 规范。
|
||||
|
||||
### 1.6 仿真浏览器 RPA 示例(必读)
|
||||
|
||||
@@ -146,12 +146,32 @@ from jiangchang_skill_core.rpa.stealth import stealth_enabled, STEALTH_INIT_SCRI
|
||||
|
||||
1. **必须先阅读** `examples/simulator_browser_rpa/README.md`
|
||||
2. 再参考:
|
||||
- `examples/simulator_browser_rpa/scripts/service/browser_session.py`
|
||||
- `examples/simulator_browser_rpa/scripts/service/adapter/`(base / mock / simulator_rpa / dispatch)
|
||||
- `examples/simulator_browser_rpa/scripts/service/task_service.py`
|
||||
- `examples/simulator_browser_rpa/scripts/service/browser_session.py` — async persistent context(**不含 goto**)
|
||||
- `examples/simulator_browser_rpa/scripts/service/simulator_playwright.py` — RPA 主流程(厚)
|
||||
- `examples/simulator_browser_rpa/scripts/service/adapter/`(薄 `simulator_rpa` + mock + dispatch)
|
||||
- `examples/simulator_browser_rpa/scripts/service/account_client.py` — account-manager subprocess
|
||||
- `examples/simulator_browser_rpa/scripts/service/task_service.py` — async 编排
|
||||
- `examples/simulator_browser_rpa/sandbox/demo_app.html`
|
||||
|
||||
> **先选类型再写代码**:真实第三方网站 → `real_browser_rpa`;自有 sandbox → `simulator_browser_rpa`。不要跨类型照抄 selector 或业务流程。
|
||||
> **先选类型再写代码**:真实第三方网站 → `real_browser_rpa`;自有 sandbox / 行业仿真 → `simulator_browser_rpa`。不要跨类型照抄 selector 或业务流程。
|
||||
|
||||
### 1.7 行业仿真平台浏览器 RPA(jc2009 类)
|
||||
|
||||
适用:**自有或共享 `sandbox.jc2009.com` 等行业仿真平台**,不是真实高风控第三方站。
|
||||
|
||||
工程范式与 §1.5 相同:
|
||||
|
||||
| 项 | 标准 |
|
||||
|----|------|
|
||||
| Playwright | **async** 贯穿;禁止 sync Playwright 用于完整 RPA 主路径 |
|
||||
| 分层 | **薄 adapter** + `{domain}_playwright.py`(示例:`simulator_playwright.py`)+ `account_client.py` subprocess |
|
||||
| 登录 | **双层**:门户 HITL(`#portal-user` / `#portal-pass` 类泛化 DOM)+ 业务系统登录(技能内自写) |
|
||||
| 账号 | `url` 用行业根,不用 `/login`;`auth_strategy=per_session_manual`;`pick_web_account` + `release_lease` |
|
||||
| 禁止 | **不要** `import account-manager` 的 `rpa_helpers` 等内部模块 |
|
||||
| Selector | 用户可见文案 / `get_by_role` / `name` 优先;`data-testid` 有则用、无则 fallback;共享 sandbox **不要求**为技能加 testid |
|
||||
| Profile | Chrome persistent profile 可能缓存旧 SPA → 联调排障:手工 `--user-data-dir` 清站点数据 |
|
||||
|
||||
权威 example:**修正后的** `examples/simulator_browser_rpa/`(不是任何生产技能仓库)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -130,6 +130,20 @@ Golden fixture 流程同理([`tests/samples/test_golden_cases.py.sample`](../t
|
||||
|
||||
---
|
||||
|
||||
## 7.1 simulator_rpa 联调检查表
|
||||
|
||||
浏览器 RPA 走 `simulator_rpa` 档位联调前,逐项确认:
|
||||
|
||||
- [ ] 数据目录 `.env` 中 `OPENCLAW_TEST_TARGET=simulator_rpa`(非 `mock` / `unit`)
|
||||
- [ ] account-manager:`platform ensure` + 账号 `active` + 有 `profile_dir`
|
||||
- [ ] 目标 sandbox UI 已部署(跨团队;本地可用 `sandbox/demo_app.html`)
|
||||
- [ ] 失败先查 `rpa-artifacts/` 截图,再查 Chrome profile 缓存(`--user-data-dir` 手工打开清站点数据)
|
||||
- [ ] 默认 `python tests/run_tests.py -v` 仍全部通过(mock 离线);example 内 `pytest` 不启真实浏览器
|
||||
|
||||
参考实现:`examples/simulator_browser_rpa/README.md`。
|
||||
|
||||
---
|
||||
|
||||
## 8. 新 skill 的最小测试清单
|
||||
|
||||
以下清单 **原文摘自 [`tests/README.md`](../tests/README.md) 「新技能最小测试清单」**(复制新仓库后逐项勾选):
|
||||
|
||||
Reference in New Issue
Block a user