@amaster.ai/pi-lark 0.1.2-beta.69 → 0.1.2-beta.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amaster.ai/pi-lark",
3
- "version": "0.1.2-beta.69",
3
+ "version": "0.1.2-beta.70",
4
4
  "description": "Pi extension for Lark/Feishu workspace — calendar, docs, drive, sheets, tasks, mail and more via lark-cli.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -61,7 +61,7 @@
61
61
  "vitest": "^4.0.0"
62
62
  },
63
63
  "dependencies": {
64
- "@amaster.ai/pi-shared": "0.1.2-beta.69"
64
+ "@amaster.ai/pi-shared": "0.1.2-beta.70"
65
65
  },
66
66
  "scripts": {
67
67
  "fetch-skills": "node scripts/fetch-skills.mjs",
@@ -66,7 +66,7 @@ lark-cli apps +release-get --as user --app-id app_xxx --release-id <上一步返
66
66
 
67
67
  #### 首次开发(无 app,无代码)
68
68
 
69
- `+create(html)` → `+init` → 加载 [`creative-design`](../creative-design/SKILL.md) skill 在 repo 根目录产出文件 → `git add .` + `git commit` → `git push origin sprint/default` → `+release-create` → `+release-get`。
69
+ `+create(html)` → `+init` → 加载 [`creative-design`](../creative-design/creative-design.md) skill 在 repo 根目录产出文件 → `git add .` + `git commit` → `git push origin sprint/default` → `+release-create` → `+release-get`。
70
70
 
71
71
  ```bash
72
72
  lark-cli apps +create --name "活动页" --app-type html --as user
@@ -125,6 +125,7 @@
125
125
  | `Delay` | 延迟 |
126
126
  | `LarkMessageAction` | 发送飞书消息 |
127
127
  | `GenerateAiTextAction` | AI 生成文本 |
128
+ | `AIAnalysisAction` | AI 分析 |
128
129
 
129
130
  > 所有 Action 节点**请勿设置** `children` ,通过 `next` 串联后继。
130
131
 
@@ -134,6 +135,7 @@
134
135
  |------|------|
135
136
  | `IfElseBranch` | 条件分支,`children.links` 含 `if_true` 和 `if_false` |
136
137
  | `SwitchBranch` | 多路分支,`children.links` 含多个 `case` |
138
+ | `AIClassificationBranch` | AI 分类分支,`children.links` 含多个 `case` |
137
139
 
138
140
  ### System 类型
139
141
 
@@ -473,6 +475,26 @@
473
475
  |------|------|------|
474
476
  | `prompt` | 是 | TextRefItem[] 提示词,支持 `text` / `ref` |
475
477
 
478
+ ### AIAnalysisAction
479
+
480
+ ```json
481
+ {
482
+ "analysis_task": [
483
+ { "value_type": "text", "value": "分析昨日订单趋势、异常原因,并给出行动建议" }
484
+ ],
485
+ "analysis_table_names": ["订单表", "退款表"],
486
+ "identity_type": "maker",
487
+ "output_instruction": "先给结论,再列证据与行动建议"
488
+ }
489
+ ```
490
+
491
+ | 字段 | 必填 | 说明 |
492
+ |------|------|------|
493
+ | `analysis_task` | 是 | TextRefItem[] 分析任务,支持 `text` / `ref` 混排;至少包含一项有效内容 |
494
+ | `analysis_table_names` | 否 | string[] 分析数据范围;为空数组 `[]` 或省略时表示当前 Base 的全部数据表 |
495
+ | `identity_type` | 是 | 数据访问身份:`maker`(固定流程身份) / `triggerPersonal`(流程触发者) |
496
+ | `output_instruction` | 否 | 仅支持纯文本 |
497
+
476
498
 
477
499
  ## Branch data 详细结构
478
500
 
@@ -552,6 +574,45 @@
552
574
  | `name` | string | 分支名称 |
553
575
  | `condition` | OrGroup | 分支条件 |
554
576
 
577
+ ### AIClassificationBranch
578
+
579
+ `AIClassificationBranch` 用 AI 对 `content` 内容做分类,再通过 `children.links` 中的 `case` 边进入命中的后续步骤。`steps[].data` 使用公开 Agent Data 协议。
580
+
581
+ ```json
582
+ {
583
+ "classes": [
584
+ {
585
+ "name": "Bug",
586
+ "desc": "功能报错、异常、不可用或结果错误"
587
+ },
588
+ {
589
+ "name": "功能建议",
590
+ "desc": "希望新增能力或优化现有功能"
591
+ }
592
+ ],
593
+ "content": [
594
+ { "value_type": "text", "value": "请根据反馈内容判断类型:" },
595
+ { "value_type": "ref", "value": "$.step_trigger.fldFeedback" }
596
+ ],
597
+ "classification_rule": "信息不足时判定为无法匹配。"
598
+ }
599
+ ```
600
+
601
+ | 字段 | 必填 | 说明 |
602
+ |------|------|----------------------------------------------------------------------|
603
+ | `classes` | 是 | 分类列表,至少 2 项。每项包含 `name` 和 `desc` |
604
+ | `classes[].name` | 是 | 分类名称,需与对应普通 `children.links[].desc` 保持一致 |
605
+ | `classes[].desc` | 是 | 分类描述,可为空字符串,但字段必须存在 |
606
+ | `content` | 是 | TextRefItem[],用于分类的内容,支持 `text` / `ref` |
607
+ | `classification_rule` | 否 | 全局分类规则纯文本 |
608
+ | `no_match_action` | 否 | 无匹配策略。`classifyToOther`:进入默认分支;`fail`:当前节点失败。省略时使用 `classifyToOther` |
609
+
610
+ `children.links` 规则:
611
+ - 每个分类命中后要跳到哪个后续步骤,必须写在 children.links 中。
612
+ - 普通分类边使用 `kind: "case"` 和 `label: "branch_1"`、`branch_2` 等稳定标签;`desc` 与 `classes[i].name` 保持一致;`to` 指向该分类的入口 step。
613
+ - `no_match_action: "classifyToOther"` 时必须额外提供一条默认分支边:`{ "kind": "case", "label": "default", "desc": "默认分支", "to": "step_other_action" }`。
614
+ - `no_match_action: "fail"` 时不要提供默认分支边。
615
+
555
616
 
556
617
  ## System data 详细结构
557
618
 
@@ -788,6 +849,12 @@ HTTPClientAction 的输出取决于 `response_type`:
788
849
  |--------|------|----------|
789
850
  | (整体出参) | AI 生成的文本内容(不支持下钻,只能引用 `$.{stepId}`) | `$.{stepId}` |
790
851
 
852
+ ##### AIAnalysisAction(AI 分析)
853
+
854
+ | pathId | 说明 | 引用示例 |
855
+ |--------|------|----------|
856
+ | `analysisResult` | AI 分析结果字符串 | `$.{stepId}.analysisResult` |
857
+
791
858
  ##### 无输出的操作节点
792
859
 
793
860
  以下节点不产生任何可引用的输出数据:
@@ -887,6 +954,7 @@ $.{stepId}.{fieldId}.fileToken → 文件 Token 列表(array<string>,仅
887
954
  | SetRecordAction | 动作 | ✅ | 动态(用户配置的字段) |
888
955
  | HTTPClientAction | 动作 | ✅ | 动态(取决于用户配置的 HTTP 响应输出) |
889
956
  | GenerateAiTextAction | 动作 | ✅ | 静态(单 string) |
957
+ | AIAnalysisAction | 动作 | ✅ | 静态(`analysisResult`) |
890
958
  | Delay | 动作 | ❌ | 无输出 |
891
959
  | LarkMessageAction | 动作 | ❌ | 无输出 |
892
960
  | IfElseBranch | 分支 | ❌ | 无输出 |
@@ -57,9 +57,10 @@
57
57
  | 新增触发+通知 | AddRecordTrigger → LarkMessageAction | [下方](#示例1-新增记录触发--发送消息) |
58
58
  | 按钮点击+调用外部接口+写入日志 | ButtonTrigger → HTTPClientAction → AddRecordAction | [下方](#示例-6-按钮触发--调用外部接口--写入同步日志) |
59
59
  | 定时+循环 | TimerTrigger → FindRecordAction → Loop → LarkMessageAction | [下方](#示例2-定时触发--查找记录--循环遍历--发送消息) |
60
- | 条件判断 | ... → IfElseBranch → 分支处理 | [下方](#示例3-条件分支-ifelsebranch) |
61
- | 多路分类 | ... → SwitchBranch → 多分支处理 | [下方](#示例4-多路分支-switchbranch) |
62
- | 复杂组合 | 定时+查找+循环+分支+消息 | [下方](#示例5-组合场景-定时查找循环分支消息) |
60
+ | 条件判断 | ... → IfElseBranch → 分支处理 | [下方](#示例3-条件分支ifelsebranch) |
61
+ | 多路分类 | ... → SwitchBranch → 多分支处理 | [下方](#示例4-多路分支switchbranch) |
62
+ | 复杂组合 | 定时+查找+循环+分支+消息 | [下方](#示例5-组合场景定时查找循环分支消息) |
63
+ | AI 分类 | ... → AIClassificationBranch → 分类后处理 | [下方](#示例7-ai-分类用户反馈自动分流) |
63
64
 
64
65
  ---
65
66
 
@@ -741,6 +742,101 @@
741
742
 
742
743
  ---
743
744
 
745
+ ### 示例 7: AI 分类(用户反馈自动分流)
746
+
747
+ **场景**: 当用户反馈表新增记录时,AI 根据反馈内容分类为 Bug 或功能建议;无法判断时标记为待人工复核。
748
+
749
+ ```json
750
+ {
751
+ "client_token": "1704067206",
752
+ "title": "用户反馈自动分流",
753
+ "steps": [
754
+ {
755
+ "id": "step_trigger",
756
+ "type": "AddRecordTrigger",
757
+ "title": "新增反馈时触发",
758
+ "next": "step_ai_classify",
759
+ "data": {
760
+ "table_name": "用户反馈表",
761
+ "watched_field_name": "反馈详情"
762
+ }
763
+ },
764
+ {
765
+ "id": "step_ai_classify",
766
+ "type": "AIClassificationBranch",
767
+ "title": "AI 判断反馈类型",
768
+ "children": {
769
+ "links": [
770
+ { "kind": "case", "to": "step_bug_action", "label": "branch_1", "desc": "Bug" },
771
+ { "kind": "case", "to": "step_feature_action", "label": "branch_2", "desc": "功能建议" },
772
+ { "kind": "case", "to": "step_other_action", "label": "default", "desc": "默认分支" }
773
+ ]
774
+ },
775
+ "next": null,
776
+ "data": {
777
+ "classes": [
778
+ {
779
+ "name": "Bug",
780
+ "desc": "功能报错、异常、崩溃、无法使用或结果错误"
781
+ },
782
+ {
783
+ "name": "功能建议",
784
+ "desc": "希望新增能力或改变产品行为"
785
+ }
786
+ ],
787
+ "content": [
788
+ { "value_type": "ref", "value": "$.step_trigger.fldFeedbackDetail" }
789
+ ],
790
+ "classification_rule": "有明确故障现象时优先归入 Bug;同时包含多个诉求时,以最影响用户完成任务的问题为准;信息不足时进入默认分支。"
791
+ }
792
+ },
793
+ {
794
+ "id": "step_bug_action",
795
+ "type": "SetRecordAction",
796
+ "title": "标记为 Bug",
797
+ "next": null,
798
+ "data": {
799
+ "table_name": "用户反馈表",
800
+ "ref_info": { "step_id": "step_trigger" },
801
+ "field_values": [
802
+ { "field_name": "分类", "value": [{ "value_type": "text", "value": "Bug" }] }
803
+ ]
804
+ }
805
+ },
806
+ {
807
+ "id": "step_feature_action",
808
+ "type": "SetRecordAction",
809
+ "title": "标记为功能建议",
810
+ "next": null,
811
+ "data": {
812
+ "table_name": "用户反馈表",
813
+ "ref_info": { "step_id": "step_trigger" },
814
+ "field_values": [
815
+ { "field_name": "分类", "value": [{ "value_type": "text", "value": "功能建议" }] }
816
+ ]
817
+ }
818
+ },
819
+ {
820
+ "id": "step_other_action",
821
+ "type": "SetRecordAction",
822
+ "title": "标记为待人工复核",
823
+ "next": null,
824
+ "data": {
825
+ "table_name": "用户反馈表",
826
+ "ref_info": { "step_id": "step_trigger" },
827
+ "field_values": [
828
+ { "field_name": "分类", "value": [{ "value_type": "text", "value": "待人工复核" }] }
829
+ ]
830
+ }
831
+ }
832
+ ]
833
+ }
834
+ ```
835
+ **关键点**:
836
+ - `classes` 按顺序对应 `branch_1`、`branch_2`;`desc` 与分类名一致,`to` 指向已定义的下游 step;
837
+
838
+ ---
839
+
744
840
  ## 构造技巧
745
841
 
746
842
  ### Loop 构造要点
@@ -148,7 +148,7 @@ lark-cli calendar +freebusy --start 2026-03-11T09:00:00+08:00 --end 2026-03-11T1
148
148
  - **会议室(Room)**:"room"不是"房间",是"会议室"。会议室是日程的一种参与人(resource attendee),不能脱离日程单独预定。
149
149
  - **日程会议 ID(Meeting ID)**:日程的历史视频会议 ID,在日程上开过视频会议才会有。
150
150
  - **日程分享链接 vs 会议链接**:两者是不同事物,不可混用。
151
- - 日程分享链接:`https://<domain>/calendar/share?token=<token>`,指向日程本身,用于分享日程详情。
151
+ - 日程分享链接:`https://<domain>/calendar/share?token=<token>`,指向日程本身,用于分享日程详情。**分享日程给某个人、某个群或粘贴到文档中,需要的都是这个日程分享链接(通过 `calendar events share_info` 获取),不是 applink**;禁止自己拼接 applink 或用 applink 代替。
152
152
  - 会议链接:`https://<domain>/j/<number>`,指向视频会议入口;同一重复性日程序列的所有实例共用同一个会议链接。
153
153
 
154
154
  ## 术语映射
@@ -165,7 +165,7 @@ lark-cli calendar +freebusy --start 2026-03-11T09:00:00+08:00 --end 2026-03-11T1
165
165
  | 按关键词搜索日程 | 本 skill(`+search-event`) |
166
166
  | 从日程获取关联的视频会议 ID 或用户绑定的会议纪要文档 | 本 skill(`+meeting`) |
167
167
  | 查看日程的参会人 / 会议室(含 `--type resource` 只看会议室) | 本 skill([`+list-attendees`](references/lark-calendar-list-attendees.md)) |
168
- | 把日程分享给某人 / 群 | 本 skill:先 `calendar events share_info` 取**日程分享链接**,再走 [lark-im](../lark-im/SKILL.md) 发送该链接;分享链接不是 applink,不要自己拼接或用 applink 代替 |
168
+ | 把日程分享给某人 / 群 / 粘贴到文档 | 本 skill:先 `calendar events share_info` 取**日程分享链接**,再走 [lark-im](../lark-im/SKILL.md) 发送或粘贴该链接;**分享日程给某个人、某个群或粘贴到文档中,需要的都是日程分享链接,不是 applink**,不要自己拼接或用 applink 代替 |
169
169
  | 从日程进一步拿 AI 智能纪要 / 逐字稿 / 妙记产物 | 先 `+meeting` 取 `meeting_id`,再进入 [`lark-meeting`](../lark-meeting/SKILL.md):[`vc +detail`](../lark-meeting/references/lark-vc-detail.md) → [`note +detail`](../lark-meeting/references/lark-note-detail.md) / [`minutes +detail`](../lark-meeting/references/lark-minutes-detail.md) |
170
170
  | 预约/改约日程、调整时间、添加/更换会议室、查会议室 | 先判断新建 vs 编辑,再进入 [schedule-meeting 工作流](references/lark-calendar-schedule-meeting.md) |
171
171
  | 仅编辑日程字段(标题/描述)或增删参会人(不涉及时间和会议室) | 先定位 `event_id`,再读 [+update](references/lark-calendar-update.md) 执行变更 |
@@ -39,7 +39,7 @@
39
39
 
40
40
  需要将文档权限授予当前应用(bot)自身时:
41
41
 
42
- 1. 先执行 `lark-cli api GET /open-apis/bot/v3/info --as bot`,从返回值取 `bot.open_id`。
42
+ 1. 先执行 `lark-cli api GET /open-apis/bot/v3/info --as bot --jq '.data.open_id'`,直接取得当前应用的 `open_id`。
43
43
  2. 再调用 `lark-cli drive permission.members create`,用 `member_type=openid`、`member_id=<bot_open_id>` 授权。
44
44
 
45
45
  ```bash
@@ -58,7 +58,7 @@ lark-cli im +chat-messages-list --chat-id oc_xxx --format json
58
58
 
59
59
  ## Resource Rendering
60
60
 
61
- Messages are rendered into human-readable text for inspection. Image messages are shown as placeholders such as `![Image](img_xxx)`; files, audio, and videos are rendered with resource keys in the content (e.g. `<audio key="file_xxx" duration="Xs"/>`). By default resource binaries are **not** downloaded.
61
+ Messages are rendered into human-readable text for inspection. Image messages are shown as placeholders such as `![Image](img_xxx)`; files, audio, and videos are rendered with resource keys in the content (e.g. `<audio key="file_xxx" duration="Xs"/>`). `folder` messages are expanded one level (children rendered inside the tag, see the row below). By default resource binaries are **not** downloaded.
62
62
 
63
63
  Two ways to get the binaries:
64
64
  - **In one pass:** add `--download-resources` to this command — every eligible resource (image/file/audio/video/media + post-embedded, excluding stickers) is downloaded into `./lark-im-resources/` and a `resources` block (`{message_id, key, type, local_path, size_bytes}`) is attached to each message. See [message enrichment](lark-im-message-enrichment.md#resource-auto-download---download-resources-opt-in).
@@ -68,6 +68,7 @@ Two ways to get the binaries:
68
68
  |---------|-------------|------|
69
69
  | Image | `![Image](img_xxx)` | `--download-resources`, or manually `im +messages-resources-download --type image` |
70
70
  | File | `<file key="file_xxx" .../>` | `--download-resources`, or manually `im +messages-resources-download --type file` |
71
+ | Folder (message) | `<folder key="file_xxx" name="assets" child_count="N"><file key="..." .../>…</folder>` (first-level children rendered inside; `has_more="true"` past the 10-item cap) | Folder itself is not a single-file resource; children are real files — download one with explicit `im +messages-resources-download --message-id <id> --file-key <child_key> --type file` (`--download-resources` auto-collection does not include folder children) |
71
72
  | Audio | `<audio key="file_xxx" duration="Xs"/>` | `--download-resources`, or manually `im +messages-resources-download --type file` |
72
73
  | Video | `<video key="file_xxx" .../>` | `--download-resources`, or manually `im +messages-resources-download --type file` |
73
74
  | Sticker | `[Sticker]` | Not downloadable (Feishu does not support fetching sticker resources) |
@@ -51,13 +51,30 @@ Each message contains:
51
51
  | `sender` | Sender information (includes `name`) |
52
52
  | `content` | Message content |
53
53
 
54
+ For `folder` messages, `content` carries a folder key; `mget` expands the folder one level (`GET /files/:file_key/folder`), rendering first-level children inside the folder tag:
55
+
56
+ ```
57
+ <folder key="file_v3_...g" name="assets" child_count="5">
58
+ <file key="file_v3_...g" name="a.pdf"/>
59
+ <folder key="file_v3_...g" name="sub" child_count="2"/>
60
+ </folder>
61
+ ```
62
+
63
+ - `child_count` on the root folder is the total first-level item count reported by the API; when a folder has more first-level children than the render cap (10), the tag carries `has_more="true"`.
64
+ - `child_count` on a nested `<folder>` child is that child's own child count (a depth hint; nested folders are not expanded further).
65
+ - A genuinely empty folder renders as `<folder key="..." name="..." child_count="0"/>`.
66
+
54
67
  For `post` messages, the attachment zone (top-level `files` array) is rendered as trailing lines in `content`, one per attachment:
55
68
 
56
69
  - `<file key="file_xxx" name="report.pdf"/>` — a file with a display name (same tag style as a standalone `file` message)
57
70
  - `<file key="file_xxx"/>` — a file with an empty display name (the server always backfills names, so this branch is rare but valid on the wire)
58
- - `<folder key="file_xxx" name="assets"/>` — a folder (`is_folder: true`, same tag style as a standalone `folder` message)
71
+ - `<folder key="file_xxx" name="assets"/>` — a folder attachment (`is_folder: true`). Like folder messages, the attachment is expanded one level (children rendered inside the tag) when runtime + message id are available; otherwise it degrades to this single-line tag.
72
+
73
+ Use `--format json` to see the full content without table truncation — note the content is the rendered text (including the `<file>`/`<folder>` lines above), not the raw post JSON.
59
74
 
60
- Use `--format json` to see the full content without table truncation — note the content is the rendered text (including the `<file>`/`<folder>` lines above), not the raw post JSON. Attachment file keys rendered in the tags are eligible for [`+messages-resources-download`](lark-im-messages-resources-download.md) via `--download-resources`.
75
+ Downloading: [`+messages-resources-download`](lark-im-messages-resources-download.md) takes an explicit `--message-id` + `--file-key` and fetches `GET /messages/:id/resources/:file_key` — this works for standalone `file` message keys, top-level `post` attachment `files[]` entries, **and file keys rendered inside `<folder>...</folder>` (folder children are real files addressed by their own file_key)**. Two caveats:
76
+ - `--download-resources` (the automatic enrichment flag on list/get commands) only auto-collects top-level single-file resources from the raw content — folder children are expanded at render time and are **not** auto-added to that worklist, so to download a folder child you pass its key explicitly to `+messages-resources-download`.
77
+ - `is_folder` entries themselves (a folder, not a file) are not downloadable as a single resource.
61
78
 
62
79
  ## Usage Scenarios
63
80
 
@@ -151,7 +151,7 @@ lark-cli im +threads-messages-list --thread <thread_id>
151
151
 
152
152
  ## Resource Rendering
153
153
 
154
- Search results reuse the same content formatter as other read commands. Image messages are rendered as placeholders such as `![Image](img_xxx)`; resource binaries are **not** downloaded automatically.
154
+ Search results reuse the same content formatter as other read commands. Image messages are rendered as placeholders such as `![Image](img_xxx)`; `folder` messages in results are expanded one level (see [`lark-im-chat-messages-list`](lark-im-chat-messages-list.md#resource-rendering) for the marker/download contract); resource binaries are **not** downloaded automatically.
155
155
 
156
156
  Use `im +messages-resources-download` if you need to fetch the underlying image or file bytes from a specific message.
157
157
 
@@ -100,7 +100,7 @@ lark-cli im +threads-messages-list --thread omt_xxx --page-token <PAGE_TOKEN>
100
100
 
101
101
  ## Resource Rendering
102
102
 
103
- Thread replies are rendered into human-readable text. Image messages appear as placeholders such as `![Image](img_xxx)`; by default resource binaries are **not** downloaded.
103
+ Thread replies are rendered into human-readable text. Image messages appear as placeholders such as `![Image](img_xxx)`; `folder` replies are expanded one level (children rendered inside a `<folder ...>` tag); by default resource binaries are **not** downloaded.
104
104
 
105
105
  Pass `--download-resources` to download every eligible resource (image/file/audio/video/media + post-embedded, excluding stickers) into `./lark-im-resources/` in one pass and attach a `resources` block to each reply (see [message enrichment](lark-im-message-enrichment.md#resource-auto-download---download-resources-opt-in)). Otherwise download individual resources manually through `im +messages-resources-download` (see [lark-im-messages-resources-download](lark-im-messages-resources-download.md)).
106
106
 
@@ -64,7 +64,9 @@ metadata:
64
64
  | 不可逆删除 | `*.delete`、`drafts.delete` | ✅ 必须 |
65
65
  | 软删除 | `*.trash`、`*.batch_trash` | ✅ 必须 |
66
66
  | 取消定时 | `*.cancel_scheduled_send` | ✅ 必须 |
67
- | 修改收信规则 | `rules.create` / `update` / `delete` | ✅ 必须 |
67
+ | 删除收信规则 | `rules.delete` | ✅ 必须 |
68
+ | 创建 / 更新收信规则 | `rules.create` / `update` | ✅ 必须 |
69
+ | 启停 / 排序收信规则 | `rules.enable` / `disable` / `reorder` | ❌ 普通写操作,免 `--yes` |
68
70
  | 标签变更 | `*.add_label`、`*.remove_label` | ❌ 可逆,免确认 |
69
71
  | 已读状态 | `*.mark_read` / `mark_unread` | ❌ 可逆,免确认 |
70
72
  | 移动文件夹 | `*.move` | ❌ 可逆,免确认 |
@@ -122,7 +124,7 @@ metadata:
122
124
  - 撤回已发送邮件:撤回邮件并查询异步撤回状态。ref: [lark-mail-recall](references/lark-mail-recall.md)
123
125
  - 修改邮件标签/已读状态/文件夹:优先使用 `+message-modify`。ref: [`+message-modify`](references/lark-mail-message-modify.md)
124
126
  - 软删除邮件:优先使用 `+message-trash`。ref: [`+message-trash`](references/lark-mail-message-trash.md)
125
- - 收信规则:创建、验证、删除自动处理收到邮件的规则。ref: [lark-mail-rules](references/lark-mail-rules.md)
127
+ - 收信规则:查看、创建、更新、删除、启停、排序自动处理收到邮件的规则。ref: [lark-mail-rules](references/lark-mail-rules.md)
126
128
  - 分享邮件到 IM:分享邮件或会话到群聊、个人会话。ref: [lark-mail-share-to-chat](references/lark-mail-share-to-chat.md)
127
129
  - 发送日程邀请邮件:在邮件中嵌入 `text/calendar` 日程邀请。ref: [lark-mail-calendar-invite](references/lark-mail-calendar-invite.md)
128
130
  - 编写复杂 HTML 正文:复杂 HTML、本地图片、安全不确定时读取规范或运行 `+lint-html`;普通正文无需预读。ref: [lark-mail-html](references/lark-mail-html.md)
@@ -244,9 +246,13 @@ lark-cli mail <resource> <method> --params '{...}' [--data '{...}']
244
246
  **GET — 只有 `--params`**(`parameters` 中有 path + query,无 `requestBody`):
245
247
 
246
248
  ```bash
247
- # schema 中:user_mailbox_id (path, required), page_size (query, required), folder_id (query, optional)
248
- lark-cli mail user_mailbox.messages list \
249
+ # schema 中:user_mailbox_id (path, required), page_size (query, required)
250
+ # user_mailbox.threads.list 要求 folder_id / label_id 必须且只能提供一个
251
+ lark-cli mail user_mailbox.threads list \
249
252
  --params '{"user_mailbox_id":"me","page_size":20,"folder_id":"INBOX"}'
253
+
254
+ lark-cli mail user_mailbox.threads list \
255
+ --params '{"user_mailbox_id":"me","page_size":20,"label_id":"FLAGGED"}'
250
256
  ```
251
257
 
252
258
  **POST — `--params` + `--data`**(`parameters` 中有 path,`requestBody` 有 body 字段):
@@ -8,7 +8,7 @@
8
8
 
9
9
  如需修改已有草稿,不要使用此命令,请使用 `lark-cli mail +draft-edit`。
10
10
 
11
- **CRITICAL - 编辑邮件内容前 MUST 先用 Read 工具读取 [references/lark-mail-html.md](references/lark-mail-html.md),其中包含邮件书写规范**
11
+ **CRITICAL - 编辑邮件内容前 MUST 先用 Read 工具读取 [lark-mail-html.md](lark-mail-html.md),其中包含邮件书写规范**
12
12
 
13
13
  ## 安全约束
14
14
 
@@ -12,7 +12,7 @@
12
12
 
13
13
  **正文整体替换的快捷方式:** `--body <text>` / `--body-file <path>`(二选一互斥)会自动展开为 `set_body` op。如果只想做整段正文替换且不需要保留引用区,用这两个 flag 即可,无需写 patch-file。要保留引用区或做更精细的 op 组合,仍走 `--patch-file`。两个入口与 `--patch-file` 内的 `set_body` / `set_reply_body` 互斥。
14
14
 
15
- **CRITICAL - 编辑邮件内容前 MUST 先用 Read 工具读取 [references/lark-mail-html.md](references/lark-mail-html.md),其中包含邮件书写规范**
15
+ **CRITICAL - 编辑邮件内容前 MUST 先用 Read 工具读取 [lark-mail-html.md](lark-mail-html.md),其中包含邮件书写规范**
16
16
 
17
17
  ## 正文编辑:快捷 flag 与 typed op 的选择
18
18
 
@@ -13,7 +13,7 @@
13
13
 
14
14
  ## CRITICAL — 发送工作流(必须遵循)
15
15
 
16
- **CRITICAL - 编辑邮件内容前 MUST 先用 Read 工具读取 [references/lark-mail-html.md](references/lark-mail-html.md),其中包含邮件书写规范**
16
+ **CRITICAL - 编辑邮件内容前 MUST 先用 Read 工具读取 [lark-mail-html.md](lark-mail-html.md),其中包含邮件书写规范**
17
17
 
18
18
  此命令默认**只保存草稿**,不会发送邮件。转发会将原邮件内容发送给新收件人,需要发送时有两种合规方式:
19
19
 
@@ -13,7 +13,7 @@
13
13
 
14
14
  ## CRITICAL — 发送工作流(必须遵循)
15
15
 
16
- **CRITICAL - 编辑邮件内容前 MUST 先用 Read 工具读取 [references/lark-mail-html.md](references/lark-mail-html.md),其中包含邮件书写规范**
16
+ **CRITICAL - 编辑邮件内容前 MUST 先用 Read 工具读取 [lark-mail-html.md](lark-mail-html.md),其中包含邮件书写规范**
17
17
 
18
18
  此命令默认**只保存草稿**,不会发送邮件。回复全部会发送给**所有**原始收件人,需要发送时有两种合规方式:
19
19
 
@@ -17,7 +17,7 @@
17
17
 
18
18
  ## CRITICAL — 发送工作流(必须遵循)
19
19
 
20
- **CRITICAL - 编辑邮件内容前 MUST 先用 Read 工具读取 [references/lark-mail-html.md](references/lark-mail-html.md),其中包含邮件书写规范**
20
+ **CRITICAL - 编辑邮件内容前 MUST 先用 Read 工具读取 [lark-mail-html.md](lark-mail-html.md),其中包含邮件书写规范**
21
21
 
22
22
  此命令默认**只保存草稿**,不会发送邮件。需要发送时,有两种合规方式:
23
23
 
@@ -1,8 +1,90 @@
1
- # 收信规则
1
+ # 收信规则 Shortcut
2
2
 
3
- 管理自动处理收到邮件的规则。规则写操作需使用真实 `rule_id`,不要猜测 ID。规则写操作执行前需按 SKILL.md 的写操作确认规则获得用户确认。
3
+ 管理自动处理收到邮件的规则。优先使用 `mail +rule-*` shortcut,通过稳定英文 alias 编写条件和动作;只有需要当前 shortcut 尚未建模的服务端字段时,才回退到 `mail user_mailbox.rules` 原子 raw 命令。规则写操作需使用真实 `rule_id`,不要猜测 ID。创建、更新、删除规则需要按 SKILL.md 的高风险写规则获得用户确认并传 `--yes`;启停和排序是普通写操作,免 `--yes`。
4
4
 
5
- ## 主题包含文本 → 标记为已读
5
+ ## 常用 shortcut
6
+
7
+ ```bash
8
+ # 列出规则,输出 semantic_spec、description、unknowns
9
+ lark-cli mail +rule-list --as user --user-mailbox-id me --format json
10
+
11
+ # 查看单条规则
12
+ lark-cli mail +rule-get --as user --user-mailbox-id me --rule-id "<rule_id>"
13
+
14
+ # dry-run 创建:主题包含 Alpha 时标为已读,不产生服务端副作用
15
+ lark-cli mail +rule-create --as user --dry-run \
16
+ --name "Alpha通知已读" \
17
+ --condition "subject:contains:Alpha" \
18
+ --action "mark_read"
19
+
20
+ # 创建同一规则
21
+ lark-cli mail +rule-create --as user \
22
+ --name "Alpha通知已读" \
23
+ --condition "subject:contains:Alpha" \
24
+ --action "mark_read" \
25
+ --yes
26
+
27
+ # 更新规则:未传字段会先读当前规则并保留;传 --condition/--action 会替换对应完整集合
28
+ lark-cli mail +rule-update --as user \
29
+ --rule-id "<rule_id>" \
30
+ --name "Alpha通知归档" \
31
+ --action "archive" \
32
+ --yes
33
+
34
+ # 启停规则
35
+ lark-cli mail +rule-disable --as user --rule-id "<rule_id>"
36
+ lark-cli mail +rule-enable --as user --rule-id "<rule_id>"
37
+
38
+ # 删除规则:真实删除必须显式 --yes;不确定时先 --dry-run
39
+ lark-cli mail +rule-delete --as user --rule-id "<rule_id>" --dry-run
40
+ lark-cli mail +rule-delete --as user --rule-id "<rule_id>" --yes
41
+
42
+ # 调整顺序:完整顺序或单条移动二选一
43
+ lark-cli mail +rule-reorder --as user --rule-ids "<rule_id_1>,<rule_id_2>,<rule_id_3>"
44
+ lark-cli mail +rule-reorder --as user --move-rule-id "<rule_id_3>" --before-rule-id "<rule_id_1>"
45
+ ```
46
+
47
+ ## Alias 速查
48
+
49
+ 条件 grammar:
50
+
51
+ ```text
52
+ --condition field:op:value
53
+ --condition field:op
54
+ --condition field
55
+ ```
56
+
57
+ 常用字段:`from`/`sender`、`to`/`recipient`、`cc`、`to_or_cc`、`subject`/`title`、`body`、`attachment_name`、`attachment_type`、`any_address`、`all_mail`/`all`、`external`、`spam`、`not_spam`、`has_attachment`。
58
+
59
+ 常用操作符:`contains`/`include`、`not_contains`/`exclude`、`starts_with`/`prefix`、`ends_with`/`suffix`、`equals`/`eq`/`is`、`not_equals`/`ne`、`contains_self`/`self`、`empty`/`is_empty`。
60
+
61
+ 动作 grammar:
62
+
63
+ ```text
64
+ --action kind
65
+ --action kind:key=value
66
+ --action kind:json={"key":"value"}
67
+ ```
68
+
69
+ 常用动作:`archive`、`delete_mail`/`trash`、`mark_read`/`read`、`move_spam`/`spam`、`not_spam`/`never_spam`、`star`/`flag`、`mute_notification`/`mute`、`move_folder:folder_id=<id>`。
70
+
71
+ `--conditions` / `--actions` 支持 JSON 或 `@file`。JSON 示例:
72
+
73
+ ```json
74
+ [
75
+ {"field":"subject","operator":"contains","value":"Alpha"},
76
+ {"field":"has_attachment"}
77
+ ]
78
+ ```
79
+
80
+ ## Unknown raw 策略
81
+
82
+ - 读路径宽容:`+rule-list` / `+rule-get` 遇到未知枚举或扩展字段仍输出规则,`unknowns[]` 会说明无法识别的 raw 片段,`raw` 会保留原始规则。
83
+ - 更新规则:`+rule-update` 是“传什么改什么”。只改名称、启停、match 或 stop-after-match 时保留未触碰的 raw;传入新的 `--condition(s)` 时替换 condition items,未传 `--match` 就保留当前 match_type;传入新的 `--action(s)` 时替换 action items。
84
+ - 输入校验:用户输入 alias/语义字符串时必须能映射到当前 shortcut 支持的枚举,否则报错;用户直接输入当前 shortcut 不认识的枚举数字,也报错。
85
+ - raw fallback:需要写入当前 shortcut 尚未建模的服务端字段时,读取 `raw` 后使用原子 `user_mailbox.rules` 命令。
86
+
87
+ ## 原子 raw fallback:主题包含文本 → 标记为已读
6
88
 
7
89
  ```bash
8
90
  # 1. 创建规则:主题包含指定文本时标记为已读
@@ -16,7 +98,8 @@ lark-cli mail user_mailbox.rules list --as user \
16
98
 
17
99
  # 3. 删除规则
18
100
  lark-cli mail user_mailbox.rules delete --as user \
19
- --params '{"user_mailbox_id":"me","rule_id":"<rule_id>"}'
101
+ --params '{"user_mailbox_id":"me","rule_id":"<rule_id>"}' \
102
+ --yes
20
103
  ```
21
104
 
22
105
  Quick codes above: condition `type=6` = subject, `operator=1` = contains, action `type=3` = mark as read.
@@ -12,7 +12,7 @@
12
12
 
13
13
  ## CRITICAL — 发送工作流(必须遵循)
14
14
 
15
- **CRITICAL - 编辑邮件内容前 MUST 先用 Read 工具读取 [references/lark-mail-html.md](references/lark-mail-html.md),其中包含邮件书写规范**
15
+ **CRITICAL - 编辑邮件内容前 MUST 先用 Read 工具读取 [lark-mail-html.md](lark-mail-html.md),其中包含邮件书写规范**
16
16
 
17
17
  此命令默认**只保存草稿**,不会发送邮件。需要发送时,有两种合规方式:
18
18
 
@@ -91,4 +91,4 @@ lark-cli mail +watch --print-output-schema
91
91
 
92
92
  - [lark-mail](../SKILL.md) — 邮箱域总览
93
93
  - [lark-mail-triage](lark-mail-triage.md) — 邮件摘要列表
94
- - [lark-event-subscribe](../../lark-event/references/lark-event-subscribe.md) — 通用事件订阅
94
+ - [lark-event](../../lark-event/SKILL.md) — 通用事件订阅
@@ -112,7 +112,7 @@ lark-cli vc +meeting-events --as <same_identity> --meeting-id <id> --page-token
112
112
  - 如果上下文没有明确 `meeting_id`,先按用户当前意图选择身份:问“我/当前用户所在会议”用 `lark-cli vc +meeting-list-active --as user --format json`;问“应用机器人可见的目标用户会议”用 `lark-cli vc +meeting-list-active --as bot --user-id <user_open_id> --format json`。返回多个会议时先让用户选择。
113
113
  - 如果上下文只有 9 位会议号,先按当前身份执行 `+meeting-list-active` 并按 `meeting_no` 匹配;匹配到唯一会议后再查事件。不要为了总结会议而自动调用 `+meeting-join`。
114
114
  - 确认 `meeting_id` 后,沿用其来源身份执行 `lark-cli vc +meeting-events --as <same_identity> --meeting-id <id> --page-all --format pretty` 拉取最新事件流。
115
- - 如果事件流显示开始共享内容(JSON 事件类型为 `magic_share_started`,pretty 时间线显示“开始共享”),并包含文档标题或 URL 等线索,必须继续读取共享文档内容后再生成总结,不能只根据共享事件和文档标题概括会议内容。
115
+ - 如果事件流显示共享内容(JSON 事件类型为 `magic_share_started`;pretty 时间线按 `start_reason` 显示“开始共享”或“正在共享”),并包含文档标题或 URL 等线索,必须继续读取共享文档内容后再生成总结,不能只根据共享事件和文档标题概括会议内容。
116
116
  - 若存在多个共享文档,按用户问题读取相关文档;处理某条文档上下文事件时必须按该 item 的 `share_id` 精确关联,不能用“最近一次共享”替代。
117
117
  - 若文档读取失败,必须明确说明“以下总结仅基于会中事件流,未成功读取共享文档内容”。
118
118
 
@@ -134,6 +134,7 @@ lark-cli vc +meeting-events --as <same_identity> --meeting-id <id> --page-token
134
134
  | 路径 | 含义与处理 |
135
135
  | --- | --- |
136
136
  | `payload.magic_share_started_items[].share_id/share_doc` | 建立一次共享会话与文档 URL/title 的映射。缺 `share_id` 时不建立映射。 |
137
+ | `payload.magic_share_started_items[].start_reason` | `share_started` 或缺失表示真实开始;`share_detected` 表示开启 Agent 入会能力时发现已有共享。两者都建立共享映射。 |
137
138
  | `payload.magic_share_ended_items[].share_id` | 结束同一 `share_id` 的共享会话;不得结束其他映射。 |
138
139
  | `payload.document_context_changed_items[]` | 结构化消费按原序读取;pretty timeline 沿用统一时间排序。每项恰有一个已知 context 才生成 pretty 条目,未知/歧义项只保留 raw。 |
139
140
  | `item.operator` | 当前 item 的 actor;缺 ID/name 时不猜共享发起人。 |
@@ -249,7 +250,7 @@ lark-cli drive +list-replies \
249
250
  | `participant_left` | 有参会人离开会议 |
250
251
  | `chat_received` | 收到会中聊天消息 |
251
252
  | `transcript_received` | 收到转写文本 |
252
- | `magic_share_started` | 开始共享内容 / 文档 |
253
+ | `magic_share_started` | 开始共享,或开启 Agent 入会能力时发现已有共享;由 `start_reason` 区分 |
253
254
  | `magic_share_ended` | 结束共享 |
254
255
  | `document_context_changed` | 评论聚焦、章节定位或元素预览上下文变化 |
255
256
  | `countdown_changed` | 会中倒计时被设置、延长、提前结束、关闭窗口,或自然结束、临近提醒 |
@@ -1,7 +1,7 @@
1
1
 
2
2
  # vc +search
3
3
 
4
- 搜索已结束的历史会议记录,支持关键词、时间范围、组织者、参与者、会议室多条件过滤。只读,仅 `--as user`。
4
+ 搜索已结束的历史会议记录,支持关键词、时间范围、组织者、参与者、会议室多条件过滤。只读,支持 `--as user` / `--as bot`。
5
5
 
6
6
  ## 关键词使用边界
7
7
 
@@ -28,6 +28,7 @@ lark-cli vc +search --query "周会"
28
28
 
29
29
  # 通过 9 位会议号查询会议 ID
30
30
  lark-cli vc +search --query "123456789" --format json --as user
31
+ lark-cli vc +search --query "123456789" --format json --as bot
31
32
 
32
33
  # 查询某一天开过的会(单日查询时,start 和 end 必须填写同一天)
33
34
  lark-cli vc +search --start 2026-03-10 --end 2026-03-10
@@ -75,9 +76,11 @@ lark-cli vc +search --query "周会" --page-token "<PAGE_TOKEN>"
75
76
 
76
77
  `vc +search` 只能搜索已结束的历史会议记录,不用于查询未来日程。查询未来会议安排请使用 [lark-calendar](../../lark-calendar/SKILL.md)。
77
78
 
78
- ### 3. 仅支持 user 身份
79
+ ### 3. 支持 user 和 bot 身份
79
80
 
80
- 该接口仅支持 `user` 身份,使用前需完成 `lark-cli auth login` 并具备 `vc:meeting.search:read` 权限。
81
+ 该接口支持 `--as user` 和 `--as bot`。user 身份需要完成 `lark-cli auth login` 并具备 `vc:meeting.search:read` 权限;bot 身份使用应用的 tenant access token,需要确认当前应用已开通 `vc:meeting.search:read` scope,且运行环境能获取有效的 TAT。
82
+
83
+ 搜索得到 `meeting_id` 后,后续 `vc +detail`、`vc +recording`、`vc meeting get` 和 `note +detail` 必须显式沿用本次搜索使用的身份。不要为了绕过权限错误自动切换身份。
81
84
 
82
85
  ### 4. 支持分页
83
86
 
@@ -131,7 +134,7 @@ lark-cli vc +search --query "周会" --page-size 15 --page-token "<PAGE_TOKEN>"
131
134
  | 命令直接报错,要求提供过滤条件 | 没有传入 `--query`、时间范围或任何过滤 ID | 至少补充一个过滤条件后重试 |
132
135
  | 时间参数校验失败 | `--start` 或 `--end` 格式不合法 | 改用 ISO 8601 或 `YYYY-MM-DD` |
133
136
  | 搜不到未来会议 | `vc +search` 只查历史会议 | 改用 [lark-calendar](../../lark-calendar/SKILL.md) 查询未来日程 |
134
- | 权限不足 | 未授权 `vc:meeting.search:read` | 使用 `auth login` 完成授权 |
137
+ | 权限不足 | 未授权 `vc:meeting.search:read` | `--as user`:按提示完成用户授权;`--as bot`:检查 tenant access token 和应用 scope,不要执行 `auth login` |
135
138
 
136
139
  ## 提示
137
140
  - 必须使用 `--format json` 输出,便于稳定解析。
@@ -15,7 +15,7 @@
15
15
  | 已有信息 | 操作 |
16
16
  |---|---|
17
17
  | `meeting_id` | 直接查询会议或关联产物 |
18
- | `meeting_no` / 9 位会议号 | 用 `vc +search --query "<meeting_no>" --format json --as user` 搜索会议,从结果的 `id` 取得 `meeting_id` |
18
+ | `meeting_no` / 9 位会议号 | 用 `vc +search --query "<meeting_no>" --format json --as <source_identity>` 搜索会议,从结果的 `id` 取得 `meeting_id` |
19
19
  | Calendar `event_id` | 用 `calendar +meeting` 获取 `meeting_id` 和用户绑定的 `meeting_note` |
20
20
  | `note_id` | 直接进入 [智能纪要场景](query-note-and-artifacts.md) |
21
21
  | `minute_token` / 妙记 URL | 直接进入 [妙记场景](query-minutes-and-artifacts.md);URL 取路径最后一段并去掉 query 参数 |
@@ -23,7 +23,7 @@
23
23
  没有标识时,用 `vc +search` 搜索已经结束的会议:
24
24
 
25
25
  ```bash
26
- lark-cli vc +search --query <query> --start <start> --end <end> --format json
26
+ lark-cli vc +search --query <query> --start <start> --end <end> --format json --as <source_identity>
27
27
  ```
28
28
 
29
29
  - 至少提供关键词、时间范围、组织者、参与者或会议室中的一个条件;不要把“总结”“回顾”“所有会议”等动作词当作 `--query`。
@@ -38,7 +38,7 @@ lark-cli vc +search --query <query> --start <start> --end <end> --format json
38
38
 
39
39
  ## 选择查询身份
40
40
 
41
- - `vc +search` 仅支持用户身份。`vc +detail`、`vc +recording`、`vc meeting get` 和 `note +detail` 支持用户或应用身份。
41
+ - `vc +search`、`vc +detail`、`vc +recording`、`vc meeting get` 和 `note +detail` 均支持用户或应用身份。没有既有身份上下文时默认使用用户身份;用户明确要求应用视角或当前链路已经使用应用身份时,使用 `--as bot`。
42
42
  - 已有 `meeting_id`、`note_id` 或 `minute_token` 时,沿用其来源身份;后续 Minutes、Note、Doc 和 Drive 命令都显式传入同一个 `--as`。不要为查询参会人或绕过权限错误擅自切换身份。
43
43
  - `note +transcript` 仅支持用户身份。应用身份查到 unified Note 时,先说明限制,只有用户明确同意后才切换身份。
44
44