@elizaos/plugin-feishu 2.0.0-alpha.6 → 2.0.0-beta.1

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/dist/index.js CHANGED
@@ -1,3 +1,257 @@
1
+ // src/index.ts
2
+ import { getConnectorAccountManager, logger as logger3 } from "@elizaos/core";
3
+
4
+ // src/accounts.ts
5
+ var DEFAULT_ACCOUNT_ID = "default";
6
+ function normalizeAccountId(accountId) {
7
+ if (!accountId || typeof accountId !== "string") {
8
+ return DEFAULT_ACCOUNT_ID;
9
+ }
10
+ const trimmed = accountId.trim().toLowerCase();
11
+ if (!trimmed || trimmed === "default") {
12
+ return DEFAULT_ACCOUNT_ID;
13
+ }
14
+ return trimmed;
15
+ }
16
+ function getMultiAccountConfig(runtime) {
17
+ const characterFeishu = runtime.character?.settings?.feishu;
18
+ return {
19
+ enabled: characterFeishu?.enabled,
20
+ appId: characterFeishu?.appId,
21
+ appSecret: characterFeishu?.appSecret,
22
+ appSecretFile: characterFeishu?.appSecretFile,
23
+ encryptKey: characterFeishu?.encryptKey,
24
+ verificationToken: characterFeishu?.verificationToken,
25
+ apiUrl: characterFeishu?.apiUrl,
26
+ dmPolicy: characterFeishu?.dmPolicy,
27
+ groupPolicy: characterFeishu?.groupPolicy,
28
+ mediaMaxMb: characterFeishu?.mediaMaxMb,
29
+ textChunkLimit: characterFeishu?.textChunkLimit,
30
+ webhookPath: characterFeishu?.webhookPath,
31
+ accounts: characterFeishu?.accounts,
32
+ groups: characterFeishu?.groups
33
+ };
34
+ }
35
+ function listFeishuAccountIds(runtime) {
36
+ const config = getMultiAccountConfig(runtime);
37
+ const accounts = config.accounts;
38
+ const ids = new Set;
39
+ const envAppId = runtime.getSetting("FEISHU_APP_ID");
40
+ const envAppSecret = runtime.getSetting("FEISHU_APP_SECRET");
41
+ const baseConfigured = Boolean(config.appId?.trim() && (config.appSecret?.trim() || config.appSecretFile));
42
+ const envConfigured = Boolean(envAppId?.trim() && envAppSecret?.trim());
43
+ if (baseConfigured || envConfigured) {
44
+ ids.add(DEFAULT_ACCOUNT_ID);
45
+ }
46
+ if (accounts && typeof accounts === "object") {
47
+ for (const id of Object.keys(accounts)) {
48
+ if (id) {
49
+ ids.add(normalizeAccountId(id));
50
+ }
51
+ }
52
+ }
53
+ const result = Array.from(ids);
54
+ if (result.length === 0) {
55
+ return [DEFAULT_ACCOUNT_ID];
56
+ }
57
+ return result.toSorted((a, b) => a.localeCompare(b));
58
+ }
59
+ function resolveDefaultFeishuAccountId(runtime) {
60
+ const ids = listFeishuAccountIds(runtime);
61
+ if (ids.includes(DEFAULT_ACCOUNT_ID)) {
62
+ return DEFAULT_ACCOUNT_ID;
63
+ }
64
+ return ids[0] ?? DEFAULT_ACCOUNT_ID;
65
+ }
66
+ function getAccountConfig(runtime, accountId) {
67
+ const config = getMultiAccountConfig(runtime);
68
+ const accounts = config.accounts;
69
+ if (!accounts || typeof accounts !== "object") {
70
+ return;
71
+ }
72
+ const direct = accounts[accountId];
73
+ if (direct) {
74
+ return direct;
75
+ }
76
+ const normalized = normalizeAccountId(accountId);
77
+ const matchKey = Object.keys(accounts).find((key) => normalizeAccountId(key) === normalized);
78
+ return matchKey ? accounts[matchKey] : undefined;
79
+ }
80
+ function mergeFeishuAccountConfig(runtime, accountId) {
81
+ const multiConfig = getMultiAccountConfig(runtime);
82
+ const { accounts: _ignored, ...baseConfig } = multiConfig;
83
+ const accountConfig = getAccountConfig(runtime, accountId) ?? {};
84
+ const envAppId = runtime.getSetting("FEISHU_APP_ID");
85
+ const envAppSecret = runtime.getSetting("FEISHU_APP_SECRET");
86
+ const envEncryptKey = runtime.getSetting("FEISHU_ENCRYPT_KEY");
87
+ const envVerificationToken = runtime.getSetting("FEISHU_VERIFICATION_TOKEN");
88
+ const envDmPolicy = runtime.getSetting("FEISHU_DM_POLICY");
89
+ const envGroupPolicy = runtime.getSetting("FEISHU_GROUP_POLICY");
90
+ const envConfig = {
91
+ appId: envAppId || undefined,
92
+ appSecret: envAppSecret || undefined,
93
+ encryptKey: envEncryptKey || undefined,
94
+ verificationToken: envVerificationToken || undefined,
95
+ dmPolicy: envDmPolicy,
96
+ groupPolicy: envGroupPolicy
97
+ };
98
+ return {
99
+ ...envConfig,
100
+ ...baseConfig,
101
+ ...accountConfig
102
+ };
103
+ }
104
+ function resolveFeishuAccount(runtime, accountId) {
105
+ const normalizedAccountId = normalizeAccountId(accountId);
106
+ const multiConfig = getMultiAccountConfig(runtime);
107
+ const baseEnabled = multiConfig.enabled !== false;
108
+ const merged = mergeFeishuAccountConfig(runtime, normalizedAccountId);
109
+ const accountEnabled = merged.enabled !== false;
110
+ const enabled = baseEnabled && accountEnabled;
111
+ const appId = merged.appId?.trim() || "";
112
+ const appSecret = merged.appSecret?.trim() || "";
113
+ let tokenSource = "none";
114
+ if (merged.appSecret?.trim()) {
115
+ tokenSource = "config";
116
+ } else {
117
+ const envAppSecret = runtime.getSetting("FEISHU_APP_SECRET");
118
+ if (envAppSecret?.trim()) {
119
+ tokenSource = "env";
120
+ }
121
+ }
122
+ if (!appId || !appSecret) {
123
+ tokenSource = "none";
124
+ }
125
+ const configured = Boolean(appId && appSecret);
126
+ const name = merged.name?.trim() || merged.botName?.trim() || undefined;
127
+ return {
128
+ accountId: normalizedAccountId,
129
+ enabled,
130
+ name,
131
+ appId,
132
+ appSecret,
133
+ tokenSource,
134
+ configured,
135
+ config: merged
136
+ };
137
+ }
138
+ function listEnabledFeishuAccounts(runtime) {
139
+ return listFeishuAccountIds(runtime).map((accountId) => resolveFeishuAccount(runtime, accountId)).filter((account) => account.enabled && account.configured);
140
+ }
141
+ function isMultiAccountEnabled(runtime) {
142
+ const accounts = listEnabledFeishuAccounts(runtime);
143
+ return accounts.length > 1;
144
+ }
145
+ function resolveFeishuGroupConfig(runtime, accountId, groupId) {
146
+ const multiConfig = getMultiAccountConfig(runtime);
147
+ const accountConfig = getAccountConfig(runtime, accountId);
148
+ const accountGroup = accountConfig?.groups?.[groupId];
149
+ if (accountGroup) {
150
+ return accountGroup;
151
+ }
152
+ return multiConfig.groups?.[groupId];
153
+ }
154
+ function isFeishuUserAllowed(params) {
155
+ const { userId, accountConfig, isGroup, groupConfig } = params;
156
+ if (isGroup) {
157
+ const policy2 = accountConfig.groupPolicy ?? "allowlist";
158
+ if (policy2 === "disabled") {
159
+ return false;
160
+ }
161
+ if (policy2 === "open") {
162
+ return true;
163
+ }
164
+ if (groupConfig?.allowFrom?.length) {
165
+ return groupConfig.allowFrom.some((allowed) => String(allowed) === userId);
166
+ }
167
+ if (accountConfig.groupAllowFrom?.length) {
168
+ return accountConfig.groupAllowFrom.some((allowed) => String(allowed) === userId);
169
+ }
170
+ return policy2 !== "allowlist";
171
+ }
172
+ const policy = accountConfig.dmPolicy ?? "pairing";
173
+ if (policy === "disabled") {
174
+ return false;
175
+ }
176
+ if (policy === "open") {
177
+ return true;
178
+ }
179
+ if (policy === "pairing") {
180
+ return true;
181
+ }
182
+ if (accountConfig.allowFrom?.length) {
183
+ return accountConfig.allowFrom.some((allowed) => String(allowed) === userId);
184
+ }
185
+ return false;
186
+ }
187
+ function isFeishuMentionRequired(params) {
188
+ const { groupConfig } = params;
189
+ return groupConfig?.requireMention ?? false;
190
+ }
191
+
192
+ // src/connector-account-provider.ts
193
+ var FEISHU_PROVIDER_ID = "feishu";
194
+ function purposeForAccount(_account) {
195
+ return ["messaging"];
196
+ }
197
+ function accessGateForAccount(account) {
198
+ const dmPolicy = account.config?.dmPolicy;
199
+ if (dmPolicy === "pairing")
200
+ return "pairing";
201
+ if (dmPolicy === "disabled")
202
+ return "disabled";
203
+ return "open";
204
+ }
205
+ function toConnectorAccount(account) {
206
+ const now = Date.now();
207
+ return {
208
+ id: normalizeAccountId(account.accountId),
209
+ provider: FEISHU_PROVIDER_ID,
210
+ label: account.name ?? account.accountId,
211
+ role: "AGENT",
212
+ purpose: purposeForAccount(account),
213
+ accessGate: accessGateForAccount(account),
214
+ status: account.enabled && account.configured ? "connected" : "disabled",
215
+ externalId: account.appId || undefined,
216
+ createdAt: now,
217
+ updatedAt: now,
218
+ metadata: {
219
+ tokenSource: account.tokenSource,
220
+ dmPolicy: account.config?.dmPolicy ?? "open",
221
+ groupPolicy: account.config?.groupPolicy ?? "allowlist",
222
+ appId: account.appId || ""
223
+ }
224
+ };
225
+ }
226
+ function createFeishuConnectorAccountProvider(runtime) {
227
+ return {
228
+ provider: FEISHU_PROVIDER_ID,
229
+ label: "Feishu",
230
+ listAccounts: async (_manager) => {
231
+ const enabled = listEnabledFeishuAccounts(runtime);
232
+ if (enabled.length > 0) {
233
+ return enabled.map(toConnectorAccount);
234
+ }
235
+ const fallback = resolveFeishuAccount(runtime, DEFAULT_ACCOUNT_ID);
236
+ return [toConnectorAccount(fallback)];
237
+ },
238
+ createAccount: async (input, _manager) => {
239
+ return {
240
+ ...input,
241
+ provider: FEISHU_PROVIDER_ID,
242
+ role: input.role ?? "AGENT",
243
+ purpose: input.purpose ?? ["messaging"],
244
+ accessGate: input.accessGate ?? "open",
245
+ status: input.status ?? "pending"
246
+ };
247
+ },
248
+ patchAccount: async (_accountId, patch, _manager) => {
249
+ return { ...patch, provider: FEISHU_PROVIDER_ID };
250
+ },
251
+ deleteAccount: async (_accountId, _manager) => {}
252
+ };
253
+ }
254
+
1
255
  // src/constants.ts
2
256
  var FEISHU_SERVICE_NAME = "feishu";
3
257
  var FEISHU_DOMAINS = {
@@ -7,79 +261,6 @@ var FEISHU_DOMAINS = {
7
261
  var MAX_MESSAGE_LENGTH = 4000;
8
262
  var DEFAULT_TIMEOUT_MS = 30000;
9
263
 
10
- // src/actions/sendMessage.ts
11
- var SEND_MESSAGE_ACTION = "SEND_FEISHU_MESSAGE";
12
- var sendMessageAction = {
13
- name: SEND_MESSAGE_ACTION,
14
- similes: [
15
- "FEISHU_SEND_MESSAGE",
16
- "FEISHU_REPLY",
17
- "FEISHU_MESSAGE",
18
- "SEND_FEISHU",
19
- "REPLY_FEISHU",
20
- "LARK_SEND_MESSAGE",
21
- "LARK_REPLY",
22
- "SEND_LARK"
23
- ],
24
- description: "Send a message to a Feishu/Lark chat",
25
- validate: async (_runtime, message) => {
26
- return message.content?.source === "feishu";
27
- },
28
- handler: async (runtime, message, state, _options, callback) => {
29
- const feishuService = runtime.getService(FEISHU_SERVICE_NAME);
30
- if (!feishuService) {
31
- if (callback) {
32
- await callback({
33
- text: "Feishu service not available"
34
- });
35
- }
36
- return { success: false, error: "Feishu service not initialized" };
37
- }
38
- const currentState = state ?? await runtime.composeState(message);
39
- const responseText = currentState.values?.response?.toString() || "";
40
- const chatId = message.content?.chatId;
41
- if (!chatId) {
42
- if (callback) {
43
- await callback({
44
- text: "No chat ID available"
45
- });
46
- }
47
- return { success: false, error: "Missing chat ID" };
48
- }
49
- if (callback) {
50
- await callback({
51
- text: responseText,
52
- action: SEND_MESSAGE_ACTION
53
- });
54
- }
55
- return {
56
- success: true,
57
- data: {
58
- action: SEND_MESSAGE_ACTION,
59
- chatId,
60
- text: responseText,
61
- replyToMessageId: message.content?.messageId
62
- }
63
- };
64
- },
65
- examples: [
66
- [
67
- {
68
- name: "{{name1}}",
69
- content: {
70
- text: "Send a message to this Feishu chat"
71
- }
72
- },
73
- {
74
- name: "{{agentName}}",
75
- content: {
76
- text: "I'll send a message to this chat now.",
77
- actions: [SEND_MESSAGE_ACTION]
78
- }
79
- }
80
- ]
81
- ]
82
- };
83
264
  // src/messageManager.ts
84
265
  import {
85
266
  ChannelType,
@@ -438,35 +619,6 @@ ${line}` : line;
438
619
  }
439
620
  }
440
621
 
441
- // src/providers/chatState.ts
442
- var CHAT_STATE_PROVIDER = "FEISHU_CHAT_STATE";
443
- var chatStateProvider = {
444
- name: CHAT_STATE_PROVIDER,
445
- description: "Provides Feishu chat context and state information",
446
- dynamic: true,
447
- get: async (_runtime, message, state) => {
448
- if (message.content?.source !== "feishu") {
449
- return { text: "" };
450
- }
451
- const chatId = message.content?.chatId;
452
- const messageId = message.content?.messageId;
453
- if (!chatId) {
454
- return { text: "" };
455
- }
456
- const stateInfo = [`Platform: Feishu/Lark`, `Chat ID: ${chatId}`];
457
- if (messageId) {
458
- stateInfo.push(`Message ID: ${messageId}`);
459
- }
460
- if (state?.values?.feishuChatType) {
461
- stateInfo.push(`Chat Type: ${state.values.feishuChatType}`);
462
- }
463
- if (state?.values?.feishuChatName) {
464
- stateInfo.push(`Chat Name: ${state.values.feishuChatName}`);
465
- }
466
- return { text: stateInfo.join(`
467
- `) };
468
- }
469
- };
470
622
  // src/service.ts
471
623
  import {
472
624
  ChannelType as ChannelType2,
@@ -476,6 +628,70 @@ import {
476
628
  Service
477
629
  } from "@elizaos/core";
478
630
  import * as lark from "@larksuiteoapi/node-sdk";
631
+ function normalizeFeishuQuery(query) {
632
+ return query.trim().toLowerCase();
633
+ }
634
+ function scoreFeishuCandidate(values, query) {
635
+ const normalized = normalizeFeishuQuery(query);
636
+ if (!normalized) {
637
+ return 0.45;
638
+ }
639
+ const candidates = values.filter((value) => typeof value === "string" && value.trim().length > 0).map((value) => value.trim().toLowerCase());
640
+ if (candidates.some((candidate) => candidate === normalized)) {
641
+ return 1;
642
+ }
643
+ return candidates.some((candidate) => candidate.includes(normalized)) ? 0.8 : 0;
644
+ }
645
+ function feishuChatToConnectorTarget(chat, score = 0.55, roomId) {
646
+ return {
647
+ target: {
648
+ source: FEISHU_SERVICE_NAME,
649
+ channelId: chat.chatId,
650
+ roomId
651
+ },
652
+ label: chat.name || chat.chatId,
653
+ kind: chat.chatType === "p2p" /* P2P */ ? "user" : "group",
654
+ description: chat.description || "Feishu/Lark chat",
655
+ score,
656
+ contexts: ["social", "connectors"],
657
+ metadata: {
658
+ chatType: chat.chatType,
659
+ ownerOpenId: chat.ownerOpenId,
660
+ tenantKey: chat.tenantKey
661
+ }
662
+ };
663
+ }
664
+ function normalizeConnectorLimit(limit, fallback = 50) {
665
+ if (!Number.isFinite(limit) || !limit || limit <= 0) {
666
+ return fallback;
667
+ }
668
+ return Math.min(Math.floor(limit), 200);
669
+ }
670
+ async function readStoredMessageMemories(runtime, roomId, limit) {
671
+ return runtime.getMemories({
672
+ tableName: "messages",
673
+ roomId,
674
+ limit,
675
+ orderBy: "createdAt",
676
+ orderDirection: "desc"
677
+ });
678
+ }
679
+ async function readStoredMessagesForTargets(runtime, targets, limit) {
680
+ const roomIds = Array.from(new Set(targets.map((target) => target.target.roomId).filter((id) => Boolean(id))));
681
+ const chunks = await Promise.all(roomIds.map((roomId) => readStoredMessageMemories(runtime, roomId, limit)));
682
+ return chunks.flat().sort((left, right) => (right.createdAt ?? 0) - (left.createdAt ?? 0)).slice(0, limit);
683
+ }
684
+ function filterMemoriesByQuery(memories, query, limit) {
685
+ const normalized = query.trim().toLowerCase();
686
+ if (!normalized) {
687
+ return memories.slice(0, limit);
688
+ }
689
+ return memories.filter((memory) => {
690
+ const text = typeof memory.content?.text === "string" ? memory.content.text : "";
691
+ return text.toLowerCase().includes(normalized);
692
+ }).slice(0, limit);
693
+ }
694
+
479
695
  class FeishuService extends Service {
480
696
  static serviceType = FEISHU_SERVICE_NAME;
481
697
  capabilityDescription = "The agent is able to send and receive messages on Feishu/Lark";
@@ -768,8 +984,103 @@ class FeishuService extends Service {
768
984
  }
769
985
  static registerSendHandlers(runtime, serviceInstance) {
770
986
  if (serviceInstance?.client && serviceInstance?.messageManager) {
771
- runtime.registerSendHandler("feishu", serviceInstance.handleSendMessage.bind(serviceInstance));
772
- logger2.info("[Feishu] Registered send handler");
987
+ const sendHandler = async (handlerRuntime, target, content) => {
988
+ await serviceInstance.handleSendMessage(handlerRuntime, target, content);
989
+ return;
990
+ };
991
+ if (typeof runtime.registerMessageConnector === "function") {
992
+ const registration = {
993
+ source: FEISHU_SERVICE_NAME,
994
+ label: "Feishu/Lark",
995
+ capabilities: [
996
+ "send_message",
997
+ "send_card",
998
+ "send_image",
999
+ "send_file"
1000
+ ],
1001
+ supportedTargetKinds: ["group", "room", "user", "channel"],
1002
+ contexts: ["social", "connectors"],
1003
+ description: "Send Feishu/Lark text, card, image, and file messages to known chats.",
1004
+ sendHandler,
1005
+ resolveTargets: async (query, context) => {
1006
+ const chats = await serviceInstance.listConnectorChats(context.runtime);
1007
+ return chats.map(({ chat, roomId }) => ({
1008
+ chat,
1009
+ roomId,
1010
+ score: scoreFeishuCandidate([chat.chatId, chat.name, chat.description, chat.ownerOpenId], query)
1011
+ })).filter(({ score }) => score > 0).sort((left, right) => right.score - left.score).slice(0, 10).map(({ chat, score, roomId }) => feishuChatToConnectorTarget(chat, score, roomId));
1012
+ },
1013
+ listRecentTargets: async (context) => (await serviceInstance.listConnectorChats(context.runtime)).slice(0, 10).map(({ chat, roomId }) => feishuChatToConnectorTarget(chat, 0.55, roomId)),
1014
+ listRooms: async (context) => (await serviceInstance.listConnectorChats(context.runtime)).map(({ chat, roomId }) => feishuChatToConnectorTarget(chat, 0.55, roomId)),
1015
+ fetchMessages: async (context, params) => {
1016
+ const limit = normalizeConnectorLimit(params?.limit);
1017
+ const target = params?.target ?? context.target;
1018
+ if (target?.roomId) {
1019
+ return readStoredMessageMemories(context.runtime, target.roomId, limit);
1020
+ }
1021
+ const targets = (await serviceInstance.listConnectorChats(context.runtime)).slice(0, 10).map(({ chat, roomId }) => feishuChatToConnectorTarget(chat, 0.55, roomId));
1022
+ return readStoredMessagesForTargets(context.runtime, targets, limit);
1023
+ },
1024
+ searchMessages: async (context, params) => {
1025
+ const limit = normalizeConnectorLimit(params?.limit);
1026
+ const target = params?.target ?? context.target;
1027
+ const messages = target?.roomId ? await readStoredMessageMemories(context.runtime, target.roomId, Math.max(limit, 100)) : await readStoredMessagesForTargets(context.runtime, (await serviceInstance.listConnectorChats(context.runtime)).slice(0, 10).map(({ chat, roomId }) => feishuChatToConnectorTarget(chat, 0.55, roomId)), Math.max(limit, 100));
1028
+ return filterMemoriesByQuery(messages, params.query, limit);
1029
+ },
1030
+ getChatContext: async (target, context) => {
1031
+ const room = target.roomId ? await context.runtime.getRoom(target.roomId) : null;
1032
+ const chatId = String(target.channelId ?? room?.channelId ?? "").trim();
1033
+ if (!chatId) {
1034
+ return null;
1035
+ }
1036
+ const chat = serviceInstance.knownChats.get(chatId) || {
1037
+ chatId,
1038
+ chatType: room?.type === ChannelType2.DM ? "p2p" /* P2P */ : "group" /* GROUP */,
1039
+ name: room?.name
1040
+ };
1041
+ return {
1042
+ target: {
1043
+ source: FEISHU_SERVICE_NAME,
1044
+ roomId: target.roomId,
1045
+ channelId: chatId
1046
+ },
1047
+ label: chat.name || chat.chatId,
1048
+ summary: chat.chatType === "p2p" /* P2P */ ? "Feishu/Lark direct chat" : "Feishu/Lark group chat",
1049
+ metadata: {
1050
+ chatType: chat.chatType,
1051
+ ownerOpenId: chat.ownerOpenId,
1052
+ tenantKey: chat.tenantKey
1053
+ }
1054
+ };
1055
+ },
1056
+ getUserContext: async (entityId, context) => {
1057
+ const entity = typeof context.runtime.getEntityById === "function" ? await context.runtime.getEntityById(String(entityId)) : null;
1058
+ if (!entity) {
1059
+ return null;
1060
+ }
1061
+ return {
1062
+ entityId,
1063
+ label: entity.names?.[0],
1064
+ aliases: entity.names,
1065
+ handles: {},
1066
+ metadata: entity.metadata
1067
+ };
1068
+ },
1069
+ getUser: async (handlerRuntime, params) => {
1070
+ const lookupParams = params;
1071
+ const entityId = String(lookupParams.entityId ?? params.userId ?? params.username ?? params.handle ?? params.target?.entityId ?? "").trim();
1072
+ if (!entityId || typeof handlerRuntime.getEntityById !== "function") {
1073
+ return null;
1074
+ }
1075
+ const entity = await handlerRuntime.getEntityById(entityId).catch(() => null);
1076
+ return entity;
1077
+ }
1078
+ };
1079
+ runtime.registerMessageConnector(registration);
1080
+ } else {
1081
+ runtime.registerSendHandler(FEISHU_SERVICE_NAME, sendHandler);
1082
+ }
1083
+ logger2.info("[Feishu] Registered message connector");
773
1084
  } else {
774
1085
  logger2.warn("[Feishu] Cannot register send handler - client not initialized");
775
1086
  }
@@ -798,206 +1109,87 @@ class FeishuService extends Service {
798
1109
  text: content.text || ""
799
1110
  };
800
1111
  const contentData = content.data;
801
- if (contentData?.card) {
802
- feishuContent.card = contentData.card;
1112
+ const feishuData = contentData?.feishu && typeof contentData.feishu === "object" ? contentData.feishu : contentData;
1113
+ if (feishuData?.card) {
1114
+ feishuContent.card = feishuData.card;
803
1115
  }
804
- if (contentData?.imageKey) {
805
- feishuContent.imageKey = contentData.imageKey;
1116
+ if (feishuData?.imageKey) {
1117
+ feishuContent.imageKey = feishuData.imageKey;
806
1118
  }
807
- if (contentData?.fileKey) {
808
- feishuContent.fileKey = contentData.fileKey;
1119
+ if (feishuData?.fileKey) {
1120
+ feishuContent.fileKey = feishuData.fileKey;
809
1121
  }
810
1122
  await this.messageManager.sendMessage(chatId, feishuContent);
811
1123
  logger2.info(`[Feishu] Message sent to chat ID: ${chatId}`);
812
1124
  }
813
- }
814
-
815
- // src/accounts.ts
816
- var DEFAULT_ACCOUNT_ID = "default";
817
- function normalizeAccountId(accountId) {
818
- if (!accountId || typeof accountId !== "string") {
819
- return DEFAULT_ACCOUNT_ID;
820
- }
821
- const trimmed = accountId.trim().toLowerCase();
822
- if (!trimmed || trimmed === "default") {
823
- return DEFAULT_ACCOUNT_ID;
824
- }
825
- return trimmed;
826
- }
827
- function getMultiAccountConfig(runtime) {
828
- const characterFeishu = runtime.character?.settings?.feishu;
829
- return {
830
- enabled: characterFeishu?.enabled,
831
- appId: characterFeishu?.appId,
832
- appSecret: characterFeishu?.appSecret,
833
- appSecretFile: characterFeishu?.appSecretFile,
834
- encryptKey: characterFeishu?.encryptKey,
835
- verificationToken: characterFeishu?.verificationToken,
836
- apiUrl: characterFeishu?.apiUrl,
837
- dmPolicy: characterFeishu?.dmPolicy,
838
- groupPolicy: characterFeishu?.groupPolicy,
839
- mediaMaxMb: characterFeishu?.mediaMaxMb,
840
- textChunkLimit: characterFeishu?.textChunkLimit,
841
- webhookPath: characterFeishu?.webhookPath,
842
- accounts: characterFeishu?.accounts,
843
- groups: characterFeishu?.groups
844
- };
845
- }
846
- function listFeishuAccountIds(runtime) {
847
- const config = getMultiAccountConfig(runtime);
848
- const accounts = config.accounts;
849
- const ids = new Set;
850
- const envAppId = runtime.getSetting("FEISHU_APP_ID");
851
- const envAppSecret = runtime.getSetting("FEISHU_APP_SECRET");
852
- const baseConfigured = Boolean(config.appId?.trim() && (config.appSecret?.trim() || config.appSecretFile));
853
- const envConfigured = Boolean(envAppId?.trim() && envAppSecret?.trim());
854
- if (baseConfigured || envConfigured) {
855
- ids.add(DEFAULT_ACCOUNT_ID);
856
- }
857
- if (accounts && typeof accounts === "object") {
858
- for (const id of Object.keys(accounts)) {
859
- if (id) {
860
- ids.add(normalizeAccountId(id));
861
- }
862
- }
863
- }
864
- const result = Array.from(ids);
865
- if (result.length === 0) {
866
- return [DEFAULT_ACCOUNT_ID];
867
- }
868
- return result.toSorted((a, b) => a.localeCompare(b));
869
- }
870
- function resolveDefaultFeishuAccountId(runtime) {
871
- const ids = listFeishuAccountIds(runtime);
872
- if (ids.includes(DEFAULT_ACCOUNT_ID)) {
873
- return DEFAULT_ACCOUNT_ID;
874
- }
875
- return ids[0] ?? DEFAULT_ACCOUNT_ID;
876
- }
877
- function getAccountConfig(runtime, accountId) {
878
- const config = getMultiAccountConfig(runtime);
879
- const accounts = config.accounts;
880
- if (!accounts || typeof accounts !== "object") {
881
- return;
882
- }
883
- const direct = accounts[accountId];
884
- if (direct) {
885
- return direct;
886
- }
887
- const normalized = normalizeAccountId(accountId);
888
- const matchKey = Object.keys(accounts).find((key) => normalizeAccountId(key) === normalized);
889
- return matchKey ? accounts[matchKey] : undefined;
890
- }
891
- function mergeFeishuAccountConfig(runtime, accountId) {
892
- const multiConfig = getMultiAccountConfig(runtime);
893
- const { accounts: _ignored, ...baseConfig } = multiConfig;
894
- const accountConfig = getAccountConfig(runtime, accountId) ?? {};
895
- const envAppId = runtime.getSetting("FEISHU_APP_ID");
896
- const envAppSecret = runtime.getSetting("FEISHU_APP_SECRET");
897
- const envEncryptKey = runtime.getSetting("FEISHU_ENCRYPT_KEY");
898
- const envVerificationToken = runtime.getSetting("FEISHU_VERIFICATION_TOKEN");
899
- const envDmPolicy = runtime.getSetting("FEISHU_DM_POLICY");
900
- const envGroupPolicy = runtime.getSetting("FEISHU_GROUP_POLICY");
901
- const envConfig = {
902
- appId: envAppId || undefined,
903
- appSecret: envAppSecret || undefined,
904
- encryptKey: envEncryptKey || undefined,
905
- verificationToken: envVerificationToken || undefined,
906
- dmPolicy: envDmPolicy,
907
- groupPolicy: envGroupPolicy
908
- };
909
- return {
910
- ...envConfig,
911
- ...baseConfig,
912
- ...accountConfig
913
- };
914
- }
915
- function resolveFeishuAccount(runtime, accountId) {
916
- const normalizedAccountId = normalizeAccountId(accountId);
917
- const multiConfig = getMultiAccountConfig(runtime);
918
- const baseEnabled = multiConfig.enabled !== false;
919
- const merged = mergeFeishuAccountConfig(runtime, normalizedAccountId);
920
- const accountEnabled = merged.enabled !== false;
921
- const enabled = baseEnabled && accountEnabled;
922
- const appId = merged.appId?.trim() || "";
923
- const appSecret = merged.appSecret?.trim() || "";
924
- let tokenSource = "none";
925
- if (merged.appSecret?.trim()) {
926
- tokenSource = "config";
927
- } else {
928
- const envAppSecret = runtime.getSetting("FEISHU_APP_SECRET");
929
- if (envAppSecret?.trim()) {
930
- tokenSource = "env";
931
- }
932
- }
933
- if (!appId || !appSecret) {
934
- tokenSource = "none";
1125
+ async sendRoomMessage(target, content) {
1126
+ await this.handleSendMessage(this.runtime, { source: FEISHU_SERVICE_NAME, channelId: target }, content);
935
1127
  }
936
- const configured = Boolean(appId && appSecret);
937
- const name = merged.name?.trim() || merged.botName?.trim() || undefined;
938
- return {
939
- accountId: normalizedAccountId,
940
- enabled,
941
- name,
942
- appId,
943
- appSecret,
944
- tokenSource,
945
- configured,
946
- config: merged
947
- };
948
- }
949
- function listEnabledFeishuAccounts(runtime) {
950
- return listFeishuAccountIds(runtime).map((accountId) => resolveFeishuAccount(runtime, accountId)).filter((account) => account.enabled && account.configured);
951
- }
952
- function isMultiAccountEnabled(runtime) {
953
- const accounts = listEnabledFeishuAccounts(runtime);
954
- return accounts.length > 1;
955
- }
956
- function resolveFeishuGroupConfig(runtime, accountId, groupId) {
957
- const multiConfig = getMultiAccountConfig(runtime);
958
- const accountConfig = getAccountConfig(runtime, accountId);
959
- const accountGroup = accountConfig?.groups?.[groupId];
960
- if (accountGroup) {
961
- return accountGroup;
1128
+ async sendDirectMessage(target, content) {
1129
+ await this.sendRoomMessage(target, content);
962
1130
  }
963
- return multiConfig.groups?.[groupId];
964
- }
965
- function isFeishuUserAllowed(params) {
966
- const { userId, accountConfig, isGroup, groupConfig } = params;
967
- if (isGroup) {
968
- const policy2 = accountConfig.groupPolicy ?? "allowlist";
969
- if (policy2 === "disabled") {
970
- return false;
1131
+ async listConnectorChats(runtime) {
1132
+ const chats = new Map;
1133
+ for (const chat of this.knownChats.values()) {
1134
+ chats.set(chat.chatId, { chat });
971
1135
  }
972
- if (policy2 === "open") {
973
- return true;
1136
+ if (typeof runtime.getRoomsForParticipant !== "function") {
1137
+ return Array.from(chats.values());
974
1138
  }
975
- if (groupConfig?.allowFrom?.length) {
976
- return groupConfig.allowFrom.some((allowed) => String(allowed) === userId);
977
- }
978
- if (accountConfig.groupAllowFrom?.length) {
979
- return accountConfig.groupAllowFrom.some((allowed) => String(allowed) === userId);
1139
+ const roomIds = await runtime.getRoomsForParticipant(runtime.agentId).catch(() => []);
1140
+ for (const roomId of roomIds) {
1141
+ const room = await runtime.getRoom(roomId).catch(() => null);
1142
+ if (room?.source !== FEISHU_SERVICE_NAME || !room.channelId) {
1143
+ continue;
1144
+ }
1145
+ const known = chats.get(room.channelId)?.chat;
1146
+ chats.set(room.channelId, {
1147
+ chat: known || {
1148
+ chatId: room.channelId,
1149
+ chatType: room.type === ChannelType2.DM ? "p2p" /* P2P */ : "group" /* GROUP */,
1150
+ name: room.name
1151
+ },
1152
+ roomId
1153
+ });
980
1154
  }
981
- return policy2 !== "allowlist";
1155
+ return Array.from(chats.values());
982
1156
  }
983
- const policy = accountConfig.dmPolicy ?? "pairing";
984
- if (policy === "disabled") {
985
- return false;
986
- }
987
- if (policy === "open") {
988
- return true;
989
- }
990
- if (policy === "pairing") {
991
- return true;
1157
+ }
1158
+
1159
+ // src/workflow-credential-provider.ts
1160
+ import { Service as Service2 } from "@elizaos/core";
1161
+ var WORKFLOW_CREDENTIAL_PROVIDER_TYPE = "workflow_credential_provider";
1162
+ var SUPPORTED = ["httpHeaderAuth"];
1163
+
1164
+ class FeishuWorkflowCredentialProvider extends Service2 {
1165
+ static serviceType = WORKFLOW_CREDENTIAL_PROVIDER_TYPE;
1166
+ capabilityDescription = "Supplies Feishu/Lark credentials to the workflow plugin.";
1167
+ static async start(runtime) {
1168
+ return new FeishuWorkflowCredentialProvider(runtime);
1169
+ }
1170
+ async stop() {}
1171
+ async resolve(_userId, credType) {
1172
+ if (credType !== "httpHeaderAuth")
1173
+ return null;
1174
+ const appId = this.runtime.getSetting("FEISHU_APP_ID");
1175
+ const appSecret = this.runtime.getSetting("FEISHU_APP_SECRET");
1176
+ if (!appId?.trim() || !appSecret?.trim())
1177
+ return null;
1178
+ return {
1179
+ status: "credential_data",
1180
+ data: {
1181
+ name: "X-Feishu-App-Id",
1182
+ value: appId.trim(),
1183
+ appSecret: appSecret.trim()
1184
+ }
1185
+ };
992
1186
  }
993
- if (accountConfig.allowFrom?.length) {
994
- return accountConfig.allowFrom.some((allowed) => String(allowed) === userId);
1187
+ checkCredentialTypes(credTypes) {
1188
+ return {
1189
+ supported: credTypes.filter((t) => SUPPORTED.includes(t)),
1190
+ unsupported: credTypes.filter((t) => !SUPPORTED.includes(t))
1191
+ };
995
1192
  }
996
- return false;
997
- }
998
- function isFeishuMentionRequired(params) {
999
- const { groupConfig } = params;
1000
- return groupConfig?.requireMention ?? false;
1001
1193
  }
1002
1194
  // src/formatting.ts
1003
1195
  var FEISHU_TEXT_CHUNK_LIMIT = 4000;
@@ -1341,17 +1533,30 @@ function isGroupChat(chatType) {
1341
1533
  var feishuPlugin = {
1342
1534
  name: FEISHU_SERVICE_NAME,
1343
1535
  description: "Feishu/Lark client plugin for elizaOS",
1344
- services: [FeishuService],
1345
- actions: [sendMessageAction],
1346
- providers: [chatStateProvider],
1347
- tests: []
1536
+ services: [FeishuService, FeishuWorkflowCredentialProvider],
1537
+ actions: [],
1538
+ providers: [],
1539
+ tests: [],
1540
+ autoEnable: {
1541
+ connectorKeys: ["feishu"]
1542
+ },
1543
+ init: async (_config, runtime) => {
1544
+ try {
1545
+ const manager = getConnectorAccountManager(runtime);
1546
+ manager.registerProvider(createFeishuConnectorAccountProvider(runtime));
1547
+ } catch (err) {
1548
+ logger3.warn({
1549
+ src: "plugin:feishu",
1550
+ err: err instanceof Error ? err.message : String(err)
1551
+ }, "Failed to register Feishu provider with ConnectorAccountManager");
1552
+ }
1553
+ }
1348
1554
  };
1349
1555
  var src_default = feishuPlugin;
1350
1556
  export {
1351
1557
  validateConfig,
1352
1558
  truncateText,
1353
1559
  stripMarkdown,
1354
- sendMessageAction,
1355
1560
  resolveFeishuSystemLocation,
1356
1561
  resolveFeishuGroupConfig,
1357
1562
  resolveFeishuAccount,
@@ -1372,8 +1577,6 @@ export {
1372
1577
  src_default as default,
1373
1578
  containsMarkdown,
1374
1579
  chunkFeishuText,
1375
- chatStateProvider,
1376
- SEND_MESSAGE_ACTION,
1377
1580
  MessageManager,
1378
1581
  MAX_MESSAGE_LENGTH,
1379
1582
  FeishuService,
@@ -1383,9 +1586,8 @@ export {
1383
1586
  FEISHU_SERVICE_NAME,
1384
1587
  FEISHU_DOMAINS,
1385
1588
  DEFAULT_TIMEOUT_MS,
1386
- DEFAULT_ACCOUNT_ID,
1387
- CHAT_STATE_PROVIDER
1589
+ DEFAULT_ACCOUNT_ID
1388
1590
  };
1389
1591
 
1390
- //# debugId=C18D17014C86A75D64756E2164756E21
1592
+ //# debugId=A7228C401E12666064756E2164756E21
1391
1593
  //# sourceMappingURL=index.js.map