fix(feishu): support Lark private chats as direct messages (openclaw#31400) thanks @stakeswky
Verified: - pnpm test -- extensions/feishu/src/bot.checkBotMentioned.test.ts - pnpm build - pnpm check (blocked by unrelated baseline lint errors in untouched files) - pnpm test:macmini (not run after pnpm check blocked) Co-authored-by: stakeswky <64798754+stakeswky@users.noreply.github.com> Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
@@ -28,6 +28,7 @@ Docs: https://docs.openclaw.ai
|
|||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
|
- Feishu/Lark private DM routing: treat inbound `chat_type: "private"` as direct-message context for pairing/mention-forward/reaction synthetic handling so Lark private chats behave like Feishu p2p DMs. (#31400) Thanks @stakeswky.
|
||||||
- Sandbox/workspace mount permissions: make primary `/workspace` bind mounts read-only whenever `workspaceAccess` is not `rw` (including `none`) across both core sandbox container and sandbox browser create flows. (#32227) Thanks @guanyu-zhang.
|
- Sandbox/workspace mount permissions: make primary `/workspace` bind mounts read-only whenever `workspaceAccess` is not `rw` (including `none`) across both core sandbox container and sandbox browser create flows. (#32227) Thanks @guanyu-zhang.
|
||||||
- Signal/message actions: allow `react` to fall back to `toolContext.currentMessageId` when `messageId` is omitted, matching Telegram behavior and unblocking agent-initiated reactions on inbound turns. (#32217) Thanks @dunamismax.
|
- Signal/message actions: allow `react` to fall back to `toolContext.currentMessageId` when `messageId` is omitted, matching Telegram behavior and unblocking agent-initiated reactions on inbound turns. (#32217) Thanks @dunamismax.
|
||||||
- Gateway/OpenAI chat completions: honor `x-openclaw-message-channel` when building `agentCommand` input for `/v1/chat/completions`, preserving caller channel identity instead of forcing `webchat`. (#30462) Thanks @bmendonca3.
|
- Gateway/OpenAI chat completions: honor `x-openclaw-message-channel` when building `agentCommand` input for `/v1/chat/completions`, preserving caller channel identity instead of forcing `webchat`. (#30462) Thanks @bmendonca3.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { parseFeishuMessageEvent } from "./bot.js";
|
|||||||
|
|
||||||
// Helper to build a minimal FeishuMessageEvent for testing
|
// Helper to build a minimal FeishuMessageEvent for testing
|
||||||
function makeEvent(
|
function makeEvent(
|
||||||
chatType: "p2p" | "group",
|
chatType: "p2p" | "group" | "private",
|
||||||
mentions?: Array<{ key: string; name: string; id: { open_id?: string } }>,
|
mentions?: Array<{ key: string; name: string; id: { open_id?: string } }>,
|
||||||
text = "hello",
|
text = "hello",
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ export type FeishuMessageEvent = {
|
|||||||
root_id?: string;
|
root_id?: string;
|
||||||
parent_id?: string;
|
parent_id?: string;
|
||||||
chat_id: string;
|
chat_id: string;
|
||||||
chat_type: "p2p" | "group";
|
chat_type: "p2p" | "group" | "private";
|
||||||
message_type: string;
|
message_type: string;
|
||||||
content: string;
|
content: string;
|
||||||
create_time?: string;
|
create_time?: string;
|
||||||
@@ -709,6 +709,7 @@ export async function handleFeishuMessage(params: {
|
|||||||
|
|
||||||
let ctx = parseFeishuMessageEvent(event, botOpenId);
|
let ctx = parseFeishuMessageEvent(event, botOpenId);
|
||||||
const isGroup = ctx.chatType === "group";
|
const isGroup = ctx.chatType === "group";
|
||||||
|
const isDirect = !isGroup;
|
||||||
const senderUserId = event.sender.sender_id.user_id?.trim() || undefined;
|
const senderUserId = event.sender.sender_id.user_id?.trim() || undefined;
|
||||||
|
|
||||||
// Handle merge_forward messages: fetch full message via API then expand sub-messages
|
// Handle merge_forward messages: fetch full message via API then expand sub-messages
|
||||||
@@ -895,7 +896,7 @@ export async function handleFeishuMessage(params: {
|
|||||||
senderName: ctx.senderName,
|
senderName: ctx.senderName,
|
||||||
}).allowed;
|
}).allowed;
|
||||||
|
|
||||||
if (!isGroup && dmPolicy !== "open" && !dmAllowed) {
|
if (isDirect && dmPolicy !== "open" && !dmAllowed) {
|
||||||
if (dmPolicy === "pairing") {
|
if (dmPolicy === "pairing") {
|
||||||
const { code, created } = await pairing.upsertPairingRequest({
|
const { code, created } = await pairing.upsertPairingRequest({
|
||||||
id: ctx.senderOpenId,
|
id: ctx.senderOpenId,
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export function isMentionForwardRequest(event: FeishuMessageEvent, botOpenId?: s
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isDirectMessage = event.message.chat_type === "p2p";
|
const isDirectMessage = event.message.chat_type !== "group";
|
||||||
const hasOtherMention = mentions.some((m) => m.id.open_id !== botOpenId);
|
const hasOtherMention = mentions.some((m) => m.id.open_id !== botOpenId);
|
||||||
|
|
||||||
if (isDirectMessage) {
|
if (isDirectMessage) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const FEISHU_REACTION_VERIFY_TIMEOUT_MS = 1_500;
|
|||||||
export type FeishuReactionCreatedEvent = {
|
export type FeishuReactionCreatedEvent = {
|
||||||
message_id: string;
|
message_id: string;
|
||||||
chat_id?: string;
|
chat_id?: string;
|
||||||
chat_type?: "p2p" | "group";
|
chat_type?: "p2p" | "group" | "private";
|
||||||
reaction_type?: { emoji_type?: string };
|
reaction_type?: { emoji_type?: string };
|
||||||
operator_type?: string;
|
operator_type?: string;
|
||||||
user_id?: { open_id?: string };
|
user_id?: { open_id?: string };
|
||||||
@@ -93,7 +93,8 @@ export async function resolveReactionSyntheticEvent(
|
|||||||
|
|
||||||
const syntheticChatIdRaw = event.chat_id ?? reactedMsg.chatId;
|
const syntheticChatIdRaw = event.chat_id ?? reactedMsg.chatId;
|
||||||
const syntheticChatId = syntheticChatIdRaw?.trim() ? syntheticChatIdRaw : `p2p:${senderId}`;
|
const syntheticChatId = syntheticChatIdRaw?.trim() ? syntheticChatIdRaw : `p2p:${senderId}`;
|
||||||
const syntheticChatType: "p2p" | "group" = event.chat_type ?? "p2p";
|
const syntheticChatType: "p2p" | "group" | "private" =
|
||||||
|
event.chat_type === "group" ? "group" : "p2p";
|
||||||
return {
|
return {
|
||||||
sender: {
|
sender: {
|
||||||
sender_id: { open_id: senderId },
|
sender_id: { open_id: senderId },
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export type FeishuMessageContext = {
|
|||||||
senderId: string;
|
senderId: string;
|
||||||
senderOpenId: string;
|
senderOpenId: string;
|
||||||
senderName?: string;
|
senderName?: string;
|
||||||
chatType: "p2p" | "group";
|
chatType: "p2p" | "group" | "private";
|
||||||
mentionedBot: boolean;
|
mentionedBot: boolean;
|
||||||
rootId?: string;
|
rootId?: string;
|
||||||
parentId?: string;
|
parentId?: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user