@openclaw/feishu 2026.2.6 → 2026.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/feishu",
3
- "version": "2026.2.6",
3
+ "version": "2026.2.9",
4
4
  "description": "OpenClaw Feishu/Lark channel plugin (community maintained by @m1heng)",
5
5
  "type": "module",
6
6
  "dependencies": {
package/src/bitable.ts CHANGED
@@ -212,7 +212,8 @@ async function createRecord(
212
212
  ) {
213
213
  const res = await client.bitable.appTableRecord.create({
214
214
  path: { app_token: appToken, table_id: tableId },
215
- data: { fields },
215
+ // oxlint-disable-next-line typescript/no-explicit-any
216
+ data: { fields: fields as any },
216
217
  });
217
218
  if (res.code !== 0) {
218
219
  throw new Error(res.msg);
@@ -232,7 +233,8 @@ async function updateRecord(
232
233
  ) {
233
234
  const res = await client.bitable.appTableRecord.update({
234
235
  path: { app_token: appToken, table_id: tableId, record_id: recordId },
235
- data: { fields },
236
+ // oxlint-disable-next-line typescript/no-explicit-any
237
+ data: { fields: fields as any },
236
238
  });
237
239
  if (res.code !== 0) {
238
240
  throw new Error(res.msg);
package/src/bot.ts CHANGED
@@ -652,7 +652,7 @@ export async function handleFeishuMessage(params: {
652
652
  channel: "feishu",
653
653
  accountId: account.accountId,
654
654
  peer: {
655
- kind: isGroup ? "group" : "dm",
655
+ kind: isGroup ? "group" : "direct",
656
656
  id: isGroup ? ctx.chatId : ctx.senderOpenId,
657
657
  },
658
658
  });
package/src/channel.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ChannelPlugin, ClawdbotConfig } from "openclaw/plugin-sdk";
1
+ import type { ChannelMeta, ChannelPlugin, ClawdbotConfig } from "openclaw/plugin-sdk";
2
2
  import { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk";
3
3
  import type { ResolvedFeishuAccount, FeishuConfig } from "./types.js";
4
4
  import {
@@ -19,7 +19,7 @@ import { probeFeishu } from "./probe.js";
19
19
  import { sendMessageFeishu } from "./send.js";
20
20
  import { normalizeFeishuTarget, looksLikeFeishuId } from "./targets.js";
21
21
 
22
- const meta = {
22
+ const meta: ChannelMeta = {
23
23
  id: "feishu",
24
24
  label: "Feishu",
25
25
  selectionLabel: "Feishu/Lark (飞书)",
@@ -28,7 +28,7 @@ const meta = {
28
28
  blurb: "飞书/Lark enterprise messaging.",
29
29
  aliases: ["lark"],
30
30
  order: 70,
31
- } as const;
31
+ };
32
32
 
33
33
  export const feishuPlugin: ChannelPlugin<ResolvedFeishuAccount> = {
34
34
  id: "feishu",
@@ -38,12 +38,11 @@ export const feishuPlugin: ChannelPlugin<ResolvedFeishuAccount> = {
38
38
  pairing: {
39
39
  idLabel: "feishuUserId",
40
40
  normalizeAllowEntry: (entry) => entry.replace(/^(feishu|user|open_id):/i, ""),
41
- notifyApproval: async ({ cfg, id, accountId }) => {
41
+ notifyApproval: async ({ cfg, id }) => {
42
42
  await sendMessageFeishu({
43
43
  cfg,
44
44
  to: id,
45
45
  text: PAIRING_APPROVED_MESSAGE,
46
- accountId,
47
46
  });
48
47
  },
49
48
  },
@@ -202,7 +201,7 @@ export const feishuPlugin: ChannelPlugin<ResolvedFeishuAccount> = {
202
201
  }),
203
202
  resolveAllowFrom: ({ cfg, accountId }) => {
204
203
  const account = resolveFeishuAccount({ cfg, accountId });
205
- return account.config?.allowFrom ?? [];
204
+ return (account.config?.allowFrom ?? []).map((entry) => String(entry));
206
205
  },
207
206
  formatAllowFrom: ({ allowFrom }) =>
208
207
  allowFrom
@@ -265,7 +264,7 @@ export const feishuPlugin: ChannelPlugin<ResolvedFeishuAccount> = {
265
264
  },
266
265
  onboarding: feishuOnboardingAdapter,
267
266
  messaging: {
268
- normalizeTarget: normalizeFeishuTarget,
267
+ normalizeTarget: (raw) => normalizeFeishuTarget(raw) ?? undefined,
269
268
  targetResolver: {
270
269
  looksLikeId: looksLikeFeishuId,
271
270
  hint: "<chatId|user:openId|chat:chatId>",
@@ -274,13 +273,33 @@ export const feishuPlugin: ChannelPlugin<ResolvedFeishuAccount> = {
274
273
  directory: {
275
274
  self: async () => null,
276
275
  listPeers: async ({ cfg, query, limit, accountId }) =>
277
- listFeishuDirectoryPeers({ cfg, query, limit, accountId }),
276
+ listFeishuDirectoryPeers({
277
+ cfg,
278
+ query: query ?? undefined,
279
+ limit: limit ?? undefined,
280
+ accountId: accountId ?? undefined,
281
+ }),
278
282
  listGroups: async ({ cfg, query, limit, accountId }) =>
279
- listFeishuDirectoryGroups({ cfg, query, limit, accountId }),
283
+ listFeishuDirectoryGroups({
284
+ cfg,
285
+ query: query ?? undefined,
286
+ limit: limit ?? undefined,
287
+ accountId: accountId ?? undefined,
288
+ }),
280
289
  listPeersLive: async ({ cfg, query, limit, accountId }) =>
281
- listFeishuDirectoryPeersLive({ cfg, query, limit, accountId }),
290
+ listFeishuDirectoryPeersLive({
291
+ cfg,
292
+ query: query ?? undefined,
293
+ limit: limit ?? undefined,
294
+ accountId: accountId ?? undefined,
295
+ }),
282
296
  listGroupsLive: async ({ cfg, query, limit, accountId }) =>
283
- listFeishuDirectoryGroupsLive({ cfg, query, limit, accountId }),
297
+ listFeishuDirectoryGroupsLive({
298
+ cfg,
299
+ query: query ?? undefined,
300
+ limit: limit ?? undefined,
301
+ accountId: accountId ?? undefined,
302
+ }),
284
303
  },
285
304
  outbound: feishuOutbound,
286
305
  status: {
@@ -302,8 +321,7 @@ export const feishuPlugin: ChannelPlugin<ResolvedFeishuAccount> = {
302
321
  probe: snapshot.probe,
303
322
  lastProbeAt: snapshot.lastProbeAt ?? null,
304
323
  }),
305
- probeAccount: async ({ cfg, accountId }) => {
306
- const account = resolveFeishuAccount({ cfg, accountId });
324
+ probeAccount: async ({ account }) => {
307
325
  return await probeFeishu(account);
308
326
  },
309
327
  buildAccountSnapshot: ({ account, runtime, probe }) => ({
package/src/onboarding.ts CHANGED
@@ -80,7 +80,10 @@ async function promptFeishuAllowFrom(params: {
80
80
  }
81
81
 
82
82
  const unique = [
83
- ...new Set([...existing.map((v) => String(v).trim()).filter(Boolean), ...parts]),
83
+ ...new Set([
84
+ ...existing.map((v: string | number) => String(v).trim()).filter(Boolean),
85
+ ...parts,
86
+ ]),
84
87
  ];
85
88
  return setFeishuAllowFrom(params.cfg, unique);
86
89
  }
package/src/outbound.ts CHANGED
@@ -9,32 +9,47 @@ export const feishuOutbound: ChannelOutboundAdapter = {
9
9
  chunkerMode: "markdown",
10
10
  textChunkLimit: 4000,
11
11
  sendText: async ({ cfg, to, text, accountId }) => {
12
- const result = await sendMessageFeishu({ cfg, to, text, accountId });
12
+ const result = await sendMessageFeishu({ cfg, to, text, accountId: accountId ?? undefined });
13
13
  return { channel: "feishu", ...result };
14
14
  },
15
15
  sendMedia: async ({ cfg, to, text, mediaUrl, accountId }) => {
16
16
  // Send text first if provided
17
17
  if (text?.trim()) {
18
- await sendMessageFeishu({ cfg, to, text, accountId });
18
+ await sendMessageFeishu({ cfg, to, text, accountId: accountId ?? undefined });
19
19
  }
20
20
 
21
21
  // Upload and send media if URL provided
22
22
  if (mediaUrl) {
23
23
  try {
24
- const result = await sendMediaFeishu({ cfg, to, mediaUrl, accountId });
24
+ const result = await sendMediaFeishu({
25
+ cfg,
26
+ to,
27
+ mediaUrl,
28
+ accountId: accountId ?? undefined,
29
+ });
25
30
  return { channel: "feishu", ...result };
26
31
  } catch (err) {
27
32
  // Log the error for debugging
28
33
  console.error(`[feishu] sendMediaFeishu failed:`, err);
29
34
  // Fallback to URL link if upload fails
30
35
  const fallbackText = `📎 ${mediaUrl}`;
31
- const result = await sendMessageFeishu({ cfg, to, text: fallbackText, accountId });
36
+ const result = await sendMessageFeishu({
37
+ cfg,
38
+ to,
39
+ text: fallbackText,
40
+ accountId: accountId ?? undefined,
41
+ });
32
42
  return { channel: "feishu", ...result };
33
43
  }
34
44
  }
35
45
 
36
46
  // No media URL, just return text result
37
- const result = await sendMessageFeishu({ cfg, to, text: text ?? "", accountId });
47
+ const result = await sendMessageFeishu({
48
+ cfg,
49
+ to,
50
+ text: text ?? "",
51
+ accountId: accountId ?? undefined,
52
+ });
38
53
  return { channel: "feishu", ...result };
39
54
  },
40
55
  };
@@ -90,16 +90,11 @@ export function createFeishuReplyDispatcher(params: CreateFeishuReplyDispatcherP
90
90
  },
91
91
  });
92
92
 
93
- const textChunkLimit = core.channel.text.resolveTextChunkLimit({
94
- cfg,
95
- channel: "feishu",
96
- defaultLimit: 4000,
93
+ const textChunkLimit = core.channel.text.resolveTextChunkLimit(cfg, "feishu", accountId, {
94
+ fallbackLimit: 4000,
97
95
  });
98
96
  const chunkMode = core.channel.text.resolveChunkMode(cfg, "feishu");
99
- const tableMode = core.channel.text.resolveMarkdownTableMode({
100
- cfg,
101
- channel: "feishu",
102
- });
97
+ const tableMode = core.channel.text.resolveMarkdownTableMode({ cfg, channel: "feishu" });
103
98
 
104
99
  const { dispatcher, replyOptions, markDispatchIdle } =
105
100
  core.channel.reply.createReplyDispatcherWithTyping({