Commit Graph

5 Commits

Author SHA1 Message Date
Hua Audio 0f395ce110 Refactor/asr tts (#1939)
* refactor: update ASR and TTS implementations

* fix lint

* Integrating asr/tts models w/ new security config

* update documents

* add arbitrary whisper transcriptor support

* update documents

* fix lint

* add mimo tts
2026-04-01 12:21:21 +08:00
ywj 009a8d702b Feat/feishu card parsing (#1534)
* feat(feishu): add interactive card message parsing

Add support for parsing inbound Feishu interactive card messages.
When a user sends a card message, the text content is now extracted
and passed to the LLM for processing.

- Add extractCardText() to recursively extract text from card JSON
- Support both JSON 1.0 (legacy) and JSON 2.0 schema formats
- Handle nested elements: header, body, actions, columns
- Extract text from markdown, lark_md, and plain_text elements
- Add comprehensive unit tests for card parsing

Fixes #<issue_number>

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>

* feat(feishu): extract and download images from interactive cards

When receiving interactive card messages, extract embedded images
(img_key, src, icon_key) and download them for LLM processing.

- Add extractCardImageKeys() to recursively extract image keys from card JSON
- Support img elements (img_key, src) and icon elements (icon_key)
- Update downloadInboundMedia() to handle MsgTypeInteractive
- Add comprehensive unit tests for image extraction

Images are downloaded and stored via MediaStore, then appended to
the message content as [image: photo] tags for LLM visibility.

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>

* fix(feishu): simplify card parsing - pass raw JSON, only extract images

Address review feedback: text extraction cannot exhaustively handle all
card formats (i18n_elements, div.fields, etc.). Pass raw JSON to LLM
instead - same approach as MsgTypePost. Only image extraction remains
as images must be downloaded for LLM to process.

- Remove extractCardText() and helper functions
- extractContent() now returns raw JSON for MsgTypeInteractive
- Keep extractCardImageKeys() for downloading embedded images
- Update tests to expect raw JSON for interactive cards

* fix(feishu): don't append media tags to interactive card JSON

Appending media tags like "[attachment]" to raw JSON content produces
invalid JSON format. For interactive cards, the JSON already contains
image information and media refs are downloaded separately.

- Skip appendMediaTags for MsgTypeInteractive to preserve valid JSON
- Add test case for interactive card with images

* fix(feishu): filter out external URLs from card image extraction

Only Feishu-hosted image keys (img_xxx, icon_xxx) can be downloaded via
the Feishu API. External URLs in src field (https://...) should be
filtered out to avoid download failures.

- Add isFeishuImageKey() to detect Feishu-hosted keys vs external URLs
- Update extractImageKeysRecursive to skip external URLs in src field
- Add tests for external URL filtering and mixed scenarios

* feat(feishu): support downloading external images from interactive cards

Previously only Feishu-hosted images (img_key, icon_key) could be
downloaded. Now external URLs in src field are also downloaded via
HTTP and made available to the LLM.

- extractCardImageKeys now returns two slices: Feishu keys and external URLs
- Add downloadExternalImage to download images from HTTP URLs
- Update downloadInboundMedia to handle both Feishu API and HTTP downloads
- Update tests for new function signature

* fix(feishu): use HTTP client with timeout for external image downloads

Replaced http.DefaultClient with a client that has a 30-second timeout
to prevent hanging on unresponsive external URLs.

Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>

* fix(feishu): resolve lint errors for shadow and formatting

- Rename err variables to avoid shadowing in downloadExternalImage
- Fix struct field alignment in TestExtractCardImageKeys

Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>

* refactor(feishu): pass external image URLs to LLM instead of downloading

Instead of downloading external images from interactive cards, pass
the URLs directly to LLM. This reduces network overhead and lets
vision-capable models fetch images as needed.

- Remove downloadExternalImage function
- Append external URLs to card content for LLM processing
- Only download Feishu-hosted images via API

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>

* fix(feishu): add blank line between functions for gci formatting

* fix(feishu): keep interactive card content as valid JSON
2026-03-20 12:59:43 +08:00
Hoshina fa1cb9cc74 fix(feishu): address PR #1000 review comments from @xiaket
- Consolidate extractImageKey/extractFileKey/extractFileName into shared
  extractJSONStringField helper to reduce code duplication
- Move mentionPlaceholderRegex to package-level position after imports
- Rename feishuCfg field to config for clarity within FeishuChannel
- Replace @_user_1 heuristic with GET /open-apis/bot/v3/info API call
  at startup for reliable bot @mention detection
- Fix double close on file handle in downloadResource by removing defer
  and using explicit close in both success and error paths
- Add unit tests for common.go and feishu_64.go helpers (53 test cases)
2026-03-03 16:44:24 +08:00
Hoshina c9fb681f3b feat(feishu): enhance channel with markdown cards, media, mentions, and editing
Upgrade the Feishu channel from basic text-only to full feature parity with
Telegram/Discord: interactive card messages with markdown rendering, message
editing (MessageEditor), placeholder messages (PlaceholderCapable), emoji
reactions (ReactionCapable), and inbound/outbound media support (MediaSender).

Also add @mention detection with lazy bot open_id discovery, group trigger
filtering with mention awareness, and multi-type inbound message parsing
(text, post, image, file, audio, video).
2026-03-03 00:49:32 +08:00
Hoshina 6122ab664b refactor(channels): add channel subpackages and update gateway imports 2026-02-20 23:25:44 +08:00