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

@@ -0,0 +1,68 @@
import * as Lark from "@larksuiteoapi/node-sdk";
import type { FeishuConfig, FeishuDomain } from "./types.js";
import { resolveFeishuCredentials } from "./accounts.js";
let cachedClient: Lark.Client | null = null;
let cachedConfig: { appId: string; appSecret: string; domain: FeishuDomain } | null = null;
function resolveDomain(domain: FeishuDomain): Lark.Domain | string {
if (domain === "lark") return Lark.Domain.Lark;
if (domain === "feishu") return Lark.Domain.Feishu;
return domain.replace(/\/+$/, ""); // Custom URL, remove trailing slashes
}
export function createFeishuClient(cfg: FeishuConfig): Lark.Client {
const creds = resolveFeishuCredentials(cfg);
if (!creds) {
throw new Error("Feishu credentials not configured (appId, appSecret required)");
}
if (
cachedClient &&
cachedConfig &&
cachedConfig.appId === creds.appId &&
cachedConfig.appSecret === creds.appSecret &&
cachedConfig.domain === creds.domain
) {
return cachedClient;
}
const client = new Lark.Client({
appId: creds.appId,
appSecret: creds.appSecret,
appType: Lark.AppType.SelfBuild,
domain: resolveDomain(creds.domain),
});
cachedClient = client;
cachedConfig = { appId: creds.appId, appSecret: creds.appSecret, domain: creds.domain };
return client;
}
export function createFeishuWSClient(cfg: FeishuConfig): Lark.WSClient {
const creds = resolveFeishuCredentials(cfg);
if (!creds) {
throw new Error("Feishu credentials not configured (appId, appSecret required)");
}
return new Lark.WSClient({
appId: creds.appId,
appSecret: creds.appSecret,
domain: resolveDomain(creds.domain),
loggerLevel: Lark.LoggerLevel.info,
});
}
export function createEventDispatcher(cfg: FeishuConfig): Lark.EventDispatcher {
const creds = resolveFeishuCredentials(cfg);
return new Lark.EventDispatcher({
encryptKey: creds?.encryptKey,
verificationToken: creds?.verificationToken,
});
}
export function clearClientCache() {
cachedClient = null;
cachedConfig = null;
}