feat(feishu): replace built-in SDK with community plugin

Replace the built-in Feishu SDK with the community-maintained
clawdbot-feishu plugin by @m1heng.

Changes:
- Remove src/feishu/ directory (19 files)
- Remove src/channels/plugins/outbound/feishu.ts
- Remove src/channels/plugins/normalize/feishu.ts
- Remove src/config/types.feishu.ts
- Remove feishu exports from plugin-sdk/index.ts
- Remove FeishuConfig from types.channels.ts

New features in community plugin:
- Document tools (read/create/edit Feishu docs)
- Wiki tools (navigate/manage knowledge base)
- Drive tools (folder/file management)
- Bitable tools (read/write table records)
- Permission tools (collaborator management)
- Emoji reactions support
- Typing indicators
- Rich media support (bidirectional image/file transfer)
- @mention handling
- Skills for feishu-doc, feishu-wiki, feishu-drive, feishu-perm

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Yifeng Wang
2026-02-05 18:26:05 +08:00
committed by cpojer
parent 02842bef91
commit 2267d58afc
66 changed files with 5702 additions and 4486 deletions

View File

@@ -1,5 +0,0 @@
export function normalizeFeishuTarget(raw: string): string {
let normalized = raw.replace(/^(feishu|lark):/i, "").trim();
normalized = normalized.replace(/^(group|chat|user|dm):/i, "").trim();
return normalized;
}

View File

@@ -1,52 +0,0 @@
import type { ChannelOutboundAdapter } from "../types.js";
import { chunkMarkdownText } from "../../../auto-reply/chunk.js";
import { getFeishuClient } from "../../../feishu/client.js";
import { sendMessageFeishu } from "../../../feishu/send.js";
function resolveReceiveIdType(target: string): "open_id" | "union_id" | "chat_id" {
const trimmed = target.trim().toLowerCase();
if (trimmed.startsWith("ou_")) {
return "open_id";
}
if (trimmed.startsWith("on_")) {
return "union_id";
}
return "chat_id";
}
export const feishuOutbound: ChannelOutboundAdapter = {
deliveryMode: "direct",
chunker: (text, limit) => chunkMarkdownText(text, limit),
chunkerMode: "markdown",
textChunkLimit: 2000,
sendText: async ({ to, text, accountId }) => {
const client = getFeishuClient(accountId ?? undefined);
const result = await sendMessageFeishu(
client,
to,
{ text },
{
receiveIdType: resolveReceiveIdType(to),
},
);
return {
channel: "feishu",
messageId: result?.message_id || "unknown",
chatId: to,
};
},
sendMedia: async ({ to, text, mediaUrl, accountId }) => {
const client = getFeishuClient(accountId ?? undefined);
const result = await sendMessageFeishu(
client,
to,
{ text: text || "" },
{ mediaUrl, receiveIdType: resolveReceiveIdType(to) },
);
return {
channel: "feishu",
messageId: result?.message_id || "unknown",
chatId: to,
};
},
};