@amaster.ai/pi-lark 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/skills/lark-approval/references/lark-approval-initiate.md +2 -5
- package/skills/lark-approval/references/lark-approval-instances-initiated.md +6 -0
- package/skills/lark-approval/references/lark-approval-tasks-query.md +9 -0
- package/skills/lark-approval/references/lark-approval-tasks-rollback.md +8 -2
- package/skills/lark-apps/SKILL.md +25 -7
- package/skills/lark-apps/references/lark-apps-access-scope-set.md +1 -1
- package/skills/lark-apps/references/lark-apps-automation.md +164 -0
- package/skills/lark-apps/references/lark-apps-db-execute.md +186 -2
- package/skills/lark-apps/references/lark-apps-db.md +3 -3
- package/skills/lark-apps/references/lark-apps-get.md +43 -0
- package/skills/lark-apps/references/lark-apps-html-publish.md +7 -2
- package/skills/lark-apps/references/lark-apps-init.md +1 -2
- package/skills/lark-apps/references/lark-apps-openapi-key.md +1 -1
- package/skills/lark-apps/references/lark-apps-release-create.md +3 -1
- package/skills/lark-apps/references/lark-apps-role.md +133 -0
- package/skills/lark-base/SKILL.md +7 -3
- package/skills/lark-base/references/dashboard-block-data-config.md +28 -2
- package/skills/lark-base/references/lark-base-cell-value.md +9 -4
- package/skills/lark-base/references/lark-base-dashboard-block-get-data.md +7 -7
- package/skills/lark-base/references/lark-base-dashboard.md +11 -2
- package/skills/lark-base/references/lark-base-data-query.md +9 -7
- package/skills/lark-base/references/lark-base-field-create.md +4 -2
- package/skills/lark-base/references/lark-base-field-json.md +52 -15
- package/skills/lark-base/references/lark-base-field-update.md +4 -2
- package/skills/lark-base/references/lark-base-view-set-filter.md +3 -1
- package/skills/lark-calendar/SKILL.md +89 -31
- package/skills/lark-calendar/references/lark-calendar-create.md +8 -39
- package/skills/lark-calendar/references/lark-calendar-room-find.md +5 -9
- package/skills/lark-calendar/references/lark-calendar-rsvp.md +1 -5
- package/skills/lark-calendar/references/lark-calendar-schedule-clear-time.md +59 -0
- package/skills/lark-calendar/references/lark-calendar-schedule-fuzzy-time.md +88 -0
- package/skills/lark-calendar/references/lark-calendar-schedule-meeting.md +67 -210
- package/skills/lark-calendar/references/lark-calendar-suggestion.md +1 -5
- package/skills/lark-calendar/references/lark-calendar-update.md +2 -7
- package/skills/lark-doc/SKILL.md +1 -1
- package/skills/lark-doc/references/lark-doc-fetch.md +4 -2
- package/skills/lark-doc/references/lark-doc-mindnote.md +17 -2
- package/skills/lark-doc/references/lark-doc-whiteboard.md +4 -0
- package/skills/lark-doc/references/lark-doc-xml-extended-blocks.md +35 -0
- package/skills/lark-doc/references/lark-doc-xml.md +3 -2
- package/skills/lark-drive/SKILL.md +20 -8
- package/skills/lark-drive/references/lark-drive-comment-location.md +16 -4
- package/skills/lark-drive/references/lark-drive-comments-guide.md +16 -8
- package/skills/lark-drive/references/lark-drive-delete.md +35 -11
- package/skills/lark-drive/references/lark-drive-export.md +39 -10
- package/skills/lark-drive/references/lark-drive-files-list.md +27 -2
- package/skills/lark-drive/references/lark-drive-inspect.md +2 -0
- package/skills/lark-drive/references/lark-drive-list-comments.md +125 -0
- package/skills/lark-drive/references/lark-drive-member-add.md +1 -1
- package/skills/lark-drive/references/lark-drive-move.md +5 -3
- package/skills/lark-drive/references/lark-drive-permission-guide.md +12 -0
- package/skills/lark-drive/references/lark-drive-pull.md +3 -3
- package/skills/lark-drive/references/lark-drive-push.md +33 -6
- package/skills/lark-drive/references/lark-drive-status.md +12 -14
- package/skills/lark-drive/references/lark-drive-task-result.md +58 -5
- package/skills/lark-drive/references/lark-drive-workflow-knowledge-organize.md +26 -20
- package/skills/lark-drive/references/lark-drive-workflow.md +2 -1
- package/skills/lark-event/SKILL.md +2 -1
- package/skills/lark-event/references/lark-event-approval.md +170 -0
- package/skills/lark-im/SKILL.md +5 -4
- package/skills/lark-im/references/lark-im-messages-reply.md +1 -1
- package/skills/lark-im/references/lark-im-messages-send.md +1 -1
- package/skills/lark-mail/SKILL.md +12 -9
- package/skills/lark-mail/references/lark-mail-forward.md +1 -1
- package/skills/lark-mail/references/lark-mail-message-modify.md +48 -0
- package/skills/lark-mail/references/lark-mail-message-trash.md +41 -0
- package/skills/lark-mail/references/lark-mail-reply-all.md +1 -1
- package/skills/lark-mail/references/lark-mail-reply.md +1 -1
- package/skills/lark-mail/references/lark-mail-watch.md +1 -1
- package/skills/lark-markdown/SKILL.md +3 -2
- package/skills/lark-markdown/references/lark-markdown-create.md +22 -2
- package/skills/lark-minutes/SKILL.md +19 -4
- package/skills/lark-minutes/references/lark-minutes-download.md +0 -2
- package/skills/lark-minutes/references/lark-minutes-search.md +0 -2
- package/skills/lark-minutes/references/lark-minutes-speaker-replace.md +0 -2
- package/skills/lark-minutes/references/lark-minutes-summary.md +0 -2
- package/skills/lark-minutes/references/lark-minutes-todo.md +2 -4
- package/skills/lark-minutes/references/lark-minutes-update.md +0 -2
- package/skills/lark-minutes/references/lark-minutes-upload.md +10 -10
- package/skills/lark-shared/SKILL.md +26 -8
- package/skills/lark-sheets/SKILL.md +98 -29
- package/skills/lark-sheets/references/lark-sheets-batch-update.md +18 -9
- package/skills/lark-sheets/references/lark-sheets-changeset.md +105 -0
- package/skills/lark-sheets/references/lark-sheets-chart.md +4 -2
- package/skills/lark-sheets/references/lark-sheets-conditional-format.md +2 -0
- package/skills/lark-sheets/references/lark-sheets-filter-view.md +1 -1
- package/skills/lark-sheets/references/lark-sheets-float-image.md +6 -6
- package/skills/lark-sheets/references/lark-sheets-formula-translation.md +12 -3
- package/skills/lark-sheets/references/lark-sheets-formula-verify.md +77 -0
- package/skills/lark-sheets/references/lark-sheets-history.md +93 -0
- package/skills/lark-sheets/references/lark-sheets-pivot-table.md +7 -2
- package/skills/lark-sheets/references/lark-sheets-range-operations.md +44 -14
- package/skills/lark-sheets/references/lark-sheets-read-data.md +3 -3
- package/skills/lark-sheets/references/lark-sheets-sheet-structure.md +4 -4
- package/skills/lark-sheets/references/lark-sheets-visual-standards.md +4 -4
- package/skills/lark-sheets/references/lark-sheets-workbook.md +29 -4
- package/skills/lark-sheets/references/lark-sheets-write-cells.md +21 -11
- package/skills/lark-slides/SKILL.md +29 -18
- package/skills/lark-slides/references/asset-planning.md +16 -5
- package/skills/lark-slides/references/examples.md +57 -227
- package/skills/lark-slides/references/iconpark.md +2 -2
- package/skills/lark-slides/references/lark-slides-create.md +21 -2
- package/skills/lark-slides/references/lark-slides-media-upload.md +0 -1
- package/skills/lark-slides/references/lark-slides-pptx-template-workflows.md +89 -0
- package/skills/lark-slides/references/lark-slides-replace-pages.md +1 -1
- package/skills/lark-slides/references/lark-slides-replace-slide.md +1 -1
- package/skills/lark-slides/references/lark-slides-screenshot.md +11 -8
- package/skills/lark-slides/references/lark-slides-whiteboard.md +31 -30
- package/skills/lark-slides/references/lark-slides-xml-get.md +100 -0
- package/skills/lark-slides/references/lark-slides-xml-presentation-slide-delete.md +9 -7
- package/skills/lark-slides/references/lark-slides-xml-presentation-slide-get.md +4 -4
- package/skills/lark-slides/references/lark-slides-xml-presentation-slide-replace.md +12 -10
- package/skills/lark-slides/references/lark-slides-xml-presentations-get.md +14 -13
- package/skills/lark-slides/references/planning-layer.md +32 -2
- package/skills/lark-slides/references/slides_chart_demo.xml +1 -0
- package/skills/lark-slides/references/slides_xml_schema_definition.xml +8 -3
- package/skills/lark-slides/references/troubleshooting.md +7 -25
- package/skills/lark-slides/references/validation-checklist.md +18 -9
- package/skills/lark-slides/references/visual-planning.md +4 -3
- package/skills/lark-slides/references/xml-format-guide.md +65 -1
- package/skills/lark-slides/references/xml-schema-quick-ref.md +7 -3
- package/skills/lark-slides/scripts/xml_text_overlap_lint.py +907 -54
- package/skills/lark-slides/scripts/xml_text_overlap_lint_test.py +876 -5
- package/skills/lark-task/SKILL.md +1 -0
- package/skills/lark-task/references/lark-task-create.md +14 -1
- package/skills/lark-vc/SKILL.md +6 -3
- package/skills/lark-vc/references/lark-vc-recording.md +0 -2
- package/skills/lark-vc/references/vc-domain-boundaries.md +9 -1
- package/skills/lark-vc-agent/SKILL.md +25 -15
- package/skills/lark-vc-agent/references/lark-vc-agent-meeting-events.md +65 -37
- package/skills/lark-vc-agent/references/lark-vc-agent-meeting-leave.md +1 -1
- package/skills/lark-vc-agent/references/lark-vc-agent-meeting-list-active.md +8 -8
- package/skills/lark-whiteboard/references/lark-whiteboard-workflow.md +5 -2
- package/skills/lark-wiki/SKILL.md +7 -3
- package/skills/lark-wiki/references/lark-wiki-move-to-drive.md +122 -0
- package/skills/lark-wiki/references/lark-wiki-move.md +5 -3
- package/skills/lark-wiki/references/lark-wiki-node-get.md +1 -1
- package/skills/lark-wiki/references/lark-wiki-node-list.md +9 -2
- package/skills/lark-calendar/references/lark-calendar-agenda.md +0 -78
- package/skills/lark-calendar/references/lark-calendar-freebusy.md +0 -124
- package/skills/lark-calendar/references/lark-calendar-search-event.md +0 -29
- package/skills/lark-sheets/references/lark-sheets-core-operations.md +0 -103
- package/skills/lark-slides/references/lark-slides-xml-presentation-slide-create.md +0 -220
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amaster.ai/pi-lark",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Pi extension for Lark/Feishu workspace — calendar, docs, drive, sheets, tasks, mail and more via lark-cli.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -56,12 +56,12 @@
|
|
|
56
56
|
}
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@earendil-works/pi-coding-agent": "0.80.
|
|
59
|
+
"@earendil-works/pi-coding-agent": "0.80.10",
|
|
60
60
|
"typebox": "*",
|
|
61
61
|
"vitest": "^4.0.0"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@amaster.ai/pi-shared": "0.1.
|
|
64
|
+
"@amaster.ai/pi-shared": "0.1.6"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"fetch-skills": "node scripts/fetch-skills.mjs",
|
|
@@ -69,19 +69,17 @@ lark-cli approval approvals get \
|
|
|
69
69
|
|---|---|---|
|
|
70
70
|
| `--data '{...}'` | 是 | 请求体,使用 JSON 传入 |
|
|
71
71
|
| `approval_code` | 是 | 审批定义 Code;必须先通过 `approvals search` / `approvals get` 确认 |
|
|
72
|
-
| `form` |
|
|
72
|
+
| `form` | 否 | 表单值,**JSON 数组字符串**,不是普通对象;API 层非必填,但审批定义存在必填控件或用户需要提交表单值时必须传 |
|
|
73
73
|
| `node_approver_list` | 否 | 节点审批人列表;仅在定义要求补充审批人时传 |
|
|
74
74
|
| `node_cc_list` | 否 | 节点抄送人列表;仅在用户明确需要补充节点抄送人时传 |
|
|
75
75
|
| `uuid` | 否 | 幂等标识;重复重试同一请求时建议显式传入 |
|
|
76
|
-
| `--params '{...}'` | 否 | 查询参数,使用 JSON 传入 |
|
|
77
|
-
| `user_id_type` | 否 | 用户 ID 类型:`user_id`、`union_id`、`open_id`;涉及人员类 ID 时建议显式传 `open_id` |
|
|
78
76
|
| `--as user` | 否 | 建议显式指定用户身份;审批发起通常应使用用户身份 |
|
|
79
77
|
| `--yes` | 是 | 写操作确认;真实执行时必须显式传入 |
|
|
80
78
|
| `--dry-run` | 否 | 预览 API 调用,不执行 |
|
|
81
79
|
|
|
82
80
|
### 4. 组装 `form`
|
|
83
81
|
|
|
84
|
-
`instances create --data.form`
|
|
82
|
+
`instances create --data.form` 是可选字段;传入时必须是一个 JSON 数组字符串。无表单或无需填写表单值的审批可省略 `form`,但只要审批定义包含需要提交的控件,就必须按控件结构组装后传入。组装原则:
|
|
85
83
|
|
|
86
84
|
- 先用 `approvals.get.form` 识别有哪些控件、每个控件的 `id` / `type` / 可选值范围,再按本文中的创建参数规则与 [`lark-approval-instance-form-control-parameters.md`](./lark-approval-instance-form-control-parameters.md) 重新组装创建 payload。
|
|
87
85
|
- 提交时必须至少保证每个控件的 `id`、`type` 与 `value` 符合当前接口要求;不要假设定义快照里出现的其他字段都能直接照搬。
|
|
@@ -173,7 +171,6 @@ lark-cli approval instances create \
|
|
|
173
171
|
}
|
|
174
172
|
]
|
|
175
173
|
}' \
|
|
176
|
-
--params '{"user_id_type":"open_id"}' \
|
|
177
174
|
--as user \
|
|
178
175
|
--yes
|
|
179
176
|
```
|
|
@@ -14,6 +14,9 @@ lark-cli approval instances initiated --params '{"page_size":20}' --as user
|
|
|
14
14
|
# 只看某个审批定义下我发起的实例
|
|
15
15
|
lark-cli approval instances initiated --params '{"definition_code":"<DEFINITION_CODE>","page_size":20}' --as user
|
|
16
16
|
|
|
17
|
+
# 按发起时间范围筛选(秒级时间戳)
|
|
18
|
+
lark-cli approval instances initiated --params '{"start_timestamp":"<START_SECONDS>","end_timestamp":"<END_SECONDS>","page_size":20}' --as user
|
|
19
|
+
|
|
17
20
|
# 使用 page_token 翻页
|
|
18
21
|
lark-cli approval instances initiated --params '{"page_size":20,"page_token":"example_page_token"}' --as user
|
|
19
22
|
|
|
@@ -30,6 +33,8 @@ lark-cli approval instances initiated --params '{"page_size":20}' --as user --dr
|
|
|
30
33
|
|------|------|------|
|
|
31
34
|
| `--params '{...}'` | 否 | 查询参数,使用 JSON 传入;不传时使用默认分页与筛选 |
|
|
32
35
|
| `definition_code` | 否 | 审批定义 Code,用于只查看某个审批定义下我发起的实例 |
|
|
36
|
+
| `start_timestamp` | 否 | 按发起时间筛选,时间范围开始值,秒级时间戳 |
|
|
37
|
+
| `end_timestamp` | 否 | 按发起时间筛选,时间范围结束值,秒级时间戳 |
|
|
33
38
|
| `locale` | 否 | 返回语言:`zh-CN`、`en-US`、`ja-JP` |
|
|
34
39
|
| `page_size` | 否 | 分页大小 |
|
|
35
40
|
| `page_token` | 否 | 翻页标记;首次请求不填,后续使用上一次返回的 `page_token` |
|
|
@@ -101,6 +106,7 @@ lark-cli approval instances initiated \
|
|
|
101
106
|
|
|
102
107
|
- **这是定位“我发起的审批实例”的首选命令**:如果你的目标是撤回、抄送、查看某个已发起审批,优先从这里拿 `instance_code`。
|
|
103
108
|
- **优先用 `definition_code` 缩小范围**:当你已知审批定义时,先筛掉无关实例,可显著提升可读性。
|
|
109
|
+
- **按时间排查时使用 `start_timestamp` / `end_timestamp`**:这两个值都是秒级时间戳,用于按发起时间缩小结果范围。
|
|
104
110
|
- **结果很多时优先 `--format table`**:适合人工快速浏览。
|
|
105
111
|
- **`count` 只在第一页返回**:做分页处理时不要假设后续页还会带总数。
|
|
106
112
|
- **`instance_status` 可直接判断下一步**:例如状态为 `1` 时通常可继续查看详情或考虑撤回,状态为 `4` 表示已经撤销,无需重复撤回。
|
|
@@ -14,6 +14,9 @@ lark-cli approval tasks query --params '{"topic":"1"}' --as user
|
|
|
14
14
|
# 查询已办审批
|
|
15
15
|
lark-cli approval tasks query --params '{"topic":"2"}' --as user
|
|
16
16
|
|
|
17
|
+
# 按任务时间范围筛选(秒级时间戳)
|
|
18
|
+
lark-cli approval tasks query --params '{"topic":"1","start_timestamp":"<START_SECONDS>","end_timestamp":"<END_SECONDS>"}' --as user
|
|
19
|
+
|
|
17
20
|
# 使用 page_token 翻页
|
|
18
21
|
lark-cli approval tasks query --params '{"topic":"1","page_token":"example_page_token"}' --as user
|
|
19
22
|
|
|
@@ -28,6 +31,8 @@ lark-cli approval tasks query --params '{"topic":"1"}' --format table --as user
|
|
|
28
31
|
| `--params '{"topic":"..."}'` | 是 | 查询参数,使用 JSON 传入 |
|
|
29
32
|
| `topic` | 是 | 任务分组主题,见下方“topic 枚举” |
|
|
30
33
|
| `definition_code` | 否 | 审批定义 Code,用于仅查询某个审批定义下的任务 |
|
|
34
|
+
| `start_timestamp` | 否 | 按任务时间筛选,时间范围开始值,秒级时间戳 |
|
|
35
|
+
| `end_timestamp` | 否 | 按任务时间筛选,时间范围结束值,秒级时间戳 |
|
|
31
36
|
| `locale` | 否 | 返回语言:`zh-CN`、`en-US`、`ja-JP` |
|
|
32
37
|
| `page_size` | 否 | 分页大小 |
|
|
33
38
|
| `page_token` | 否 | 翻页标记;首次请求不填,后续使用上一次返回的 `page_token` |
|
|
@@ -67,10 +72,14 @@ lark-cli approval tasks query --params '{"topic":"1"}' --format table --as user
|
|
|
67
72
|
| `tasks[].summaries` | 表单摘要字段列表 |
|
|
68
73
|
| `tasks[].support_api_operate` | 是否支持通过 API 同意或拒绝该任务 |
|
|
69
74
|
| `tasks[].user_id` | 任务所属用户 ID |
|
|
75
|
+
| `tasks[].instance_external_id` | 三方审批实例 ID,仅第三方审批实例存在 |
|
|
76
|
+
| `tasks[].task_external_id` | 三方审批任务 ID,仅第三方审批任务存在 |
|
|
77
|
+
| `tasks[].link` | 三方审批跳转链接 |
|
|
70
78
|
|
|
71
79
|
## 使用建议
|
|
72
80
|
|
|
73
81
|
- 常见处理链:先用 `tasks query` 拿到 `task_id` 和 `instance_code`,若用户需要查看详情、当前节点、表单内容、流程进度等内容,则调用 `instances get` 查看详情,最后执行 `tasks approve` / `tasks reject` / `tasks transfer` / `tasks add_sign` / `tasks rollback`。
|
|
74
82
|
- 如果你只想看“已发起的审批实例”,使用 `instances initiated`;`tasks query` 更适合围绕“任务分组”来拉取列表。
|
|
83
|
+
- 按时间排查任务时使用 `start_timestamp` / `end_timestamp` 缩小范围;这两个值都是秒级时间戳。
|
|
75
84
|
- 需要继续翻页时,直接把上一次返回的 `page_token` 放回 `--params`。
|
|
76
85
|
- 当结果量较大时,优先使用 `--format table` 提升可读性。
|
|
@@ -23,6 +23,12 @@ lark-cli approval tasks rollback \
|
|
|
23
23
|
--as user \
|
|
24
24
|
--yes
|
|
25
25
|
|
|
26
|
+
# 退回到发起节点(发起节点 ID 为 START)
|
|
27
|
+
lark-cli approval tasks rollback \
|
|
28
|
+
--data '{"instance_code":"<INSTANCE_CODE>","task_id":"<TASK_ID>","node_ids":["START"],"comment":"退回发起人补充材料"}' \
|
|
29
|
+
--as user \
|
|
30
|
+
--yes
|
|
31
|
+
|
|
26
32
|
# 传多个候选节点 ID(以实际审批定义支持情况为准)
|
|
27
33
|
lark-cli approval tasks rollback \
|
|
28
34
|
--data '{"instance_code":"<INSTANCE_CODE>","task_id":"<TASK_ID>","node_ids":["<NODE_ID_1>","<NODE_ID_2>"],"comment":"退回上一处理节点"}' \
|
|
@@ -43,7 +49,7 @@ lark-cli approval tasks rollback \
|
|
|
43
49
|
| `--data '{...}'` | 是 | 请求体 JSON,使用 JSON 传入 |
|
|
44
50
|
| `instance_code` | 是 | 审批实例 Code;通常先通过 `tasks query` 或 `instances initiated` / `instances get` 获取 |
|
|
45
51
|
| `task_id` | 是 | 审批任务 ID;通常先通过 `tasks query` 获取 |
|
|
46
|
-
| `node_ids` | 是 | 退回目标节点 ID
|
|
52
|
+
| `node_ids` | 是 | 退回目标节点 ID 数组;发起节点 ID 为 `START`;执行前应先确认这些节点确实可作为退回目标 |
|
|
47
53
|
| `comment` | 否 | 审批意见或退回说明,例如 `请补充附件后重新提交`、`预算说明不完整,请补充` |
|
|
48
54
|
| `--as user` | 否 | 建议显式指定用户身份;审批退回通常必须以用户身份执行 |
|
|
49
55
|
| `--yes` | 否 | 确认执行高风险写操作;未带时可能返回 `confirmation_required` / exit 10 |
|
|
@@ -75,7 +81,7 @@ lark-cli approval instances get --params '{"instance_code":"<INSTANCE_CODE>"}' -
|
|
|
75
81
|
## 使用建议
|
|
76
82
|
|
|
77
83
|
- **`instance_code` 和 `task_id` 要成对使用**:仅有实例 ID 或仅有任务 ID 都不足以准确执行退回操作。
|
|
78
|
-
- **`node_ids` 是必填项**:退回并不是“自动退回上一步”,而是要明确给出目标节点 ID
|
|
84
|
+
- **`node_ids` 是必填项**:退回并不是“自动退回上一步”,而是要明确给出目标节点 ID 数组;退回发起节点时传 `START`。
|
|
79
85
|
- **先确认节点是否可退回**:不同审批定义支持的退回目标可能不同;在不确定时,先通过 `instances get` 或业务侧流程信息核实。
|
|
80
86
|
- **优先从 `tasks query` 的待办列表拿任务参数**:尤其是 `topic=1` 的待办审批,最适合作为 rollback 的输入来源。
|
|
81
87
|
- **先检查是否支持 API 操作**:如果 `tasks[].support_api_operate` 为 `false`,说明该任务可能不支持通过 API 执行处理动作,退回前应谨慎验证。
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: lark-apps
|
|
3
3
|
version: 1.0.0
|
|
4
|
-
description: "妙搭(Spark/Miaoda)应用开发与托管:应用创建、HTML静态站点发布、本地全栈开发、云端生成迭代、AI相关能力和飞书平台能力或者其他外部能力集成、日志/Trace/监控指标/PV/UV
|
|
4
|
+
description: "妙搭(Spark/Miaoda)应用开发与托管:应用创建、HTML静态站点发布、本地全栈开发、云端生成迭代、AI相关能力和飞书平台能力或者其他外部能力集成、日志/Trace/监控指标/PV/UV 查询、环境变量管理、应用角色与成员管理、自动化触发器(定时/记录变更/Webhook/飞书审批)。当用户要开发/新建一个系统·工具·平台·应用,或要本地开发 / 云端开发 / 修改 / 部署 / 发布 / 上线 / 拿可分享链接,或用 HTML 做页面·网站·部署到妙搭,或提到妙搭/Spark/Miaoda(应用运行时域名形如 *.aiforce.cloud)、应用数据库、应用文件存储、开放 API Key、可见范围、应用角色/角色成员、线上日志、接口请求量、错误量、延迟、访问量、环境变量、给妙搭应用配自动化任务/定时触发/审批通过后自动触发时使用。不负责普通云盘文件上传(lark-drive)、飞书文档编辑(lark-doc)、原生幻灯片创建(lark-slides)。"
|
|
5
5
|
metadata:
|
|
6
6
|
requires:
|
|
7
7
|
bins: ["lark-cli"]
|
|
@@ -12,6 +12,16 @@ metadata:
|
|
|
12
12
|
|
|
13
13
|
妙搭应用属于用户资产。默认用 `--as user`;认证、scope、exit-10、高风险确认、`_notice` 等通用处理只读 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md),不要在本 skill 里复制。妙搭应用有三条开发路径:**本地全栈**(拉源码本地写)/ **HTML 托管**(发布静态产物)/ **云端会话**(妙搭 AI 生成)。
|
|
14
14
|
|
|
15
|
+
## 身份与授权
|
|
16
|
+
|
|
17
|
+
妙搭应用是用户的个人资产,统一 `--as user`(见开头)。已有用户身份可用时直接执行业务命令,**不要为了预防权限问题主动重新登录**,否则可能中断原任务并触发不必要的设备授权。仅当 CLI 明确返回未登录或缺少本域 scope 时,一次性执行:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
lark-cli auth login --domain apps
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
因缺权限失败(`error.subtype == "missing_scope"`)时的通用处理见 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md),同样按 `--domain apps` 授权;授权成功后只恢复原业务操作,不扩展任务范围。
|
|
24
|
+
|
|
15
25
|
## 意图路由
|
|
16
26
|
|
|
17
27
|
按具体操作查命令(开发路径先用下方「选择开发路径」判定表定好再进来取命令):
|
|
@@ -20,19 +30,22 @@ metadata:
|
|
|
20
30
|
|---|---|---|
|
|
21
31
|
| 创建**新**应用资产、拿 app_id | `+create` | [`lark-apps-create.md`](references/lark-apps-create.md) |
|
|
22
32
|
| 找已有 app_id、按名字过滤应用 | `+list --keyword <name>` | [`lark-apps-list.md`](references/lark-apps-list.md) |
|
|
33
|
+
| 查单个应用详情(类型、名称、发布状态等) | `+get --app-id <app_id>` | [`lark-apps-get.md`](references/lark-apps-get.md) |
|
|
23
34
|
| 改应用名或描述 | `+update` | [`lark-apps-update.md`](references/lark-apps-update.md) |
|
|
24
35
|
| 发布本地 `index.html` 或静态目录为可访问 URL | `+html-publish` | [`lark-apps-html-publish.md`](references/lark-apps-html-publish.md) |
|
|
25
|
-
| 开发已有应用 / 初始化本地仓库(开发方式已定为本地后;先解析 app_id,勿 `+create` 新建) | `+init`(或手动 `+git-credential-init` + 原生 git)。**执行前必读** [`lark-apps-local-dev.md`](references/lark-apps-local-dev.md)
|
|
36
|
+
| 开发已有应用 / 初始化本地仓库(开发方式已定为本地后;先解析 app_id,勿 `+create` 新建) | `+init`(或手动 `+git-credential-init` + 原生 git)。**执行前必读** [`lark-apps-local-dev.md`](references/lark-apps-local-dev.md);修改源码还须遵守下方「平台资源与应用源码边界」 | [`lark-apps-init.md`](references/lark-apps-init.md), [`lark-apps-git-credential.md`](references/lark-apps-git-credential.md) |
|
|
26
37
|
| 本地开发时 `.env.local` 损坏/丢失,重新拉取启动期环境变量 | `+env-pull` | [`lark-apps-env-pull.md`](references/lark-apps-env-pull.md) |
|
|
27
38
|
| 管理应用环境变量(查看/设置/删除) | `+env-list`, `+env-set`, `+env-delete` | [`lark-apps-env.md`](references/lark-apps-env.md) |
|
|
28
39
|
| 查线上日志、Trace、请求数、错误率、延迟、CPU、memory、PV/UV/访问量 | `+log-list`, `+log-get`, `+trace-list`, `+trace-get`, `+metric-list`, `+analytics-list` | [`lark-apps-observability.md`](references/lark-apps-observability.md) |
|
|
29
40
|
| 看表 / 看结构 / 初始化多环境 / 导入导出数据 / 变更追溯 / 行级审计 / dev→online 发布 / 时间点恢复 / 查 DB 用量 | `+db-table-list`、`+db-table-get`、`+db-env-create`、`+db-data-export`/`+db-data-import`、`+db-changelog-list`、`+db-audit-status`/`+db-audit-enable`/`+db-audit-disable`/`+db-audit-list`、`+db-env-diff`/`+db-env-migrate`、`+db-recovery-diff`/`+db-recovery-apply`、`+db-quota-get` | [`lark-apps-db.md`](references/lark-apps-db.md) |
|
|
30
|
-
| 逐条执行 SQL(SELECT / DML / DDL
|
|
41
|
+
| 逐条执行 SQL(SELECT / DML / DDL);建表 / 改表 / 写 SQL 的平台规范 | `+db-execute` | [`lark-apps-db-execute.md`](references/lark-apps-db-execute.md)(含「平台 SQL 规范」:审计列 / RLS / `user_profile` / 禁用 SQL / PG 陷阱) |
|
|
31
42
|
| 管理应用文件存储:上传/下载本地文件、列出/查看/删除已存文件、生成临时分享链接、查存储用量 | `+file-upload`/`+file-download`/`+file-list`/`+file-get`/`+file-sign`/`+file-delete`/`+file-quota-get` | [`lark-apps-file.md`](references/lark-apps-file.md) |
|
|
32
43
|
| **部署/上线全栈应用**("部署""上线""推上去并部署""发布到云端");查发布状态/历史 | `+release-create`(部署上线动作), `+release-get`(轮询发布结果,finished 给 online_url / failed 给 error_logs), `+release-list` | [`lark-apps-release-create.md`](references/lark-apps-release-create.md), [`lark-apps-release-get.md`](references/lark-apps-release-get.md), [`lark-apps-release-list.md`](references/lark-apps-release-list.md) |
|
|
33
44
|
| 设置或查看运行时可见范围 | `+access-scope-set`, `+access-scope-get` | 对应 access-scope reference |
|
|
45
|
+
| 管理 `app_...` 应用内角色、角色成员,或查询用户匹配角色 | `+role-list/get/create/update/delete`, `+role-member-list/add/remove`, `+role-match-list` | [`lark-apps-role.md`](references/lark-apps-role.md) |
|
|
34
46
|
| 云端 Agent 生成/迭代应用(开发方式已定为云端后) | `+session-create` -> `+chat` -> `+session-get` | [`lark-apps-cloud-dev.md`](references/lark-apps-cloud-dev.md) |
|
|
35
47
|
| 管理妙搭应用开放 API Key(创建/查看/启停/重置/删除凭证;密钥仅 create/reset 一次性返回) | `+openapi-key-list/get/create/update/enable/disable/delete/reset` | [`lark-apps-openapi-key.md`](references/lark-apps-openapi-key.md) |
|
|
48
|
+
| 管理妙搭应用自动化触发器(定时/记录变更/Webhook/飞书审批四类触发器的查询/创建/更新/启停;Webhook URL·Token 一次性回显、不落盘) | `+automation-list/get/create/update/enable/disable` | [`lark-apps-automation.md`](references/lark-apps-automation.md) |
|
|
36
49
|
| 查看某次会话某一轮(turn)的回复消息(含仍在生成中的本轮)/ 导出上一轮模型回复("这一轮回复了什么""上一轮的回复""导出某轮消息") | 先 `+session-get`(取 `latest_turn.turn_id`)-> `+session-messages-list --turn-id <id>`(仅 user 身份;分页用 `--page-token`) | [`lark-apps-session-messages-list.md`](references/lark-apps-session-messages-list.md) |
|
|
37
50
|
| 外部能力(AI模型能力和飞书平台能力)集成/插件/Plugin/Capability | `+plugin-install`, `+plugin-list`, `+plugin-uninstall` | [`lark-apps-plugin-install.md`](references/lark-apps-plugin-install.md), [`lark-apps-plugin-uninstall.md`](references/lark-apps-plugin-uninstall.md), [`lark-apps-plugin-list.md`](references/lark-apps-plugin-list.md) |
|
|
38
51
|
|
|
@@ -66,10 +79,15 @@ metadata:
|
|
|
66
79
|
- 发布态链接来源:html → `+html-publish` 的 `data.url`;全栈 → `+release-get` 轮询 `finished` 给 `online_url` / `failed` 给 `error_logs`。
|
|
67
80
|
- **可见范围**:发布态链接(html 的 `data.url`、全栈的 `online_url`)默认仅**创建者可见**,发给他人对方会无权限打不开。当可分享链接交付给用户前,先告知当前仅本人可见,再询问是否用 `+access-scope-set`(`tenant`/`public`/`specific`)放开(可先 `+access-scope-get` 查当前范围)。
|
|
68
81
|
|
|
69
|
-
##
|
|
82
|
+
## 平台资源与应用源码边界
|
|
70
83
|
|
|
71
|
-
-
|
|
72
|
-
-
|
|
84
|
+
- `apps +role-*` 只管理平台角色资源;修改已初始化应用的源码(包括当前目录已经是应用项目)时,先查看工作区 `.agents/skills/`,完整读取与任务匹配的领域 skill,再按其路由读取所需 reference。角色鉴权或运行态角色管理读应用内 `authz-guide`,不能用本 skill 的平台命令参考推断运行时合同。
|
|
85
|
+
- `lark-cli` 只用于开发过程中的平台资源核验或变更。应用运行时代码必须使用工程内领域 skill 规定的 SDK,禁止通过 `exec` 或子进程调用 `lark-cli`。
|
|
86
|
+
- 平台回读出的当前资源 ID、名称和成员只用于事实核验,不自动构成业务策略;除非需求或应用内领域 skill 明确定义,禁止把当前样本硬编码成 allowlist、denylist、只读集合或权限规则。
|
|
87
|
+
- 实现领域 SDK 时,以实际包导出的类型和应用内领域 reference 记录的入参、响应路径为准;禁止修改 ambient `.d.ts`、补造宽松类型或强制断言,让猜测的 SDK 结构仅在本地“编译通过”。
|
|
88
|
+
- typecheck/build 成功不等于合同正确。交付前逐项核对每个 SDK 调用的入参、响应取值路径和策略分支;涉及更新、删除等不同动作时,分别验证各自动作所需的完整状态,不能复用更弱的前置判断。
|
|
89
|
+
- 源码任务交付前确认新增页面、Controller、Module 已接入真实 router/bootstrap,并运行项目现有 typecheck/build;只创建未接线文件不算完成。
|
|
90
|
+
- `+access-scope-*` 只管运行时可见范围(谁能打开应用),不是角色权限;应用协作者/开发权限仍需使用妙搭 Web。自动化触发器请用 `+automation-*`(见「意图路由」)。
|
|
73
91
|
|
|
74
92
|
## app_id 获取
|
|
75
93
|
|
|
@@ -89,4 +107,4 @@ metadata:
|
|
|
89
107
|
## 高影响动作:确认与预授权
|
|
90
108
|
|
|
91
109
|
- **预授权判定**:判断用户是否表达了"放手做完、不用中途逐步问我"的意图——明确免确认(如"别问 / 直接做 / 自己定"),或要求一气呵成做到完成(如"做完部署上线给我")。是 → 整个流程按合理默认往下走、不再逐步确认(含 clone 到派生目录、发布等);否 → 缺失参数(如目录)该问就问、高影响动作先确认。
|
|
92
|
-
- **禁止预授权判定底线**(即便已预授权也不豁免):① 会删/丢数据或不可逆的 DB 操作(判据见 [`lark-apps-db-execute.md`](references/lark-apps-db-execute.md))先 `--dry-run` 确认;② `+html-publish` 体积超限时(判据见 [`lark-apps-html-publish.md`](references/lark-apps-html-publish.md)),立即停止并转述超限项。
|
|
110
|
+
- **禁止预授权判定底线**(即便已预授权也不豁免):① 会删/丢数据或不可逆的 DB 操作(判据见 [`lark-apps-db-execute.md`](references/lark-apps-db-execute.md))先 `--dry-run` 确认;② `+role-delete`、`+role-member-remove --all`、批量移除成员必须先确认 app、role、成员范围和后果,不能从泛化"直接做"推导出 `--yes`;命令式“删除/移除某对象”只确定操作目标,不等于用户已确认不可逆后果,未明确确认时应在说明影响后停下请求确认;③ `+html-publish` 体积超限时(判据见 [`lark-apps-html-publish.md`](references/lark-apps-html-publish.md)),立即停止并转述超限项。
|
|
@@ -37,4 +37,4 @@ lark-cli apps +access-scope-set --app-id app_xxx --scope specific \
|
|
|
37
37
|
|
|
38
38
|
若服务端返回"应用未发布/需先发布才能设置可见范围",把这一情况转述给用户并询问是否现在发布,得到同意后再 `+release-create`,不要把这个 hint 当指令自动发布。
|
|
39
39
|
|
|
40
|
-
用户给的是姓名、部门名或群名时,先解析成 ID 再组装 `--targets`:人名→`ou_` 用 `lark-cli contact +search-user --query <名字>`,群名→`oc_` 用 `lark-cli im +chat-search --query <群名>`,部门→`
|
|
40
|
+
用户给的是姓名、部门名或群名时,先解析成 ID 再组装 `--targets`:人名→`ou_` 用 `lark-cli contact +search-user --query <名字>`,群名→`oc_` 用 `lark-cli im +chat-search --query <群名>`,部门→`od-` 走 contact/通讯录。多候选时展示名称和 ID 让用户选,不要要求用户手填 `ou_` / `od-` / `oc_`。
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# apps automation 触发器命令族 SOP
|
|
2
|
+
|
|
3
|
+
管理妙搭应用的自动化触发器(定时 / 记录变更 / Webhook / 飞书审批四类)。全部操作需 `--as user`(AuthType: user)。`--help` 是参数细节的完整来源;本文件只记录 Agent 不看就会做错的领域规则。
|
|
4
|
+
|
|
5
|
+
## 何时用本 skill(路由锚点)
|
|
6
|
+
|
|
7
|
+
**当用户消息里出现「妙搭应用名 / app_id」+ 以下任一意图,路由本 skill,不要走 lark-event 或 lark-openapi-explorer:**
|
|
8
|
+
|
|
9
|
+
- 「(每天 / 定时 / 每 N 小时 / 每周 X)自动跑 / 自动触发 / 定时同步」→ `+automation-create --trigger-type cron`
|
|
10
|
+
- 「数据表 / 记录 / 表里 X 字段(新增 / 更新 / 删除 / 变化)时(触发 / 通知 / 处理)」→ `+automation-create --trigger-type record-change`
|
|
11
|
+
- 「(webhook / 外部回调 / 外部系统调用 / HTTP 触发)」→ `+automation-create --trigger-type webhook`
|
|
12
|
+
- 「(审批 / 报销 / 请假 / 出差)(通过 / 拒绝 / 提交 / 撤回)后自动 X」→ `+automation-create --trigger-type feishu-approval`
|
|
13
|
+
- 「这个应用配了哪些(自动化 / 触发器 / 定时任务)」→ `+automation-list`
|
|
14
|
+
- 「(暂停 / 停用 / 先别自动跑 / 关掉自动触发)某个(触发器 / 定时任务 / 自动化)」→ `+automation-disable`(不是 update 改条件、不是 delete——本 skill 不提供删除)
|
|
15
|
+
- 「换 / 重置 webhook 回调地址 / URL」→ `+automation-update --reset-url --app-env <preview|runtime>`
|
|
16
|
+
- 「换 / 重置 / 轮换 webhook token / bearer」→ `+automation-update --reset-token`
|
|
17
|
+
|
|
18
|
+
**边界(防误路由)**:`lark-event` 是**实时事件流消费**(agent 长连接订阅事件),不管妙搭应用触发器的**配置**;用户说「配 / 设置一个触发器」而不是「订阅事件流」时,本 skill 才是正确选择。「审批通过触发」在妙搭应用语境下属于本 skill 的 `feishu-approval` 类型,不是 lark-event。
|
|
19
|
+
|
|
20
|
+
### 回应「怎么配」类问题的正确姿势
|
|
21
|
+
|
|
22
|
+
用户问「怎么配 / 怎么设置一个 X 触发器」时,**先展示完整命令模板 + 你对核心参数的推断**(让用户能确认你理解对了),再追问缺失的必填项(`--name` 之类)或可选项。**不要跳过展示、直接连环追问**,那样用户没法确认你有没有理解意图。
|
|
23
|
+
|
|
24
|
+
示范:用户说「报销审批一旦通过就自动触发处理,怎么配?」
|
|
25
|
+
- ✅ 正确:先写出「这是 feishu-approval 类型,命令模板:`apps +automation-create --app-id <id> --name <name> --trigger-type feishu-approval --event-type approval_instance --instance-status APPROVED [--approval-code <code>]`。需要你确认:(1) 触发器名 `<name>`;(2) 是否限定特定审批流程——限定就传 `--approval-code`(从飞书审批管理后台拿),不传则匹配所有审批定义」。
|
|
26
|
+
- ❌ 错误:直接问「叫什么名字?监听哪个审批?」——用户没法确认你有没有把「审批通过」映射到 `--event-type approval_instance --instance-status APPROVED`。
|
|
27
|
+
|
|
28
|
+
同理,cron/record-change/webhook 三类的「怎么配」都遵循此模式:先给命令 + 参数推断,后追问缺项。
|
|
29
|
+
|
|
30
|
+
## 命令路由
|
|
31
|
+
|
|
32
|
+
| 命令 | 用途 | Risk |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `+automation-list` | 列出应用所有触发器(可按类型过滤、`--all` 聚合翻页) | read |
|
|
35
|
+
| `+automation-get` | 查看单个触发器完整配置(Webhook Bearer Token 恒脱敏) | read |
|
|
36
|
+
| `+automation-create` | 创建触发器,四类共用一条命令,按 `--trigger-type` 分派 | write |
|
|
37
|
+
| `+automation-update` | 改条件/描述,或经专用 flag 管理 Webhook URL·Token | high-risk-write |
|
|
38
|
+
| `+automation-enable` | 启用触发器(`status→enabled`,开始自动触发) | write |
|
|
39
|
+
| `+automation-disable` | 停用触发器(`status→disabled`,停止触发,不删除) | write |
|
|
40
|
+
|
|
41
|
+
触发器以 **应用内唯一的 `--name`** 定位(不是 id)。所有单条命令都用 `--app-id` + `--name`;名字忘了先 `+automation-list` 查。
|
|
42
|
+
|
|
43
|
+
## 四类触发器 payload
|
|
44
|
+
|
|
45
|
+
`--trigger-type` 用面向 Agent 的 kebab-case(`cron` / `record-change` / `webhook` / `feishu-approval`),CLI 内部转 snake_case 下推。类型专属 flag 只在对应类型生效。
|
|
46
|
+
|
|
47
|
+
### cron(定时)
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
+automation-create --app-id <id> --name daily --trigger-type cron \
|
|
51
|
+
--cron '0 9 * * *' [--timezone Asia/Shanghai]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- `--cron` 是**五段式**(`minute hour day month weekday`),非六段。
|
|
55
|
+
- **最小间隔 30 分钟**:`--cron '* * * * *'`(每分钟)或 `*/n`(n<30)会被 CLI 本地拦截报错;后端也会二次校验。
|
|
56
|
+
- `--timezone` 缺省补 `Asia/Shanghai`(IANA 时区名)。
|
|
57
|
+
|
|
58
|
+
### record-change(记录变更)
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
+automation-create --app-id <id> --name onUpd --trigger-type record-change \
|
|
62
|
+
--table <table_name> --event UPDATE [--fields '["status"]']
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- `--event` 是**大写枚举**:`INSERT` / `UPDATE` / `UPSERT` / `DELETE`(CLI 会 uppercase,但请按枚举传)。
|
|
66
|
+
- `--table` 是应用数据库里的**表名**(对应 `+db-table-list` / `+db-table-get` 输出里 `.name` 字段的值),必填。妙搭应用的 dataloom 表以名称作为稳定标识符,没有独立的 `table_id`。
|
|
67
|
+
- `--fields` 是 JSON 字符串数组,仅对 `UPDATE`/`UPSERT` 有意义;`'["*"]'` 表示监听所有字段;不传表示不限定字段。
|
|
68
|
+
|
|
69
|
+
### webhook(外部回调)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
+automation-create --app-id <id> --name hook --trigger-type webhook \
|
|
73
|
+
[--white-ip-list '["1.1.1.1","2.2.2.2"]']
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- 创建时可选 `--white-ip-list`(JSON 字符串数组)限制回调来源 IP。
|
|
77
|
+
- 回调 URL 分 **preview / runtime 两套**,创建时不回显;用 `+automation-get` 查当前配置,用 `+automation-update --reset-url --app-env <preview|runtime>` 轮换。
|
|
78
|
+
- Bearer Token 是回调鉴权凭证,见下方「凭证脱敏与一次性回显」。
|
|
79
|
+
|
|
80
|
+
### feishu-approval(飞书审批)
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
+automation-create --app-id <id> --name apv --trigger-type feishu-approval \
|
|
84
|
+
--event-type approval_instance --instance-status APPROVED [--approval-code <code>]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
- `--event-type` 必填,取 `approval_instance` 或 `approval_task`,决定状态用哪套 flag:
|
|
88
|
+
- `approval_instance` → `--instance-status`(可重复)
|
|
89
|
+
- `approval_task` → `--task-status`(可重复)
|
|
90
|
+
- **领域规则**:状态按 `event-type` 分桶校验,两桶枚举**不完全相同**(`PENDING`/`APPROVED`/`REJECTED`/`REVERTED`/`OVERTIME_CLOSE`/`OVERTIME_RECOVER` 两桶共享;`TRANSFERRED`/`ROLLBACK`/`DONE` 仅 task 有;`CANCELED`/`DELETED` 仅 instance 有);传错桶的状态会被 CLI 本地拦截,错误信息会打印该桶的合法值列表。具体枚举见命令 `--help`。
|
|
91
|
+
|
|
92
|
+
## approval-code 获取路径
|
|
93
|
+
|
|
94
|
+
`--approval-code` **可选**。不传时匹配所有审批定义;要限定某个审批流程时,从**飞书审批管理后台**获取具体的 code 传给它。触发器 OpenAPI 不提供审批定义查询能力,具体 code 需去审批管理后台查。
|
|
95
|
+
|
|
96
|
+
## 凭证脱敏与一次性回显(安全关键)
|
|
97
|
+
|
|
98
|
+
- `+automation-get` / `+automation-list`:**恒不返回明文 Bearer Token**——`trigger_condition.token_value` 被抹为 `null`。用户想知道「token 是什么」时,list/get 都查不到明文。
|
|
99
|
+
- `+automation-update --enable-token` / `--reset-token`:明文 Bearer Token **仅当次 stdout 回显一次**,同时 stderr 打印一次性告警:
|
|
100
|
+
```text
|
|
101
|
+
warning: this bearer token is shown only once and is NOT stored by lark-cli — copy it now and store it in your own secret manager.
|
|
102
|
+
```
|
|
103
|
+
- Webhook URL 同理:`--reset-url` 后新 URL 仅当次回显一次,旧 URL 立即失效。
|
|
104
|
+
- CLI 不落盘任何明文 token/URL(不写 cache / config / recent / debug log / 错误信息)。
|
|
105
|
+
- **Token 丢失只能 reset**:找不回,唯一恢复方式是 `+automation-update --reset-token`(旧 token 同时失效)。
|
|
106
|
+
|
|
107
|
+
## 高危确认
|
|
108
|
+
|
|
109
|
+
`+automation-update` 整体是 `high-risk-write`,任何一次调用都需显式 `--yes`;缺少时框架会要求确认(退出码 10)。**不要自动补 `--yes`**——需用户明确确认后再加。以下 Webhook 动作 flag 尤其不可逆:
|
|
110
|
+
|
|
111
|
+
- `--reset-url`(旧回调 URL 立即失效,需配 `--app-env preview|runtime`)
|
|
112
|
+
- `--reset-token`(旧 token 立即失效)
|
|
113
|
+
- `--disable-token`(关闭 token 校验,**不可逆**)
|
|
114
|
+
|
|
115
|
+
四个 Webhook 动作 flag(`--reset-url` / `--enable-token` / `--disable-token` / `--reset-token`)**每次只能传一个**。不确定影响时先跑 `--dry-run` 看将发出的请求(不含明文)。
|
|
116
|
+
|
|
117
|
+
### 执行前必须完成的确认步骤(高危写强制协议)
|
|
118
|
+
|
|
119
|
+
**在带 `--yes` 执行任何高危写之前,Agent 必须先完成以下 3 件事**,缺一不可——即使用户口气很急、即使命令一眼就明:
|
|
120
|
+
|
|
121
|
+
1. **确认目标唯一**:不允许"猜名字"或"批量试所有可能的名字"。若不确定 `--name`,先 `+automation-list --app-id <id>` 让用户在候选中点名;`--name` 不明的绝不执行写操作,更不要 for 循环批量试。
|
|
122
|
+
2. **确认可选参数已定**:`--reset-url` 必须由用户明确指定 `--app-env preview` 还是 `runtime`;不要默认取 runtime 或 preview。同一触发器的 preview/runtime 是两条独立的 URL,误重置另一条不可回退。
|
|
123
|
+
3. **告知不可逆后果并等确认**:把即将发生的 3 件事复述给用户——(a)旧 URL/Token 立即永久失效;(b)新 URL/Token 仅当次回显一次、CLI 不保存;(c)本次操作无法撤销——等用户回复"确认"再加 `--yes` 跑。
|
|
124
|
+
|
|
125
|
+
只要有一项没做,就先跟用户对齐、不要执行。这些是 skill 层的护栏,不是 CLI 层的(CLI 只强制 `--yes`,不强制上面 3 件事)。
|
|
126
|
+
|
|
127
|
+
## ⚠️ 安全告警:无鉴权公网回调组合态
|
|
128
|
+
|
|
129
|
+
`--disable-token`(关闭 Bearer Token 校验,不可逆)**叠加** `--white-ip-list '[]'`(清空 IP 白名单)会让 Webhook 触发器进入「**无鉴权公网回调**」组合态——**任何来源都能触发该 Webhook**,没有任何一道防线拦截。
|
|
130
|
+
|
|
131
|
+
- 两道防线:Token 校验(谁能调)+ IP 白名单(从哪能调)。**不要同时关闭这两道防线。**
|
|
132
|
+
- 若确需关闭 Token(例如对端无法带 Bearer 头),务必**保留 IP 白名单**收敛来源;反之若要放开 IP,务必**保留 Token 校验**。
|
|
133
|
+
- 用户同时要求「关 token 校验 + 清空 IP 白名单」时,Agent 的正确响应是**在识别到该请求的第一时间**(不要等命令跑失败才补警告)向用户输出以下 3 件事,再等确认——不要只描述"没有任何防线"就停下:
|
|
134
|
+
1. 复述后果:这会形成无鉴权公网回调,任何来源都能触发。
|
|
135
|
+
2. **主动给出替代方案**:明确建议"要么只关 Token 保留 IP 白名单,要么只放开 IP 保留 Token",让用户在保留一道防线的两条备选里选一条。
|
|
136
|
+
3. 只有用户明确回复"我理解风险、就是要两道都关"时,才继续按高危写协议(见上节「执行前必须完成的确认步骤」)走。
|
|
137
|
+
|
|
138
|
+
## 默认 disabled
|
|
139
|
+
|
|
140
|
+
`+automation-create` 创建后触发器**默认 disabled**,不会自动触发。需 `+automation-enable` 才开始按条件自动运行(且触发器执行的是**线上已发布**的应用代码——应用未发布时即便 enable 也不会有实际效果)。
|
|
141
|
+
|
|
142
|
+
**Agent 行为约束**:用户只说"创建/配一个触发器"时,**不要**主动在同一个 turn 里 `+automation-enable`。让用户自己在下一轮决定是否启用;主动启用会:
|
|
143
|
+
- 让 webhook 类型立即可被外部调用(原本用户可能只是想"备好 URL 稍后用")
|
|
144
|
+
- 让 cron 到点真实触发(原本用户可能想"先建好观察配置")
|
|
145
|
+
- 让 record-change 立即响应表变更
|
|
146
|
+
|
|
147
|
+
创建成功后的推荐话术:`已创建 <name>,当前 disabled;需要真正开始自动运行时告诉我,我用 +automation-enable 启用它。` **不要**在创建成功后立即启用,即使 skill 里说"需 enable 才自动触发"——这条是给用户的说明,不是给 agent 的行动指令。
|
|
148
|
+
|
|
149
|
+
## 常见错误与决策场景
|
|
150
|
+
|
|
151
|
+
| 现象 / 用户意图 | 正确处理 |
|
|
152
|
+
|---|---|
|
|
153
|
+
| 创建报名字冲突(`--name` 应用内唯一) | 换名或加后缀重试 |
|
|
154
|
+
| cron 报非法 / 间隔过小 | 检查是否五段式、分钟字段是否 `*` 或 `*/n`(n<30) |
|
|
155
|
+
| `--reset-url` 报缺 app-env | 补 `--app-env preview` 或 `--app-env runtime` |
|
|
156
|
+
| 想把 cron 触发器改成 webhook(跨类型改) | update 不支持换类型,本 skill 也不提供删除。旧触发器只能 `+automation-disable` 停用(保留在应用里),另建一个 webhook 触发器;若要真正清理旧触发器,请到妙搭 web 手动删除 |
|
|
157
|
+
| 触发器 enable 了但不触发 | 确认应用**已发布**;触发器跑的是线上已发布代码 |
|
|
158
|
+
| 「token 泄露了」 | 优先 `+automation-update --reset-token --yes` 轮换(旧 token 立即失效),而非直接 disable-token 关校验 |
|
|
159
|
+
| 「回调 URL 泄露了」 | `+automation-update --reset-url --app-env <env> --yes` 轮换 |
|
|
160
|
+
|
|
161
|
+
## 不在本 skill 范围
|
|
162
|
+
|
|
163
|
+
- 审批定义查询、Webhook 消费端实现、实时触发日志 tail:本期不支持。
|
|
164
|
+
- 身份选择、权限不足处理、exit-10 审批、通用「禁输出密钥」红线、高风险操作通用框架:见 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md),不在此重复。
|
|
@@ -2,16 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
经妙搭服务端在应用数据库执行 SQL。运行时命令事实以 `lark-cli apps +db-execute --help` 为准。
|
|
4
4
|
|
|
5
|
+
> **写 SQL 前先看文末「平台 SQL 规范」**:妙搭底层是 PostgreSQL + 一层平台约束,SQL 内容不符合会被服务端直接拒或建出行为不对的表。最容易踩的三条:① 建业务表必须带 4 个审计列(`_created_at`/`_updated_at`/`_created_by`/`_updated_by`)+ 启用 RLS + 4 条 policy,一次调用里写全;② 人员字段用内置复合类型 `user_profile`(写入 `ROW('<user_id>')::user_profile`,查询解引用 `(field).user_id`);③ `CREATE/DROP DATABASE·SCHEMA·USER·ROLE`、非白名单 `CREATE EXTENSION`、平台保留表 `auth`/`users` 会被硬拒,`online` 环境禁 DDL。
|
|
6
|
+
|
|
5
7
|
## 何时用
|
|
6
8
|
|
|
7
|
-
用于通过妙搭服务端执行应用数据库 SQL。不要从环境变量里取连接串裸连数据库;本地调试也走这个 shortcut
|
|
9
|
+
用于通过妙搭服务端执行应用数据库 SQL。不要从环境变量里取连接串裸连数据库;本地调试也走这个 shortcut。写什么样的 SQL(平台约束、建表模板、`user_profile`、审计列、禁用 SQL、PG 陷阱)见文末「平台 SQL 规范」。
|
|
8
10
|
|
|
9
11
|
## 命令骨架
|
|
10
12
|
|
|
11
13
|
- 必填:`--app-id`,以及 `--sql` / `--file` 二选一(互斥)。
|
|
12
14
|
- `--sql`:内联 SQL 文本;传 `-` 时从 stdin 读。绝对路径文件经 stdin 传入:`--sql - < <absolute-path>`(shell 解析路径,CLI 仅接收内容)。
|
|
13
15
|
- `--file`:`.sql` 文件路径,需为工作目录内的相对路径(如 `--file ./migration.sql`);绝对路径、或经 `..`/符号链接越出工作目录的路径会被拒绝。文件不在工作目录内时,改用 `--sql - < <文件路径>` 经 stdin 传入。
|
|
14
|
-
- `--environment` 枚举:`dev` / `online
|
|
16
|
+
- `--environment` 枚举:`dev` / `online`,**不传则由服务端按应用是否开启多环境自动选择(多环境→`dev`,未开启多环境→`online`)**;要固定环境就显式传 `--environment dev|online`。**未开启多环境的应用显式传 `--environment dev` 会报错(无 dev 分支)——这类应用不传 `--environment`(走 `online`)或显式 `--environment online`**。旧名 `--env` 已**移除**:传入会报 validation 错(提示改用 `--environment`),一律用 `--environment`。
|
|
15
17
|
- risk 是 `high-risk-write`(SQL 可含 DML/DDL):任何执行都需 `--yes`,否则返回 `confirmation_required` / exit 10。`--dry-run` 预览不需要 `--yes`。
|
|
16
18
|
- **不会自动为你包事务,事务边界需自己在 SQL 里控制**:多语句默认逐条独立提交,中间某条失败时前序语句已生效、不会回滚;若需要「要么全部成功、要么全部回滚」的原子性,请在 SQL 内显式写 `BEGIN … COMMIT`(详见下「Agent 规则」)。
|
|
17
19
|
|
|
@@ -42,3 +44,185 @@ lark-cli apps +db-execute --app-id app_xxx --environment dev --sql - --yes < /Us
|
|
|
42
44
|
- 多语句失败时,失败前的语句可能已经 commit 落地。不要整批重跑;按错误 message/hint 修失败语句,并从剩余语句继续。
|
|
43
45
|
- 如果需要原子性,让用户在 SQL 内显式写 `BEGIN` / `COMMIT`,不要假设 CLI 会包事务。
|
|
44
46
|
- 不要把数据库连接串从 env 中取出来裸连。
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
# 平台 SQL 规范
|
|
51
|
+
|
|
52
|
+
上面讲命令怎么调,这里讲**该写出什么样的 SQL**:妙搭底层是 PostgreSQL + 一层平台约束(RLS、审计列、`user_profile` 复合类型、禁用 SQL 白名单),不符合会被服务端直接拒或建出行为不对的表。看表 / 看结构用 [`+db-table-list`/`+db-table-get`](lark-apps-db.md),别手写系统表查询模拟。
|
|
53
|
+
|
|
54
|
+
## 平台禁用 SQL(硬拒绝)
|
|
55
|
+
|
|
56
|
+
以下命中会被服务端拒,`error`(`type:"api"`)的 message/hint 会说明原因——先按 hint 修再重试,不要反复重试同一句。
|
|
57
|
+
|
|
58
|
+
| 类别 | 禁止 |
|
|
59
|
+
|---|---|
|
|
60
|
+
| 数据库级 | `CREATE / DROP / ALTER DATABASE` |
|
|
61
|
+
| Schema 级 | `CREATE / DROP SCHEMA` |
|
|
62
|
+
| 用户 / 角色级 | `CREATE / DROP USER`、`CREATE / DROP / ALTER ROLE` |
|
|
63
|
+
| Owner 切换 | `REASSIGN OWNED` / `DROP OWNED` |
|
|
64
|
+
|
|
65
|
+
## 建表规范(CREATE TABLE)
|
|
66
|
+
|
|
67
|
+
新建业务表必须:4 个审计列 + 启用 RLS + 4 条默认 policy,**放在同一次 `+db-execute` 调用里**(RLS / policy / COMMENT / INDEX 一起)。裸表名,不写 `public.` 或 schema 前缀。
|
|
68
|
+
|
|
69
|
+
```sql
|
|
70
|
+
CREATE TABLE IF NOT EXISTS <table> (
|
|
71
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
72
|
+
-- ... 业务列 ...
|
|
73
|
+
name varchar(100) NOT NULL,
|
|
74
|
+
_created_at TIMESTAMP(3) WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
75
|
+
_created_by user_profile DEFAULT (
|
|
76
|
+
CASE
|
|
77
|
+
WHEN current_setting('app.user_id', TRUE) = '' THEN NULL
|
|
78
|
+
ELSE concat('(', current_setting('app.user_id', TRUE), ')')::user_profile
|
|
79
|
+
END
|
|
80
|
+
),
|
|
81
|
+
_updated_at TIMESTAMP(3) WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
82
|
+
_updated_by user_profile DEFAULT (
|
|
83
|
+
CASE
|
|
84
|
+
WHEN current_setting('app.user_id', TRUE) = '' THEN NULL
|
|
85
|
+
ELSE concat('(', current_setting('app.user_id', TRUE), ')')::user_profile
|
|
86
|
+
END
|
|
87
|
+
)
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
ALTER TABLE <table> ENABLE ROW LEVEL SECURITY;
|
|
91
|
+
|
|
92
|
+
CREATE POLICY service_role_bypass_policy ON <table>
|
|
93
|
+
TO service_role USING (true);
|
|
94
|
+
|
|
95
|
+
CREATE POLICY "修改全部数据" ON <table>
|
|
96
|
+
AS PERMISSIVE FOR ALL TO authenticated USING (true);
|
|
97
|
+
|
|
98
|
+
CREATE POLICY "查看全部数据" ON <table>
|
|
99
|
+
AS PERMISSIVE FOR SELECT TO authenticated, anon USING (true);
|
|
100
|
+
|
|
101
|
+
CREATE POLICY "修改本人数据" ON <table>
|
|
102
|
+
AS PERMISSIVE FOR ALL TO authenticated USING (
|
|
103
|
+
(current_setting('app.user_id'::text) = ANY (ARRAY[]::text[]))
|
|
104
|
+
AND (current_setting('app.user_id'::text) = ((_created_by).user_id)::text)
|
|
105
|
+
);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
建表流程:先 `+db-table-list` / `+db-table-get` 确认表不存在或看现有结构 → 生成 DDL → 向用户展示影响并取得授权 → `+db-execute ... --yes` 执行。
|
|
109
|
+
|
|
110
|
+
## 审计列
|
|
111
|
+
|
|
112
|
+
- 平台自动维护的四列固定叫 `_created_at` / `_updated_at` / `_created_by` / `_updated_by`(**下划线开头**)。查询 / 排序 / 过滤一律用这些名字,别写 `created_at`。
|
|
113
|
+
- `_created_at` / `_updated_at` 在 INSERT 时可省略(有默认值);需要业务归属时显式写 `_created_by` / `_updated_by`。
|
|
114
|
+
- UPDATE 业务字段时建议同步 `_updated_at = CURRENT_TIMESTAMP` 和 `_updated_by`。
|
|
115
|
+
|
|
116
|
+
## `user_profile` 复合类型
|
|
117
|
+
|
|
118
|
+
平台内置类型 `(user_id varchar, name varchar, email varchar, avatar text, status integer)`,无需创建。**业务 SQL 只允许访问 `(field).user_id`**,不要依赖 `name` / `email` / `avatar` / `status`(可能为空或过期)。
|
|
119
|
+
|
|
120
|
+
```sql
|
|
121
|
+
-- 写入 / 更新:用 ROW()::user_profile,更新时替换整个字段,不改单个属性
|
|
122
|
+
INSERT INTO teacher (teacher_profile, class_id)
|
|
123
|
+
VALUES (ROW('<user_id>')::user_profile, gen_random_uuid());
|
|
124
|
+
|
|
125
|
+
UPDATE teacher SET teacher_profile = ROW('<user_id>')::user_profile
|
|
126
|
+
WHERE (teacher_profile).user_id = '<old_user_id>';
|
|
127
|
+
|
|
128
|
+
-- 查询 / 过滤:解引用取 user_id;raw SQL 返回给前端前必须解引用,别直接返回复合类型
|
|
129
|
+
SELECT (teacher_profile).user_id AS teacher_profile, class_id FROM teacher;
|
|
130
|
+
|
|
131
|
+
-- 索引 / 唯一性:表达式列用三重括号;表达式唯一性用 CREATE UNIQUE INDEX,
|
|
132
|
+
-- 不能用 ALTER TABLE ADD CONSTRAINT UNIQUE(不支持表达式列)
|
|
133
|
+
CREATE INDEX idx_teacher_user_id ON teacher (((teacher_profile).user_id));
|
|
134
|
+
CREATE UNIQUE INDEX uk_teacher_user_id ON teacher (((teacher_profile).user_id));
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## DDL 规则
|
|
138
|
+
|
|
139
|
+
| 场景 | 做法 |
|
|
140
|
+
|---|---|
|
|
141
|
+
| 加列 | `ALTER TABLE <t> ADD COLUMN IF NOT EXISTS <col> <type>`,相关 `COMMENT ON` 同次执行 |
|
|
142
|
+
| 加索引 | `CREATE INDEX IF NOT EXISTS idx_<t>_<cols> ON <t>(...)` |
|
|
143
|
+
| JSONB 类型声明 | 必须 `COMMENT ON COLUMN <t>.<col> IS '@type { ... }'` 声明 TypeScript 类型,和 CREATE / ALTER 同次调用 |
|
|
144
|
+
| 加 NOT NULL 列 | 必须带 `DEFAULT` 让存量行自动填:`ADD COLUMN <col> <type> NOT NULL DEFAULT <值>` |
|
|
145
|
+
| 删表 / 删列 | 有业务数据默认禁止;必须用户明确授权后才执行,并说明数据丢失风险 |
|
|
146
|
+
| 强约束 | `UNIQUE` / `FOREIGN KEY` / `NOT NULL` 默认谨慎,不确定不加 |
|
|
147
|
+
|
|
148
|
+
**多环境库加约束前先查 online 存量**:`dev` 干净不代表 `online` 干净,约束发布到 online 会撞线上存量数据而失败。发布前一律先用 `--environment online` 查清楚,按约束类型分三种:
|
|
149
|
+
|
|
150
|
+
- **加唯一约束(`UNIQUE` / 唯一索引)**:线上不能有重复值。先查重复,有则先清理再加:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
lark-cli apps +db-execute --app-id app_xxx --environment online --sql \
|
|
154
|
+
"SELECT <cols>, count(*) FROM t GROUP BY <cols> HAVING count(*) > 1" --yes
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
- **已有列改 `NOT NULL`(收紧约束)**:线上该列不能有 NULL。先查 NULL 行数,有就先回填(`UPDATE t SET <col> = <默认值> WHERE <col> IS NULL`)再加约束:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
lark-cli apps +db-execute --app-id app_xxx --environment online --sql \
|
|
161
|
+
"SELECT count(*) FROM t WHERE <col> IS NULL" --yes
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
- **新加 `NOT NULL` 字段**:必须带 `DEFAULT`,且要求线上该表**无存量数据**,否则发布报错。线上已有数据时别直接加,改走三步安全变更:先 `ADD COLUMN <col> <type>`(可空)→ 回填 `UPDATE t SET <col> = <值>` → 再 `ALTER COLUMN <col> SET NOT NULL`。先查线上行数判断走哪条:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
lark-cli apps +db-execute --app-id app_xxx --environment online --sql \
|
|
168
|
+
"SELECT count(*) FROM t" --yes
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## SELECT 规则
|
|
172
|
+
|
|
173
|
+
| 规则 | 要求 |
|
|
174
|
+
|---|------------------------------------------------------------------|
|
|
175
|
+
| 行数 | 结果集有硬上限(平台限制 1000 行),超限**报错而非静默截断**;大表必须显式 `LIMIT`、聚合或游标分页 |
|
|
176
|
+
| 分页 | 大表优先游标分页 `WHERE id > <last_id> ORDER BY id LIMIT n`,避免大 `OFFSET` |
|
|
177
|
+
| user_profile | 返回给前端前解引用:`(owner).user_id AS owner` |
|
|
178
|
+
| 统计 | 总数用 `count(*)`、分组用 `GROUP BY`,别把全量拉到 agent 侧再统计 |
|
|
179
|
+
| 慢查询 | 用 `EXPLAIN (ANALYZE, BUFFERS)`;大表 Seq Scan 考虑加索引 |
|
|
180
|
+
|
|
181
|
+
## DML 规则
|
|
182
|
+
|
|
183
|
+
**INSERT**
|
|
184
|
+
- UUID 主键省略,交给 `DEFAULT gen_random_uuid()`;外键 UUID 用子查询取父表 id,不手写。
|
|
185
|
+
- NOT NULL 且无默认值的列必须给值;批量 INSERT 每行列数一致。
|
|
186
|
+
- 需要幂等用 `ON CONFLICT ... DO NOTHING / DO UPDATE`。
|
|
187
|
+
- 标量子查询必须保证单行,非唯一条件加 `ORDER BY ... LIMIT 1`。
|
|
188
|
+
|
|
189
|
+
**UPDATE**
|
|
190
|
+
- **必须有明确 `WHERE`,禁止无条件 UPDATE**。
|
|
191
|
+
- 用户说「修改 / 更新 / 改一下」数据时用 UPDATE,**禁止 DELETE + INSERT** 模式。
|
|
192
|
+
- 更新 `user_profile` / 复合类型时替换整个字段。
|
|
193
|
+
- 批量更新前影响范围不明确,先 `SELECT count(*)` 给用户确认。
|
|
194
|
+
|
|
195
|
+
**DELETE / TRUNCATE**(属会丢数据的高影响操作,按上面「Agent 规则」的确认流程走)
|
|
196
|
+
- 已有表 / 已有数据默认禁止;先 `SELECT count(*)` 展示命中行数、取得用户明确授权,再带 `--yes` 执行。
|
|
197
|
+
- `TRUNCATE` 影响整表,视同高风险删除。
|
|
198
|
+
|
|
199
|
+
```sql
|
|
200
|
+
UPDATE task
|
|
201
|
+
SET status = 'done', _updated_at = CURRENT_TIMESTAMP, _updated_by = ROW('<user_id>')::user_profile
|
|
202
|
+
WHERE id = (SELECT id FROM task WHERE title = '梳理需求' ORDER BY _created_at DESC LIMIT 1);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## 常见 PostgreSQL 陷阱
|
|
206
|
+
|
|
207
|
+
| 陷阱 | 正确做法 |
|
|
208
|
+
|---|---|
|
|
209
|
+
| 表名带 schema 前缀 | 业务表一律裸表名 `FROM orders`,别写 `public.orders` |
|
|
210
|
+
| 保留字作标识符 | 避免 `user` / `order` / `desc` / `offset` / `references` 等 |
|
|
211
|
+
| 内联 COMMENT | 禁止 `col TEXT COMMENT 'xx'`,用独立 `COMMENT ON COLUMN` |
|
|
212
|
+
| 手写系统表查结构 | 常规结构查询用 `+db-table-list` / `+db-table-get`,别手写 `information_schema` / `pg_indexes` 模拟 |
|
|
213
|
+
| 空数组类型不明 | 写 `ARRAY[]::text[]` 或 `'{}'::text[]` |
|
|
214
|
+
| `ROUND` 报错 | 用 `ROUND(num::numeric, n)` 或 `ROUND(num::double precision)` |
|
|
215
|
+
| `DISTINCT` + 窗口函数 | 分两层查询,先 DISTINCT 再窗口函数 |
|
|
216
|
+
| MySQL 方言 | 不用 `SHOW TABLES` / `DESCRIBE` / 内联 `COMMENT`;用 `+db-table-*` 和 `COMMENT ON` |
|
|
217
|
+
| 多语句以为自动回滚 | `A; B; C` 不自动包事务,B 失败时 A 已提交;要原子性显式 `BEGIN; ... COMMIT;`(见上「命令骨架」「Agent 规则」) |
|
|
218
|
+
|
|
219
|
+
## 数据类型与设计
|
|
220
|
+
|
|
221
|
+
| 项目 | 规则 |
|
|
222
|
+
|---|---|
|
|
223
|
+
| 主键 | 默认 `id uuid PRIMARY KEY DEFAULT gen_random_uuid()` |
|
|
224
|
+
| 命名 | 表名单数、全小写、snake_case、无冗余后缀 |
|
|
225
|
+
| 枚举 / 状态 | 用 `varchar(255)`,值用小写英文 + 下划线 |
|
|
226
|
+
| JSONB | 必须 `COMMENT ON COLUMN ... IS '@type { ... }'` 声明类型 |
|
|
227
|
+
| 附件 / 图片 | URL 用 `TEXT`,命名 `xxx_url` |
|
|
228
|
+
| 约束 | `UNIQUE` / `FOREIGN KEY` / `NOT NULL` 默认谨慎,新增 NOT NULL 列优先带 `DEFAULT` |
|