docs: precipitate Action/CRUD Lookup contract for skill authors

This commit is contained in:
2026-08-16 12:58:39 +08:00
parent 2d02ccff5d
commit da5e03a77c
11 changed files with 187 additions and 15 deletions

View File

@@ -9,6 +9,12 @@
- 小节正文写用户能看懂的变化(新能力、修复、注意事项),避免堆砌内部实现细节
- 打 tag 前**必须**为即将发布的版本新增一节;找不到匹配小节时,本次发布不会更新 changelog 字段
## 1.0.83
- 沉淀跨表 Lookup 契约:Action 可用内联 `lookup` 或绑列下拉,禁止让用户手填内部编号
- 统一展示:`编号 · 名称`,可选 `extra_column` 时为 `编号 · 名称(额外)`
- 更新 `ACTIONS.md` / `SCHEMA.md` / `skill-actions.schema.json`、示例与验收清单
## 1.0.82
- 沉淀数据管理技能按钮可选悬停字段 `hoverHint`:短名看不懂或会覆盖数据时再写;不回退说明或确认黄条

View File

@@ -1,7 +1,7 @@
---
name: 技能开发模板(通用业务版)
description: "OpenClaw 通用业务技能开发模板,供复制后定制新业务 skill。定制步骤见 development/DEVELOPMENT.md。"
version: 1.0.82
version: 1.0.83
author: 深圳匠厂科技有限公司
metadata:
openclaw:

View File

@@ -4,3 +4,4 @@
- `skill-policy-snapshot.*.example.json`:Data Policy Snapshot 形状参考(见 `references/POLICY.md`)。
- `skill-cell-presentation.example.json`:数据管理单元格呈现文档形状参考(见 `references/CELL_PRESENTATION.md`)。
- `render-html.action.example.json`:HTML 报告「重新生成」Action 形状参考(固定 id `render-html`;见 `references/ACTIONS.md`)。
- `lookup-action.example.json`:Action 内联 Lookup 下拉形状参考(跨表引用勿填编号;见 `references/ACTIONS.md`「跨表引用:Lookup」)。

View File

@@ -0,0 +1,48 @@
{
"_comment": "形状参考:Action 参数引用同库另一张表时用 Lookup 下拉,勿让用户填内部编号。完整契约见 references/ACTIONS.md「跨表引用:Lookup」与 references/SCHEMA.md。",
"schemaVersion": 1,
"skill": "your-skill-slug",
"actions": [
{
"id": "send-with-template",
"label": "按模板发送(示例)",
"description": "演示内联 lookup:从 message_templates 选模板;-- 表示自动挑选。",
"placements": ["toolbar"],
"executionProfile": "async",
"interaction": "form",
"bind": {
"tables": ["leads"]
},
"entrypoint": {
"type": "cli",
"command": "engage",
"args": ["--template-id", "{{templateId}}", "--content", "{{content}}"]
},
"inputSchema": {
"type": "object",
"properties": {
"content": {
"type": "string",
"title": "正文",
"description": "填了就按这里发;留空则用下面的话术模板。",
"display_type": "textarea"
},
"templateId": {
"type": "number",
"title": "话术模板",
"description": "仅在正文留空时生效。选 -- = 自动挑选。",
"display_type": "lookup",
"lookup": {
"ref_table": "message_templates",
"value_column": "id",
"label_column": "name",
"extra_column": "channel",
"filter_column": "is_active",
"filter_value": 1
}
}
}
}
}
]
}

View File

@@ -116,20 +116,66 @@
"type": "string",
"minLength": 1,
"pattern": "^[a-z][a-z0-9_]*$",
"description": "可选。绑定业务表物理列名;replaces create/update 时宿主可复用该列的中文名与 lookup 下拉"
"description": "可选。绑定业务表物理列名;Action 弹窗(toolbar/batch)与 replaces create/update 抽屉均可复用该列的中文名与 lookup 下拉"
},
"display_type": {
"type": "string",
"enum": ["textarea", "date", "datetime_unix_seconds", "url", "email"],
"description": "可选。表单控件提示;与 format 二选一即可。须与 CRUD display_type 语义对齐(见 ACTIONS.md / SCHEMA.md)。"
"enum": ["textarea", "date", "datetime_unix_seconds", "url", "email", "lookup"],
"description": "可选。表单控件提示;与 format 二选一即可。lookup=关联下拉(须配 lookup 对象或绑到已有 lookup 列)。须与 CRUD display_type 语义对齐(见 ACTIONS.md / SCHEMA.md)。"
},
"format": {
"type": "string",
"enum": ["textarea", "date", "datetime_unix_seconds", "url", "email"],
"enum": ["textarea", "date", "datetime_unix_seconds", "url", "email", "lookup"],
"description": "可选。display_type 别名,语义相同。"
},
"lookup": {
"$ref": "#/$defs/lookupConfig",
"description": "可选。内联同库表关联 Lookup(与列 options_json lookup 对象同构)。用于当前表没有对应列时;推荐同时设 display_type=lookup。见 ACTIONS.md「跨表引用:Lookup」。"
}
}
},
"lookupConfig": {
"type": "object",
"required": ["ref_table", "value_column", "label_column"],
"additionalProperties": false,
"properties": {
"ref_table": {
"type": "string",
"minLength": 1,
"pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$",
"description": "同库被引用表名"
},
"value_column": {
"type": "string",
"minLength": 1,
"pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$",
"description": "提交值列(编号 / 外键)"
},
"label_column": {
"type": "string",
"minLength": 1,
"pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$",
"description": "主文案列"
},
"extra_column": {
"type": "string",
"minLength": 1,
"pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$",
"description": "可选。第三展示列;有值时宿主拼成「value · label(extra)」"
},
"filter_column": {
"type": "string",
"minLength": 1,
"pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$",
"description": "可选。等值过滤列"
},
"filter_value": {
"type": ["string", "number", "boolean", "null"],
"description": "可选。与 filter_column 配对的等值"
}
},
"description": "同库 FK 式 Lookup。展示:value · label;有 extra 时 value · label(extra)。宿主亦接受 camelCase 键名。"
},
"inputSchema": {
"type": "object",
"required": ["type", "properties"],
@@ -203,7 +249,7 @@
"minLength": 1,
"pattern": "^[a-z][a-z0-9_]*$"
},
"description": "可选。将 inputSchema 属性名映射到业务表物理列名,供 replaces create/update 抽屉复用列 displayName / lookup options。"
"description": "可选。将 inputSchema 属性名映射到业务表物理列名,供 Action 弹窗与 replaces create/update 抽屉复用列 displayName / lookup options。"
}
},
"description": "表级绑定;toolbar 必填。可选 inputMapping / columnMapping。concurrency/locks 勿写入。"

View File

@@ -96,6 +96,7 @@ checklist_version: 1.0
- [ ] A4-3 **P0** 异步任务在任务中心能看到进行中与结束状态;结束有成功或失败结论
- [ ] A4-4 **P1** 进行中的进度/步骤信息对用户可理解
- [ ] A4-5 **P1** 已对外暴露的动作参数覆盖主路径关键输入(无“命令行能做、动作入口不能做”的关键缺口)
- [ ] A4-6 **P0** 若 Action 需引用同库另一张业务表(话术/平台/账号等):参数为 Lookup 下拉(内联 `lookup` 或绑列),**不是**手填内部编号;可选「自动」可留空提交
---

View File

@@ -7,7 +7,7 @@
| 文档 | 职责 |
|------|------|
| 本文 | sync/async、任务中心、Agent 禁令、单内核编排、队列 pick、同步 vs 导出 |
| [`../references/ACTIONS.md`](../references/ACTIONS.md) | `actions.json` 字段、placements、`bind.tables`、inputSchema |
| [`../references/ACTIONS.md`](../references/ACTIONS.md) | `actions.json` 字段、placements、`bind.tables`、inputSchema、跨表 Lookup |
| [`LOGGING.md`](LOGGING.md) | `job_context` / `emit` / `finish` / Run Journal |
| [`DATA_PATHS.md`](DATA_PATHS.md) | 下载/导入等落盘路径 |

View File

@@ -176,11 +176,12 @@ Action 是**可选能力**:
- `update` / `delete` 可用 `inputMapping`(`$row.$pk`、`$selection.ids`)预填主键。
- 宿主导入仍直写:有 `replaces:create` 的表慎用宿主导入,或另做 import Action。
- 整表 `_jiangchang_tables.readonly=1` 时仍隐藏写按钮(优先于 `replaces`)。
- **列元数据复用(lookup)**:create/update 抽屉可将 `inputSchema` 字段对齐业务列,复用中文名与 lookup 下拉:
- **列元数据复用(lookup)**:Action 表单(含 toolbar/batch 弹窗与 create/update 抽屉)可将 `inputSchema` 字段对齐业务列,复用中文名与 lookup 下拉:
- 优先让属性名 = 物理列名(如 `platform_key`);
- 或 `bind.columnMapping`:`{ "platform": "platform_key" }`;
- 或字段上写 `"column": "platform_key"`。
- **不要**在 actions.json 里写死会过期的全量平台 `enum`。
- 当前表没有对应列时,用字段内联 `lookup`(见下文「跨表引用:Lookup」)。
- **不要**在 actions.json 里写死会过期的全量平台 `enum`,也**不要**让用户手填内部编号。
## `interaction`(点击交互方式)
@@ -583,6 +584,57 @@ HINT: <next step>
- [ ] 成功路径带 `refreshCatalog`(或等价让侧栏/预览看到更新)
## inputSchema 与参数表单
### 跨表引用:Lookup(宿主已支持;勿让用户填编号)
当 Action 参数要引用**同库另一张业务表**的一行(话术模板、平台、账号等)时,必须用 Lookup 下拉,**禁止**做成「请填写编号」的数字框(用户记不住内部 id,体验差)。
| 场景 | 怎么配 | 说明 |
|------|--------|------|
| 当前表已有同含义列,且列上已是 CRUD lookup | `column` / `bind.columnMapping`,或属性名 = 列名 | toolbar/batch 弹窗与 create/update 抽屉都会复用该列已解析的选项 |
| 当前表没有该列(如在「潜客」表上选「话术模板」) | `display_type: "lookup"` + 字段内联 `lookup` 对象 | 打开表单时宿主按当前技能库解析选项 |
内联 `lookup` 与列元数据 `options_json` **同构**(见 [`SCHEMA.md`](SCHEMA.md)「表关联 lookup」):
```json
{
"templateId": {
"type": "number",
"title": "话术模板",
"description": "仅在正文留空时生效;选 -- 表示自动挑选。",
"display_type": "lookup",
"lookup": {
"ref_table": "message_templates",
"value_column": "id",
"label_column": "name",
"extra_column": "channel",
"filter_column": "is_active",
"filter_value": 1
}
}
}
```
| 字段 | 必填 | 说明 |
|------|------|------|
| `ref_table` | 是 | 同库被引用表 |
| `value_column` | 是 | 提交给 CLI 的值(编号 / 外键) |
| `label_column` | 是 | 主文案列 |
| `extra_column` | 否 | 第三展示列(任意列名,不限「备注」) |
| `filter_column` / `filter_value` | 否 | 等值过滤 |
**下拉展示(宿主统一,技能只配列):** `{value} · {label}`;有非空 `extra_column` 时为 `{value} · {label}({extra})`。例:`2 · 通用私信-留资`、`2 · 通用私信-留资(dm)`。
**可选「自动」:** 字段不要放进 `required`;不要用 `minimum: 1` 卡死留空。宿主会省略空的可选数字参数,避免「提交的数据无效」。
**反模式(勿做):**
- 标题写成「某某编号」,说明里教用户去左侧表抄 id
- 用静态 `enum` 罗列会增长/变更的业务行(会过期)
- 在技能里自己拼假 label 列代替宿主统一格式(难维护)
形状参考:[`assets/examples/lookup-action.example.json`](../assets/examples/lookup-action.example.json)。
### 表单字段类型对照(须与 CRUD 对称)
Skill Action 弹窗与数据管理「新增 / 编辑」使用**同一套控件语义**。CRUD 侧配置见 [`SCHEMA.md`](SCHEMA.md)「表单与展示:稳定字段类型」;本表只写 Action 怎么配。
@@ -595,7 +647,7 @@ Skill Action 弹窗与数据管理「新增 / 编辑」使用**同一套控件
| 数字 | `type: number` | `display_type: number` 或 INT/REAL/NUMERIC |
| 开关 | `type: boolean` | `display_type: boolean` |
| 枚举下拉 | `enum: [...]` | `options_json` 数组 |
| 关联下拉 | 绑列 lookup(`column` / `columnMapping`) | `display_type: lookup` |
| 关联下拉(Lookup) | 内联 `display_type: lookup` + `lookup`,或绑列 `column` / `columnMapping` | `display_type: lookup` + `options_json` 对象 |
| 密码 | `sensitive: true` | 列 `sensitive` |
| 日期(日) | `display_type` 或 `format`: `date` | `display_type: date` → 存 `YYYY-MM-DD` |
| 日期时间 | `display_type` 或 `format`: `datetime_unix_seconds` | 同左;**存/传 Unix 秒** |
@@ -617,9 +669,11 @@ Skill Action 弹窗与数据管理「新增 / 编辑」使用**同一套控件
- 根:`object`;属性:`string` / `number` / `boolean`(`object`/`array` 仅作 JSON 多行编辑兼容,新技能慎用)
- `enum` / `default` / `required` / `sensitive` / `readOnly`
- `display_type` / `format`:`textarea` | `date` | `datetime_unix_seconds` | `url` | `email`
- `display_type` / `format`:`textarea` | `date` | `datetime_unix_seconds` | `url` | `email` | **`lookup`**
- 字段内联 `lookup`(与 CRUD `options_json` lookup 对象同构;可选 `extra_column`)
- 属性级 `description`(表单标签下方灰字说明)
- 简单模板替换(`{{fieldName}}`)
- 可选空数字字段提交时由宿主省略,避免 `""` 触发 number 校验失败
**与数据管理「新增 / 编辑」表单的分工(勿混用配置入口):**

View File

@@ -518,6 +518,7 @@ CREATE TABLE demo_items (
"ref_table": "platforms",
"value_column": "platform_key",
"label_column": "display_name",
"extra_column": "category",
"filter_column": "enabled",
"filter_value": 1
}
@@ -526,13 +527,23 @@ CREATE TABLE demo_items (
| 字段 | 必填 | 说明 |
|---|---|---|
| `ref_table` | 是 | 同库被引用表名(snake_case 标识符) |
| `value_column` | 是 | 写入当前字段的值列 |
| `label_column` | 是 | 下拉展示名列 |
| `value_column` | 是 | 写入当前字段的值列(编号 / 外键) |
| `label_column` | 是 | 下拉主文案列(名称) |
| `extra_column` | 否 | 第三展示列(不必叫「备注」);有值时拼进括号 |
| `filter_column` / `filter_value` | 否 | 等值过滤(如只列出 `enabled=1`) |
宿主在加载表 schema 时查询 `ref_table`,把结果展开成 `{value,label}` 下拉选项;**物理列仍存标量**(如 `platform_key` 文本、`account_id` 整数),不做嵌套子表。
示例:账号表的平台字段 → 平台信息表;凭据表的账号编号 → 账号信息表。
**统一展示文案(宿主固定一种,技能只配列):**
- 默认:`{value} · {label}`,例如 `2 · 通用私信-留资`、`douyin · 抖音`
- 配置了 `extra_column` 且该行有非空值:`{value} · {label}({extra})`
- 未配置 `extra_column`、或额外列为空:不加 `()`
- `label` 为空或与 `value` 相同时:只显示 `value`(可再带额外括号)
Action 弹窗内联 Lookup 与上表 **同构**(字段名一致),见 [`ACTIONS.md`](ACTIONS.md)「跨表引用:Lookup」。
示例:账号表的平台字段 → 平台信息表;凭据表的账号编号 → 账号信息表;私信 Action 选话术 → `message_templates`。
## 幂等初始化标准

View File

@@ -1,6 +1,6 @@
"""技能标识、版本与平台公共库约束(复制后请修改 slug/version/logger)。"""
SKILL_SLUG = "your-skill-slug"
SKILL_VERSION = "1.0.82"
SKILL_VERSION = "1.0.83"
LOG_LOGGER_NAME = "openclaw.skill.your_skill_slug"
PLATFORM_KIT_MIN_VERSION = "1.2.11"

View File

@@ -341,6 +341,8 @@ class TestDocsStandards(unittest.TestCase):
"表单与展示:稳定字段类型(宿主支持,须与 Action 对称)",
"datetime_unix_seconds",
"display_type: \"number\"",
"extra_column",
"{value} · {label}",
"DEFAULT",
"description",
"文件 / 图片上传",
@@ -354,6 +356,9 @@ class TestDocsStandards(unittest.TestCase):
for marker in (
"inputSchema 与参数表单",
"表单字段类型对照(须与 CRUD 对称)",
"跨表引用:Lookup",
"display_type: \"lookup\"",
"extra_column",
"数据管理新增/编辑",
"_jiangchang_columns.description",
"datetime_unix_seconds",