* feat(wecom): handle inbound file messages over HTTP callback
Parse MsgType=file (FileName + MediaId), download via media/get API,
and forward as core.FileAttachment for agents. Add MIME inference helper
and unit tests. Document inbound capabilities in config.example.toml.
WebSocket AI bot mode unchanged; file receive there depends on WeChat policy.
* chore(wecom): add Info/Warn logs for callback diagnostics
Log every POST (size, query flags), parsed msg_type/msg_id/from_user,
duplicate/old/allow_from drops, unsupported types at Warn, and Debug
preview of decrypted XML (truncated). Helps trace missing file pushes.
* feat(wecom-ws): receive image, file, mixed and quote media over AI bot WebSocket
Parse msgtype image/file/mixed and quote (text, voice, image, file, mixed)
per WeCom smart-bot protocol. Download encrypted media from signed URLs
and decrypt with AES-256-CBC (IV = first 16 bytes of base64 key), matching
@wecom/aibot-node-sdk. Voice accepts both content and legacy text fields.
Adds wsCollectInboundParts, deliverWSMediaInbound, unit tests for collect,
Content-Disposition parsing, and round-trip decryption.
* fix(wecom-ws): handle file in mixed payloads and normalize aeskey decoding
- Collect file items inside mixed.msg_item and merge top-level file/image
when msgtype is file/image but a non-empty mixed block is also present.
- decodeWeComAESKey: trim whitespace, URL-safe base64, padding, optional hex.
- Add regression tests for mixed+file and aeskey variants.
* fix: satisfy golangci-lint (gosimple, staticcheck)
- wecom: use := for walkMixed/walkQuote closures (S1021).
- engine: drop unused assignment from sessions.NewSession in cmdNew (SA4006).
---------
Co-authored-by: Claude <noreply@anthropic.com>