Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/docs/tools/feishu-channel.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pip install lark-oapi
- `TOOL_FEISHU_CHANNEL_APP_ID`
- `TOOL_FEISHU_CHANNEL_APP_SECRET`
- `TOOL_FEISHU_CHANNEL_TRANSPORT`,默认 `ws`
- `TOOL_FEISHU_CHANNEL_STREAMING`,是否开启流式输出,默认 `false`
- `TOOL_FEISHU_CHANNEL_REACTIONS`,是否在收到消息时回复“收到”表情,默认 `false`

或在 `config.yaml` 中配置:

Expand All @@ -39,6 +41,7 @@ tool:
app_secret: xxx
transport: ws
streaming: true
reactions: true
```

## 最小示例
Expand Down
44 changes: 44 additions & 0 deletions veadk/extensions/feishu_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ class FeishuMessageContext:
text: str


FEISHU_EMOJI_ONE_SECOND = "OneSecond"


class FeishuChannelExtension:
"""Bridge a Feishu bot channel with a VeADK runner.

Expand All @@ -85,6 +88,7 @@ def __init__(
ignore_empty_messages: bool = True,
channel_kwargs: dict[str, Any] | None = None,
streaming: bool = False,
reactions: bool = False,
) -> None:
self.runner = runner
self.session_id_factory = session_id_factory or self.default_session_id_factory
Expand All @@ -93,6 +97,10 @@ def __init__(
self.response_formatter = response_formatter or self.default_response_formatter
self.reply_in_thread = reply_in_thread
self.ignore_empty_messages = ignore_empty_messages
self.reactions = (
reactions
or str(os.getenv("TOOL_FEISHU_CHANNEL_REACTIONS", "")).lower() == "true"
)
self.streaming = (
streaming
or str(os.getenv("TOOL_FEISHU_CHANNEL_STREAMING", "")).lower() == "true"
Expand Down Expand Up @@ -172,6 +180,42 @@ async def _on_message(self, message: Any) -> None:

context = self.build_message_context(message=message, text=text)

if self.reactions and context.message_id:
try:
import lark_oapi.api.im.v1 as lark_im

emoji = (
lark_im.Emoji.builder().emoji_type(FEISHU_EMOJI_ONE_SECOND).build()
)
request = (
lark_im.CreateMessageReactionRequest.builder()
.message_id(context.message_id)
.request_body(
lark_im.CreateMessageReactionRequestBody.builder()
.reaction_type(emoji)
.build()
)
.build()
)

if hasattr(self.channel, "client"):
response = await self._maybe_await(
self.channel.client.im.v1.message_reaction.create(request)
)

if not response.success():
logger.error(
f"Failed to add reaction to message {context.message_id}: {response.code} {response.msg}"
)
else:
logger.warning(
"Channel has no client attribute, cannot send reaction"
)
except Exception as e:
logger.error(
f"Failed to add reaction to message {context.message_id}: {e}"
)

send_options = {}
if self.reply_in_thread and context.message_id:
send_options["reply_to"] = context.message_id
Expand Down
Loading