@yanhaidao/wecom 2.3.14 → 2.3.141
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
CHANGED
package/src/agent/handler.ts
CHANGED
|
@@ -708,7 +708,7 @@ const ctxPayload = core.channel.reply.finalizeInboundContext({
|
|
|
708
708
|
ctx: ctxPayload,
|
|
709
709
|
cfg: config,
|
|
710
710
|
replyOptions: {
|
|
711
|
-
disableBlockStreaming:
|
|
711
|
+
disableBlockStreaming: false,
|
|
712
712
|
},
|
|
713
713
|
dispatcherOptions: {
|
|
714
714
|
deliver: async (payload: { text?: string }, info: { kind: string }) => {
|
|
@@ -735,9 +735,9 @@ const ctxPayload = core.channel.reply.finalizeInboundContext({
|
|
|
735
735
|
touchTransportSession?.({ lastOutboundAt: Date.now(), running: true });
|
|
736
736
|
log?.(`[wecom-agent] reply chunk delivered (${info.kind}) to ${fromUser}, len=${chunk.length}`);
|
|
737
737
|
|
|
738
|
-
//
|
|
738
|
+
// 强制延时:确保企业微信有足够时间处理顺序(优化:200ms → 50ms)
|
|
739
739
|
if (i + MAX_CHUNK_SIZE < text.length) {
|
|
740
|
-
await new Promise(resolve => setTimeout(resolve,
|
|
740
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
741
741
|
}
|
|
742
742
|
} catch (err: unknown) {
|
|
743
743
|
const message = err instanceof Error ? `${err.message}${err.cause ? ` (cause: ${String(err.cause)})` : ""}` : String(err);
|
|
@@ -756,9 +756,9 @@ const ctxPayload = core.channel.reply.finalizeInboundContext({
|
|
|
756
756
|
}
|
|
757
757
|
}
|
|
758
758
|
|
|
759
|
-
// 不同 Block
|
|
759
|
+
// 不同 Block 之间也增加一点间隔(优化:200ms → 50ms)
|
|
760
760
|
if (info.kind !== "final") {
|
|
761
|
-
await new Promise(resolve => setTimeout(resolve,
|
|
761
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
762
762
|
}
|
|
763
763
|
};
|
|
764
764
|
|
|
@@ -631,16 +631,108 @@ export class WecomDocClient {
|
|
|
631
631
|
return json;
|
|
632
632
|
}
|
|
633
633
|
|
|
634
|
-
async editSheetData(params: {
|
|
635
|
-
|
|
636
|
-
|
|
634
|
+
async editSheetData(params: {
|
|
635
|
+
agent: ResolvedAgentAccount;
|
|
636
|
+
docId: string;
|
|
637
|
+
sheetId: string;
|
|
638
|
+
startRow?: number;
|
|
639
|
+
startColumn?: number;
|
|
640
|
+
gridData?: any;
|
|
641
|
+
}) {
|
|
642
|
+
const { agent, docId, sheetId, startRow = 0, startColumn = 0, gridData } = params;
|
|
643
|
+
|
|
644
|
+
// Validate required docId
|
|
645
|
+
const normalizedDocId = readString(docId);
|
|
646
|
+
if (!normalizedDocId) {
|
|
647
|
+
throw new Error('docId is required');
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// Validate required sheetId
|
|
651
|
+
const normalizedSheetId = readString(sheetId);
|
|
652
|
+
if (!normalizedSheetId) {
|
|
653
|
+
throw new Error('sheetId is required');
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// Build GridData per official API
|
|
657
|
+
// gridData.rows[i].values[j] must be: {cell_value: {text} | {link: {text, url}}, cell_format?: {...}}
|
|
658
|
+
const finalGridData = {
|
|
659
|
+
start_row: startRow,
|
|
660
|
+
start_column: startColumn,
|
|
661
|
+
rows: (gridData?.rows || []).map((row: any) => ({
|
|
662
|
+
values: (row.values || []).map((cell: any) => {
|
|
663
|
+
// If already CellData format, use as-is
|
|
664
|
+
if (cell && typeof cell === 'object' && cell.cell_value) {
|
|
665
|
+
return cell;
|
|
666
|
+
}
|
|
667
|
+
// Otherwise wrap primitive as CellValue
|
|
668
|
+
return { cell_value: { text: String(cell ?? '') } };
|
|
669
|
+
})
|
|
670
|
+
}))
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
// Build batch_update request per official API
|
|
674
|
+
const body = {
|
|
675
|
+
docid: normalizedDocId,
|
|
676
|
+
requests: [{
|
|
677
|
+
update_range_request: {
|
|
678
|
+
sheet_id: normalizedSheetId,
|
|
679
|
+
grid_data: finalGridData
|
|
680
|
+
}
|
|
681
|
+
}]
|
|
682
|
+
};
|
|
683
|
+
|
|
637
684
|
const json = await this.postWecomDocApi({
|
|
638
|
-
path: "/cgi-bin/wedoc/spreadsheet/
|
|
639
|
-
actionLabel: "
|
|
685
|
+
path: "/cgi-bin/wedoc/spreadsheet/batch_update",
|
|
686
|
+
actionLabel: "spreadsheet_batch_update",
|
|
640
687
|
agent, body,
|
|
641
688
|
});
|
|
642
689
|
return { raw: json, docId: body.docid as string };
|
|
643
690
|
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Build CellFormat object per official API
|
|
694
|
+
*/
|
|
695
|
+
private buildCellFormat(formatData: any): any {
|
|
696
|
+
const textFormat: any = {};
|
|
697
|
+
|
|
698
|
+
// Font properties
|
|
699
|
+
if (formatData.font != null) {
|
|
700
|
+
textFormat.font = String(formatData.font);
|
|
701
|
+
}
|
|
702
|
+
if (formatData.font_size != null) {
|
|
703
|
+
textFormat.font_size = Math.min(72, Math.max(1, Number(formatData.font_size)));
|
|
704
|
+
}
|
|
705
|
+
if (formatData.bold != null) {
|
|
706
|
+
textFormat.bold = Boolean(formatData.bold);
|
|
707
|
+
}
|
|
708
|
+
if (formatData.italic != null) {
|
|
709
|
+
textFormat.italic = Boolean(formatData.italic);
|
|
710
|
+
}
|
|
711
|
+
if (formatData.strikethrough != null) {
|
|
712
|
+
textFormat.strikethrough = Boolean(formatData.strikethrough);
|
|
713
|
+
}
|
|
714
|
+
if (formatData.underline != null) {
|
|
715
|
+
textFormat.underline = Boolean(formatData.underline);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Color (RGBA)
|
|
719
|
+
if (formatData.color != null && typeof formatData.color === "object") {
|
|
720
|
+
const color = formatData.color;
|
|
721
|
+
textFormat.color = {
|
|
722
|
+
red: Math.min(255, Math.max(0, Number(color.red ?? 0))),
|
|
723
|
+
green: Math.min(255, Math.max(0, Number(color.green ?? 0))),
|
|
724
|
+
blue: Math.min(255, Math.max(0, Number(color.blue ?? 0))),
|
|
725
|
+
alpha: Math.min(255, Math.max(0, Number(color.alpha ?? 255)))
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// Return empty object if no format properties
|
|
730
|
+
if (Object.keys(textFormat).length === 0) {
|
|
731
|
+
return null;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
return { text_format: textFormat };
|
|
735
|
+
}
|
|
644
736
|
|
|
645
737
|
async getSheetData(params: { agent: ResolvedAgentAccount; docId: string; sheetId: string; range: string }) {
|
|
646
738
|
const { agent, docId, sheetId, range } = params;
|
|
@@ -877,7 +877,7 @@ export const wecomDocToolSchema = {
|
|
|
877
877
|
{
|
|
878
878
|
type: "object",
|
|
879
879
|
additionalProperties: false,
|
|
880
|
-
required: ["action", "docId", "
|
|
880
|
+
required: ["action", "docId", "sheetId", "gridData"],
|
|
881
881
|
properties: {
|
|
882
882
|
action: { const: "edit_sheet_data" },
|
|
883
883
|
accountId: accountIdProperty,
|
|
@@ -885,24 +885,146 @@ export const wecomDocToolSchema = {
|
|
|
885
885
|
...docIdProperty,
|
|
886
886
|
description: "在线表格 docid",
|
|
887
887
|
},
|
|
888
|
-
|
|
888
|
+
sheetId: {
|
|
889
|
+
type: "string",
|
|
890
|
+
minLength: 1,
|
|
891
|
+
description: "工作表 sheet_id",
|
|
892
|
+
},
|
|
893
|
+
startRow: {
|
|
894
|
+
type: "integer",
|
|
895
|
+
minimum: 0,
|
|
896
|
+
description: "起始行号(从 0 开始)",
|
|
897
|
+
},
|
|
898
|
+
startColumn: {
|
|
899
|
+
type: "integer",
|
|
900
|
+
minimum: 0,
|
|
901
|
+
description: "起始列号(从 0 开始)",
|
|
902
|
+
},
|
|
903
|
+
gridData: {
|
|
889
904
|
type: "object",
|
|
890
|
-
description: "
|
|
891
|
-
additionalProperties:
|
|
892
|
-
required: ["
|
|
905
|
+
description: "表格数据,按企业微信官方 GridData 定义填写",
|
|
906
|
+
additionalProperties: false,
|
|
907
|
+
required: ["rows"],
|
|
893
908
|
properties: {
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
909
|
+
startRow: { type: "integer", minimum: 0, description: "起始行号(从 0 开始)" },
|
|
910
|
+
startColumn: { type: "integer", minimum: 0, description: "起始列号(从 0 开始)" },
|
|
911
|
+
rows: {
|
|
912
|
+
type: "array",
|
|
913
|
+
minItems: 1,
|
|
914
|
+
description: "行数据列表",
|
|
915
|
+
items: {
|
|
916
|
+
type: "object",
|
|
917
|
+
additionalProperties: false,
|
|
918
|
+
required: ["values"],
|
|
919
|
+
properties: {
|
|
920
|
+
values: {
|
|
921
|
+
type: "array",
|
|
922
|
+
minItems: 1,
|
|
923
|
+
description: "单元格数据列表(CellData 格式)",
|
|
924
|
+
items: {
|
|
925
|
+
type: "object",
|
|
926
|
+
additionalProperties: false,
|
|
927
|
+
required: ["cell_value"],
|
|
928
|
+
properties: {
|
|
929
|
+
cell_value: {
|
|
930
|
+
type: "object",
|
|
931
|
+
description: "单元格值(text 或 link 二选一)",
|
|
932
|
+
additionalProperties: false,
|
|
933
|
+
oneOf: [
|
|
934
|
+
{ required: ["text"], not: { required: ["link"] } },
|
|
935
|
+
{ required: ["link"], not: { required: ["text"] } }
|
|
936
|
+
],
|
|
937
|
+
properties: {
|
|
938
|
+
text: { type: "string", description: "文本内容" },
|
|
939
|
+
link: {
|
|
940
|
+
type: "object",
|
|
941
|
+
description: "超链接内容",
|
|
942
|
+
additionalProperties: false,
|
|
943
|
+
required: ["text", "url"],
|
|
944
|
+
properties: {
|
|
945
|
+
text: { type: "string", description: "链接显示文本" },
|
|
946
|
+
url: { type: "string", description: "链接地址" }
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
},
|
|
951
|
+
cell_format: {
|
|
952
|
+
type: "object",
|
|
953
|
+
description: "单元格格式(可选)",
|
|
954
|
+
additionalProperties: false,
|
|
955
|
+
properties: {
|
|
956
|
+
text_format: {
|
|
957
|
+
type: "object",
|
|
958
|
+
description: "文本格式",
|
|
959
|
+
additionalProperties: false,
|
|
960
|
+
properties: {
|
|
961
|
+
font: {
|
|
962
|
+
type: "string",
|
|
963
|
+
description: "字体名称(Microsoft YaHei, SimSun, Arial 等)"
|
|
964
|
+
},
|
|
965
|
+
font_size: {
|
|
966
|
+
type: "integer",
|
|
967
|
+
minimum: 1,
|
|
968
|
+
maximum: 72,
|
|
969
|
+
description: "字体大小(最大 72)"
|
|
970
|
+
},
|
|
971
|
+
bold: {
|
|
972
|
+
type: "boolean",
|
|
973
|
+
description: "加粗"
|
|
974
|
+
},
|
|
975
|
+
italic: {
|
|
976
|
+
type: "boolean",
|
|
977
|
+
description: "斜体"
|
|
978
|
+
},
|
|
979
|
+
strikethrough: {
|
|
980
|
+
type: "boolean",
|
|
981
|
+
description: "删除线"
|
|
982
|
+
},
|
|
983
|
+
underline: {
|
|
984
|
+
type: "boolean",
|
|
985
|
+
description: "下划线"
|
|
986
|
+
},
|
|
987
|
+
color: {
|
|
988
|
+
type: "object",
|
|
989
|
+
description: "字体颜色(RGBA)",
|
|
990
|
+
additionalProperties: false,
|
|
991
|
+
properties: {
|
|
992
|
+
red: {
|
|
993
|
+
type: "integer",
|
|
994
|
+
minimum: 0,
|
|
995
|
+
maximum: 255,
|
|
996
|
+
description: "红色通道"
|
|
997
|
+
},
|
|
998
|
+
green: {
|
|
999
|
+
type: "integer",
|
|
1000
|
+
minimum: 0,
|
|
1001
|
+
maximum: 255,
|
|
1002
|
+
description: "绿色通道"
|
|
1003
|
+
},
|
|
1004
|
+
blue: {
|
|
1005
|
+
type: "integer",
|
|
1006
|
+
minimum: 0,
|
|
1007
|
+
maximum: 255,
|
|
1008
|
+
description: "蓝色通道"
|
|
1009
|
+
},
|
|
1010
|
+
alpha: {
|
|
1011
|
+
type: "integer",
|
|
1012
|
+
minimum: 0,
|
|
1013
|
+
maximum: 255,
|
|
1014
|
+
description: "透明度(255 完全不透明)"
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
906
1028
|
}
|
|
907
1029
|
},
|
|
908
1030
|
},
|
|
@@ -930,34 +1052,8 @@ export const wecomDocToolSchema = {
|
|
|
930
1052
|
},
|
|
931
1053
|
},
|
|
932
1054
|
},
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
additionalProperties: false,
|
|
936
|
-
required: ["action", "docId", "requests"],
|
|
937
|
-
properties: {
|
|
938
|
-
action: { const: "modify_sheet_properties" },
|
|
939
|
-
accountId: accountIdProperty,
|
|
940
|
-
docId: {
|
|
941
|
-
...docIdProperty,
|
|
942
|
-
description: "在线表格 docid",
|
|
943
|
-
},
|
|
944
|
-
requests: {
|
|
945
|
-
type: "array",
|
|
946
|
-
minItems: 1,
|
|
947
|
-
maxItems: 5,
|
|
948
|
-
description: "修改属性请求列表,必须遵循企业微信 modify_sheet_properties 定义",
|
|
949
|
-
items: {
|
|
950
|
-
type: "object",
|
|
951
|
-
oneOf: [
|
|
952
|
-
{ required: ["add_sheet_request"], properties: { add_sheet_request: addSheetRequest } },
|
|
953
|
-
{ required: ["update_range_request"], properties: { update_range_request: updateRangeRequest } },
|
|
954
|
-
{ required: ["delete_dimension_request"], properties: { delete_dimension_request: deleteDimensionRequest } },
|
|
955
|
-
{ required: ["delete_sheet_request"], properties: { delete_sheet_request: deleteSheetRequest } }
|
|
956
|
-
]
|
|
957
|
-
}
|
|
958
|
-
},
|
|
959
|
-
},
|
|
960
|
-
},
|
|
1055
|
+
// Note: batch_update is the underlying API, but users should use edit_sheet_data action instead
|
|
1056
|
+
// The edit_sheet_data action handles conversion to batch_update format internally
|
|
961
1057
|
{
|
|
962
1058
|
type: "object",
|
|
963
1059
|
additionalProperties: false,
|
|
@@ -909,7 +909,10 @@ export function registerWecomDocTools(api: OpenClawPluginApi) {
|
|
|
909
909
|
const result = await docClient.editSheetData({
|
|
910
910
|
agent: account,
|
|
911
911
|
docId: params.docId,
|
|
912
|
-
|
|
912
|
+
sheetId: params.sheetId,
|
|
913
|
+
startRow: params.startRow ?? 0,
|
|
914
|
+
startColumn: params.startColumn ?? 0,
|
|
915
|
+
gridData: params.gridData,
|
|
913
916
|
});
|
|
914
917
|
return buildToolResult({
|
|
915
918
|
ok: true,
|