Files
xuzhigang 1181dafc76 feat(im): support rich-text message attachment zone in send/reply/mge… (#2515)
* feat(im): support rich-text message attachment zone in send/reply/mget/edit

Support the post message attachment zone (top-level files array) end to end:
- +messages-send / +messages-reply: repeatable --attachment file_key flags
  merged into the post content's files array (deduplicated).
- +messages-mget: render attachment-zone files/folders as <file>/<folder>
  tags in content, extract file keys for --download-resources.
- +messages-edit: new shortcut (PUT /open-apis/im/v1/messages/:id) with
  --set-attachments / --clear-attachments; body-only edits preserve the
  attachment zone by default.
- Attachment flags are mutually exclusive with --content carrying a files
  array (declare the zone via one or the other, not both).
- bot-only identity, matching server behavior (user token rejected).
- Fixes from review: attachments no longer bypass content mutual-exclusion
  validation (P1); merge dedups by key.
- Docs (SKILL.md, references, affordance) and unit tests updated.

* fix(im): address design-review findings (auto-infer post, dedup set, doc routing)

- --attachment/--set-attachments/--clear-attachments now infer msg_type=post
  automatically; only an explicit incompatible --msg-type conflicts.
  --text is rejected with attachments (text is a standalone message, not a
  post body) with a hint to use --markdown or --content.
- --set-attachments deduplicates repeated keys (docs promised this; the
  replace helper now enforces it).
- Shortcut Description no longer leaks the HTTP path or the raw server
  error phrase; it describes the command semantically.
- affordance/im.md +messages-edit now routes WHEN: interactive cards go to
  messages.patch, corrected messages go to +messages-send, and attachment
  tri-state tips are listed.
- mget doc no longer claims --format json exposes raw wire fields (the
  output is the rendered content); download eligibility clarified.
2026-08-28 16:55:28 +08:00
..

Affordance

Per-command usage guidance for the CLI, authored as one markdown file per domain (<service>.md). It is surfaced in lark-cli <command> --help and in the schema output, and read directly at runtime (lazy, cached) — there is no build step. Maintain these files alongside skills/ and shortcuts/.

Format

A small, fixed markdown subset; each file describes one domain:

# <domain>            optional `> skill: <name>` applies to every command below
## Skills             optional bullets shown on the business-domain help;
                      merged after `> skill:` and not inherited by commands
## <command>          the command as typed, minus `lark-cli <domain>`; a
                      +-prefixed heading (## +create) targets that shortcut
<lead paragraph>      when to use this command
### Avoid when        when not to use it / which command to use instead
### Prerequisites     what you must have first (e.g. an id, and where it comes from)
### Tips              gotchas and constraints
### Examples          **description** lines, each followed by a fenced command
### Skills            bullet skill names, or name/relpath references
                      (lark-contact/references/x.md), to read for usage;
                      merged with the domain `> skill:` default (deduped,
                      domain first)
### <other heading>   a custom section; flows through verbatim

Reference another command with [[command]] — it renders as command in help. Under Avoid when it means "use that one instead"; under Prerequisites ("… from command") it means "get the input there first".

Both service-API commands (## messages get) and +-prefixed shortcuts (## +create) take entries. A ### Skills entry is a skill name (validated against <name>/SKILL.md) or a name/relpath reference into that skill (validated against the path); help drops any that don't resolve, so a typo shows nothing. Point a command at its own reference (e.g. +search-userlark-contact/references/lark-contact-search-user.md) rather than re-listing the domain skill, which the > skill: default already covers. When a shortcut also sets a hand-authored Tips list in Go, the overlay's ### Tips win — they replace the Go tips (not merged), so keep tips in one place.

The reserved domain-level ## Skills section controls the skill pointers on lark-cli <domain> --help. Its entries use the same name or name/relpath format and existence gating as command-level ### Skills. The canonical > skill: is shown first automatically; additional domain entries are display-only and do not become defaults for every command. If ## Skills is absent, the existing single domain guide behavior is unchanged.

Example

## messages get
Fetch the full content of a single message by id.

### Avoid when
- Reading several at once → use [[messages batch_get]]

### Prerequisites
- message_id from [[messages list]]

### Examples

**Fetch one message**
```bash
lark-cli mail user_mailbox.messages get --message-id "<id>"
```

Notes

  • Write plain prose; the only convention is wrapping command references in [[ ]].
  • Treat the lead as decision context, not a second command description. The shortcut or method description stays canonical; omit the lead when it would only restate that description.
  • Keep it concise and high-signal — don't restate field/flag names, id types, or anything the schema and flags already show; the agent infers the rest.
  • Command-form headings resolve to method ids via the registry, so plural resource names (messages) map to the singular method id (message) automatically. +-prefixed shortcut headings are matched verbatim (no plural/space folding), so the heading must equal the shortcut command exactly (## +history-revert).