"use strict"; /** * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates * SPDX-License-Identifier: MIT * * OpenClaw Lark/Feishu plugin entry point. * * Registers the Feishu channel and all tool families: * doc, wiki, drive, perm, bitable, task, calendar. */ import { emptyPluginConfigSchema } from 'openclaw/plugin-sdk'; import { feishuPlugin } from './src/channel/plugin'; import { LarkClient } from './src/core/lark-client'; import { registerOapiTools } from './src/tools/oapi/index'; import { registerFeishuMcpDocTools } from './src/tools/mcp/doc/index'; import { registerFeishuOAuthTool } from './src/tools/oauth'; import { registerFeishuOAuthBatchAuthTool } from './src/tools/oauth-batch-auth'; import { runDiagnosis, formatDiagReportCli, traceByMessageId, formatTraceOutput, analyzeTrace, } from './src/commands/diagnose'; import { registerCommands } from './src/commands/index'; import { larkLogger } from './src/core/lark-logger'; import { emitSecurityWarnings } from './src/core/security-check'; const log = larkLogger('plugin'); // --------------------------------------------------------------------------- // Re-exports for external consumers // --------------------------------------------------------------------------- export { monitorFeishuProvider } from './src/channel/monitor'; export { sendMessageFeishu, sendCardFeishu, updateCardFeishu, editMessageFeishu } from './src/messaging/outbound/send'; export { getMessageFeishu } from './src/messaging/outbound/fetch'; export { uploadImageLark, uploadFileLark, sendImageLark, sendFileLark, sendAudioLark, uploadAndSendMediaLark, } from './src/messaging/outbound/media'; export { sendTextLark, sendCardLark, sendMediaLark, } from './src/messaging/outbound/deliver'; export { probeFeishu } from './src/channel/probe'; export { addReactionFeishu, removeReactionFeishu, listReactionsFeishu, FeishuEmoji, VALID_FEISHU_EMOJI_TYPES, } from './src/messaging/outbound/reactions'; export { forwardMessageFeishu } from './src/messaging/outbound/forward'; export { updateChatFeishu, addChatMembersFeishu, removeChatMembersFeishu, listChatMembersFeishu, } from './src/messaging/outbound/chat-manage'; export { feishuMessageActions } from './src/messaging/outbound/actions'; export { mentionedBot, nonBotMentions, extractMessageBody, formatMentionForText, formatMentionForCard, formatMentionAllForText, formatMentionAllForCard, buildMentionedMessage, buildMentionedCardContent, } from './src/messaging/inbound/mention'; export { feishuPlugin } from './src/channel/plugin'; export { handleFeishuReaction } from './src/messaging/inbound/reaction-handler'; export { parseMessageEvent } from './src/messaging/inbound/parse'; export { checkMessageGate } from './src/messaging/inbound/gate'; export { isMessageExpired } from './src/messaging/inbound/dedup'; // --------------------------------------------------------------------------- // Plugin definition // --------------------------------------------------------------------------- const plugin = { id: 'openclaw-lark', name: 'Feishu', description: 'Lark/Feishu channel plugin with im/doc/wiki/drive/task/calendar tools', configSchema: emptyPluginConfigSchema(), register(api) { LarkClient.setRuntime(api.runtime); api.registerChannel({ plugin: feishuPlugin }); // ======================================== // Register OAPI tools (calendar, task - using Feishu Open API directly) registerOapiTools(api); // Register MCP doc tools (using Model Context Protocol) registerFeishuMcpDocTools(api); // Register OAuth tool (UAT device flow authorization) registerFeishuOAuthTool(api); // Register OAuth batch auth tool (batch authorization for all app scopes) registerFeishuOAuthBatchAuthTool(api); // ---- Tool call hooks (auto-trace AI tool invocations) ---- api.on('before_tool_call', (event) => { log.info(`tool call: ${event.toolName} params=${JSON.stringify(event.params)}`); }); api.on('after_tool_call', (event) => { if (event.error) { log.error(`tool fail: ${event.toolName} ${event.error} (${event.durationMs ?? 0}ms)`); } else { log.info(`tool done: ${event.toolName} ok (${event.durationMs ?? 0}ms)`); } }); // ---- Diagnostic commands ---- // CLI: openclaw feishu-diagnose [--trace ] api.registerCli((ctx) => { ctx.program .command('feishu-diagnose') .description('运行飞书插件诊断,检查配置、连通性和权限状态') .option('--trace ', '按 message_id 追踪完整处理链路') .option('--analyze', '分析追踪日志(需配合 --trace 使用)') .action(async (opts) => { try { if (opts.trace) { const lines = await traceByMessageId(opts.trace); // eslint-disable-next-line no-console -- CLI 命令直接输出到终端 console.log(formatTraceOutput(lines, opts.trace)); if (opts.analyze && lines.length > 0) { // eslint-disable-next-line no-console -- CLI 命令直接输出到终端 console.log(analyzeTrace(lines, opts.trace)); } } else { const report = await runDiagnosis({ config: ctx.config, logger: ctx.logger, }); // eslint-disable-next-line no-console -- CLI 命令直接输出到终端 console.log(formatDiagReportCli(report)); if (report.overallStatus === 'unhealthy') { process.exitCode = 1; } } } catch (err) { ctx.logger.error(`诊断命令执行失败: ${err}`); process.exitCode = 1; } }); }, { commands: ['feishu-diagnose'] }); // Chat commands: /feishu_diagnose, /feishu_doctor, /feishu_auth, /feishu registerCommands(api); // ---- Multi-account security checks ---- if (api.config) { emitSecurityWarnings(api.config, api.logger); } }, }; export default plugin;