openclaw-home-pc/openclaw/extensions/openclaw-lark/index.js
2026-03-21 15:31:06 +08:00

120 lines
6.4 KiB
JavaScript

"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 <messageId>]
api.registerCli((ctx) => {
ctx.program
.command('feishu-diagnose')
.description('运行飞书插件诊断,检查配置、连通性和权限状态')
.option('--trace <messageId>', '按 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;