Codify Skill Action sync/async and task-center gold standards (v1.0.40)
All checks were successful
技能自动化发布 / release (push) Successful in 7s

This commit is contained in:
2026-07-14 07:55:55 +08:00
parent 2e5a8d5eed
commit a7baba7210
13 changed files with 412 additions and 23 deletions

View File

@@ -525,9 +525,11 @@ metadata:
若技能需要出现在宿主**数据管理按钮**、**技能详情**、**定时任务**或 **Agent 直接调用**中,提供 `assets/actions.json`。
- 契约说明见 [`references/ACTIONS.md`](../references/ACTIONS.md)
- **运行时金标准**见 [`SKILL_ACTION_RUNTIME.md`](SKILL_ACTION_RUNTIME.md)sync/async、任务中心、Agent 禁令)
- 字段契约见 [`references/ACTIONS.md`](../references/ACTIONS.md)
- JSON Schema 见 [`assets/schemas/skill-actions.schema.json`](../assets/schemas/skill-actions.schema.json)
- 模板最小示例仅暴露 `health` / `version` / `config-path` 三个 CLI 子命令
- 模板最小示例仅暴露 `health` / `version` / `config-path`(均显式 `executionProfile: "sync"`
- 含浏览器 RPA / 长耗时的业务技能:**必须**增加至少一条 `"executionProfile": "async"` 且 `placements` 含 `agent` 的 action`POLICY-SKILL-ACTION-001`
- 没有宿主直接操作需求时,**可以删除** `actions.json`;删除后勿保留失效引用
- 复制为新技能后scaffold 会自动将 `your-skill-slug` 与 `your_skill_slug` 替换为新 slug后者用于 `LOG_LOGGER_NAME` 等下划线形式action 业务命令由技能作者自行调整
@@ -539,6 +541,25 @@ python {skillRoot}/scripts/main.py <command> <args...>
CLI 必须提供稳定退出码、结构化成功输出,以及 `ERROR:<CODE>:` / `HINT:` 错误契约(详见 `references/ACTIONS.md`)。
### 编排范式:单内核 + 多入口
长任务 / RPA 技能推荐拆分(勿把 `job_context` 塞进纯业务内核):
```text
execute_single_<biz>(...) # 鉴权 + 业务 + task_log无 job_context
cmd_run(...) # 单条job_context + execute_single + finish
cmd_run_pick(N, ...) # 批量顺序job_context + for-loop + emit(progress) + finish(partial|success|failed)
cmd_stats() # 只读 syncJSON无 job_context
```
- 批量数量用 **`pickCount` / `--pick N` 参数**(任意正整数),不写死条数。
- **顺序执行、不并发**同一浏览器 Profile / account lease。
- 详情见 [`SKILL_ACTION_RUNTIME.md`](SKILL_ACTION_RUNTIME.md) §5§6。
### 队列 + pick可选
有「待处理列表」时:队列表 `pending → processing → success/failed`;数据管理录入或 `import-*` 入库;`run --pick N` 消费;失败用 `reset` 回 `pending`不自动重试。Manifest 上配置 `*-run-pick`asynctoolbar/cron/agent
## 12. 如何接兄弟技能
如果 skill 要依赖兄弟 skill不要在业务代码里写死绝对路径。

View File

@@ -96,6 +96,8 @@ OpenClaw 技能常在客户电脑上异步执行,且大量依赖 RPA、浏览
2. 关键步骤 `emit(...)``@rpa_step` / `video.add_step`
3. 每个出口 `finish(status=..., message=..., skill=SKILL_SLUG, **fields)` — **不要**手写多行 JSON 结果
**单内核多入口**`execute_single_*` 不含 `job_context`;仅 `cmd_run` / `cmd_run_pick` 包裹。批量 pick 循环内 `checkpoint()` + `emit(..., progress=...)`;部分失败用 `finish(status="partial")`。完整范式见 [`SKILL_ACTION_RUNTIME.md`](SKILL_ACTION_RUNTIME.md)。
RPA 等待用 `interruptible_sleep`**不要**裸 `asyncio.sleep`(否则暂停响应滞后)。
暂停在**步骤边界**生效(当前 `@rpa_step` / `emit` 执行完后、下一步开始前),与影刀「当前指令完成后暂停」一致。
@@ -306,4 +308,5 @@ def cmd_run(target=None, input_id=None):
| [`CLI.md`](../references/CLI.md) | `logs` / `log-get` 命令与手工排查入口 |
| [`CONFIG.md`](CONFIG.md) | 敏感配置不进日志;`.env` 边界 |
| [`DEVELOPMENT.md`](DEVELOPMENT.md) | `service/` 层日志职责与发布前检查清单 |
| [`SKILL_ACTION_RUNTIME.md`](SKILL_ACTION_RUNTIME.md) | 任务中心 / async Job 与 `job_context` 边界 |
| [`POLICY_MATRIX.md`](POLICY_MATRIX.md) | 可自动检测的 logging hard policy 索引 |

View File

@@ -28,6 +28,7 @@
| POLICY-CONTROL-002 | `task_service.py` 须使用 `job_context(``finish(` | development/LOGGING.md §2.5、§7 | hard | 扫描 `scripts/service/task_service.py` | `tests/test_development_policy_guard.py::TestPolicyControl002` |
| POLICY-CONTROL-003 | `scripts/service/*.py` 不得裸 `asyncio.sleep`RPA 等待须 `interruptible_sleep` | development/RPA.md §0.1 | hard | 扫描 service 层 Python | `tests/test_development_policy_guard.py::TestPolicyControl003` |
| POLICY-DATA-PATH-001 | 技能拥有路径须经 `resolve_data_path` / `get_*_dir``.env.example` 禁止 `./` CWD 相对路径;业务代码禁止 `abspath(config.get(...))` | development/DATA_PATHS.md | hard | 扫描 `.env.example``scripts/**/*.py` | `tests/test_development_policy_guard.py::TestPolicyDataPath001` |
| POLICY-SKILL-ACTION-001 | 存在 `development/SKILL_ACTION_RUNTIME.md`schema 含 `executionProfile`;业务技能(非模板占位 slug若 service 含 `RpaVideoSession``actions.json` 须有 `executionProfile=async` 且 placements 含 `agent` 的 action | development/SKILL_ACTION_RUNTIME.mdreferences/ACTIONS.md | hard | 文档/schema/manifest 检查 | `tests/test_development_policy_guard.py::TestPolicySkillAction001` |
---

View File

@@ -11,9 +11,10 @@
7. [`RPA.md`](RPA.md) — 涉及浏览器 / 桌面 / 手机自动化时
8. [`CONFIG.md`](CONFIG.md) — `.env` 规范与 bootstrap 机制
9. [`DATA_PATHS.md`](DATA_PATHS.md) — 下载/导入/导出等本地文件路径标准(涉及文件读写时必读)
10. [`RUNTIME.md`](RUNTIME.md) — 共享 runtime、数据路径、发布打包与编码约定
10. [`SKILL_ACTION_RUNTIME.md`](SKILL_ACTION_RUNTIME.md) — Skill Action sync/async、任务中心、Agent 禁令、队列 pick涉及 RPA / 长任务 / 数据管理按钮 / Cron / Agent 时必读)
11. [`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)。
Agent 调用契约见 [`../references/CLI.md`](../references/CLI.md)、[`../references/SCHEMA.md`](../references/SCHEMA.md)、[`../references/ACTIONS.md`](../references/ACTIONS.md)
用户市场说明见根目录 [`README.md`](../README.md),不要写进本目录。

View File

@@ -0,0 +1,162 @@
# Skill Action Runtime宿主任务中心契约
本文是匠厂宿主 **Skill Action / 任务中心** 的技能侧金标准。涉及浏览器 RPA、长耗时任务、数据管理按钮、定时任务或 Agent 直接调用时**必读**。
**边界:**
| 文档 | 职责 |
|------|------|
| 本文 | sync/async、任务中心、Agent 禁令、编排范式、队列 pick |
| [`../references/ACTIONS.md`](../references/ACTIONS.md) | `actions.json` 字段、placements、inputSchema |
| [`LOGGING.md`](LOGGING.md) | `job_context` / `emit` / `finish` / Run Journal |
| [`DATA_PATHS.md`](DATA_PATHS.md) | 下载/导入等落盘路径 |
宿主实现细节以匠厂 Host API 为准;技能侧只需保证 manifest 与 CLI 契约稳定。
---
## 1. 核心原则
1. **宿主管调度,技能管业务** — 不自行实现任务中心 / Job 轮询 / 后台守护进程。
2. **长耗时 = async** — 开浏览器、RPA、HTTP 大文件下载等必须 `executionProfile: "async"`,进**任务中心**。
3. **Agent 禁止 `exec` 直跑长任务 CLI** — 必须 `run_skill_action`;禁止 `exec python main.py run` + `process poll` 干等。
4. **进度走 Journal**`emit` / `video.add_step` → Run JournalUI / Skill Run Card / 任务中心展示;**不靠 stdout 流**。
5. **显式声明 `executionProfile`** — 宿主省略时默认 `async`;模板要求每个 action **写明** `sync``async`,避免歧义。
---
## 2. `executionProfile`sync vs async
| 值 | 宿主行为 | 超时 | 任务中心 |
|----|----------|------|----------|
| **`sync`** | 内联等待 CLI 结束,把结果直接返回调用方 | 默认约 **30s**`SKILL_ACTION_SYNC_TIMEOUT_MS` | ❌ 不进 |
| **`async`** | 后台 spawn Job立即返回 `jobId` | Job 本身无默认墙钟上限(可暂停/停止) | ✅ 进入 |
| **省略** | 宿主视为 **async** | 同 async | ✅ |
### 硬规则
| 场景 | 必须 |
|------|------|
| 浏览器 / Playwright / RPA 主路径 | `async` + 建议 `confirmation` |
| 单次可能超过 ~20s 的网络/下载 | `async` |
| `health` / `version` / `config-path` / 纯统计 / 快速导入 | `sync` |
| 数据管理 **toolbar** | **只放 async**(宿主前端对 sync 结果会报错) |
### Agent 路径启发式(宿主行为,技能作者需知)
- 显式写了 `executionProfile` → 以显式为准。
- 未写时:描述含「统计 / 检查 / 不启动浏览器」等只读语义 → Agent 侧可当 **sync**;有 `confirmation` 的副作用 → **async**
- **模板要求一律显式写出**,不要依赖启发式。
---
## 3. 三入口如何感知 sync / async
三个入口统一走 `POST /api/skill-actions/run`,带 `source.kind`
| 入口 | `source.kind` | 推荐 |
|------|---------------|------|
| **Agent** | `agent` | `run_skill_action`;长任务 async秒回 jobId |
| **数据管理** | `data-management` | toolbar 按钮触发 async action |
| **定时任务** | `cron` | Cron 配置 async action + `pickCount` 等参数 |
技能 **不要** 在 Python 里为三个入口写三套分支;宿主读 manifest 分流。
---
## 4. Action 分类与 placements 矩阵
| Action 类型 | `executionProfile` | 典型 placements | `confirmation` |
|-------------|--------------------|-----------------|----------------|
| 运行检查 / 版本 / 配置路径 | `sync` | `skill-detail`, `agent`(只读) | 无 |
| 库 / 队列统计 | `sync` | `skill-detail`, `agent` | 无 |
| 数据导入 / 失败重置 | `sync` | `skill-detail`, `agent` | 可选 |
| **单条**副作用 RPA | `async` | `agent`, `skill-detail` | **必须** |
| **批量顺序** RPApick | `async` | **`toolbar`**, `cron`, `agent` | **必须** |
禁忌:
- 高副作用 async action 不要默认只挂 `toolbar`(应有 confirmation
-`sensitive` 参数的 action 不要挂 `toolbar` / `cron`(除非有明确安全设计)。
- 不要为了「按钮多」暴露所有 CLI 子命令。
---
## 5. 技能内编排范式(单内核 + 多入口)
推荐结构(对齐 create-account / download-video 金标准):
```text
execute_single_<biz>(...) # 纯业务:鉴权 + 核心逻辑 + task_log不含 job_context
cmd_run(...) # 单条job_context + execute_single + finish
cmd_run_pick(N, ...) # 批量job_context + for-loop execute_single + emit(progress) + finish
cmd_stats() # 只读 syncJSON stdout无 job_context
```
要点:
1. **`job_context` 只包编排层**`cmd_run` / `cmd_run_pick`),不包 `execute_single_*`
2. 批量 **顺序、不并发**;数量由参数 `pickCount` / `--pick N` 传入(不写死 100/200
3. pick 循环内:`checkpoint()` + `emit("正在处理 {i}/{total}", progress={...})`
4. 结束:全成功 `finish(success)`;部分失败 `finish(partial)`;全失败 `finish(failed)`
5. 同一浏览器 Profile / account lease**禁止并发**;顺序执行 + lease 即可。
详见 [`LOGGING.md`](LOGGING.md) §2.5 与 `scripts/service/task_service.py` 示范。
---
## 6. 队列 + pick可选Type B 批量)
有「待处理列表」的技能(账号开通、视频下载、帖子发布等)建议:
| 能力 | 约定 |
|------|------|
| 队列表 | `status`: `pending``processing``success` / `failed` |
| 入库 | 数据管理 CRUD`import-*`(相对 `{skill_data}/imports/`,见 [`DATA_PATHS.md`](DATA_PATHS.md) |
| 消费 | `run --pick N`,默认仅 `pending` |
| 重试 | `reset` 或数据管理改 `pending`**failed 不要自动重试** |
| 批次 | 可选 `batch_id`,便于筛选与任务中心对照 |
| Manifest | `*-run-pick``async``placements``toolbar` / `cron` / `agent``inputSchema.pickCount` |
批量有两种合理形态(都是**顺序**
| 形态 | 任务中心条数 | 适用 |
|------|-------------|------|
| 一次 `run-pick` 处理 N 条 | **1** 条 Job | 同类 RPA、同 Profile、定时消费队列 |
| Agent/UI 触发 N 次单条 `run` | **N** 条 Job | 每条独立追踪 / 独立重试 |
默认优先 **一次 pick、一条 Job**(与 create-account `--pick`、download `--pick` 一致)。
---
## 7. Agent / SKILL.md 契约(复制后必改)
业务技能 `SKILL.md` 应明确:
1. 副作用任务必须通过宿主 **Skill Action**`run_skill_action`)调用。
2. **禁止**对长任务使用 `exec` + `process poll`
3. 单条 vs 批量 action id 与参数(如 `url` / `pickCount`)。
4. 长任务进度看**任务中心** / Skill Run Card不等 CLI stdout。
模板源仓库的 `SKILL.md` 含占位段落scaffold 后按业务改写。
---
## 8. Policy
自动检测索引见 [`POLICY_MATRIX.md`](POLICY_MATRIX.md)
- **POLICY-SKILL-ACTION-001**`SKILL_ACTION_RUNTIME.md` 存在schema 含 `executionProfile`;有 RPA 的业务技能必须声明 async agent action。
---
## 9. 与宿主 API参考
| API | 用途 |
|-----|------|
| `GET /api/skill-actions/{skillSlug}` | 读 manifest |
| `POST /api/skill-actions/run` | 执行 actionsync inline / async job |
| `GET /api/skill-actions/jobs` | 任务中心列表 |
| `GET /api/skill-actions/jobs/{jobId}` | 单 Job 详情 / 事件 |
Agent 工具(插件):`list_skill_actions``get_skill_action``run_skill_action`;正常对话**不要**轮询 `get_skill_action_job`(交给 UI / 任务中心)。