@openclaw/feishu 2026.8.2 → 2026.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.js CHANGED
@@ -1,11 +1,11 @@
1
- import { a as setFeishuNamedAccountEnabled, i as feishuSetupAdapter, n as feishuSetupWizard, r as runFeishuLogin, t as feishuPlugin } from "./channel-BtM7n79m.js";
2
- import { B as resolveFeishuToolAccount, F as feishuExternalToolResult, I as toolExecutionErrorResult, L as unknownToolActionResult, P as registerFeishuDriveTools, R as createFeishuToolClient, et as chunkFeishuMarkdown, rt as parseFeishuMarkdown, z as resolveAnyEnabledFeishuToolsConfig } from "./reply-delivery-result-BIIeISPG.js";
1
+ import { a as setFeishuNamedAccountEnabled, i as feishuSetupAdapter, n as feishuSetupWizard, r as runFeishuLogin, t as feishuPlugin } from "./channel-DSYCNah8.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-CEFTDA3f.js";
3
3
  import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, n as buildFeishuModelOverrideParentCandidates, r as parseFeishuConversationId, t as buildFeishuConversationId } from "./conversation-id-VYgGQ-GX.js";
4
- import { s as resolveConfiguredHttpTimeoutMs } from "./client-vJJyfkxI.js";
4
+ import { s as resolveConfiguredHttpTimeoutMs } from "./client-DMbIL3UH.js";
5
5
  import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
6
- import { o as registerFeishuChatTools } from "./chat-Cbr7P_JH.js";
6
+ import { o as registerFeishuChatTools } from "./chat-CxXaPTuO.js";
7
7
  import { n as getFeishuThreadBindingManager, t as createFeishuThreadBindingManager } from "./thread-bindings-BiL1wGqK.js";
8
- import { n as handleFeishuSubagentEnded, t as handleFeishuSubagentDeliveryTarget } from "./subagent-hooks-BnO3ALWB.js";
8
+ import { n as handleFeishuSubagentEnded, t as handleFeishuSubagentDeliveryTarget } from "./subagent-hooks-Buadpie_.js";
9
9
  import { optionalPositiveIntegerSchema } from "openclaw/plugin-sdk/channel-actions";
10
10
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
11
11
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, readStringValue, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -166,23 +166,6 @@ const FeishuDocSchema = Type.Union([
166
166
  const MIN_COLUMN_WIDTH = 50;
167
167
  const MAX_COLUMN_WIDTH = 400;
168
168
  const DEFAULT_TABLE_WIDTH = 730;
169
- /**
170
- * Calculate adaptive column widths based on cell content length.
171
- *
172
- * Algorithm:
173
- * 1. For each column, find the max content length across all rows
174
- * 2. Weight CJK characters as 2x width (they render wider)
175
- * 3. Calculate proportional widths based on content length
176
- * 4. Apply min/max constraints
177
- * 5. Redistribute remaining space to fill total table width
178
- *
179
- * Total width is derived from the original column_width values returned
180
- * by the Convert API, ensuring tables match Feishu's expected dimensions.
181
- *
182
- * @param blocks - Array of blocks from Convert API
183
- * @param tableBlockId - The block_id of the table block
184
- * @returns Array of column widths in pixels
185
- */
186
169
  function normalizeChildBlockIds(children) {
187
170
  if (Array.isArray(children)) return children;
188
171
  return typeof children === "string" ? [children] : [];
@@ -287,86 +270,61 @@ function cleanBlocksForDescendant(blocks) {
287
270
  return cleanBlock;
288
271
  });
289
272
  }
290
- async function insertTableRow(client, docToken, blockId, rowIndex = -1) {
291
- const res = await client.docx.documentBlock.patch({
292
- path: {
293
- document_id: docToken,
294
- block_id: blockId
295
- },
296
- data: { insert_table_row: { row_index: rowIndex } }
297
- });
298
- if (res.code !== 0) throw new Error(res.msg);
299
- return {
300
- success: true,
301
- block: res.data?.block
302
- };
303
- }
304
- async function insertTableColumn(client, docToken, blockId, columnIndex = -1) {
305
- const res = await client.docx.documentBlock.patch({
306
- path: {
307
- document_id: docToken,
308
- block_id: blockId
309
- },
310
- data: { insert_table_column: { column_index: columnIndex } }
311
- });
312
- if (res.code !== 0) throw new Error(res.msg);
313
- return {
314
- success: true,
315
- block: res.data?.block
316
- };
317
- }
318
- async function deleteTableRows(client, docToken, blockId, rowStart, rowCount = 1) {
319
- const res = await client.docx.documentBlock.patch({
320
- path: {
321
- document_id: docToken,
322
- block_id: blockId
323
- },
324
- data: { delete_table_rows: {
325
- row_start_index: rowStart,
326
- row_end_index: rowStart + rowCount
327
- } }
328
- });
329
- if (res.code !== 0) throw new Error(res.msg);
330
- return {
331
- success: true,
332
- rows_deleted: rowCount,
333
- block: res.data?.block
334
- };
335
- }
336
- async function deleteTableColumns(client, docToken, blockId, columnStart, columnCount = 1) {
337
- const res = await client.docx.documentBlock.patch({
338
- path: {
339
- document_id: docToken,
340
- block_id: blockId
341
- },
342
- data: { delete_table_columns: {
343
- column_start_index: columnStart,
344
- column_end_index: columnStart + columnCount
345
- } }
346
- });
347
- if (res.code !== 0) throw new Error(res.msg);
348
- return {
349
- success: true,
350
- columns_deleted: columnCount,
351
- block: res.data?.block
352
- };
353
- }
354
- 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
+ }
355
317
  const res = await client.docx.documentBlock.patch({
356
318
  path: {
357
- document_id: docToken,
358
- block_id: blockId
319
+ document_id: doc_token,
320
+ block_id
359
321
  },
360
- data: { merge_table_cells: {
361
- row_start_index: rowStart,
362
- row_end_index: rowEnd,
363
- column_start_index: columnStart,
364
- column_end_index: columnEnd
365
- } }
322
+ data
366
323
  });
367
324
  if (res.code !== 0) throw new Error(res.msg);
368
325
  return {
369
326
  success: true,
327
+ ...counts,
370
328
  block: res.data?.block
371
329
  };
372
330
  }
@@ -852,12 +810,15 @@ function cleanBlocksForInsert(blocks) {
852
810
  }
853
811
  /** Max blocks per documentBlockChildren.create request */
854
812
  const MAX_CONVERT_RETRY_DEPTH = 8;
813
+ function assertFeishuDocApiSuccess(response) {
814
+ if (response.code !== 0) throw new Error(response.msg);
815
+ }
855
816
  async function convertMarkdown(client, markdown) {
856
817
  const res = await client.docx.document.convert({ data: {
857
818
  content_type: "markdown",
858
819
  content: markdown
859
820
  } });
860
- if (res.code !== 0) throw new Error(res.msg);
821
+ assertFeishuDocApiSuccess(res);
861
822
  return {
862
823
  blocks: res.data?.blocks ?? [],
863
824
  firstLevelBlockIds: res.data?.first_level_block_ids ?? []
@@ -941,7 +902,7 @@ async function insertBlocks(client, docToken, blocks, parentBlockId, index) {
941
902
  ...index !== void 0 ? { index: index + offset } : {}
942
903
  }
943
904
  });
944
- if (res.code !== 0) throw new Error(res.msg);
905
+ assertFeishuDocApiSuccess(res);
945
906
  allInserted.push(...res.data?.children ?? []);
946
907
  }
947
908
  return {
@@ -1020,21 +981,18 @@ async function insertBlocksWithDescendant(client, docToken, blocks, firstLevelBl
1020
981
  }
1021
982
  async function clearDocumentContent(client, docToken) {
1022
983
  const existing = await client.docx.documentBlock.list({ path: { document_id: docToken } });
1023
- if (existing.code !== 0) throw new Error(existing.msg);
984
+ assertFeishuDocApiSuccess(existing);
1024
985
  const childIds = existing.data?.items?.filter((b) => b.parent_id === docToken && b.block_type !== 1).map((b) => b.block_id) ?? [];
1025
- if (childIds.length > 0) {
1026
- const res = await client.docx.documentBlockChildren.batchDelete({
1027
- path: {
1028
- document_id: docToken,
1029
- block_id: docToken
1030
- },
1031
- data: {
1032
- start_index: 0,
1033
- end_index: childIds.length
1034
- }
1035
- });
1036
- if (res.code !== 0) throw new Error(res.msg);
1037
- }
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
+ }));
1038
996
  return childIds.length;
1039
997
  }
1040
998
  async function uploadImageToDocx(client, blockId, imageBuffer, fileName, docToken) {
@@ -1064,13 +1022,13 @@ async function processImages(client, docToken, images, insertedBlocks, maxBytes,
1064
1022
  remoteReadTimeoutMs: imageReadTimeoutMs
1065
1023
  });
1066
1024
  const fileToken = await uploadImageToDocx(client, blockId, upload.buffer, upload.fileName, docToken);
1067
- await client.docx.documentBlock.patch({
1025
+ assertFeishuDocApiSuccess(await client.docx.documentBlock.patch({
1068
1026
  path: {
1069
1027
  document_id: docToken,
1070
1028
  block_id: blockId
1071
1029
  },
1072
1030
  data: { replace_image: { token: fileToken } }
1073
- });
1031
+ }));
1074
1032
  processed++;
1075
1033
  } catch (err) {
1076
1034
  console.error(`Failed to process image ${url}:`, err);
@@ -1127,14 +1085,13 @@ async function uploadImageBlock(client, docToken, maxBytes, imageReadTimeoutMs,
1127
1085
  const imageBlockId = insertRes.data?.children?.find((b) => b.block_type === 27)?.block_id;
1128
1086
  if (!imageBlockId) throw new Error("Failed to create image block");
1129
1087
  const fileToken = await uploadImageToDocx(client, imageBlockId, upload.buffer, upload.fileName, docToken);
1130
- const patchRes = await client.docx.documentBlock.patch({
1088
+ assertFeishuDocApiSuccess(await client.docx.documentBlock.patch({
1131
1089
  path: {
1132
1090
  document_id: docToken,
1133
1091
  block_id: imageBlockId
1134
1092
  },
1135
1093
  data: { replace_image: { token: fileToken } }
1136
- });
1137
- if (patchRes.code !== 0) throw new Error(patchRes.msg);
1094
+ }));
1138
1095
  return {
1139
1096
  success: true,
1140
1097
  block_id: imageBlockId,
@@ -1162,21 +1119,18 @@ async function uploadFileBlock(client, docToken, maxBytes, localRoots, url, file
1162
1119
  document_id: docToken,
1163
1120
  block_id: parentId
1164
1121
  } });
1165
- if (childrenRes.code !== 0) throw new Error(childrenRes.msg);
1122
+ assertFeishuDocApiSuccess(childrenRes);
1166
1123
  const placeholderIdx = (childrenRes.data?.items ?? []).findIndex((item) => item.block_id === placeholderBlock.block_id);
1167
- if (placeholderIdx >= 0) {
1168
- const deleteRes = await client.docx.documentBlockChildren.batchDelete({
1169
- path: {
1170
- document_id: docToken,
1171
- block_id: parentId
1172
- },
1173
- data: {
1174
- start_index: placeholderIdx,
1175
- end_index: placeholderIdx + 1
1176
- }
1177
- });
1178
- if (deleteRes.code !== 0) throw new Error(deleteRes.msg);
1179
- }
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
+ }));
1180
1134
  const fileToken = (await client.drive.media.uploadAll({ data: {
1181
1135
  file_name: upload.fileName,
1182
1136
  parent_type: "docx_file",
@@ -1209,7 +1163,7 @@ async function readDoc(client, docToken) {
1209
1163
  client.docx.document.get({ path: { document_id: docToken } }),
1210
1164
  client.docx.documentBlock.list({ path: { document_id: docToken } })
1211
1165
  ]);
1212
- if (contentRes.code !== 0) throw new Error(contentRes.msg);
1166
+ assertFeishuDocApiSuccess(contentRes);
1213
1167
  const blocks = blocksRes.data?.items ?? [];
1214
1168
  const blockCounts = {};
1215
1169
  const structuredTypes = [];
@@ -1235,7 +1189,7 @@ async function createDoc(client, title, folderToken, options) {
1235
1189
  title,
1236
1190
  folder_token: folderToken
1237
1191
  } });
1238
- if (res.code !== 0) throw new Error(res.msg);
1192
+ assertFeishuDocApiSuccess(res);
1239
1193
  const doc = res.data?.document;
1240
1194
  const docToken = doc?.document_id;
1241
1195
  if (!docToken) throw new Error("Document creation succeeded but no document_id was returned");
@@ -1248,7 +1202,7 @@ async function createDoc(client, title, folderToken, options) {
1248
1202
  if (shouldGrantToRequester) {
1249
1203
  if (!requesterOpenId) requesterPermissionSkippedReason = "trusted requester identity unavailable";
1250
1204
  else try {
1251
- await client.drive.permissionMember.create({
1205
+ assertFeishuDocApiSuccess(await client.drive.permissionMember.create({
1252
1206
  path: { token: docToken },
1253
1207
  params: {
1254
1208
  type: "docx",
@@ -1259,7 +1213,7 @@ async function createDoc(client, title, folderToken, options) {
1259
1213
  member_id: requesterOpenId,
1260
1214
  perm: requesterPermType
1261
1215
  }
1262
- });
1216
+ }));
1263
1217
  requesterPermissionAdded = true;
1264
1218
  } catch (err) {
1265
1219
  requesterPermissionError = formatErrorMessage(err);
@@ -1322,7 +1276,7 @@ async function insertDoc(client, docToken, markdown, afterBlockId, maxBytes, ima
1322
1276
  document_id: docToken,
1323
1277
  block_id: afterBlockId
1324
1278
  } });
1325
- if (blockInfo.code !== 0) throw new Error(blockInfo.msg);
1279
+ assertFeishuDocApiSuccess(blockInfo);
1326
1280
  const parentId = blockInfo.data?.block?.parent_id ?? docToken;
1327
1281
  const items = [];
1328
1282
  let pageToken;
@@ -1335,7 +1289,7 @@ async function insertDoc(client, docToken, markdown, afterBlockId, maxBytes, ima
1335
1289
  },
1336
1290
  params: pageToken ? { page_token: pageToken } : {}
1337
1291
  });
1338
- if (childrenRes.code !== 0) throw new Error(childrenRes.msg);
1292
+ assertFeishuDocApiSuccess(childrenRes);
1339
1293
  items.push(...childrenRes.data?.items ?? []);
1340
1294
  if (childrenRes.data?.has_more !== true) break;
1341
1295
  const nextPageToken = childrenRes.data.page_token?.trim();
@@ -1385,7 +1339,7 @@ async function createTable(client, docToken, rowSize, columnSize, parentBlockId,
1385
1339
  } }
1386
1340
  }] }
1387
1341
  });
1388
- if (res.code !== 0) throw new Error(res.msg);
1342
+ assertFeishuDocApiSuccess(res);
1389
1343
  const tableBlock = res.data?.children?.find((b) => b.block_type === 31);
1390
1344
  const cells = normalizeInsertedChildBlocks(tableBlock?.children);
1391
1345
  return {
@@ -1403,7 +1357,7 @@ async function writeTableCells(client, docToken, tableBlockId, values) {
1403
1357
  document_id: docToken,
1404
1358
  block_id: tableBlockId
1405
1359
  } });
1406
- if (tableRes.code !== 0) throw new Error(tableRes.msg);
1360
+ assertFeishuDocApiSuccess(tableRes);
1407
1361
  const tableBlock = tableRes.data?.block;
1408
1362
  if (tableBlock?.block_type !== 31) throw new Error("table_block_id is not a table block");
1409
1363
  const tableData = tableBlock.table;
@@ -1423,21 +1377,18 @@ async function writeTableCells(client, docToken, tableBlockId, values) {
1423
1377
  document_id: docToken,
1424
1378
  block_id: cellId
1425
1379
  } });
1426
- if (childrenRes.code !== 0) throw new Error(childrenRes.msg);
1380
+ assertFeishuDocApiSuccess(childrenRes);
1427
1381
  const existingChildren = childrenRes.data?.items ?? [];
1428
- if (existingChildren.length > 0) {
1429
- const delRes = await client.docx.documentBlockChildren.batchDelete({
1430
- path: {
1431
- document_id: docToken,
1432
- block_id: cellId
1433
- },
1434
- data: {
1435
- start_index: 0,
1436
- end_index: existingChildren.length
1437
- }
1438
- });
1439
- if (delRes.code !== 0) throw new Error(delRes.msg);
1440
- }
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
+ }));
1441
1392
  const converted = await convertMarkdown(client, rowValues[c] ?? "");
1442
1393
  const { orderedBlocks } = normalizeConvertedBlockTree(converted.blocks, converted.firstLevelBlockIds);
1443
1394
  if (orderedBlocks.length > 0) await insertBlocks(client, docToken, orderedBlocks, cellId);
@@ -1466,19 +1417,17 @@ async function createTableWithValues(client, docToken, rowSize, columnSize, valu
1466
1417
  };
1467
1418
  }
1468
1419
  async function updateBlock(client, docToken, blockId, content) {
1469
- const blockInfo = await client.docx.documentBlock.get({ path: {
1420
+ assertFeishuDocApiSuccess(await client.docx.documentBlock.get({ path: {
1470
1421
  document_id: docToken,
1471
1422
  block_id: blockId
1472
- } });
1473
- if (blockInfo.code !== 0) throw new Error(blockInfo.msg);
1474
- const res = await client.docx.documentBlock.patch({
1423
+ } }));
1424
+ assertFeishuDocApiSuccess(await client.docx.documentBlock.patch({
1475
1425
  path: {
1476
1426
  document_id: docToken,
1477
1427
  block_id: blockId
1478
1428
  },
1479
1429
  data: { update_text_elements: { elements: [{ text_run: { content } }] } }
1480
- });
1481
- if (res.code !== 0) throw new Error(res.msg);
1430
+ }));
1482
1431
  return {
1483
1432
  success: true,
1484
1433
  block_id: blockId
@@ -1489,16 +1438,16 @@ async function deleteBlock(client, docToken, blockId) {
1489
1438
  document_id: docToken,
1490
1439
  block_id: blockId
1491
1440
  } });
1492
- if (blockInfo.code !== 0) throw new Error(blockInfo.msg);
1441
+ assertFeishuDocApiSuccess(blockInfo);
1493
1442
  const parentId = blockInfo.data?.block?.parent_id ?? docToken;
1494
1443
  const children = await client.docx.documentBlockChildren.get({ path: {
1495
1444
  document_id: docToken,
1496
1445
  block_id: parentId
1497
1446
  } });
1498
- if (children.code !== 0) throw new Error(children.msg);
1447
+ assertFeishuDocApiSuccess(children);
1499
1448
  const index = (children.data?.items ?? []).findIndex((item) => item.block_id === blockId);
1500
1449
  if (index === -1) throw new Error("Block not found");
1501
- const res = await client.docx.documentBlockChildren.batchDelete({
1450
+ assertFeishuDocApiSuccess(await client.docx.documentBlockChildren.batchDelete({
1502
1451
  path: {
1503
1452
  document_id: docToken,
1504
1453
  block_id: parentId
@@ -1507,8 +1456,7 @@ async function deleteBlock(client, docToken, blockId) {
1507
1456
  start_index: index,
1508
1457
  end_index: index + 1
1509
1458
  }
1510
- });
1511
- if (res.code !== 0) throw new Error(res.msg);
1459
+ }));
1512
1460
  return {
1513
1461
  success: true,
1514
1462
  deleted_block_id: blockId
@@ -1516,7 +1464,7 @@ async function deleteBlock(client, docToken, blockId) {
1516
1464
  }
1517
1465
  async function listBlocks(client, docToken) {
1518
1466
  const res = await client.docx.documentBlock.list({ path: { document_id: docToken } });
1519
- if (res.code !== 0) throw new Error(res.msg);
1467
+ assertFeishuDocApiSuccess(res);
1520
1468
  return { blocks: res.data?.items ?? [] };
1521
1469
  }
1522
1470
  async function getBlock(client, docToken, blockId) {
@@ -1524,12 +1472,12 @@ async function getBlock(client, docToken, blockId) {
1524
1472
  document_id: docToken,
1525
1473
  block_id: blockId
1526
1474
  } });
1527
- if (res.code !== 0) throw new Error(res.msg);
1475
+ assertFeishuDocApiSuccess(res);
1528
1476
  return { block: res.data?.block };
1529
1477
  }
1530
1478
  async function listAppScopes(client) {
1531
1479
  const res = await client.application.scope.list({});
1532
- if (res.code !== 0) throw new Error(res.msg);
1480
+ assertFeishuDocApiSuccess(res);
1533
1481
  const scopes = res.data?.scopes ?? [];
1534
1482
  const granted = scopes.filter((s) => s.grant_status === 1);
1535
1483
  const pending = scopes.filter((s) => s.grant_status !== 1);
@@ -1609,11 +1557,11 @@ function registerFeishuDocTools(api) {
1609
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));
1610
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));
1611
1559
  case "color_text": return feishuExternalToolResult(await updateColorText(client, p.doc_token, p.block_id, p.content));
1612
- case "insert_table_row": return feishuExternalToolResult(await insertTableRow(client, p.doc_token, p.block_id, p.row_index));
1613
- case "insert_table_column": return feishuExternalToolResult(await insertTableColumn(client, p.doc_token, p.block_id, p.column_index));
1614
- case "delete_table_rows": return feishuExternalToolResult(await deleteTableRows(client, p.doc_token, p.block_id, p.row_start, p.row_count));
1615
- case "delete_table_columns": return feishuExternalToolResult(await deleteTableColumns(client, p.doc_token, p.block_id, p.column_start, p.column_count));
1616
- 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));
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));
1617
1565
  default: return feishuExternalToolResult({ error: "Unknown action" });
1618
1566
  }
1619
1567
  } catch (err) {