@openclaw/feishu 2026.5.2-beta.2 → 2026.5.3-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.
Files changed (224) hide show
  1. package/dist/accounts-Ba3-WP1z.js +423 -0
  2. package/dist/api.js +2280 -0
  3. package/dist/app-registration-B8qc1MCM.js +184 -0
  4. package/dist/audio-preflight.runtime-BPlzkO3l.js +7 -0
  5. package/dist/card-interaction-BfRLgvw_.js +96 -0
  6. package/dist/channel-CSD_Jt8I.js +1668 -0
  7. package/dist/channel-entry.js +22 -0
  8. package/dist/channel-plugin-api.js +2 -0
  9. package/dist/channel.runtime-DYsXcD36.js +700 -0
  10. package/dist/client-DBVoQL5w.js +157 -0
  11. package/dist/contract-api.js +9 -0
  12. package/dist/conversation-id-DWS3Ep2A.js +139 -0
  13. package/dist/directory.static-f3EeoRJd.js +44 -0
  14. package/dist/drive-C5eJLJr7.js +883 -0
  15. package/dist/index.js +68 -0
  16. package/dist/monitor-CT189QfR.js +60 -0
  17. package/dist/monitor.account-dJV2jO8C.js +4990 -0
  18. package/dist/monitor.state-DYM02ipp.js +100 -0
  19. package/dist/policy-D6c-wMPl.js +118 -0
  20. package/dist/probe-BNzzU_uR.js +149 -0
  21. package/dist/rolldown-runtime-DUslC3ob.js +14 -0
  22. package/dist/runtime-CG0DuRCy.js +8 -0
  23. package/dist/runtime-api.js +14 -0
  24. package/dist/secret-contract-Dm4Z_zQN.js +119 -0
  25. package/dist/secret-contract-api.js +2 -0
  26. package/dist/security-audit-DqJdocrN.js +11 -0
  27. package/dist/security-audit-shared-ByuMx9cJ.js +38 -0
  28. package/dist/security-contract-api.js +2 -0
  29. package/dist/send-DowxxbpH.js +1218 -0
  30. package/dist/session-conversation-B4nrW-vo.js +27 -0
  31. package/dist/session-key-api.js +2 -0
  32. package/dist/setup-api.js +2 -0
  33. package/dist/setup-entry.js +15 -0
  34. package/dist/subagent-hooks-C3UhPVLV.js +227 -0
  35. package/dist/subagent-hooks-api.js +23 -0
  36. package/dist/targets-JMFJRKSe.js +48 -0
  37. package/dist/thread-bindings-BmS6TLes.js +222 -0
  38. package/package.json +15 -6
  39. package/api.ts +0 -31
  40. package/channel-entry.ts +0 -20
  41. package/channel-plugin-api.ts +0 -1
  42. package/contract-api.ts +0 -16
  43. package/index.ts +0 -82
  44. package/runtime-api.ts +0 -55
  45. package/secret-contract-api.ts +0 -5
  46. package/security-contract-api.ts +0 -1
  47. package/session-key-api.ts +0 -1
  48. package/setup-api.ts +0 -3
  49. package/setup-entry.test.ts +0 -14
  50. package/setup-entry.ts +0 -13
  51. package/src/accounts.test.ts +0 -459
  52. package/src/accounts.ts +0 -326
  53. package/src/app-registration.ts +0 -331
  54. package/src/approval-auth.test.ts +0 -24
  55. package/src/approval-auth.ts +0 -25
  56. package/src/async.test.ts +0 -35
  57. package/src/async.ts +0 -104
  58. package/src/audio-preflight.runtime.ts +0 -9
  59. package/src/bitable.test.ts +0 -131
  60. package/src/bitable.ts +0 -762
  61. package/src/bot-content.ts +0 -474
  62. package/src/bot-group-name.test.ts +0 -108
  63. package/src/bot-runtime-api.ts +0 -12
  64. package/src/bot-sender-name.ts +0 -125
  65. package/src/bot.broadcast.test.ts +0 -463
  66. package/src/bot.card-action.test.ts +0 -577
  67. package/src/bot.checkBotMentioned.test.ts +0 -265
  68. package/src/bot.helpers.test.ts +0 -118
  69. package/src/bot.stripBotMention.test.ts +0 -126
  70. package/src/bot.test.ts +0 -3040
  71. package/src/bot.ts +0 -1559
  72. package/src/card-action.ts +0 -447
  73. package/src/card-interaction.test.ts +0 -129
  74. package/src/card-interaction.ts +0 -159
  75. package/src/card-test-helpers.ts +0 -47
  76. package/src/card-ux-approval.ts +0 -65
  77. package/src/card-ux-launcher.test.ts +0 -99
  78. package/src/card-ux-launcher.ts +0 -121
  79. package/src/card-ux-shared.ts +0 -33
  80. package/src/channel-runtime-api.ts +0 -16
  81. package/src/channel.runtime.ts +0 -47
  82. package/src/channel.test.ts +0 -959
  83. package/src/channel.ts +0 -1313
  84. package/src/chat-schema.ts +0 -25
  85. package/src/chat.test.ts +0 -196
  86. package/src/chat.ts +0 -188
  87. package/src/client.test.ts +0 -433
  88. package/src/client.ts +0 -290
  89. package/src/comment-dispatcher-runtime-api.ts +0 -6
  90. package/src/comment-dispatcher.test.ts +0 -169
  91. package/src/comment-dispatcher.ts +0 -107
  92. package/src/comment-handler-runtime-api.ts +0 -3
  93. package/src/comment-handler.test.ts +0 -486
  94. package/src/comment-handler.ts +0 -309
  95. package/src/comment-reaction.test.ts +0 -166
  96. package/src/comment-reaction.ts +0 -259
  97. package/src/comment-shared.test.ts +0 -182
  98. package/src/comment-shared.ts +0 -406
  99. package/src/comment-target.ts +0 -44
  100. package/src/config-schema.test.ts +0 -309
  101. package/src/config-schema.ts +0 -333
  102. package/src/conversation-id.test.ts +0 -18
  103. package/src/conversation-id.ts +0 -199
  104. package/src/dedup-runtime-api.ts +0 -1
  105. package/src/dedup.ts +0 -141
  106. package/src/directory.static.ts +0 -61
  107. package/src/directory.test.ts +0 -136
  108. package/src/directory.ts +0 -124
  109. package/src/doc-schema.ts +0 -182
  110. package/src/docx-batch-insert.test.ts +0 -91
  111. package/src/docx-batch-insert.ts +0 -223
  112. package/src/docx-color-text.ts +0 -154
  113. package/src/docx-table-ops.test.ts +0 -53
  114. package/src/docx-table-ops.ts +0 -316
  115. package/src/docx-types.ts +0 -38
  116. package/src/docx.account-selection.test.ts +0 -79
  117. package/src/docx.test.ts +0 -685
  118. package/src/docx.ts +0 -1616
  119. package/src/drive-schema.ts +0 -92
  120. package/src/drive.test.ts +0 -1219
  121. package/src/drive.ts +0 -829
  122. package/src/dynamic-agent.ts +0 -137
  123. package/src/event-types.ts +0 -45
  124. package/src/external-keys.test.ts +0 -20
  125. package/src/external-keys.ts +0 -19
  126. package/src/lifecycle.test-support.ts +0 -220
  127. package/src/media.test.ts +0 -900
  128. package/src/media.ts +0 -861
  129. package/src/mention-target.types.ts +0 -5
  130. package/src/mention.ts +0 -114
  131. package/src/message-action-contract.ts +0 -13
  132. package/src/monitor-state-runtime-api.ts +0 -7
  133. package/src/monitor-transport-runtime-api.ts +0 -7
  134. package/src/monitor.account.ts +0 -468
  135. package/src/monitor.acp-init-failure.lifecycle.test-support.ts +0 -219
  136. package/src/monitor.bot-identity.ts +0 -86
  137. package/src/monitor.bot-menu-handler.ts +0 -165
  138. package/src/monitor.bot-menu.lifecycle.test-support.ts +0 -224
  139. package/src/monitor.bot-menu.test.ts +0 -178
  140. package/src/monitor.broadcast.reply-once.lifecycle.test-support.ts +0 -264
  141. package/src/monitor.card-action.lifecycle.test-support.ts +0 -373
  142. package/src/monitor.cleanup.test.ts +0 -376
  143. package/src/monitor.comment-notice-handler.ts +0 -105
  144. package/src/monitor.comment.test.ts +0 -937
  145. package/src/monitor.comment.ts +0 -1386
  146. package/src/monitor.lifecycle.test.ts +0 -4
  147. package/src/monitor.message-handler.ts +0 -339
  148. package/src/monitor.reaction.lifecycle.test-support.ts +0 -68
  149. package/src/monitor.reaction.test.ts +0 -713
  150. package/src/monitor.startup.test.ts +0 -192
  151. package/src/monitor.startup.ts +0 -74
  152. package/src/monitor.state.defaults.test.ts +0 -46
  153. package/src/monitor.state.ts +0 -170
  154. package/src/monitor.synthetic-error.ts +0 -18
  155. package/src/monitor.test-mocks.ts +0 -45
  156. package/src/monitor.transport.ts +0 -424
  157. package/src/monitor.ts +0 -100
  158. package/src/monitor.webhook-e2e.test.ts +0 -272
  159. package/src/monitor.webhook-security.test.ts +0 -264
  160. package/src/monitor.webhook.test-helpers.ts +0 -116
  161. package/src/outbound-runtime-api.ts +0 -1
  162. package/src/outbound.test.ts +0 -935
  163. package/src/outbound.ts +0 -718
  164. package/src/perm-schema.ts +0 -52
  165. package/src/perm.ts +0 -170
  166. package/src/pins.ts +0 -108
  167. package/src/policy.test.ts +0 -334
  168. package/src/policy.ts +0 -236
  169. package/src/post.test.ts +0 -105
  170. package/src/post.ts +0 -275
  171. package/src/probe.test.ts +0 -275
  172. package/src/probe.ts +0 -166
  173. package/src/processing-claims.ts +0 -59
  174. package/src/qr-terminal.ts +0 -1
  175. package/src/reactions.ts +0 -123
  176. package/src/reasoning-preview.test.ts +0 -59
  177. package/src/reasoning-preview.ts +0 -20
  178. package/src/reply-dispatcher-runtime-api.ts +0 -7
  179. package/src/reply-dispatcher.test.ts +0 -1144
  180. package/src/reply-dispatcher.ts +0 -650
  181. package/src/runtime.ts +0 -9
  182. package/src/secret-contract.ts +0 -145
  183. package/src/secret-input.ts +0 -1
  184. package/src/security-audit-shared.ts +0 -69
  185. package/src/security-audit.test.ts +0 -61
  186. package/src/security-audit.ts +0 -1
  187. package/src/send-result.ts +0 -29
  188. package/src/send-target.test.ts +0 -80
  189. package/src/send-target.ts +0 -35
  190. package/src/send.reply-fallback.test.ts +0 -292
  191. package/src/send.test.ts +0 -550
  192. package/src/send.ts +0 -800
  193. package/src/sequential-key.test.ts +0 -72
  194. package/src/sequential-key.ts +0 -28
  195. package/src/sequential-queue.test.ts +0 -92
  196. package/src/sequential-queue.ts +0 -16
  197. package/src/session-conversation.ts +0 -42
  198. package/src/session-route.ts +0 -48
  199. package/src/setup-core.ts +0 -51
  200. package/src/setup-surface.test.ts +0 -174
  201. package/src/setup-surface.ts +0 -581
  202. package/src/streaming-card.test.ts +0 -190
  203. package/src/streaming-card.ts +0 -490
  204. package/src/subagent-hooks.test.ts +0 -603
  205. package/src/subagent-hooks.ts +0 -397
  206. package/src/targets.ts +0 -97
  207. package/src/test-support/lifecycle-test-support.ts +0 -453
  208. package/src/thread-bindings.test.ts +0 -143
  209. package/src/thread-bindings.ts +0 -330
  210. package/src/tool-account-routing.test.ts +0 -187
  211. package/src/tool-account.test.ts +0 -44
  212. package/src/tool-account.ts +0 -93
  213. package/src/tool-factory-test-harness.ts +0 -79
  214. package/src/tool-result.test.ts +0 -32
  215. package/src/tool-result.ts +0 -16
  216. package/src/tools-config.test.ts +0 -21
  217. package/src/tools-config.ts +0 -22
  218. package/src/types.ts +0 -104
  219. package/src/typing.test.ts +0 -144
  220. package/src/typing.ts +0 -214
  221. package/src/wiki-schema.ts +0 -55
  222. package/src/wiki.ts +0 -227
  223. package/subagent-hooks-api.ts +0 -31
  224. package/tsconfig.json +0 -16
@@ -0,0 +1,883 @@
1
+ import { d as formatFeishuApiError, f as isRecord$1, h as readString, i as listFeishuAccountIds, l as encodeQuery, o as resolveFeishuAccount, r as listEnabledFeishuAccounts, s as resolveFeishuRuntimeAccount, u as extractReplyText, y as parseFeishuCommentTarget } from "./accounts-Ba3-WP1z.js";
2
+ import { r as createFeishuClient } from "./client-DBVoQL5w.js";
3
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
4
+ import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
5
+ import { Type } from "typebox";
6
+ //#region extensions/feishu/src/tools-config.ts
7
+ /**
8
+ * Default tool configuration.
9
+ * - doc, chat, wiki, drive, scopes: enabled by default
10
+ * - perm: disabled by default (sensitive operation)
11
+ */
12
+ const DEFAULT_TOOLS_CONFIG = {
13
+ doc: true,
14
+ chat: true,
15
+ wiki: true,
16
+ drive: true,
17
+ perm: false,
18
+ scopes: true
19
+ };
20
+ /**
21
+ * Resolve tools config with defaults.
22
+ */
23
+ function resolveToolsConfig(cfg) {
24
+ return {
25
+ ...DEFAULT_TOOLS_CONFIG,
26
+ ...cfg
27
+ };
28
+ }
29
+ //#endregion
30
+ //#region extensions/feishu/src/tool-account.ts
31
+ function resolveImplicitToolAccountId(params) {
32
+ const explicitAccountId = normalizeOptionalString(params.executeParams?.accountId);
33
+ if (explicitAccountId) return explicitAccountId;
34
+ const contextualAccountId = normalizeOptionalString(params.defaultAccountId);
35
+ if (contextualAccountId && listFeishuAccountIds(params.api.config).includes(contextualAccountId)) {
36
+ if (resolveFeishuAccount({
37
+ cfg: params.api.config,
38
+ accountId: contextualAccountId
39
+ }).enabled) return contextualAccountId;
40
+ }
41
+ const configuredDefaultAccountId = normalizeOptionalString((params.api.config?.channels?.feishu)?.defaultAccount);
42
+ if (configuredDefaultAccountId) return configuredDefaultAccountId;
43
+ }
44
+ function resolveFeishuToolAccount(params) {
45
+ if (!params.api.config) throw new Error("Feishu config unavailable");
46
+ return resolveFeishuRuntimeAccount({
47
+ cfg: params.api.config,
48
+ accountId: resolveImplicitToolAccountId(params)
49
+ });
50
+ }
51
+ function createFeishuToolClient(params) {
52
+ return createFeishuClient(resolveFeishuToolAccount(params));
53
+ }
54
+ function resolveAnyEnabledFeishuToolsConfig(accounts) {
55
+ const merged = {
56
+ doc: false,
57
+ chat: false,
58
+ wiki: false,
59
+ drive: false,
60
+ perm: false,
61
+ scopes: false
62
+ };
63
+ for (const account of accounts) {
64
+ const cfg = resolveToolsConfig(account.config.tools);
65
+ merged.doc = merged.doc || cfg.doc;
66
+ merged.chat = merged.chat || cfg.chat;
67
+ merged.wiki = merged.wiki || cfg.wiki;
68
+ merged.drive = merged.drive || cfg.drive;
69
+ merged.perm = merged.perm || cfg.perm;
70
+ merged.scopes = merged.scopes || cfg.scopes;
71
+ }
72
+ return merged;
73
+ }
74
+ //#endregion
75
+ //#region extensions/feishu/src/chat-schema.ts
76
+ const CHAT_ACTION_VALUES = [
77
+ "members",
78
+ "info",
79
+ "member_info"
80
+ ];
81
+ const MEMBER_ID_TYPE_VALUES = [
82
+ "open_id",
83
+ "user_id",
84
+ "union_id"
85
+ ];
86
+ const FeishuChatSchema = Type.Object({
87
+ action: Type.Unsafe({
88
+ type: "string",
89
+ enum: [...CHAT_ACTION_VALUES],
90
+ description: "Action to run: members | info | member_info"
91
+ }),
92
+ chat_id: Type.Optional(Type.String({ description: "Chat ID (from URL or event payload)" })),
93
+ member_id: Type.Optional(Type.String({ description: "Member ID for member_info lookups" })),
94
+ page_size: Type.Optional(Type.Number({ description: "Page size (1-100, default 50)" })),
95
+ page_token: Type.Optional(Type.String({ description: "Pagination token" })),
96
+ member_id_type: Type.Optional(Type.Unsafe({
97
+ type: "string",
98
+ enum: [...MEMBER_ID_TYPE_VALUES],
99
+ description: "Member ID type (default: open_id)"
100
+ }))
101
+ });
102
+ //#endregion
103
+ //#region extensions/feishu/src/chat.ts
104
+ function json(data) {
105
+ return {
106
+ content: [{
107
+ type: "text",
108
+ text: JSON.stringify(data, null, 2)
109
+ }],
110
+ details: data
111
+ };
112
+ }
113
+ async function getChatInfo(client, chatId) {
114
+ const res = await client.im.chat.get({ path: { chat_id: chatId } });
115
+ if (res.code !== 0) throw new Error(res.msg);
116
+ const chat = res.data;
117
+ return {
118
+ chat_id: chatId,
119
+ name: chat?.name,
120
+ description: chat?.description,
121
+ owner_id: chat?.owner_id,
122
+ tenant_key: chat?.tenant_key,
123
+ user_count: chat?.user_count,
124
+ chat_mode: chat?.chat_mode,
125
+ chat_type: chat?.chat_type,
126
+ join_message_visibility: chat?.join_message_visibility,
127
+ leave_message_visibility: chat?.leave_message_visibility,
128
+ membership_approval: chat?.membership_approval,
129
+ moderation_permission: chat?.moderation_permission,
130
+ avatar: chat?.avatar
131
+ };
132
+ }
133
+ async function getChatMembers(client, chatId, pageSize, pageToken, memberIdType) {
134
+ const page_size = pageSize ? Math.max(1, Math.min(100, pageSize)) : 50;
135
+ const res = await client.im.chatMembers.get({
136
+ path: { chat_id: chatId },
137
+ params: {
138
+ page_size,
139
+ page_token: pageToken,
140
+ member_id_type: memberIdType ?? "open_id"
141
+ }
142
+ });
143
+ if (res.code !== 0) throw new Error(res.msg);
144
+ return {
145
+ chat_id: chatId,
146
+ has_more: res.data?.has_more,
147
+ page_token: res.data?.page_token,
148
+ members: res.data?.items?.map((item) => ({
149
+ member_id: item.member_id,
150
+ name: item.name,
151
+ tenant_key: item.tenant_key,
152
+ member_id_type: item.member_id_type
153
+ })) ?? []
154
+ };
155
+ }
156
+ async function getFeishuMemberInfo(client, memberId, memberIdType = "open_id") {
157
+ const res = await client.contact.user.get({
158
+ path: { user_id: memberId },
159
+ params: {
160
+ user_id_type: memberIdType,
161
+ department_id_type: "open_department_id"
162
+ }
163
+ });
164
+ if (res.code !== 0) throw new Error(res.msg);
165
+ const user = res.data?.user;
166
+ return {
167
+ member_id: memberId,
168
+ member_id_type: memberIdType,
169
+ open_id: user?.open_id,
170
+ user_id: user?.user_id,
171
+ union_id: user?.union_id,
172
+ name: user?.name,
173
+ en_name: user?.en_name,
174
+ nickname: user?.nickname,
175
+ email: user?.email,
176
+ enterprise_email: user?.enterprise_email,
177
+ mobile: user?.mobile,
178
+ mobile_visible: user?.mobile_visible,
179
+ status: user?.status,
180
+ avatar: user?.avatar,
181
+ department_ids: user?.department_ids,
182
+ department_path: user?.department_path,
183
+ leader_user_id: user?.leader_user_id,
184
+ city: user?.city,
185
+ country: user?.country,
186
+ work_station: user?.work_station,
187
+ join_time: user?.join_time,
188
+ is_tenant_manager: user?.is_tenant_manager,
189
+ employee_no: user?.employee_no,
190
+ employee_type: user?.employee_type,
191
+ description: user?.description,
192
+ job_title: user?.job_title,
193
+ geo: user?.geo
194
+ };
195
+ }
196
+ function registerFeishuChatTools(api) {
197
+ if (!api.config) return;
198
+ const accounts = listEnabledFeishuAccounts(api.config);
199
+ if (accounts.length === 0) return;
200
+ const firstAccount = accounts[0];
201
+ if (!resolveToolsConfig(firstAccount.config.tools).chat) return;
202
+ const getClient = () => createFeishuClient(firstAccount);
203
+ api.registerTool({
204
+ name: "feishu_chat",
205
+ label: "Feishu Chat",
206
+ description: "Feishu chat operations. Actions: members, info, member_info",
207
+ parameters: FeishuChatSchema,
208
+ async execute(_toolCallId, params) {
209
+ const p = params;
210
+ try {
211
+ const client = getClient();
212
+ switch (p.action) {
213
+ case "members":
214
+ if (!p.chat_id) return json({ error: "chat_id is required for action members" });
215
+ return json(await getChatMembers(client, p.chat_id, p.page_size, p.page_token, p.member_id_type));
216
+ case "info":
217
+ if (!p.chat_id) return json({ error: "chat_id is required for action info" });
218
+ return json(await getChatInfo(client, p.chat_id));
219
+ case "member_info":
220
+ if (!p.member_id) return json({ error: "member_id is required for action member_info" });
221
+ return json(await getFeishuMemberInfo(client, p.member_id, p.member_id_type ?? "open_id"));
222
+ default: return json({ error: `Unknown action: ${String(p.action)}` });
223
+ }
224
+ } catch (err) {
225
+ return json({ error: formatFeishuApiError(err, { includeNestedErrorLogId: true }) });
226
+ }
227
+ }
228
+ }, { name: "feishu_chat" });
229
+ }
230
+ //#endregion
231
+ //#region extensions/feishu/src/tool-result.ts
232
+ function jsonToolResult(data) {
233
+ return {
234
+ content: [{
235
+ type: "text",
236
+ text: JSON.stringify(data, null, 2)
237
+ }],
238
+ details: data
239
+ };
240
+ }
241
+ function unknownToolActionResult(action) {
242
+ return jsonToolResult({ error: `Unknown action: ${String(action)}` });
243
+ }
244
+ function toolExecutionErrorResult(error) {
245
+ return jsonToolResult({ error: formatErrorMessage(error) });
246
+ }
247
+ //#endregion
248
+ //#region extensions/feishu/src/comment-reaction.ts
249
+ const COMMENT_TYPING_REACTION_TYPE = "Typing";
250
+ const COMMENT_REACTION_TIMEOUT_MS = 3e4;
251
+ const commentTypingReactionState = /* @__PURE__ */ new Map();
252
+ function buildCommentTypingReactionKey(params) {
253
+ return `${params.fileType}:${params.fileToken}:${params.replyId}`;
254
+ }
255
+ function ensureCommentTypingReactionState(key) {
256
+ const existing = commentTypingReactionState.get(key);
257
+ if (existing) return existing;
258
+ const created = {
259
+ active: false,
260
+ cleaned: false,
261
+ cleanupPromise: void 0
262
+ };
263
+ commentTypingReactionState.set(key, created);
264
+ return created;
265
+ }
266
+ async function requestCommentTypingReactionWithClient(params) {
267
+ try {
268
+ const response = await params.client.request({
269
+ method: "POST",
270
+ url: `/open-apis/drive/v2/files/${encodeURIComponent(params.fileToken)}/comments/reaction` + encodeQuery({ file_type: params.fileType }),
271
+ data: {
272
+ action: params.action,
273
+ reply_id: params.replyId,
274
+ reaction_type: COMMENT_TYPING_REACTION_TYPE
275
+ },
276
+ timeout: COMMENT_REACTION_TIMEOUT_MS
277
+ });
278
+ if (response.code === 0) return true;
279
+ params.runtime?.log?.(`${params.logPrefix ?? "[feishu]"}: comment typing reaction ${params.action} failed reply=${params.replyId} file=${params.fileType}:${params.fileToken} code=${response.code ?? "unknown"} msg=${response.msg ?? "unknown"} log_id=${response.log_id ?? response.error?.log_id ?? "unknown"}`);
280
+ } catch (error) {
281
+ params.runtime?.log?.(`${params.logPrefix ?? "[feishu]"}: comment typing reaction ${params.action} threw reply=${params.replyId} file=${params.fileType}:${params.fileToken} error=${formatCommentReactionFailure(error)}`);
282
+ }
283
+ return false;
284
+ }
285
+ function formatCommentReactionFailure(error) {
286
+ return formatFeishuApiError(error, { includeNestedErrorLogId: true });
287
+ }
288
+ async function requestCommentTypingReaction(params) {
289
+ const account = resolveFeishuRuntimeAccount({
290
+ cfg: params.cfg,
291
+ accountId: params.accountId
292
+ });
293
+ if (!account.configured || !(account.config.typingIndicator ?? true)) return false;
294
+ return requestCommentTypingReactionWithClient({
295
+ client: createFeishuClient(account),
296
+ fileToken: params.fileToken,
297
+ fileType: params.fileType,
298
+ replyId: params.replyId,
299
+ action: params.action,
300
+ runtime: params.runtime,
301
+ logPrefix: `feishu[${account.accountId}]`
302
+ });
303
+ }
304
+ async function cleanupCommentTypingReactionByKey(params) {
305
+ const state = ensureCommentTypingReactionState(params.key);
306
+ if (state.cleaned) return false;
307
+ if (state.cleanupPromise) return await state.cleanupPromise;
308
+ const cleanupPromise = (async () => {
309
+ if (!state.active) {
310
+ state.cleaned = true;
311
+ return false;
312
+ }
313
+ const deleted = await params.performDelete();
314
+ if (deleted) {
315
+ state.cleaned = true;
316
+ state.active = false;
317
+ }
318
+ return deleted;
319
+ })();
320
+ state.cleanupPromise = cleanupPromise;
321
+ try {
322
+ return await cleanupPromise;
323
+ } finally {
324
+ state.cleanupPromise = void 0;
325
+ if (state.cleaned) {
326
+ state.active = false;
327
+ commentTypingReactionState.delete(params.key);
328
+ }
329
+ }
330
+ }
331
+ async function cleanupAmbientCommentTypingReaction(params) {
332
+ const deliveryContext = params.deliveryContext;
333
+ if (deliveryContext?.channel && deliveryContext.channel !== "feishu" && deliveryContext.channel !== "feishu-comment") return false;
334
+ const target = parseFeishuCommentTarget(deliveryContext?.to);
335
+ const replyId = typeof deliveryContext?.threadId === "string" || typeof deliveryContext?.threadId === "number" ? String(deliveryContext.threadId).trim() : "";
336
+ if (!target || !replyId) return false;
337
+ return cleanupCommentTypingReactionByKey({
338
+ key: buildCommentTypingReactionKey({
339
+ fileToken: target.fileToken,
340
+ fileType: target.fileType,
341
+ replyId
342
+ }),
343
+ performDelete: () => requestCommentTypingReactionWithClient({
344
+ client: params.client,
345
+ fileToken: target.fileToken,
346
+ fileType: target.fileType,
347
+ replyId,
348
+ action: "delete",
349
+ runtime: params.runtime,
350
+ logPrefix: "[feishu]"
351
+ })
352
+ });
353
+ }
354
+ function createCommentTypingReactionLifecycle(params) {
355
+ const key = params.replyId?.trim() ? buildCommentTypingReactionKey({
356
+ fileToken: params.fileToken,
357
+ fileType: params.fileType,
358
+ replyId: params.replyId.trim()
359
+ }) : void 0;
360
+ const state = key ? ensureCommentTypingReactionState(key) : void 0;
361
+ return {
362
+ start: async () => {
363
+ const replyId = params.replyId?.trim();
364
+ if (!state || state.cleaned || state.active || !replyId) return;
365
+ state.active = await requestCommentTypingReaction({
366
+ cfg: params.cfg,
367
+ fileToken: params.fileToken,
368
+ fileType: params.fileType,
369
+ replyId,
370
+ action: "add",
371
+ accountId: params.accountId,
372
+ runtime: params.runtime
373
+ });
374
+ },
375
+ cleanup: async () => {
376
+ const replyId = params.replyId?.trim();
377
+ if (!key || !replyId) return;
378
+ await cleanupCommentTypingReactionByKey({
379
+ key,
380
+ performDelete: () => requestCommentTypingReaction({
381
+ cfg: params.cfg,
382
+ fileToken: params.fileToken,
383
+ fileType: params.fileType,
384
+ replyId,
385
+ action: "delete",
386
+ accountId: params.accountId,
387
+ runtime: params.runtime
388
+ })
389
+ });
390
+ }
391
+ };
392
+ }
393
+ //#endregion
394
+ //#region extensions/feishu/src/drive-schema.ts
395
+ const FileType = Type.Union([
396
+ Type.Literal("doc"),
397
+ Type.Literal("docx"),
398
+ Type.Literal("sheet"),
399
+ Type.Literal("bitable"),
400
+ Type.Literal("folder"),
401
+ Type.Literal("file"),
402
+ Type.Literal("mindnote"),
403
+ Type.Literal("shortcut")
404
+ ]);
405
+ const CommentFileType = Type.Union([
406
+ Type.Literal("doc"),
407
+ Type.Literal("docx"),
408
+ Type.Literal("sheet"),
409
+ Type.Literal("file"),
410
+ Type.Literal("slides")
411
+ ]);
412
+ const FeishuDriveSchema = Type.Union([
413
+ Type.Object({
414
+ action: Type.Literal("list"),
415
+ folder_token: Type.Optional(Type.String({ description: "Folder token (optional, omit for root directory)" }))
416
+ }),
417
+ Type.Object({
418
+ action: Type.Literal("info"),
419
+ file_token: Type.String({ description: "File or folder token" }),
420
+ type: FileType
421
+ }),
422
+ Type.Object({
423
+ action: Type.Literal("create_folder"),
424
+ name: Type.String({ description: "Folder name" }),
425
+ folder_token: Type.Optional(Type.String({ description: "Parent folder token (optional, omit for root)" }))
426
+ }),
427
+ Type.Object({
428
+ action: Type.Literal("move"),
429
+ file_token: Type.String({ description: "File token to move" }),
430
+ type: FileType,
431
+ folder_token: Type.String({ description: "Target folder token" })
432
+ }),
433
+ Type.Object({
434
+ action: Type.Literal("delete"),
435
+ file_token: Type.String({ description: "File token to delete" }),
436
+ type: FileType
437
+ }),
438
+ Type.Object({
439
+ action: Type.Literal("list_comments"),
440
+ file_token: Type.String({ description: "Document token" }),
441
+ file_type: Type.Optional(CommentFileType),
442
+ page_size: Type.Optional(Type.Integer({
443
+ minimum: 1,
444
+ maximum: 100,
445
+ description: "Page size"
446
+ })),
447
+ page_token: Type.Optional(Type.String({ description: "Comment page token" }))
448
+ }),
449
+ Type.Object({
450
+ action: Type.Literal("list_comment_replies"),
451
+ file_token: Type.String({ description: "Document token" }),
452
+ file_type: Type.Optional(CommentFileType),
453
+ comment_id: Type.String({ description: "Comment id" }),
454
+ page_size: Type.Optional(Type.Integer({
455
+ minimum: 1,
456
+ maximum: 100,
457
+ description: "Page size"
458
+ })),
459
+ page_token: Type.Optional(Type.String({ description: "Reply page token" }))
460
+ }),
461
+ Type.Object({
462
+ action: Type.Literal("add_comment"),
463
+ file_token: Type.String({ description: "Document token" }),
464
+ file_type: Type.Optional(Type.Union([Type.Literal("doc"), Type.Literal("docx")], { description: "Document type. Defaults to docx when omitted." })),
465
+ content: Type.String({ description: "Comment text content" }),
466
+ block_id: Type.Optional(Type.String({ description: "Optional docx block id for a local comment. Omit to create a full-document comment." }))
467
+ }),
468
+ Type.Object({
469
+ action: Type.Literal("reply_comment"),
470
+ file_token: Type.String({ description: "Document token" }),
471
+ file_type: Type.Optional(CommentFileType),
472
+ comment_id: Type.String({ description: "Comment id" }),
473
+ content: Type.String({ description: "Reply text content" })
474
+ })
475
+ ]);
476
+ //#endregion
477
+ //#region extensions/feishu/src/drive.ts
478
+ var FeishuReplyCommentError = class extends Error {
479
+ constructor(params) {
480
+ super(params.message);
481
+ this.name = "FeishuReplyCommentError";
482
+ this.httpStatus = params.httpStatus;
483
+ this.feishuCode = params.feishuCode;
484
+ this.feishuMsg = params.feishuMsg;
485
+ this.feishuLogId = params.feishuLogId;
486
+ }
487
+ };
488
+ const FEISHU_DRIVE_REQUEST_TIMEOUT_MS = 3e4;
489
+ function getDriveInternalClient(client) {
490
+ return client;
491
+ }
492
+ function buildReplyElements(content) {
493
+ return [{
494
+ type: "text",
495
+ text: content
496
+ }];
497
+ }
498
+ async function requestDriveApi(params) {
499
+ return await getDriveInternalClient(params.client).request({
500
+ method: params.method,
501
+ url: params.url,
502
+ params: params.query ?? {},
503
+ data: params.data ?? {},
504
+ timeout: FEISHU_DRIVE_REQUEST_TIMEOUT_MS
505
+ });
506
+ }
507
+ function assertDriveApiSuccess(response) {
508
+ if (response.code !== 0) throw new Error(response.msg ?? "Feishu Drive API request failed");
509
+ return response;
510
+ }
511
+ function normalizeCommentReply(reply) {
512
+ return {
513
+ reply_id: reply.reply_id,
514
+ user_id: reply.user_id,
515
+ create_time: reply.create_time,
516
+ update_time: reply.update_time,
517
+ text: extractReplyText(reply)
518
+ };
519
+ }
520
+ function normalizeCommentCard(comment) {
521
+ const replies = comment.reply_list?.replies ?? [];
522
+ const rootReply = replies[0];
523
+ return {
524
+ comment_id: comment.comment_id,
525
+ user_id: comment.user_id,
526
+ create_time: comment.create_time,
527
+ update_time: comment.update_time,
528
+ is_solved: comment.is_solved,
529
+ is_whole: comment.is_whole,
530
+ quote: comment.quote,
531
+ text: extractReplyText(rootReply),
532
+ has_more_replies: comment.has_more,
533
+ replies_page_token: comment.page_token,
534
+ replies: replies.slice(1).map(normalizeCommentReply)
535
+ };
536
+ }
537
+ function normalizeCommentPageSize(pageSize) {
538
+ if (typeof pageSize !== "number" || !Number.isFinite(pageSize)) return;
539
+ return String(Math.min(Math.max(Math.floor(pageSize), 1), 100));
540
+ }
541
+ function resolveAmbientCommentTarget(context) {
542
+ const deliveryContext = context?.deliveryContext;
543
+ if (deliveryContext?.channel && deliveryContext.channel !== "feishu") return null;
544
+ return parseFeishuCommentTarget(deliveryContext?.to);
545
+ }
546
+ function applyAmbientCommentDefaults(params, context) {
547
+ const ambient = resolveAmbientCommentTarget(context);
548
+ if (!ambient) return params;
549
+ return {
550
+ ...params,
551
+ file_token: params.file_token?.trim() || ambient.fileToken,
552
+ file_type: params.file_type ?? ambient.fileType,
553
+ comment_id: params.comment_id?.trim() || ambient.commentId
554
+ };
555
+ }
556
+ function applyAddCommentAmbientDefaults(params, context) {
557
+ const ambient = resolveAmbientCommentTarget(context);
558
+ if (!ambient || ambient.fileType !== "doc" && ambient.fileType !== "docx") return params;
559
+ return {
560
+ ...params,
561
+ file_token: params.file_token?.trim() || ambient.fileToken,
562
+ file_type: params.file_type ?? ambient.fileType
563
+ };
564
+ }
565
+ function applyAddCommentDefaults(params) {
566
+ const fileType = params.file_type ?? "docx";
567
+ if (!params.file_type) console.info(`[feishu_drive] add_comment missing file_type; defaulting to docx file_token=${params.file_token ?? "unknown"}`);
568
+ return {
569
+ ...params,
570
+ file_type: fileType
571
+ };
572
+ }
573
+ function applyCommentFileTypeDefault(params, action) {
574
+ const fileType = params.file_type ?? "docx";
575
+ if (!params.file_type) console.info(`[feishu_drive] ${action} missing file_type; defaulting to docx file_token=${params.file_token ?? "unknown"}`);
576
+ return {
577
+ ...params,
578
+ file_type: fileType
579
+ };
580
+ }
581
+ function formatDriveApiError(error) {
582
+ return formatFeishuApiError(error, { includeConfigParams: true });
583
+ }
584
+ function extractDriveApiErrorMeta(error) {
585
+ if (!isRecord$1(error)) return { message: typeof error === "string" ? error : JSON.stringify(error) };
586
+ const response = isRecord$1(error.response) ? error.response : void 0;
587
+ const responseData = isRecord$1(response?.data) ? response?.data : void 0;
588
+ return {
589
+ message: typeof error.message === "string" ? error.message : typeof error === "string" ? error : JSON.stringify(error),
590
+ httpStatus: typeof response?.status === "number" ? response.status : void 0,
591
+ feishuCode: typeof responseData?.code === "number" ? responseData.code : readString(responseData?.code),
592
+ feishuMsg: readString(responseData?.msg),
593
+ feishuLogId: readString(responseData?.log_id)
594
+ };
595
+ }
596
+ function isReplyNotAllowedError(error) {
597
+ if (!(error instanceof FeishuReplyCommentError)) return false;
598
+ return error.feishuCode === 1069302;
599
+ }
600
+ async function getRootFolderToken(client) {
601
+ const internalClient = getDriveInternalClient(client);
602
+ const domain = internalClient.domain ?? "https://open.feishu.cn";
603
+ const res = await internalClient.httpInstance.get(`${domain}/open-apis/drive/explorer/v2/root_folder/meta`);
604
+ if (res.code !== 0) throw new Error(res.msg ?? "Failed to get root folder");
605
+ const token = res.data?.token;
606
+ if (!token) throw new Error("Root folder token not found");
607
+ return token;
608
+ }
609
+ async function listFolder(client, folderToken) {
610
+ const validFolderToken = folderToken && folderToken !== "0" ? folderToken : void 0;
611
+ const res = await client.drive.file.list({ params: validFolderToken ? { folder_token: validFolderToken } : {} });
612
+ if (res.code !== 0) throw new Error(res.msg);
613
+ return {
614
+ files: res.data?.files?.map((f) => ({
615
+ token: f.token,
616
+ name: f.name,
617
+ type: f.type,
618
+ url: f.url,
619
+ created_time: f.created_time,
620
+ modified_time: f.modified_time,
621
+ owner_id: f.owner_id
622
+ })) ?? [],
623
+ next_page_token: res.data?.next_page_token
624
+ };
625
+ }
626
+ async function getFileInfo(client, fileToken, folderToken) {
627
+ const res = await client.drive.file.list({ params: folderToken ? { folder_token: folderToken } : {} });
628
+ if (res.code !== 0) throw new Error(res.msg);
629
+ const file = res.data?.files?.find((f) => f.token === fileToken);
630
+ if (!file) throw new Error(`File not found: ${fileToken}`);
631
+ return {
632
+ token: file.token,
633
+ name: file.name,
634
+ type: file.type,
635
+ url: file.url,
636
+ created_time: file.created_time,
637
+ modified_time: file.modified_time,
638
+ owner_id: file.owner_id
639
+ };
640
+ }
641
+ async function createFolder(client, name, folderToken) {
642
+ let effectiveToken = folderToken && folderToken !== "0" ? folderToken : "0";
643
+ if (effectiveToken === "0") try {
644
+ effectiveToken = await getRootFolderToken(client);
645
+ } catch {}
646
+ const res = await client.drive.file.createFolder({ data: {
647
+ name,
648
+ folder_token: effectiveToken
649
+ } });
650
+ if (res.code !== 0) throw new Error(res.msg);
651
+ return {
652
+ token: res.data?.token,
653
+ url: res.data?.url
654
+ };
655
+ }
656
+ async function moveFile(client, fileToken, type, folderToken) {
657
+ const res = await client.drive.file.move({
658
+ path: { file_token: fileToken },
659
+ data: {
660
+ type,
661
+ folder_token: folderToken
662
+ }
663
+ });
664
+ if (res.code !== 0) throw new Error(res.msg);
665
+ return {
666
+ success: true,
667
+ task_id: res.data?.task_id
668
+ };
669
+ }
670
+ async function deleteFile(client, fileToken, type) {
671
+ const res = await client.drive.file.delete({
672
+ path: { file_token: fileToken },
673
+ params: { type }
674
+ });
675
+ if (res.code !== 0) throw new Error(res.msg);
676
+ return {
677
+ success: true,
678
+ task_id: res.data?.task_id
679
+ };
680
+ }
681
+ async function listComments(client, params) {
682
+ const response = assertDriveApiSuccess(await requestDriveApi({
683
+ client,
684
+ method: "GET",
685
+ url: `/open-apis/drive/v1/files/${encodeURIComponent(params.file_token)}/comments` + encodeQuery({
686
+ file_type: params.file_type,
687
+ page_size: normalizeCommentPageSize(params.page_size),
688
+ page_token: params.page_token,
689
+ user_id_type: "open_id"
690
+ })
691
+ }));
692
+ return {
693
+ has_more: response.data?.has_more ?? false,
694
+ page_token: response.data?.page_token,
695
+ comments: (response.data?.items ?? []).map(normalizeCommentCard)
696
+ };
697
+ }
698
+ async function listCommentReplies(client, params) {
699
+ const response = assertDriveApiSuccess(await requestDriveApi({
700
+ client,
701
+ method: "GET",
702
+ url: `/open-apis/drive/v1/files/${encodeURIComponent(params.file_token)}/comments/${encodeURIComponent(params.comment_id)}/replies` + encodeQuery({
703
+ file_type: params.file_type,
704
+ page_size: normalizeCommentPageSize(params.page_size),
705
+ page_token: params.page_token,
706
+ user_id_type: "open_id"
707
+ })
708
+ }));
709
+ return {
710
+ has_more: response.data?.has_more ?? false,
711
+ page_token: response.data?.page_token,
712
+ replies: (response.data?.items ?? []).map(normalizeCommentReply)
713
+ };
714
+ }
715
+ async function addComment(client, params) {
716
+ if (params.block_id?.trim() && params.file_type !== "docx") throw new Error("block_id is only supported for docx comments");
717
+ return {
718
+ success: true,
719
+ ...assertDriveApiSuccess(await requestDriveApi({
720
+ client,
721
+ method: "POST",
722
+ url: `/open-apis/drive/v1/files/${encodeURIComponent(params.file_token)}/new_comments`,
723
+ data: {
724
+ file_type: params.file_type,
725
+ reply_elements: buildReplyElements(params.content),
726
+ ...params.block_id?.trim() ? { anchor: { block_id: params.block_id.trim() } } : {}
727
+ }
728
+ })).data
729
+ };
730
+ }
731
+ async function queryCommentById(client, params) {
732
+ return assertDriveApiSuccess(await requestDriveApi({
733
+ client,
734
+ method: "POST",
735
+ url: `/open-apis/drive/v1/files/${encodeURIComponent(params.file_token)}/comments/batch_query` + encodeQuery({
736
+ file_type: params.file_type,
737
+ user_id_type: "open_id"
738
+ }),
739
+ data: { comment_ids: [params.comment_id] }
740
+ })).data?.items?.find((comment) => comment.comment_id?.trim() === params.comment_id);
741
+ }
742
+ async function replyComment(client, params) {
743
+ const url = `/open-apis/drive/v1/files/${encodeURIComponent(params.file_token)}/comments/${encodeURIComponent(params.comment_id)}/replies`;
744
+ const query = { file_type: params.file_type };
745
+ try {
746
+ const response = await requestDriveApi({
747
+ client,
748
+ method: "POST",
749
+ url,
750
+ query,
751
+ data: { content: { elements: [{
752
+ type: "text_run",
753
+ text_run: { text: params.content }
754
+ }] } }
755
+ });
756
+ if (response.code === 0) return {
757
+ success: true,
758
+ ...response.data
759
+ };
760
+ console.warn(`[feishu_drive] replyComment failed comment=${params.comment_id} file_type=${params.file_type} code=${response.code ?? "unknown"} msg=${response.msg ?? "unknown"} log_id=${response.log_id ?? "unknown"}`);
761
+ throw new FeishuReplyCommentError({
762
+ message: response.msg ?? "Feishu Drive reply comment failed",
763
+ feishuCode: response.code,
764
+ feishuMsg: response.msg,
765
+ feishuLogId: response.log_id
766
+ });
767
+ } catch (error) {
768
+ if (error instanceof FeishuReplyCommentError) throw error;
769
+ const meta = extractDriveApiErrorMeta(error);
770
+ console.warn(`[feishu_drive] replyComment threw comment=${params.comment_id} file_type=${params.file_type} error=${formatDriveApiError(error)}`);
771
+ throw new FeishuReplyCommentError({
772
+ message: meta.message,
773
+ httpStatus: meta.httpStatus,
774
+ feishuCode: meta.feishuCode,
775
+ feishuMsg: meta.feishuMsg,
776
+ feishuLogId: meta.feishuLogId
777
+ });
778
+ }
779
+ }
780
+ async function deliverCommentThreadText(client, params) {
781
+ let isWholeComment = params.is_whole_comment;
782
+ if (isWholeComment === void 0) try {
783
+ isWholeComment = (await queryCommentById(client, params))?.is_whole === true;
784
+ } catch (error) {
785
+ console.warn(`[feishu_drive] comment metadata preflight failed comment=${params.comment_id} file_type=${params.file_type} error=${formatErrorMessage(error)}`);
786
+ isWholeComment = false;
787
+ }
788
+ if (isWholeComment) {
789
+ if (params.file_type !== "doc" && params.file_type !== "docx") throw new Error(`Whole-document comment follow-ups are only supported for doc/docx (got ${params.file_type})`);
790
+ const wholeCommentFileType = params.file_type;
791
+ console.info(`[feishu_drive] whole-comment compatibility path comment=${params.comment_id} file_type=${params.file_type} mode=add_comment`);
792
+ return {
793
+ delivery_mode: "add_comment",
794
+ ...await addComment(client, {
795
+ file_token: params.file_token,
796
+ file_type: wholeCommentFileType,
797
+ content: params.content
798
+ })
799
+ };
800
+ }
801
+ try {
802
+ return {
803
+ delivery_mode: "reply_comment",
804
+ ...await replyComment(client, params)
805
+ };
806
+ } catch (error) {
807
+ if (error instanceof FeishuReplyCommentError && isReplyNotAllowedError(error)) {
808
+ if (params.file_type !== "doc" && params.file_type !== "docx") throw error;
809
+ const fallbackFileType = params.file_type;
810
+ console.info(`[feishu_drive] reply-not-allowed compatibility path comment=${params.comment_id} file_type=${params.file_type} mode=add_comment log_id=${error.feishuLogId ?? "unknown"}`);
811
+ return {
812
+ delivery_mode: "add_comment",
813
+ ...await addComment(client, {
814
+ file_token: params.file_token,
815
+ file_type: fallbackFileType,
816
+ content: params.content
817
+ })
818
+ };
819
+ }
820
+ throw error;
821
+ }
822
+ }
823
+ function registerFeishuDriveTools(api) {
824
+ if (!api.config) return;
825
+ const accounts = listEnabledFeishuAccounts(api.config);
826
+ if (accounts.length === 0) return;
827
+ if (!resolveAnyEnabledFeishuToolsConfig(accounts).drive) return;
828
+ api.registerTool((ctx) => {
829
+ const defaultAccountId = ctx.agentAccountId;
830
+ return {
831
+ name: "feishu_drive",
832
+ label: "Feishu Drive",
833
+ description: "Feishu cloud storage operations. Actions: list, info, create_folder, move, delete, list_comments, list_comment_replies, add_comment, reply_comment",
834
+ parameters: FeishuDriveSchema,
835
+ async execute(_toolCallId, params) {
836
+ const p = params;
837
+ try {
838
+ const client = createFeishuToolClient({
839
+ api,
840
+ executeParams: p,
841
+ defaultAccountId
842
+ });
843
+ switch (p.action) {
844
+ case "list": return jsonToolResult(await listFolder(client, p.folder_token));
845
+ case "info": return jsonToolResult(await getFileInfo(client, p.file_token));
846
+ case "create_folder": return jsonToolResult(await createFolder(client, p.name, p.folder_token));
847
+ case "move": return jsonToolResult(await moveFile(client, p.file_token, p.type, p.folder_token));
848
+ case "delete": return jsonToolResult(await deleteFile(client, p.file_token, p.type));
849
+ case "list_comments": return jsonToolResult(await listComments(client, applyCommentFileTypeDefault(applyAmbientCommentDefaults(p, ctx), "list_comments")));
850
+ case "list_comment_replies": return jsonToolResult(await listCommentReplies(client, applyCommentFileTypeDefault(applyAmbientCommentDefaults(p, ctx), "list_comment_replies")));
851
+ case "add_comment": {
852
+ const resolved = applyAddCommentDefaults(applyAddCommentAmbientDefaults(p, ctx));
853
+ try {
854
+ return jsonToolResult(await addComment(client, resolved));
855
+ } finally {
856
+ cleanupAmbientCommentTypingReaction({
857
+ client: getDriveInternalClient(client),
858
+ deliveryContext: ctx.deliveryContext
859
+ });
860
+ }
861
+ }
862
+ case "reply_comment": {
863
+ const resolved = applyCommentFileTypeDefault(applyAmbientCommentDefaults(p, ctx), "reply_comment");
864
+ try {
865
+ return jsonToolResult(await deliverCommentThreadText(client, resolved));
866
+ } finally {
867
+ cleanupAmbientCommentTypingReaction({
868
+ client: getDriveInternalClient(client),
869
+ deliveryContext: ctx.deliveryContext
870
+ });
871
+ }
872
+ }
873
+ default: return unknownToolActionResult(p.action);
874
+ }
875
+ } catch (err) {
876
+ return toolExecutionErrorResult(err);
877
+ }
878
+ }
879
+ };
880
+ }, { name: "feishu_drive" });
881
+ }
882
+ //#endregion
883
+ export { jsonToolResult as a, getChatInfo as c, registerFeishuChatTools as d, createFeishuToolClient as f, createCommentTypingReactionLifecycle as i, getChatMembers as l, resolveFeishuToolAccount as m, registerFeishuDriveTools as n, toolExecutionErrorResult as o, resolveAnyEnabledFeishuToolsConfig as p, cleanupAmbientCommentTypingReaction as r, unknownToolActionResult as s, deliverCommentThreadText as t, getFeishuMemberInfo as u };