mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
refactor(feishu): unify private tool registration setup (#130522)
This commit is contained in:
committed by
GitHub
parent
801cbbd665
commit
fc51e97e60
+14
-54
@@ -6,54 +6,6 @@ import {
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
import { registerFeishuSubagentHooks } from "./subagent-hooks-api.js";
|
||||
|
||||
function registerFeishuDocTools(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerFeishuDocTools",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
function registerFeishuChatTools(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerFeishuChatTools",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
function registerFeishuWikiTools(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerFeishuWikiTools",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
function registerFeishuDriveTools(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerFeishuDriveTools",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
function registerFeishuPermTools(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerFeishuPermTools",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
function registerFeishuBitableTools(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerFeishuBitableTools",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
export default defineBundledChannelEntry({
|
||||
id: "feishu",
|
||||
name: "Feishu",
|
||||
@@ -73,11 +25,19 @@ export default defineBundledChannelEntry({
|
||||
},
|
||||
registerFull(api) {
|
||||
registerFeishuSubagentHooks(api);
|
||||
registerFeishuDocTools(api);
|
||||
registerFeishuChatTools(api);
|
||||
registerFeishuWikiTools(api);
|
||||
registerFeishuDriveTools(api);
|
||||
registerFeishuPermTools(api);
|
||||
registerFeishuBitableTools(api);
|
||||
for (const exportName of [
|
||||
"registerFeishuDocTools",
|
||||
"registerFeishuChatTools",
|
||||
"registerFeishuWikiTools",
|
||||
"registerFeishuDriveTools",
|
||||
"registerFeishuPermTools",
|
||||
"registerFeishuBitableTools",
|
||||
]) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(
|
||||
import.meta.url,
|
||||
{ specifier: "./api.js", exportName },
|
||||
);
|
||||
register(api);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -5,7 +5,6 @@ import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
|
||||
import { Type, type TSchema } from "typebox";
|
||||
import type { OpenClawPluginApi } from "../runtime-api.js";
|
||||
import { listEnabledFeishuAccounts } from "./accounts.js";
|
||||
import { createFeishuToolClient, resolveAnyEnabledFeishuToolsConfig } from "./tool-account.js";
|
||||
import { feishuExternalToolResult as json } from "./tool-result.js";
|
||||
|
||||
@@ -586,12 +585,7 @@ export function registerFeishuBitableTools(api: OpenClawPluginApi) {
|
||||
return;
|
||||
}
|
||||
|
||||
const accounts = listEnabledFeishuAccounts(api.config);
|
||||
if (accounts.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(accounts);
|
||||
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(api.config);
|
||||
if (!toolsCfg.bitable) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import type * as Lark from "@larksuiteoapi/node-sdk";
|
||||
import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
|
||||
import type { OpenClawPluginToolContext } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import type { OpenClawPluginApi } from "../runtime-api.js";
|
||||
import { listEnabledFeishuAccounts } from "./accounts.js";
|
||||
import { FeishuChatSchema, type FeishuChatParams } from "./chat-schema.js";
|
||||
import { resolveFeishuChatType } from "./chat-type.js";
|
||||
import { createFeishuClient } from "./client.js";
|
||||
@@ -244,12 +243,7 @@ export function registerFeishuChatTools(api: OpenClawPluginApi) {
|
||||
}
|
||||
const cfg = api.config;
|
||||
|
||||
const accounts = listEnabledFeishuAccounts(cfg);
|
||||
if (accounts.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(accounts);
|
||||
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(cfg);
|
||||
if (!toolsCfg.chat) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { Type } from "typebox";
|
||||
import type { OpenClawPluginApi } from "../runtime-api.js";
|
||||
import { listEnabledFeishuAccounts } from "./accounts.js";
|
||||
import { resolveConfiguredHttpTimeoutMs } from "./client-timeout.js";
|
||||
import { FeishuDocSchema, type FeishuDocParams } from "./doc-schema.js";
|
||||
import { BATCH_SIZE, insertBlocksInBatches } from "./docx-batch-insert.js";
|
||||
@@ -76,28 +75,20 @@ const BLOCK_TYPE_NAMES: Record<number, string> = {
|
||||
// Block types that cannot be created via documentBlockChildren.create API
|
||||
const UNSUPPORTED_CREATE_TYPES = new Set([31, 32]);
|
||||
|
||||
/** Clean blocks for insertion (remove unsupported types and read-only fields) */
|
||||
/** Remove block types unsupported by the children insertion API. */
|
||||
function cleanBlocksForInsert(blocks: FeishuDocxBlock[]): {
|
||||
cleaned: FeishuDocxBlock[];
|
||||
skipped: string[];
|
||||
} {
|
||||
const skipped: string[] = [];
|
||||
const cleaned = blocks
|
||||
.filter((block) => {
|
||||
if (UNSUPPORTED_CREATE_TYPES.has(block.block_type)) {
|
||||
const typeName = BLOCK_TYPE_NAMES[block.block_type] || `type_${block.block_type}`;
|
||||
skipped.push(typeName);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map((block) => {
|
||||
if (block.block_type === 31 && block.table?.merge_info) {
|
||||
const { merge_info: _merge_info, ...tableRest } = block.table;
|
||||
return Object.assign({}, block, { table: tableRest });
|
||||
}
|
||||
return block;
|
||||
});
|
||||
const cleaned = blocks.filter((block) => {
|
||||
if (UNSUPPORTED_CREATE_TYPES.has(block.block_type)) {
|
||||
const typeName = BLOCK_TYPE_NAMES[block.block_type] || `type_${block.block_type}`;
|
||||
skipped.push(typeName);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return { cleaned, skipped };
|
||||
}
|
||||
|
||||
@@ -1200,16 +1191,9 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if any account is configured
|
||||
const accounts = listEnabledFeishuAccounts(api.config);
|
||||
if (accounts.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register if enabled on any account; account routing is resolved per execution.
|
||||
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(accounts);
|
||||
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(api.config);
|
||||
|
||||
const registered: string[] = [];
|
||||
type FeishuDocExecuteParams = FeishuDocParams & { accountId?: string };
|
||||
|
||||
const getClient = (params: { accountId?: string } | undefined, defaultAccountId?: string) =>
|
||||
@@ -1434,7 +1418,6 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
||||
},
|
||||
{ name: "feishu_doc" },
|
||||
);
|
||||
registered.push("feishu_doc");
|
||||
}
|
||||
|
||||
// Keep feishu_app_scopes as independent tool
|
||||
@@ -1464,7 +1447,6 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
||||
}),
|
||||
{ name: "feishu_app_scopes" },
|
||||
);
|
||||
registered.push("feishu_app_scopes");
|
||||
}
|
||||
}
|
||||
/* oxlint-disable max-lines -- TODO: split this grandfathered oversized file. */
|
||||
|
||||
@@ -4,7 +4,6 @@ import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
|
||||
import { isRecord, readStringValue as readString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import type { OpenClawPluginApi } from "../runtime-api.js";
|
||||
import { listEnabledFeishuAccounts } from "./accounts.js";
|
||||
import { cleanupAmbientCommentTypingReaction } from "./comment-reaction.js";
|
||||
import { encodeQuery, extractReplyText, formatFeishuApiError } from "./comment-shared.js";
|
||||
import { parseFeishuCommentTarget, type CommentFileType } from "./comment-target.js";
|
||||
@@ -798,12 +797,7 @@ export function registerFeishuDriveTools(api: OpenClawPluginApi) {
|
||||
return;
|
||||
}
|
||||
|
||||
const accounts = listEnabledFeishuAccounts(api.config);
|
||||
if (accounts.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(accounts);
|
||||
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(api.config);
|
||||
if (!toolsCfg.drive) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Feishu plugin module implements perm behavior.
|
||||
import type * as Lark from "@larksuiteoapi/node-sdk";
|
||||
import type { OpenClawPluginApi } from "../runtime-api.js";
|
||||
import { listEnabledFeishuAccounts } from "./accounts.js";
|
||||
import { FeishuPermSchema, type FeishuPermParams } from "./perm-schema.js";
|
||||
import { createFeishuToolClient, resolveAnyEnabledFeishuToolsConfig } from "./tool-account.js";
|
||||
import {
|
||||
@@ -118,12 +117,7 @@ export function registerFeishuPermTools(api: OpenClawPluginApi) {
|
||||
return;
|
||||
}
|
||||
|
||||
const accounts = listEnabledFeishuAccounts(api.config);
|
||||
if (accounts.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(accounts);
|
||||
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(api.config);
|
||||
if (!toolsCfg.perm) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ vi.mock("./client.js", () => ({
|
||||
}));
|
||||
|
||||
let registerFeishuBitableTools: typeof import("./bitable.js").registerFeishuBitableTools;
|
||||
let registerFeishuChatTools: typeof import("./chat.js").registerFeishuChatTools;
|
||||
let registerFeishuDocTools: typeof import("./docx.js").registerFeishuDocTools;
|
||||
let registerFeishuDriveTools: typeof import("./drive.js").registerFeishuDriveTools;
|
||||
let registerFeishuPermTools: typeof import("./perm.js").registerFeishuPermTools;
|
||||
let registerFeishuWikiTools: typeof import("./wiki.js").registerFeishuWikiTools;
|
||||
@@ -92,6 +94,8 @@ describe("feishu tool account routing", () => {
|
||||
}),
|
||||
));
|
||||
({ registerFeishuWikiTools } = await import("./wiki.js"));
|
||||
({ registerFeishuChatTools } = await import("./chat.js"));
|
||||
({ registerFeishuDocTools } = await import("./docx.js"));
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
@@ -103,6 +107,41 @@ describe("feishu tool account routing", () => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test.each([
|
||||
["missing channel", {}],
|
||||
["unconfigured account", { channels: { feishu: { accounts: { a: { enabled: true } } } } }],
|
||||
[
|
||||
"disabled channel",
|
||||
{ channels: { feishu: { ...createConfig({}).channels?.feishu, enabled: false } } },
|
||||
],
|
||||
[
|
||||
"disabled accounts",
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
accounts: {
|
||||
a: { enabled: false, appId: "app-a", appSecret: "sec-a" }, // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
])("does not register workplace tools for %s", (_label, config) => {
|
||||
const { api, registered } = createToolFactoryHarness(config);
|
||||
for (const register of [
|
||||
registerFeishuDocTools,
|
||||
registerFeishuChatTools,
|
||||
registerFeishuWikiTools,
|
||||
registerFeishuDriveTools,
|
||||
registerFeishuPermTools,
|
||||
registerFeishuBitableTools,
|
||||
]) {
|
||||
register(api);
|
||||
}
|
||||
expect(registered).toEqual([]);
|
||||
expect(createFeishuClientMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("wiki tool registers when first account disables it and routes to agentAccountId", async () => {
|
||||
const { api, resolveTool } = createToolFactoryHarness(
|
||||
createConfig({
|
||||
|
||||
@@ -4,6 +4,7 @@ import { normalizeOptionalAccountId } from "openclaw/plugin-sdk/account-resoluti
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import type { OpenClawPluginApi } from "../runtime-api.js";
|
||||
import {
|
||||
listEnabledFeishuAccounts,
|
||||
listFeishuAccountIds,
|
||||
resolveDefaultFeishuAccountId,
|
||||
resolveFeishuAccount,
|
||||
@@ -128,8 +129,9 @@ export function createFeishuToolClient(params: {
|
||||
}
|
||||
|
||||
export function resolveAnyEnabledFeishuToolsConfig(
|
||||
accounts: ResolvedFeishuAccount[],
|
||||
config: OpenClawPluginApi["config"],
|
||||
): Required<FeishuToolsConfig> {
|
||||
const accounts = listEnabledFeishuAccounts(config);
|
||||
const merged: Required<FeishuToolsConfig> = {
|
||||
doc: false,
|
||||
chat: false,
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import type * as Lark from "@larksuiteoapi/node-sdk";
|
||||
import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
|
||||
import type { OpenClawPluginApi } from "../runtime-api.js";
|
||||
import { listEnabledFeishuAccounts } from "./accounts.js";
|
||||
import { createFeishuToolClient, resolveAnyEnabledFeishuToolsConfig } from "./tool-account.js";
|
||||
import {
|
||||
feishuExternalToolResult as jsonResult,
|
||||
@@ -209,12 +208,7 @@ export function registerFeishuWikiTools(api: OpenClawPluginApi) {
|
||||
return;
|
||||
}
|
||||
|
||||
const accounts = listEnabledFeishuAccounts(api.config);
|
||||
if (accounts.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(accounts);
|
||||
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(api.config);
|
||||
if (!toolsCfg.wiki) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user