@openclaw/feishu 2026.3.1 → 2026.3.7

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.
Files changed (76) hide show
  1. package/index.ts +2 -2
  2. package/package.json +1 -1
  3. package/src/accounts.test.ts +268 -11
  4. package/src/accounts.ts +101 -14
  5. package/src/bitable.ts +40 -28
  6. package/src/bot.checkBotMentioned.test.ts +9 -1
  7. package/src/bot.stripBotMention.test.ts +118 -22
  8. package/src/bot.test.ts +945 -77
  9. package/src/bot.ts +492 -165
  10. package/src/card-action.ts +1 -1
  11. package/src/channel.test.ts +1 -1
  12. package/src/channel.ts +72 -68
  13. package/src/chat.test.ts +2 -2
  14. package/src/chat.ts +1 -1
  15. package/src/client.test.ts +221 -4
  16. package/src/client.ts +70 -5
  17. package/src/config-schema.test.ts +33 -6
  18. package/src/config-schema.ts +18 -10
  19. package/src/dedup.ts +47 -1
  20. package/src/directory.test.ts +40 -0
  21. package/src/directory.ts +29 -50
  22. package/src/doc-schema.ts +16 -22
  23. package/src/docx-batch-insert.test.ts +90 -0
  24. package/src/docx-batch-insert.ts +8 -11
  25. package/src/docx.account-selection.test.ts +10 -16
  26. package/src/docx.test.ts +41 -189
  27. package/src/docx.ts +1 -1
  28. package/src/drive.ts +13 -17
  29. package/src/dynamic-agent.ts +1 -1
  30. package/src/feishu-command-handler.ts +59 -0
  31. package/src/media.test.ts +164 -14
  32. package/src/media.ts +44 -10
  33. package/src/mention.ts +1 -1
  34. package/src/monitor.account.ts +284 -25
  35. package/src/monitor.reaction.test.ts +395 -46
  36. package/src/monitor.startup.test.ts +25 -8
  37. package/src/monitor.startup.ts +20 -7
  38. package/src/monitor.state.defaults.test.ts +46 -0
  39. package/src/monitor.state.ts +88 -9
  40. package/src/monitor.test-mocks.ts +45 -0
  41. package/src/monitor.transport.ts +4 -1
  42. package/src/monitor.ts +4 -4
  43. package/src/monitor.webhook-security.test.ts +13 -11
  44. package/src/onboarding.status.test.ts +25 -0
  45. package/src/onboarding.test.ts +143 -0
  46. package/src/onboarding.ts +213 -106
  47. package/src/outbound.test.ts +178 -0
  48. package/src/outbound.ts +39 -6
  49. package/src/perm.ts +11 -15
  50. package/src/policy.test.ts +40 -0
  51. package/src/policy.ts +9 -10
  52. package/src/probe.test.ts +54 -36
  53. package/src/probe.ts +57 -37
  54. package/src/reactions.ts +1 -1
  55. package/src/reply-dispatcher.test.ts +216 -0
  56. package/src/reply-dispatcher.ts +89 -22
  57. package/src/runtime.ts +1 -1
  58. package/src/secret-input.ts +13 -0
  59. package/src/send-message.ts +71 -0
  60. package/src/send-target.test.ts +74 -0
  61. package/src/send-target.ts +7 -3
  62. package/src/send.reply-fallback.test.ts +74 -0
  63. package/src/send.test.ts +1 -1
  64. package/src/send.ts +88 -49
  65. package/src/streaming-card.test.ts +54 -0
  66. package/src/streaming-card.ts +96 -28
  67. package/src/targets.test.ts +29 -0
  68. package/src/targets.ts +25 -1
  69. package/src/tool-account-routing.test.ts +3 -3
  70. package/src/tool-account.ts +1 -1
  71. package/src/tool-factory-test-harness.ts +1 -1
  72. package/src/tool-result.test.ts +32 -0
  73. package/src/tool-result.ts +14 -0
  74. package/src/types.ts +11 -4
  75. package/src/typing.ts +1 -1
  76. package/src/wiki.ts +15 -19
@@ -0,0 +1,32 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ jsonToolResult,
4
+ toolExecutionErrorResult,
5
+ unknownToolActionResult,
6
+ } from "./tool-result.js";
7
+
8
+ describe("jsonToolResult", () => {
9
+ it("formats tool result with text content and details", () => {
10
+ const payload = { ok: true, id: "abc" };
11
+ expect(jsonToolResult(payload)).toEqual({
12
+ content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
13
+ details: payload,
14
+ });
15
+ });
16
+
17
+ it("formats unknown action errors", () => {
18
+ expect(unknownToolActionResult("create")).toEqual({
19
+ content: [
20
+ { type: "text", text: JSON.stringify({ error: "Unknown action: create" }, null, 2) },
21
+ ],
22
+ details: { error: "Unknown action: create" },
23
+ });
24
+ });
25
+
26
+ it("formats execution errors", () => {
27
+ expect(toolExecutionErrorResult(new Error("boom"))).toEqual({
28
+ content: [{ type: "text", text: JSON.stringify({ error: "boom" }, null, 2) }],
29
+ details: { error: "boom" },
30
+ });
31
+ });
32
+ });
@@ -0,0 +1,14 @@
1
+ export function jsonToolResult(data: unknown) {
2
+ return {
3
+ content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }],
4
+ details: data,
5
+ };
6
+ }
7
+
8
+ export function unknownToolActionResult(action: unknown) {
9
+ return jsonToolResult({ error: `Unknown action: ${String(action)}` });
10
+ }
11
+
12
+ export function toolExecutionErrorResult(error: unknown) {
13
+ return jsonToolResult({ error: error instanceof Error ? error.message : String(error) });
14
+ }
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { BaseProbeResult } from "openclaw/plugin-sdk";
1
+ import type { BaseProbeResult } from "openclaw/plugin-sdk/feishu";
2
2
  import type {
3
3
  FeishuConfigSchema,
4
4
  FeishuGroupSchema,
@@ -14,8 +14,15 @@ export type FeishuAccountConfig = z.infer<typeof FeishuAccountConfigSchema>;
14
14
  export type FeishuDomain = "feishu" | "lark" | (string & {});
15
15
  export type FeishuConnectionMode = "websocket" | "webhook";
16
16
 
17
+ export type FeishuDefaultAccountSelectionSource =
18
+ | "explicit-default"
19
+ | "mapped-default"
20
+ | "fallback";
21
+ export type FeishuAccountSelectionSource = "explicit" | FeishuDefaultAccountSelectionSource;
22
+
17
23
  export type ResolvedFeishuAccount = {
18
24
  accountId: string;
25
+ selectionSource: FeishuAccountSelectionSource;
19
26
  enabled: boolean;
20
27
  configured: boolean;
21
28
  name?: string;
@@ -36,16 +43,16 @@ export type FeishuMessageContext = {
36
43
  senderId: string;
37
44
  senderOpenId: string;
38
45
  senderName?: string;
39
- chatType: "p2p" | "group";
46
+ chatType: "p2p" | "group" | "private";
40
47
  mentionedBot: boolean;
48
+ hasAnyMention?: boolean;
41
49
  rootId?: string;
42
50
  parentId?: string;
51
+ threadId?: string;
43
52
  content: string;
44
53
  contentType: string;
45
54
  /** Mention forward targets (excluding the bot itself) */
46
55
  mentionTargets?: MentionTarget[];
47
- /** Extracted message body (after removing @ placeholders) */
48
- mentionMessageBody?: string;
49
56
  };
50
57
 
51
58
  export type FeishuSendResult = {
package/src/typing.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ClawdbotConfig, RuntimeEnv } from "openclaw/plugin-sdk";
1
+ import type { ClawdbotConfig, RuntimeEnv } from "openclaw/plugin-sdk/feishu";
2
2
  import { resolveFeishuAccount } from "./accounts.js";
3
3
  import { createFeishuClient } from "./client.js";
4
4
  import { getFeishuRuntime } from "./runtime.js";
package/src/wiki.ts CHANGED
@@ -1,18 +1,14 @@
1
1
  import type * as Lark from "@larksuiteoapi/node-sdk";
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/feishu";
3
3
  import { listEnabledFeishuAccounts } from "./accounts.js";
4
4
  import { createFeishuToolClient, resolveAnyEnabledFeishuToolsConfig } from "./tool-account.js";
5
+ import {
6
+ jsonToolResult,
7
+ toolExecutionErrorResult,
8
+ unknownToolActionResult,
9
+ } from "./tool-result.js";
5
10
  import { FeishuWikiSchema, type FeishuWikiParams } from "./wiki-schema.js";
6
11
 
7
- // ============ Helpers ============
8
-
9
- function json(data: unknown) {
10
- return {
11
- content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }],
12
- details: data,
13
- };
14
- }
15
-
16
12
  type ObjType = "doc" | "sheet" | "mindnote" | "bitable" | "file" | "docx" | "slides";
17
13
 
18
14
  // ============ Actions ============
@@ -194,22 +190,22 @@ export function registerFeishuWikiTools(api: OpenClawPluginApi) {
194
190
  });
195
191
  switch (p.action) {
196
192
  case "spaces":
197
- return json(await listSpaces(client));
193
+ return jsonToolResult(await listSpaces(client));
198
194
  case "nodes":
199
- return json(await listNodes(client, p.space_id, p.parent_node_token));
195
+ return jsonToolResult(await listNodes(client, p.space_id, p.parent_node_token));
200
196
  case "get":
201
- return json(await getNode(client, p.token));
197
+ return jsonToolResult(await getNode(client, p.token));
202
198
  case "search":
203
- return json({
199
+ return jsonToolResult({
204
200
  error:
205
201
  "Search is not available. Use feishu_wiki with action: 'nodes' to browse or action: 'get' to lookup by token.",
206
202
  });
207
203
  case "create":
208
- return json(
204
+ return jsonToolResult(
209
205
  await createNode(client, p.space_id, p.title, p.obj_type, p.parent_node_token),
210
206
  );
211
207
  case "move":
212
- return json(
208
+ return jsonToolResult(
213
209
  await moveNode(
214
210
  client,
215
211
  p.space_id,
@@ -219,13 +215,13 @@ export function registerFeishuWikiTools(api: OpenClawPluginApi) {
219
215
  ),
220
216
  );
221
217
  case "rename":
222
- return json(await renameNode(client, p.space_id, p.node_token, p.title));
218
+ return jsonToolResult(await renameNode(client, p.space_id, p.node_token, p.title));
223
219
  default:
224
220
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- exhaustive check fallback
225
- return json({ error: `Unknown action: ${(p as any).action}` });
221
+ return unknownToolActionResult((p as { action?: unknown }).action);
226
222
  }
227
223
  } catch (err) {
228
- return json({ error: err instanceof Error ? err.message : String(err) });
224
+ return toolExecutionErrorResult(err);
229
225
  }
230
226
  },
231
227
  };