@openclaw/feishu 2026.7.2-beta.7 → 2026.8.1-beta.3
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/accounts-CCCdMen2.js +203 -0
- package/dist/api.js +61 -60
- package/dist/{channel-CScE82zY.js → channel-Ceq80_zP.js} +71 -42
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-B21e1E0r.js → channel.runtime-DnRyzGoU.js} +201 -152
- package/dist/{client-Dcbs6vml.js → client-Hp7uo_cl.js} +27 -16
- package/dist/contract-api.js +2 -2
- package/dist/{conversation-id-BeJL-wq7.js → conversation-id-VYgGQ-GX.js} +11 -15
- package/dist/doctor-contract-api.js +1 -1
- package/dist/doctor-contract-bEQXIXyP.js +158 -0
- package/dist/{drive-hSi_Utp0.js → drive-BVYM_Y4k.js} +325 -44
- package/dist/{media-CEUraFOR.js → media-BDouVaaM.js} +298 -182
- package/dist/{monitor-DngbaA6a.js → monitor-CZ8cDXrq.js} +3 -3
- package/dist/{monitor.account-BnTWCw55.js → monitor.account-Dq_voVMB.js} +263 -179
- package/dist/{monitor.startup-CqH2tiJq.js → monitor.startup-BGErejNH.js} +1 -1
- package/dist/{probe-p3POS2RN.js → probe-DVpy58s0.js} +2 -2
- package/dist/security-audit-D6Fz2h6p.js +23 -0
- package/dist/{send-result-B9_BpUPx.js → send-result-DEAycmOk.js} +18 -9
- package/dist/session-binding-contract-api.js +2 -2
- package/dist/{session-conversation-BksWrfzm.js → session-conversation-DFCIvQK-.js} +1 -1
- package/dist/session-key-api.js +1 -1
- package/dist/setup-api.js +1 -1
- package/dist/{subagent-hooks-Cx1cX7rW.js → subagent-hooks-KUi-7vUy.js} +4 -64
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/{thread-bindings-N3wkgkIN.js → thread-bindings-CptM_YU6.js} +7 -9
- package/openclaw.plugin.json +143 -1
- package/package.json +4 -4
- package/skills/feishu-doc/SKILL.md +20 -195
- package/skills/feishu-doc/references/block-types.md +9 -14
- package/skills/feishu-drive/SKILL.md +16 -102
- package/skills/feishu-perm/SKILL.md +10 -110
- package/skills/feishu-wiki/SKILL.md +13 -109
- package/dist/accounts-u9X5Wsan.js +0 -469
- package/dist/doctor-contract-BiD9tyIv.js +0 -102
- package/dist/security-audit-D7WK_BHh.js +0 -11
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { a as resolveDefaultFeishuAccountId,
|
|
2
|
-
import { A as resolveFeishuChatType, b as resolveFeishuChatReadPreliminaryAuthorization, h as authorizeFeishuChatMemberRead, m as assertFeishuChatReadAllowed } from "./send-result-
|
|
3
|
-
import { r as createFeishuClient } from "./client-
|
|
1
|
+
import { a as resolveDefaultFeishuAccountId, i as listFeishuAccountIds, o as resolveFeishuAccount, r as listEnabledFeishuAccounts, s as resolveFeishuRuntimeAccount } from "./accounts-CCCdMen2.js";
|
|
2
|
+
import { A as resolveFeishuChatType, b as resolveFeishuChatReadPreliminaryAuthorization, h as authorizeFeishuChatMemberRead, m as assertFeishuChatReadAllowed } from "./send-result-DEAycmOk.js";
|
|
3
|
+
import { r as createFeishuClient } from "./client-Hp7uo_cl.js";
|
|
4
4
|
import { optionalPositiveIntegerSchema } from "openclaw/plugin-sdk/channel-actions";
|
|
5
|
-
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
|
-
import { normalizeOptionalAccountId } from "openclaw/plugin-sdk/account-resolution";
|
|
7
5
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
8
|
-
import {
|
|
6
|
+
import { isRecord, normalizeOptionalString, normalizeStringEntries, readStringValue } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
|
+
import { normalizeOptionalAccountId } from "openclaw/plugin-sdk/account-resolution";
|
|
9
8
|
import { Type } from "typebox";
|
|
9
|
+
import { wrapExternalContent } from "openclaw/plugin-sdk/security-runtime";
|
|
10
|
+
import { jsonResult } from "openclaw/plugin-sdk/tool-results";
|
|
10
11
|
import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
|
|
12
|
+
import { retryAsync } from "openclaw/plugin-sdk/retry-runtime";
|
|
11
13
|
//#region extensions/feishu/src/tools-config.ts
|
|
12
14
|
/**
|
|
13
15
|
* Default tool configuration.
|
|
@@ -56,14 +58,18 @@ function resolveImplicitToolAccountId(params) {
|
|
|
56
58
|
}).enabled) return contextualAccountId;
|
|
57
59
|
}
|
|
58
60
|
const configuredDefaultAccountId = normalizeOptionalString((params.api.config?.channels?.feishu)?.defaultAccount);
|
|
59
|
-
if (configuredDefaultAccountId
|
|
60
|
-
|
|
61
|
+
if (configuredDefaultAccountId && resolveFeishuAccount({
|
|
62
|
+
cfg: params.api.config,
|
|
63
|
+
accountId: configuredDefaultAccountId
|
|
64
|
+
}).enabled) return configuredDefaultAccountId;
|
|
65
|
+
if (params.api.config) for (const accountId of listFeishuAccountIds(params.api.config)) {
|
|
61
66
|
const account = resolveFeishuAccount({
|
|
62
67
|
cfg: params.api.config,
|
|
63
68
|
accountId
|
|
64
69
|
});
|
|
65
70
|
if (account.enabled && account.configured && resolveToolsConfig(account.config.tools)[params.requiredTool.family]) return accountId;
|
|
66
71
|
}
|
|
72
|
+
throw new Error(`No usable Feishu account has ${params.requiredTool.label} tools enabled`);
|
|
67
73
|
}
|
|
68
74
|
function resolveFeishuToolAccount(params) {
|
|
69
75
|
if (!params.api.config) throw new Error("Feishu config unavailable");
|
|
@@ -71,7 +77,7 @@ function resolveFeishuToolAccount(params) {
|
|
|
71
77
|
cfg: params.api.config,
|
|
72
78
|
accountId: resolveImplicitToolAccountId(params)
|
|
73
79
|
});
|
|
74
|
-
if (
|
|
80
|
+
if (!resolveToolsConfig(account.config.tools)[params.requiredTool.family]) throw new Error(`Feishu ${params.requiredTool.label} tools are disabled for account "${account.accountId}"`);
|
|
75
81
|
return account;
|
|
76
82
|
}
|
|
77
83
|
function createFeishuToolClient(params) {
|
|
@@ -99,6 +105,26 @@ function resolveAnyEnabledFeishuToolsConfig(accounts) {
|
|
|
99
105
|
}
|
|
100
106
|
return merged;
|
|
101
107
|
}
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region extensions/feishu/src/tool-result.ts
|
|
110
|
+
function feishuExternalToolResult(details) {
|
|
111
|
+
return {
|
|
112
|
+
content: [{
|
|
113
|
+
type: "text",
|
|
114
|
+
text: wrapExternalContent(JSON.stringify(details, null, 2), {
|
|
115
|
+
source: "api",
|
|
116
|
+
includeWarning: false
|
|
117
|
+
})
|
|
118
|
+
}],
|
|
119
|
+
details
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function unknownToolActionResult(action) {
|
|
123
|
+
return jsonResult({ error: `Unknown action: ${String(action)}` });
|
|
124
|
+
}
|
|
125
|
+
function toolExecutionErrorResult(error) {
|
|
126
|
+
return feishuExternalToolResult({ error: formatErrorMessage(error) });
|
|
127
|
+
}
|
|
102
128
|
const FeishuChatSchema = Type.Object({
|
|
103
129
|
action: Type.Enum([
|
|
104
130
|
"members",
|
|
@@ -125,6 +151,267 @@ const FeishuChatSchema = Type.Object({
|
|
|
125
151
|
}))
|
|
126
152
|
});
|
|
127
153
|
//#endregion
|
|
154
|
+
//#region extensions/feishu/src/comment-target.ts
|
|
155
|
+
const FEISHU_COMMENT_FILE_TYPES = [
|
|
156
|
+
"doc",
|
|
157
|
+
"docx",
|
|
158
|
+
"file",
|
|
159
|
+
"sheet",
|
|
160
|
+
"slides"
|
|
161
|
+
];
|
|
162
|
+
function normalizeCommentFileType(value) {
|
|
163
|
+
return typeof value === "string" && FEISHU_COMMENT_FILE_TYPES.includes(value) ? value : void 0;
|
|
164
|
+
}
|
|
165
|
+
function buildFeishuCommentTarget(params) {
|
|
166
|
+
return `comment:${params.fileType}:${params.fileToken}:${params.commentId}`;
|
|
167
|
+
}
|
|
168
|
+
function parseFeishuCommentTarget(raw) {
|
|
169
|
+
const trimmed = raw?.trim();
|
|
170
|
+
if (!trimmed?.startsWith("comment:")) return null;
|
|
171
|
+
const parts = trimmed.split(":");
|
|
172
|
+
if (parts.length !== 4) return null;
|
|
173
|
+
const fileType = normalizeCommentFileType(parts[1]);
|
|
174
|
+
const fileToken = parts[2]?.trim();
|
|
175
|
+
const commentId = parts[3]?.trim();
|
|
176
|
+
if (!fileType || !fileToken || !commentId) return null;
|
|
177
|
+
return {
|
|
178
|
+
fileType,
|
|
179
|
+
fileToken,
|
|
180
|
+
commentId
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region extensions/feishu/src/send-rate-limit.ts
|
|
185
|
+
const FEISHU_SEND_RATE_LIMIT_CODES = /* @__PURE__ */ new Set([230020, 11232]);
|
|
186
|
+
function getFeishuSendRateLimitCode(error) {
|
|
187
|
+
if (!isRecord(error)) return;
|
|
188
|
+
const response = isRecord(error.response) ? error.response : void 0;
|
|
189
|
+
if (response?.status === 429) return 429;
|
|
190
|
+
const code = (isRecord(response?.data) ? response.data : void 0)?.code;
|
|
191
|
+
return typeof code === "number" && FEISHU_SEND_RATE_LIMIT_CODES.has(code) ? code : void 0;
|
|
192
|
+
}
|
|
193
|
+
function getFeishuSendRateLimitCodeFromResponse(response) {
|
|
194
|
+
if (!isRecord(response)) return;
|
|
195
|
+
const code = response.code;
|
|
196
|
+
return typeof code === "number" && FEISHU_SEND_RATE_LIMIT_CODES.has(code) ? code : void 0;
|
|
197
|
+
}
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region extensions/feishu/src/comment-shared.ts
|
|
200
|
+
function encodeQuery(params) {
|
|
201
|
+
const query = new URLSearchParams();
|
|
202
|
+
for (const [key, value] of Object.entries(params)) {
|
|
203
|
+
const trimmed = value?.trim();
|
|
204
|
+
if (trimmed) query.set(key, trimmed);
|
|
205
|
+
}
|
|
206
|
+
const queryString = query.toString();
|
|
207
|
+
return queryString ? `?${queryString}` : "";
|
|
208
|
+
}
|
|
209
|
+
function formatFeishuApiError(error, options = {}) {
|
|
210
|
+
if (!isRecord(error)) return typeof error === "string" ? error : JSON.stringify(error);
|
|
211
|
+
const config = isRecord(error.config) ? error.config : void 0;
|
|
212
|
+
const response = isRecord(error.response) ? error.response : void 0;
|
|
213
|
+
const responseData = isRecord(response?.data) ? response?.data : void 0;
|
|
214
|
+
const feishuLogId = readStringValue(responseData?.log_id) || (options.includeNestedErrorLogId ? readStringValue(isRecord(responseData?.error) ? responseData.error.log_id : void 0) : void 0);
|
|
215
|
+
const nestedError = isRecord(responseData?.error) ? responseData.error : void 0;
|
|
216
|
+
return JSON.stringify({
|
|
217
|
+
message: typeof error.message === "string" ? error.message : typeof error === "string" ? error : JSON.stringify(error),
|
|
218
|
+
code: readStringValue(error.code),
|
|
219
|
+
method: readStringValue(config?.method),
|
|
220
|
+
url: readStringValue(config?.url),
|
|
221
|
+
...options.includeConfigParams ? { params: config?.params } : {},
|
|
222
|
+
http_status: typeof response?.status === "number" ? response.status : void 0,
|
|
223
|
+
feishu_code: typeof responseData?.code === "number" ? responseData.code : readStringValue(responseData?.code),
|
|
224
|
+
feishu_msg: readStringValue(responseData?.msg),
|
|
225
|
+
feishu_log_id: feishuLogId,
|
|
226
|
+
feishu_troubleshooter: readStringValue(responseData?.troubleshooter) || readStringValue(nestedError?.troubleshooter)
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
function formatFeishuApiFailure(error, errorPrefix, options = {}) {
|
|
230
|
+
return `${errorPrefix}: ${formatFeishuApiError(error, options) || "unknown error"}`;
|
|
231
|
+
}
|
|
232
|
+
function createFeishuApiError(error, errorPrefix, options = {}) {
|
|
233
|
+
return new Error(formatFeishuApiFailure(error, errorPrefix, options), { cause: error });
|
|
234
|
+
}
|
|
235
|
+
const FEISHU_SEND_RETRY_BASE_MS = 500;
|
|
236
|
+
async function requestFeishuApi(request, errorPrefix, options = {}) {
|
|
237
|
+
try {
|
|
238
|
+
return await retryAsync(async () => {
|
|
239
|
+
const result = await request();
|
|
240
|
+
const fulfilledRateLimit = getFeishuSendRateLimitCodeFromResponse(result);
|
|
241
|
+
if (fulfilledRateLimit !== void 0) throw Object.assign(/* @__PURE__ */ new Error(`Request fulfilled with rate-limit code ${fulfilledRateLimit}`), { response: {
|
|
242
|
+
status: 200,
|
|
243
|
+
data: result
|
|
244
|
+
} });
|
|
245
|
+
return result;
|
|
246
|
+
}, {
|
|
247
|
+
attempts: 3,
|
|
248
|
+
minDelayMs: options.retryDelayMs ?? FEISHU_SEND_RETRY_BASE_MS,
|
|
249
|
+
shouldRetry: (error) => getFeishuSendRateLimitCode(error) !== void 0
|
|
250
|
+
});
|
|
251
|
+
} catch (error) {
|
|
252
|
+
throw createFeishuApiError(error, errorPrefix, options);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function readDocsLinkUrl(element) {
|
|
256
|
+
const docsLink = isRecord(element.docs_link) ? element.docs_link : void 0;
|
|
257
|
+
return normalizeOptionalString(docsLink?.url) || normalizeOptionalString(docsLink?.link) || normalizeOptionalString(element.url) || normalizeOptionalString(element.link) || void 0;
|
|
258
|
+
}
|
|
259
|
+
function readMentionUserId(element) {
|
|
260
|
+
const mention = isRecord(element.mention) ? element.mention : void 0;
|
|
261
|
+
return normalizeOptionalString((isRecord(element.person) ? element.person : void 0)?.user_id) || normalizeOptionalString(mention?.user_id) || normalizeOptionalString(mention?.open_id) || normalizeOptionalString(element.mention_user) || normalizeOptionalString(element.user_id) || void 0;
|
|
262
|
+
}
|
|
263
|
+
function readMentionDisplayText(element, userId) {
|
|
264
|
+
const mention = isRecord(element.mention) ? element.mention : void 0;
|
|
265
|
+
const mentionName = normalizeOptionalString(mention?.name) || normalizeOptionalString(mention?.display_name) || normalizeOptionalString(element.name);
|
|
266
|
+
return mentionName ? `@${mentionName}` : `@${userId}`;
|
|
267
|
+
}
|
|
268
|
+
function normalizeCommentText(parts) {
|
|
269
|
+
return parts.join("").trim() || void 0;
|
|
270
|
+
}
|
|
271
|
+
function normalizeCommentSemanticText(parts) {
|
|
272
|
+
return parts.join("").replace(/\s+/g, " ").trim() || void 0;
|
|
273
|
+
}
|
|
274
|
+
function readElementTextPreservingWhitespace(element) {
|
|
275
|
+
return (isRecord(element.text_run) ? readStringValue(element.text_run.content) || readStringValue(element.text_run.text) : void 0) || readStringValue(element.text) || readStringValue(element.content) || readStringValue(element.name) || void 0;
|
|
276
|
+
}
|
|
277
|
+
const FEISHU_LINK_TOKEN_MIN_LENGTH = 22;
|
|
278
|
+
const FEISHU_LINK_TOKEN_MAX_LENGTH = 28;
|
|
279
|
+
const COMMENT_LINK_KIND_ALIASES = /* @__PURE__ */ new Map([
|
|
280
|
+
["doc", "doc"],
|
|
281
|
+
["docs", "doc"],
|
|
282
|
+
["docx", "docx"],
|
|
283
|
+
["sheet", "sheet"],
|
|
284
|
+
["sheets", "sheet"],
|
|
285
|
+
["slide", "slides"],
|
|
286
|
+
["slides", "slides"],
|
|
287
|
+
["file", "file"],
|
|
288
|
+
["files", "file"],
|
|
289
|
+
["wiki", "wiki"],
|
|
290
|
+
["mindnote", "mindnote"],
|
|
291
|
+
["mindnotes", "mindnote"],
|
|
292
|
+
["bitable", "bitable"],
|
|
293
|
+
["base", "base"]
|
|
294
|
+
]);
|
|
295
|
+
function isCommentFileType(value) {
|
|
296
|
+
return typeof value === "string" && FEISHU_COMMENT_FILE_TYPES.includes(value);
|
|
297
|
+
}
|
|
298
|
+
function isReasonableFeishuLinkToken(token) {
|
|
299
|
+
return typeof token === "string" && token.length >= FEISHU_LINK_TOKEN_MIN_LENGTH && token.length <= FEISHU_LINK_TOKEN_MAX_LENGTH;
|
|
300
|
+
}
|
|
301
|
+
function parseCommentLinkedDocumentPath(pathname) {
|
|
302
|
+
const segments = normalizeStringEntries(pathname.split("/"));
|
|
303
|
+
const offset = segments[0]?.toLowerCase() === "space" ? 1 : 0;
|
|
304
|
+
const kind = COMMENT_LINK_KIND_ALIASES.get(segments[offset]?.toLowerCase() ?? "");
|
|
305
|
+
const token = normalizeOptionalString(segments[offset + 1]);
|
|
306
|
+
if (!kind || !isReasonableFeishuLinkToken(token)) return null;
|
|
307
|
+
return {
|
|
308
|
+
urlKind: kind,
|
|
309
|
+
token
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function hasResolvedLinkedDocumentReference(link) {
|
|
313
|
+
return link.urlKind !== "unknown" && (Boolean(link.resolvedObjToken) || Boolean(link.wikiNodeToken));
|
|
314
|
+
}
|
|
315
|
+
function resolveCommentLinkedDocumentFromUrl(params) {
|
|
316
|
+
const link = {
|
|
317
|
+
rawUrl: params.rawUrl,
|
|
318
|
+
urlKind: "unknown"
|
|
319
|
+
};
|
|
320
|
+
try {
|
|
321
|
+
const parsedPath = parseCommentLinkedDocumentPath(new URL(params.rawUrl).pathname);
|
|
322
|
+
if (!parsedPath) return link;
|
|
323
|
+
const { urlKind, token } = parsedPath;
|
|
324
|
+
link.urlKind = urlKind;
|
|
325
|
+
if (urlKind === "wiki") {
|
|
326
|
+
link.urlKind = "wiki";
|
|
327
|
+
link.wikiNodeToken = token;
|
|
328
|
+
} else {
|
|
329
|
+
link.resolvedObjType = urlKind;
|
|
330
|
+
link.resolvedObjToken = token;
|
|
331
|
+
}
|
|
332
|
+
if (link.resolvedObjType && link.resolvedObjToken && isCommentFileType(link.resolvedObjType) && params.currentDocument?.fileType === link.resolvedObjType && params.currentDocument.fileToken === link.resolvedObjToken) link.isCurrentDocument = true;
|
|
333
|
+
else if (link.resolvedObjType && link.resolvedObjToken && isCommentFileType(link.resolvedObjType)) link.isCurrentDocument = false;
|
|
334
|
+
} catch {
|
|
335
|
+
return link;
|
|
336
|
+
}
|
|
337
|
+
return link;
|
|
338
|
+
}
|
|
339
|
+
function parseCommentContentElements(params) {
|
|
340
|
+
const elements = Array.isArray(params.elements) ? params.elements : [];
|
|
341
|
+
const plainTextParts = [];
|
|
342
|
+
const semanticTextParts = [];
|
|
343
|
+
const mentions = [];
|
|
344
|
+
const linkedDocuments = [];
|
|
345
|
+
const botIds = new Set(Array.from(params.botOpenIds ?? []).map((value) => normalizeOptionalString(value)).filter((value) => Boolean(value)));
|
|
346
|
+
const linkedDocumentKeys = /* @__PURE__ */ new Set();
|
|
347
|
+
let botMentioned = false;
|
|
348
|
+
for (const rawElement of elements) {
|
|
349
|
+
if (!isRecord(rawElement)) continue;
|
|
350
|
+
const element = rawElement;
|
|
351
|
+
const type = normalizeOptionalString(element.type);
|
|
352
|
+
const text = (type === "text_run" ? readElementTextPreservingWhitespace(element) : void 0) || (type === "text" ? readElementTextPreservingWhitespace(element) : void 0) || (type === "docs_link" || type === "link" ? readDocsLinkUrl(element) : void 0) || (type === "mention" || type === "mention_user" || type === "person" ? (() => {
|
|
353
|
+
const userId = readMentionUserId(element);
|
|
354
|
+
return userId ? readMentionDisplayText(element, userId) : void 0;
|
|
355
|
+
})() : void 0) || readElementTextPreservingWhitespace(element) || void 0;
|
|
356
|
+
if (type === "mention" || type === "mention_user" || type === "person") {
|
|
357
|
+
const userId = readMentionUserId(element);
|
|
358
|
+
if (userId) {
|
|
359
|
+
const displayText = readMentionDisplayText(element, userId);
|
|
360
|
+
const isBotMention = botIds.has(userId);
|
|
361
|
+
mentions.push({
|
|
362
|
+
userId,
|
|
363
|
+
displayText,
|
|
364
|
+
isBotMention
|
|
365
|
+
});
|
|
366
|
+
plainTextParts.push(displayText);
|
|
367
|
+
if (!isBotMention) semanticTextParts.push(displayText);
|
|
368
|
+
else botMentioned = true;
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
if (type === "docs_link" || type === "link") {
|
|
373
|
+
const rawUrl = readDocsLinkUrl(element);
|
|
374
|
+
if (rawUrl) {
|
|
375
|
+
plainTextParts.push(rawUrl);
|
|
376
|
+
semanticTextParts.push(rawUrl);
|
|
377
|
+
const linkedDocument = resolveCommentLinkedDocumentFromUrl({
|
|
378
|
+
rawUrl,
|
|
379
|
+
currentDocument: params.currentDocument
|
|
380
|
+
});
|
|
381
|
+
if (hasResolvedLinkedDocumentReference(linkedDocument)) {
|
|
382
|
+
const key = [
|
|
383
|
+
linkedDocument.rawUrl,
|
|
384
|
+
linkedDocument.urlKind,
|
|
385
|
+
linkedDocument.resolvedObjType,
|
|
386
|
+
linkedDocument.resolvedObjToken,
|
|
387
|
+
linkedDocument.wikiNodeToken
|
|
388
|
+
].join(":");
|
|
389
|
+
if (!linkedDocumentKeys.has(key)) {
|
|
390
|
+
linkedDocumentKeys.add(key);
|
|
391
|
+
linkedDocuments.push(linkedDocument);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (text) {
|
|
398
|
+
plainTextParts.push(text);
|
|
399
|
+
semanticTextParts.push(text);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return {
|
|
403
|
+
plainText: normalizeCommentText(plainTextParts),
|
|
404
|
+
semanticText: normalizeCommentSemanticText(semanticTextParts),
|
|
405
|
+
mentions,
|
|
406
|
+
linkedDocuments,
|
|
407
|
+
botMentioned
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
function extractReplyText(reply) {
|
|
411
|
+
if (!reply || !isRecord(reply.content)) return;
|
|
412
|
+
return parseCommentContentElements({ elements: Array.isArray(reply.content.elements) ? reply.content.elements : [] }).plainText;
|
|
413
|
+
}
|
|
414
|
+
//#endregion
|
|
128
415
|
//#region extensions/feishu/src/chat.ts
|
|
129
416
|
function readChatPageSize(params) {
|
|
130
417
|
return readPositiveIntegerParam(params, "page_size", {
|
|
@@ -292,6 +579,7 @@ function registerFeishuChatTools(api) {
|
|
|
292
579
|
if (!resolveAnyEnabledFeishuToolsConfig(accounts).chat) return;
|
|
293
580
|
api.registerTool((toolContext) => ({
|
|
294
581
|
name: "feishu_chat",
|
|
582
|
+
resultContentSource: "network",
|
|
295
583
|
label: "Feishu Chat",
|
|
296
584
|
description: "Feishu chat operations. Actions: members, info, member_info",
|
|
297
585
|
parameters: FeishuChatSchema,
|
|
@@ -310,7 +598,7 @@ function registerFeishuChatTools(api) {
|
|
|
310
598
|
const client = createFeishuClient(account);
|
|
311
599
|
switch (p.action) {
|
|
312
600
|
case "members":
|
|
313
|
-
if (!p.chat_id) return
|
|
601
|
+
if (!p.chat_id) return feishuExternalToolResult({ error: "chat_id is required for action members" });
|
|
314
602
|
{
|
|
315
603
|
const chat = await getAuthorizedFeishuChatInfo({
|
|
316
604
|
client,
|
|
@@ -327,12 +615,12 @@ function registerFeishuChatTools(api) {
|
|
|
327
615
|
ctx: toolContext,
|
|
328
616
|
memberIdType: p.member_id_type
|
|
329
617
|
});
|
|
330
|
-
if (authorization.kind === "direct") return
|
|
618
|
+
if (authorization.kind === "direct") return feishuExternalToolResult(buildFeishuDirectChatMembers(authorization));
|
|
331
619
|
}
|
|
332
|
-
return
|
|
620
|
+
return feishuExternalToolResult(await getChatMembers(client, p.chat_id, readChatPageSize(rawParams), p.page_token, p.member_id_type));
|
|
333
621
|
case "info":
|
|
334
|
-
if (!p.chat_id) return
|
|
335
|
-
return
|
|
622
|
+
if (!p.chat_id) return feishuExternalToolResult({ error: "chat_id is required for action info" });
|
|
623
|
+
return feishuExternalToolResult(await getAuthorizedFeishuChatInfo({
|
|
336
624
|
client,
|
|
337
625
|
cfg,
|
|
338
626
|
account,
|
|
@@ -340,8 +628,8 @@ function registerFeishuChatTools(api) {
|
|
|
340
628
|
ctx: toolContext
|
|
341
629
|
}));
|
|
342
630
|
case "member_info":
|
|
343
|
-
if (!p.member_id) return
|
|
344
|
-
if (!p.chat_id) return
|
|
631
|
+
if (!p.member_id) return feishuExternalToolResult({ error: "member_id is required for action member_info" });
|
|
632
|
+
if (!p.chat_id) return feishuExternalToolResult({ error: "chat_id is required for action member_info" });
|
|
345
633
|
{
|
|
346
634
|
const chat = await getAuthorizedFeishuChatInfo({
|
|
347
635
|
client,
|
|
@@ -362,27 +650,19 @@ function registerFeishuChatTools(api) {
|
|
|
362
650
|
if (authorization.kind === "group") {
|
|
363
651
|
const memberIdType = p.member_id_type ?? "open_id";
|
|
364
652
|
await assertFeishuChatMember(client, p.chat_id, p.member_id, memberIdType);
|
|
365
|
-
return
|
|
653
|
+
return feishuExternalToolResult(await getFeishuMemberInfo(client, p.member_id, memberIdType));
|
|
366
654
|
}
|
|
367
|
-
return
|
|
655
|
+
return feishuExternalToolResult(await getFeishuMemberInfo(client, authorization.memberId, authorization.memberIdType));
|
|
368
656
|
}
|
|
369
|
-
default: return
|
|
657
|
+
default: return feishuExternalToolResult({ error: `Unknown action: ${String(p.action)}` });
|
|
370
658
|
}
|
|
371
659
|
} catch (err) {
|
|
372
|
-
return
|
|
660
|
+
return feishuExternalToolResult({ error: formatFeishuApiError(err, { includeNestedErrorLogId: true }) });
|
|
373
661
|
}
|
|
374
662
|
}
|
|
375
663
|
}), { name: "feishu_chat" });
|
|
376
664
|
}
|
|
377
665
|
//#endregion
|
|
378
|
-
//#region extensions/feishu/src/tool-result.ts
|
|
379
|
-
function unknownToolActionResult(action) {
|
|
380
|
-
return jsonResult({ error: `Unknown action: ${String(action)}` });
|
|
381
|
-
}
|
|
382
|
-
function toolExecutionErrorResult(error) {
|
|
383
|
-
return jsonResult({ error: formatErrorMessage(error) });
|
|
384
|
-
}
|
|
385
|
-
//#endregion
|
|
386
666
|
//#region extensions/feishu/src/comment-reaction.ts
|
|
387
667
|
const COMMENT_TYPING_REACTION_TYPE = "Typing";
|
|
388
668
|
const COMMENT_REACTION_TIMEOUT_MS = 3e4;
|
|
@@ -726,15 +1006,15 @@ function formatDriveApiError(error) {
|
|
|
726
1006
|
return formatFeishuApiError(error, { includeConfigParams: true });
|
|
727
1007
|
}
|
|
728
1008
|
function extractDriveApiErrorMeta(error) {
|
|
729
|
-
if (!isRecord
|
|
730
|
-
const response = isRecord
|
|
731
|
-
const responseData = isRecord
|
|
1009
|
+
if (!isRecord(error)) return { message: typeof error === "string" ? error : JSON.stringify(error) };
|
|
1010
|
+
const response = isRecord(error.response) ? error.response : void 0;
|
|
1011
|
+
const responseData = isRecord(response?.data) ? response?.data : void 0;
|
|
732
1012
|
return {
|
|
733
1013
|
message: typeof error.message === "string" ? error.message : typeof error === "string" ? error : JSON.stringify(error),
|
|
734
1014
|
httpStatus: typeof response?.status === "number" ? response.status : void 0,
|
|
735
|
-
feishuCode: typeof responseData?.code === "number" ? responseData.code :
|
|
736
|
-
feishuMsg:
|
|
737
|
-
feishuLogId:
|
|
1015
|
+
feishuCode: typeof responseData?.code === "number" ? responseData.code : readStringValue(responseData?.code),
|
|
1016
|
+
feishuMsg: readStringValue(responseData?.msg),
|
|
1017
|
+
feishuLogId: readStringValue(responseData?.log_id)
|
|
738
1018
|
};
|
|
739
1019
|
}
|
|
740
1020
|
function isReplyNotAllowedError(error) {
|
|
@@ -1013,6 +1293,7 @@ function registerFeishuDriveTools(api) {
|
|
|
1013
1293
|
const defaultAccountId = ctx.agentAccountId;
|
|
1014
1294
|
return {
|
|
1015
1295
|
name: "feishu_drive",
|
|
1296
|
+
resultContentSource: "network",
|
|
1016
1297
|
label: "Feishu Drive",
|
|
1017
1298
|
description: "Feishu cloud storage operations. Actions: list, info, create_folder, move, delete, list_comments, list_comment_replies, add_comment, reply_comment",
|
|
1018
1299
|
parameters: FeishuDriveSchema,
|
|
@@ -1029,21 +1310,21 @@ function registerFeishuDriveTools(api) {
|
|
|
1029
1310
|
}
|
|
1030
1311
|
});
|
|
1031
1312
|
switch (p.action) {
|
|
1032
|
-
case "list": return
|
|
1313
|
+
case "list": return feishuExternalToolResult(await listFolder(client, {
|
|
1033
1314
|
folder_token: p.folder_token,
|
|
1034
1315
|
page_size: p.page_size,
|
|
1035
1316
|
page_token: p.page_token
|
|
1036
1317
|
}));
|
|
1037
|
-
case "info": return
|
|
1038
|
-
case "create_folder": return
|
|
1039
|
-
case "move": return
|
|
1040
|
-
case "delete": return
|
|
1041
|
-
case "list_comments": return
|
|
1042
|
-
case "list_comment_replies": return
|
|
1318
|
+
case "info": return feishuExternalToolResult(await getFileInfo(client, p.file_token, p.type));
|
|
1319
|
+
case "create_folder": return feishuExternalToolResult(await createFolder(client, p.name, p.folder_token));
|
|
1320
|
+
case "move": return feishuExternalToolResult(await moveFile(client, p.file_token, p.type, p.folder_token));
|
|
1321
|
+
case "delete": return feishuExternalToolResult(await deleteFile(client, p.file_token, p.type));
|
|
1322
|
+
case "list_comments": return feishuExternalToolResult(await listComments(client, applyCommentFileTypeDefault(applyAmbientCommentDefaults(p, ctx), "list_comments")));
|
|
1323
|
+
case "list_comment_replies": return feishuExternalToolResult(await listCommentReplies(client, applyCommentFileTypeDefault(applyAmbientCommentDefaults(p, ctx), "list_comment_replies")));
|
|
1043
1324
|
case "add_comment": {
|
|
1044
1325
|
const resolved = applyAddCommentDefaults(applyAddCommentAmbientDefaults(p, ctx));
|
|
1045
1326
|
try {
|
|
1046
|
-
return
|
|
1327
|
+
return feishuExternalToolResult(await addComment(client, resolved));
|
|
1047
1328
|
} finally {
|
|
1048
1329
|
cleanupAmbientCommentTypingReaction({
|
|
1049
1330
|
client: getDriveInternalClient(client),
|
|
@@ -1054,7 +1335,7 @@ function registerFeishuDriveTools(api) {
|
|
|
1054
1335
|
case "reply_comment": {
|
|
1055
1336
|
const resolved = applyCommentFileTypeDefault(applyAmbientCommentDefaults(p, ctx), "reply_comment");
|
|
1056
1337
|
try {
|
|
1057
|
-
return
|
|
1338
|
+
return feishuExternalToolResult(await deliverCommentThreadText(client, resolved));
|
|
1058
1339
|
} finally {
|
|
1059
1340
|
cleanupAmbientCommentTypingReaction({
|
|
1060
1341
|
client: getDriveInternalClient(client),
|
|
@@ -1072,4 +1353,4 @@ function registerFeishuDriveTools(api) {
|
|
|
1072
1353
|
}, { name: "feishu_drive" });
|
|
1073
1354
|
}
|
|
1074
1355
|
//#endregion
|
|
1075
|
-
export {
|
|
1356
|
+
export { resolveFeishuToolAccount as C, resolveAnyEnabledFeishuToolsConfig as S, parseFeishuCommentTarget as _, assertFeishuChatMember as a, unknownToolActionResult as b, getChatMembers as c, encodeQuery as d, extractReplyText as f, normalizeCommentFileType as g, buildFeishuCommentTarget as h, createCommentTypingReactionLifecycle as i, getFeishuMemberInfo as l, requestFeishuApi as m, registerFeishuDriveTools as n, buildFeishuDirectChatMembers as o, parseCommentContentElements as p, cleanupAmbientCommentTypingReaction as r, getChatInfo as s, deliverCommentThreadText as t, registerFeishuChatTools as u, feishuExternalToolResult as v, createFeishuToolClient as x, toolExecutionErrorResult as y };
|