@openclaw/feishu 2026.9.1-beta.1 → 2026.9.2
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-RwSyseKr.js → accounts-cCMNFBKg.js} +1 -1
- package/dist/api.js +222 -284
- package/dist/{app-registration-BpfUzS9m.js → app-registration-BI99e_JI.js} +12 -9
- package/dist/{channel-Dpgf8wLD.js → channel-VytDDz_B.js} +244 -582
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-BIEERwaT.js → channel.runtime-CAD74kBO.js} +15 -19
- package/dist/{chat-C1nuW5UY.js → chat-DDhIcPQy.js} +13 -13
- package/dist/{client-DalLmpMf.js → client-DMbIL3UH.js} +3 -6
- package/dist/contract-api.js +2 -2
- package/dist/doctor-contract-api.js +1 -1
- package/dist/doctor-contract-w6FpMypv.js +465 -0
- package/dist/index.js +11 -42
- package/dist/{json-response-CheljwGr.js → json-response-DXajw_FU.js} +1 -1
- package/dist/{monitor.startup-D-gL82OO.js → monitor-rPJ_Mz4M.js} +62 -2
- package/dist/{monitor.account-DhhotI_Q.js → monitor.account-v0XIDyfs.js} +270 -299
- package/dist/{probe-CfhhR_0a.js → probe-D_SatdZl.js} +3 -3
- package/dist/{presentation-card-C8Z7Tgru.js → reply-delivery-result-CYaKkbUN.js} +334 -240
- package/dist/{security-audit-D6Fz2h6p.js → security-audit-DKfR4Cv3.js} +1 -1
- package/dist/{security-audit-shared-BgpY7AiJ.js → security-audit-shared-CK5rVR-1.js} +2 -1
- package/dist/security-contract-api.js +1 -1
- package/dist/session-binding-contract-api.js +1 -1
- package/dist/setup-api.js +1 -1
- package/dist/{subagent-hooks-KUi-7vUy.js → subagent-hooks-Buadpie_.js} +3 -6
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/{targets-BUjQ1TcA.js → targets-BTQCYRZQ.js} +4 -4
- package/dist/{thread-bindings-CptM_YU6.js → thread-bindings-BiL1wGqK.js} +20 -9
- package/node_modules/@larksuiteoapi/node-sdk/node_modules/ws/lib/permessage-deflate.js +3 -1
- package/node_modules/@larksuiteoapi/node-sdk/node_modules/ws/package.json +1 -1
- package/node_modules/typebox/build/format/email.mjs +1 -1
- package/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
- package/node_modules/typebox/build/format/json_pointer.d.mts +2 -2
- package/node_modules/typebox/build/format/json_pointer.mjs +2 -2
- package/node_modules/typebox/build/format/json_pointer_uri_fragment.d.mts +2 -2
- package/node_modules/typebox/build/format/json_pointer_uri_fragment.mjs +2 -2
- package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
- package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
- package/node_modules/typebox/build/system/memory/assign.mjs +2 -1
- package/node_modules/typebox/build/system/memory/create.mjs +3 -4
- package/node_modules/typebox/build/system/memory/discard.mjs +2 -2
- package/node_modules/typebox/build/system/memory/freeze.d.mts +4 -0
- package/node_modules/typebox/build/system/memory/freeze.mjs +6 -0
- package/node_modules/typebox/build/system/memory/update.mjs +3 -2
- package/node_modules/typebox/package.json +1 -1
- package/openclaw.plugin.json +45 -238
- package/package.json +6 -5
- package/dist/doctor-contract-bEQXIXyP.js +0 -158
- package/dist/monitor-BRg3sHH7.js +0 -62
package/dist/api.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { r as
|
|
2
|
-
import {
|
|
3
|
-
import { A as feishuExternalToolResult, F as resolveFeishuToolAccount, M as unknownToolActionResult, N as createFeishuToolClient, P as resolveAnyEnabledFeishuToolsConfig, Q as parseFeishuMarkdown, Y as chunkFeishuMarkdown, j as toolExecutionErrorResult, k as registerFeishuDriveTools } from "./presentation-card-C8Z7Tgru.js";
|
|
1
|
+
import { a as setFeishuNamedAccountEnabled, i as feishuSetupAdapter, n as feishuSetupWizard, r as runFeishuLogin, t as feishuPlugin } from "./channel-VytDDz_B.js";
|
|
2
|
+
import { G as createFeishuToolClient, H as feishuExternalToolResult, K as resolveAnyEnabledFeishuToolsConfig, U as toolExecutionErrorResult, V as registerFeishuDriveTools, W as unknownToolActionResult, lt as parseFeishuMarkdown, ot as chunkFeishuMarkdown, q as resolveFeishuToolAccount } from "./reply-delivery-result-CYaKkbUN.js";
|
|
4
3
|
import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, n as buildFeishuModelOverrideParentCandidates, r as parseFeishuConversationId, t as buildFeishuConversationId } from "./conversation-id-VYgGQ-GX.js";
|
|
5
|
-
import { s as resolveConfiguredHttpTimeoutMs } from "./client-
|
|
4
|
+
import { s as resolveConfiguredHttpTimeoutMs } from "./client-DMbIL3UH.js";
|
|
6
5
|
import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
|
|
7
|
-
import { o as registerFeishuChatTools } from "./chat-
|
|
8
|
-
import { n as getFeishuThreadBindingManager, t as createFeishuThreadBindingManager } from "./thread-bindings-
|
|
9
|
-
import { n as handleFeishuSubagentEnded, t as handleFeishuSubagentDeliveryTarget } from "./subagent-hooks-
|
|
6
|
+
import { o as registerFeishuChatTools } from "./chat-DDhIcPQy.js";
|
|
7
|
+
import { n as getFeishuThreadBindingManager, t as createFeishuThreadBindingManager } from "./thread-bindings-BiL1wGqK.js";
|
|
8
|
+
import { n as handleFeishuSubagentEnded, t as handleFeishuSubagentDeliveryTarget } from "./subagent-hooks-Buadpie_.js";
|
|
10
9
|
import { optionalPositiveIntegerSchema } from "openclaw/plugin-sdk/channel-actions";
|
|
11
10
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
12
11
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, readStringValue, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
@@ -167,23 +166,6 @@ const FeishuDocSchema = Type.Union([
|
|
|
167
166
|
const MIN_COLUMN_WIDTH = 50;
|
|
168
167
|
const MAX_COLUMN_WIDTH = 400;
|
|
169
168
|
const DEFAULT_TABLE_WIDTH = 730;
|
|
170
|
-
/**
|
|
171
|
-
* Calculate adaptive column widths based on cell content length.
|
|
172
|
-
*
|
|
173
|
-
* Algorithm:
|
|
174
|
-
* 1. For each column, find the max content length across all rows
|
|
175
|
-
* 2. Weight CJK characters as 2x width (they render wider)
|
|
176
|
-
* 3. Calculate proportional widths based on content length
|
|
177
|
-
* 4. Apply min/max constraints
|
|
178
|
-
* 5. Redistribute remaining space to fill total table width
|
|
179
|
-
*
|
|
180
|
-
* Total width is derived from the original column_width values returned
|
|
181
|
-
* by the Convert API, ensuring tables match Feishu's expected dimensions.
|
|
182
|
-
*
|
|
183
|
-
* @param blocks - Array of blocks from Convert API
|
|
184
|
-
* @param tableBlockId - The block_id of the table block
|
|
185
|
-
* @returns Array of column widths in pixels
|
|
186
|
-
*/
|
|
187
169
|
function normalizeChildBlockIds(children) {
|
|
188
170
|
if (Array.isArray(children)) return children;
|
|
189
171
|
return typeof children === "string" ? [children] : [];
|
|
@@ -288,86 +270,61 @@ function cleanBlocksForDescendant(blocks) {
|
|
|
288
270
|
return cleanBlock;
|
|
289
271
|
});
|
|
290
272
|
}
|
|
291
|
-
async function
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
async function deleteTableColumns(client, docToken, blockId, columnStart, columnCount = 1) {
|
|
338
|
-
const res = await client.docx.documentBlock.patch({
|
|
339
|
-
path: {
|
|
340
|
-
document_id: docToken,
|
|
341
|
-
block_id: blockId
|
|
342
|
-
},
|
|
343
|
-
data: { delete_table_columns: {
|
|
344
|
-
column_start_index: columnStart,
|
|
345
|
-
column_end_index: columnStart + columnCount
|
|
346
|
-
} }
|
|
347
|
-
});
|
|
348
|
-
if (res.code !== 0) throw new Error(res.msg);
|
|
349
|
-
return {
|
|
350
|
-
success: true,
|
|
351
|
-
columns_deleted: columnCount,
|
|
352
|
-
block: res.data?.block
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
async function mergeTableCells(client, docToken, blockId, rowStart, rowEnd, columnStart, columnEnd) {
|
|
273
|
+
async function patchTable(client, params) {
|
|
274
|
+
const { doc_token, block_id } = params;
|
|
275
|
+
let data;
|
|
276
|
+
const counts = {};
|
|
277
|
+
switch (params.action) {
|
|
278
|
+
case "insert_table_row": {
|
|
279
|
+
const { row_index = -1 } = params;
|
|
280
|
+
data = { insert_table_row: { row_index } };
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
case "insert_table_column": {
|
|
284
|
+
const { column_index = -1 } = params;
|
|
285
|
+
data = { insert_table_column: { column_index } };
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
case "delete_table_rows": {
|
|
289
|
+
const { row_start, row_count = 1 } = params;
|
|
290
|
+
data = { delete_table_rows: {
|
|
291
|
+
row_start_index: row_start,
|
|
292
|
+
row_end_index: row_start + row_count
|
|
293
|
+
} };
|
|
294
|
+
counts.rows_deleted = row_count;
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
case "delete_table_columns": {
|
|
298
|
+
const { column_start, column_count = 1 } = params;
|
|
299
|
+
data = { delete_table_columns: {
|
|
300
|
+
column_start_index: column_start,
|
|
301
|
+
column_end_index: column_start + column_count
|
|
302
|
+
} };
|
|
303
|
+
counts.columns_deleted = column_count;
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
case "merge_table_cells": {
|
|
307
|
+
const { row_start, row_end, column_start, column_end } = params;
|
|
308
|
+
data = { merge_table_cells: {
|
|
309
|
+
row_start_index: row_start,
|
|
310
|
+
row_end_index: row_end,
|
|
311
|
+
column_start_index: column_start,
|
|
312
|
+
column_end_index: column_end
|
|
313
|
+
} };
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
356
317
|
const res = await client.docx.documentBlock.patch({
|
|
357
318
|
path: {
|
|
358
|
-
document_id:
|
|
359
|
-
block_id
|
|
319
|
+
document_id: doc_token,
|
|
320
|
+
block_id
|
|
360
321
|
},
|
|
361
|
-
data
|
|
362
|
-
row_start_index: rowStart,
|
|
363
|
-
row_end_index: rowEnd,
|
|
364
|
-
column_start_index: columnStart,
|
|
365
|
-
column_end_index: columnEnd
|
|
366
|
-
} }
|
|
322
|
+
data
|
|
367
323
|
});
|
|
368
324
|
if (res.code !== 0) throw new Error(res.msg);
|
|
369
325
|
return {
|
|
370
326
|
success: true,
|
|
327
|
+
...counts,
|
|
371
328
|
block: res.data?.block
|
|
372
329
|
};
|
|
373
330
|
}
|
|
@@ -836,7 +793,7 @@ const BLOCK_TYPE_NAMES = {
|
|
|
836
793
|
32: "TableCell"
|
|
837
794
|
};
|
|
838
795
|
const UNSUPPORTED_CREATE_TYPES = /* @__PURE__ */ new Set([31, 32]);
|
|
839
|
-
/**
|
|
796
|
+
/** Remove block types unsupported by the children insertion API. */
|
|
840
797
|
function cleanBlocksForInsert(blocks) {
|
|
841
798
|
const skipped = [];
|
|
842
799
|
return {
|
|
@@ -847,24 +804,21 @@ function cleanBlocksForInsert(blocks) {
|
|
|
847
804
|
return false;
|
|
848
805
|
}
|
|
849
806
|
return true;
|
|
850
|
-
}).map((block) => {
|
|
851
|
-
if (block.block_type === 31 && block.table?.merge_info) {
|
|
852
|
-
const { merge_info: _merge_info, ...tableRest } = block.table;
|
|
853
|
-
return Object.assign({}, block, { table: tableRest });
|
|
854
|
-
}
|
|
855
|
-
return block;
|
|
856
807
|
}),
|
|
857
808
|
skipped
|
|
858
809
|
};
|
|
859
810
|
}
|
|
860
811
|
/** Max blocks per documentBlockChildren.create request */
|
|
861
812
|
const MAX_CONVERT_RETRY_DEPTH = 8;
|
|
813
|
+
function assertFeishuDocApiSuccess(response) {
|
|
814
|
+
if (response.code !== 0) throw new Error(response.msg);
|
|
815
|
+
}
|
|
862
816
|
async function convertMarkdown(client, markdown) {
|
|
863
817
|
const res = await client.docx.document.convert({ data: {
|
|
864
818
|
content_type: "markdown",
|
|
865
819
|
content: markdown
|
|
866
820
|
} });
|
|
867
|
-
|
|
821
|
+
assertFeishuDocApiSuccess(res);
|
|
868
822
|
return {
|
|
869
823
|
blocks: res.data?.blocks ?? [],
|
|
870
824
|
firstLevelBlockIds: res.data?.first_level_block_ids ?? []
|
|
@@ -909,7 +863,8 @@ function normalizeConvertedBlockTree(blocks, firstLevelIds) {
|
|
|
909
863
|
const parentId = typeof block?.parent_id === "string" ? block.parent_id : "";
|
|
910
864
|
return !childIds.has(blockId) && (!parentId || !byId.has(parentId));
|
|
911
865
|
}).toSorted((a, b) => (originalOrder.get(a.block_id ?? "__missing__") ?? 0) - (originalOrder.get(b.block_id ?? "__missing__") ?? 0)).map((block) => block.block_id).filter((blockId) => typeof blockId === "string");
|
|
912
|
-
const
|
|
866
|
+
const rootIds = (firstLevelIds && firstLevelIds.length > 0 ? firstLevelIds : inferredTopLevelIds).filter((id) => typeof id === "string" && byId.has(id));
|
|
867
|
+
const uniqueRootIds = uniqueStrings(rootIds);
|
|
913
868
|
const orderedBlocks = [];
|
|
914
869
|
const visited = /* @__PURE__ */ new Set();
|
|
915
870
|
const visit = (blockId) => {
|
|
@@ -947,7 +902,7 @@ async function insertBlocks(client, docToken, blocks, parentBlockId, index) {
|
|
|
947
902
|
...index !== void 0 ? { index: index + offset } : {}
|
|
948
903
|
}
|
|
949
904
|
});
|
|
950
|
-
|
|
905
|
+
assertFeishuDocApiSuccess(res);
|
|
951
906
|
allInserted.push(...res.data?.children ?? []);
|
|
952
907
|
}
|
|
953
908
|
return {
|
|
@@ -1026,21 +981,18 @@ async function insertBlocksWithDescendant(client, docToken, blocks, firstLevelBl
|
|
|
1026
981
|
}
|
|
1027
982
|
async function clearDocumentContent(client, docToken) {
|
|
1028
983
|
const existing = await client.docx.documentBlock.list({ path: { document_id: docToken } });
|
|
1029
|
-
|
|
984
|
+
assertFeishuDocApiSuccess(existing);
|
|
1030
985
|
const childIds = existing.data?.items?.filter((b) => b.parent_id === docToken && b.block_type !== 1).map((b) => b.block_id) ?? [];
|
|
1031
|
-
if (childIds.length > 0) {
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
});
|
|
1042
|
-
if (res.code !== 0) throw new Error(res.msg);
|
|
1043
|
-
}
|
|
986
|
+
if (childIds.length > 0) assertFeishuDocApiSuccess(await client.docx.documentBlockChildren.batchDelete({
|
|
987
|
+
path: {
|
|
988
|
+
document_id: docToken,
|
|
989
|
+
block_id: docToken
|
|
990
|
+
},
|
|
991
|
+
data: {
|
|
992
|
+
start_index: 0,
|
|
993
|
+
end_index: childIds.length
|
|
994
|
+
}
|
|
995
|
+
}));
|
|
1044
996
|
return childIds.length;
|
|
1045
997
|
}
|
|
1046
998
|
async function uploadImageToDocx(client, blockId, imageBuffer, fileName, docToken) {
|
|
@@ -1070,13 +1022,13 @@ async function processImages(client, docToken, images, insertedBlocks, maxBytes,
|
|
|
1070
1022
|
remoteReadTimeoutMs: imageReadTimeoutMs
|
|
1071
1023
|
});
|
|
1072
1024
|
const fileToken = await uploadImageToDocx(client, blockId, upload.buffer, upload.fileName, docToken);
|
|
1073
|
-
await client.docx.documentBlock.patch({
|
|
1025
|
+
assertFeishuDocApiSuccess(await client.docx.documentBlock.patch({
|
|
1074
1026
|
path: {
|
|
1075
1027
|
document_id: docToken,
|
|
1076
1028
|
block_id: blockId
|
|
1077
1029
|
},
|
|
1078
1030
|
data: { replace_image: { token: fileToken } }
|
|
1079
|
-
});
|
|
1031
|
+
}));
|
|
1080
1032
|
processed++;
|
|
1081
1033
|
} catch (err) {
|
|
1082
1034
|
console.error(`Failed to process image ${url}:`, err);
|
|
@@ -1133,14 +1085,13 @@ async function uploadImageBlock(client, docToken, maxBytes, imageReadTimeoutMs,
|
|
|
1133
1085
|
const imageBlockId = insertRes.data?.children?.find((b) => b.block_type === 27)?.block_id;
|
|
1134
1086
|
if (!imageBlockId) throw new Error("Failed to create image block");
|
|
1135
1087
|
const fileToken = await uploadImageToDocx(client, imageBlockId, upload.buffer, upload.fileName, docToken);
|
|
1136
|
-
|
|
1088
|
+
assertFeishuDocApiSuccess(await client.docx.documentBlock.patch({
|
|
1137
1089
|
path: {
|
|
1138
1090
|
document_id: docToken,
|
|
1139
1091
|
block_id: imageBlockId
|
|
1140
1092
|
},
|
|
1141
1093
|
data: { replace_image: { token: fileToken } }
|
|
1142
|
-
});
|
|
1143
|
-
if (patchRes.code !== 0) throw new Error(patchRes.msg);
|
|
1094
|
+
}));
|
|
1144
1095
|
return {
|
|
1145
1096
|
success: true,
|
|
1146
1097
|
block_id: imageBlockId,
|
|
@@ -1168,21 +1119,18 @@ async function uploadFileBlock(client, docToken, maxBytes, localRoots, url, file
|
|
|
1168
1119
|
document_id: docToken,
|
|
1169
1120
|
block_id: parentId
|
|
1170
1121
|
} });
|
|
1171
|
-
|
|
1122
|
+
assertFeishuDocApiSuccess(childrenRes);
|
|
1172
1123
|
const placeholderIdx = (childrenRes.data?.items ?? []).findIndex((item) => item.block_id === placeholderBlock.block_id);
|
|
1173
|
-
if (placeholderIdx >= 0) {
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
});
|
|
1184
|
-
if (deleteRes.code !== 0) throw new Error(deleteRes.msg);
|
|
1185
|
-
}
|
|
1124
|
+
if (placeholderIdx >= 0) assertFeishuDocApiSuccess(await client.docx.documentBlockChildren.batchDelete({
|
|
1125
|
+
path: {
|
|
1126
|
+
document_id: docToken,
|
|
1127
|
+
block_id: parentId
|
|
1128
|
+
},
|
|
1129
|
+
data: {
|
|
1130
|
+
start_index: placeholderIdx,
|
|
1131
|
+
end_index: placeholderIdx + 1
|
|
1132
|
+
}
|
|
1133
|
+
}));
|
|
1186
1134
|
const fileToken = (await client.drive.media.uploadAll({ data: {
|
|
1187
1135
|
file_name: upload.fileName,
|
|
1188
1136
|
parent_type: "docx_file",
|
|
@@ -1215,7 +1163,7 @@ async function readDoc(client, docToken) {
|
|
|
1215
1163
|
client.docx.document.get({ path: { document_id: docToken } }),
|
|
1216
1164
|
client.docx.documentBlock.list({ path: { document_id: docToken } })
|
|
1217
1165
|
]);
|
|
1218
|
-
|
|
1166
|
+
assertFeishuDocApiSuccess(contentRes);
|
|
1219
1167
|
const blocks = blocksRes.data?.items ?? [];
|
|
1220
1168
|
const blockCounts = {};
|
|
1221
1169
|
const structuredTypes = [];
|
|
@@ -1241,7 +1189,7 @@ async function createDoc(client, title, folderToken, options) {
|
|
|
1241
1189
|
title,
|
|
1242
1190
|
folder_token: folderToken
|
|
1243
1191
|
} });
|
|
1244
|
-
|
|
1192
|
+
assertFeishuDocApiSuccess(res);
|
|
1245
1193
|
const doc = res.data?.document;
|
|
1246
1194
|
const docToken = doc?.document_id;
|
|
1247
1195
|
if (!docToken) throw new Error("Document creation succeeded but no document_id was returned");
|
|
@@ -1251,23 +1199,25 @@ async function createDoc(client, title, folderToken, options) {
|
|
|
1251
1199
|
let requesterPermissionAdded = false;
|
|
1252
1200
|
let requesterPermissionSkippedReason;
|
|
1253
1201
|
let requesterPermissionError;
|
|
1254
|
-
if (shouldGrantToRequester)
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1202
|
+
if (shouldGrantToRequester) {
|
|
1203
|
+
if (!requesterOpenId) requesterPermissionSkippedReason = "trusted requester identity unavailable";
|
|
1204
|
+
else try {
|
|
1205
|
+
assertFeishuDocApiSuccess(await client.drive.permissionMember.create({
|
|
1206
|
+
path: { token: docToken },
|
|
1207
|
+
params: {
|
|
1208
|
+
type: "docx",
|
|
1209
|
+
need_notification: false
|
|
1210
|
+
},
|
|
1211
|
+
data: {
|
|
1212
|
+
member_type: "openid",
|
|
1213
|
+
member_id: requesterOpenId,
|
|
1214
|
+
perm: requesterPermType
|
|
1215
|
+
}
|
|
1216
|
+
}));
|
|
1217
|
+
requesterPermissionAdded = true;
|
|
1218
|
+
} catch (err) {
|
|
1219
|
+
requesterPermissionError = formatErrorMessage(err);
|
|
1220
|
+
}
|
|
1271
1221
|
}
|
|
1272
1222
|
return {
|
|
1273
1223
|
document_id: docToken,
|
|
@@ -1326,11 +1276,12 @@ async function insertDoc(client, docToken, markdown, afterBlockId, maxBytes, ima
|
|
|
1326
1276
|
document_id: docToken,
|
|
1327
1277
|
block_id: afterBlockId
|
|
1328
1278
|
} });
|
|
1329
|
-
|
|
1279
|
+
assertFeishuDocApiSuccess(blockInfo);
|
|
1330
1280
|
const parentId = blockInfo.data?.block?.parent_id ?? docToken;
|
|
1331
1281
|
const items = [];
|
|
1332
1282
|
let pageToken;
|
|
1333
|
-
|
|
1283
|
+
const seenPageTokens = /* @__PURE__ */ new Set();
|
|
1284
|
+
while (true) {
|
|
1334
1285
|
const childrenRes = await client.docx.documentBlockChildren.get({
|
|
1335
1286
|
path: {
|
|
1336
1287
|
document_id: docToken,
|
|
@@ -1338,10 +1289,15 @@ async function insertDoc(client, docToken, markdown, afterBlockId, maxBytes, ima
|
|
|
1338
1289
|
},
|
|
1339
1290
|
params: pageToken ? { page_token: pageToken } : {}
|
|
1340
1291
|
});
|
|
1341
|
-
|
|
1292
|
+
assertFeishuDocApiSuccess(childrenRes);
|
|
1342
1293
|
items.push(...childrenRes.data?.items ?? []);
|
|
1343
|
-
|
|
1344
|
-
|
|
1294
|
+
if (childrenRes.data?.has_more !== true) break;
|
|
1295
|
+
const nextPageToken = childrenRes.data.page_token?.trim();
|
|
1296
|
+
if (!nextPageToken) throw new Error(`Feishu document children pagination is missing its next page token for parent block "${parentId}"`);
|
|
1297
|
+
if (seenPageTokens.has(nextPageToken)) throw new Error(`Feishu document children pagination repeated token for parent block "${parentId}"`);
|
|
1298
|
+
seenPageTokens.add(nextPageToken);
|
|
1299
|
+
pageToken = nextPageToken;
|
|
1300
|
+
}
|
|
1345
1301
|
const blockIndex = items.findIndex((item) => item.block_id === afterBlockId);
|
|
1346
1302
|
if (blockIndex === -1) throw new Error(`after_block_id "${afterBlockId}" was not found among the children of parent block "${parentId}". Use list_blocks to verify the block ID.`);
|
|
1347
1303
|
const { blocks, inserted, imagesProcessed } = await convertInsertAndProcessDocx({
|
|
@@ -1383,7 +1339,7 @@ async function createTable(client, docToken, rowSize, columnSize, parentBlockId,
|
|
|
1383
1339
|
} }
|
|
1384
1340
|
}] }
|
|
1385
1341
|
});
|
|
1386
|
-
|
|
1342
|
+
assertFeishuDocApiSuccess(res);
|
|
1387
1343
|
const tableBlock = res.data?.children?.find((b) => b.block_type === 31);
|
|
1388
1344
|
const cells = normalizeInsertedChildBlocks(tableBlock?.children);
|
|
1389
1345
|
return {
|
|
@@ -1401,7 +1357,7 @@ async function writeTableCells(client, docToken, tableBlockId, values) {
|
|
|
1401
1357
|
document_id: docToken,
|
|
1402
1358
|
block_id: tableBlockId
|
|
1403
1359
|
} });
|
|
1404
|
-
|
|
1360
|
+
assertFeishuDocApiSuccess(tableRes);
|
|
1405
1361
|
const tableBlock = tableRes.data?.block;
|
|
1406
1362
|
if (tableBlock?.block_type !== 31) throw new Error("table_block_id is not a table block");
|
|
1407
1363
|
const tableData = tableBlock.table;
|
|
@@ -1421,21 +1377,18 @@ async function writeTableCells(client, docToken, tableBlockId, values) {
|
|
|
1421
1377
|
document_id: docToken,
|
|
1422
1378
|
block_id: cellId
|
|
1423
1379
|
} });
|
|
1424
|
-
|
|
1380
|
+
assertFeishuDocApiSuccess(childrenRes);
|
|
1425
1381
|
const existingChildren = childrenRes.data?.items ?? [];
|
|
1426
|
-
if (existingChildren.length > 0) {
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
});
|
|
1437
|
-
if (delRes.code !== 0) throw new Error(delRes.msg);
|
|
1438
|
-
}
|
|
1382
|
+
if (existingChildren.length > 0) assertFeishuDocApiSuccess(await client.docx.documentBlockChildren.batchDelete({
|
|
1383
|
+
path: {
|
|
1384
|
+
document_id: docToken,
|
|
1385
|
+
block_id: cellId
|
|
1386
|
+
},
|
|
1387
|
+
data: {
|
|
1388
|
+
start_index: 0,
|
|
1389
|
+
end_index: existingChildren.length
|
|
1390
|
+
}
|
|
1391
|
+
}));
|
|
1439
1392
|
const converted = await convertMarkdown(client, rowValues[c] ?? "");
|
|
1440
1393
|
const { orderedBlocks } = normalizeConvertedBlockTree(converted.blocks, converted.firstLevelBlockIds);
|
|
1441
1394
|
if (orderedBlocks.length > 0) await insertBlocks(client, docToken, orderedBlocks, cellId);
|
|
@@ -1464,19 +1417,17 @@ async function createTableWithValues(client, docToken, rowSize, columnSize, valu
|
|
|
1464
1417
|
};
|
|
1465
1418
|
}
|
|
1466
1419
|
async function updateBlock(client, docToken, blockId, content) {
|
|
1467
|
-
|
|
1420
|
+
assertFeishuDocApiSuccess(await client.docx.documentBlock.get({ path: {
|
|
1468
1421
|
document_id: docToken,
|
|
1469
1422
|
block_id: blockId
|
|
1470
|
-
} });
|
|
1471
|
-
|
|
1472
|
-
const res = await client.docx.documentBlock.patch({
|
|
1423
|
+
} }));
|
|
1424
|
+
assertFeishuDocApiSuccess(await client.docx.documentBlock.patch({
|
|
1473
1425
|
path: {
|
|
1474
1426
|
document_id: docToken,
|
|
1475
1427
|
block_id: blockId
|
|
1476
1428
|
},
|
|
1477
1429
|
data: { update_text_elements: { elements: [{ text_run: { content } }] } }
|
|
1478
|
-
});
|
|
1479
|
-
if (res.code !== 0) throw new Error(res.msg);
|
|
1430
|
+
}));
|
|
1480
1431
|
return {
|
|
1481
1432
|
success: true,
|
|
1482
1433
|
block_id: blockId
|
|
@@ -1487,16 +1438,16 @@ async function deleteBlock(client, docToken, blockId) {
|
|
|
1487
1438
|
document_id: docToken,
|
|
1488
1439
|
block_id: blockId
|
|
1489
1440
|
} });
|
|
1490
|
-
|
|
1441
|
+
assertFeishuDocApiSuccess(blockInfo);
|
|
1491
1442
|
const parentId = blockInfo.data?.block?.parent_id ?? docToken;
|
|
1492
1443
|
const children = await client.docx.documentBlockChildren.get({ path: {
|
|
1493
1444
|
document_id: docToken,
|
|
1494
1445
|
block_id: parentId
|
|
1495
1446
|
} });
|
|
1496
|
-
|
|
1447
|
+
assertFeishuDocApiSuccess(children);
|
|
1497
1448
|
const index = (children.data?.items ?? []).findIndex((item) => item.block_id === blockId);
|
|
1498
1449
|
if (index === -1) throw new Error("Block not found");
|
|
1499
|
-
|
|
1450
|
+
assertFeishuDocApiSuccess(await client.docx.documentBlockChildren.batchDelete({
|
|
1500
1451
|
path: {
|
|
1501
1452
|
document_id: docToken,
|
|
1502
1453
|
block_id: parentId
|
|
@@ -1505,8 +1456,7 @@ async function deleteBlock(client, docToken, blockId) {
|
|
|
1505
1456
|
start_index: index,
|
|
1506
1457
|
end_index: index + 1
|
|
1507
1458
|
}
|
|
1508
|
-
});
|
|
1509
|
-
if (res.code !== 0) throw new Error(res.msg);
|
|
1459
|
+
}));
|
|
1510
1460
|
return {
|
|
1511
1461
|
success: true,
|
|
1512
1462
|
deleted_block_id: blockId
|
|
@@ -1514,7 +1464,7 @@ async function deleteBlock(client, docToken, blockId) {
|
|
|
1514
1464
|
}
|
|
1515
1465
|
async function listBlocks(client, docToken) {
|
|
1516
1466
|
const res = await client.docx.documentBlock.list({ path: { document_id: docToken } });
|
|
1517
|
-
|
|
1467
|
+
assertFeishuDocApiSuccess(res);
|
|
1518
1468
|
return { blocks: res.data?.items ?? [] };
|
|
1519
1469
|
}
|
|
1520
1470
|
async function getBlock(client, docToken, blockId) {
|
|
@@ -1522,12 +1472,12 @@ async function getBlock(client, docToken, blockId) {
|
|
|
1522
1472
|
document_id: docToken,
|
|
1523
1473
|
block_id: blockId
|
|
1524
1474
|
} });
|
|
1525
|
-
|
|
1475
|
+
assertFeishuDocApiSuccess(res);
|
|
1526
1476
|
return { block: res.data?.block };
|
|
1527
1477
|
}
|
|
1528
1478
|
async function listAppScopes(client) {
|
|
1529
1479
|
const res = await client.application.scope.list({});
|
|
1530
|
-
|
|
1480
|
+
assertFeishuDocApiSuccess(res);
|
|
1531
1481
|
const scopes = res.data?.scopes ?? [];
|
|
1532
1482
|
const granted = scopes.filter((s) => s.grant_status === 1);
|
|
1533
1483
|
const pending = scopes.filter((s) => s.grant_status !== 1);
|
|
@@ -1545,10 +1495,7 @@ async function listAppScopes(client) {
|
|
|
1545
1495
|
}
|
|
1546
1496
|
function registerFeishuDocTools(api) {
|
|
1547
1497
|
if (!api.config) return;
|
|
1548
|
-
const
|
|
1549
|
-
if (accounts.length === 0) return;
|
|
1550
|
-
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(accounts);
|
|
1551
|
-
const registered = [];
|
|
1498
|
+
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(api.config);
|
|
1552
1499
|
const getClient = (params, defaultAccountId) => createFeishuToolClient({
|
|
1553
1500
|
api,
|
|
1554
1501
|
executeParams: params,
|
|
@@ -1576,80 +1523,75 @@ function registerFeishuDocTools(api) {
|
|
|
1576
1523
|
label: "Doc"
|
|
1577
1524
|
}
|
|
1578
1525
|
}));
|
|
1579
|
-
if (toolsCfg.doc) {
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
name: "feishu_doc",
|
|
1586
|
-
resultContentSource: "network",
|
|
1587
|
-
label: "Feishu Doc",
|
|
1588
|
-
description: "Feishu document operations. Actions: read, write, append, insert, create, list_blocks, get_block, update_block, delete_block, create_table, write_table_cells, create_table_with_values, insert_table_row, insert_table_column, delete_table_rows, delete_table_columns, merge_table_cells, upload_image, upload_file, color_text",
|
|
1589
|
-
parameters: FeishuDocSchema,
|
|
1590
|
-
async execute(_toolCallId, params) {
|
|
1591
|
-
const p = params;
|
|
1592
|
-
try {
|
|
1593
|
-
if (p.action === "create" && Object.hasOwn(p, "content")) return feishuExternalToolResult({ error: "Feishu document creation does not support content. Call action \"create\" first, then call action \"write\" with the returned document_id as doc_token." });
|
|
1594
|
-
const client = getClient(p, defaultAccountId);
|
|
1595
|
-
switch (p.action) {
|
|
1596
|
-
case "read": return feishuExternalToolResult(await readDoc(client, p.doc_token));
|
|
1597
|
-
case "write": return feishuExternalToolResult(await writeDoc(client, p.doc_token, p.content, getMediaMaxBytes(p, defaultAccountId), getImageReadTimeoutMs(p, defaultAccountId), api.logger));
|
|
1598
|
-
case "append": return feishuExternalToolResult(await appendDoc(client, p.doc_token, p.content, getMediaMaxBytes(p, defaultAccountId), getImageReadTimeoutMs(p, defaultAccountId), api.logger));
|
|
1599
|
-
case "insert": return feishuExternalToolResult(await insertDoc(client, p.doc_token, p.content, p.after_block_id, getMediaMaxBytes(p, defaultAccountId), getImageReadTimeoutMs(p, defaultAccountId), api.logger));
|
|
1600
|
-
case "create": return feishuExternalToolResult(await createDoc(client, p.title, p.folder_token, {
|
|
1601
|
-
grantToRequester: p.grant_to_requester,
|
|
1602
|
-
requesterOpenId: trustedRequesterOpenId
|
|
1603
|
-
}));
|
|
1604
|
-
case "list_blocks": return feishuExternalToolResult(await listBlocks(client, p.doc_token));
|
|
1605
|
-
case "get_block": return feishuExternalToolResult(await getBlock(client, p.doc_token, p.block_id));
|
|
1606
|
-
case "update_block": return feishuExternalToolResult(await updateBlock(client, p.doc_token, p.block_id, p.content));
|
|
1607
|
-
case "delete_block": return feishuExternalToolResult(await deleteBlock(client, p.doc_token, p.block_id));
|
|
1608
|
-
case "create_table": return feishuExternalToolResult(await createTable(client, p.doc_token, p.row_size, p.column_size, p.parent_block_id, p.column_width));
|
|
1609
|
-
case "write_table_cells": return feishuExternalToolResult(await writeTableCells(client, p.doc_token, p.table_block_id, p.values));
|
|
1610
|
-
case "create_table_with_values": return feishuExternalToolResult(await createTableWithValues(client, p.doc_token, p.row_size, p.column_size, p.values, p.parent_block_id, p.column_width));
|
|
1611
|
-
case "upload_image": return feishuExternalToolResult(await uploadImageBlock(client, p.doc_token, getMediaMaxBytes(p, defaultAccountId), getImageReadTimeoutMs(p, defaultAccountId), mediaLocalRoots, p.url, p.file_path, p.parent_block_id, p.filename, p.index, p.image));
|
|
1612
|
-
case "upload_file": return feishuExternalToolResult(await uploadFileBlock(client, p.doc_token, getMediaMaxBytes(p, defaultAccountId), mediaLocalRoots, p.url, p.file_path, p.parent_block_id, p.filename));
|
|
1613
|
-
case "color_text": return feishuExternalToolResult(await updateColorText(client, p.doc_token, p.block_id, p.content));
|
|
1614
|
-
case "insert_table_row": return feishuExternalToolResult(await insertTableRow(client, p.doc_token, p.block_id, p.row_index));
|
|
1615
|
-
case "insert_table_column": return feishuExternalToolResult(await insertTableColumn(client, p.doc_token, p.block_id, p.column_index));
|
|
1616
|
-
case "delete_table_rows": return feishuExternalToolResult(await deleteTableRows(client, p.doc_token, p.block_id, p.row_start, p.row_count));
|
|
1617
|
-
case "delete_table_columns": return feishuExternalToolResult(await deleteTableColumns(client, p.doc_token, p.block_id, p.column_start, p.column_count));
|
|
1618
|
-
case "merge_table_cells": return feishuExternalToolResult(await mergeTableCells(client, p.doc_token, p.block_id, p.row_start, p.row_end, p.column_start, p.column_end));
|
|
1619
|
-
default: return feishuExternalToolResult({ error: "Unknown action" });
|
|
1620
|
-
}
|
|
1621
|
-
} catch (err) {
|
|
1622
|
-
return feishuExternalToolResult({ error: formatErrorMessage(err) });
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
};
|
|
1626
|
-
}, { name: "feishu_doc" });
|
|
1627
|
-
registered.push("feishu_doc");
|
|
1628
|
-
}
|
|
1629
|
-
if (toolsCfg.scopes) {
|
|
1630
|
-
api.registerTool((ctx) => ({
|
|
1631
|
-
name: "feishu_app_scopes",
|
|
1526
|
+
if (toolsCfg.doc) api.registerTool((ctx) => {
|
|
1527
|
+
const defaultAccountId = ctx.agentAccountId;
|
|
1528
|
+
const mediaLocalRoots = resolveDocToolLocalRoots(ctx);
|
|
1529
|
+
const trustedRequesterOpenId = ctx.messageChannel === "feishu" ? normalizeOptionalString(ctx.requesterSenderId) : void 0;
|
|
1530
|
+
return {
|
|
1531
|
+
name: "feishu_doc",
|
|
1632
1532
|
resultContentSource: "network",
|
|
1633
|
-
label: "Feishu
|
|
1634
|
-
description: "
|
|
1635
|
-
parameters:
|
|
1636
|
-
async execute() {
|
|
1533
|
+
label: "Feishu Doc",
|
|
1534
|
+
description: "Feishu document operations. Actions: read, write, append, insert, create, list_blocks, get_block, update_block, delete_block, create_table, write_table_cells, create_table_with_values, insert_table_row, insert_table_column, delete_table_rows, delete_table_columns, merge_table_cells, upload_image, upload_file, color_text",
|
|
1535
|
+
parameters: FeishuDocSchema,
|
|
1536
|
+
async execute(_toolCallId, params) {
|
|
1537
|
+
const p = params;
|
|
1637
1538
|
try {
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1539
|
+
if (p.action === "create" && Object.hasOwn(p, "content")) return feishuExternalToolResult({ error: "Feishu document creation does not support content. Call action \"create\" first, then call action \"write\" with the returned document_id as doc_token." });
|
|
1540
|
+
const client = getClient(p, defaultAccountId);
|
|
1541
|
+
switch (p.action) {
|
|
1542
|
+
case "read": return feishuExternalToolResult(await readDoc(client, p.doc_token));
|
|
1543
|
+
case "write": return feishuExternalToolResult(await writeDoc(client, p.doc_token, p.content, getMediaMaxBytes(p, defaultAccountId), getImageReadTimeoutMs(p, defaultAccountId), api.logger));
|
|
1544
|
+
case "append": return feishuExternalToolResult(await appendDoc(client, p.doc_token, p.content, getMediaMaxBytes(p, defaultAccountId), getImageReadTimeoutMs(p, defaultAccountId), api.logger));
|
|
1545
|
+
case "insert": return feishuExternalToolResult(await insertDoc(client, p.doc_token, p.content, p.after_block_id, getMediaMaxBytes(p, defaultAccountId), getImageReadTimeoutMs(p, defaultAccountId), api.logger));
|
|
1546
|
+
case "create": return feishuExternalToolResult(await createDoc(client, p.title, p.folder_token, {
|
|
1547
|
+
grantToRequester: p.grant_to_requester,
|
|
1548
|
+
requesterOpenId: trustedRequesterOpenId
|
|
1549
|
+
}));
|
|
1550
|
+
case "list_blocks": return feishuExternalToolResult(await listBlocks(client, p.doc_token));
|
|
1551
|
+
case "get_block": return feishuExternalToolResult(await getBlock(client, p.doc_token, p.block_id));
|
|
1552
|
+
case "update_block": return feishuExternalToolResult(await updateBlock(client, p.doc_token, p.block_id, p.content));
|
|
1553
|
+
case "delete_block": return feishuExternalToolResult(await deleteBlock(client, p.doc_token, p.block_id));
|
|
1554
|
+
case "create_table": return feishuExternalToolResult(await createTable(client, p.doc_token, p.row_size, p.column_size, p.parent_block_id, p.column_width));
|
|
1555
|
+
case "write_table_cells": return feishuExternalToolResult(await writeTableCells(client, p.doc_token, p.table_block_id, p.values));
|
|
1556
|
+
case "create_table_with_values": return feishuExternalToolResult(await createTableWithValues(client, p.doc_token, p.row_size, p.column_size, p.values, p.parent_block_id, p.column_width));
|
|
1557
|
+
case "upload_image": return feishuExternalToolResult(await uploadImageBlock(client, p.doc_token, getMediaMaxBytes(p, defaultAccountId), getImageReadTimeoutMs(p, defaultAccountId), mediaLocalRoots, p.url, p.file_path, p.parent_block_id, p.filename, p.index, p.image));
|
|
1558
|
+
case "upload_file": return feishuExternalToolResult(await uploadFileBlock(client, p.doc_token, getMediaMaxBytes(p, defaultAccountId), mediaLocalRoots, p.url, p.file_path, p.parent_block_id, p.filename));
|
|
1559
|
+
case "color_text": return feishuExternalToolResult(await updateColorText(client, p.doc_token, p.block_id, p.content));
|
|
1560
|
+
case "insert_table_row":
|
|
1561
|
+
case "insert_table_column":
|
|
1562
|
+
case "delete_table_rows":
|
|
1563
|
+
case "delete_table_columns":
|
|
1564
|
+
case "merge_table_cells": return feishuExternalToolResult(await patchTable(client, p));
|
|
1565
|
+
default: return feishuExternalToolResult({ error: "Unknown action" });
|
|
1566
|
+
}
|
|
1646
1567
|
} catch (err) {
|
|
1647
1568
|
return feishuExternalToolResult({ error: formatErrorMessage(err) });
|
|
1648
1569
|
}
|
|
1649
1570
|
}
|
|
1650
|
-
}
|
|
1651
|
-
|
|
1652
|
-
|
|
1571
|
+
};
|
|
1572
|
+
}, { name: "feishu_doc" });
|
|
1573
|
+
if (toolsCfg.scopes) api.registerTool((ctx) => ({
|
|
1574
|
+
name: "feishu_app_scopes",
|
|
1575
|
+
resultContentSource: "network",
|
|
1576
|
+
label: "Feishu App Scopes",
|
|
1577
|
+
description: "List current app permissions (scopes). Use to debug permission issues or check available capabilities.",
|
|
1578
|
+
parameters: Type.Object({}),
|
|
1579
|
+
async execute() {
|
|
1580
|
+
try {
|
|
1581
|
+
const result = await listAppScopes(createFeishuToolClient({
|
|
1582
|
+
api,
|
|
1583
|
+
defaultAccountId: ctx.agentAccountId,
|
|
1584
|
+
requiredTool: {
|
|
1585
|
+
family: "scopes",
|
|
1586
|
+
label: "App Scopes"
|
|
1587
|
+
}
|
|
1588
|
+
}));
|
|
1589
|
+
return feishuExternalToolResult(result);
|
|
1590
|
+
} catch (err) {
|
|
1591
|
+
return feishuExternalToolResult({ error: formatErrorMessage(err) });
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
}), { name: "feishu_app_scopes" });
|
|
1653
1595
|
}
|
|
1654
1596
|
//#endregion
|
|
1655
1597
|
//#region extensions/feishu/src/wiki-schema.ts
|
|
@@ -1837,9 +1779,7 @@ async function renameNode(client, spaceId, nodeToken, title) {
|
|
|
1837
1779
|
}
|
|
1838
1780
|
function registerFeishuWikiTools(api) {
|
|
1839
1781
|
if (!api.config) return;
|
|
1840
|
-
|
|
1841
|
-
if (accounts.length === 0) return;
|
|
1842
|
-
if (!resolveAnyEnabledFeishuToolsConfig(accounts).wiki) return;
|
|
1782
|
+
if (!resolveAnyEnabledFeishuToolsConfig(api.config).wiki) return;
|
|
1843
1783
|
api.registerTool((ctx) => {
|
|
1844
1784
|
const defaultAccountId = ctx.agentAccountId;
|
|
1845
1785
|
return {
|
|
@@ -1989,9 +1929,7 @@ async function removeMember(client, token, type, memberType, memberId) {
|
|
|
1989
1929
|
}
|
|
1990
1930
|
function registerFeishuPermTools(api) {
|
|
1991
1931
|
if (!api.config) return;
|
|
1992
|
-
|
|
1993
|
-
if (accounts.length === 0) return;
|
|
1994
|
-
if (!resolveAnyEnabledFeishuToolsConfig(accounts).perm) return;
|
|
1932
|
+
if (!resolveAnyEnabledFeishuToolsConfig(api.config).perm) return;
|
|
1995
1933
|
api.registerTool((ctx) => {
|
|
1996
1934
|
const defaultAccountId = ctx.agentAccountId;
|
|
1997
1935
|
return {
|
|
@@ -2339,7 +2277,7 @@ async function createApp(client, name, folderToken, logger) {
|
|
|
2339
2277
|
url: res.data?.app?.url,
|
|
2340
2278
|
cleaned_placeholder_rows: cleanedRows,
|
|
2341
2279
|
cleaned_default_fields: cleanedFields,
|
|
2342
|
-
hint: tableId ? `Table created. Use app_token="${appToken}" and table_id="${tableId}" for other bitable tools.` : "
|
|
2280
|
+
hint: tableId ? `Table created. Use app_token="${appToken}" and table_id="${tableId}" for other bitable tools.` : "Application created, but table metadata was not retrieved. Inspect the existing application using the returned app_token or URL; do not create it again."
|
|
2343
2281
|
};
|
|
2344
2282
|
}
|
|
2345
2283
|
async function createField(client, appToken, tableId, fieldName, fieldType, property) {
|
|
@@ -2383,13 +2321,15 @@ async function updateRecord(client, appToken, tableId, recordId, fields) {
|
|
|
2383
2321
|
});
|
|
2384
2322
|
return { record: res.data?.record };
|
|
2385
2323
|
}
|
|
2324
|
+
const BITABLE_APP_TOKEN_DESCRIPTION = "Bitable application token (the /base/ URL identifier, or app_token from metadata). Not the node token in a /wiki/ URL.";
|
|
2325
|
+
const BITABLE_RECORD_FIELDS_DESCRIPTION = "Field values keyed by field name. Format by type: Text='string', Number=123, SingleSelect='Option', MultiSelect=['A','B'], DateTime=timestamp_ms, User=[{id:'ou_xxx'}], URL={text:'Display',link:'https://...'}";
|
|
2386
2326
|
const GetMetaSchema = Type.Object({ url: Type.String({ description: "Bitable URL. Supports both formats: /base/XXX?table=YYY or /wiki/XXX?table=YYY" }) });
|
|
2387
2327
|
const ListFieldsSchema = Type.Object({
|
|
2388
|
-
app_token: Type.String({ description:
|
|
2328
|
+
app_token: Type.String({ description: BITABLE_APP_TOKEN_DESCRIPTION }),
|
|
2389
2329
|
table_id: Type.String({ description: "Table ID (from URL: ?table=YYY)" })
|
|
2390
2330
|
});
|
|
2391
2331
|
const ListRecordsSchema = Type.Object({
|
|
2392
|
-
app_token: Type.String({ description:
|
|
2332
|
+
app_token: Type.String({ description: BITABLE_APP_TOKEN_DESCRIPTION }),
|
|
2393
2333
|
table_id: Type.String({ description: "Table ID (from URL: ?table=YYY)" }),
|
|
2394
2334
|
page_size: optionalPositiveIntegerSchema({
|
|
2395
2335
|
description: "Number of records per page (1-500, default 100)",
|
|
@@ -2398,7 +2338,7 @@ const ListRecordsSchema = Type.Object({
|
|
|
2398
2338
|
page_token: Type.Optional(Type.String({ description: "Pagination token from previous response" }))
|
|
2399
2339
|
});
|
|
2400
2340
|
const GetRecordSchema = Type.Object({
|
|
2401
|
-
app_token: Type.String({ description:
|
|
2341
|
+
app_token: Type.String({ description: BITABLE_APP_TOKEN_DESCRIPTION }),
|
|
2402
2342
|
table_id: Type.String({ description: "Table ID (from URL: ?table=YYY)" }),
|
|
2403
2343
|
record_id: Type.String({ description: "Record ID to retrieve" })
|
|
2404
2344
|
});
|
|
@@ -2411,16 +2351,16 @@ const BitableFieldValueSchema = Type.Unsafe({ type: [
|
|
|
2411
2351
|
"null"
|
|
2412
2352
|
] });
|
|
2413
2353
|
const CreateRecordSchema = Type.Object({
|
|
2414
|
-
app_token: Type.String({ description:
|
|
2354
|
+
app_token: Type.String({ description: BITABLE_APP_TOKEN_DESCRIPTION }),
|
|
2415
2355
|
table_id: Type.String({ description: "Table ID (from URL: ?table=YYY)" }),
|
|
2416
|
-
fields: Type.Record(Type.String(), BitableFieldValueSchema, { description:
|
|
2356
|
+
fields: Type.Record(Type.String(), BitableFieldValueSchema, { description: BITABLE_RECORD_FIELDS_DESCRIPTION })
|
|
2417
2357
|
});
|
|
2418
2358
|
const CreateAppSchema = Type.Object({
|
|
2419
2359
|
name: Type.String({ description: "Name for the new Bitable application" }),
|
|
2420
2360
|
folder_token: Type.Optional(Type.String({ description: "Optional folder token to place the Bitable in a specific folder" }))
|
|
2421
2361
|
});
|
|
2422
2362
|
const CreateFieldSchema = Type.Object({
|
|
2423
|
-
app_token: Type.String({ description:
|
|
2363
|
+
app_token: Type.String({ description: BITABLE_APP_TOKEN_DESCRIPTION }),
|
|
2424
2364
|
table_id: Type.String({ description: "Table ID (from URL: ?table=YYY)" }),
|
|
2425
2365
|
field_name: Type.String({ description: "Name for the new field" }),
|
|
2426
2366
|
field_type: Type.Number({
|
|
@@ -2430,16 +2370,14 @@ const CreateFieldSchema = Type.Object({
|
|
|
2430
2370
|
property: Type.Optional(Type.Record(Type.String(), BitableFieldValueSchema, { description: "Field-specific properties (e.g., options for SingleSelect, format for Number)" }))
|
|
2431
2371
|
});
|
|
2432
2372
|
const UpdateRecordSchema = Type.Object({
|
|
2433
|
-
app_token: Type.String({ description:
|
|
2373
|
+
app_token: Type.String({ description: BITABLE_APP_TOKEN_DESCRIPTION }),
|
|
2434
2374
|
table_id: Type.String({ description: "Table ID (from URL: ?table=YYY)" }),
|
|
2435
2375
|
record_id: Type.String({ description: "Record ID to update" }),
|
|
2436
|
-
fields: Type.Record(Type.String(), BitableFieldValueSchema, { description:
|
|
2376
|
+
fields: Type.Record(Type.String(), BitableFieldValueSchema, { description: BITABLE_RECORD_FIELDS_DESCRIPTION })
|
|
2437
2377
|
});
|
|
2438
2378
|
function registerFeishuBitableTools(api) {
|
|
2439
2379
|
if (!api.config) return;
|
|
2440
|
-
|
|
2441
|
-
if (accounts.length === 0) return;
|
|
2442
|
-
if (!resolveAnyEnabledFeishuToolsConfig(accounts).bitable) return;
|
|
2380
|
+
if (!resolveAnyEnabledFeishuToolsConfig(api.config).bitable) return;
|
|
2443
2381
|
const getClient = (params, defaultAccountId) => createFeishuToolClient({
|
|
2444
2382
|
api,
|
|
2445
2383
|
executeParams: params,
|