199 lines
10 KiB
Markdown
199 lines
10 KiB
Markdown
# Skill Action Runtime(宿主任务中心契约)
|
||
|
||
本文是匠厂宿主 **Skill Action / 任务中心** 的技能侧金标准。涉及浏览器 RPA、长耗时任务、数据管理按钮、定时任务或 Agent 直接调用时**必读**。
|
||
|
||
**边界:**
|
||
|
||
| 文档 | 职责 |
|
||
|------|------|
|
||
| 本文 | sync/async、任务中心、Agent 禁令、单内核编排、队列 pick、同步 vs 导出 |
|
||
| [`../references/ACTIONS.md`](../references/ACTIONS.md) | `actions.json` 字段、placements、`bind.tables`、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. **单业务内核、多入口** — 数据管理、定时任务、Agent、技能详情与直接 CLI 复用同一 domain service;禁止按入口复制业务逻辑。
|
||
3. **五职责正交** — `placements` / `bind.tables` / `executionProfile` / `entrypoint` / domain service 各管一事(见 ACTIONS.md)。
|
||
4. **长耗时建议 async** — 开浏览器、RPA、HTTP 大文件下载等建议 `executionProfile: "async"`,进**任务中心**;这是选择建议,**不**限制可以出现在哪些 placement。
|
||
5. **Agent 禁止 `exec` 直跑长任务 CLI** — 必须 `run_skill_action`;禁止 `exec python main.py run` + `process poll` 干等。
|
||
6. **进度走 Journal** — `emit` / `video.add_step` → Run Journal;UI / Skill Run Card / 任务中心展示;**不靠 stdout 流**。
|
||
7. **显式声明 `executionProfile`** — 每个 action **必须**写明 `sync` 或 `async`;禁止依赖宿主缺省;禁止第三种模糊模式(`auto` / `background` / `deferred` 等)。
|
||
|
||
---
|
||
|
||
## 2. `executionProfile`:sync vs async
|
||
|
||
| 值 | 宿主行为 | 超时 | 任务中心 |
|
||
|----|----------|------|----------|
|
||
| **`sync`** | 调用方等待 CLI 结束,直接返回结构化结果或结构化错误;**不**创建后台 Job | 默认约 **30s**(`SKILL_ACTION_SYNC_TIMEOUT_MS`) | ❌ 不进 |
|
||
| **`async`** | 后台 spawn Job,立即返回 `jobId`;`emit` / `checkpoint` / `finish`;长任务应支持暂停/停止/取消检查 | Job 本身无默认墙钟上限 | ✅ 进入 |
|
||
|
||
直接执行 CLI:终端等待进程结束。宿主经 Action 调用同一 CLI:再按 `executionProfile` 分流。技能不得自建任务中心。
|
||
|
||
### 选择建议(不是 placement 硬限制)
|
||
|
||
| 场景 | 建议 |
|
||
|------|------|
|
||
| 浏览器 / Playwright / RPA 主路径 | `async` + 建议 `confirmation` |
|
||
| 单次可能超过 ~20s 的网络/下载/同步 | `async` |
|
||
| `health` / `version` / `config-path` / 纯统计 / 秒级查询 | `sync` |
|
||
| 任意 placement(含 toolbar) | 允许 sync 或 async;以 manifest 为准 |
|
||
|
||
合法:`sync|async` × `toolbar|cron|agent|skill-detail`。
|
||
|
||
历史说明:旧文档曾错误地把数据管理按钮入口与异步执行方式绑死。该约束**已废止**;模板测试与 Schema **不得**再建立「入口位置决定 sync/async」一类硬耦合。宿主省略 `executionProfile` 时的兼容行为以宿主实现为准,**新技能不得依赖**。
|
||
|
||
---
|
||
|
||
## 3. 多入口如何感知 sync / async
|
||
|
||
多个入口统一走 `POST /api/skill-actions/run`,可能带 `source.kind`:
|
||
|
||
| 入口 | 常见 `source.kind` | 说明 |
|
||
|------|-------------------|------|
|
||
| **Agent** | `agent` | `run_skill_action`;按 manifest 的 executionProfile 执行 |
|
||
| **数据管理** | `data-management` | toolbar 按钮;须 `bind.tables` |
|
||
| **定时任务** | `cron` | Cron 配置参数后调用同一 Action |
|
||
| **技能详情** | (依宿主) | 与上同一 CLI / 同一业务内核 |
|
||
|
||
技能 **不要** 在 Python 里按 `source` / placement 写业务分叉;宿主读 manifest 分流展示与等待策略。
|
||
|
||
---
|
||
|
||
## 4. Action 分类与 placements(示例,不是限制)
|
||
|
||
下表只表示常见组合示例。**placements 以 manifest 为准;sync/async 不影响展示入口。**
|
||
|
||
| Action 类型 | 常见 `executionProfile` | 常见 placements | `confirmation` |
|
||
|-------------|-------------------------|-----------------|----------------|
|
||
| 运行检查 / 版本 / 配置路径 | `sync` | `skill-detail`, `agent` | 无 |
|
||
| 库 / 队列统计 | `sync` | `skill-detail`, `agent` | 无 |
|
||
| 外源 → 本地库同步 | `sync` 或 `async` | 可含 `toolbar`(须 `bind.tables`)、`cron`、`agent` | 可选 |
|
||
| 数据导入 / 失败重置 | `sync` 或 `async` | `skill-detail`, `agent` | 可选 |
|
||
| **单条**副作用 RPA | `async`(建议) | `agent`, `skill-detail` | **建议** |
|
||
| **批量顺序** RPA(pick) | `async`(建议) | `toolbar`, `cron`, `agent` | **建议** |
|
||
|
||
禁忌:
|
||
|
||
- 高副作用 action 不要默认只挂 `toolbar`(应有 confirmation)。
|
||
- 含 `sensitive` 参数的 action 不要挂 `toolbar` / `cron`(除非有明确安全设计)。
|
||
- 不要为了「按钮多」暴露所有 CLI 子命令。
|
||
- 不要按入口复制多套采集 / 同步 / 处理实现。
|
||
|
||
---
|
||
|
||
## 5. 技能内编排范式(单内核 + 多入口)
|
||
|
||
推荐分层:
|
||
|
||
```text
|
||
scripts/cli/app.py # 参数解析 → 调用 task / service
|
||
scripts/service/task_service.py # job_context / emit / checkpoint / finish / 错误转换
|
||
scripts/service/<domain>_service.py # 唯一业务内核
|
||
scripts/db/*_repository.py # 只负责读写与事务
|
||
assets/actions.json # 声明入口、参数、placement、executionProfile、bind
|
||
```
|
||
|
||
长任务 / 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 execute_single + emit(progress) + finish
|
||
cmd_stats() # 只读 sync:JSON stdout,无 job_context
|
||
```
|
||
|
||
要点:
|
||
|
||
1. **`job_context` 只包编排层**(`cmd_run` / `cmd_run_pick`),不包 `execute_single_*` / domain service。
|
||
2. 批量 **顺序、不并发**;数量由参数 `pickCount` / `--pick N` 传入。
|
||
3. pick 循环内:`checkpoint()` + `emit("正在处理 {i}/{total}", progress={...})`。
|
||
4. 结束:全成功 `finish(success)`;部分失败 `finish(partial)`;全失败 `finish(failed)`。
|
||
5. 同一浏览器 Profile / account lease:**禁止并发**。
|
||
6. 兼容旧命令(例如旧 export 需先刷新)必须调用同一 sync / domain 内核,禁止重写采集逻辑。
|
||
|
||
详见 [`LOGGING.md`](LOGGING.md) §2.5 与 `scripts/service/task_service.py` 示范。可复用契约样例见 `tests/samples/test_action_core_contract.py.sample`、`tests/samples/test_sync_contract.py.sample`。
|
||
|
||
---
|
||
|
||
## 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`;有 toolbar 则 `bind.tables` 必填 |
|
||
|
||
批量有两种合理形态(都是**顺序**):
|
||
|
||
| 形态 | 任务中心条数 | 适用 |
|
||
|------|-------------|------|
|
||
| 一次 `run-pick` 处理 N 条 | **1** 条 Job | 同类 RPA、同 Profile、定时消费队列 |
|
||
| Agent/UI 触发 N 次单条 `run` | **N** 条 Job | 每条独立追踪 / 独立重试 |
|
||
|
||
默认优先 **一次 pick、一条 Job**。
|
||
|
||
---
|
||
|
||
## 7. 业务同步与系统导出
|
||
|
||
| 能力 | 方向 | 负责方 |
|
||
|------|------|--------|
|
||
| 同步 / refresh / collect | 外部来源 → 技能本地 SQLite | 技能 domain service |
|
||
| 导出当前数据表 | 本地库 → CSV/Excel | **宿主**数据管理统一导出 |
|
||
| 特殊业务报告 | 多表合并 / 特殊格式 / 附加计算 | 仅系统导出不足时提供 `export-*` |
|
||
|
||
同步 Action 默认写库、不写导出文件。通用幂等 / 事务 / 空结果保护见 [`../references/SCHEMA.md`](../references/SCHEMA.md)。
|
||
|
||
---
|
||
|
||
## 8. 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。
|
||
5. 多入口复用同一业务内核;异步 Action 进入任务中心。
|
||
|
||
模板源仓库的 `SKILL.md` 含占位段落;scaffold 后按业务改写。
|
||
|
||
---
|
||
|
||
## 9. Policy
|
||
|
||
自动检测索引见 [`POLICY_MATRIX.md`](POLICY_MATRIX.md):
|
||
|
||
- **POLICY-SKILL-ACTION-001**:Runtime 文档存在;schema 含 `executionProfile`;有 RPA 的业务技能须声明 async agent action。
|
||
- **POLICY-SKILL-ACTION-002**:每个 Action 显式声明 `executionProfile`(sync/async)。
|
||
- **POLICY-SKILL-ACTION-003**:toolbar Action 必须声明合法 `bind.tables`。
|
||
- **POLICY-SKILL-ACTION-004**:placements 与 executionProfile 正交(文档/测试不得写死耦合)。
|
||
- **POLICY-ARCH-CORE-001** / **POLICY-DATA-SYNC-001**:见矩阵;完整语义多用 sample / code review。
|
||
|
||
---
|
||
|
||
## 10. 与宿主 API(参考)
|
||
|
||
| API | 用途 |
|
||
|-----|------|
|
||
| `GET /api/skill-actions/{skillSlug}` | 读 manifest |
|
||
| `POST /api/skill-actions/run` | 执行 action(sync 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 / 任务中心)。
|
||
|
||
表级 `bind.tables` 过滤依赖宿主支持;旧宿主忽略绑定时,toolbar Action 可能在技能全部数据表显示——新技能仍须显式绑定,待宿主升级后完整按表过滤生效。
|