Release v1.0.107: precipitate bind.selectionMode contract
All checks were successful
技能自动化发布 / release (push) Successful in 5s
All checks were successful
技能自动化发布 / release (push) Successful in 5s
This commit is contained in:
@@ -9,6 +9,12 @@
|
||||
- 小节正文写用户能看懂的变化(新能力、修复、注意事项),避免堆砌内部实现细节
|
||||
- 打 tag 前**必须**为即将发布的版本新增一节;找不到匹配小节时,本次发布不会更新 changelog 字段
|
||||
|
||||
## 1.0.107
|
||||
|
||||
- 沉淀数据管理 `bind.selectionMode` 契约(`required` / `none` / `optional`):同一按钮可「有勾选走 ids、无勾选走 pickCount」
|
||||
- 明确省略时的宿主兼容推断、空选数量字段名约定,以及勿再拆同义双按钮
|
||||
- 更新 ACTIONS.md / Schema / SKILL_ACTION_RUNTIME / CHECKLIST A4-9;新增 `selection-mode-optional.action.example.json`
|
||||
|
||||
## 1.0.106
|
||||
|
||||
- 文档契约:补充可选 `metadata.openclaw.brands`(OEM 市场编码 → `skill_market_relations`)
|
||||
|
||||
3
SKILL.md
3
SKILL.md
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: 技能开发模板(通用业务版)
|
||||
description: "OpenClaw 通用业务技能开发模板,供复制后定制新业务 skill。定制步骤见 development/DEVELOPMENT.md。"
|
||||
version: 1.0.106
|
||||
version: 1.0.107
|
||||
author: 深圳匠厂科技有限公司
|
||||
metadata:
|
||||
openclaw:
|
||||
@@ -38,6 +38,7 @@ allowed-tools:
|
||||
- **数据管理**:既是 **UI 执行面**(点按钮走与对话相同的闭环),也是数据与过程可见;不是「只读库」。
|
||||
- **`placements`**:只决定 Action **出现在哪里**(toolbar / row / batch / cron / agent / skill-detail)。其中 `row` 表示**行级入口**(宿主可呈现为操作列、行右键、行内「⋯」等;技能配什么就显示什么,无独立菜单 DSL)。数据管理技能按钮顺序见 `actions` **数组相对顺序**(详见 `references/ACTIONS.md`),无独立 sortOrder。
|
||||
- **`bind.tables`**:只决定数据管理出现在哪些表;含 `toolbar` 时**必须**显式非空绑定。
|
||||
- **`bind.selectionMode`(可选)**:表勾选如何驱动 Action(`required` / `none` / `optional`);省略由宿主推断。同一能力勿拆两个同义顶栏按钮,见 `references/ACTIONS.md`。
|
||||
- **`executionProfile`**:只决定执行方式——`sync` 当场返回结果,`async` 进**任务中心**。与 placements / 入口**无关**。心智上多数为 sync,仅长任务 / RPA 标 async;宿主省略该字段时按 sync。每个 Action **仍必须**显式写 `sync` 或 `async`。
|
||||
- **`policy`(可选)**:需要按用户/角色控制数据管理按钮或行列时,在 `actions.json` 顶层启用 Data Policy,由技能 `policy` CLI 输出 Snapshot;**未启用 = 与今日一致(L0)**。详见 `references/POLICY.md`。用户/角色数据源(飞书/库/API)属技能内部,宿主不托管。
|
||||
- **`cellPresentation`(可选)**:需要数据管理「某格特殊标色/强调」时启用;技能按当前数据写入呈现(语义 tone),宿主映射主题样式;**未启用 = P0 无标色**。用途不限(超时、预警、驳回等)。详见 `references/CELL_PRESENTATION.md`。
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
- `actions.json`:Skill Action manifest 最小示例(按入口定位表决定是否保留/扩展;见 `development/PRODUCT_SURFACES.md`)。每个 action **必须**显式声明 `executionProfile`(`sync` \| `async`)。默认仅 `health` / `version` / `config-path`,不放 toolbar,故无 `bind` 示例。
|
||||
- **业务技能注意:** 若主路径在数据管理,准备/载入/导入类 Action 应挂 `toolbar` + `bind.tables`(用户看得见),**不要**只挂 `skill-detail` 却在教程里写成「技能详情点按钮」。见 `development/TUTORIAL_SURFACES.md` §5、`references/ACTIONS.md`「用户可见性」。
|
||||
- `html/example-report.html`:HTML 报告页最小壳(`{{TITLE}}` / `{{GENERATED_AT}}` / `{{BODY}}`);含数据管理 iframe 预览布局基线(流体铺满、禁横向滚动);渲染后须写入数据目录 `html/`,见 `references/ACTIONS.md`「HTML 页面报告」。
|
||||
- `examples/`:CLI 成功输出形状示例、Action 形状参考(含 `path-root-file-action.example.json`、`selection-label-column.action.example.json`、`render-html.action.example.json` 等;虚构路径与数据)。
|
||||
- `examples/`:CLI 成功输出形状示例、Action 形状参考(含 `path-root-file-action.example.json`、`selection-label-column.action.example.json`、`selection-mode-optional.action.example.json`、`render-html.action.example.json` 等;虚构路径与数据)。
|
||||
- `schemas/`:轻量 JSON Schema(`skill-actions.schema.json` 为**新技能严格规范**)。
|
||||
|
||||
`skill-actions.schema.json` 使用 `additionalProperties: false`。正式支持 `bind.tables`(toolbar Action 必填)与可选 `bind.inputMapping` / `columnMapping` / **`labelColumn`**(选择摘要标签列);placements 含 `toolbar` / `row` / `batch` / `cron` / `agent` / `skill-detail`(对齐匠厂宿主)。数据管理 confirm/form 弹层默认展示「已选择」摘要;**form + 有摘要时映射 `readOnly` 默认不占参数区(仍提交)**,可选 **`revealInForm`** 强制显示。可选 `hoverHint` 为数据管理工具栏悬停(省略不显示,不回退)。`concurrency`/`locks` 仍为预留。`placements` 与 `executionProfile` 正交——进任务中心只看 `async`,与入口无关。表级 Action 与 Agent 契约见 [`references/ACTIONS.md`](../references/ACTIONS.md);开发深度规范见 [`development/SKILL_ACTION_RUNTIME.md`](../development/SKILL_ACTION_RUNTIME.md)。
|
||||
`skill-actions.schema.json` 使用 `additionalProperties: false`。正式支持 `bind.tables`(toolbar Action 必填)与可选 `bind.inputMapping` / `columnMapping` / **`labelColumn`**(选择摘要标签列)/ **`selectionMode`**(`required` \| `none` \| `optional`:表勾选如何驱动 Action;省略则宿主兼容推断)。placements 含 `toolbar` / `row` / `batch` / `cron` / `agent` / `skill-detail`(对齐匠厂宿主)。数据管理 confirm/form 弹层在会应用勾选时展示「已选择」摘要;**form + 有摘要时映射 `readOnly` 默认不占参数区(仍提交)**,可选 **`revealInForm`** 强制显示。可选 `hoverHint` 为数据管理工具栏悬停(省略不显示,不回退)。`concurrency`/`locks` 仍为预留。`placements` 与 `executionProfile` 正交——进任务中心只看 `async`,与入口无关。表级 Action 与 Agent 契约见 [`references/ACTIONS.md`](../references/ACTIONS.md);开发深度规范见 [`development/SKILL_ACTION_RUNTIME.md`](../development/SKILL_ACTION_RUNTIME.md)。
|
||||
|
||||
- 用户市场四 Tab 见根目录 [`README.md`](../README.md) / [`TUTORIAL.md`](../TUTORIAL.md) / [`DEMO.md`](../DEMO.md) / [`CHANGELOG.md`](../CHANGELOG.md);写法契约见 [`development/TUTORIAL_SURFACES.md`](../development/TUTORIAL_SURFACES.md)
|
||||
- Agent 调用/编排参考见 [`references/`](../references/)(含 [`ACTIONS.md`](../references/ACTIONS.md))
|
||||
|
||||
@@ -6,4 +6,6 @@
|
||||
- `render-html.action.example.json`:HTML 报告「重新生成」Action 形状参考(固定 id `render-html`;见 `references/ACTIONS.md`)。
|
||||
- `lookup-action.example.json`:Action 内联 Lookup 形状参考(单选 + `multiple: true` 多选并列;跨表引用勿填编号;见 `references/ACTIONS.md`「跨表引用:Lookup」)。
|
||||
- `visible-when-action.example.json`:Action 参数字段条件显隐 `visibleWhen` 形状参考(互斥模式联动;见 `references/ACTIONS.md`「字段条件显隐」;≠ Policy L3)。
|
||||
- `selection-label-column.action.example.json`:选择摘要 `bind.labelColumn` 形状参考(见 `references/ACTIONS.md`「选择摘要」)。
|
||||
- `selection-mode-optional.action.example.json`:`bind.selectionMode: "optional"` 智能勾选/按数量合并形状参考(见 `references/ACTIONS.md`「勾选驱动模式」)。
|
||||
- `replaces-create.action.example.json` / `replaces-update.action.example.json` / `replaces-delete.action.example.json` / `replaces-import.action.example.json`:数据管理默认按钮接管(`replaces`)形状参考;**import 时 UI 仍用宿主「导入数据」面板**,确认后调技能写库(见 `references/ACTIONS.md`「`replaces`」)。
|
||||
|
||||
46
assets/examples/selection-mode-optional.action.example.json
Normal file
46
assets/examples/selection-mode-optional.action.example.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"id": "process-queue",
|
||||
"label": "处理队列",
|
||||
"description": "有勾选则按编号处理;无勾选则按 pickCount 从可操作队列领取。示例:bind.selectionMode=optional,避免拆成两个同义顶栏按钮。",
|
||||
"placements": ["toolbar", "batch", "cron", "agent"],
|
||||
"executionProfile": "async",
|
||||
"interaction": "form",
|
||||
"confirmation": {
|
||||
"message": "将按技能业务规则处理记录(有勾选则处理勾选;未勾选则按数量从队列领取)。"
|
||||
},
|
||||
"bind": {
|
||||
"tables": ["business_items"],
|
||||
"selectionMode": "optional",
|
||||
"labelColumn": "display_name",
|
||||
"inputMapping": {
|
||||
"itemIds": "$selection.ids"
|
||||
}
|
||||
},
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"required": ["itemIds", "pickCount"],
|
||||
"properties": {
|
||||
"itemIds": {
|
||||
"type": "string",
|
||||
"title": "编号列表",
|
||||
"description": "勾选时由宿主预填;无勾选时不要传",
|
||||
"readOnly": true
|
||||
},
|
||||
"pickCount": {
|
||||
"type": "number",
|
||||
"title": "处理数量",
|
||||
"description": "未勾选时:从队列领取可操作状态记录的条数",
|
||||
"default": 1,
|
||||
"minimum": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"entrypoint": {
|
||||
"type": "cli",
|
||||
"command": "process",
|
||||
"args": ["--ids", "{{itemIds}}", "--pick", "{{pickCount}}"]
|
||||
},
|
||||
"hostEffects": {
|
||||
"onSuccess": ["reloadTable", "clearSelection"]
|
||||
}
|
||||
}
|
||||
@@ -311,9 +311,14 @@
|
||||
"minLength": 1,
|
||||
"pattern": "^[a-z][a-z0-9_]*$",
|
||||
"description": "可选。数据管理 Action 确认/表单弹层「已选择」摘要用的可读标签列(#id + 标签)。仅影响展示,不改变提交 payload。省略时宿主按常见列名启发(title/name 等),再不行只显示编号。"
|
||||
},
|
||||
"selectionMode": {
|
||||
"type": "string",
|
||||
"enum": ["required", "none", "optional"],
|
||||
"description": "可选。数据管理勾选如何驱动本 Action:required=必须有勾选(无勾选禁用);none=忽略表勾选(不出现假「已选择」);optional=有勾选走 $selection.ids,无勾选走 pickCount/maxLeads 等空选数量字段。省略时宿主推断:有 $selection.ids 或 batch → required,否则 → none。与 placements/executionProfile 正交。"
|
||||
}
|
||||
},
|
||||
"description": "表级绑定;toolbar 必填。可选 inputMapping / columnMapping / labelColumn。concurrency/locks 勿写入。"
|
||||
"description": "表级绑定;toolbar 必填。可选 inputMapping / columnMapping / labelColumn / selectionMode。concurrency/locks 勿写入。"
|
||||
},
|
||||
"hostEffectId": {
|
||||
"type": "string",
|
||||
|
||||
@@ -111,6 +111,7 @@ checklist_version: 1.0
|
||||
- [ ] A4-6 **P0** 若 Action 需引用同库另一张业务表(话术/平台/账号等):参数为 Lookup 下拉(内联 `lookup` 或绑列),**不是**手填内部编号;可选「自动」可留空提交
|
||||
- [ ] A4-7 **P1** 若 Action 有互斥采集/操作模式(如「按关键词 / 按主页」):用 `inputSchema` 字段级 **`visibleWhen`** 联动显隐,勿只靠 `description` 灰字说明「仅某某时填写」(见 `references/ACTIONS.md`;勿与 Policy L3 行态 `visibleWhen` 混淆)
|
||||
- [ ] A4-8 **P1** 行内/勾选打开的 `form`:有「已选择」时参数区不应再重复映射主键(`inputMapping` + `readOnly`);需要强制露出时用 `revealInForm`,**禁止**用 `visibleWhen` 藏主键(会不提交)
|
||||
- [ ] A4-9 **P1** 若同一能力既支持「勾选处理」又支持「按数量从队列领取」:用一个 Action + `bind.selectionMode: "optional"`(勿拆两个同义顶栏按钮);无勾选可点、有勾选显示「已选择」、空选数量字段用 `pickCount` 等约定名(见 `references/ACTIONS.md`)
|
||||
---
|
||||
|
||||
## 5. 账号与浏览器会话(网页 RPA 适用;其他形态标 N/A 或改测等价项)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
| 文档 | 职责 |
|
||||
|------|------|
|
||||
| 本文 | sync/async、任务中心、Agent 禁令、单内核编排、队列 pick、同步 vs 导出 |
|
||||
| [`../references/ACTIONS.md`](../references/ACTIONS.md) | `actions.json` 字段、placements、`bind.tables`、inputSchema、跨表 Lookup、字段条件显隐 `visibleWhen`、本地路径 `file`/`directory` + 可选 **`pathRoot`**、选择摘要「已选择」与映射 **`readOnly` / `revealInForm`**、**按钮中文名 `label` 参考** |
|
||||
| [`../references/ACTIONS.md`](../references/ACTIONS.md) | `actions.json` 字段、placements、`bind.tables`、`bind.selectionMode`、inputSchema、跨表 Lookup、字段条件显隐 `visibleWhen`、本地路径 `file`/`directory` + 可选 **`pathRoot`**、选择摘要「已选择」与映射 **`readOnly` / `revealInForm`**、**按钮中文名 `label` 参考** |
|
||||
| [`LOGGING.md`](LOGGING.md) | `job_context` / `emit` / `finish` / Run Journal |
|
||||
| [`DATA_PATHS.md`](DATA_PATHS.md) | 下载/导入等落盘路径 |
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
1. **宿主管调度,技能管业务** — 不自行实现任务中心 / Job 轮询 / 后台守护进程。
|
||||
2. **单业务内核、多入口** — 数据管理、定时任务、Agent、技能详情与直接 CLI 复用同一 domain service;禁止按入口复制业务逻辑。
|
||||
3. **五职责正交** — `placements` / `bind.tables` / `executionProfile` / `entrypoint` / domain service 各管一事(见 ACTIONS.md)。可选第六轴 **policy**(见 `references/POLICY.md`):未启用 = L0 与今日一致。可选 **`hostEffects` / `steps`**(见 ACTIONS.md):数据管理交互前后的 UI/级联编排;省略 = 不额外改 UI(匠厂宿主 ≥2.8.5)。可选 **`hoverHint`**(见 ACTIONS.md):数据管理工具栏悬停;省略 = 不显示,不回退说明或确认黄条。可选 **`visibleWhen`**(见 ACTIONS.md):Action 参数表单字段条件显隐;省略 = 字段始终平铺;**勿与** Policy L3 行态 `visibleWhen` 混淆;**勿**用其藏映射主键。可选 **`pathRoot`**(见 ACTIONS.md):`file`/`directory` 原生选路对话框起始目录(相对技能数据根;省略默认 `{skill_data}/input`)。可选 **`bind.labelColumn`**(见 ACTIONS.md):选择摘要可读标签列;省略 = 宿主常见列名启发。可选 **`revealInForm`**(见 ACTIONS.md):有「已选择」时仍强制显示某 `readOnly` 字段;省略 = 映射只读默认不占 form 参数区(仍提交)。可选 **`cellPresentation`**(见 `references/CELL_PRESENTATION.md`):单元格语义标色;省略 = P0。
|
||||
3. **五职责正交** — `placements` / `bind.tables` / `executionProfile` / `entrypoint` / domain service 各管一事(见 ACTIONS.md)。可选第六轴 **policy**(见 `references/POLICY.md`):未启用 = L0 与今日一致。可选 **`hostEffects` / `steps`**(见 ACTIONS.md):数据管理交互前后的 UI/级联编排;省略 = 不额外改 UI(匠厂宿主 ≥2.8.5)。可选 **`hoverHint`**(见 ACTIONS.md):数据管理工具栏悬停;省略 = 不显示,不回退说明或确认黄条。可选 **`visibleWhen`**(见 ACTIONS.md):Action 参数表单字段条件显隐;省略 = 字段始终平铺;**勿与** Policy L3 行态 `visibleWhen` 混淆;**勿**用其藏映射主键。可选 **`pathRoot`**(见 ACTIONS.md):`file`/`directory` 原生选路对话框起始目录(相对技能数据根;省略默认 `{skill_data}/input`)。可选 **`bind.labelColumn`**(见 ACTIONS.md):选择摘要可读标签列;省略 = 宿主常见列名启发。可选 **`bind.selectionMode`**(见 ACTIONS.md):表勾选如何驱动 Action(`required` / `none` / `optional`);省略 = 宿主按 `$selection.ids` / `batch` 推断。可选 **`revealInForm`**(见 ACTIONS.md):有「已选择」时仍强制显示某 `readOnly` 字段;省略 = 映射只读默认不占 form 参数区(仍提交)。可选 **`cellPresentation`**(见 `references/CELL_PRESENTATION.md`):单元格语义标色;省略 = P0。
|
||||
4. **长耗时建议 async** — 开浏览器、RPA、HTTP 大文件下载等建议 `executionProfile: "async"`,进**任务中心**;这是对**方法**的选择,**不**限制可以出现在哪些 placement / 入口。
|
||||
5. **Agent:短 CLI / 长 Action** — 短查询可用共享 Python bash CLI;长任务 / RPA **禁止** `exec` + `process poll`,必须 `run_skill_action`。
|
||||
6. **进度走 Journal** — `emit` / `video.add_step` → Run Journal;UI / Skill Run Card / 任务中心展示;**不靠 stdout 流**。
|
||||
|
||||
@@ -107,7 +107,7 @@ Action 是否提供、挂哪些 `placements`,由本技能 **入口定位表**
|
||||
| entrypoint | `type = cli`、`command`、`args`(**必填** JSON 数组,项为 `string` / `number` / `boolean`) |
|
||||
| placements | `toolbar`、`row`、`batch`、`skill-detail`、`agent`、`cron`;仅 `replaces` 时可为空数组 |
|
||||
| **replaces** | 可选 `"create"` \| `"update"` \| `"delete"` \| `"import"` — 接管默认新增/编辑/删除/导入(须 `bind.tables`) |
|
||||
| **bind** | `{ "tables": ["business_table"] }`;可选 `inputMapping`、`columnMapping`、**`labelColumn`**(行内/批量预填与选择摘要标签,见下节) |
|
||||
| **bind** | `{ "tables": ["business_table"] }`;可选 `inputMapping`、`columnMapping`、**`labelColumn`**、**`selectionMode`**(行内/批量预填、选择摘要标签、勾选驱动模式,见下节) |
|
||||
| **policy** | 可选;`enabled` + `entrypoint`(推荐 `policy` CLI);见 POLICY.md。未启用 = L0 |
|
||||
| **cellPresentation** | 可选;`{ "enabled": true }` 时宿主应加载单元格呈现;见 [`CELL_PRESENTATION.md`](CELL_PRESENTATION.md)。未启用 = P0 |
|
||||
| inputSchema | 根 `type: object`;properties 使用 `string` / `number` / `boolean`;支持 `enum`、`default`、`required`、`sensitive`、`readOnly`、可选 **`revealInForm`**;可选 `display_type` / `format`(含 `file` / `directory` 等);可选 **`pathRoot`**(file/directory 起始目录,相对技能数据根);可选 **`visibleWhen`**(字段条件显隐,见专节) |
|
||||
@@ -133,7 +133,7 @@ Action 是否提供、挂哪些 `placements`,由本技能 **入口定位表**
|
||||
|
||||
规则:
|
||||
|
||||
- `bind` 为 object,`additionalProperties: false`;当前允许 `tables`(必填键当存在 bind 时)与可选 `inputMapping`、`columnMapping`、**`labelColumn`**。
|
||||
- `bind` 为 object,`additionalProperties: false`;当前允许 `tables`(必填键当存在 bind 时)与可选 `inputMapping`、`columnMapping`、**`labelColumn`**、**`selectionMode`**。
|
||||
- `tables` 非空数组、元素唯一、英文 **snake_case**、不得为空字符串。
|
||||
- **`placements` 含 `toolbar` 时必须显式声明非空 `bind.tables`**(模板 Schema `if/then` + 自动测试强制)。
|
||||
- `row` / `batch` **建议**同样声明 `bind.tables`,避免在无关表上露出按钮;未声明时宿主可能按兼容逻辑在更多表上展示。
|
||||
@@ -142,14 +142,38 @@ Action 是否提供、挂哪些 `placements`,由本技能 **入口定位表**
|
||||
- **`inputMapping`(可选)**:把行/勾选映射到 `inputSchema` 字段,例如 `"leadId": "$row.$pk"`、`"ids": "$selection.ids"`。适合 `row` / `batch`。宿主仍会提交这些字段。映射字段建议标 `readOnly: true`:无「已选择」时只读展示;**有「已选择」时默认不占参数区**(仍提交,见下节)。不要用 `visibleWhen` 去「藏」映射主键。
|
||||
- **`columnMapping`(可选)**:把 inputSchema 属性名映射到物理列名,供表单复用列展示名 / lookup。
|
||||
- **`labelColumn`(可选)**:物理列名,供数据管理 Action 弹层「已选择」摘要展示 `#id + 标签`。**仅影响展示,不改变 CLI/提交 payload,也不决定业务是否跳过某些状态。** 省略时宿主用常见列名启发(如 `title` / `name` / `nickname` 等);再没有则只显示编号。列名不常见、或启发会选错列时再显式声明。
|
||||
- **`selectionMode`(可选)**:数据管理**表勾选**如何驱动本 Action(与 `placements` / `executionProfile` 正交)。见下节「勾选驱动模式」。
|
||||
- `concurrency` / `locks` 仍未稳定,**不要**写入新技能 manifest。
|
||||
|
||||
### 数据管理:勾选驱动模式 `bind.selectionMode`
|
||||
|
||||
同一业务能力应尽量用**一个** Action(多个 `placements`),避免「勾选下载」与「按数量处理队列」拆成两个同义顶栏按钮、却让用户误以为勾选生效。
|
||||
|
||||
| 值 | 含义 | 典型场景 |
|
||||
|----|------|----------|
|
||||
| `required` | 必须有表勾选;无勾选时宿主**禁用**按钮;弹层可显示「已选择」 | 经典批量:仅处理勾选行 |
|
||||
| `none` | **忽略**表勾选;即使勾选了也不显示「已选择」、也不把 `$selection.ids` 带进提交 | 经典工具栏「按数量从队列领取」 |
|
||||
| `optional` | **智能合并**:有勾选 → 走 `$selection.ids`(显示「已选择」);无勾选 → 走空选数量字段(如 `pickCount`) | 统一「视频下载 / 处理队列」一类按钮 |
|
||||
| **省略** | 宿主兼容推断:`inputMapping` 含 `$selection.ids` 或 `placements` 含 `batch` → `required`;否则 → `none` | 旧技能零改动 |
|
||||
|
||||
**`optional` 写法要点:**
|
||||
|
||||
1. `bind.inputMapping` 声明 `"itemIds": "$selection.ids"`(字段名自定),并 `selectionMode: "optional"`。
|
||||
2. `inputSchema` 同时声明勾选字段与空选数量字段;两者都可写进 `required`——宿主只校验**当前分支**。
|
||||
3. 空选数量字段名约定(宿主按字段名识别,保守列表):`pickCount` / `maxLeads` / `maxCount` / `takeCount` / `pick`。
|
||||
4. `entrypoint.args` 可同时写 `--ids {{itemIds}}` 与 `--pick {{pickCount}}`;缺值的 `--flag` + 空串由宿主压缩掉,不会留下脏 argv。
|
||||
5. 有勾选时隐藏数量字段;无勾选时隐藏 `$selection.ids` 映射字段(`$row.*` 行上下文不受影响)。
|
||||
6. **不要**为同一能力再挂第二个 toolbar 按钮。
|
||||
|
||||
示例:[`assets/examples/selection-mode-optional.action.example.json`](../assets/examples/selection-mode-optional.action.example.json)。
|
||||
|
||||
### 数据管理:选择摘要(宿主默认能力)
|
||||
|
||||
当用户在数据管理**勾选行**(或行内打开带行上下文的动作)后打开 `confirm` / `form` 弹层时,宿主会展示通用 **「已选择 · N 条」** 摘要(`#主键` + 可读标签;超过约 3 条可展开查看全部)。这是**宿主 UX**,对所有技能默认生效:
|
||||
当用户在数据管理**勾选行**(或行内打开带行上下文的动作)后打开 `confirm` / `form` 弹层时,若当前 Action 的 `selectionMode` 会**应用**表勾选(`required`,或 `optional` 且已勾选),宿主会展示通用 **「已选择 · N 条」** 摘要(`#主键` + 可读标签;超过约 3 条可展开查看全部)。这是**宿主 UX**,对适用技能默认生效:
|
||||
|
||||
- **技能零改动即可受益**;不要在 `confirmation.message` 里手写「已选 id 列表」,也不要为了面板去拼业务状态跳过文案。
|
||||
- **技能零改动即可受益**(省略 `selectionMode` 时的 `required` 推断路径);不要在 `confirmation.message` 里手写「已选 id 列表」,也不要为了面板去拼业务状态跳过文案。
|
||||
- 摘要与执行解耦:勾选了谁由 UI 说明;**实际处理哪些行、是否跳过某些状态,仍由技能 CLI / domain service 决定**。
|
||||
- `selectionMode: "none"` 时即使表上有勾选,也**不**展示假「已选择」、不把勾选 id 预填进本 Action。
|
||||
- 需要稳定标签列时,在 `bind` 上声明可选 `labelColumn`(见上)。示例:[`assets/examples/selection-label-column.action.example.json`](../assets/examples/selection-label-column.action.example.json)。
|
||||
|
||||
**与 `confirm` / `form` 的信息架构对齐(映射只读字段):**
|
||||
@@ -662,7 +686,7 @@ HINT: <next step>
|
||||
|----|------|
|
||||
| `toolbar` | 数据管理表顶栏技能按钮(须配合 `bind.tables`) |
|
||||
| `row` | 数据管理**行级入口**(建议 `bind.tables` + `inputMapping`;表需有主键)。技能声明后,由宿主呈现为操作列链接、**行右键菜单**和/或行内「⋯」等壳;**不**新增 `row-context-menu` 等 placement |
|
||||
| `batch` | 数据管理批量操作(需勾选行;无勾选时宿主禁用按钮) |
|
||||
| `batch` | 数据管理批量操作入口。默认(`selectionMode` 省略或 `required`)需勾选行,无勾选时宿主禁用按钮;`optional` / `none` 时无勾选也可点(见 `bind.selectionMode`) |
|
||||
| `skill-detail` | 技能详情页直调(与安装/四 Tab 同属技能市场详情;已声明则须自测) |
|
||||
| `agent` | Agent 可直接调用(`run_skill_action`) |
|
||||
| `cron` | 定时任务「技能直调」 |
|
||||
@@ -1099,6 +1123,8 @@ CRUD 侧宿主义务与禁止事项见 [`SCHEMA.md`](SCHEMA.md)「表单与展
|
||||
|
||||
若还需要默认篇数,可在同一 `properties` 里为 `pickCount` 增加 `"default": 1`、`"minimum": 1`。
|
||||
|
||||
与 **`bind.selectionMode: "optional"`** 联用时:无勾选弹层展示 `pickCount`;有勾选则隐藏 `pickCount`、提交 `$selection.ids`。不要再拆第二个「只 pick / 只勾选」toolbar 按钮。见上文「勾选驱动模式」。
|
||||
|
||||
约定:
|
||||
|
||||
- `boolean` 在宿主中渲染为开关
|
||||
@@ -1109,7 +1135,7 @@ CRUD 侧宿主义务与禁止事项见 [`SCHEMA.md`](SCHEMA.md)「表单与展
|
||||
- `required` 字段在提交前校验
|
||||
- `sensitive` 字段不得出现在低信任入口
|
||||
- `readOnly: true`:数据管理表单中标记为只读;**有「已选择」且该字段来自 `inputMapping`(或无 mapping 时的约定 id 字段)时,宿主默认不渲染该控件,预设值仍随提交传入**(与 `confirm` 无参数区对齐信息架构)。无「已选择」时仍只读展示。需要强制露出时加 `revealInForm: true`。**不要**用 `visibleWhen` 藏映射主键(会不提交)。
|
||||
- `placements` 含 `batch` 的动作在数据管理表顶常驻,无勾选时禁用(与表删除一致)
|
||||
- `placements` 含 `batch` 的动作:默认(`selectionMode` 为 `required` 或省略推断为 required)无勾选时禁用;`selectionMode` 为 `optional` / `none` 时无勾选也可点(见「勾选驱动模式」)
|
||||
- 需要确认的副作用操作使用 `confirmation.message`
|
||||
- 短名看不懂或会覆盖数据时,用独立的 `hoverHint`;不要把确认黄条复用成悬停
|
||||
- 模板参数使用 `{{fieldName}}`,且必须在 `inputSchema.properties` 中声明
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""技能标识、版本与平台公共库约束(复制后请修改 slug/version/logger)。"""
|
||||
|
||||
SKILL_SLUG = "your-skill-slug"
|
||||
SKILL_VERSION = "1.0.106"
|
||||
SKILL_VERSION = "1.0.107"
|
||||
LOG_LOGGER_NAME = "openclaw.skill.your_skill_slug"
|
||||
PLATFORM_KIT_MIN_VERSION = "1.2.11"
|
||||
|
||||
@@ -74,7 +74,7 @@ def _validate_bind_tables(action_id: str, bind: object) -> list[str]:
|
||||
errors: list[str] = []
|
||||
if not isinstance(bind, dict):
|
||||
return [f"{action_id}: bind must be object"]
|
||||
allowed = {"tables", "inputMapping", "columnMapping", "labelColumn"}
|
||||
allowed = {"tables", "inputMapping", "columnMapping", "labelColumn", "selectionMode"}
|
||||
unknown = set(bind.keys()) - allowed
|
||||
if unknown:
|
||||
errors.append(f"{action_id}: bind only allows {sorted(allowed)}, got {sorted(bind.keys())}")
|
||||
@@ -98,6 +98,11 @@ def _validate_bind_tables(action_id: str, bind: object) -> list[str]:
|
||||
errors.append(f"{action_id}: bind.labelColumn must be non-empty string")
|
||||
elif not _TABLE_NAME_PATTERN.fullmatch(label_column):
|
||||
errors.append(f"{action_id}: bind.labelColumn {label_column!r} must be snake_case")
|
||||
selection_mode = bind.get("selectionMode")
|
||||
if selection_mode is not None and selection_mode not in ("required", "none", "optional"):
|
||||
errors.append(
|
||||
f"{action_id}: bind.selectionMode must be required|none|optional, got {selection_mode!r}"
|
||||
)
|
||||
return errors
|
||||
|
||||
|
||||
@@ -470,6 +475,53 @@ class TestActionsManifest(unittest.TestCase):
|
||||
}
|
||||
jsonschema.validate(instance=manifest, schema=schema)
|
||||
|
||||
def test_schema_allows_bind_selection_mode(self) -> None:
|
||||
try:
|
||||
import jsonschema
|
||||
except ImportError:
|
||||
self.fail("jsonschema is required")
|
||||
schema = _load_actions_schema()
|
||||
bind_props = schema["$defs"]["bind"]["properties"]
|
||||
self.assertIn("selectionMode", bind_props)
|
||||
self.assertEqual(
|
||||
bind_props["selectionMode"].get("enum"),
|
||||
["required", "none", "optional"],
|
||||
)
|
||||
manifest = {
|
||||
"schemaVersion": 1,
|
||||
"skill": "your-skill-slug",
|
||||
"actions": [
|
||||
{
|
||||
"id": "probe-selection-mode",
|
||||
"label": "处理队列",
|
||||
"description": "验证 bind.selectionMode 可通过 Schema",
|
||||
"placements": ["toolbar", "batch"],
|
||||
"executionProfile": "async",
|
||||
"interaction": "form",
|
||||
"bind": {
|
||||
"tables": ["demo_items"],
|
||||
"selectionMode": "optional",
|
||||
"inputMapping": {"itemIds": "$selection.ids"},
|
||||
"labelColumn": "display_name",
|
||||
},
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"required": ["itemIds", "pickCount"],
|
||||
"properties": {
|
||||
"itemIds": {"type": "string", "readOnly": True},
|
||||
"pickCount": {"type": "number", "default": 1, "minimum": 1},
|
||||
},
|
||||
},
|
||||
"entrypoint": {
|
||||
"type": "cli",
|
||||
"command": "process",
|
||||
"args": ["--ids", "{{itemIds}}", "--pick", "{{pickCount}}"],
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
jsonschema.validate(instance=manifest, schema=schema)
|
||||
|
||||
def test_no_execution_profile_placement_coupling_in_tests(self) -> None:
|
||||
"""守护:本文件不得引入入口位置与 sync/async 的错误硬耦合断言。"""
|
||||
path = os.path.join(get_skill_root(), "tests", "test_actions_manifest.py")
|
||||
@@ -632,6 +684,8 @@ class TestActionsManifest(unittest.TestCase):
|
||||
"cellPresentation",
|
||||
"CELL_PRESENTATION.md",
|
||||
"labelColumn",
|
||||
"selectionMode",
|
||||
"勾选驱动",
|
||||
"已选择",
|
||||
"revealInForm",
|
||||
"映射只读",
|
||||
|
||||
@@ -415,14 +415,18 @@ class TestDocsStandards(unittest.TestCase):
|
||||
def test_visible_when_example_is_listed(self) -> None:
|
||||
text = self._read("assets/examples/README.md")
|
||||
self.assertIn("visible-when-action.example.json", text)
|
||||
self.assertIn("selection-mode-optional.action.example.json", text)
|
||||
checklist = self._read("development/CHECKLIST.md")
|
||||
self.assertIn("A4-7", checklist)
|
||||
self.assertIn("visibleWhen", checklist)
|
||||
self.assertIn("A4-8", checklist)
|
||||
self.assertIn("revealInForm", checklist)
|
||||
self.assertIn("A4-9", checklist)
|
||||
self.assertIn("selectionMode", checklist)
|
||||
runtime = self._read("development/SKILL_ACTION_RUNTIME.md")
|
||||
self.assertIn("visibleWhen", runtime)
|
||||
self.assertIn("revealInForm", runtime)
|
||||
self.assertIn("selectionMode", runtime)
|
||||
|
||||
def test_guarded_docs_do_not_reference_amazon_implementation(self) -> None:
|
||||
forbidden = (
|
||||
|
||||
Reference in New Issue
Block a user