@max1874/feishu 0.2.21 → 0.2.23
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/package.json +1 -1
- package/src/docx.ts +94 -19
package/package.json
CHANGED
package/src/docx.ts
CHANGED
|
@@ -508,6 +508,20 @@ async function grantFullAccess(client: Lark.Client, docToken: string, memberId:
|
|
|
508
508
|
return res.data;
|
|
509
509
|
}
|
|
510
510
|
|
|
511
|
+
/** Transfer document ownership to a user (open_id) */
|
|
512
|
+
async function transferOwner(client: Lark.Client, docToken: string, newOwnerOpenId: string) {
|
|
513
|
+
const res = await client.drive.permissionMember.transferOwner({
|
|
514
|
+
path: { token: docToken },
|
|
515
|
+
params: { type: "docx", need_notification: false, remove_old_owner: false },
|
|
516
|
+
data: {
|
|
517
|
+
member_type: "openid",
|
|
518
|
+
member_id: newOwnerOpenId,
|
|
519
|
+
},
|
|
520
|
+
});
|
|
521
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
522
|
+
return res.data;
|
|
523
|
+
}
|
|
524
|
+
|
|
511
525
|
async function createDoc(
|
|
512
526
|
client: Lark.Client,
|
|
513
527
|
title: string,
|
|
@@ -526,16 +540,32 @@ async function createDoc(
|
|
|
526
540
|
await setDocPermissionTenantEditable(client, docId);
|
|
527
541
|
}
|
|
528
542
|
|
|
529
|
-
// Auto-
|
|
543
|
+
// Auto-transfer ownership to the sender, and grant group access if in group chat
|
|
544
|
+
let ownerTransferredTo: string | undefined;
|
|
530
545
|
let grantedTo: string | undefined;
|
|
531
546
|
const convCtx = getConversationContext();
|
|
532
547
|
if (docId && convCtx) {
|
|
533
|
-
|
|
548
|
+
// Transfer ownership to the user who triggered this request
|
|
534
549
|
try {
|
|
535
|
-
await
|
|
536
|
-
|
|
550
|
+
await transferOwner(client, docId, convCtx.senderOpenId);
|
|
551
|
+
ownerTransferredTo = convCtx.senderOpenId;
|
|
537
552
|
} catch {
|
|
538
|
-
//
|
|
553
|
+
// Fallback: grant full_access if transfer fails
|
|
554
|
+
try {
|
|
555
|
+
await grantFullAccess(client, docId, convCtx.senderOpenId);
|
|
556
|
+
grantedTo = convCtx.senderOpenId;
|
|
557
|
+
} catch {
|
|
558
|
+
// Non-fatal: doc is created, permission grant failed
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// In group chats, also grant full_access to the chat group
|
|
563
|
+
if (convCtx.chatType === "group") {
|
|
564
|
+
try {
|
|
565
|
+
await grantFullAccess(client, docId, convCtx.chatId);
|
|
566
|
+
} catch {
|
|
567
|
+
// Non-fatal
|
|
568
|
+
}
|
|
539
569
|
}
|
|
540
570
|
}
|
|
541
571
|
|
|
@@ -544,6 +574,7 @@ async function createDoc(
|
|
|
544
574
|
title: doc?.title,
|
|
545
575
|
url: `https://feishu.cn/docx/${docId}`,
|
|
546
576
|
permission: permission ?? "private",
|
|
577
|
+
...(ownerTransferredTo && { owner_transferred_to: ownerTransferredTo }),
|
|
547
578
|
...(grantedTo && { granted_full_access_to: grantedTo }),
|
|
548
579
|
};
|
|
549
580
|
}
|
|
@@ -865,7 +896,11 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
865
896
|
{
|
|
866
897
|
name: "feishu_doc_read",
|
|
867
898
|
label: "Feishu Doc Read",
|
|
868
|
-
description:
|
|
899
|
+
description:
|
|
900
|
+
"Read plain text content and metadata from a Feishu document. " +
|
|
901
|
+
"Use this for a quick overview of document content. " +
|
|
902
|
+
"For structured content (tables, block details), use feishu_doc_list_blocks instead. " +
|
|
903
|
+
"Extract doc_token from URL: /docx/XXX or /docs/XXX.",
|
|
869
904
|
parameters: DocTokenSchema,
|
|
870
905
|
async execute(_toolCallId, params) {
|
|
871
906
|
const { doc_token } = params as { doc_token: string };
|
|
@@ -886,7 +921,10 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
886
921
|
name: "feishu_doc_create",
|
|
887
922
|
label: "Feishu Doc Create",
|
|
888
923
|
description:
|
|
889
|
-
"Create a new empty Feishu document.
|
|
924
|
+
"Create a new empty Feishu document. " +
|
|
925
|
+
"Automatically grants full_access permission to the conversation participant so they can edit. " +
|
|
926
|
+
"After creating, use feishu_doc_write to populate content. " +
|
|
927
|
+
"Set permission='tenant_editable' to allow anyone in the organization to edit via link.",
|
|
890
928
|
parameters: CreateDocSchema,
|
|
891
929
|
async execute(_toolCallId, params) {
|
|
892
930
|
const { title, folder_token, permission } = params as {
|
|
@@ -911,7 +949,10 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
911
949
|
name: "feishu_doc_write",
|
|
912
950
|
label: "Feishu Doc Write",
|
|
913
951
|
description:
|
|
914
|
-
"Write markdown content to a Feishu document
|
|
952
|
+
"Write markdown content to a Feishu document. WARNING: This REPLACES ALL existing content. " +
|
|
953
|
+
"Use for: initial document population, complete rewrites. " +
|
|
954
|
+
"For partial edits, use feishu_doc_update_block instead. " +
|
|
955
|
+
"Supports: headings, lists, code blocks, quotes, links, images, tables, bold/italic/strikethrough.",
|
|
915
956
|
parameters: WriteDocSchema,
|
|
916
957
|
async execute(_toolCallId, params) {
|
|
917
958
|
const { doc_token, content } = params as { doc_token: string; content: string };
|
|
@@ -932,7 +973,10 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
932
973
|
name: "feishu_doc_append",
|
|
933
974
|
label: "Feishu Doc Append",
|
|
934
975
|
description:
|
|
935
|
-
"Append markdown content to the
|
|
976
|
+
"Append markdown content to the END of a Feishu document without touching existing content. " +
|
|
977
|
+
"Use for: adding new sections, logging, incremental content building. " +
|
|
978
|
+
"Cannot insert in the middle - for that, use feishu_doc_update_block or delete+append. " +
|
|
979
|
+
"Supports same markdown syntax as feishu_doc_write.",
|
|
936
980
|
parameters: AppendDocSchema,
|
|
937
981
|
async execute(_toolCallId, params) {
|
|
938
982
|
const { doc_token, content } = params as { doc_token: string; content: string };
|
|
@@ -952,7 +996,11 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
952
996
|
{
|
|
953
997
|
name: "feishu_doc_update_block",
|
|
954
998
|
label: "Feishu Doc Update Block",
|
|
955
|
-
description:
|
|
999
|
+
description:
|
|
1000
|
+
"Update the text content of a specific block without affecting other parts of the document. " +
|
|
1001
|
+
"WORKFLOW: First call feishu_doc_list_blocks to find the block_id, then update it here. " +
|
|
1002
|
+
"Use for: fixing typos, updating a paragraph, modifying specific sections. " +
|
|
1003
|
+
"Only works on text-based blocks (paragraphs, headings, lists). Cannot change block type.",
|
|
956
1004
|
parameters: UpdateBlockSchema,
|
|
957
1005
|
async execute(_toolCallId, params) {
|
|
958
1006
|
const { doc_token, block_id, content } = params as {
|
|
@@ -976,7 +1024,11 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
976
1024
|
{
|
|
977
1025
|
name: "feishu_doc_delete_block",
|
|
978
1026
|
label: "Feishu Doc Delete Block",
|
|
979
|
-
description:
|
|
1027
|
+
description:
|
|
1028
|
+
"Delete a specific block from a Feishu document. " +
|
|
1029
|
+
"WORKFLOW: First call feishu_doc_list_blocks to find the block_id, then delete it here. " +
|
|
1030
|
+
"Use for: removing outdated content, clearing sections before rewriting. " +
|
|
1031
|
+
"Combine with feishu_doc_append to replace content in the middle of a document.",
|
|
980
1032
|
parameters: DeleteBlockSchema,
|
|
981
1033
|
async execute(_toolCallId, params) {
|
|
982
1034
|
const { doc_token, block_id } = params as { doc_token: string; block_id: string };
|
|
@@ -997,7 +1049,10 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
997
1049
|
name: "feishu_doc_list_blocks",
|
|
998
1050
|
label: "Feishu Doc List Blocks",
|
|
999
1051
|
description:
|
|
1000
|
-
"List all blocks in a Feishu document with
|
|
1052
|
+
"List all blocks in a Feishu document with their block_id and full content. " +
|
|
1053
|
+
"ESSENTIAL for editing: returns block_id needed by update_block/delete_block/get_block. " +
|
|
1054
|
+
"Better than feishu_doc_read for: seeing document structure, reading tables, finding specific sections. " +
|
|
1055
|
+
"Block types include: text, headings (1-9), bullet/ordered lists, code, quote, table, image, divider.",
|
|
1001
1056
|
parameters: DocTokenSchema,
|
|
1002
1057
|
async execute(_toolCallId, params) {
|
|
1003
1058
|
const { doc_token } = params as { doc_token: string };
|
|
@@ -1017,7 +1072,10 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
1017
1072
|
{
|
|
1018
1073
|
name: "feishu_doc_get_block",
|
|
1019
1074
|
label: "Feishu Doc Get Block",
|
|
1020
|
-
description:
|
|
1075
|
+
description:
|
|
1076
|
+
"Get detailed content of a specific block by its block_id. " +
|
|
1077
|
+
"Use when feishu_doc_list_blocks output is truncated or you need fresh data for one block. " +
|
|
1078
|
+
"Returns full block structure including nested content (e.g., table cells).",
|
|
1021
1079
|
parameters: GetBlockSchema,
|
|
1022
1080
|
async execute(_toolCallId, params) {
|
|
1023
1081
|
const { doc_token, block_id } = params as { doc_token: string; block_id: string };
|
|
@@ -1037,7 +1095,11 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
1037
1095
|
{
|
|
1038
1096
|
name: "feishu_folder_list",
|
|
1039
1097
|
label: "Feishu Folder List",
|
|
1040
|
-
description:
|
|
1098
|
+
description:
|
|
1099
|
+
"List documents and subfolders in a Feishu Drive folder. " +
|
|
1100
|
+
"Extract folder_token from URL: /drive/folder/XXX. " +
|
|
1101
|
+
"Use to browse available documents or find a doc_token to read/edit. " +
|
|
1102
|
+
"Returns: file name, type (docx/sheet/folder/etc), token, URL, last modified time.",
|
|
1041
1103
|
parameters: FolderTokenSchema,
|
|
1042
1104
|
async execute(_toolCallId, params) {
|
|
1043
1105
|
const { folder_token } = params as { folder_token: string };
|
|
@@ -1058,7 +1120,9 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
1058
1120
|
name: "feishu_doc_set_permission",
|
|
1059
1121
|
label: "Feishu Doc Set Permission",
|
|
1060
1122
|
description:
|
|
1061
|
-
"
|
|
1123
|
+
"Change document sharing permissions after creation. " +
|
|
1124
|
+
"Options: 'tenant_editable' = anyone in organization can edit via link; 'private' = only owner/explicitly granted users. " +
|
|
1125
|
+
"Note: feishu_doc_create already grants full_access to the conversation participant.",
|
|
1062
1126
|
parameters: SetPermissionSchema,
|
|
1063
1127
|
async execute(_toolCallId, params) {
|
|
1064
1128
|
const { doc_token, permission } = params as { doc_token: string; permission: DocPermission };
|
|
@@ -1094,7 +1158,10 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
1094
1158
|
name: "feishu_wiki_read",
|
|
1095
1159
|
label: "Feishu Wiki Read",
|
|
1096
1160
|
description:
|
|
1097
|
-
"Read content from a Feishu
|
|
1161
|
+
"Read content from a Feishu Wiki (knowledge base) page. " +
|
|
1162
|
+
"Extract wiki_token from URL: /wiki/XXX. " +
|
|
1163
|
+
"Different from feishu_doc_read - wikis have their own token format and metadata. " +
|
|
1164
|
+
"Returns wiki node info and document content if the underlying type is docx.",
|
|
1098
1165
|
parameters: WikiTokenSchema,
|
|
1099
1166
|
async execute(_toolCallId, params) {
|
|
1100
1167
|
const { wiki_token } = params as { wiki_token: string };
|
|
@@ -1114,7 +1181,10 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
1114
1181
|
{
|
|
1115
1182
|
name: "feishu_wiki_spaces",
|
|
1116
1183
|
label: "Feishu Wiki Spaces",
|
|
1117
|
-
description:
|
|
1184
|
+
description:
|
|
1185
|
+
"List all Wiki spaces (knowledge bases) the app has access to. " +
|
|
1186
|
+
"Returns space_id needed for feishu_wiki_nodes. " +
|
|
1187
|
+
"Use this first when browsing wikis to find the right knowledge base.",
|
|
1118
1188
|
parameters: Type.Object({}),
|
|
1119
1189
|
async execute() {
|
|
1120
1190
|
try {
|
|
@@ -1134,7 +1204,10 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
1134
1204
|
name: "feishu_wiki_nodes",
|
|
1135
1205
|
label: "Feishu Wiki Nodes",
|
|
1136
1206
|
description:
|
|
1137
|
-
"List wiki
|
|
1207
|
+
"List wiki pages within a Wiki space. " +
|
|
1208
|
+
"WORKFLOW: First call feishu_wiki_spaces to get space_id, then list nodes here. " +
|
|
1209
|
+
"Use parent_node_token to browse nested pages (children of a specific node). " +
|
|
1210
|
+
"Returns node_token for use with feishu_wiki_read.",
|
|
1138
1211
|
parameters: WikiSpaceIdSchema,
|
|
1139
1212
|
async execute(_toolCallId, params) {
|
|
1140
1213
|
const { space_id, parent_node_token } = params as {
|
|
@@ -1158,7 +1231,9 @@ export function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
|
1158
1231
|
name: "feishu_app_scopes",
|
|
1159
1232
|
label: "Feishu App Scopes",
|
|
1160
1233
|
description:
|
|
1161
|
-
"List
|
|
1234
|
+
"List the app's current permissions (scopes) granted in Feishu admin console. " +
|
|
1235
|
+
"Use when a tool fails with permission errors to diagnose what's missing. " +
|
|
1236
|
+
"Common required scopes: docx:document (read/edit docs), wiki:wiki (read wikis), drive:drive (folder access).",
|
|
1162
1237
|
parameters: Type.Object({}),
|
|
1163
1238
|
async execute() {
|
|
1164
1239
|
try {
|