Skip to content

feat(im): add strict Feishu image send path#456

Open
xfcycc wants to merge 1 commit into
larksuite:mainfrom
xfcycc:feat/strict-feishu-image-send
Open

feat(im): add strict Feishu image send path#456
xfcycc wants to merge 1 commit into
larksuite:mainfrom
xfcycc:feat/strict-feishu-image-send

Conversation

@xfcycc
Copy link
Copy Markdown

@xfcycc xfcycc commented Apr 30, 2026

Summary

Add a strict Feishu image-message path for cases where an agent must send an actual IM image instead of a card image, text link, or file fallback.

Feishu's documented image delivery flow is two-step:

  1. upload the image with image_type=message to get an image_key
  2. send or reply with msg_type=image and content={"image_key":"..."}

This PR exposes that path as a dedicated bot tool and only reports success after Feishu returns a real message_id for the image message.

What changed

  • Added uploadAndSendImageLark, a strict upload-then-send helper that:
    • fetches local or remote image bytes through the existing media loader and SSRF/local-root checks
    • validates image size, format, and dimensions before upload
    • uploads with image_type=message
    • sends msg_type=image with the returned image_key
    • fails if Feishu returns a non-zero code or omits message_id
  • Added feishu_im_bot_send_image as a new bot-identity IM tool in src/tools/tat/im/send-image.ts.
  • Kept the existing feishu_im_bot_image download tool unchanged; the new send tool is registered separately from src/tools/tat/im/index.ts.
  • Documented agent routing in skills/feishu-channel-rules/SKILL.md so image sends use the strict image tool instead of card/markdown embedding.
  • Added tests covering successful strict image sends, non-image rejection before upload, and missing message_id failures.

Why

The generic media path can fall back to sending a text link when upload fails. That behavior is useful for best-effort delivery, but it makes ok=true ambiguous for tasks that require the recipient to actually see an image message.

This PR adds a separate strict path for those cases:

  • no text-link fallback
  • no file fallback for images that should be image messages
  • no fabricated card img_key values
  • no URL placed directly in image_key

Security and permissions

  • Uses bot identity / tenant token, not user OAuth.
  • Requires the existing bot-side capabilities used by the plugin: im:resource for image upload and im:message:send_as_bot / message send permission for delivery.
  • Local file access is fixed to /tmp/openclaw; the agent cannot pass a custom local_roots value through the tool.
  • Remote URLs continue through the shared SSRF protection before fetch.
  • Tool description explicitly restricts use to a user-requested send where the destination is the current conversation or explicitly provided by the user.

Testing

After rebasing onto latest main (bfb0ff7):

  • pnpm test -- tests/media-image-send.test.ts — 21 files / 171 tests passed
  • pnpm exec eslint src/messaging/outbound/media.ts src/tools/tat/im/send-image.ts tests/media-image-send.test.ts index.ts
  • pnpm build
  • git diff --check
  • Real Feishu smoke tests:
    • sent two PNG images to the current group through the installed Feishu media path
    • sent one PNG image through a local build of uploadAndSendImageLark before the file-split refactor, returning a real Feishu message id
    • sent one PNG image through a media-only bundle after the file-split refactor, returning messageId=om_x100b501ba09c4888c3205f456e16391 and detected png 640x320

Notes

pnpm typecheck still fails on baseline issues unrelated to this PR:

  • openclaw/plugin-sdk/zalouser is not exported by the installed openclaw package
  • src/messaging/inbound/handler.ts has existing implicit any parameters
  • src/messaging/outbound/actions.ts still advertises cards in capabilities, while the installed SDK type only accepts presentation / delivery-pin
  • latest main adds src/tools/oapi/task/task.ts, where agent_task_status is not recognized by the installed SDK type

- add uploadAndSendImageLark for Feishu upload-then-send image delivery

- register feishu_im_bot_send_image with fixed /tmp/openclaw local access

- validate image format, size, dimensions, and successful message_id responses

- document agent usage and cover strict image sends with tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant