@amaster.ai/pi-lark 0.1.2-beta.62 → 0.1.2-beta.64

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.62",
3
+ "version": "0.1.2-beta.64",
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.62"
64
+ "@amaster.ai/pi-shared": "0.1.2-beta.64"
65
65
  },
66
66
  "scripts": {
67
67
  "fetch-skills": "node scripts/fetch-skills.mjs",
@@ -114,6 +114,7 @@ Shortcut 是对常用操作的高级封装(`lark-cli im +<verb> [flags]`)。
114
114
  | [`+chat-search`](references/lark-im-chat-search.md) | Search visible group chats by --query keyword and/or --member-ids; user/bot; e.g. look up chat_id by group name; supports type filters, sorting, auto-pagination, and --exclude-muted (user identity only) |
115
115
  | [`+chat-update`](references/lark-im-chat-update.md) | Update group chat name or description; user/bot; updates a chat's name or description |
116
116
  | [`+message-read-users`](references/lark-im-message-read-status.md) | List users who read one message; user/bot; identity-specific scopes; supports bounded auto-pagination |
117
+ | [`+messages-edit`](references/lark-im-messages-edit.md) | Edit a message's content (text/post, including the attachment zone); bot-only (user identity is rejected by the server); PUT /open-apis/im/v1/messages/:message_id |
117
118
  | [`+messages-mget`](references/lark-im-messages-mget.md) | Batch get messages by IDs; user/bot; fetches up to 50 om_ message IDs, formats sender names, expands thread replies |
118
119
  | [`+messages-read-status`](references/lark-im-message-read-status.md) | Batch query whether the current user read 1–50 messages; user-only; returns readable items and invalid message IDs |
119
120
  | [`+messages-reply`](references/lark-im-messages-reply.md) | Reply to a message (supports thread replies); user/bot; supports text/markdown/post/media replies, reply-in-thread, idempotency key |
@@ -163,6 +164,11 @@ lark-cli im <resource> <method> [flags] # 调用 API
163
164
  - `update` — 设置自己的群昵称。Set or update your own nickname in the chat (self-only). Identity: `user` only (`user_access_token`); `nickname` must be a non-empty string (max 300 bytes). Use DELETE to clear it.
164
165
  - `delete` — 清空自己的群昵称。Clear your own nickname in the chat (self-only). Identity: `user` only (`user_access_token`).
165
166
 
167
+ ### chat.join_requests
168
+
169
+ - `list` — 列出群的待审批入群申请(仅群主/管理员,user_access_token)。List pending join requests for a chat. Identity: `user` only (`user_access_token`); the caller must be the chat owner or an admin. Paginated (`page_size` 1-100); stop on `has_more == false` — `page_token` is returned even on the last page, so paging while it is present never terminates.
170
+ - `handle` — 批量审批入群申请(approve/reject,仅群主/管理员,user_access_token)。Approve or reject pending join requests in bulk (1-50 items, processed in order). Identity: `user` only (`user_access_token`); the caller must be the chat owner or an admin. `results[]` mirrors `items[]` in count and order — check each `result` (`success` / `failed` / `already_handled`); exit 0 does not mean every item succeeded.
171
+
166
172
  ### chat.managers
167
173
 
168
174
  - `add_managers` — 指定群管理员。Identity: supports `user` and `bot`; only the group owner can add managers; max 10 managers per chat (20 for super-large chats), and at most 5 bots per request.
@@ -237,6 +243,8 @@ lark-cli im <resource> <method> [flags] # 调用 API
237
243
  | `chat.managers.delete_managers` | `im:chat.managers:write_only` |
238
244
  | `chat.moderation.get` | `im:chat.moderation:read` |
239
245
  | `chat.moderation.update` | `im:chat:moderation:write_only` |
246
+ | `chat.join_requests.list` | `im:chat.membership_application:read` |
247
+ | `chat.join_requests.handle` | `im:chat.membership_application:write` |
240
248
  | `+messages-read-status` | user: `im:message:readonly` (recommended), `im:message`, or `im:message:get_as_user` |
241
249
  | `+message-read-users` | user: `im:message:readonly` (recommended), `im:message`, `im:message:basic`, or `im:message:get_as_user`; bot: `im:message:readonly` |
242
250
  | `messages.read_status` | `im:message:readonly` (recommended), `im:message`, or `im:message:get_as_user` |
@@ -0,0 +1,89 @@
1
+ # im +messages-edit
2
+
3
+ > **Prerequisite:** Read [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) first to understand authentication, global parameters, and safety rules.
4
+
5
+ Edit an already-sent message's content. **Bot identity only** — the edit API does not accept user tokens. Only messages the bot sent can be edited.
6
+
7
+ This skill maps to the shortcut: `lark-cli im +messages-edit` (PUT on the message edit endpoint).
8
+
9
+ ## Safety Constraints
10
+
11
+ Editing rewrites a message visible to other people. Before calling it, you **must** confirm with the user:
12
+
13
+ 1. Which message to edit (its `message_id`)
14
+ 2. The new content
15
+
16
+ The bot must be the original sender — editing another identity's message fails. Identity is always the bot: user identity is rejected server-side (`user access token not support`).
17
+
18
+ **Do not** edit a message without explicit user approval.
19
+
20
+ ## Choose The Right Content Flag
21
+
22
+ | Need | Recommended flag | Why |
23
+ |------|------|------|
24
+ | Edit to headings, lists, links, summaries, or Markdown-looking content | `--markdown` | Best default for lightweight formatting; converted to Feishu `post` JSON |
25
+ | Edit to exact plain text | `--text` | Preserves literal text; no Markdown conversion |
26
+ | Precisely control the new payload | `--content` | You provide the exact JSON for `text` / `post` |
27
+ | Attach files/folders to the edited message's attachment zone | `--set-attachments` | Repeatable, as bare `file_key` (`file_xxx`); **replaces** the post content's `files` array (flag values are the final list, discarding any `files` in `--content`). Requires a post message (`--markdown` or `--msg-type post`). Name/metadata are filled by the server, not the client |
28
+ | Clear the edited message's attachment zone | `--clear-attachments` | Sets `files:[]` on the post content. Requires a post message; mutually exclusive with `--set-attachments` |
29
+ | Keep the existing attachment zone while rewriting the body | *(no attachment flag)* | **Default.** Editing with only `--markdown` / `--text` / `--content` leaves the current `files` array untouched — a body-only edit never drops attachments |
30
+
31
+ ## Editing the Attachment Zone
32
+
33
+ `post` messages can carry an attachment zone — a top-level `files` array that renders files/folders under the rich-text body.
34
+
35
+ **Default: no attachment flag preserves the attachment zone.** Editing with only `--markdown` / `--text` / `--content` (i.e. passing neither `--set-attachments` nor `--clear-attachments`) rewrites the body and keeps the existing `files` array unchanged. This is the safe default — fixing a typo must not drop the files you attached. Only pass `--set-attachments` to replace the zone, or `--clear-attachments` to remove it.
36
+
37
+ To edit a message so it attaches (or re-attaches) files:
38
+
39
+ ```bash
40
+ lark-cli im +messages-edit --as bot --message-id om_xxx --markdown "Updated content" --set-attachments file_xxx --set-attachments file_yyy
41
+ ```
42
+
43
+ - `--set-attachments` accepts a bare file/folder key (`file_xxx`), and may be repeated.
44
+ - **`--set-attachments` is a replace, not an append:** the flag values become the final `files` array. Send/reply's `--attachment` merges; edit's `--set-attachments` replaces.
45
+ - **Mutually exclusive with `--content` carrying files:** when `--content` already contains a `files` array, `--set-attachments` and `--clear-attachments` are rejected — declare the attachment zone either via `--content` or via the attachment flags, not both. Use `--markdown` (which never emits a `files` array) or a `--content` without `files` together with the attachment flags.
46
+ - The server fills name/size/mime/is_folder from file service metadata; the client does not (and cannot) override the display name.
47
+ - When `--set-attachments` is present the effective `msg_type` is forced to `post`. Pair it with `--markdown` (or `--content` with post JSON plus `--msg-type post`); `--text` cannot carry an attachment zone.
48
+ - The edited content replaces the whole message content, so include every file you want to keep in the new attachment zone.
49
+
50
+ To **clear** the attachment zone entirely, pass `--clear-attachments` instead of `--set-attachments`:
51
+
52
+ ```bash
53
+ lark-cli im +messages-edit --as bot --message-id om_xxx --markdown "Updated content" --clear-attachments
54
+ ```
55
+
56
+ - `--clear-attachments` sets the post content's `files` array to `[]`, telling the server to remove all file/folder attachments.
57
+ - It cannot be used together with `--set-attachments`.
58
+ - Like `--set-attachments`, it forces the effective `msg_type` to `post`, so pair it with `--markdown` or `--msg-type post --content <post-json>`.
59
+
60
+ ## Parameters
61
+
62
+ | Parameter | Required | Description |
63
+ |------|------|------|
64
+ | `--message-id <id>` | Yes | Message ID (`om_xxx`) to edit |
65
+ | `--text <string>` | One content option | Plain text content |
66
+ | `--markdown <string>` | One content option | Markdown text, converted to `post` JSON |
67
+ | `--content <json>` | One content option | Exact message content JSON; must match the effective `--msg-type` |
68
+ | `--set-attachments <key>` | One content option | Repeatable bare file/folder key (`file_xxx`); **replaces** the post attachment zone — the flag values become the final `files` array, discarding any `files` written in `--content`, and duplicate keys are sent once. Name/size/mime/is_folder are filled by the server |
69
+ | `--clear-attachments` | One content option | Clear the post attachment zone by setting `files:[]` |
70
+ | `--msg-type <type>` | No | Message type (default `text`). When `--markdown`/`--set-attachments`/`--clear-attachments` is used the effective type is inferred automatically |
71
+ | `--as <identity>` | No | Identity type: `bot` only (user identity is rejected by the server) |
72
+ | `--dry-run` | No | Print the request only, do not execute it |
73
+
74
+ ## Return Value
75
+
76
+ ```json
77
+ {
78
+ "message_id": "om_xxx",
79
+ "chat_id": "oc_xxx",
80
+ "update_time": "1234567890"
81
+ }
82
+ ```
83
+
84
+ ## Common Mistakes
85
+
86
+ - Editing a message the calling identity did not send — the API rejects it.
87
+ - Using `--set-attachments` with `--text`. The attachment zone only exists on `post` messages; use `--markdown` or `--msg-type post`.
88
+ - Supplying only the files you want to keep, then losing the text. Editing replaces the entire content; pass the full new content (text + attachments) in one call.
89
+ - Assuming a body-only edit clears the attachment zone. It does not — without `--set-attachments` / `--clear-attachments` the existing attachments are preserved.
@@ -51,6 +51,14 @@ Each message contains:
51
51
  | `sender` | Sender information (includes `name`) |
52
52
  | `content` | Message content |
53
53
 
54
+ For `post` messages, the attachment zone (top-level `files` array) is rendered as trailing lines in `content`, one per attachment:
55
+
56
+ - `<file key="file_xxx" name="report.pdf"/>` — a file with a display name (same tag style as a standalone `file` message)
57
+ - `<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)
59
+
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`.
61
+
54
62
  ## Usage Scenarios
55
63
 
56
64
  ### Scenario 1: Fetch the full content of a specific message
@@ -187,6 +187,7 @@ lark-cli im +messages-reply --message-id om_xxx --msg-type interactive --content
187
187
  | `--video <path\|url\|key>` | One content option | Cwd-relative local video path, URL, or `file_key` (`file_xxx`); **must be used together with `--video-cover`** |
188
188
  | `--video-cover <path\|url\|key>` | **Required with `--video`** | Cwd-relative local cover image path, URL, or `image_key` (`img_xxx`) |
189
189
  | `--audio <path\|url\|key>` | One content option | Voice-message audio key, URL, or cwd-relative local path. Local paths and URLs must be Opus (`.opus` or Ogg Opus `.ogg`) |
190
+ | `--attachment <key>` | One content option | Repeatable bare file/folder key (`file_xxx`); merges into the post message's attachment zone. Requires a post message (`--markdown` or `--msg-type post`). Name/size/mime/is_folder are filled by the server from file service metadata, not taken from the client. Use this instead of `--file` when the file should render inside a rich-text message's attachment area |
190
191
  | `--reply-in-thread` | No | Reply inside the thread. The reply appears in the target message's thread instead of the main chat stream |
191
192
  | `--idempotency-key <key>` | No | Idempotency key, max 50 characters; the same key sends only one reply within 1 hour |
192
193
  | `--as <identity>` | No | Identity type: `bot` or `user` (default `bot`) |
@@ -206,6 +207,7 @@ lark-cli im +messages-reply --message-id om_xxx --msg-type interactive --content
206
207
  - Using `--content` without making the JSON match the effective `--msg-type`.
207
208
  - Explicitly setting `--msg-type` to something that conflicts with `--text`, `--markdown`, or media flags.
208
209
  - Mixing `--text`, `--markdown`, or `--content` with media flags in one command.
210
+ - Using `--attachment` with `--text` or a media flag. The attachment zone only exists on `post` messages — pair `--attachment` with `--markdown` or `--msg-type post`.
209
211
 
210
212
  ## Return Value
211
213
 
@@ -34,6 +34,7 @@ When using `--as user`, the message is sent as the authorized end user and requi
34
34
  | Send plain text exactly as written | `--text` | Preserves literal text; no Markdown conversion |
35
35
  | Precisely control the final payload | `--content` | You provide the exact JSON for `text` / `post` / `interactive` / `share_*` / media payloads |
36
36
  | Send image / file / video / audio | `--image` / `--file` / `--video` / `--audio` | Shortcut uploads URLs, or cwd-relative local files automatically |
37
+ | Attach files/folders to a post message's attachment zone | `--attachment` | Repeatable, as bare `file_key` (`file_xxx`); merges into the post content's `files` array. Requires a post message (`--markdown` or `--msg-type post`). Name/metadata are filled by the server, not the client |
37
38
 
38
39
  ### `--text` vs `--markdown`
39
40
 
@@ -190,12 +191,13 @@ lark-cli im +messages-send --chat-id oc_xxx --msg-type interactive --content '<c
190
191
  | `--video <path\|url\|key>` | One content option | Cwd-relative local video path, URL, or `file_key` (`file_xxx`). Local paths and URLs are uploaded automatically. **Must be paired with `--video-cover`** |
191
192
  | `--video-cover <path\|url\|key>` | **Required with `--video`** | Cwd-relative local cover image path, URL, or `image_key` (`img_xxx`). Local paths and URLs are uploaded automatically |
192
193
  | `--audio <path\|url\|key>` | One content option | Voice-message audio key, URL, or cwd-relative local path. Local paths and URLs must be Opus (`.opus` or Ogg Opus `.ogg`) |
194
+ | `--attachment <key>` | One content option | Repeatable bare file/folder key (`file_xxx`); merges into the post message's attachment zone. Requires a post message (`--markdown` or `--msg-type post`). Name/size/mime/is_folder are filled by the server from file service metadata, not taken from the client. Use this instead of `--file` when the file should render inside a rich-text message's attachment area |
193
195
  | `--msg-type <type>` | No | Message type (default `text`). If you use `--text` / `--markdown` / media flags, the effective type is inferred automatically. Explicitly setting a conflicting `--msg-type` fails validation |
194
196
  | `--idempotency-key <key>` | No | Idempotency key, max 50 characters; the same key sends only one message within 1 hour |
195
197
  | `--as <identity>` | No | Identity type: `bot` or `user` (default `bot`) |
196
198
  | `--dry-run` | No | Print the request only, do not execute it |
197
199
 
198
- > **Mutual exclusivity rule:** `--text`, `--markdown`, `--content`, and `--image`/`--file`/`--video`/`--audio` cannot be used together. Media flags are also mutually exclusive with each other.
200
+ > **Mutual exclusivity rule:** `--text`, `--markdown`, `--content`, and `--image`/`--file`/`--video`/`--audio` cannot be used together. Media flags are also mutually exclusive with each other. `--attachment` cannot be combined with a `--content` that already contains a `files` array (the attachment zone is declared either via `--content` or via `--attachment`, not both).
199
201
  >
200
202
  > **Video cover rule:** `--video` **must** be accompanied by `--video-cover`. Omitting `--video-cover` when using `--video` will fail validation. `--video-cover` cannot be used without `--video`.
201
203
 
@@ -209,13 +211,15 @@ lark-cli im +messages-send --chat-id oc_xxx --msg-type interactive --content '<c
209
211
  - Using `--content` without making the JSON match the effective `--msg-type`.
210
212
  - Explicitly setting `--msg-type` to something that conflicts with `--text`, `--markdown`, or media flags.
211
213
  - Mixing `--text`, `--markdown`, or `--content` with media flags in one command.
214
+ - Using `--attachment` with `--text` or a media flag. The attachment zone only exists on `post` messages — pair `--attachment` with `--markdown` or `--msg-type post`.
215
+ - Using `--file` when the file should sit inside a rich-text message's attachment area. `--file` sends a standalone `file`-type message; use `--attachment` (with `--markdown` or post `--content`) to attach files/folders inside a post message.
212
216
 
213
217
  ## `content` Format Reference
214
218
 
215
219
  | `msg_type` | Example `content` |
216
220
  |----------|-------------|
217
221
  | `text` | `{"text":"Hello <at user_id=\"ou_xxx\">name</at>"}` |
218
- | `post` | `{"zh_cn":{"title":"Title","content":[[{"tag":"text","text":"Body"}]]}}` |
222
+ | `post` | `{"zh_cn":{"title":"Title","content":[[{"tag":"text","text":"Body"}]]},"files":[{"key":"file_xxx"}]}` — the top-level `files` array is the attachment zone; each entry carries a file/folder `key` (name/metadata are backfilled by the server from file service metadata — a client-supplied `name` has no effect) |
219
223
  | `image` | `{"image_key":"img_xxx"}` |
220
224
  | `file` | `{"file_key":"file_xxx"}` |
221
225
  | `audio` | `{"file_key":"file_xxx"}` |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: lark-sheets
3
- version: 3.1.6
3
+ version: 3.1.8
4
4
  description: "飞书电子表格:创建和操作电子表格。支持创建表格、管理工作表与行列结构(增删/合并/调整尺寸/隐藏/冻结)、读写单元格(值/公式/样式/批注/单元格图片)、查找替换、多操作批量更新,以及图表、透视表、条件格式、筛选器、迷你图、浮动图片等对象的创建与维护。当用户需要创建电子表格、管理工作表、批量读写或编辑数据、统计汇总与可视化、表格美化、公式计算(含 Excel 公式迁移)、金融/财务建模(DCF、三张表、预算、Sensitivity 等)等任务时使用。若用户是想按名称或关键词搜索云空间(云盘/云存储)里的表格文件,请改用 lark-drive 的 drive +search 先定位资源。当用户给出 doubao.com 的 /sheets/ URL/token 时,也应直接使用本 skill,不要因为域名不是飞书而回退到 WebFetch;路由依据是 URL 路径模式和 token,而不是域名。"
5
5
  metadata:
6
6
  requires:
@@ -87,7 +87,7 @@ _公共:URL/token(无 sheet 定位) · 系统:`--dry-run`_
87
87
  | `--colors` | string + File + Stdin(简单 JSON) | optional | 下拉胶囊背景色,RGB hex 数组(如 `["#1FB6C1","#F006C2"]`)。长度可短不可长——超长 Validate 拦截(`--colors length (N) must not exceed dropdown source size (M)`),未指定项按内置 10 色色板循环补色。**单独传即生效**;`--highlight=false` 时被忽略。 |
88
88
  | `--multiple` | bool | optional | 启用多选 |
89
89
  | `--highlight` | bool | optional | 下拉胶囊背景色高亮开关。**不传 = 开**(按内置 10 色色板循环上色);`--highlight=false` 关闭得到纯白下拉。配色用 `--colors` 覆盖。 |
90
- | `--source-range` | string | xor | listFromRange 模式的下拉源 range,A1 表示法 + sheet 前缀(如 `'Sheet1'!T1:T3`)。映射到 server `data_validation.range`,搭配 server `data_validation.type='listFromRange'` 自动生效。跟 `--options` 二选一:传 `--options` 走 inline 列表(type=list),传本 flag 走 range 引用(type=listFromRange)。`--colors` 长度规则不变(≤ 源 range 单元格数),`--highlight` / `--multiple` 行为相同。当 `--highlight` 开启且 source 覆盖单元格数超过 2000 时,服务端会将该下拉判为 option-error(这是不支持的组合);CLI 会向 stderr 输出 warning。如需取消,传 `--highlight=false`。 |
90
+ | `--source-range` | string | xor | listFromRange 模式的下拉源 range,A1 表示法 + sheet 前缀(如 `'Sheet1'!T1:T3`)。映射到 server `data_validation.range`,搭配 server `data_validation.type='listFromRange'` 自动生效。跟 `--options` 二选一:传 `--options` 走 inline 列表(type=list),传本 flag 走 range 引用(type=listFromRange)。`--colors` 长度规则不变(≤ 源 range 单元格数),`--highlight` / `--multiple` 行为相同。当 `--highlight` 开启且 source 覆盖单元格数超过 2000 时,服务端会将该下拉判为 option-error(这是不支持的组合);CLI 会在返回结果的 `data.warnings` 中给出 warning。如需取消,传 `--highlight=false`。 |
91
91
 
92
92
  ### `+dropdown-delete`
93
93
 
@@ -18,18 +18,20 @@
18
18
 
19
19
  ## 使用场景
20
20
 
21
- 读写条件格式对象。本 reference 覆盖 4 个 shortcut:
21
+ 读写条件格式对象,并读取条件格式**计算后的单元格样式结果**。本 reference 覆盖这些 shortcut:
22
22
 
23
23
  | 操作需求 | 使用工具 | 说明 |
24
24
  |---------|---------|------|
25
- | 查看已有条件格式 | `+cond-format-list` | 获取规则类型、范围和样式配置 |
26
- | 创建/更新/删除条件格式 | `+cond-format-{create|update|delete}` | 对条件格式规则执行写入操作 |
25
+ | 查看已有条件格式规则 | `+cond-format-list` | 获取规则类型、范围和样式配置;用于确认规则对象已存在 |
26
+ | 创建/更新/删除条件格式规则 | `+cond-format-create` / `+cond-format-update` / `+cond-format-delete` | 对条件格式规则执行写入操作 |
27
+ | 验证条件格式计算结果 | `+cond-format-result-get` | 读取命中后的 `cell_styles`,确认条件格式是否真的作用到哨兵单元格 |
28
+ | 常规读数时临时带上条件格式 | `+cells-get --include conditional_format` | 与 `+cond-format-result-get` 等价地合并条件格式样式,但仍归属普通单元格读取入口 |
27
29
 
28
- 典型工作流:先读取现有条件格式了解配置 → 执行创建/更新/删除 → **必须再次读取验证结果**。
30
+ 典型工作流:先读取现有条件格式了解配置 → 执行创建/更新/删除 → **必须先用 `+cond-format-list` 验证规则对象,再用 `+cond-format-result-get` 抽查计算结果**。
29
31
 
30
32
  **常见配置错误(必须注意)**:
31
- - **创建后必须验证**:条件格式创建后必须调用 `+cond-format-list` 验证规则是否生效。如果验证发现规则未生效或配置不正确,应立即修复并重试
32
- - **验证要覆盖哨兵格**:不要只确认规则对象存在;还要按用户规则抽查 2-3 个应命中的单元格/行(含边界行、空值、重复值、非图例状态),确认公式、范围、颜色语义能解释这些哨兵。若规则存在但哨兵颜色/命中逻辑不对,继续修正
33
+ - **创建后必须两段验证**:条件格式创建后先调用 `+cond-format-list` 验证规则对象(rule_type / ranges / style / attrs)是否存在且配置正确;再调用 `+cond-format-result-get --range "<哨兵范围>"` 读取命中后的 `cell_styles`,验证条件格式是否真的按计算结果作用到单元格。如果任一阶段不符合预期,应立即修复并重试
34
+ - **验证要覆盖哨兵格**:不要只确认规则对象存在;还要按用户规则抽查 2-3 个应命中 / 不应命中的单元格/行(含边界行、空值、重复值、非图例状态),用 `+cond-format-result-get` 读取 `cell_styles.background_color` / `font_color` / `font_weight` 等结果,确认公式、范围、颜色语义能解释这些哨兵。若规则存在但哨兵样式/命中逻辑不对,继续修正
33
35
  - **范围要精确**:条件格式的应用范围必须精确覆盖用户指定的列/行,不要遗漏
34
36
  - **`style.back_color` vs `style.fore_color` 的中文语义**:用户中文语境下的"**标红/染色/标记**"指**单元格背景色**,用 `back_color`;"**文字红/字体红/把字变红**"才用 `fore_color`。默认无说明时选 `back_color`。用户说"**标红**"用标准红 `back_color: "#FF0000"`;说"**高亮/突出**"才用浅色底(如 `#FFE6E6`)配合可选的 `fore_color` 加深字体——把"标红"做成浅粉会被认为没按要求标色
35
37
  - **日期/空值比较必须防空**:用户说"过期的标红"时,除了 `TODAY()`,公式必须排除空单元格,否则空白格也会被误判为"早于今天"而全表标红。正确公式:`=AND(E1<>"", E1<=TODAY())`;错误公式:`=E1<=TODAY()`(空值会被当作 0 判为过期)
@@ -79,6 +81,7 @@ Step 2: 基于辅助列值做条件格式(用 cellIs 或引用辅助列的 exp
79
81
  | Shortcut | Risk | 分组 |
80
82
  | --- | --- | --- |
81
83
  | `+cond-format-list` | read | 对象 |
84
+ | `+cond-format-result-get` | read | 对象 |
82
85
  | `+cond-format-create` | write | 对象 |
83
86
  | `+cond-format-update` | write | 对象 |
84
87
  | `+cond-format-delete` | high-risk-write | 对象 |
@@ -93,6 +96,15 @@ _公共四件套 · 系统:`--dry-run`_
93
96
  | --- | --- | --- | --- |
94
97
  | `--rule-id` | string | optional | 按规则 id 过滤 |
95
98
 
99
+ ### `+cond-format-result-get`
100
+
101
+ _公共四件套 · 系统:`--dry-run`_
102
+
103
+ | Flag | Type | 必填 | 说明 |
104
+ | --- | --- | --- | --- |
105
+ | `--range` | string | required | A1 范围,如 `A1:F10`(不带 sheet 前缀;用 `--sheet-id` / `--sheet-name` 指定 sheet) |
106
+ | `--max-chars` | int | optional | 单次返回字符上限,默认 500000(兜底防爆) |
107
+
96
108
  ### `+cond-format-create`
97
109
 
98
110
  _公共四件套 · 系统:`--dry-run`_
@@ -162,6 +174,29 @@ lark-cli sheets +cond-format-create --url "..." --sheet-id "$SID" \
162
174
  lark-cli sheets +cond-format-create --url "..." --sheet-id "$SID" \
163
175
  --rule-type dataBar --ranges '["B2:B100"]' \
164
176
  --properties @rule.json
177
+
178
+ # 创建后先确认规则对象存在
179
+ lark-cli sheets +cond-format-list --url "..." --sheet-id "$SID"
180
+
181
+ # 再抽查条件格式计算结果:读取哨兵单元格的命中样式
182
+ lark-cli sheets +cond-format-result-get --url "..." --sheet-id "$SID" \
183
+ --range "B2:B10"
184
+ ```
185
+
186
+ ### `+cond-format-result-get`
187
+
188
+ 用于读取条件格式**计算后的样式结果**,不是读取规则对象。创建 / 更新条件格式后必须用它抽查哨兵单元格。
189
+
190
+ CLI 会对白名单字段做输出裁剪:顶层只保留警告、分页和返回单元格计数;每个 range 只保留请求/实际范围、真实行列坐标、截断标记和二维 `cells`;每个 cell 只保留 `cell_styles`,不返回 `value` / `formula` / `note` / `data_validation` / `border_styles` 等其它单元格数据。`cell_styles` 是底层开启条件格式计算后得到的最终合并样式,不包含 `rule_id` 或独立的命中标记。
191
+
192
+ ```bash
193
+ # 读取 B2:B10 的条件格式命中样式,返回 cell_styles.background_color / font_color 等
194
+ lark-cli sheets +cond-format-result-get --url "..." --sheet-id "$SID" \
195
+ --range "B2:B10"
196
+
197
+ # 如果只想在普通读取里临时合并条件格式,也可用 +cells-get --include conditional_format
198
+ lark-cli sheets +cells-get --url "..." --sheet-id "$SID" \
199
+ --range "B2:B10" --include conditional_format
165
200
  ```
166
201
 
167
202
  ### `+cond-format-update`
@@ -180,4 +215,4 @@ lark-cli sheets +cond-format-delete --url "..." --sheet-id "$SID" --rule-id "$RU
180
215
 
181
216
  - `Validate`:XOR 公共四件套;`--rule-type` / `--ranges` 必填;`--properties` 必须能解析为合法 JSON;按 `--rule-type` 检查必填子字段(`cellIs` 需 `attrs.operator` + `attrs.value`、`expression` 需 `attrs.formula`、`colorScale` 需 `min/mid/max` 配色等);`+cond-format-delete` 强制 `--yes` 或 `--dry-run`。
182
217
  - `DryRun`:写操作输出"将要 POST/PATCH/DELETE 的 conditional_format 请求模板"。
183
- - `Execute`:写后不自动回读;如需确认,自行调用 `+cond-format-list --rule-id <id>` 比对规则 / 范围 / 样式。
218
+ - `Execute`:写后不自动回读;必须自行调用 `+cond-format-list --rule-id <id>` 比对规则 / 范围 / 样式,并用 `+cond-format-result-get --range <哨兵范围>` 验证实际计算后的单元格样式。
@@ -165,7 +165,7 @@ _公共四件套 · 系统:`--dry-run`_
165
165
  | Flag | Type | 必填 | 说明 |
166
166
  | --- | --- | --- | --- |
167
167
  | `--range` | string | required | A1 范围,如 `A1:F10`(不带 sheet 前缀;用 `--sheet-id` / `--sheet-name` 指定 sheet) |
168
- | `--include` | string_slice | optional | 要返回的信息类别,逗号分隔多个。`truncation` 会额外按行高列宽 / 字号 / 自动换行估算每个单元格是否被截断显示,返回 `isRowTruncated` / `isColTruncated`(有额外计算开销,仅排版检查 / 调整行高列宽前才开)(可选值:`value` / `formula` / `style` / `comment` / `data_validation` / `truncation`) |
168
+ | `--include` | string_slice | optional | 要返回的信息类别,逗号分隔多个。`truncation` 会额外按行高列宽 / 字号 / 自动换行估算每个单元格是否被截断显示,返回 `isRowTruncated` / `isColTruncated`(有额外计算开销,仅排版检查 / 调整行高列宽前才开)(可选值:`value` / `formula` / `style` / `comment` / `data_validation` / `conditional_format` / `truncation`) |
169
169
  | `--max-chars` | int | optional | 单次返回字符上限,默认 500000(兜底防爆)。要整表无截断直接用 --output-path 落盘(上限自动放宽到 2000 万字符——读取链路非流式,此上限是内存保护;更大就显式给 --max-chars);仅当要让结果直接进上下文、又不落盘时才调小(如 25000),按 has_more 分页。 传 0 表示「不自设上限」,等价于不传(仍是 500000 / 落盘时 2000 万),不会退回底层工具那个更小的默认截断。 |
170
170
  | `--output-path` | string | optional | 把完整读取结果写入本地路径(如 `./out.json`),文件内容为 data 载荷的 JSON;stdout 只回一个含 output_path/字节数的确认信息。**一旦设置,字符上限自动放宽到有界的 2000 万字符**(覆盖 --max-chars 默认),并非无限——读取链路非流式,该上限是内存保护;显式 --max-chars 优先。stdout 回执带 `complete` 字段(命中上限时另有 `truncated` 与提示),据此判断文件是否完整,不要默认整表已落全。省略时按常规把结果打到 stdout。 |
171
171
  | `--skip-hidden` | bool | optional | 跳过隐藏行列,默认 `false` |
@@ -321,7 +321,7 @@ _公共四件套 · 系统:`--dry-run`_
321
321
  | `--colors` | string + File + Stdin(简单 JSON) | optional | 下拉胶囊背景色,RGB hex 数组(如 `["#1FB6C1","#F006C2"]`)。长度可短不可长——超长 Validate 拦截(`--colors length (N) must not exceed dropdown source size (M)`),未指定项按内置 10 色色板循环补色。**单独传即生效**;`--highlight=false` 时被忽略。 |
322
322
  | `--multiple` | bool | optional | 启用多选;默认 `false` |
323
323
  | `--highlight` | bool | optional | 下拉胶囊背景色高亮开关。**不传 = 开**(按内置 10 色色板循环上色);`--highlight=false` 关闭得到纯白下拉。配色用 `--colors` 覆盖。 |
324
- | `--source-range` | string | xor | listFromRange 模式的下拉源 range,A1 表示法 + sheet 前缀(如 `'Sheet1'!T1:T3`)。映射到 server `data_validation.range`,搭配 server `data_validation.type='listFromRange'` 自动生效。跟 `--options` 二选一:传 `--options` 走 inline 列表(type=list),传本 flag 走 range 引用(type=listFromRange)。`--colors` 长度规则不变(≤ 源 range 单元格数),`--highlight` / `--multiple` 行为相同。当 `--highlight` 开启且 source 覆盖单元格数超过 2000 时,服务端会将该下拉判为 option-error(这是不支持的组合);CLI 会向 stderr 输出 warning。如需取消,传 `--highlight=false`。 |
324
+ | `--source-range` | string | xor | listFromRange 模式的下拉源 range,A1 表示法 + sheet 前缀(如 `'Sheet1'!T1:T3`)。映射到 server `data_validation.range`,搭配 server `data_validation.type='listFromRange'` 自动生效。跟 `--options` 二选一:传 `--options` 走 inline 列表(type=list),传本 flag 走 range 引用(type=listFromRange)。`--colors` 长度规则不变(≤ 源 range 单元格数),`--highlight` / `--multiple` 行为相同。当 `--highlight` 开启且 source 覆盖单元格数超过 2000 时,服务端会将该下拉判为 option-error(这是不支持的组合);CLI 会在返回结果的 `data.warnings` 中给出 warning。如需取消,传 `--highlight=false`。 |
325
325
 
326
326
  ### `+csv-put`
327
327