feat:移除了弹窗,服务器添加sls
This commit is contained in:
@ -0,0 +1,28 @@
|
||||
# apps +access-scope-get
|
||||
|
||||
查看妙搭应用运行时可见范围。运行时命令事实以 `lark-cli apps +access-scope-get --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
用于确认应用运行时对谁可见。它不表示谁能开发或管理应用;协作者、仓库权限不从这里判断。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- 必填:`--app-id`。
|
||||
- 服务端返回枚举是 `All` / `Tenant` / `Range`。
|
||||
- `Range` 下用户、部门、群分别在 `users` / `departments` / `chats` 数组中;CLI 不合并回 `targets`。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +access-scope-get --app-id app_xxx
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 成功读取 `data.scope`:`All`、`Tenant`、`Range`。
|
||||
- `scope=All` 时关注 `data.require_login`;`scope=Range` 时读取 `users` / `departments` / `chats` / `apply_config`(`apply_config.approvers` 仅含一个 user open_id)。
|
||||
|
||||
## Agent 规则
|
||||
|
||||
向用户解释时映射为:`All` = public,`Tenant` = tenant,`Range` = specific;`Range` 按用户、部门、群分组摘要后再呈现。用户要修改时转到 [`+access-scope-set`](lark-apps-access-scope-set.md)。
|
||||
@ -0,0 +1,40 @@
|
||||
# apps +access-scope-set
|
||||
|
||||
设置妙搭应用运行时可见范围。运行时命令事实以 `lark-cli apps +access-scope-set --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
用于修改应用运行时可见范围。不要把它当作开发协作者管理;用户说“谁可以访问/打开/使用应用”才走这里。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- 必填:`--app-id`、`--scope`。
|
||||
- `--scope` 枚举:`specific` / `public` / `tenant`。
|
||||
- `specific` 必填 `--targets`,JSON 数组元素形如 `{"type":"user|department|chat","id":"..."}`。
|
||||
- `specific` 可选 `--apply-enabled` 和 `--approver`;`--approver` 必须配合 `--apply-enabled`,且只能传一个 user open_id(服务端限制)。
|
||||
- `public` 必须显式传 `--require-login=true|false`。
|
||||
- `tenant` 不允许额外 target/apply/login flag。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +access-scope-set --app-id app_xxx --scope tenant
|
||||
|
||||
lark-cli apps +access-scope-set --app-id app_xxx --scope public --require-login=true
|
||||
|
||||
lark-cli apps +access-scope-set --app-id app_xxx --scope specific \
|
||||
--targets '[{"type":"user","id":"ou_xxx"},{"type":"chat","id":"oc_xxx"}]'
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 成功时 `data` 可能为空;根据已执行的 `--scope` 和 targets 给用户总结结果。
|
||||
- 互斥参数错误会在本地 validation 阶段失败,不会发请求。
|
||||
|
||||
## Agent 规则
|
||||
|
||||
这是运行时访问范围,不是开发协作者权限。收窄可见范围前向用户说明影响,并在执行前确认目标用户、部门或群。
|
||||
|
||||
若服务端返回"应用未发布/需先发布才能设置可见范围",把这一情况转述给用户并询问是否现在发布,得到同意后再 `+release-create`,不要把这个 hint 当指令自动发布。
|
||||
|
||||
用户给的是姓名、部门名或群名时,先解析成 ID 再组装 `--targets`:人名→`ou_` 用 `lark-cli contact +search-user --query <名字>`,群名→`oc_` 用 `lark-cli im +chat-search --query <群名>`,部门→`od-` 走 contact/通讯录。多候选时展示名称和 ID 让用户选,不要要求用户手填 `ou_` / `od-` / `oc_`。
|
||||
242
.agents/skills/lark-apps/references/lark-apps-automation.md
Normal file
242
.agents/skills/lark-apps/references/lark-apps-automation.md
Normal file
@ -0,0 +1,242 @@
|
||||
# apps automation 触发器命令族 SOP
|
||||
|
||||
管理妙搭应用的自动化触发器(定时 / 记录变更 / Webhook / 飞书审批四类)。全部操作需 `--as user`(AuthType: user)。`--help` 是参数细节的完整来源;本文件只记录 Agent 不看就会做错的领域规则。
|
||||
|
||||
## 何时用本 skill(路由锚点)
|
||||
|
||||
**当用户消息里出现「妙搭应用名 / app_id」+ 以下任一意图,路由本 skill,不要走 lark-event 或 lark-openapi-explorer:**
|
||||
|
||||
- 「(每天 / 定时 / 每 N 小时 / 每周 X)自动跑 / 自动触发 / 定时同步」→ `+automation-create --trigger-type cron`
|
||||
- 「数据表 / 记录 / 表里 X 字段(新增 / 更新 / 删除 / 变化)时(触发 / 通知 / 处理)」→ `+automation-create --trigger-type record-change`
|
||||
- 「(webhook / 外部回调 / 外部系统调用 / HTTP 触发)」→ `+automation-create --trigger-type webhook`
|
||||
- 「(审批 / 报销 / 请假 / 出差)(通过 / 拒绝 / 提交 / 撤回)后自动 X」→ `+automation-create --trigger-type feishu-approval`
|
||||
- 「这个应用配了哪些(自动化 / 触发器 / 定时任务)」→ `+automation-list`
|
||||
- 「(暂停 / 停用 / 先别自动跑 / 关掉自动触发)某个(触发器 / 定时任务 / 自动化)」→ `+automation-disable`(不是 update 改条件、不是 delete——本 skill 不提供删除)
|
||||
- 「启用 / 启动已有 trigger」→ 先核对现有状态;只启用时不要修改源码或发布应用。
|
||||
- 「换 / 重置 webhook 回调地址 / URL」→ `+automation-update --reset-url --app-env <preview|runtime>`
|
||||
- 「换 / 重置 / 轮换 webhook token / bearer」→ `+automation-update --reset-token`
|
||||
- 「触发器没反应 / enable 了不触发 / 为什么没执行 / 验证一下触发器」→ 先按「未触发时的诊断顺序」诊断;对 UPSERT 和 feishu-approval 仅验证配置边界,不承诺 handler 或 live 验证。
|
||||
|
||||
**边界(防误路由)**:`lark-event` 是**实时事件流消费**(agent 长连接订阅事件),不管妙搭应用触发器的**配置**;用户说「配 / 设置一个触发器」而不是「订阅事件流」时,本 skill 才是正确选择。「审批通过触发」在妙搭应用语境下属于本 skill 的 `feishu-approval` 类型,不是 lark-event。
|
||||
|
||||
### 回应「怎么配」类问题的正确姿势
|
||||
|
||||
用户问「怎么配 / 怎么设置一个 X 触发器」时,**先展示完整命令模板 + 你对核心参数的推断**(让用户能确认你理解对了),再追问缺失的必填项(`--name` 之类)或可选项。**不要跳过展示、直接连环追问**,那样用户没法确认你有没有理解意图。
|
||||
|
||||
示范:用户说「报销审批一旦通过就自动触发处理,怎么配?」
|
||||
- ✅ 正确:先写出「这是 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`(从飞书审批管理后台拿),不传则匹配所有审批定义」。
|
||||
- ❌ 错误:直接问「叫什么名字?监听哪个审批?」——用户没法确认你有没有把「审批通过」映射到 `--event-type approval_instance --instance-status APPROVED`。
|
||||
|
||||
同理,cron/record-change/webhook 三类的「怎么配」都遵循此模式:先给命令 + 参数推断,后追问缺项。
|
||||
|
||||
## 命令路由
|
||||
|
||||
| 命令 | 用途 | Risk |
|
||||
|---|---|---|
|
||||
| `+automation-list` | 列出应用所有触发器(可按类型过滤、`--all` 聚合翻页) | read |
|
||||
| `+automation-get` | 查看单个触发器完整配置(Webhook Bearer Token 恒脱敏) | read |
|
||||
| `+automation-create` | 创建触发器,四类共用一条命令,按 `--trigger-type` 分派 | write |
|
||||
| `+automation-update` | 改条件/描述,或经专用 flag 管理 Webhook URL·Token | high-risk-write |
|
||||
| `+automation-enable` | 启用触发器(`status→enabled`,开始自动触发) | write |
|
||||
| `+automation-disable` | 停用触发器(`status→disabled`,停止触发,不删除) | write |
|
||||
|
||||
触发器以 **应用内唯一的 `--name`** 定位(不是 id)。所有单条命令都用 `--app-id` + `--name`;名字忘了先 `+automation-list` 查。
|
||||
|
||||
## 四类触发器 payload
|
||||
|
||||
`--trigger-type` 用面向 Agent 的 kebab-case(`cron` / `record-change` / `webhook` / `feishu-approval`),CLI 内部转 snake_case 下推。类型专属 flag 只在对应类型生效。
|
||||
|
||||
### cron(定时)
|
||||
|
||||
```bash
|
||||
+automation-create --app-id <id> --name daily --trigger-type cron \
|
||||
--cron '0 9 * * *' [--timezone Asia/Shanghai]
|
||||
```
|
||||
|
||||
- `--cron` 是**五段式**(`minute hour day month weekday`),非六段。
|
||||
- **最小间隔 30 分钟**:`--cron '* * * * *'`(每分钟)或 `*/n`(n<30)会被 CLI 本地拦截报错;后端也会二次校验。
|
||||
- `--timezone` 缺省补 `Asia/Shanghai`(IANA 时区名)。
|
||||
|
||||
### record-change(记录变更)
|
||||
|
||||
```bash
|
||||
+automation-create --app-id <id> --name onUpd --trigger-type record-change \
|
||||
--table <table_name> --event UPDATE [--fields '["status"]']
|
||||
```
|
||||
|
||||
- `--event` 是**大写枚举**:`INSERT` / `UPDATE` / `UPSERT` / `DELETE`(CLI 会 uppercase,但请按枚举传)。
|
||||
- `--table` 是应用数据库里的**表名**(对应 `+db-table-list` / `+db-table-get` 输出里 `.name` 字段的值),必填。妙搭应用的 dataloom 表以名称作为稳定标识符,没有独立的 `table_id`。
|
||||
- `--fields` 是 JSON 字符串数组,仅对 `UPDATE`/`UPSERT` 有意义;`'["*"]'` 表示监听所有字段;不传表示不限定字段。
|
||||
|
||||
### webhook(外部回调)
|
||||
|
||||
```bash
|
||||
+automation-create --app-id <id> --name hook --trigger-type webhook \
|
||||
[--white-ip-list '["1.1.1.1","2.2.2.2"]']
|
||||
```
|
||||
|
||||
- 创建时可选 `--white-ip-list`(JSON 字符串数组)限制回调来源 IP。
|
||||
- 回调 URL 分 **preview / runtime 两套**,创建时不回显;用 `+automation-get` 查当前配置,用 `+automation-update --reset-url --app-env <preview|runtime>` 轮换。
|
||||
- Bearer Token 是回调鉴权凭证,见下方「凭证脱敏与一次性回显」。
|
||||
|
||||
### feishu-approval(飞书审批)
|
||||
|
||||
```bash
|
||||
+automation-create --app-id <id> --name apv --trigger-type feishu-approval \
|
||||
--event-type approval_instance --instance-status APPROVED [--approval-code <code>]
|
||||
```
|
||||
|
||||
- `--event-type` 必填,取 `approval_instance` 或 `approval_task`,决定状态用哪套 flag:
|
||||
- `approval_instance` → `--instance-status`(可重复)
|
||||
- `approval_task` → `--task-status`(可重复)
|
||||
- **领域规则**:状态按 `event-type` 分桶校验,两桶枚举**不完全相同**(`PENDING`/`APPROVED`/`REJECTED`/`REVERTED`/`OVERTIME_CLOSE`/`OVERTIME_RECOVER` 两桶共享;`TRANSFERRED`/`ROLLBACK`/`DONE` 仅 task 有;`CANCELED`/`DELETED` 仅 instance 有);传错桶的状态会被 CLI 本地拦截,错误信息会打印该桶的合法值列表。具体枚举见命令 `--help`。
|
||||
|
||||
## approval-code 获取路径
|
||||
|
||||
`--approval-code` **可选**。不传时匹配所有审批定义;要限定某个审批流程时,从**飞书审批管理后台**获取具体的 code 传给它。触发器 OpenAPI 不提供审批定义查询能力,具体 code 需去审批管理后台查。
|
||||
|
||||
## 凭证脱敏与一次性回显(安全关键)
|
||||
|
||||
- `+automation-get` / `+automation-list`:**恒不返回明文 Bearer Token**——`trigger_condition.token_value` 被抹为 `null`。用户想知道「token 是什么」时,list/get 都查不到明文。
|
||||
- `+automation-update --enable-token` / `--reset-token`:明文 Bearer Token **仅当次 stdout 回显一次**,同时 stderr 打印一次性告警:
|
||||
```text
|
||||
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.
|
||||
```
|
||||
- Webhook URL 同理:`--reset-url` 后新 URL 仅当次回显一次,旧 URL 立即失效。
|
||||
- CLI 不落盘任何明文 token/URL(不写 cache / config / recent / debug log / 错误信息)。
|
||||
- **Token 丢失只能 reset**:找不回,唯一恢复方式是 `+automation-update --reset-token`(旧 token 同时失效)。
|
||||
|
||||
## 高危确认
|
||||
|
||||
`+automation-update` 整体是 `high-risk-write`,任何一次调用都需显式 `--yes`;缺少时框架会要求确认(退出码 10)。**不要自动补 `--yes`**——需用户明确确认后再加。以下 Webhook 动作 flag 尤其不可逆:
|
||||
|
||||
- `--reset-url`(旧回调 URL 立即失效,需配 `--app-env preview|runtime`)
|
||||
- `--reset-token`(旧 token 立即失效)
|
||||
- `--disable-token`(关闭 token 校验,**不可逆**)
|
||||
|
||||
四个 Webhook 动作 flag(`--reset-url` / `--enable-token` / `--disable-token` / `--reset-token`)**每次只能传一个**。不确定影响时先跑 `--dry-run` 看将发出的请求(不含明文)。
|
||||
|
||||
### 执行前必须完成的确认步骤(高危写强制协议)
|
||||
|
||||
**在带 `--yes` 执行任何高危写之前,Agent 必须先完成以下 3 件事**,缺一不可——即使用户口气很急、即使命令一眼就明:
|
||||
|
||||
1. **确认目标唯一**:不允许"猜名字"或"批量试所有可能的名字"。若不确定 `--name`,先 `+automation-list --app-id <id>` 让用户在候选中点名;`--name` 不明的绝不执行写操作,更不要 for 循环批量试。
|
||||
2. **确认可选参数已定**:`--reset-url` 必须由用户明确指定 `--app-env preview` 还是 `runtime`;不要默认取 runtime 或 preview。同一触发器的 preview/runtime 是两条独立的 URL,误重置另一条不可回退。
|
||||
3. **告知不可逆后果并等确认**:把即将发生的 3 件事复述给用户——(a)旧 URL/Token 立即永久失效;(b)新 URL/Token 仅当次回显一次、CLI 不保存;(c)本次操作无法撤销——等用户回复"确认"再加 `--yes` 跑。
|
||||
|
||||
只要有一项没做,就先跟用户对齐、不要执行。这些是 skill 层的护栏,不是 CLI 层的(CLI 只强制 `--yes`,不强制上面 3 件事)。
|
||||
|
||||
## ⚠️ 安全告警:无鉴权公网回调组合态
|
||||
|
||||
`--disable-token`(关闭 Bearer Token 校验,不可逆)**叠加** `--white-ip-list '[]'`(清空 IP 白名单)会让 Webhook 触发器进入「**无鉴权公网回调**」组合态——**任何来源都能触发该 Webhook**,没有任何一道防线拦截。
|
||||
|
||||
- 两道防线:Token 校验(谁能调)+ IP 白名单(从哪能调)。**不要同时关闭这两道防线。**
|
||||
- 若确需关闭 Token(例如对端无法带 Bearer 头),务必**保留 IP 白名单**收敛来源;反之若要放开 IP,务必**保留 Token 校验**。
|
||||
- 用户同时要求「关 token 校验 + 清空 IP 白名单」时,Agent 的正确响应是**在识别到该请求的第一时间**(不要等命令跑失败才补警告)向用户输出以下 3 件事,再等确认——不要只描述"没有任何防线"就停下:
|
||||
1. 复述后果:这会形成无鉴权公网回调,任何来源都能触发。
|
||||
2. **主动给出替代方案**:明确建议"要么只关 Token 保留 IP 白名单,要么只放开 IP 保留 Token",让用户在保留一道防线的两条备选里选一条。
|
||||
3. 只有用户明确回复"我理解风险、就是要两道都关"时,才继续按高危写协议(见上节「执行前必须完成的确认步骤」)走。
|
||||
|
||||
## 默认 disabled
|
||||
|
||||
`+automation-create` 创建后触发器**默认 disabled**,不会自动触发。需 `+automation-enable` 才开始按条件自动运行(且触发器执行的是**线上已发布**的应用代码——应用未发布时即便 enable 也不会有实际效果)。
|
||||
|
||||
**Agent 行为约束**:用户只说"创建/配一个触发器"时,**不要**主动在同一个 turn 里 `+automation-enable`。让用户自己在下一轮决定是否启用;主动启用会:
|
||||
- 让 webhook 类型立即可被外部调用(原本用户可能只是想"备好 URL 稍后用")
|
||||
- 让 cron 到点真实触发(原本用户可能想"先建好观察配置")
|
||||
- 让 record-change 立即响应表变更
|
||||
|
||||
创建成功后的推荐话术:`已创建 <name>,当前 disabled;需要真正开始自动运行时告诉我,我用 +automation-enable 启用它。` **不要**在创建成功后立即启用,即使 skill 里说"需 enable 才自动触发"——这条是给用户的说明,不是给 agent 的行动指令。
|
||||
|
||||
## 本地全栈 Trigger 闭环
|
||||
|
||||
当用户希望触发器实际执行业务代码时,先确认当前工作区是已初始化的应用项目,并读取其中与触发器任务匹配的 guide。
|
||||
|
||||
`--name` 是应用内唯一的 trigger 定位键;代码侧绑定名称必须与它逐字相同。不得用 trigger ID 或方法名代替它。具体 handler 语法和接入方式以项目 guide 为准。
|
||||
|
||||
### 仅创建/配置触发器
|
||||
|
||||
适用于 cron、record-change、webhook 和 feishu-approval。用 `+automation-create` 创建,并省略 `--status` 或显式传 `disabled`,然后报告 name 和 disabled 状态。
|
||||
|
||||
不要传 `--status enabled`,也不要写 handler、commit/push、release 或 enable;更不能把创建 API 成功称为“可运行”。默认 disabled 是这个意图的终点,不是稍后自动 enable 的待办。
|
||||
|
||||
### 仅启用已有 disabled trigger
|
||||
|
||||
用户只要求启用已存在且 disabled 的 trigger、没有要求修改代码或制造真实 runtime 事件时,先用 `+automation-get` 核对 name、类型和 disabled 状态,再用 `+release-list --status finished --page-size 1` 核对是否存在已完成线上 release。release history 只能证明当前线上应用有已发布版本,不能证明该 trigger name 已绑定 handler。不存在 finished release 时说明 enable 只会改变配置状态、当前没有可执行的线上版本;存在时说明它会对当前线上应用激活这条 trigger 配置。随后按用户要求执行 `+automation-enable`,再用 `+automation-get` 确认 enabled。
|
||||
|
||||
这条路径不得修改 handler、commit/push 或 release。未发布时不得自动创建 release,也不得声称 trigger 已开始实际运行。即使存在 finished release,也只能把 enable 报告为配置激活;没有 handler 来源或 runtime 结果时,不得声称业务 handler 已存在、已运行或可用。若用户期待尚未发布的本地改动生效,或检查后发现确实需要新增/修改 handler,转到下方“实现或更新 handler 后发布并启动/测试”路径;不要为单纯 enable 发布整个 `sprint/default`。
|
||||
|
||||
对 UPSERT 或 feishu-approval 只改变配置状态;由于本 guide 没有其已证实的 handler、投递或 live 验证契约,启用后也不得声称业务代码已运行或触发器已实测可用。
|
||||
|
||||
### 测试已有线上 trigger(不改代码)
|
||||
|
||||
用户要求测试已经发布的 trigger、没有要求修改 handler 时,先用 `+automation-get` 核对 name、类型、当前状态,再用 `+release-list --status finished --page-size 1` 确认应用存在 finished release,并说明本次测试覆盖当前线上代码。没有 finished release 时停止 runtime test,只报告配置状态;不得为测试自动修改源码、commit/push 或 release。release history 不证明该 name 已绑定 handler,真实 probe 的结果才是本次验证证据;若用户期待本地未发布改动,改走代码变更闭环。
|
||||
|
||||
记录测试前状态,并在任何临时 enable 之前完成两类授权和全部 preflight:测试请求已明确包含临时 enable,或另行取得 enable 授权;同时按下方“运行时验证的操作级授权”确定具体事件、影响、载荷、观察结果和清理。原本 disabled 时完成这些门槛后才临时 enable,并在验证结束后恢复 disabled;原本 enabled 时不要无意义切换状态。原本为 disabled 时,无论 probe 成功、失败、结果不确定,还是临时 enable 后提前结束或中断,最终都必须 `+automation-disable` 并回读 disabled,不得停在 enabled。测试意图本身不决定数据库记录、Webhook 请求或其他事件载荷。
|
||||
|
||||
### 仅完成 handler(不发布/不启用)
|
||||
|
||||
仅对 cron、webhook、record-change 的 `INSERT`、`UPDATE`、`DELETE` 使用此路径。
|
||||
|
||||
创建或定位已明确 name 的 disabled trigger,读取项目 guide,按其要求实现同名业务 handler,完成本地验证。只在既有 Git 确认或预授权下 commit/push;停止在 `+release-create` 和 `+automation-enable` 之前。用户没有明确“发布好”时,先问,不能默认把完整应用上线。
|
||||
|
||||
### 把 handler 发布好,但先不要启动
|
||||
|
||||
仅对 cron、webhook、record-change 的 `INSERT`、`UPDATE`、`DELETE` 使用此路径。先用 `+automation-get` 定位;不存在时用 `+automation-create` 创建同名 disabled trigger,再次回读确认。已存在时记录它是否 enabled。按项目 guide 完成同名业务 handler 并本地验证后,commit、`git push origin sprint/default`。若 trigger 已 enabled,先说明发布前必须临时停用以及可能造成的运行中断,并取得这次临时停用授权;未获授权时停止在发布前。取得授权后,在发布前执行 `+automation-disable`,并再次用 `+automation-get` 确认 disabled。随后发布完整应用:
|
||||
|
||||
```bash
|
||||
lark-cli apps +release-create --as user --app-id <app_id> --branch sprint/default
|
||||
```
|
||||
|
||||
若 `+release-create` 本身返回错误或未返回 `data.release_id`:视为确认未创建本轮 release(新代码未上线),原本 enabled 的 trigger 恢复 enabled 并回读、原本 disabled 的保持 disabled,然后停止;若因超时等导致创建结果未知,保持 disabled,先用 `+release-list --status finished --page-size 1` 核对是否已产生新 release 再决定。取得 `data.release_id` 后,对**这一轮** ID 调用 `+release-get`:`publishing` 时每 20 秒继续轮询,整体最多约 5 分钟;超时且状态仍不确定时报告 `release_id` 和当前 status,并保持 disabled;只有 `data.status=finished` 才算完成。确认 `failed` 且新代码未上线时,原本 enabled 的 trigger 恢复 enabled 并回读,原本 disabled 的保持 disabled。release 是整个应用上线,可能影响既有线上功能;未获得启动或测试授权时,finished 后始终保持 disabled,不执行 `+automation-enable`。
|
||||
|
||||
### 实现或更新 handler 后发布并启动/测试
|
||||
|
||||
仅当本轮确实需要新增或修改 cron、webhook、record-change 的 `INSERT`、`UPDATE`、`DELETE` handler,且用户要求把这次代码发布后启动或测试时,才使用此路径。按以下不可跳过的顺序执行:
|
||||
|
||||
1. 用 `+automation-get` 定位并记录发布前状态,再核对其 `--name`、类型并读取项目 guide;不存在时用 `+automation-create` 创建同名 trigger 并保持默认 disabled。
|
||||
2. 按项目 guide 完成同名业务 handler 并本地验证。
|
||||
3. 在 Git 已确认/预授权时 commit,然后执行 `git push origin sprint/default`。
|
||||
4. 若 trigger 当前 enabled,先说明发布前必须临时停用以及可能造成的运行中断,并取得这次临时停用授权;未获授权时停止在发布前。取得授权后执行 `+automation-disable`,并再次用 `+automation-get` 确认 disabled;原本 disabled 时不要无意义切换状态。
|
||||
5. 执行 `+release-create --branch sprint/default`。若该命令本身返回错误或未返回 `data.release_id`:视为确认未创建本轮 release(新代码未上线),原本 enabled 的 trigger 恢复 enabled 并回读、原本 disabled 的保持 disabled 后停止;若因超时等导致结果未知,保持 disabled,先用 `+release-list --status finished --page-size 1` 核对是否已产生新 release 再决定。取得 `data.release_id` 后进入下一步。
|
||||
6. 对该 ID 执行 `+release-get`,只有 `data.status=finished` 才能继续;`publishing` 时每 20 秒继续轮询,整体最多约 5 分钟。超时且状态仍不确定时停止本轮轮询、报告 `release_id` 和当前 status,并保持 disabled;确认 `failed` 时报告发布失败,原本 enabled 的 trigger 仅在确认新代码未上线后恢复 enabled,原本 disabled 的保持 disabled。发布状态仍不确定时不得进入 enable、probe 或状态恢复分支。`is_published=true` 不能代替这轮发布完成。
|
||||
7. **仅启动**:取得持续启动授权后执行 `+automation-enable`,并用 `+automation-get` 确认 enabled;到此结束,不制造 runtime probe。
|
||||
8. **测试(含“启动并测试”)**:先按下节“运行时验证的操作级授权”完成全部 preflight,包括具体事件、sibling 影响、载荷、观察结果和清理;完成前保持 disabled,之后才执行 `+automation-enable` 并回读,再由已授权主体制造真实 runtime 条件并核验业务结果。若同时明确要求持续启动,只有 probe 成功后才保持 enabled。
|
||||
9. 若用户仅要求测试而不是持续启动,只在本轮 release 已 `finished` 且 probe 成功后恢复到发布前状态:原本 disabled 或本轮新建的 trigger `+automation-disable` 并回读;原本 enabled 的可保持 enabled。无论用户是仅测试还是启动并测试,probe 失败、结果不确定或 enable 后提前结束时,一律 `+automation-disable` 并回读 disabled;不得把“发布前 enabled”当作失败后的恢复依据,因为本轮新代码已经上线。只有旧 release 已回滚并验证,或修复后重新发布且 probe 成功,才可再次 enabled。恢复失败时明确报告当前状态。
|
||||
|
||||
没有通用的 `automation-debug` 或 trigger 日志 shortcut。缺少安全事件入口、匹配环境或可观察结果时,记录 blocked,不能编造测试成功。
|
||||
|
||||
### 运行时验证的操作级授权
|
||||
|
||||
启用 trigger 的授权不等于制造 runtime 事件的授权,测试授权也不等于任意数据库写入授权。cron 可等待计划时间;webhook 只能向既有 runtime URL 发送已授权、安全且不泄露凭证的请求。record-change 在执行任何 DML 前,必须明确并取得覆盖以下作用域的授权:环境、表、操作、精确测试记录或筛选条件、payload、预期结果和清理方式。
|
||||
|
||||
优先使用专用测试记录,不要任取线上业务记录。用户已明确授权精确、可撤回的测试夹具及其清理时,不机械追加一轮确认;目标或影响仍不清楚时必须停下。record-change probe 前先执行 `+automation-list --trigger-type record-change --all`,检查同一环境、表和操作可能命中的其他 enabled trigger;若存在 sibling match,必须说明聚合业务影响并取得覆盖这些影响的授权,或换成隔离夹具/经授权临时停用后再测。`UPDATE` 要限定精确条件并保留恢复方式;`INSERT` 要预先约定清理;恢复 UPDATE 或清理 INSERT 也可能再次触发自动化,必须纳入影响说明和授权。`DELETE` 必须遵循 [lark-apps-db-execute.md](lark-apps-db-execute.md):先 `SELECT count(*)`、执行 `--dry-run`,展示影响后取得针对该删除目标的明确授权,再带 `--yes` 执行;清理动作若包含未预先授权的删除,同样走该门槛。
|
||||
|
||||
缺少安全、已授权且可清理的事件入口时,记录 blocked,不得用“测试一下”推导任意 online 数据写入。
|
||||
|
||||
### UPSERT 与飞书审批边界
|
||||
|
||||
record-change 的 UPSERT 可创建 disabled 配置,但当前没有已证实的运行时代码契约;不得静默按 UPDATE 处理,也不得承诺 handler 或 live 验证。
|
||||
|
||||
feishu-approval 可创建 disabled 配置,并读取或更新 `event_type`、对应 status 和可选 `approval_code`。当前没有已证实的运行时 handler 契约或实际投递验证;不要把 enable 或审批 API 成功称为业务代码已执行。
|
||||
|
||||
### 未触发时的诊断顺序
|
||||
|
||||
按 `--name` / 项目 guide 要求的代码接入 → 本轮 release `finished` → enabled 状态 → 类型条件、环境和已有日志的顺序排查。客户审批投递故障属于服务端事件投递排查,不要归因于此 SOP 或改写无关业务代码。
|
||||
|
||||
## 常见错误与决策场景
|
||||
|
||||
| 现象 / 用户意图 | 正确处理 |
|
||||
|---|---|
|
||||
| 创建报名字冲突(`--name` 应用内唯一) | 换名或加后缀重试 |
|
||||
| cron 报非法 / 间隔过小 | 检查是否五段式、分钟字段是否 `*` 或 `*/n`(n<30) |
|
||||
| `--reset-url` 报缺 app-env | 补 `--app-env preview` 或 `--app-env runtime` |
|
||||
| 想把 cron 触发器改成 webhook(跨类型改) | update 不支持换类型,本 skill 也不提供删除。旧触发器只能 `+automation-disable` 停用(保留在应用里),另建一个 webhook 触发器;若要真正清理旧触发器,请到妙搭 web 手动删除 |
|
||||
| 触发器 enable 了但不触发 | 已证实的 cron、webhook、record-change(INSERT/UPDATE/DELETE)按「未触发时的诊断顺序」排查;UPSERT 和 feishu-approval 仅核对配置边界,不承诺 handler 或 live 验证。 |
|
||||
| 「token 泄露了」 | 优先 `+automation-update --reset-token --yes` 轮换(旧 token 立即失效),而非直接 disable-token 关校验 |
|
||||
| 「回调 URL 泄露了」 | `+automation-update --reset-url --app-env <env> --yes` 轮换 |
|
||||
|
||||
## 不在本 skill 范围
|
||||
|
||||
- 审批定义查询、Webhook 消费端实现、实时触发日志 tail:本期不支持。
|
||||
- 身份选择、权限不足处理、exit-10 审批、通用「禁输出密钥」红线、高风险操作通用框架:见 [`../../lark-shared/SKILL.md`](../../lark-shared/SKILL.md),不在此重复。
|
||||
119
.agents/skills/lark-apps/references/lark-apps-cloud-dev.md
Normal file
119
.agents/skills/lark-apps/references/lark-apps-cloud-dev.md
Normal file
@ -0,0 +1,119 @@
|
||||
# lark-apps 云端会话开发
|
||||
|
||||
适用:用户希望让云端妙搭 Agent 生成或迭代应用,而不是把代码拉到本地开发。
|
||||
|
||||
## 核心流程
|
||||
|
||||
整个开发在云端进行:本地只负责「发消息 + 轮询状态」,不拉源码、不产出代码、不启动本地 dev server。所有 session/chat 命令都以用户身份执行(`--as user`)。
|
||||
|
||||
### 资源模型:app → session → turn
|
||||
|
||||
三层父子关系,下层都挂在上层之下:
|
||||
|
||||
- **app(应用资产)**:一个妙搭应用,由 `+create` 创建并拿到 `app_id`。云端生成应用类型用 `full_stack`。
|
||||
- **session(会话)**:一个 app 下的一段独立对话上下文,由 `+session-create` 创建并拿到 `session_id`。一个 app 可有多个 session;`is_active` 表示该 session 当前是否可写(可发起对话)。
|
||||
- **turn(轮)**:一个 session 里的一轮交互 = 一条用户消息 + 妙搭 Agent 针对它的生成/迭代。`+chat` 发一条消息就发起一轮;轮的句柄是 `turn_id`,状态看 `latest_turn.status`。
|
||||
|
||||
### 执行模型:异步 + 轮询
|
||||
|
||||
`+chat` 把消息入队后**立即返回、不等生成完成,响应不带 `turn_id`**;本轮状态与轮询节奏全靠 `+session-get` 读 `latest_turn.status` / `is_streaming` / `next_poll_after_ms`。
|
||||
|
||||
`+session-get` 关键字段:
|
||||
|
||||
- `is_streaming`:当前是否有一轮正在跑(`true`=还在生成)。
|
||||
- `latest_turn.status`:最近一轮的状态,只有 `running` / `completed` / `failed` / `cancelled`。
|
||||
- `latest_turn.turn_id`:最近一轮的句柄(`+session-stop --turn-id` 用它)。
|
||||
- `latest_turn.user_message`:本轮用户发的消息。
|
||||
- `latest_turn.messages`:本轮完成后回看全貌的消息列表,按时序排列、每条带 `role`(用户消息、模型回复、工具调用等都在内,role 取值如 `user` / `assistant` / `tool`)。注意它在 `latest_turn` 仍 running/初始化期可能为空——该轮**进行中**的实时进展改用 `+session-messages-list --turn-id <latest_turn.turn_id>` 读(见下方轮询规则)。
|
||||
- `queued_messages` / `queued_count`:还没开始跑、排在后面的消息。
|
||||
- `next_poll_after_ms`:建议的下次轮询间隔(毫秒,固定值);非空时优先用它。
|
||||
|
||||
轮询规则:
|
||||
|
||||
- 节奏按 [初始化 vs 增量修改](#初始化-vs-增量修改) 判定:增量 5-10 秒一次;初始化 60-120 秒一次;`next_poll_after_ms` 非空时用它。
|
||||
- `is_streaming=true`、`building` / `running` / `streaming` 表示仍在生成,继续轮询,不傻等也不提前放弃;初始化阶段单次 sleep 拉到 60-120 秒,进入 `streaming` 或属增量修改时切回 5-10 秒。
|
||||
- `is_streaming=false` 且 `latest_turn.status=completed` 表示本轮完成,可发下一条。
|
||||
- `failed` / `cancelled` 时转述错误字段或 hint,由用户决定是否重试,不要静默重发。
|
||||
- 不知道某 app 有哪些 session 时,先 `+session-list --app-id <id>`,再选最近活跃的或让用户确认,别直接猜 `session_id`。
|
||||
- 要中止正在运行的一轮,从 `+session-get` 的 `latest_turn.turn_id` 取值,再调用 `+session-stop --turn-id <turn_id>`。
|
||||
- 状态与节奏看 `+session-get`,本轮实时内容看 `+session-messages-list`:想在 running 期间向用户播报"云端 Agent 此刻在做什么",用 `+session-messages-list --turn-id <latest_turn.turn_id>` 读已产出的增量消息(running 期间即可读,不必等本轮结束)。复用上面的轮询节奏、不另起更密的轮询;续拉时把上次响应的 `next_page_token` 作 `--page-token` 只取新消息,转述时简述进展、不原样打印整段消息或工具输出。
|
||||
|
||||
### 典型链路
|
||||
|
||||
```bash
|
||||
# 1) 建 app,拿 app_id(云端生成走 full_stack)
|
||||
lark-cli apps +create --name "待办应用" --app-type full_stack \
|
||||
--description "支持新增、完成、筛选待办"
|
||||
|
||||
# 2) 在该 app 下建 session,拿 session_id
|
||||
lark-cli apps +session-create --app-id app_xxx
|
||||
|
||||
# 3) 发消息发起一轮(异步入队,立即返回,无 turn_id)
|
||||
lark-cli apps +chat --app-id app_xxx --session-id sess_xxx --message "做一个待办清单页面"
|
||||
|
||||
# 4) 轮询本轮状态;完成后从 latest_turn.messages 读取结果
|
||||
lark-cli apps +session-get --app-id app_xxx --session-id sess_xxx
|
||||
|
||||
# 找该 app 已有的会话(续聊/不确定 session 时用)
|
||||
lark-cli apps +session-list --app-id app_xxx
|
||||
```
|
||||
|
||||
## 完成态不等于发布态
|
||||
|
||||
通用发布态判定(is_published 语义、开发态链接拼接、发布态链接来源)见 SKILL.md「发布态护栏」。本 reference 只补云端会话特有的措辞:
|
||||
|
||||
- `+session-get` 返回 `is_streaming=false` 且 `latest_turn.status=completed`,只说明本轮云端生成/迭代结束,不等于已发布部署。
|
||||
- 如果只完成了云端会话、没有确认发布完成,就明确告诉用户“开发态链接可进入继续编辑,发布态是否为最新版本尚未确认”。
|
||||
|
||||
## 需求发送
|
||||
|
||||
- 只有用户明确选择云端路径,或明确说“让妙搭 Agent / 云端 AI 生成/迭代”时,才进入本 reference;不要因为用户只说“做个 X”或“给我链接”就默认云端。
|
||||
- 进入云端路径后,极简需求也可直接发起生成,例如“做个投票工具”“做个站会小应用”。先建 `full_stack` app,再用 `+chat --message "<用户原话>"` 透传需求,不编造实体、字段或业务细节。
|
||||
- 如果需求过泛,可在 `+chat --message` 中保留原话,并只补一句“请先生成通用版本,后续可继续迭代”,不要用多轮追问阻塞生成。
|
||||
|
||||
## 会话落点
|
||||
|
||||
| 情形 | 动作 |
|
||||
|---|---|
|
||||
| 全新应用 + 云端生成 | 先 `+create --app-type full_stack` 拿 `app_id`,再 `+session-create` -> `+chat` |
|
||||
| 已知 app_id,用户没指定会话 | 先 `+session-list`;有活跃会话时问用户继续现有还是新开 |
|
||||
| 用户说“新开一段/换个话题” | `+session-create` 后再 `+chat` |
|
||||
| 用户说“接着刚才” | 复用上下文 session_id;拿不到就 `+session-list` 让用户选 |
|
||||
| 用户问会话“进行到哪一步/当前状态/最新进展” | 用 `+session-get --session-id <sid>` 读状态。`+session-list` 只负责发现/选择会话,不含执行状态;它返回空不等于无状态可查(session_id 也可能来自上下文),别用 `+session-list`/`+release-list` 代替 `+session-get` 回答进度 |
|
||||
|
||||
## 初始化 vs 增量修改
|
||||
|
||||
`+chat` 单轮的耗时差距很大,取决于目标 app 是否**已初始化**。两者的轮询节奏不同,**`+chat` 前先把状态判定清楚**,不要拿"是不是第一次发消息"当代理判断——session 是新建的不代表 app 没初始化过。
|
||||
|
||||
### 判定规则
|
||||
|
||||
**已初始化**(满足任一即认为已初始化):
|
||||
|
||||
1. 本地存在该 app 的项目目录(已 `+init` 或 clone 过),**且** git commit 数 > 2;
|
||||
2. 应用维度(云端)至少有一个已提交的版本,按以下任一信号判断:
|
||||
- `lark-cli apps +session-get --app-id <app_id> --session-id <session_id>` 的返回里出现已提交版本信息;
|
||||
- 在 `lark-cli apps +list`(必要时配 `--keyword <name>` 定位)的目标 app 条目里 `is_published: true`。
|
||||
|
||||
**未初始化**(两个条件同时成立):
|
||||
|
||||
1. 本地不存在该 app 的项目目录;
|
||||
2. 应用维度没有任何已提交版本(即上面两路云端信号都判 false)。
|
||||
|
||||
### 两种 `+chat` 的行为
|
||||
|
||||
| 状态 | 服务端动作 | 单轮耗时 | 轮询建议 |
|
||||
|---|---|---|---|
|
||||
| 已初始化 → **增量修改** | 云端 Agent 在已有云端工作区上对**已提交代码**做局部修改,跳过方案设计与首次生成 | 通常分钟级 | `next_poll_after_ms` 为空时 5-10 秒一次 |
|
||||
| 未初始化 → **首次初始化 + 生成** | 服务端跑完整的应用初始化流程:需求分析、技术方案、数据模型、UI 与后端代码生成、首版代码提交到云端工作区 | 视需求复杂度,**通常 20~50 分钟** | `next_poll_after_ms` 为空时 60-120 秒一次 |
|
||||
|
||||
初始化阶段 `+session-get` 可能长时间持续返回 `building` / `running`,是正常状态,**不要按失败处理,也不要催用户**。
|
||||
|
||||
## 字段注意
|
||||
|
||||
所有字段统一 snake_case,顶层和嵌套 turn 字段都一样:`session_id`、`is_active`、`is_streaming`、`next_poll_after_ms`、`latest_turn.turn_id`、`latest_turn.status`、`latest_turn.user_message`、`latest_turn.messages`。
|
||||
|
||||
`+session-stop` 只停止正在运行的当前轮,不关闭会话;停完仍可继续 `+chat`。
|
||||
|
||||
## 不适用
|
||||
|
||||
- 用户要本地写代码、改仓库、跑 dev server:读 [`lark-apps-local-dev.md`](lark-apps-local-dev.md)。
|
||||
39
.agents/skills/lark-apps/references/lark-apps-create.md
Normal file
39
.agents/skills/lark-apps/references/lark-apps-create.md
Normal file
@ -0,0 +1,39 @@
|
||||
# apps +create
|
||||
|
||||
创建妙搭应用。运行时命令事实以 `lark-cli apps +create --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
用来创建应用资产并拿到 `app_id`。它不负责把自然语言需求交给云端 Agent:用户要“帮我生成/迭代应用”时,先创建 `full_stack` app,再进入 [`lark-apps-cloud-dev.md`](lark-apps-cloud-dev.md) 用 `+session-create` / `+chat` 提交需求。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- 必填:`--name`、`--app-type`。
|
||||
- app type 语义取值为 `html` / `full_stack`;CLI 会把输入归一成小写后校验。
|
||||
- 可选:`--description`、`--icon-url`。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +create --name "客户调研问卷" --app-type html
|
||||
|
||||
lark-cli apps +create --name "审批系统" --app-type full_stack \
|
||||
--description "部门审批系统,支持登录、提交申请、多级审批"
|
||||
|
||||
lark-cli apps +create --name "Demo" --app-type html --dry-run
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 成功默认 JSON envelope 中读取 `data.app.app_id`,同时可用 `data.app.name` / `description` 向用户确认结果。
|
||||
- pretty 输出只适合人看;后续命令需要 app_id 时,用 JSON 或 `--jq '.data.app.app_id'`。
|
||||
|
||||
## app type 与命名
|
||||
|
||||
- `--app-type` 取值与判定信号见 SKILL.md「选择开发路径」,此处不重复。
|
||||
- 用户只给自然语言需求时,据此生成简洁的 `--name` 和一句 `--description` 直接创建;不满意再用 `+update` 改。
|
||||
|
||||
创建后按用户路径继续:
|
||||
|
||||
- 本地应用开发(含 html 和 full_stack):读 [`lark-apps-local-dev.md`](lark-apps-local-dev.md)。
|
||||
- 云端 Agent 生成/迭代:读 [`lark-apps-cloud-dev.md`](lark-apps-cloud-dev.md)。
|
||||
228
.agents/skills/lark-apps/references/lark-apps-db-execute.md
Normal file
228
.agents/skills/lark-apps/references/lark-apps-db-execute.md
Normal file
@ -0,0 +1,228 @@
|
||||
# apps +db-execute
|
||||
|
||||
经妙搭服务端在应用数据库执行 SQL。运行时命令事实以 `lark-cli apps +db-execute --help` 为准。
|
||||
|
||||
> **写 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。
|
||||
|
||||
## 何时用
|
||||
|
||||
用于通过妙搭服务端执行应用数据库 SQL。不要从环境变量里取连接串裸连数据库;本地调试也走这个 shortcut。写什么样的 SQL(平台约束、建表模板、`user_profile`、审计列、禁用 SQL、PG 陷阱)见文末「平台 SQL 规范」。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- 必填:`--app-id`,以及 `--sql` / `--file` 二选一(互斥)。
|
||||
- `--sql`:内联 SQL 文本;传 `-` 时从 stdin 读。绝对路径文件经 stdin 传入:`--sql - < <absolute-path>`(shell 解析路径,CLI 仅接收内容)。
|
||||
- `--file`:`.sql` 文件路径,需为工作目录内的相对路径(如 `--file ./migration.sql`);绝对路径、或经 `..`/符号链接越出工作目录的路径会被拒绝。文件不在工作目录内时,改用 `--sql - < <文件路径>` 经 stdin 传入。
|
||||
- `--environment` 枚举:`dev` / `online`,**不传则由服务端按应用是否开启多环境自动选择(多环境→`dev`,未开启多环境→`online`)**;要固定环境就显式传 `--environment dev|online`。**未开启多环境的应用显式传 `--environment dev` 会报错(无 dev 分支)——这类应用不传 `--environment`(走 `online`)或显式 `--environment online`**。旧名 `--env` 已**移除**:传入会报 validation 错(提示改用 `--environment`),一律用 `--environment`。
|
||||
- risk 是 `high-risk-write`(SQL 可含 DML/DDL):任何执行都需 `--yes`,否则返回 `confirmation_required` / exit 10。`--dry-run` 预览不需要 `--yes`。
|
||||
- **不会自动为你包事务,事务边界需自己在 SQL 里控制**:多语句默认逐条独立提交,中间某条失败时前序语句已生效、不会回滚;若需要「要么全部成功、要么全部回滚」的原子性,请在 SQL 内显式写 `BEGIN … COMMIT`(详见下「Agent 规则」)。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-execute --app-id app_xxx --environment dev --sql "select * from orders limit 5" --yes
|
||||
lark-cli apps +db-execute --app-id app_xxx --environment dev --file ./migration.sql --dry-run
|
||||
# 绝对路径文件 / cwd 不固定:经 stdin 传入
|
||||
lark-cli apps +db-execute --app-id app_xxx --environment dev --sql - --yes < /Users/.../migrations/0001_init.sql
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 成功默认 JSON 的 `data` 按 SQL 类型自适应(不透传后端原始串):
|
||||
- 单 SELECT → `data` 是行数组 `[{...}]`(空 → `[]`),直接 `-q '.data[].col'` 取字段。
|
||||
- 单 DML → `data = {command, rows_affected}`(如 `{"command":"INSERT","rows_affected":1}`)。
|
||||
- 单 DDL → `data = {command}`(如 `{"command":"CREATE_TABLE"}`)。
|
||||
- 多语句 → `data` 是元素数组:SELECT 为 `{command:"SELECT", rows:[...]}`,DML 为 `{command, rows_affected}`,DDL 为 `{command}`。
|
||||
- pretty 会按 SELECT/DML/DDL 自适应渲染;多语句会逐条显示 Statement 摘要。
|
||||
- 失败返回 typed `error`(`type:"api"`、`subtype:"server_error"`、`code`、`message`、`hint`):失败位置在 `message` 的「(at statement N of M)」;前序是否落地 / 是否整批回滚写在 `hint`——事务内失败「Transaction rolled back; no changes persisted.」;非事务多语句前序已落地「Earlier statements were committed and not rolled back; fix statement N and re-run the remaining statements.」;首句即失败(无前序落地)「No statements were applied; fix the SQL and re-run.」。据此决定整段重跑还是只跑剩余语句。
|
||||
|
||||
## Agent 规则
|
||||
|
||||
- 该命令为 high-risk-write,执行一律需 `--yes`;无 `--yes` 会返回 `confirmation_required` / exit 10。
|
||||
- **只读查询、以及不删除/不丢失既有数据且可撤回的语句**:已授权时可直接带 `--yes` 执行。
|
||||
- **会删除或丢失既有数据、或难以撤回的语句**:先 `--dry-run` 预览(无需 `--yes`),向用户确认后再带 `--yes` 执行;不要在用户不知情时自动补 `--yes`。
|
||||
- 多语句失败时,失败前的语句可能已经 commit 落地。不要整批重跑;按错误 message/hint 修失败语句,并从剩余语句继续。
|
||||
- 如果需要原子性,让用户在 SQL 内显式写 `BEGIN` / `COMMIT`,不要假设 CLI 会包事务。
|
||||
- 不要把数据库连接串从 env 中取出来裸连。
|
||||
|
||||
---
|
||||
|
||||
# 平台 SQL 规范
|
||||
|
||||
上面讲命令怎么调,这里讲**该写出什么样的 SQL**:妙搭底层是 PostgreSQL + 一层平台约束(RLS、审计列、`user_profile` 复合类型、禁用 SQL 白名单),不符合会被服务端直接拒或建出行为不对的表。看表 / 看结构用 [`+db-table-list`/`+db-table-get`](lark-apps-db.md),别手写系统表查询模拟。
|
||||
|
||||
## 平台禁用 SQL(硬拒绝)
|
||||
|
||||
以下命中会被服务端拒,`error`(`type:"api"`)的 message/hint 会说明原因——先按 hint 修再重试,不要反复重试同一句。
|
||||
|
||||
| 类别 | 禁止 |
|
||||
|---|---|
|
||||
| 数据库级 | `CREATE / DROP / ALTER DATABASE` |
|
||||
| Schema 级 | `CREATE / DROP SCHEMA` |
|
||||
| 用户 / 角色级 | `CREATE / DROP USER`、`CREATE / DROP / ALTER ROLE` |
|
||||
| Owner 切换 | `REASSIGN OWNED` / `DROP OWNED` |
|
||||
|
||||
## 建表规范(CREATE TABLE)
|
||||
|
||||
新建业务表必须:4 个审计列 + 启用 RLS + 4 条默认 policy,**放在同一次 `+db-execute` 调用里**(RLS / policy / COMMENT / INDEX 一起)。裸表名,不写 `public.` 或 schema 前缀。
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS <table> (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
-- ... 业务列 ...
|
||||
name varchar(100) NOT NULL,
|
||||
_created_at TIMESTAMP(3) WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
_created_by user_profile DEFAULT (
|
||||
CASE
|
||||
WHEN current_setting('app.user_id', TRUE) = '' THEN NULL
|
||||
ELSE concat('(', current_setting('app.user_id', TRUE), ')')::user_profile
|
||||
END
|
||||
),
|
||||
_updated_at TIMESTAMP(3) WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
_updated_by user_profile DEFAULT (
|
||||
CASE
|
||||
WHEN current_setting('app.user_id', TRUE) = '' THEN NULL
|
||||
ELSE concat('(', current_setting('app.user_id', TRUE), ')')::user_profile
|
||||
END
|
||||
)
|
||||
);
|
||||
|
||||
ALTER TABLE <table> ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
CREATE POLICY service_role_bypass_policy ON <table>
|
||||
TO service_role USING (true);
|
||||
|
||||
CREATE POLICY "修改全部数据" ON <table>
|
||||
AS PERMISSIVE FOR ALL TO authenticated USING (true);
|
||||
|
||||
CREATE POLICY "查看全部数据" ON <table>
|
||||
AS PERMISSIVE FOR SELECT TO authenticated, anon USING (true);
|
||||
|
||||
CREATE POLICY "修改本人数据" ON <table>
|
||||
AS PERMISSIVE FOR ALL TO authenticated USING (
|
||||
(current_setting('app.user_id'::text) = ANY (ARRAY[]::text[]))
|
||||
AND (current_setting('app.user_id'::text) = ((_created_by).user_id)::text)
|
||||
);
|
||||
```
|
||||
|
||||
建表流程:先 `+db-table-list` / `+db-table-get` 确认表不存在或看现有结构 → 生成 DDL → 向用户展示影响并取得授权 → `+db-execute ... --yes` 执行。
|
||||
|
||||
## 审计列
|
||||
|
||||
- 平台自动维护的四列固定叫 `_created_at` / `_updated_at` / `_created_by` / `_updated_by`(**下划线开头**)。查询 / 排序 / 过滤一律用这些名字,别写 `created_at`。
|
||||
- `_created_at` / `_updated_at` 在 INSERT 时可省略(有默认值);需要业务归属时显式写 `_created_by` / `_updated_by`。
|
||||
- UPDATE 业务字段时建议同步 `_updated_at = CURRENT_TIMESTAMP` 和 `_updated_by`。
|
||||
|
||||
## `user_profile` 复合类型
|
||||
|
||||
平台内置类型 `(user_id varchar, name varchar, email varchar, avatar text, status integer)`,无需创建。**业务 SQL 只允许访问 `(field).user_id`**,不要依赖 `name` / `email` / `avatar` / `status`(可能为空或过期)。
|
||||
|
||||
```sql
|
||||
-- 写入 / 更新:用 ROW()::user_profile,更新时替换整个字段,不改单个属性
|
||||
INSERT INTO teacher (teacher_profile, class_id)
|
||||
VALUES (ROW('<user_id>')::user_profile, gen_random_uuid());
|
||||
|
||||
UPDATE teacher SET teacher_profile = ROW('<user_id>')::user_profile
|
||||
WHERE (teacher_profile).user_id = '<old_user_id>';
|
||||
|
||||
-- 查询 / 过滤:解引用取 user_id;raw SQL 返回给前端前必须解引用,别直接返回复合类型
|
||||
SELECT (teacher_profile).user_id AS teacher_profile, class_id FROM teacher;
|
||||
|
||||
-- 索引 / 唯一性:表达式列用三重括号;表达式唯一性用 CREATE UNIQUE INDEX,
|
||||
-- 不能用 ALTER TABLE ADD CONSTRAINT UNIQUE(不支持表达式列)
|
||||
CREATE INDEX idx_teacher_user_id ON teacher (((teacher_profile).user_id));
|
||||
CREATE UNIQUE INDEX uk_teacher_user_id ON teacher (((teacher_profile).user_id));
|
||||
```
|
||||
|
||||
## DDL 规则
|
||||
|
||||
| 场景 | 做法 |
|
||||
|---|---|
|
||||
| 加列 | `ALTER TABLE <t> ADD COLUMN IF NOT EXISTS <col> <type>`,相关 `COMMENT ON` 同次执行 |
|
||||
| 加索引 | `CREATE INDEX IF NOT EXISTS idx_<t>_<cols> ON <t>(...)` |
|
||||
| JSONB 类型声明 | 必须 `COMMENT ON COLUMN <t>.<col> IS '@type { ... }'` 声明 TypeScript 类型,和 CREATE / ALTER 同次调用 |
|
||||
| 加 NOT NULL 列 | 必须带 `DEFAULT` 让存量行自动填:`ADD COLUMN <col> <type> NOT NULL DEFAULT <值>` |
|
||||
| 删表 / 删列 | 有业务数据默认禁止;必须用户明确授权后才执行,并说明数据丢失风险 |
|
||||
| 强约束 | `UNIQUE` / `FOREIGN KEY` / `NOT NULL` 默认谨慎,不确定不加 |
|
||||
|
||||
**多环境库加约束前先查 online 存量**:`dev` 干净不代表 `online` 干净,约束发布到 online 会撞线上存量数据而失败。发布前一律先用 `--environment online` 查清楚,按约束类型分三种:
|
||||
|
||||
- **加唯一约束(`UNIQUE` / 唯一索引)**:线上不能有重复值。先查重复,有则先清理再加:
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-execute --app-id app_xxx --environment online --sql \
|
||||
"SELECT <cols>, count(*) FROM t GROUP BY <cols> HAVING count(*) > 1" --yes
|
||||
```
|
||||
|
||||
- **已有列改 `NOT NULL`(收紧约束)**:线上该列不能有 NULL。先查 NULL 行数,有就先回填(`UPDATE t SET <col> = <默认值> WHERE <col> IS NULL`)再加约束:
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-execute --app-id app_xxx --environment online --sql \
|
||||
"SELECT count(*) FROM t WHERE <col> IS NULL" --yes
|
||||
```
|
||||
|
||||
- **新加 `NOT NULL` 字段**:必须带 `DEFAULT`,且要求线上该表**无存量数据**,否则发布报错。线上已有数据时别直接加,改走三步安全变更:先 `ADD COLUMN <col> <type>`(可空)→ 回填 `UPDATE t SET <col> = <值>` → 再 `ALTER COLUMN <col> SET NOT NULL`。先查线上行数判断走哪条:
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-execute --app-id app_xxx --environment online --sql \
|
||||
"SELECT count(*) FROM t" --yes
|
||||
```
|
||||
|
||||
## SELECT 规则
|
||||
|
||||
| 规则 | 要求 |
|
||||
|---|------------------------------------------------------------------|
|
||||
| 行数 | 结果集有硬上限(平台限制 1000 行),超限**报错而非静默截断**;大表必须显式 `LIMIT`、聚合或游标分页 |
|
||||
| 分页 | 大表优先游标分页 `WHERE id > <last_id> ORDER BY id LIMIT n`,避免大 `OFFSET` |
|
||||
| user_profile | 返回给前端前解引用:`(owner).user_id AS owner` |
|
||||
| 统计 | 总数用 `count(*)`、分组用 `GROUP BY`,别把全量拉到 agent 侧再统计 |
|
||||
| 慢查询 | 用 `EXPLAIN (ANALYZE, BUFFERS)`;大表 Seq Scan 考虑加索引 |
|
||||
|
||||
## DML 规则
|
||||
|
||||
**INSERT**
|
||||
- UUID 主键省略,交给 `DEFAULT gen_random_uuid()`;外键 UUID 用子查询取父表 id,不手写。
|
||||
- NOT NULL 且无默认值的列必须给值;批量 INSERT 每行列数一致。
|
||||
- 需要幂等用 `ON CONFLICT ... DO NOTHING / DO UPDATE`。
|
||||
- 标量子查询必须保证单行,非唯一条件加 `ORDER BY ... LIMIT 1`。
|
||||
|
||||
**UPDATE**
|
||||
- **必须有明确 `WHERE`,禁止无条件 UPDATE**。
|
||||
- 用户说「修改 / 更新 / 改一下」数据时用 UPDATE,**禁止 DELETE + INSERT** 模式。
|
||||
- 更新 `user_profile` / 复合类型时替换整个字段。
|
||||
- 批量更新前影响范围不明确,先 `SELECT count(*)` 给用户确认。
|
||||
|
||||
**DELETE / TRUNCATE**(属会丢数据的高影响操作,按上面「Agent 规则」的确认流程走)
|
||||
- 已有表 / 已有数据默认禁止;先 `SELECT count(*)` 展示命中行数、取得用户明确授权,再带 `--yes` 执行。
|
||||
- `TRUNCATE` 影响整表,视同高风险删除。
|
||||
|
||||
```sql
|
||||
UPDATE task
|
||||
SET status = 'done', _updated_at = CURRENT_TIMESTAMP, _updated_by = ROW('<user_id>')::user_profile
|
||||
WHERE id = (SELECT id FROM task WHERE title = '梳理需求' ORDER BY _created_at DESC LIMIT 1);
|
||||
```
|
||||
|
||||
## 常见 PostgreSQL 陷阱
|
||||
|
||||
| 陷阱 | 正确做法 |
|
||||
|---|---|
|
||||
| 表名带 schema 前缀 | 业务表一律裸表名 `FROM orders`,别写 `public.orders` |
|
||||
| 保留字作标识符 | 避免 `user` / `order` / `desc` / `offset` / `references` 等 |
|
||||
| 内联 COMMENT | 禁止 `col TEXT COMMENT 'xx'`,用独立 `COMMENT ON COLUMN` |
|
||||
| 手写系统表查结构 | 常规结构查询用 `+db-table-list` / `+db-table-get`,别手写 `information_schema` / `pg_indexes` 模拟 |
|
||||
| 空数组类型不明 | 写 `ARRAY[]::text[]` 或 `'{}'::text[]` |
|
||||
| `ROUND` 报错 | 用 `ROUND(num::numeric, n)` 或 `ROUND(num::double precision)` |
|
||||
| `DISTINCT` + 窗口函数 | 分两层查询,先 DISTINCT 再窗口函数 |
|
||||
| MySQL 方言 | 不用 `SHOW TABLES` / `DESCRIBE` / 内联 `COMMENT`;用 `+db-table-*` 和 `COMMENT ON` |
|
||||
| 多语句以为自动回滚 | `A; B; C` 不自动包事务,B 失败时 A 已提交;要原子性显式 `BEGIN; ... COMMIT;`(见上「命令骨架」「Agent 规则」) |
|
||||
|
||||
## 数据类型与设计
|
||||
|
||||
| 项目 | 规则 |
|
||||
|---|---|
|
||||
| 主键 | 默认 `id uuid PRIMARY KEY DEFAULT gen_random_uuid()` |
|
||||
| 命名 | 表名单数、全小写、snake_case、无冗余后缀 |
|
||||
| 枚举 / 状态 | 用 `varchar(255)`,值用小写英文 + 下划线 |
|
||||
| JSONB | 必须 `COMMENT ON COLUMN ... IS '@type { ... }'` 声明类型 |
|
||||
| 附件 / 图片 | URL 用 `TEXT`,命名 `xxx_url` |
|
||||
| 约束 | `UNIQUE` / `FOREIGN KEY` / `NOT NULL` 默认谨慎,新增 NOT NULL 列优先带 `DEFAULT` |
|
||||
162
.agents/skills/lark-apps/references/lark-apps-db.md
Normal file
162
.agents/skills/lark-apps/references/lark-apps-db.md
Normal file
@ -0,0 +1,162 @@
|
||||
# apps db 域命令
|
||||
|
||||
管理妙搭应用数据库:看表与结构、初始化与发布多环境、数据搬运、变更治理、时间点恢复、用量。逐条跑 SQL(SELECT/DML/DDL)走 [`+db-execute`](lark-apps-db-execute.md)(单独一篇)。运行时命令事实以 `lark-cli apps +<cmd> --help` 为准;认证、`--as user`、exit 码、`_notice` 等通用处理见 [`../../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 与本域 [`SKILL.md`](../SKILL.md)。
|
||||
|
||||
## 何时用
|
||||
|
||||
用户要看应用里有哪些表 / 某张表的结构、把单库应用拆成 dev/online 多环境、把数据导进导出表、查谁在什么时候改了表结构或表数据、开关行级审计、把开发环境的库结构发布到线上、把库恢复到过去某个时间点、或看数据库用量时。逐条执行 SQL 走 [`+db-execute`](lark-apps-db-execute.md);文件存储(上传/下载文件)走 [`lark-apps-file.md`](lark-apps-file.md)。**建表 / 改表 / 写 SQL 的平台内容规范**(审计列、RLS、`user_profile`、禁用 SQL、PG 陷阱)见 [`lark-apps-db-execute.md`](lark-apps-db-execute.md) 的「平台 SQL 规范」。
|
||||
|
||||
## 命令一览
|
||||
|
||||
| 命令 | 做什么 | 关键参数 |
|
||||
|---|---|---|
|
||||
| `+db-table-list` | 列出某环境的数据表 | `--environment`、`--page-size`/`--page-token` |
|
||||
| `+db-table-get` | 看单张表的结构(字段/索引/约束/DDL) | `--table`、`--environment`、`--format` |
|
||||
| `+db-env-create` | 把单库应用初始化为 dev/online 多环境(高危) | `--environment`、`--sync-data`、`--yes` |
|
||||
| `+db-data-export` | 把一张表的数据导出到本地文件 | `--table`、`--output`、`--limit`、`--environment` |
|
||||
| `+db-data-import` | 把本地 csv/json 文件导进一张表(高危) | `--file`、`--table`、`--environment`、`--yes` |
|
||||
| `+db-changelog-list` | 查表结构变更(DDL)历史 | `--table`、`--change-id`、`--since`/`--until`、`--environment` |
|
||||
| `+db-audit-status` | 看哪些表开了行级审计、保留期 | `--table`、`--environment` |
|
||||
| `+db-audit-enable` | 给某表开启行级变更审计 | `--table`、`--retention`、`--environment` |
|
||||
| `+db-audit-disable` | 关闭某表的行级审计 | `--table`、`--environment` |
|
||||
| `+db-audit-list` | 列出表的行级变更事件(增删改追溯) | `--table`(可重复)、`--since`/`--until`、`--environment` |
|
||||
| `+db-env-diff` | 预览开发环境待发布到线上的结构变更 | `--app-id` |
|
||||
| `+db-env-migrate` | 把开发环境的结构变更发布到线上(高危) | `--app-id`、`--yes` |
|
||||
| `+db-recovery-diff` | 预览把库恢复到某时间点会带来的变更 | `--target` |
|
||||
| `+db-recovery-apply` | 把库恢复到某个时间点、覆盖当前数据(高危) | `--target`、`--yes` |
|
||||
| `+db-quota-get` | 查数据库存储用量 | `--environment` |
|
||||
|
||||
## 约定(先读)
|
||||
|
||||
- **环境 `--environment dev|online`(可省略)**:看表、看结构、数据导入导出、变更追溯、审计、配额都按环境区分。省略 `--environment` 时 CLI 不带该参数、由服务端按应用形态自动选分支——多环境应用走 `dev`、未开多环境的走 `online`;要固定环境就显式传。唯一会报错的组合:对未开多环境的应用显式传 `--environment dev`(无 `dev` 分支)。写操作建议先在 `dev` 验(仅多环境应用有 `dev`)。旧名 `--env` 已**移除**:传入会报 validation 错(提示改用 `--environment`),一律用 `--environment`。`+db-env-diff`/`+db-env-migrate` 是「dev→online 发布」语义,**没有** `--environment`。
|
||||
- **本地文件 / `--output` 用工作目录内相对路径**:导入 `--file ./orders.csv`、导出 `--output ./out.csv`;绝对路径、或经 `..`/符号链接越出工作目录的 `--output` 会被拒(validation / exit 2)。路径在别处先 `cd` 过去或改成相对路径。
|
||||
- **高危操作必须带 `--yes`**:`+db-env-create`、`+db-data-import`、`+db-env-migrate`、`+db-recovery-apply` 缺省会被确认关卡拦下;动手前先用对应的预览命令或 `--dry-run` 看清影响。
|
||||
- **时间参数按口语自然传**(`--since`/`--until`/`--target`),格式见末尾。
|
||||
|
||||
## 各命令
|
||||
|
||||
### 表与结构
|
||||
|
||||
**`+db-table-list`**:列出某环境的数据表。分页 `--page-size`(默认 20)/ `--page-token`(上一页 cursor)。每项给表名、描述、估算行数、大小、列数;要完整列定义 / 索引 / 约束用 `+db-table-get`。只知道业务对象名时,先用它定位可能的表名。
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-table-list --app-id app_xxx
|
||||
lark-cli apps +db-table-list --app-id app_xxx --environment dev --page-size 50
|
||||
```
|
||||
|
||||
**`+db-table-get`**:看单张表的结构。默认 JSON 给结构化的字段 / 索引 / 约束 / 估算行数 / 大小;`--format pretty` 直接输出建表 DDL 文本(给用户看建表语句或做迁移参照时用)。
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-table-get --app-id app_xxx --table orders
|
||||
lark-cli apps +db-table-get --app-id app_xxx --table orders --environment dev --format pretty
|
||||
```
|
||||
|
||||
### 多环境数据库(初始化 + 发布)
|
||||
|
||||
**`+db-env-create`(高危)**:把存量单库应用初始化为 dev/online 两套库,不可逆,必须带 `--yes`。`--environment` 目前只支持 `dev`(默认 `dev`);`--sync-data` 把现有 online 数据复制到新环境(不传则不复制)。注意:`+create --app-type full_stack` 新建的应用通常已自带多环境,重复初始化会返回冲突错误(应用已是多环境)——按 `error.hint` 转述状态即可,别重复初始化。
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-env-create --app-id app_xxx --environment dev --dry-run
|
||||
lark-cli apps +db-env-create --app-id app_xxx --environment dev --sync-data --yes
|
||||
```
|
||||
|
||||
**`+db-env-diff`**:预览开发环境里待发布到线上的表结构变更,不落地。发布前先看这个。无待发布变更时明确返回「无变更」。
|
||||
|
||||
**`+db-env-migrate`(高危)**:把开发环境的结构变更正式发布到线上,不可逆,必须带 `--yes`,返回实际发布的变更条数。发布是异步的,命令会等到完成再返回结果。
|
||||
|
||||
> 预览与发布同一端点,故 `+db-env-diff` 也需 `spark:app:write` scope(不是纯只读权限)。
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-env-diff --app-id app_xxx
|
||||
lark-cli apps +db-env-migrate --app-id app_xxx --yes
|
||||
```
|
||||
|
||||
### 数据导入导出
|
||||
|
||||
**`+db-data-export`**:把一张表导出到本地文件。导出格式**只由 `--output` 的扩展名决定**——`.csv` / `.json` / `.sql`,缺省按 `<表名>.csv` 落在当前目录。注意:全局 `--format json|pretty` 只控制**命令自身输出**(成功摘要 / 错误信封)的渲染,**不影响导出文件的格式**;`--output` 后缀必须是 `.csv/.json/.sql` 之一,否则报 validation 错误(exit 2),且不支持导出到 stdout。两道体量约束:
|
||||
|
||||
- `--limit`(1..5000,默认 5000)是**行数上限守卫**:表的行数超过它会被整体拒掉(不是「只导前 N 行」);
|
||||
- 导出产物 >1 MB 也会被拒。
|
||||
|
||||
超大表别硬导:先用 `+db-execute` 加 `WHERE` / `LIMIT` 缩小范围、分批导。
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-data-export --app-id app_xxx --table orders --output ./orders.csv
|
||||
lark-cli apps +db-data-export --app-id app_xxx --table orders --output ./orders.json --environment dev
|
||||
```
|
||||
|
||||
**`+db-data-import`(高危)**:把本地 csv/json 文件的数据导进表。文件需是 `.csv`/`.json`、≤1 MB,必须带 `--yes`。目标表缺省取文件名去掉**最后一个**扩展名(如 `orders.csv`→`orders`,`orders.2026.csv`→`orders.2026`);文件名带点号时建议显式传 `--table` 以免落到意外的表名。
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-data-import --app-id app_xxx --table orders --file ./orders.csv --environment dev --yes
|
||||
```
|
||||
|
||||
**导入/导出限额**:体积 ≤ **1 MB**、行数 ≤ **5000**,导入导出都一样,超限会被拒。超限就分批——导入拆成 ≤1 MB / ≤5000 行的多个文件,导出用 `WHERE` / `LIMIT` 缩小范围。
|
||||
|
||||
### 变更追溯与审计
|
||||
|
||||
**`+db-changelog-list`**:查表结构变更(DDL)历史——谁、什么时候、改了哪张表、做了什么。可按 `--table` 过滤、按 `--change-id` 精确定位某条、用 `--since`/`--until` 圈时间区间,分页 `--page-size`/`--page-token`。
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-changelog-list --app-id app_xxx --table orders --since 7d
|
||||
```
|
||||
|
||||
**`+db-audit-status`**:看审计开关状态。给 `--table` 看单表,不给则列出所有已配置的表(开没开、保留期)。
|
||||
|
||||
**`+db-audit-enable` / `+db-audit-disable`**:开 / 关某张表的行级变更审计。`--retention` 设保留期,取值 `7d`/`30d`/`180d`/`360d`/`forever`(默认 `7d`)。不要对已经开启审计的表重复 enable——不确定就先用 `+db-audit-status` 查。
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-audit-enable --app-id app_xxx --table orders --retention 30d
|
||||
lark-cli apps +db-audit-disable --app-id app_xxx --table orders
|
||||
```
|
||||
|
||||
**`+db-audit-list`**:列出表的行级变更事件(INSERT/UPDATE/DELETE 的前后值与操作人)。`--table` 必填、可重复传多张表;`--since`/`--until` 圈时间。
|
||||
- **多表查询**:会先帮用户把不存在、或没开审计的表过滤掉再查,被过滤的表及原因列在结果的 `skipped` 里——据此告诉用户哪些表没纳入及为什么。
|
||||
- **单表查询**:不预过滤,表不存在 / 未开审计会直接报错(按 `error.hint` 转述给用户,引导先 `+db-audit-enable`)。
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-audit-list --app-id app_xxx --table orders --since 24h
|
||||
lark-cli apps +db-audit-list --app-id app_xxx --table orders --table users
|
||||
```
|
||||
|
||||
### 时间点恢复(PITR)
|
||||
|
||||
**`+db-recovery-diff`**:预览把库恢复到 `--target` 时间点会带来哪些变更(受影响的表、行数、预计耗时),不落地。同样需 `spark:app:write` scope。
|
||||
|
||||
**`+db-recovery-apply`(高危)**:把库恢复到某个时间点,**会覆盖当前数据**,不可逆,必须带 `--yes`。
|
||||
|
||||
- 可恢复窗口最长 **7 天**,且不早于**最近一次 `+db-env-migrate`**;超出窗口的目标会被拒。
|
||||
- 目标时间点与当前库一致时返回 `no_changes`(空操作),不算失败。
|
||||
- 动手前务必先 `+db-recovery-diff` 给用户确认。
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-recovery-diff --app-id app_xxx --target 2h
|
||||
lark-cli apps +db-recovery-apply --app-id app_xxx --target 2026-04-15T10:00:00Z --yes
|
||||
```
|
||||
|
||||
### 配额
|
||||
|
||||
**`+db-quota-get`**:查数据库存储用量(已用量、表数、视图数;配额接入后还会给总配额与使用率)。
|
||||
|
||||
```bash
|
||||
lark-cli apps +db-quota-get --app-id app_xxx --environment dev
|
||||
```
|
||||
|
||||
## 时间格式(`--since` / `--until` / `--target`)
|
||||
|
||||
按用户口语自然传入即可,支持:
|
||||
- 相对时间 `7d` / `2h` / `30s`(从现在往前推)
|
||||
- 日期 `2026-04-15`
|
||||
- 日期时间 `2026-04-15T10:00:00`
|
||||
- 带时区的 ISO 8601 `2026-04-15T10:00:00Z` / `2026-04-15T10:00:00+08:00`
|
||||
|
||||
> **时区**:不带时区的 `日期` / `日期时间` 按**运行机器的本地时区**解析(再归一化到 UTC)。CI(UTC)与本地(如 UTC+8)跑同一条命令,时间边界会差几小时;要精确锁定时区时显式写 ISO 8601 带偏移(如 `...+08:00` / `...Z`)。`--target`(PITR 恢复)尤其建议带时区,避免恢复到非预期时间点。
|
||||
|
||||
## Agent 规则
|
||||
|
||||
- 用户说「本地 / 开发库 / 调试库」优先 `--environment dev`,线上排查用 `--environment online`;数据面写操作(导入 / 审计开关)建议先在 `dev` 验再动 `online`。**注意省略 `--environment` 时写操作会落到服务端选中的分支——单环境应用即 `online`(生产)**:不确定应用是否多环境时,写操作显式传 `--environment`;显式 `dev` 在单环境应用上会安全报错(无 dev 分支),正好当「是否多环境」的探针用。
|
||||
- 看表用 `+db-table-list`,看结构用 `+db-table-get`(要建表语句加 `--format pretty`);`+db-env-create` 仅用于存量单库拆多环境,新建的 full_stack 应用一般不需要。
|
||||
- 四个高危命令(`+db-env-create`、`+db-data-import`、`+db-env-migrate`、`+db-recovery-apply`)动手前先看清影响再带 `--yes`:发布 / 恢复先跑对应预览 `+db-env-diff` / `+db-recovery-diff`,导入无预览命令、可先 `--dry-run` 看请求或先在 `--environment dev` 验;不要静默追加 `--yes`,遇 confirmation_required(exit 10)按 lark-shared 协议向用户确认不可逆风险后再补 `--yes` 重试。
|
||||
- 导入 / 导出的本地路径用工作目录内相对路径;超大表导出会被行数 / 体积上限拒,改用 `+db-execute` 分批。
|
||||
- `+db-audit-list` 多表查询时,把结果里 `skipped` 的表(不存在 / 未开审计)连同原因一并向用户说明,不要让用户以为这些表「没有变更」。
|
||||
- 恢复是覆盖式且不可逆:`+db-recovery-apply` 前必须先 `+db-recovery-diff`,并明确告知用户会覆盖当前数据。
|
||||
37
.agents/skills/lark-apps/references/lark-apps-env-pull.md
Normal file
37
.agents/skills/lark-apps/references/lark-apps-env-pull.md
Normal file
@ -0,0 +1,37 @@
|
||||
# apps +env-pull
|
||||
|
||||
> **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md)(认证 / 全局参数 / 安全)。
|
||||
|
||||
把妙搭应用 dev 启动期环境变量拉取到本地项目根的 `.env.local`。身份固定 `--as user`;scope `spark:app:read`。`--app-id` 必填,目标项目根默认当前工作目录(`--project-path` 可指定)。
|
||||
|
||||
这个命令是 dev-only 的本地恢复工具:内部固定 `POST env_vars`,body 为 `env=dev`。它没有 `--env` flag,也不管理线上环境变量。
|
||||
|
||||
## 何时别用(核心反模式)
|
||||
|
||||
**通常不需要手动跑**——脚手架的 `npm run dev` 在起本地开发时会自动后台拉取(非阻塞)。手动再跑会重复做同样的事,并用服务端返回值覆盖 `.env.local` 里的同名 key;本地无关行和注释会保留。
|
||||
|
||||
只在这些兜底场景用:
|
||||
|
||||
- 不通过 `npm run dev` 启动(直接跑 `node` / IDE debug)。
|
||||
- `.env.local` 被改坏 / 删除,想重新同步。
|
||||
|
||||
## 行为
|
||||
|
||||
- **合并、不清空**:写入 `.env.local` 时保留你手写的内容与注释——命中的 key 替换值,新 key 追加,不整体覆盖。
|
||||
- **安全护栏**:返回的 envelope **不会回显任何 env key / value**(防止 token / 数据库凭据泄漏到日志或 CI 输出)。要看实际值请直接读 `.env.local`。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +env-pull --app-id <app_id>
|
||||
```
|
||||
|
||||
## 失败处理
|
||||
|
||||
`missing_scope`(没拿到 `spark:app:read`)时,按 lark-shared 引导 `lark-cli auth login --domain apps`。其余失败优先转述 `error.hint` / `error.message`。
|
||||
|
||||
## 参考
|
||||
|
||||
- [lark-apps](../SKILL.md) — 妙搭应用全部命令 + 心智模型
|
||||
- [lark-apps-local-dev](lark-apps-local-dev.md) — 本地应用开发端到端流程
|
||||
- [lark-shared](../../lark-shared/SKILL.md) — 认证和全局参数
|
||||
48
.agents/skills/lark-apps/references/lark-apps-env.md
Normal file
48
.agents/skills/lark-apps/references/lark-apps-env.md
Normal file
@ -0,0 +1,48 @@
|
||||
# apps env
|
||||
|
||||
> **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md)(认证 / 全局参数 / 安全)。
|
||||
|
||||
管理妙搭应用环境变量。查看用 `+env-list`,设置用 `+env-set`,删除用 `+env-delete`。没有单变量 get 命令;要确认某个 key 是否存在,使用 list 后用 `--jq` 过滤。
|
||||
|
||||
环境 flag 使用 `--environment`;不要使用旧的 `--env`,也不要使用短选项。
|
||||
|
||||
## 查看
|
||||
|
||||
`+env-list` 默认查 dev,且默认不返回 value。只有显式传 `--include-values` 后,响应中才可能出现变量值;不要在公开日志里展示带值输出。
|
||||
|
||||
接口契约:list 使用 `POST env_vars`,body 固定包含 `env` 和 CLI 场景 `scene=2`;set 使用 `POST create_or_update_env_var`;delete 使用 `POST delete_env_vars`。`--include-values` 只控制 CLI 输出是否展示 value,不作为服务端查询参数发送。
|
||||
|
||||
```bash
|
||||
lark-cli apps +env-list --app-id <app_id>
|
||||
lark-cli apps +env-list --app-id <app_id> --environment online
|
||||
lark-cli apps +env-list --app-id <app_id> --include-values --jq '.data.items[] | select(.key == "FOO")'
|
||||
```
|
||||
|
||||
## 设置
|
||||
|
||||
dev 环境设置不需要 `--yes`。设置 online 环境需要人类确认并显式传 `--yes`;如果用户在同一轮已经明确说“确认/直接执行”,视为已确认,直接带 `--yes`,不要再次追问。`--dry-run` 可用于预览请求且不需要 `--yes`。变量值支持直接传 `<value>`,也支持 `@file` 或 stdin 输入。
|
||||
|
||||
回复中只说明 app/env/key 和执行结果;不要回显真实 value。需要举例时使用 `<value>`、`@file` 或 stdin。
|
||||
|
||||
```bash
|
||||
lark-cli apps +env-set --app-id <app_id> --key FOO --value <value>
|
||||
lark-cli apps +env-set --app-id <app_id> --key FOO --value @./secret.txt
|
||||
lark-cli apps +env-set --app-id <app_id> --environment online --key FOO --value <value> --dry-run
|
||||
lark-cli apps +env-set --app-id <app_id> --environment online --key FOO --value <value> --yes
|
||||
```
|
||||
|
||||
## 删除
|
||||
|
||||
`+env-delete` 是 high-risk-write。尊重 exit 10 confirmation protocol:先让用户确认 app/env/key 和删除后果,再传 `--yes`。不要自动补 `--yes`。如果只是认证失败后让用户重登,重登完成不等于删除确认;继续删除前仍需确认。
|
||||
|
||||
```bash
|
||||
lark-cli apps +env-delete --app-id <app_id> --key FOO --dry-run
|
||||
lark-cli apps +env-delete --app-id <app_id> --key FOO --yes
|
||||
lark-cli apps +env-delete --app-id <app_id> --environment online --key FOO --yes
|
||||
```
|
||||
|
||||
## 反模式
|
||||
|
||||
- 不要把 `+env-pull` 当成环境变量管理命令;它只是刷新本地 `.env.local` 的兜底工具。
|
||||
- 不要为了看一个变量臆造名为 env-get 的 apps shortcut;用 `+env-list --include-values` 加 `--jq`。
|
||||
- 不要把真实 secret 写进示例或对话输出;需要示例时使用 `<value>`、`@file` 或 stdin。
|
||||
96
.agents/skills/lark-apps/references/lark-apps-file.md
Normal file
96
.agents/skills/lark-apps/references/lark-apps-file.md
Normal file
@ -0,0 +1,96 @@
|
||||
# apps file 域命令(应用存储)
|
||||
|
||||
管理妙搭应用的文件存储:上传 / 下载本地文件、列出与查看已存文件、生成临时分享链接、批量删除、查看用量。运行时命令事实以 `lark-cli apps +<cmd> --help` 为准;认证、`--as user`、exit 码、`_notice` 等通用处理见 [`../../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 与本域 [`SKILL.md`](../SKILL.md)。
|
||||
|
||||
## 何时用
|
||||
|
||||
用户要在某个妙搭应用里上传 / 下载 / 列出 / 删除文件、拿文件的临时分享链接、或看存储用量时。普通飞书云盘走 [`lark-drive`](../../lark-drive/SKILL.md);数据库里的表数据走 `+db-*`。
|
||||
|
||||
## 命令一览
|
||||
|
||||
| 命令 | 做什么 | 关键参数 |
|
||||
|---|---|---|
|
||||
| `+file-list` | 列出文件,可按名/路径/类型/大小/上传时间过滤 | `--app-id`、过滤器、`--page-size`/`--page-token` |
|
||||
| `+file-get` | 查单个文件的元数据 | `--app-id`、`--path` |
|
||||
| `+file-sign` | 生成有时效的下载链接(用于分享 / 直接下载) | `--app-id`、`--path`、`--expires-in` |
|
||||
| `+file-download` | 把远端文件保存到本地 | `--app-id`、`--path`、`--output` |
|
||||
| `+file-upload` | 上传本地文件到应用存储 | `--app-id`、`--file` |
|
||||
| `+file-delete` | 按路径批量删除文件 | `--app-id`、`--path`(可重复)、`--yes` |
|
||||
| `+file-quota-get` | 查应用的文件存储用量 | `--app-id` |
|
||||
|
||||
## 寻址与约定(先读)
|
||||
|
||||
- **远端文件统一用 `--path` 精确寻址**(远端路径,带前导 `/`)。只知道文件名时,先用 `+file-list --name <名>` 定位拿到 `path`,再做后续操作。
|
||||
- **本地文件 / 输出路径用工作目录内的相对路径**(如 `--file ./report.pdf`、`--output ./out.png`);路径在别处时先 `cd` 过去或改成相对路径。
|
||||
- 上传只接收本地 `--file`:文件名沿用本地文件名,远端路径由平台分配、全局唯一(无需也无法手填)。
|
||||
- file 域不区分环境,没有 `--env`。
|
||||
|
||||
## 各命令
|
||||
|
||||
### +file-list
|
||||
列出应用文件,支持精确过滤:`--name`(文件名)、`--path`(远端路径)、`--type`(MIME 类型)、`--size-gt`/`--size-lt`(字节)、`--uploaded-since`/`--uploaded-until`(上传时间区间,时间格式见末尾)。分页 `--page-size`(默认 20,范围 1..200)/ `--page-token`。列表每项给名称、路径、大小、类型、上传时间(pretty 表格即这 5 列);上传者、下载地址(如有)仅在 JSON 输出里,单文件详情用 `+file-get`。
|
||||
|
||||
```bash
|
||||
lark-cli apps +file-list --app-id app_xxx
|
||||
lark-cli apps +file-list --app-id app_xxx --type image/png --uploaded-since 7d
|
||||
```
|
||||
|
||||
### +file-get
|
||||
按 `--path` 查单个文件的元数据。路径不存在时返回明确的「文件不存在」错误。
|
||||
|
||||
```bash
|
||||
lark-cli apps +file-get --app-id app_xxx --path /1858537546760216.png
|
||||
```
|
||||
|
||||
### +file-sign
|
||||
为指定文件生成一个**有时效的下载链接**——适合发给用户分享、或直接下载。`--expires-in` 设有效期秒数(默认 1 天,最长 30 天)。`pretty` 模式只输出链接本身,便于复制 / 管道;要把到期时间一并告诉用户时用默认 JSON 输出(含到期时间)。
|
||||
|
||||
```bash
|
||||
lark-cli apps +file-sign --app-id app_xxx --path /1858537546760216.png --expires-in 3600
|
||||
```
|
||||
|
||||
### +file-download
|
||||
把远端文件保存到本地。`--output` 指定保存路径,缺省时按远端文件名保存到当前目录。
|
||||
|
||||
```bash
|
||||
lark-cli apps +file-download --app-id app_xxx --path /1858537546760216.png --output ./logo.png
|
||||
```
|
||||
|
||||
### +file-upload
|
||||
上传一个本地文件。文件名沿用本地文件名(特殊字符做 URL 编码透传;以 `.` 开头的隐藏文件名会加 `_` 前缀,避免下载回本地时覆盖隐藏文件),远端路径由平台分配。单文件上限 100 MB。
|
||||
|
||||
```bash
|
||||
lark-cli apps +file-upload --app-id app_xxx --file ./report.pdf
|
||||
```
|
||||
|
||||
### +file-delete(高危)
|
||||
按路径批量删除,`--path` 可重复传多个。删除是高危操作,必须带 `--yes`;缺省会被确认关卡拦下。**逐项返回结果**:部分文件删除失败(如某个路径不存在)不影响其余文件,整体仍算成功,失败项在结果里单独标出原因。
|
||||
|
||||
```bash
|
||||
lark-cli apps +file-delete --app-id app_xxx --path /1858537546760216.png --yes
|
||||
lark-cli apps +file-delete --app-id app_xxx --path /a.png --path /b.png --yes
|
||||
```
|
||||
|
||||
### +file-quota-get
|
||||
查应用的文件存储用量(已用量、文件数;配额接入后还会给总配额与使用率)。
|
||||
|
||||
```bash
|
||||
lark-cli apps +file-quota-get --app-id app_xxx
|
||||
```
|
||||
|
||||
## 时间格式(`--uploaded-since` / `--uploaded-until`)
|
||||
|
||||
按用户口语自然传入即可,支持:
|
||||
- 相对时间 `7d` / `2h` / `30s`(从现在往前推)
|
||||
- 日期 `2026-04-15`
|
||||
- 日期时间 `2026-04-15T10:00:00`
|
||||
- 带时区的 ISO 8601 `2026-04-15T10:00:00Z` / `2026-04-15T10:00:00+08:00`
|
||||
|
||||
> **时区**:不带时区的 `日期` / `日期时间` 按**运行机器的本地时区**解析(再归一化到 UTC 发给服务端)。CI(UTC)与本地(如 UTC+8)跑同一条命令,过滤边界会差几小时;要精确到某时区时显式写 ISO 8601 带偏移(如 `...+08:00` / `...Z`)。
|
||||
|
||||
## Agent 规则
|
||||
|
||||
- 寻址一律用 `--path`;用户只给文件名时先 `+file-list --name <名>` 定位,多个同名再让用户确认。
|
||||
- 上传 / 下载的本地路径用工作目录内相对路径;不在当前目录就 `cd` 过去或改相对路径。
|
||||
- 用户要「分享链接 / 临时下载地址」时用 `+file-sign`,把返回的链接转述给用户。
|
||||
- 删除前判断意图:已明确要删且授权时可直接带 `--yes`;不确定删哪些时先 `+file-list` 给用户确认。批量删除部分失败不报错,按逐项结果向用户说明哪些成功、哪些没删掉及原因。
|
||||
43
.agents/skills/lark-apps/references/lark-apps-get.md
Normal file
43
.agents/skills/lark-apps/references/lark-apps-get.md
Normal file
@ -0,0 +1,43 @@
|
||||
# apps +get
|
||||
|
||||
按 app_id 查询单个应用详情。运行时命令事实以 `lark-cli apps +get --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
需要查看一个应用的类型、名称、描述、发布状态等详情时使用。如果只是按应用名模糊搜索定位 app_id,用 `+list --keyword`。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- 必填:`--app-id`。
|
||||
- 返回应用的完整信息:`app_id`、`app_type`、`name`、`description`、`icon_url`、`created_at`、`updated_at`、`is_published`。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +get --app-id app_xxx
|
||||
lark-cli apps +get --app-id app_xxx --dry-run
|
||||
lark-cli apps +get --app-id app_xxx -q '.data.app.app_type'
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 成功读取 `data.app` 对象,包含以下字段:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `app_id` | string | 应用唯一标识 |
|
||||
| `app_type` | string | 应用类型(如 HTML、FULL_STACK、MODERN_HTML) |
|
||||
| `name` | string | 应用显示名称 |
|
||||
| `description` | string | 应用功能说明 |
|
||||
| `icon_url` | string | 应用图标 URL |
|
||||
| `created_at` | string | 创建时间(ISO 8601 UTC) |
|
||||
| `updated_at` | string | 最后更新时间(ISO 8601 UTC) |
|
||||
| `is_published` | boolean | 是否已发布 |
|
||||
|
||||
- pretty 输出展示核心字段:`app_id`、`app_type`、`name`、`is_published`、`updated_at`。
|
||||
- `is_published=true` 只代表应用历史上有发布版本,不代表最新代码已部署。
|
||||
|
||||
## Agent 规则
|
||||
|
||||
- 用户已有 `app_id` 想查看详情时用 `+get`;只有应用名时用 `+list --keyword`。
|
||||
- 不要把 `cli_` 开头的飞书应用 ID 传给 `+get`,只接受 `app_` 开头的应用 ID。
|
||||
@ -0,0 +1,37 @@
|
||||
# apps Git credential
|
||||
|
||||
妙搭 Git 凭证用于本地原生 `git clone/pull/push`。运行时命令事实以 `lark-cli apps +git-credential-init --help`、`+git-credential-list --help`、`+git-credential-remove --help` 为准。
|
||||
|
||||
## 命令
|
||||
|
||||
```bash
|
||||
lark-cli apps +git-credential-init --app-id app_xxx
|
||||
lark-cli apps +git-credential-list
|
||||
lark-cli apps +git-credential-remove --app-id app_xxx
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- `+git-credential-init` 成功后读取 `data.repository_url`;不要展示或保存其中的凭据细节,只用于下一步 `git clone`。响应还包含 `data.commit_author_name` 和 `data.commit_author_email`,这两个字段由 `+init` 内部消费,自动写入仓库 repo-local git config(`user.name` / `user.email`),agent 和用户无需手动配置。
|
||||
- `+git-credential-list` 返回本地记录和状态;可用来判断是否需要重新 init。
|
||||
- `+git-credential-remove` 只清本地配置;成功后告知不会删除云端应用或仓库。
|
||||
|
||||
## 行为规则
|
||||
|
||||
- `+git-credential-init` 返回 `repository_url`,并配置 URL-scoped Git credential helper。后续 clone/pull/push 使用原生 git。
|
||||
- `+git-credential-list` 列出本地已配置的妙搭 Git 凭证,不需要 `--app-id`。
|
||||
- `+git-credential-remove` 只移除本地凭证/helper,不删除云端应用或仓库。
|
||||
- 看到 Repository URL 后继续:
|
||||
|
||||
```bash
|
||||
git clone <repository_url>
|
||||
cd <repo>
|
||||
git checkout sprint/default
|
||||
```
|
||||
|
||||
## Agent 规则
|
||||
|
||||
- 不要手动打印、保存或拼接 token。
|
||||
- clone、pull、push、diff、log 等代码仓库操作都使用原生 `git`;不存在 `apps +pull` / `apps +push` / `apps code +read` 这类代码读写 shortcut,不要臆造。
|
||||
- 不要 push/force-push `main`;`main` 是发布态快照,由 `apps +release-create` 成功后服务端推进,直推/force-push 会被服务端护栏拒绝。
|
||||
- Git 认证失败、本地凭证损坏或 helper 缺失时,重新执行 `+git-credential-init --app-id <id>` 覆盖本地配置;不要让用户复制 token 到 remote URL。
|
||||
@ -0,0 +1,58 @@
|
||||
# apps +html-publish
|
||||
|
||||
把本地 HTML 文件或静态目录发布为妙搭应用访问 URL。运行时命令事实以 `lark-cli apps +html-publish --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
用于把已经存在的本地 HTML 文件或静态产物目录发布成妙搭访问 URL。它不负责生成 HTML 内容,也不负责全栈应用代码发布。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- 必填:`--app-id`、`--path`。
|
||||
- `--path` **必须是相对路径**(如 `./dist`、`./index.html`),不支持绝对路径。如果目标文件在其他目录,先 `cd` 到该目录再用相对路径,或用相对于当前目录的路径。
|
||||
- `--path` 可以是单个文件或目录;入口必须是 `index.html`。
|
||||
- 可选:`--allow-sensitive`,跳过凭据文件扫描。
|
||||
- 客户端打包 tar.gz 上传发布。三条硬性大小限制,任一超限即被客户端拒绝、无法发布:单个 `.html` 文件 ≤ 10MB、打包后 tar.gz ≤ 20MB、未压缩候选文件总量 ≤ 200MB。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +create --name "Demo" --app-type html
|
||||
lark-cli apps +html-publish --app-id app_xxx --path ./dist
|
||||
lark-cli apps +html-publish --app-id app_xxx --path ./index.html --dry-run
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
命令内部完成 tar.gz 打包 → TOS 上传 → 触发发布,返回 `data.release_id`。拿到 `release_id` 后用 `+release-get --app-id <app_id> --release-id <release_id>` 轮询发布状态直到 `finished`,从中读取 `online_url`。
|
||||
|
||||
- 业务失败如构建失败、应用不存在通常带 `error.hint`;优先转述 hint。网络/服务端失败则建议稍后重试。
|
||||
|
||||
## 链接边界
|
||||
|
||||
- 发布态访问链接以 `+release-get` 轮询 `finished` 返回的 `online_url` 为准。
|
||||
- 重新发布前,`+list` 的 `is_published=true` 只能说明历史上发布过,不代表当前本地产物已经部署。
|
||||
|
||||
## 发布前置门(第一步,先于任何其他动作)
|
||||
|
||||
收到发布意图后,第一个动作是量三个尺寸,不是读文件内容、不是打包:
|
||||
1. 单个 `.html` ≤ 10MB / tar.gz ≤ 20MB / 未压缩总量 ≤ 200MB。
|
||||
2. 任一超限 → 立即 STOP,把超限数字转述给用户,交还决定权。
|
||||
3. 三项都通过 → 才进入下面的命令骨架。
|
||||
|
||||
## 预览与发布边界
|
||||
|
||||
- 用户只说“用 HTML 写个 PPT/页面给我看看”时,先生成本地文件或目录,返回路径并问是否发布到妙搭分享;不要默认创建应用或部署。
|
||||
- 用户明确说“部署出去/发链接/可分享”时,才创建 `html` 应用并用 `+html-publish`。
|
||||
- 用户要发布但没有 app_id 时,先 `+create --app-type html` 创建应用;应用名可从页面/站点主题生成,不要让用户手动提供 app_id。
|
||||
- 若产物首页不是 `index.html`,发布前改名或复制为 `index.html`;目录发布时只传干净产物目录,例如 `./dist`。`.git` 目录会被自动排除,不会进入压缩包。
|
||||
- 重新部署同一个 HTML 应用时复用原 `app_id`,只重新执行 `+html-publish --app-id <id> --path <dir-or-index.html>`。
|
||||
|
||||
## 安全规则
|
||||
|
||||
默认会拦截 `.env`、`.npmrc`、`.aws/credentials` 等凭据文件。只有用户明确要发布凭据示例文件或教程内容时,才追加 `--allow-sensitive`;追加前先说明将包含哪些敏感候选文件。
|
||||
|
||||
## 常见失败
|
||||
|
||||
- `--path` 传了绝对路径:`--path` 只接受相对路径,传绝对路径会报 `--path must be a relative path within the current directory`。改用 `cd` + 相对路径,例如 `cd /target/dir && lark-cli apps +html-publish --path .`。
|
||||
- 缺少 `index.html`:目录根放置 `index.html`,或单文件路径直接指向名为 `index.html` 的文件。
|
||||
36
.agents/skills/lark-apps/references/lark-apps-init.md
Normal file
36
.agents/skills/lark-apps/references/lark-apps-init.md
Normal file
@ -0,0 +1,36 @@
|
||||
# apps +init
|
||||
|
||||
`+init` 初始化妙搭应用的代码(clone 仓库、scaffold/同步源码、拉取本地环境变量)。运行时命令事实以 `lark-cli apps +init --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
用于把妙搭应用源码拉到本地并准备开发环境。用户只是要云端 Agent 生成应用时,不要初始化本地仓库。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- 必填:`--app-id`。
|
||||
- 可选:`--dir`,clone 目标目录;省略时默认 `./<app-id>`。
|
||||
- 固定 checkout 分支:`sprint/default`。
|
||||
- `+init` 会初始化 Git 凭证、clone 仓库、切到工作分支并生成/同步本地项目。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +init --app-id app_xxx --dir ./my-app
|
||||
lark-cli apps +init --app-id app_xxx --dir /absolute/path/my-app
|
||||
lark-cli apps +init --app-id app_xxx --dir ./my-app --dry-run
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 真跑时 stdout 是 JSON envelope;stderr 会有 `->` / `→` 进度行。成功读 stdout,失败解析 stderr 末尾的 JSON 错误。
|
||||
- 成功普通初始化读取 `data.clone_path`、`branch`、`committed`、`pushed`;`repository_url` 已脱敏,不要当凭据使用。
|
||||
- `scaffold=already_initialized` 表示目录已初始化:跳过 clone/scaffold/commit,但仍会执行一次 env-pull 刷新本地环境变量(输出含 `env_pulled`,成功时含 `env_file`,失败时含 `env_pull_error` 且退出码仍为 0);此时通常没有 `repository_url` / `branch`。
|
||||
- `--dry-run` 只打印计划,不执行 git / npx;若输出含 `dir_error`,真跑前先让用户换目录。
|
||||
|
||||
## Agent 规则
|
||||
|
||||
- 目标目录必须不存在、为空目录,或已含 `.spark/meta.json` 且其 app_id 与 `--app-id` 一致的已初始化仓库。
|
||||
- 目标目录已含 `.spark/meta.json` 时,`+init` 会跳过 clone/scaffold,但仍执行一次 env-pull 刷新本地环境变量;告知用户“仓库已初始化,本地环境变量已刷新,可直接开发”,不要误报失败或重复 clone。
|
||||
- `+init` 输出没有必要原样复述;告诉用户 clone path、分支和下一步即可。
|
||||
- 新建应用做本地初始化时,若选定的目标目录已存在,不要复用,改用一个不冲突的目录名(已预授权”放手做”时自动追加后缀如 `-2`;否则向用户确认目录名)。
|
||||
37
.agents/skills/lark-apps/references/lark-apps-list.md
Normal file
37
.agents/skills/lark-apps/references/lark-apps-list.md
Normal file
@ -0,0 +1,37 @@
|
||||
# apps +list
|
||||
|
||||
列出当前用户可见的妙搭应用,用于从应用名定位 `app_id`。运行时命令事实以 `lark-cli apps +list --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
在下游操作需要 `app_id`、而用户只给了应用名/描述时,用 `--keyword` 定位。无明确目的的全量枚举会浪费上下文,优先按关键词缩小范围。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- 支持 `--keyword` 按应用名模糊搜索。
|
||||
- `--ownership` 枚举:`all` / `mine` / `shared`(默认 `all` = 我创建的 + 共享给我的;`mine` = 仅我创建;`shared` = 仅共享给我)。
|
||||
- `--app-type` 枚举:`html` / `full_stack`。
|
||||
- 分页:`--page-size` 默认 20,`--page-token` 传上一页 cursor。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +list --keyword "审批"
|
||||
lark-cli apps +list --ownership mine --app-type full_stack
|
||||
lark-cli apps +list --page-token "<cursor>"
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 成功读取 `data.items[]`;保留字段为 `description`、`app_id`、`name`、`is_published`、`online_url`、`updated_at`,用于候选展示的核心字段是 `name`、`app_id`、`updated_at`。
|
||||
- `is_published=true` 只代表应用历史上有发布版本,不代表最新云端会话、最新代码提交或最新 HTML 产物已经部署。
|
||||
- `online_url` 是当前已有发布态入口;若你没有在本轮确认发布完成,不要把它描述成“最新版本链接”。
|
||||
- 默认输出已裁掉 `icon_url`(图片 URL,agent 无法渲染)和 `created_at`(与 `updated_at` 冗余);需要时可用 `--jq` 过滤上述保留字段。
|
||||
- `data.items` 可能为空;不要把空列表当失败。
|
||||
- 若有 `has_more=true`,用返回的 `page_token` / `next_page_token` 继续翻页。
|
||||
|
||||
## Agent 规则
|
||||
|
||||
多候选时展示名称、app_id、updated_at 让用户确认。用户描述里已经有 `app_xxx` 或妙搭链接时,直接提取,不再 `+list`。
|
||||
|
||||
把 `+list` 当定位工具和发布态快照工具,不要把 `is_published` 当部署完成证明。需要证明“最新内容已上线”时,使用对应发布命令的完成状态:看 `+release-get` 的 `finished`。
|
||||
121
.agents/skills/lark-apps/references/lark-apps-local-dev.md
Normal file
121
.agents/skills/lark-apps/references/lark-apps-local-dev.md
Normal file
@ -0,0 +1,121 @@
|
||||
# lark-apps 本地开发
|
||||
|
||||
适用:用户要把妙搭应用(full_stack 或 html)源码拉到本地,用本地 code agent/IDE 开发、调试数据库,再发布。
|
||||
|
||||
## 新建 vs 已有应用
|
||||
|
||||
新建还是修改已有,由上方入口(SKILL.md「选择开发路径」)判定;进到本地流程后按分支走:
|
||||
|
||||
- **新建**:从 `+create` 开始走下面的端到端流程。
|
||||
- **已有应用**(本地还没有源码):跳过 `+create`,先按下方「存量应用入口」拿 `app_id`,再 `+init`(或 `+git-credential-init` + `git clone`)把它拉到本地,然后照常开发。
|
||||
|
||||
## 端到端流程(新建应用)
|
||||
|
||||
### full_stack
|
||||
|
||||
`+create(full_stack)` -> `+init`(或手动 `+git-credential-init` + `git clone`)-> 读仓库 Skill -> `npm install && npm run dev` -> 按需 `+db-*` 调库 -> 非自动化改动按本页 commit/push/release;包含自动化 handler 时,在任何 release 前转到 [automation SOP](lark-apps-automation.md),由它接管状态门禁和完整发布。
|
||||
|
||||
```bash
|
||||
# 新建 full_stack 应用
|
||||
lark-cli apps +create --as user --name "审批系统" --app-type full_stack \
|
||||
--description "支持登录、提交申请、多级审批、状态查询"
|
||||
|
||||
# 初始化本地仓库(--dir 取值见下方「领域规则」,勿照抄此处示例值)
|
||||
lark-cli apps +init --as user --app-id app_xxx --dir ./approval-app
|
||||
|
||||
# 进入仓库后按项目脚手架启动
|
||||
cd ./approval-app
|
||||
npm install
|
||||
npm run dev
|
||||
|
||||
# 开发完成后:提交本次改动 -> git push origin sprint/default -> +release-create。
|
||||
# +release-create 部署的是远端 sprint/default 上已 push 的代码,不是本地工作区——没 commit + push 的改动不会进入发布。
|
||||
git add <本次开发的文件> # 提交粒度见下方「改完代码后部署上线」
|
||||
git commit -m "feat: ..."
|
||||
git push origin sprint/default
|
||||
lark-cli apps +release-create --as user --app-id app_xxx --branch sprint/default
|
||||
```
|
||||
|
||||
### html
|
||||
|
||||
#### 首次开发(无 app,无代码)
|
||||
|
||||
`+create(html)` → `+init` → 加载 [`creative-design`](../creative-design/SKILL.md) skill 在 repo 根目录产出文件 → `git add .` + `git commit` → `git push origin sprint/default` → `+release-create` → `+release-get`。
|
||||
|
||||
```bash
|
||||
lark-cli apps +create --name "活动页" --app-type html --as user
|
||||
|
||||
lark-cli apps +init --app-id app_xxx --dir ./my-page
|
||||
|
||||
cd ./my-page
|
||||
# html 类型无需 npm install,+init 已跳过依赖安装
|
||||
# 加载 creative-design skill,在 repo 根目录产出 HTML 及关联文件(JSX 组件、starter components 等)
|
||||
|
||||
git add .
|
||||
git commit -m "feat: ..."
|
||||
git push origin sprint/default
|
||||
lark-cli apps +release-create --app-id app_xxx
|
||||
```
|
||||
|
||||
#### 已有 app,二次开发/迭代
|
||||
|
||||
`+init`(拉取远程代码)→ 加载 creative-design skill 在 repo 根目录迭代 → `git add .` + `git commit` → `git push origin sprint/default` → `+release-create` → `+release-get`。
|
||||
|
||||
#### creative-design 已提前生成文件,需要 init 后迁入
|
||||
|
||||
`+create(html)` → `+init` → 先 `ls` 查看 repo 根目录模板结构(创意模式模板无 `src/` 目录,文件直接放根目录)→ 将已生成的所有产出文件(HTML、JSX 组件、starter components 等)拷贝到 repo 根目录 → `git add .` + `git commit` → `git push origin sprint/default` → `+release-create` → `+release-get`。
|
||||
|
||||
`+init` 是推荐便捷入口;想逐步手动控制时,先 `+git-credential-init` 拿 `repository_url`,再用原生 `git clone` / `git checkout sprint/default`。
|
||||
|
||||
**`+init` 完成后必须执行**:`cat <project-path>/.agents/skills/plugin-guide/SKILL.md`,读取仓库插件指引。该文件包含插件目录、实例配置规则和调用代码生成方式——不读就无法正确集成插件能力。文件不存在则跳过。
|
||||
|
||||
## Trigger guide 的项目边界
|
||||
|
||||
涉及自动化业务代码时,先查看工作区 `.agents/skills/`,读取与自动化任务匹配的 `trigger-guide`。它定义业务 handler 的实现与接入约束;Apps 触发器配置细节见 [automation SOP](lark-apps-automation.md)。
|
||||
|
||||
文件缺失或不能覆盖当前任务时,报告项目缺少可用的领域 guide;不要在本 lark-cli reference 中猜测安装命令、版本或包内目录。由项目维护方通过其受支持的初始化或同步流程补齐后,再继续代码闭环;`+init` 只负责准备本地项目,不能替代领域 guide。
|
||||
|
||||
## 改完代码后部署上线
|
||||
|
||||
已拉到本地、改完代码,用户说"推上去""部署""上线""发布到云端"时,按此序列。
|
||||
|
||||
若本次改动包含自动化 handler,在执行本节通用 commit/push/release 序列前就转到 [automation SOP](lark-apps-automation.md) 的匹配路径,由该 SOP 负责完整的状态门禁、commit/push、release 和可选 enable/test;不要先按本节发布再补 trigger 状态检查。下列通用序列只用于不含自动化 handler 的改动。
|
||||
|
||||
> `+release-create` 部署的是远端 `sprint/default` 上**已 push** 的代码,不是你本地工作区——未 commit / 未 push 的改动不会进入这次发布。所以发布前务必先把本次改动提交并推送。
|
||||
|
||||
1. `git status` 看本次改动;`git add <本次相关文件>` 暂存后 `git commit` 提交。只提交本次任务相关的改动即可,无关的零散文件不必强求清空——发布门禁是「**本次相关改动已提交并推送**」,不是「工作区绝对干净」。
|
||||
2. `git push origin sprint/default` 把工作分支推到云端(遇非 fast-forward:先 `git pull --rebase origin sprint/default` 解决冲突再推,绝不 force-push;遇 Git 认证失败 / 401 / 403 / credential helper 缺失 / token 过期:先执行 `lark-cli apps +git-credential-init --app-id <app_id> --as user` 刷新本地 Git 凭证,再重试原 git 命令;刷新凭证也失败时,停止并向用户报告错误,不要换路)。
|
||||
3. `lark-cli apps +release-create --as user --app-id <app_id> --branch sprint/default` 发起部署上线,记下返回的 `release_id`。
|
||||
4. `lark-cli apps +release-get --as user --app-id <app_id> --release-id <release_id>` 轮询:`publishing` 时每 20 秒继续轮询,整体最多约 5 分钟;超时仍未完成时停止本轮轮询、报告 `release_id` 和当前 status。`finished` 成功时,若返回 `online_url`,可直接使用;未返回时不要编造链接。交付线上访问链接给他人前,注意 `online_url` 默认仅创建者可见,需先告知当前仅本人可见、按需用 `+access-scope-set` 放开可见范围。无需再调 `+list`;`failed` 时若返回非空 `error_logs`,据此给出失败原因;否则只报告 `release_id` 和当前 status,不要编造原因(`+list` 仅作独立查询入口)。
|
||||
|
||||
用户只要求启用已有 trigger 时,转到 [automation SOP 的「仅启用已有 disabled trigger」路径](lark-apps-automation.md#仅启用已有-disabled-trigger);不得因 enable 反向修改 handler、commit/push 或 release。
|
||||
|
||||
## 领域规则
|
||||
|
||||
- 代码读写走原生 `git`;CLI 负责凭证、初始化、发布和数据库调试。不存在 `apps +pull` / `apps +push` / `apps code +read` 这类代码读写 shortcut,不要臆造。
|
||||
- 工作环境没有 `git` 时,先引导安装 Git(macOS 可用 `xcode-select --install` 或 `brew install git`;Linux 按发行版包管理器安装),安装后重试原 `+init` / git 命令;不要因此改走其他发布链路。
|
||||
- `+init` 会编排 `+git-credential-init`、`git clone`、切到 `sprint/default`、运行脚手架,并在有变更时提交/推送。
|
||||
- `+init --dir` 选目录:用户已预授权或表达"不要询问"(见 SKILL.md「预授权判定」)→ 按应用名派生 `./<app-name>` 直接传 `--dir`、不停问;否则先问用户用哪个目录再传。目标已存在/非空时回问换目录。
|
||||
- `sprint/default` 是工作分支;`main` 是发布态快照,由 `+release-create` 成功后服务端 fast-forward 推进;服务端护栏禁直推 `main`、拒 force-push、要求 `sprint/default` fast-forward。
|
||||
- 已拉到本地后,pull/push/diff/log 都用原生 git;云端 `sprint/default` 比本地新时,先 `git pull --rebase origin sprint/default`,解决冲突后再 push 和 publish。
|
||||
- `git clone` / `git pull` / `git push` 如果报认证失败、401/403、credential helper 缺失或 token 过期,优先重新执行 `lark-cli apps +git-credential-init --app-id <app_id> --as user` 更新本地 Git 凭证,然后重试原 git 命令;刷新凭证也失败时,停止并向用户报告错误,不要换路;不要手动复制 token、不要把 token 拼进 remote URL。
|
||||
- 环境变量由脚手架在本地启动时处理;需要手动刷新时用 `+env-pull`。
|
||||
- 资源型文件(图片、字体、音视频等)不要直接引用本地路径,也不要提交到 git 仓库或以 base64 内联到代码中。先通过 `lark-cli apps +file-upload --app-id <app_id> --file <local_path>` 上传到应用文件存储,拿到返回的远端 URL 后在代码中引用该 URL。详情读 [`lark-apps-file.md`](lark-apps-file.md)。上传返回的链接按 app 隔离,不同应用必须各自重新上传,不能跨应用复用同一链接。
|
||||
- DB 调试用 `+db-table-list` / `+db-table-get` / `+db-execute`;不要裸连数据库或自行拼连接串。
|
||||
- DB 分 `dev` / `online`;使用 `--environment dev|online`,不要使用旧的 `--env`。只有确认应用已开启多环境时才引导 `--environment dev`;单环境应用省略 `--environment`(服务端选 online)或显式传 `--environment online`。在 dev 写入不能证明线上 handler 已验证。dev 的库结构变更要上线时,仍按应用发布链路走 `+release-create`,不要另造“数据库发布”步骤。
|
||||
- 存量单库应用需要 dev/online 多环境时,用 `+db-env-create --environment dev`。这是不可逆 high-risk 操作。
|
||||
- 只从 `+list` 看到 `is_published=true`,不能证明本地刚推送的代码已经部署;必须有本轮 `+release-get finished`。
|
||||
|
||||
## 存量应用入口
|
||||
|
||||
已有项目目录先读 `.spark/meta.json` 取 `app_id`;没有本地项目但知道应用名时用:
|
||||
|
||||
```bash
|
||||
lark-cli apps +list --keyword "应用名"
|
||||
```
|
||||
|
||||
拿到 `app_id` 后再 `+init` 或 `+git-credential-init`。
|
||||
|
||||
## 何时不用
|
||||
|
||||
- 用户明确要云端妙搭 Agent 生成/迭代,而不是本地写代码:读 [`lark-apps-cloud-dev.md`](lark-apps-cloud-dev.md)。
|
||||
@ -0,0 +1,48 @@
|
||||
# apps observability
|
||||
|
||||
> **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md)(认证 / 全局参数 / 安全)。
|
||||
|
||||
查询妙搭应用的线上运行观测和产品访问分析。所有 observability 命令只支持 `--environment online`;省略 `--environment` 时默认就是 online,传 dev 或其他环境是不支持的。不要使用旧的 `--env`,也不要使用短选项。
|
||||
|
||||
日志和 trace 的用户侧环境仍然是 online;但 OpenAPI 请求体里的后端 `app_env` 固定发送 `runtime`,因为线上应用的运行时日志和 trace 存储在 runtime 观测环境下。dry-run 输出会展示这个后端参数。
|
||||
|
||||
metric / analytics 的 `--environment` 只是 CLI 侧 online-only 校验:`+metric-list` 和 `+analytics-list` 不会向 OpenAPI body 发送 `env` 或 `app_env`。dry-run 里看不到环境字段是预期行为,不要补造参数。
|
||||
|
||||
时间过滤支持相对时间(如 `30s`、`5m`、`0.5h`、`2h`、`3d`、`1w`)、本地日期 / 时间和 RFC3339。
|
||||
|
||||
## 命令选择
|
||||
|
||||
- 日志检索:用 `+log-list` 搜索日志,用 `+log-get` 按 log ID 取单条日志。
|
||||
- `+log-list` 不再支持 `--log-id`;已有 log ID 时直接用 `+log-get --log-id <log_id>`。
|
||||
- 前端 ERROR 日志详情:`+log-get` 可能补充 `source_stack`;没有独立的 source-stack 命令。
|
||||
- Trace 检索:用 `+trace-list` 搜索 trace,用 `+trace-get` 按 trace ID 取详情。
|
||||
- 运行时指标:请求数、错误、延迟、CPU、memory 用 `+metric-list`。
|
||||
- 产品分析:PV、UV、访问量这类业务访问分析用 `+analytics-list`,不要放到 runtime metric 里混查。
|
||||
- `+analytics-list` 按最新 OpenAPI 发送 `metric_types`、纳秒时间戳和 `need_pack_lack_point=false`;`group_by` 暂不支持。
|
||||
- 用户询问“最近一小时接口请求量、错误量、延迟、接口慢/报错多”时,这是平台运行时监控,不是本地项目文件。先用 `apps +list --keyword` 找 `app_id`,再查 `+metric-list`。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +log-list --app-id <app_id> --level error --keyword timeout --since 0.5h
|
||||
lark-cli apps +log-get --app-id <app_id> --log-id <log_id>
|
||||
lark-cli apps +trace-list --app-id <app_id> --trace-id <trace_id>
|
||||
lark-cli apps +trace-get --app-id <app_id> --trace-id <trace_id>
|
||||
lark-cli apps +metric-list --app-id <app_id> --metric requests --series total --since 1d
|
||||
lark-cli apps +metric-list --app-id <app_id> --metric requests --since 1h
|
||||
lark-cli apps +metric-list --app-id <app_id> --metric latency --since 1h
|
||||
lark-cli apps +metric-list --app-id <app_id> --metric latency --series p99 --since 1d
|
||||
lark-cli apps +metric-list --app-id <app_id> --metric cpu --since 1h
|
||||
lark-cli apps +metric-list --app-id <app_id> --metric memory --since 1h
|
||||
lark-cli apps +analytics-list --app-id <app_id> --analytics users --series active-users --granularity day
|
||||
lark-cli apps +analytics-list --app-id <app_id> --analytics page-view --granularity day
|
||||
```
|
||||
|
||||
## 使用边界
|
||||
|
||||
- 如果用户问“接口慢、报错多、CPU/内存高”,优先走 `+metric-list`。
|
||||
- `+metric-list --metric requests` 不传 `--series` 会同时返回请求总量 total 和错误量 error;`--metric latency` 不传 `--series` 会同时返回 p50 和 p99。只想看单条曲线时再传 `--series total|error|p50|p99`。
|
||||
- 按接口收窄范围时使用 `--api <path-or-name>`;当前没有 `group-by` 参数,不要臆造。
|
||||
- `+metric-list` 未显式传 `--down-sample` 时会按时间范围自动选择粒度:短范围用 `1m`,中等范围用 `1h`,长范围用 `1d`;显式传入时尊重用户指定。
|
||||
- 如果用户问“页面访问量、PV、UV、活跃用户”,优先走 `+analytics-list`。
|
||||
- 如果用户已有 `trace_id` 或 `log_id`,直接用对应 get 命令;不知道 ID 时先 list。
|
||||
79
.agents/skills/lark-apps/references/lark-apps-openapi-key.md
Normal file
79
.agents/skills/lark-apps/references/lark-apps-openapi-key.md
Normal file
@ -0,0 +1,79 @@
|
||||
# apps openapi-key 命令族 SOP
|
||||
|
||||
管理妙搭应用对外暴露的 HTTP API Key(`/openapi/**` 鉴权凭证)。全部操作需 `--as user`(AuthType: user)。`--help` 是参数细节的完整来源;本文件只记录 Agent 不看就会做错的领域规则。
|
||||
|
||||
## 命令路由
|
||||
|
||||
| 命令 | 用途 |
|
||||
|---|---|
|
||||
| `+openapi-key-list` | 列出应用所有 API Key(脱敏) |
|
||||
| `+openapi-key-get` | 查看单个 Key 详情(脱敏) |
|
||||
| `+openapi-key-create` | 创建新 Key,**原始密钥一次性可见** |
|
||||
| `+openapi-key-update` | 改名或改 config(不改 status) |
|
||||
| `+openapi-key-enable` | 启用 Key(status→1) |
|
||||
| `+openapi-key-disable` | 停用 Key(status→0),**泄露/疑似泄露优先用这个而非 delete** |
|
||||
| `+openapi-key-delete` | 永久删除 Key(不可逆) |
|
||||
| `+openapi-key-reset` | 轮换密钥(刷新原始 Key),**一次性可见** |
|
||||
|
||||
## 脱敏口径(安全关键)
|
||||
|
||||
- `list` / `get` / `update` / `enable` / `disable`:返回结构里 **无** `api_key` 字段,只有 `key_preview`(格式:`****` + 原始密钥末 4 位,如 `****5f4a`)。
|
||||
- `create` / `reset`:**仅** 在 `data.api_key`(顶层)返回原始密钥一次;同时在 stderr 打印一次性提示:
|
||||
```
|
||||
warning: this api_key is shown only once and is NOT stored by lark-cli — copy it now and store it in your own secret manager.
|
||||
```
|
||||
- 原始密钥绝不写入 cache / config / recent / debug log / 错误信息。
|
||||
|
||||
## 一次性密钥语义
|
||||
|
||||
CLI 不保存原始密钥。密钥在 `create` / `reset` 时仅随响应返回一次。**密钥丢失不能用 `get` 找回**——唯一恢复方式是 `+openapi-key-reset` 重新生成新密钥(旧密钥同时失效)。
|
||||
|
||||
## scope 结构与 CLI 表达
|
||||
|
||||
后端 `config.request_scope` 的真实结构(**snake_case**——Lark 开放网关 `/open-apis/` 对外契约约定;`api_key.thrift` 的 camelCase go.tag 是内部表示,OGW 已转成 snake_case):
|
||||
|
||||
```json
|
||||
{
|
||||
"allow_all": true,
|
||||
"http_infos": [
|
||||
{ "http_method": "GET", "http_path": "/openapi/some-path" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- `allow_all=true`:放开该应用所有 `/openapi/**` 路由;`http_infos` 此时忽略。
|
||||
- `allow_all=false`:按 `http_infos` 逐条授权,每条需 `http_method`(大写)+ `http_path`(`/openapi/` 开头)。
|
||||
|
||||
CLI 提供三种互斥的 scope 表达方式:
|
||||
|
||||
| flag | 用途 | 备注 |
|
||||
|---|---|---|
|
||||
| `--scope-all` | `allow_all=true`,放开所有路由 | bool flag,显式传 `--scope-all=false` 也算"已设置" |
|
||||
| `--scope-api 'METHOD /openapi/path'` | 逐条授权一个路由,可重复 | 路由从应用 `docs/openapi.json` 取 |
|
||||
| `--scope '<raw request_scope JSON>'` | 高级逃生口,直传 request_scope JSON(snake_case) | CLI 只校验合法 JSON;`--scope` 与 `--scope-all`/`--scope-api` 互斥 |
|
||||
|
||||
### scope 值来源
|
||||
|
||||
妙搭应用的 `/openapi/**` 路由定义在应用仓库,并同步维护在 `docs/openapi.json`(`paths` 下每个 `"/openapi/..."` 条目 + HTTP 方法)。要授权哪些路由,读目标应用自己的 `docs/openapi.json`,取 `(method, path)` 对。CLI 本身不提供 API 路由发现功能(P1 规划中)。
|
||||
|
||||
## 高风险操作
|
||||
|
||||
`delete` 和 `reset` 是高风险(`high-risk-write`),有以下约束:
|
||||
|
||||
- 需显式传 `--yes`(框架 `cmdutil.RequireConfirmation`);缺少时退出码 10,**不要自动补 `--yes`**(遵循 lark-shared 安全红线)。
|
||||
- 支持 `--dry-run` 查看将要执行的 HTTP 请求(不含密钥);不确定时先 dry-run。
|
||||
- **泄露场景**:应优先 `+openapi-key-disable` 立即停用,而非 `+openapi-key-delete`——停用可随时 enable 恢复,delete 不可逆。
|
||||
|
||||
## 典型决策场景
|
||||
|
||||
| 用户意图 | 正确操作 |
|
||||
|---|---|
|
||||
| "key 泄露了,先停掉" | `+openapi-key-disable`(不是 delete) |
|
||||
| "key 丢了/忘了,再给我一个" | `+openapi-key-reset`(不是 create 新 key;reset 轮换密钥、保留原 key 配置) |
|
||||
| "我的 key 密钥是什么" | 解释:list/get 不回显原始密钥,只能用 `+openapi-key-reset` 轮换 |
|
||||
| "给应用创建一个有权限限制的 key" | `+openapi-key-create --name ... --scope-api 'GET /openapi/...'`(路由取自应用 `docs/openapi.json`) |
|
||||
|
||||
## 不在本 skill 范围
|
||||
|
||||
- OpenAPI spec 全量导出、实时日志 tail、Webhook 消费、多鉴权方式:本期不支持。
|
||||
- 身份选择、权限不足处理(`missing_scopes`→`console_url`)、exit-10 审批、通用"禁输出密钥"红线、高风险操作通用框架:见 [`../../lark-shared/SKILL.md`](../../lark-shared/SKILL.md),不在此重复。
|
||||
@ -0,0 +1,36 @@
|
||||
# apps +plugin-install
|
||||
|
||||
> **本地命令**:读当前目录的 `package.json`,在项目根目录下运行(和 npm 一样)。**不接受 `--app-id`**——它不是远端 API 命令。
|
||||
|
||||
安装插件包到项目。运行时命令事实以 `lark-cli apps +plugin-install --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
用户要接入 AI 能力或飞书平台能力,需要先安装对应的插件包。安装后才能创建插件实例。具体有哪些可用插件、该选哪个,读取创建的应用仓库 Skill:`.agents/skills/plugin-guide/SKILL.md`。
|
||||
|
||||
**插件包 ≠ npm 包**:插件包写入 `actionPlugins`,npm 写入 `dependencies`,两套独立机制。禁止用 `npm install` 代替本命令。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- `--name <key>`:插件包 key(从仓库 Skill 的「AI 插件目录」获取)。不传则批量安装 `actionPlugins` 中声明的所有插件。
|
||||
- `--version <ver>`:指定版本(如 `1.0.0`)。不传则安装最新版。
|
||||
|
||||
在项目根目录下运行(和 npm 一样,无需指定路径)。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
# 安装最新版
|
||||
lark-cli apps +plugin-install --name <plugin-key>
|
||||
|
||||
# 安装指定版本
|
||||
lark-cli apps +plugin-install --name <plugin-key> --version 1.0.0
|
||||
|
||||
# 批量安装已声明的所有插件
|
||||
lark-cli apps +plugin-install
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 已安装同版本会跳过(status=already_installed)。
|
||||
- 失败时 hint 指示原因(网络/版本不存在/package.json 缺失)。
|
||||
23
.agents/skills/lark-apps/references/lark-apps-plugin-list.md
Normal file
23
.agents/skills/lark-apps/references/lark-apps-plugin-list.md
Normal file
@ -0,0 +1,23 @@
|
||||
# apps +plugin-list
|
||||
|
||||
> **本地命令**:读当前目录的 `package.json`,在项目根目录下运行(和 npm 一样)。**不接受 `--app-id`**——它不是远端 API 命令。
|
||||
|
||||
列出已声明的插件包及安装状态。运行时命令事实以 `lark-cli apps +plugin-list --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
查看当前项目声明了哪些插件、是否已安装。`declared_not_installed` 状态表示需要运行 `+plugin-install` 安装。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
在项目根目录下运行(和 npm 一样,无需指定路径)。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +plugin-list --format json
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- `data.plugins[]` 包含 `key`、`version`、`status`(`installed` / `declared_not_installed`)。
|
||||
@ -0,0 +1,25 @@
|
||||
# apps +plugin-uninstall
|
||||
|
||||
> **本地命令**:读当前目录的 `package.json`,在项目根目录下运行(和 npm 一样)。**不接受 `--app-id`**——它不是远端 API 命令。
|
||||
|
||||
卸载插件包。运行时命令事实以 `lark-cli apps +plugin-uninstall --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
用户不再需要某个插件能力时,卸载对应的插件包。卸载前应先删除该插件的所有实例。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- `--name <key>`:要卸载的插件包 key。
|
||||
|
||||
在项目根目录下运行(和 npm 一样,无需指定路径)。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +plugin-uninstall --name <plugin-key>
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 删除 `node_modules/{key}` + 移除 `actionPlugins` 条目。
|
||||
@ -0,0 +1,32 @@
|
||||
# apps +release-create
|
||||
|
||||
为妙搭应用创建发布 release。运行时命令事实以 `lark-cli apps +release-create --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
用于把应用的代码分支推进到发布流程(html 和 full_stack 统一走此入口)。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- 必填:`--app-id`。
|
||||
- 可选:`--branch`;省略时服务端使用默认发布分支。
|
||||
- 返回 `release_id` 和 `status`,后续用 `+release-get` 轮询。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +release-create --app-id app_xxx
|
||||
lark-cli apps +release-create --app-id app_xxx --branch sprint/default --dry-run
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 成功读取 `data.release_id`、`data.status` 和 `data.sync`;`release_id` 是后续 `+release-get` 的入参。
|
||||
- `sync=true` 表示同步部署(服务端等待部署完成后才返回),`sync=false` 或缺失表示异步部署。
|
||||
- `status=publishing` 表示发布仍在进行;继续用 `+release-get` 轮询,轮询间隔应该为 20s。应用发布平均耗时大约 2min,整体超时时间大约 5min。
|
||||
- `status=finished` 表示部署已完成(同步部署时可能直接返回此状态)。
|
||||
- `+release-create` 返回 release 只代表发布已发起。只有 `+release-get` 对同一个 `release_id` 返回 `finished` 后,才能说本轮最新版本已部署。
|
||||
|
||||
## Agent 规则
|
||||
|
||||
`+release-create` 部署的是远端 `sprint/default` 上已 push 的代码,不是本地工作区——本地若有你修改但未推送的改动,需要先 `git add` + `git commit` 并 `git push` 到 `sprint/default`,否则这些改动不会进入这次发布。`git push` 如遇认证失败、401/403、credential helper 缺失或 token 过期,先执行 `lark-cli apps +git-credential-init --app-id <app_id> --as user` 刷新本地 Git 凭证,再重试原 git 命令;刷新凭证也失败时,停止并向用户报告错误,不要换路;不要手动复制 token 或改 remote URL。发布后若 status 是 `publishing`,用 [`+release-get`](lark-apps-release-get.md) 查询。`+release-create` 部署上线属高影响动作——作为别的命令的连带前置时,按 SKILL.md「高影响动作:确认与预授权」先征得用户同意再发布。
|
||||
28
.agents/skills/lark-apps/references/lark-apps-release-get.md
Normal file
28
.agents/skills/lark-apps/references/lark-apps-release-get.md
Normal file
@ -0,0 +1,28 @@
|
||||
# apps +release-get
|
||||
|
||||
按 release ID 查询单次发布详情。运行时命令事实以 `lark-cli apps +release-get --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
用于跟进已知 `release_id` 的发布状态。没有 `release_id` 时先读 [`lark-apps-release-list.md`](lark-apps-release-list.md),不要让用户手填。
|
||||
|
||||
`release_id` 是妙搭发布 ID(`+release-create` 返回),不是飞书审批实例号;查发布进度/失败都在 `apps +release-*` 命令族内完成,不要路由到 lark-approval。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- 必填:`--app-id`、`--release-id`。
|
||||
- `release_id` 来自 `+release-create` 或 `+release-list`。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +release-get --app-id app_xxx --release-id release_yyy
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 成功可能直接返回 release 字段,也可能包在 `data.release`;读取 `release_id`、`status`、`created_at`、`updated_at`,以及 `commit_id`(本轮发布对应的 git commit SHA,pretty 输出在其非空时展示一行)。
|
||||
- `status=publishing` 继续轮询。此时尚无 `online_url`;不要拿其它链接(如 `+list` 里的应用主页 / 开发态预览 URL)冒充"本轮发布的访问链接"——只回报 `release_id`、`status`,并说明 `finished` 后才可能有 `online_url`。
|
||||
- `status=finished` 发布成功——若输出含 `online_url`,直接读取它作为本轮发布的线上访问链接;未返回时只报告发布完成,不要编造链接。该链接默认仅创建者可见,交付他人前先告知当前仅本人可见、按需用 `+access-scope-set` 放开可见范围。无需再调 `+list`(`+list` 仍可用于按应用名浏览,但不是发布主流程的必经步骤)。
|
||||
- `status=failed` 发布失败——若输出含 `error_logs`(`step`/`error_log`),据此向用户转述关键失败步骤和可行动修复;未返回时不要编造失败原因。
|
||||
- 只有当这个 `release_id` 已返回 `finished`,随后读到的 `online_url` 才能被表述为"本轮发布后的访问链接"。单独从 `+list` 看到 `is_published=true` 不能证明最新版本已部署。
|
||||
@ -0,0 +1,31 @@
|
||||
# apps +release-list
|
||||
|
||||
分页查询妙搭应用发布历史,最新发布在前。运行时命令事实以 `lark-cli apps +release-list --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
用户问"最近发布""历史版本""上次为什么失败",但没有提供 `release_id` 时使用。拿到候选 release 后再接 `+release-get`。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- 必填:`--app-id`。
|
||||
- 可选 `--status`:`publishing` / `finished` / `failed`。
|
||||
- 可选 `--page-size`:默认 20,最大 500;总是发送给服务端。
|
||||
- 可选 `--page-token`:上一页 cursor。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +release-list --app-id app_xxx --page-size 10
|
||||
lark-cli apps +release-list --app-id app_xxx --status failed
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 成功读取 `data.releases[]`;关键字段是 `release_id`、`status`、`created_at`、`updated_at`。
|
||||
- `release_id` 用于继续查 `+release-get`。
|
||||
- 若 `has_more=true`,用 `next_page_token` / `page_token` 翻页。
|
||||
|
||||
## Agent 规则
|
||||
|
||||
用户限定只看 N 条("最近 N 条""最新 N 个""只要前 N 条")时用 `--page-size N`(如"最近一次发布"→ `--page-size 1`),而不是取全量再本地截断。
|
||||
133
.agents/skills/lark-apps/references/lark-apps-role.md
Normal file
133
.agents/skills/lark-apps/references/lark-apps-role.md
Normal file
@ -0,0 +1,133 @@
|
||||
# apps role 域命令(应用角色)
|
||||
|
||||
管理妙搭应用内的平台角色、角色成员,以及查询某个用户命中的角色。运行时命令事实以 `lark-cli apps +<cmd> --help` 为准;身份、授权和高风险确认遵循本域 [`SKILL.md`](../SKILL.md)。
|
||||
|
||||
## 何时用
|
||||
|
||||
用户要列出、查看、创建、更新或删除某个妙搭应用内的平台角色,管理角色的用户、部门或群成员,或查询某个用户在应用中命中的角色时使用。多维表格 / Base 的角色与权限走 `lark-base`;设置谁能访问应用走 `+access-scope-*`,不要路由到本命令域。
|
||||
|
||||
## 命令一览
|
||||
|
||||
| 命令 | 做什么 | 关键参数 |
|
||||
|---|---|---|
|
||||
| `+role-list` | 分页列出角色,或按名称筛选角色 | `--app-id`、`--name`、`--page-size`/`--page-token` |
|
||||
| `+role-get` | 根据真实 `role_id` 读取角色详情 | `--app-id`、`--role-id` |
|
||||
| `+role-match-list` | 查询指定用户命中的角色 | `--app-id`、`--user-id` |
|
||||
| `+role-create` | 创建角色 | `--app-id`、`--name`、`--description`、`--role-id` |
|
||||
| `+role-update` | 更新角色名称或描述 | `--app-id`、`--role-id`、`--name`/`--description` |
|
||||
| `+role-delete` | 永久删除角色 | `--app-id`、`--role-id`、`--yes` |
|
||||
| `+role-member-list` | 查询角色的用户、部门和群成员 | `--app-id`、`--role-id`、`--member-type` |
|
||||
| `+role-member-add` | 向角色添加用户、部门或群成员 | `--app-id`、`--role-id`、`--users`/`--departments`/`--chats` |
|
||||
| `+role-member-remove` | 定向移除或清空角色成员 | `--app-id`、`--role-id`、成员参数或 `--all`、`--yes` |
|
||||
|
||||
## 约定(先读)
|
||||
|
||||
- `app_...` 标识的是妙搭应用,其角色和成员只使用 `apps +role-*` / `apps +role-member-*`;不要改走 Base 角色命令或裸 bitable API。
|
||||
- 角色名称不是 `role_id`。只有名称时优先用 `+role-list --name` 精确解析;若已取得完整分页列表,也可从中证明精确名称唯一命中。0 条如实报告,多条让用户消歧,唯一命中后才使用返回的真实 ID。
|
||||
- `+role-list` 返回 `has_more=true` 时,用本页 `page_token` 继续查询,直到 `has_more=false`;不要根据 `total` 补造条目。
|
||||
- `+role-list`、`+role-get`、`+role-match-list` 的角色数据分别位于 `data.items`、`data.role`、`data.roles`,不要混用。
|
||||
- 同一角色的写入及依赖该写入结果的操作必须串行。不同角色的独立操作只有在每次写入可单独追溯、失败不影响其它目标且分别验收时才可并行;否则保持串行。互不依赖的名称解析或只读查询可并行。
|
||||
|
||||
## 各命令
|
||||
|
||||
### 查询角色
|
||||
|
||||
```bash
|
||||
lark-cli apps +role-list --app-id <app_id> --page-size 100
|
||||
lark-cli apps +role-list --app-id <app_id> --name '<exact_name>'
|
||||
lark-cli apps +role-get --app-id <app_id> --role-id <role_id>
|
||||
lark-cli apps +role-match-list --app-id <app_id> --user-id <ou_x>
|
||||
```
|
||||
|
||||
整理角色列表时保留 `role_id`、`name` 和 `description`。不要猜测未知 `role_id`,也不要从同名候选中静默选择。
|
||||
`items=[]` 时直接报告当前没有角色;不要为表格补造“无”或 `N/A` 占位行。
|
||||
`+role-match-list --user-id` 只接受 `ou_...`;用户给的是姓名、邮箱或手机号时,先解析唯一 open ID,再查询命中角色。
|
||||
|
||||
### 创建与更新
|
||||
|
||||
```bash
|
||||
lark-cli apps +role-create --app-id <app_id> --name '<name>' \
|
||||
--description '<description>'
|
||||
|
||||
# 只修改名称
|
||||
lark-cli apps +role-update --app-id <app_id> --role-id <role_id> \
|
||||
--name '<new_name>' --as user --format json
|
||||
|
||||
# 只修改描述
|
||||
lark-cli apps +role-update --app-id <app_id> --role-id <role_id> \
|
||||
--description '<new_description>' --as user --format json
|
||||
```
|
||||
|
||||
- `--description` 和创建时的 `--role-id` 可选;仅在确实需要稳定 ID 时传 `--role-id`,创建后不能修改。
|
||||
- 更新时只传用户明确要求变更的字段。
|
||||
- 成功响应中的角色位于 `data.role`。只有用户要求独立验证,或结果将用于后续高风险操作时,才额外执行 `+role-get`。
|
||||
|
||||
### 删除角色
|
||||
|
||||
普通“删除某角色”请求只说明目标,**不等于不可逆确认**。如果用户尚未明确确认删除后果,本轮只能定位角色、读取完整成员并说明影响,最后请求确认;不得在同一轮自动追加 `--yes`。用户已明确确认不可逆删除时才继续。
|
||||
|
||||
只有名称时仍按上述规则唯一解析,优先使用 `+role-list --name`。目标写前已不存在时立即停止,如实说明本次是 no-op、没有执行删除,不能把“当前不存在”表述为“删除成功”。
|
||||
|
||||
删除前读取准确角色和完整成员范围,向用户说明 app、role、`users` / `departments` / `chats` 影响;得到不可逆删除确认后才使用 `--yes`:
|
||||
|
||||
```bash
|
||||
lark-cli apps +role-get --app-id <app_id> --role-id <role_id>
|
||||
lark-cli apps +role-member-list --app-id <app_id> --role-id <role_id>
|
||||
lark-cli apps +role-delete --app-id <app_id> --role-id <role_id> --yes
|
||||
```
|
||||
|
||||
成功响应包含匹配的 `data.role_id` 和 `data.deleted=true`。只有用户明确要求独立验证删除结果时,才再用 `+role-list --name` 检查目标 ID 已不存在。
|
||||
|
||||
### 成员 ID 解析
|
||||
|
||||
成员 flags 只接受 open ID:用户 `ou_...`、部门 `od-...`、群 `oc_...`。用户已提供对应类型的合法 open ID 时直接使用;只有名称或邮箱时才解析。
|
||||
对象类型以用户语义为准,不能互换解析器:用户走通讯录用户搜索,部门走部门搜索,群走群搜索。
|
||||
|
||||
```bash
|
||||
# 用户:每个姓名或邮箱单独查询。
|
||||
lark-cli contact +search-user --query '<姓名或邮箱>' \
|
||||
--exclude-external-users --page-size 30
|
||||
|
||||
# 部门:拉完分页,只接受唯一的 open_department_id。
|
||||
lark-cli api POST /open-apis/contact/v3/departments/search \
|
||||
--params '{"user_id_type":"open_id","department_id_type":"open_department_id","page_size":50}' \
|
||||
--data '{"query":"<部门名称>"}'
|
||||
|
||||
# 群:拉完分页,只接受名称精确匹配的唯一 chat_id。
|
||||
lark-cli im +chat-search --query '<群名称>' --page-size 50
|
||||
```
|
||||
|
||||
- 只接受与输入姓名、邮箱或群名精确匹配的唯一结果;部门搜索只接受完整 query 的唯一 `od-...`。0 条、多条或分页未完成时停止写入并让用户补充或消歧。
|
||||
- 多个对象逐个解析。全部解析成功且总数不超过 100 后,按类型放入一次成员写入;任一对象失败时不要部分写入,也不要自动拆批。
|
||||
|
||||
### 成员操作
|
||||
|
||||
```bash
|
||||
# 省略 --member-type,返回完整 users / departments / chats。
|
||||
lark-cli apps +role-member-list --app-id <app_id> --role-id <role_id>
|
||||
|
||||
lark-cli apps +role-member-add --app-id <app_id> --role-id <role_id> \
|
||||
--users ou_x,ou_y --departments od-x --chats oc_x
|
||||
|
||||
lark-cli apps +role-member-remove --app-id <app_id> --role-id <role_id> \
|
||||
--users ou_x --yes
|
||||
|
||||
# 清空成员,不删除角色。
|
||||
lark-cli apps +role-member-remove --app-id <app_id> --role-id <role_id> \
|
||||
--all --yes
|
||||
```
|
||||
|
||||
- `+role-member-list` 不分页;`--member-type` 只返回选中类型的字段,未返回的成员字段表示“未查询”而不是空。影响确认或完整比较时必须省略它。
|
||||
- 汇总 `--member-type` 结果时明确这是过滤投影,不得据此断言角色没有其它类型成员。
|
||||
- 用户要求 CLI 原生 table 时,直接执行 `+role-member-list --format table`;可原样转发或做事实摘要,不要先取 JSON 再手工重建一张替代表格。
|
||||
- 写入和依赖其结果的回读不得放进同一个并发批次;必须等待写入完整返回成功后,再单独发起回读。误并发时只能以写入完成后的新回读作为结果证据。
|
||||
- 添加前仅在用户要求独立证明或确认其他成员类型未变化时读取完整基线,并在写后完整回读;否则成功响应即可作为结果。
|
||||
- 定向移除前确认准确成员及影响。若需要证明结果,写后完整回读;不要把过滤结果当作完整成员集合。
|
||||
- `--all` 前读取完整成员范围并确认;成功后执行一次无过滤 `+role-member-list`,确认三个成员数组均为空。
|
||||
|
||||
## 权限
|
||||
|
||||
| 操作 | 所需 scope |
|
||||
|---|---|
|
||||
| list / get / member-list / match-list | `spark:app:read` |
|
||||
| create / update / delete / member-add / member-remove | `spark:app:write` |
|
||||
@ -0,0 +1,53 @@
|
||||
# apps +session-messages-list
|
||||
|
||||
按 page_token 分页读取某个会话轮次(turn)的回复消息。运行时命令事实以 `lark-cli apps +session-messages-list --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
用于拉取妙搭应用一轮对话(turn)产生的回复消息列表。只读,scope `spark:app:read`,用户身份。对仍在 running 的 turn 也可读——消息随生成增量出现,配合 `--page-token` 续拉新消息,可用于云端开发期间实时播报本轮进展。它不发消息、也不判断轮次状态;想知道某轮是否跑完、拿 `turn_id`,仍先用 `+session-get`。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
```bash
|
||||
lark-cli apps +session-messages-list --app-id <app_id> --session-id <session_id> --turn-id <turn_id> [--page-token <token>]
|
||||
```
|
||||
|
||||
| 旗标 | 必填 | 说明 |
|
||||
|------|:----:|------|
|
||||
| `--app-id` | 是 | 应用 ID |
|
||||
| `--session-id` | 是 | 会话 ID |
|
||||
| `--turn-id` | 是 | 轮次 ID,来自 `+session-get` 的 `latest_turn.turn_id` |
|
||||
| `--page-token` | 否 | string,上一页响应里的 `next_page_token`;首页省略 |
|
||||
|
||||
## turn_id 来源
|
||||
|
||||
`--turn-id` 不是用户能直接提供的,必须先跑 `+session-get` 拿 `latest_turn.turn_id`。没有 `turn_id` 时不要猜,先 `+session-get`。
|
||||
|
||||
## 示例
|
||||
|
||||
先取最新轮次的 `turn_id`,再拉第一页,最后用 `next_page_token` 续拉下一页:
|
||||
|
||||
```bash
|
||||
# 1. 从 +session-get 提取 latest_turn.turn_id
|
||||
TURN_ID=$(lark-cli apps +session-get --app-id app_xxx --session-id conv_xxx -q '.data.latest_turn.turn_id')
|
||||
|
||||
# 2. 拉第一页(省略 --page-token)
|
||||
lark-cli apps +session-messages-list --app-id app_xxx --session-id conv_xxx --turn-id "$TURN_ID"
|
||||
|
||||
# 3. has_more=true 时,把上一页的 next_page_token 作为 --page-token 续拉
|
||||
lark-cli apps +session-messages-list --app-id app_xxx --session-id conv_xxx --turn-id "$TURN_ID" --page-token tok_next
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- `data.messages[]`:每条含 `message_id`、`role`、`content`。
|
||||
- `data.next_page_token`(string):下一页分页令牌,作为下次调用的 `--page-token`。**注意它在最后一页仍非空**(解码形如 `{"offset":N}`),不能用它是否为空判断还有没有下一页。
|
||||
- `data.has_more`(bool):是否还有更多消息。**这是判断要不要续拉的唯一依据。**
|
||||
- pretty 输出为消息表 + 末行 `next_page_token: <token> has_more: <bool>`;自动化取字段用 JSON 或 `-q`。
|
||||
- 业务失败(app/session/turn 不存在或 ID 写错)通常带 `error.hint` 指向 `+session-get`,优先转述 hint。
|
||||
|
||||
## 分页规则
|
||||
|
||||
单次调用只返回一页。Agent 自行续拉:把本次响应的 `next_page_token` 作为下次的 `--page-token`,直到 `has_more` 为 `false` 才停。首页不要传 `--page-token`。
|
||||
|
||||
> ⚠️ **终止条件只看 `has_more`,不要拿 `next_page_token` 是否为空判断。** 即使 `has_more=false`(已是最后一页),后端仍会返回一个非空的 `next_page_token`(解码形如 `{"offset":N}`);若以「token 非空就继续」为循环条件,会在末页之后继续翻出空页(每页 0 条),白费调用。读到 `has_more=false` 立即停止,不要再用该 token 续拉。
|
||||
30
.agents/skills/lark-apps/references/lark-apps-update.md
Normal file
30
.agents/skills/lark-apps/references/lark-apps-update.md
Normal file
@ -0,0 +1,30 @@
|
||||
# apps +update
|
||||
|
||||
部分更新妙搭应用元信息。运行时命令事实以 `lark-cli apps +update --help` 为准。
|
||||
|
||||
## 何时用
|
||||
|
||||
只更新应用展示元信息。用户要改代码、发布内容、可见范围或数据库时,不走 `+update`。
|
||||
|
||||
## 命令骨架
|
||||
|
||||
- 必填:`--app-id`。
|
||||
- 至少提供一个:`--name` 或 `--description`。
|
||||
- 只发送用户提供的字段,不会清空未提供字段。
|
||||
|
||||
## 示例
|
||||
|
||||
```bash
|
||||
lark-cli apps +update --app-id app_xxx --name "审批系统"
|
||||
lark-cli apps +update --app-id app_xxx --description "用于部门审批流转"
|
||||
lark-cli apps +update --app-id app_xxx --name "审批系统" --description "用于部门审批流转" --dry-run
|
||||
```
|
||||
|
||||
## 输出契约
|
||||
|
||||
- 成功读取 `data.app`;响应是完整应用对象,不只是被修改字段。
|
||||
- 缺 `--app-id` 或没有提供 `--name` / `--description` 会在本地 validation 失败。
|
||||
|
||||
## Agent 规则
|
||||
|
||||
更新前复述要变更的字段;用户没有提到的字段不要补默认值。执行后只转述新的名称/描述和 app_id,不需要展开原始响应。
|
||||
Reference in New Issue
Block a user