@yanhaidao/wecom 2.3.150 → 2.3.180
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/README.md +238 -385
- package/SKILLS_CAL.md +895 -0
- package/SKILLS_DOC.md +2136 -0
- package/changelog/v2.3.16.md +11 -0
- package/changelog/v2.3.18.md +22 -0
- package/index.ts +39 -3
- package/package.json +2 -3
- package/src/agent/handler.event-filter.test.ts +11 -0
- package/src/agent/handler.ts +732 -643
- package/src/app/account-runtime.ts +46 -20
- package/src/app/index.ts +19 -1
- package/src/capability/calendar/SKILLS_CHECKLIST.md +251 -0
- package/src/capability/calendar/client.ts +815 -0
- package/src/capability/calendar/index.ts +3 -0
- package/src/capability/calendar/schema.ts +417 -0
- package/src/capability/calendar/tool.ts +417 -0
- package/src/capability/calendar/types.ts +309 -0
- package/src/capability/doc/client.ts +567 -62
- package/src/capability/doc/schema.ts +419 -318
- package/src/capability/doc/tool.ts +1510 -1178
- package/src/capability/doc/types.ts +130 -14
- package/src/capability/mcp/index.ts +10 -0
- package/src/capability/mcp/schema.ts +107 -0
- package/src/capability/mcp/tool.ts +170 -0
- package/src/capability/mcp/transport.ts +394 -0
- package/src/channel.ts +70 -28
- package/src/config/schema.ts +71 -102
- package/src/outbound.test.ts +91 -14
- package/src/outbound.ts +143 -30
- package/src/runtime/reply-orchestrator.test.ts +35 -2
- package/src/runtime/reply-orchestrator.ts +14 -2
- package/src/runtime/session-manager.ts +20 -6
- package/src/runtime/source-registry.ts +165 -0
- package/src/target.ts +7 -4
- package/src/transport/bot-ws/inbound.test.ts +46 -0
- package/src/transport/bot-ws/inbound.ts +23 -5
- package/src/transport/bot-ws/media.ts +269 -0
- package/src/transport/bot-ws/reply.test.ts +85 -17
- package/src/transport/bot-ws/reply.ts +109 -21
- package/src/transport/bot-ws/sdk-adapter.test.ts +64 -1
- package/src/transport/bot-ws/sdk-adapter.ts +88 -12
- package/.claude/settings.local.json +0 -11
- package/docs/update-content-fix.md +0 -135
|
@@ -1,1290 +1,1622 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
3
|
-
import {
|
|
4
|
-
import { WecomDocClient } from "./client.js";
|
|
3
|
+
import { isWecomAgentSource } from "../../runtime/source-registry.js";
|
|
5
4
|
import type { ResolvedAgentAccount } from "../../types/index.js";
|
|
6
5
|
import { resolveAgentAccountOrUndefined } from "../bot/fallback-delivery.js";
|
|
7
|
-
|
|
6
|
+
import { WecomDocClient } from "./client.js";
|
|
7
|
+
import { wecomDocToolSchema } from "./schema.js";
|
|
8
8
|
import { UpdateRequest } from "./types.js";
|
|
9
9
|
|
|
10
10
|
function readString(value: unknown): string {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const trimmed = String(value ?? "").trim();
|
|
12
|
+
return trimmed || "";
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
function mapDocTypeLabel(docType: number): string {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
if (docType === 10) return "智能表格";
|
|
17
|
+
return docType === 4 ? "表格" : "文档";
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
function summarizeDocInfo(info: any = {}) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
const docName = readString(info.doc_name) || "未命名文档";
|
|
22
|
+
const docType = mapDocTypeLabel(Number(info.doc_type));
|
|
23
|
+
return `${docType}"${docName}"信息已获取`;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
function summarizeDocAuth(result: any = {}) {
|
|
27
|
-
|
|
27
|
+
return `权限信息已获取:通知成员 ${result.docMembers?.length ?? 0},协作者 ${result.coAuthList?.length ?? 0}`;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
function readBooleanFlag(value: unknown): boolean | null {
|
|
31
|
-
|
|
31
|
+
return typeof value === "boolean" ? value : null;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
function formatDocMemberRef(value: any) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return "";
|
|
36
|
+
const userid = readString(value.userid ?? value.userId);
|
|
37
|
+
if (userid) return `userid:${userid}`;
|
|
38
|
+
const partyid = readString(value.partyid);
|
|
39
|
+
if (partyid) return `partyid:${partyid}`;
|
|
40
|
+
const tagid = readString(value.tagid);
|
|
41
|
+
if (tagid) return `tagid:${tagid}`;
|
|
42
|
+
return "";
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
function mapDocMemberList(values: any) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
return Array.isArray(values)
|
|
47
|
+
? values.map((item) => formatDocMemberRef(item)).filter(Boolean)
|
|
48
|
+
: [];
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
function describeFlagState(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
function describeFlagState(
|
|
52
|
+
value: boolean | null,
|
|
53
|
+
enabledLabel: string,
|
|
54
|
+
disabledLabel: string,
|
|
55
|
+
unknownLabel = "未知",
|
|
56
|
+
) {
|
|
57
|
+
if (value === true) return enabledLabel;
|
|
58
|
+
if (value === false) return disabledLabel;
|
|
59
|
+
return unknownLabel;
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
function buildDocAuthDiagnosis(result: any = {}, requesterSenderId = "") {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
63
|
+
const accessRule =
|
|
64
|
+
result.accessRule && typeof result.accessRule === "object" ? result.accessRule : {};
|
|
65
|
+
const viewers = mapDocMemberList(result.docMembers);
|
|
66
|
+
const collaborators = mapDocMemberList(result.coAuthList);
|
|
67
|
+
const requester = readString(requesterSenderId);
|
|
68
|
+
const requesterViewerRef = requester ? `userid:${requester}` : "";
|
|
69
|
+
const requesterIsViewer = requesterViewerRef ? viewers.includes(requesterViewerRef) : false;
|
|
70
|
+
const requesterIsCollaborator = requesterViewerRef
|
|
71
|
+
? collaborators.includes(requesterViewerRef)
|
|
72
|
+
: false;
|
|
73
|
+
const internalAccessEnabled = readBooleanFlag(accessRule.enable_corp_internal);
|
|
74
|
+
const externalAccessEnabled = readBooleanFlag(accessRule.enable_corp_external);
|
|
75
|
+
const externalShareAllowed =
|
|
76
|
+
typeof accessRule.ban_share_external === "boolean" ? !accessRule.ban_share_external : null;
|
|
77
|
+
const likelyAnonymousLinkFailure =
|
|
78
|
+
internalAccessEnabled === true && externalAccessEnabled === false;
|
|
79
|
+
const findings = [
|
|
80
|
+
`企业内访问:${describeFlagState(internalAccessEnabled, "开启", "关闭")}`,
|
|
81
|
+
`企业外访问:${describeFlagState(externalAccessEnabled, "开启", "关闭")}`,
|
|
82
|
+
`外部分享:${describeFlagState(externalShareAllowed, "允许", "禁止")}`,
|
|
83
|
+
`查看成员:${viewers.length}`,
|
|
84
|
+
`协作者:${collaborators.length}`,
|
|
85
|
+
];
|
|
86
|
+
const recommendations: string[] = [];
|
|
87
|
+
if (likelyAnonymousLinkFailure) {
|
|
88
|
+
recommendations.push(
|
|
89
|
+
'当前更像是仅企业内可访问;匿名浏览器或未登录企业微信环境通常会显示"文档不存在"。',
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
if (requester) {
|
|
93
|
+
if (requesterIsCollaborator) {
|
|
94
|
+
recommendations.push(`当前请求人 ${requester} 已在协作者列表中。`);
|
|
95
|
+
} else if (requesterIsViewer) {
|
|
96
|
+
recommendations.push(`当前请求人 ${requester} 已在查看成员列表中,但还不是协作者。`);
|
|
97
|
+
} else {
|
|
98
|
+
recommendations.push(`当前请求人 ${requester} 不在查看成员或协作者列表中。`);
|
|
90
99
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
internalAccessEnabled,
|
|
103
|
+
externalAccessEnabled,
|
|
104
|
+
externalShareAllowed,
|
|
105
|
+
viewerCount: viewers.length,
|
|
106
|
+
collaboratorCount: collaborators.length,
|
|
107
|
+
viewers,
|
|
108
|
+
collaborators,
|
|
109
|
+
requesterSenderId: requester || undefined,
|
|
110
|
+
requesterRole: requesterIsCollaborator
|
|
111
|
+
? "collaborator"
|
|
112
|
+
: requesterIsViewer
|
|
113
|
+
? "viewer"
|
|
114
|
+
: requester
|
|
115
|
+
? "none"
|
|
116
|
+
: "unknown",
|
|
117
|
+
likelyAnonymousLinkFailure,
|
|
118
|
+
findings,
|
|
119
|
+
recommendations,
|
|
120
|
+
};
|
|
105
121
|
}
|
|
106
122
|
|
|
107
123
|
function summarizeDocAuthDiagnosis(diagnosis: any = {}) {
|
|
108
|
-
|
|
109
|
-
|
|
124
|
+
const parts = Array.isArray(diagnosis.findings) ? diagnosis.findings : [];
|
|
125
|
+
return parts.length > 0 ? `文档权限诊断:${parts.join(",")}` : "文档权限诊断已完成";
|
|
110
126
|
}
|
|
111
127
|
|
|
112
128
|
function buildDocIdUsageHint(docId?: string) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
129
|
+
const normalizedDocId = readString(docId);
|
|
130
|
+
if (!normalizedDocId) return "";
|
|
131
|
+
return `后续权限、分享和诊断操作请使用真实 docId:${normalizedDocId};不要直接使用分享链接路径中的片段。`;
|
|
116
132
|
}
|
|
117
133
|
|
|
118
134
|
function safeParseJson(text: string) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
135
|
+
try {
|
|
136
|
+
return JSON.parse(text);
|
|
137
|
+
} catch {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
124
140
|
}
|
|
125
141
|
|
|
126
142
|
function extractEmbeddedJson(html: string, variableName: string) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
143
|
+
const source = String(html ?? "");
|
|
144
|
+
if (!source) return null;
|
|
145
|
+
const marker = `window.${variableName}=`;
|
|
146
|
+
const start = source.indexOf(marker);
|
|
147
|
+
if (start < 0) return null;
|
|
148
|
+
const valueStart = start + marker.length;
|
|
149
|
+
const end = source.indexOf(";</script>", valueStart);
|
|
150
|
+
if (end < 0) return null;
|
|
151
|
+
return safeParseJson(source.slice(valueStart, end));
|
|
136
152
|
}
|
|
137
153
|
|
|
138
|
-
function buildShareLinkDiagnosis(params: {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
154
|
+
function buildShareLinkDiagnosis(params: {
|
|
155
|
+
shareUrl: string;
|
|
156
|
+
finalUrl: string;
|
|
157
|
+
status: number;
|
|
158
|
+
contentType: string;
|
|
159
|
+
basicClientVars: any;
|
|
160
|
+
}) {
|
|
161
|
+
const { shareUrl, finalUrl, status, contentType, basicClientVars } = params;
|
|
162
|
+
const parsedUrl = new URL(finalUrl || shareUrl);
|
|
163
|
+
const pathSegments = parsedUrl.pathname.split("/").filter(Boolean);
|
|
164
|
+
const pathResourceType = readString(pathSegments[0]);
|
|
165
|
+
const pathResourceId = readString(pathSegments[1]);
|
|
166
|
+
const shareCode = readString(parsedUrl.searchParams.get("scode"));
|
|
167
|
+
const userInfo =
|
|
168
|
+
basicClientVars?.userInfo && typeof basicClientVars.userInfo === "object"
|
|
169
|
+
? basicClientVars.userInfo
|
|
170
|
+
: {};
|
|
171
|
+
const docInfo =
|
|
172
|
+
basicClientVars?.docInfo && typeof basicClientVars.docInfo === "object"
|
|
173
|
+
? basicClientVars.docInfo
|
|
174
|
+
: {};
|
|
175
|
+
const padInfo = docInfo?.padInfo && typeof docInfo.padInfo === "object" ? docInfo.padInfo : {};
|
|
176
|
+
const ownerInfo =
|
|
177
|
+
docInfo?.ownerInfo && typeof docInfo.ownerInfo === "object" ? docInfo.ownerInfo : {};
|
|
178
|
+
const shareInfo =
|
|
179
|
+
docInfo?.shareInfo && typeof docInfo.shareInfo === "object" ? docInfo.shareInfo : {};
|
|
180
|
+
const aclInfo = docInfo?.aclInfo && typeof docInfo.aclInfo === "object" ? docInfo.aclInfo : {};
|
|
181
|
+
const userType = readString(userInfo.userType);
|
|
182
|
+
const padType = readString(padInfo.padType);
|
|
183
|
+
const padId = readString(padInfo.padId);
|
|
184
|
+
const padTitle = readString(padInfo.padTitle);
|
|
185
|
+
const isGuest = userType === "guest" || Number(userInfo.loginType) === 0;
|
|
186
|
+
const isBlankPage = padType === "blankpage";
|
|
187
|
+
const likelyUnavailableToGuest = isGuest && isBlankPage && !padTitle;
|
|
188
|
+
const findings = [
|
|
189
|
+
`HTTP ${String(status || "")}`.trim(),
|
|
190
|
+
`内容类型:${readString(contentType) || "未知"}`,
|
|
191
|
+
`访问身份:${userType || "未知"}`,
|
|
192
|
+
`页面类型:${padType || "未知"}`,
|
|
193
|
+
`路径资源:${pathResourceType || "未知"} / ${pathResourceId || "未知"}`,
|
|
194
|
+
];
|
|
195
|
+
const recommendations: string[] = [];
|
|
196
|
+
if (likelyUnavailableToGuest) {
|
|
197
|
+
recommendations.push(
|
|
198
|
+
'当前链接对 guest/未登录企业微信环境返回 blankpage,外部访问会表现为打不开或像"文档不存在"。',
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
if (shareCode) {
|
|
202
|
+
recommendations.push(
|
|
203
|
+
`当前链接带有分享码 scode=${shareCode}。如分享码过期或未生效,外部访问会失败。`,
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
if (pathResourceId && padId && pathResourceId !== padId) {
|
|
207
|
+
recommendations.push(
|
|
208
|
+
`链接路径中的资源标识与页面 padId 不一致:path=${pathResourceId},padId=${padId}。`,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
if (pathResourceId && padId && pathResourceId === padId) {
|
|
212
|
+
recommendations.push(
|
|
213
|
+
"链接路径资源标识与页面 padId 一致,但这仍不等同于 Wedoc API 可用的真实 docId。",
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
shareUrl,
|
|
218
|
+
finalUrl,
|
|
219
|
+
httpStatus: status,
|
|
220
|
+
contentType: readString(contentType) || undefined,
|
|
221
|
+
pathResourceType: pathResourceType || undefined,
|
|
222
|
+
pathResourceId: pathResourceId || undefined,
|
|
223
|
+
shareCode: shareCode || undefined,
|
|
224
|
+
userType: userType || undefined,
|
|
225
|
+
isGuest,
|
|
226
|
+
padId: padId || undefined,
|
|
227
|
+
padType: padType || undefined,
|
|
228
|
+
padTitle: padTitle || undefined,
|
|
229
|
+
ownerId: readString(ownerInfo.ownerId) || undefined,
|
|
230
|
+
hasShareInfo: Object.keys(shareInfo).length > 0,
|
|
231
|
+
hasAclInfo: Object.keys(aclInfo).length > 0,
|
|
232
|
+
likelyUnavailableToGuest,
|
|
233
|
+
findings,
|
|
234
|
+
recommendations,
|
|
235
|
+
};
|
|
210
236
|
}
|
|
211
237
|
|
|
212
238
|
async function inspectWecomShareLink(params: { shareUrl: string }) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
239
|
+
const { shareUrl } = params;
|
|
240
|
+
const normalizedUrl = readString(shareUrl);
|
|
241
|
+
if (!normalizedUrl) throw new Error("shareUrl required");
|
|
242
|
+
let parsed;
|
|
243
|
+
try {
|
|
244
|
+
parsed = new URL(normalizedUrl);
|
|
245
|
+
} catch {
|
|
246
|
+
throw new Error("shareUrl must be a valid URL");
|
|
247
|
+
}
|
|
248
|
+
// To protect URLs containing underscores from markdown italic corruption in output, we ensure we return exactly what we got or wrap it later.
|
|
223
249
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
+
const response = await fetch(parsed.toString(), {
|
|
251
|
+
headers: {
|
|
252
|
+
"user-agent": "OpenClaw-Wechat/1.0",
|
|
253
|
+
accept: "text/html,application/xhtml+xml",
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
const contentType = response.headers?.get("content-type") || "";
|
|
257
|
+
const html = await response.text();
|
|
258
|
+
const basicClientVars = extractEmbeddedJson(html, "basicClientVars");
|
|
259
|
+
const diagnosis = buildShareLinkDiagnosis({
|
|
260
|
+
shareUrl: normalizedUrl,
|
|
261
|
+
finalUrl: response.url || parsed.toString(),
|
|
262
|
+
status: response.status,
|
|
263
|
+
contentType,
|
|
264
|
+
basicClientVars,
|
|
265
|
+
});
|
|
266
|
+
return {
|
|
267
|
+
raw: {
|
|
268
|
+
httpStatus: response.status,
|
|
269
|
+
// Markdown italic protection for URLs
|
|
270
|
+
finalUrl: `\u00A0${response.url || parsed.toString()}\u00A0`.trim(),
|
|
271
|
+
contentType,
|
|
272
|
+
basicClientVars,
|
|
273
|
+
},
|
|
274
|
+
diagnosis,
|
|
275
|
+
};
|
|
250
276
|
}
|
|
251
277
|
|
|
252
278
|
function summarizeShareLinkDiagnosis(diagnosis: any = {}) {
|
|
253
|
-
|
|
254
|
-
|
|
279
|
+
const parts = Array.isArray(diagnosis.findings) ? diagnosis.findings : [];
|
|
280
|
+
return parts.length > 0 ? `分享链接校验:${parts.join(",")}` : "分享链接校验已完成";
|
|
255
281
|
}
|
|
256
282
|
|
|
257
283
|
function summarizeSheetProperties(result: any = {}) {
|
|
258
|
-
|
|
284
|
+
return `表格属性已获取:工作表 ${result.properties?.length ?? 0}`;
|
|
259
285
|
}
|
|
260
286
|
|
|
261
287
|
function summarizeDocAccess(result: any = {}) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
288
|
+
const parts = [];
|
|
289
|
+
if (result.addedViewerCount) parts.push(`新增查看成员 ${result.addedViewerCount}`);
|
|
290
|
+
if (result.addedCollaboratorCount) parts.push(`新增协作者 ${result.addedCollaboratorCount}`);
|
|
291
|
+
if (result.removedViewerCount) parts.push(`移除查看成员 ${result.removedViewerCount}`);
|
|
292
|
+
if (result.removedCollaboratorCount) parts.push(`移除协作者 ${result.removedCollaboratorCount}`);
|
|
293
|
+
return parts.length > 0 ? `文档权限已更新:${parts.join(",")}` : "文档权限已更新";
|
|
268
294
|
}
|
|
269
295
|
|
|
270
296
|
function summarizeFormInfo(result: any = {}) {
|
|
271
|
-
|
|
272
|
-
|
|
297
|
+
const title = readString(result.formInfo?.form_title) || "未命名收集表";
|
|
298
|
+
return `收集表"${title}"信息已获取`;
|
|
273
299
|
}
|
|
274
300
|
|
|
275
301
|
function summarizeFormAnswer(result: any = {}) {
|
|
276
|
-
|
|
302
|
+
return `收集表答案已获取:字段 ${result.answerList?.length ?? 0}`;
|
|
277
303
|
}
|
|
278
304
|
|
|
279
305
|
function summarizeFormStatistic(result: any = {}) {
|
|
280
|
-
|
|
306
|
+
return `收集表统计已获取:请求 ${result.items?.length ?? 0},成功 ${result.successCount ?? 0}`;
|
|
281
307
|
}
|
|
282
308
|
|
|
283
309
|
function summarizeAdvancedAccount(result: any = {}, action: string) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
310
|
+
if (action === "assign") return `高级功能账号分配任务已提交,jobid: ${result.jobid || "未知"}`;
|
|
311
|
+
if (action === "cancel") return `高级功能账号取消任务已提交,jobid: ${result.jobid || "未知"}`;
|
|
312
|
+
return `高级功能账号列表已获取:${result.userList?.length ?? 0} 个`;
|
|
287
313
|
}
|
|
288
314
|
|
|
289
315
|
function readMemberUserId(value: any) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
316
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
317
|
+
return readString(value);
|
|
318
|
+
}
|
|
319
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return "";
|
|
320
|
+
return readString(value.userid ?? value.userId);
|
|
295
321
|
}
|
|
296
322
|
|
|
297
323
|
function hasMemberUserId(values: any, requesterSenderId: string) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
324
|
+
const normalizedRequesterSenderId = readString(requesterSenderId);
|
|
325
|
+
if (!normalizedRequesterSenderId) return false;
|
|
326
|
+
return (
|
|
327
|
+
Array.isArray(values) &&
|
|
328
|
+
values.some((item) => readMemberUserId(item) === normalizedRequesterSenderId)
|
|
329
|
+
);
|
|
301
330
|
}
|
|
302
331
|
|
|
303
|
-
function resolveCreateCollaborators(params: {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
return explicitCollaborators;
|
|
332
|
+
function resolveCreateCollaborators(params: { toolContext: any; requestParams: any }) {
|
|
333
|
+
const { toolContext, requestParams } = params;
|
|
334
|
+
const explicitCollaborators = Array.isArray(requestParams?.collaborators)
|
|
335
|
+
? [...requestParams.collaborators]
|
|
336
|
+
: [];
|
|
337
|
+
const requesterSenderId = readString(toolContext?.senderId || toolContext?.requesterSenderId); // align with OpenClaw standard `senderId`
|
|
338
|
+
if (!requesterSenderId) return explicitCollaborators;
|
|
339
|
+
// By default, let's always auto-grant requester
|
|
340
|
+
if (hasMemberUserId(explicitCollaborators, requesterSenderId)) return explicitCollaborators;
|
|
341
|
+
if (hasMemberUserId(requestParams?.viewers, requesterSenderId)) return explicitCollaborators;
|
|
342
|
+
explicitCollaborators.push(requesterSenderId);
|
|
343
|
+
return explicitCollaborators;
|
|
316
344
|
}
|
|
317
345
|
|
|
318
346
|
function buildToolResult(payload: any) {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
347
|
+
// To avoid formatting issues with URLs having underscores rendering as markdown Italics
|
|
348
|
+
if (payload.url) payload.url = `<${payload.url}>`;
|
|
349
|
+
if (payload.diagnosis?.finalUrl) payload.diagnosis.finalUrl = `<${payload.diagnosis.finalUrl}>`;
|
|
350
|
+
if (payload.diagnosis?.shareUrl) payload.diagnosis.shareUrl = `<${payload.diagnosis.shareUrl}>`;
|
|
351
|
+
return {
|
|
352
|
+
content: [{ type: "text" as const, text: JSON.stringify(payload, null, 2) }],
|
|
353
|
+
details: payload,
|
|
354
|
+
};
|
|
327
355
|
}
|
|
328
356
|
|
|
329
357
|
export function registerWecomDocTools(api: OpenClawPluginApi) {
|
|
330
|
-
|
|
331
|
-
|
|
358
|
+
if (typeof api?.registerTool !== "function") return;
|
|
359
|
+
const docClient = new WecomDocClient();
|
|
332
360
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
361
|
+
api.registerTool((toolContext: any) => {
|
|
362
|
+
if (
|
|
363
|
+
toolContext?.messageChannel !== "wecom" ||
|
|
364
|
+
!isWecomAgentSource({
|
|
365
|
+
accountId: toolContext?.agentAccountId || toolContext?.accountId,
|
|
366
|
+
sessionKey: toolContext?.sessionKey,
|
|
367
|
+
sessionId: toolContext?.sessionId,
|
|
368
|
+
})
|
|
369
|
+
) {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
345
372
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
373
|
+
return {
|
|
374
|
+
name: "wecom_doc",
|
|
375
|
+
label: "WeCom Doc",
|
|
376
|
+
description:
|
|
377
|
+
"企业微信文档工具。支持文档/表格/收集表完整CRUD操作、查看/协作者权限配置、属性查询以及分享打不开可用性诊断功能。",
|
|
378
|
+
parameters: wecomDocToolSchema,
|
|
379
|
+
async execute(_toolCallId, params: any) {
|
|
380
|
+
try {
|
|
381
|
+
let accountId =
|
|
382
|
+
params.accountId || toolContext?.agentAccountId || toolContext?.accountId || "default";
|
|
383
|
+
const account = resolveAgentAccountOrUndefined(api.config, accountId);
|
|
384
|
+
if (!account || !account.configured) {
|
|
385
|
+
throw new Error(`WeCom account ${accountId} not configured for Doc API requirements`);
|
|
386
|
+
}
|
|
358
387
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
388
|
+
const action = params.action;
|
|
389
|
+
switch (action) {
|
|
390
|
+
case "create": {
|
|
391
|
+
const explicitCollaborators = Array.isArray(params.collaborators)
|
|
392
|
+
? [...params.collaborators]
|
|
393
|
+
: [];
|
|
394
|
+
const result = await docClient.createDoc({
|
|
395
|
+
agent: account,
|
|
396
|
+
docName: params.docName,
|
|
397
|
+
docType: params.docType,
|
|
398
|
+
spaceId: params.spaceId,
|
|
399
|
+
fatherId: params.fatherId,
|
|
400
|
+
adminUsers: params.adminUsers,
|
|
401
|
+
});
|
|
374
402
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
item.includes("qpic.cn") || item.includes("weixin.qq.com"));
|
|
391
|
-
}
|
|
392
|
-
return false;
|
|
393
|
-
};
|
|
403
|
+
// Auto-set security rules for better default permissions (internal users can edit)
|
|
404
|
+
try {
|
|
405
|
+
await docClient.setDocJoinRule({
|
|
406
|
+
agent: account,
|
|
407
|
+
docId: result.docId,
|
|
408
|
+
request: {
|
|
409
|
+
enable_corp_internal: true,
|
|
410
|
+
corp_internal_auth: 2, // 2 = edit permission
|
|
411
|
+
enable_corp_external: false,
|
|
412
|
+
ban_share_external: false,
|
|
413
|
+
},
|
|
414
|
+
});
|
|
415
|
+
} catch (err) {
|
|
416
|
+
// Non-fatal: document created, just default permissions may be read-only
|
|
417
|
+
}
|
|
394
418
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
419
|
+
// Handle initial content (title/body separation) if provided
|
|
420
|
+
// Supports: string (text) or {type: "text"|"image", content/url: string}
|
|
421
|
+
let contentResult: any = null;
|
|
422
|
+
if (Array.isArray(params.init_content) && params.init_content.length > 0) {
|
|
423
|
+
try {
|
|
424
|
+
// Helper: check if content item is an image
|
|
425
|
+
const isImageItem = (item: any): boolean => {
|
|
426
|
+
if (typeof item === "object" && item !== null) {
|
|
427
|
+
return item.type === "image" || (item.url && !item.content);
|
|
428
|
+
}
|
|
429
|
+
if (typeof item === "string") {
|
|
430
|
+
// Detect image URLs
|
|
431
|
+
return (
|
|
432
|
+
item.startsWith("http") &&
|
|
433
|
+
(item.includes(".png") ||
|
|
434
|
+
item.includes(".jpg") ||
|
|
435
|
+
item.includes(".jpeg") ||
|
|
436
|
+
item.includes(".gif") ||
|
|
437
|
+
item.includes("qpic.cn") ||
|
|
438
|
+
item.includes("weixin.qq.com"))
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
return false;
|
|
442
|
+
};
|
|
402
443
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
return Buffer.from(arrayBuffer).toString("base64");
|
|
411
|
-
};
|
|
444
|
+
// Helper: get image URL from content item
|
|
445
|
+
const getImageUrl = (item: any): string => {
|
|
446
|
+
if (typeof item === "object" && item !== null) {
|
|
447
|
+
return item.url || item.content || "";
|
|
448
|
+
}
|
|
449
|
+
return String(item);
|
|
450
|
+
};
|
|
412
451
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
452
|
+
// Helper: get text from content item
|
|
453
|
+
const getText = (item: any): string => {
|
|
454
|
+
if (typeof item === "object" && item !== null) {
|
|
455
|
+
return item.content || item.text || "";
|
|
456
|
+
}
|
|
457
|
+
return String(item);
|
|
458
|
+
};
|
|
420
459
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
const imgUrl = getImageUrl(firstItem);
|
|
460
|
+
// Helper: download image from URL or read local file and convert to base64
|
|
461
|
+
const getImageAsBase64 = async (imageSource: string): Promise<string> => {
|
|
462
|
+
// Check if it's a local file path or remote URL
|
|
463
|
+
const isLocalFile =
|
|
464
|
+
!imageSource.startsWith("http") && !imageSource.startsWith("data:");
|
|
427
465
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
agent: account,
|
|
433
|
-
docId: result.docId,
|
|
434
|
-
base64_content: base64,
|
|
435
|
-
});
|
|
466
|
+
if (isLocalFile) {
|
|
467
|
+
// Local file path - read using Node.js fs
|
|
468
|
+
const fs = await import("fs");
|
|
469
|
+
const path = await import("path");
|
|
436
470
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
docId: result.docId,
|
|
442
|
-
requests: [{
|
|
443
|
-
insert_image: {
|
|
444
|
-
image_id: uploadResult.url,
|
|
445
|
-
location: { index: 0 },
|
|
446
|
-
width: uploadResult.width,
|
|
447
|
-
height: uploadResult.height
|
|
448
|
-
}
|
|
449
|
-
}]
|
|
450
|
-
});
|
|
451
|
-
} catch (uploadErr) {
|
|
452
|
-
console.error(`Failed to upload first image ${imgUrl}:`, uploadErr);
|
|
453
|
-
throw new Error(`First image upload failed: ${uploadErr instanceof Error ? uploadErr.message : String(uploadErr)}`);
|
|
454
|
-
}
|
|
455
|
-
} else {
|
|
456
|
-
const titleText = getText(firstItem);
|
|
457
|
-
await docClient.updateDocContent({
|
|
458
|
-
agent: account,
|
|
459
|
-
docId: result.docId,
|
|
460
|
-
requests: [{
|
|
461
|
-
insert_text: {
|
|
462
|
-
text: titleText,
|
|
463
|
-
location: { index: 0 }
|
|
464
|
-
}
|
|
465
|
-
}]
|
|
466
|
-
});
|
|
471
|
+
// Resolve to absolute path if relative
|
|
472
|
+
const absolutePath = path.isAbsolute(imageSource)
|
|
473
|
+
? imageSource
|
|
474
|
+
: path.join(process.cwd(), imageSource);
|
|
467
475
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
agent: account,
|
|
472
|
-
docId: result.docId,
|
|
473
|
-
requests: [{
|
|
474
|
-
update_text_property: {
|
|
475
|
-
text_property: { bold: true },
|
|
476
|
-
ranges: [{ start_index: 0, length: titleText.length }]
|
|
477
|
-
}
|
|
478
|
-
}]
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
}
|
|
476
|
+
if (!fs.existsSync(absolutePath)) {
|
|
477
|
+
throw new Error(`Local image file not found: ${absolutePath}`);
|
|
478
|
+
}
|
|
483
479
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
480
|
+
const fileBuffer = fs.readFileSync(absolutePath);
|
|
481
|
+
return fileBuffer.toString("base64");
|
|
482
|
+
} else if (imageSource.startsWith("data:")) {
|
|
483
|
+
// Data URL (base64 already)
|
|
484
|
+
const matches = imageSource.match(
|
|
485
|
+
/^data:image\/(?:png|jpeg|gif|webp);base64,(.*)$/,
|
|
486
|
+
);
|
|
487
|
+
if (matches && matches[1]) {
|
|
488
|
+
return matches[1];
|
|
489
|
+
}
|
|
490
|
+
throw new Error("Invalid data URL format");
|
|
491
|
+
} else {
|
|
492
|
+
// Remote URL - download first
|
|
493
|
+
console.log(
|
|
494
|
+
`[wecom-doc] Downloading remote image: ${imageSource.substring(0, 50)}...`,
|
|
495
|
+
);
|
|
496
|
+
const response = await fetch(imageSource);
|
|
497
|
+
if (!response.ok) {
|
|
498
|
+
throw new Error(
|
|
499
|
+
`Failed to download image: ${response.status} ${response.statusText}`,
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
503
|
+
return Buffer.from(arrayBuffer).toString("base64");
|
|
504
|
+
}
|
|
505
|
+
};
|
|
488
506
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
507
|
+
// Step 1: Insert first paragraph (title) at index 0
|
|
508
|
+
if (params.init_content[0]) {
|
|
509
|
+
const firstItem = params.init_content[0];
|
|
510
|
+
if (isImageItem(firstItem)) {
|
|
511
|
+
// First item is image - upload first, then insert at index 0
|
|
512
|
+
const imgUrl = getImageUrl(firstItem);
|
|
495
513
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
514
|
+
try {
|
|
515
|
+
// Upload image to WeCom to get proper image_id
|
|
516
|
+
const base64 = await getImageAsBase64(imgUrl);
|
|
517
|
+
const uploadResult = await docClient.uploadDocImage({
|
|
518
|
+
agent: account,
|
|
519
|
+
docId: result.docId,
|
|
520
|
+
base64_content: base64,
|
|
521
|
+
});
|
|
522
|
+
console.log(
|
|
523
|
+
`[wecom-doc] Title image uploaded: ${uploadResult.width}x${uploadResult.height}`,
|
|
524
|
+
);
|
|
499
525
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
526
|
+
// Insert image using uploaded URL
|
|
527
|
+
// Note: version is optional, API handles concurrency
|
|
528
|
+
await docClient.updateDocContent({
|
|
529
|
+
agent: account,
|
|
530
|
+
docId: result.docId,
|
|
531
|
+
requests: [
|
|
532
|
+
{
|
|
533
|
+
insert_image: {
|
|
534
|
+
image_id: uploadResult.url,
|
|
535
|
+
location: { index: 0 },
|
|
536
|
+
width: uploadResult.width,
|
|
537
|
+
height: uploadResult.height,
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
],
|
|
541
|
+
});
|
|
542
|
+
} catch (uploadErr) {
|
|
543
|
+
console.error(`Failed to upload first image ${imgUrl}:`, uploadErr);
|
|
544
|
+
throw new Error(
|
|
545
|
+
`First image upload failed: ${uploadErr instanceof Error ? uploadErr.message : String(uploadErr)}`,
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
} else {
|
|
549
|
+
const titleText = getText(firstItem);
|
|
550
|
+
await docClient.updateDocContent({
|
|
551
|
+
agent: account,
|
|
552
|
+
docId: result.docId,
|
|
553
|
+
requests: [
|
|
554
|
+
{
|
|
555
|
+
insert_text: {
|
|
556
|
+
text: titleText,
|
|
557
|
+
location: { index: 0 },
|
|
558
|
+
},
|
|
559
|
+
},
|
|
560
|
+
],
|
|
561
|
+
});
|
|
503
562
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
563
|
+
// Apply Title Styling (Bold)
|
|
564
|
+
if (titleText.length > 0) {
|
|
565
|
+
await docClient.updateDocContent({
|
|
566
|
+
agent: account,
|
|
567
|
+
docId: result.docId,
|
|
568
|
+
requests: [
|
|
569
|
+
{
|
|
570
|
+
update_text_property: {
|
|
571
|
+
text_property: { bold: true },
|
|
572
|
+
ranges: [{ start_index: 0, length: titleText.length }],
|
|
573
|
+
},
|
|
574
|
+
},
|
|
575
|
+
],
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
512
580
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
await docClient.updateDocContent({
|
|
518
|
-
agent: account,
|
|
519
|
-
docId: result.docId,
|
|
520
|
-
version: currentVersion, // Pass version for concurrency control
|
|
521
|
-
requests: [
|
|
522
|
-
{
|
|
523
|
-
insert_paragraph: {
|
|
524
|
-
location: { index: docEndIndex }
|
|
525
|
-
}
|
|
526
|
-
},
|
|
527
|
-
{
|
|
528
|
-
insert_image: {
|
|
529
|
-
image_id: uploadResult.url,
|
|
530
|
-
location: { index: docEndIndex + 1 },
|
|
531
|
-
width: uploadResult.width,
|
|
532
|
-
height: uploadResult.height
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
]
|
|
536
|
-
});
|
|
537
|
-
} catch (uploadErr) {
|
|
538
|
-
console.error(`Failed to upload image ${imgUrl}:`, uploadErr);
|
|
539
|
-
throw new Error(`Image upload failed: ${uploadErr instanceof Error ? uploadErr.message : String(uploadErr)}`);
|
|
540
|
-
}
|
|
541
|
-
} else {
|
|
542
|
-
const text = getText(item);
|
|
543
|
-
if (!text) continue;
|
|
581
|
+
// Step 2: For subsequent items, append with proper paragraph handling
|
|
582
|
+
// Per API spec: must get latest version and index before each batch_update
|
|
583
|
+
for (let i = 1; i < params.init_content.length; i++) {
|
|
584
|
+
const item = params.init_content[i];
|
|
544
585
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
docId: result.docId,
|
|
552
|
-
version: currentVersion, // Pass version for concurrency control
|
|
553
|
-
requests: [
|
|
554
|
-
{
|
|
555
|
-
insert_paragraph: {
|
|
556
|
-
location: { index: docEndIndex }
|
|
557
|
-
}
|
|
558
|
-
},
|
|
559
|
-
{
|
|
560
|
-
insert_text: {
|
|
561
|
-
text: text,
|
|
562
|
-
location: { index: docEndIndex + 1 }
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
]
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
contentResult = "init_content_populated";
|
|
570
|
-
} catch (err) {
|
|
571
|
-
contentResult = `content_failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
572
|
-
}
|
|
573
|
-
}
|
|
586
|
+
// Refresh content to get latest document structure and version
|
|
587
|
+
// API requires: version difference ≤ 100 from latest
|
|
588
|
+
const currentContent = await docClient.getDocContent({
|
|
589
|
+
agent: account,
|
|
590
|
+
docId: result.docId,
|
|
591
|
+
});
|
|
574
592
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
accessResult = await docClient.grantDocAccess({
|
|
579
|
-
agent: account,
|
|
580
|
-
docId: result.docId,
|
|
581
|
-
viewers: params.viewers,
|
|
582
|
-
collaborators: explicitCollaborators,
|
|
583
|
-
});
|
|
584
|
-
} catch (err) {
|
|
585
|
-
return buildToolResult({
|
|
586
|
-
ok: false,
|
|
587
|
-
partial: true,
|
|
588
|
-
action: "create",
|
|
589
|
-
accountId: account.accountId,
|
|
590
|
-
resourceType: result.docTypeLabel,
|
|
591
|
-
canonicalDocId: result.docId,
|
|
592
|
-
docId: result.docId,
|
|
593
|
-
title: readString(params.docName),
|
|
594
|
-
url: result.url || undefined,
|
|
595
|
-
summary: `已创建${mapDocTypeLabel(result.docType)}"${readString(params.docName)}"(docId: ${result.docId}),但权限授予失败`,
|
|
596
|
-
usageHint: buildDocIdUsageHint(result.docId) || undefined,
|
|
597
|
-
error: err instanceof Error ? err.message : String(err),
|
|
598
|
-
raw: { create: result.raw },
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
return buildToolResult({
|
|
603
|
-
ok: true,
|
|
604
|
-
action: "create",
|
|
605
|
-
accountId: account.accountId,
|
|
606
|
-
resourceType: result.docTypeLabel,
|
|
607
|
-
canonicalDocId: result.docId,
|
|
608
|
-
docId: result.docId,
|
|
609
|
-
title: readString(params.docName),
|
|
610
|
-
url: result.url || undefined,
|
|
611
|
-
summary: accessResult
|
|
612
|
-
? `已创建${mapDocTypeLabel(result.docType)}"${readString(params.docName)}"(docId: ${result.docId});${summarizeDocAccess(accessResult)}` + (contentResult ? `;内容填充: ${contentResult}` : "")
|
|
613
|
-
: `已创建${mapDocTypeLabel(result.docType)}"${readString(params.docName)}"(docId: ${result.docId})` + (contentResult ? `;内容填充: ${contentResult}` : ""),
|
|
614
|
-
usageHint: buildDocIdUsageHint(result.docId) || undefined,
|
|
615
|
-
raw: accessResult ? { create: result.raw, access: accessResult.raw } : result.raw,
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
case "rename": {
|
|
619
|
-
const result = await docClient.renameDoc({
|
|
620
|
-
agent: account,
|
|
621
|
-
docId: params.docId,
|
|
622
|
-
newName: params.newName,
|
|
623
|
-
});
|
|
624
|
-
return buildToolResult({
|
|
625
|
-
ok: true,
|
|
626
|
-
action: "rename",
|
|
627
|
-
accountId: account.accountId,
|
|
628
|
-
docId: result.docId,
|
|
629
|
-
title: result.newName,
|
|
630
|
-
summary: `文档已重命名为"${result.newName}"`,
|
|
631
|
-
raw: result.raw,
|
|
632
|
-
});
|
|
633
|
-
}
|
|
634
|
-
case "copy": {
|
|
635
|
-
const result = await docClient.copyDoc({
|
|
636
|
-
agent: account,
|
|
637
|
-
docId: params.docId,
|
|
638
|
-
newName: params.newName,
|
|
639
|
-
spaceId: params.spaceId,
|
|
640
|
-
fatherId: params.fatherId,
|
|
641
|
-
});
|
|
642
|
-
return buildToolResult({
|
|
643
|
-
ok: true,
|
|
644
|
-
action: "copy",
|
|
645
|
-
accountId: account.accountId,
|
|
646
|
-
docId: result.docId,
|
|
647
|
-
summary: `文档已成功复制,新 docId: ${result.docId}`,
|
|
648
|
-
raw: result.raw,
|
|
649
|
-
});
|
|
650
|
-
}
|
|
651
|
-
case "get_info": {
|
|
652
|
-
const result = await docClient.getDocBaseInfo({
|
|
653
|
-
agent: account,
|
|
654
|
-
docId: params.docId,
|
|
655
|
-
});
|
|
656
|
-
return buildToolResult({
|
|
657
|
-
ok: true,
|
|
658
|
-
action: "get_info",
|
|
659
|
-
accountId: account.accountId,
|
|
660
|
-
docId: params.docId,
|
|
661
|
-
title: readString(result.info?.doc_name) || undefined,
|
|
662
|
-
resourceType:
|
|
663
|
-
Number(result.info?.doc_type) === 10 ? "smart_table" : Number(result.info?.doc_type) === 4 ? "spreadsheet" : "doc",
|
|
664
|
-
summary: summarizeDocInfo(result.info),
|
|
665
|
-
raw: result.raw,
|
|
666
|
-
});
|
|
667
|
-
}
|
|
668
|
-
case "share": {
|
|
669
|
-
const result = await docClient.shareDoc({
|
|
670
|
-
agent: account,
|
|
671
|
-
docId: params.docId,
|
|
672
|
-
});
|
|
673
|
-
return buildToolResult({
|
|
674
|
-
ok: true,
|
|
675
|
-
action: "share",
|
|
676
|
-
accountId: account.accountId,
|
|
677
|
-
canonicalDocId: params.docId,
|
|
678
|
-
docId: params.docId,
|
|
679
|
-
url: result.shareUrl || undefined,
|
|
680
|
-
summary: result.shareUrl ? `文档分享链接已获取(docId: ${params.docId})` : `文档分享接口调用成功(docId: ${params.docId})`,
|
|
681
|
-
usageHint: buildDocIdUsageHint(params.docId) || undefined,
|
|
682
|
-
raw: result.raw,
|
|
683
|
-
});
|
|
684
|
-
}
|
|
685
|
-
case "get_auth": {
|
|
686
|
-
const result = await docClient.getDocAuth({
|
|
687
|
-
agent: account,
|
|
688
|
-
docId: params.docId,
|
|
689
|
-
});
|
|
690
|
-
const diagnosis = buildDocAuthDiagnosis(result, toolContext?.senderId);
|
|
691
|
-
return buildToolResult({
|
|
692
|
-
ok: true,
|
|
693
|
-
action: "get_auth",
|
|
694
|
-
accountId: account.accountId,
|
|
695
|
-
canonicalDocId: params.docId,
|
|
696
|
-
docId: params.docId,
|
|
697
|
-
summary: summarizeDocAuth(result),
|
|
698
|
-
diagnosis,
|
|
699
|
-
raw: result.raw,
|
|
700
|
-
});
|
|
701
|
-
}
|
|
702
|
-
case "diagnose_auth": {
|
|
703
|
-
const result = await docClient.getDocAuth({
|
|
704
|
-
agent: account,
|
|
705
|
-
docId: params.docId,
|
|
706
|
-
});
|
|
707
|
-
const diagnosis = buildDocAuthDiagnosis(result, toolContext?.senderId);
|
|
708
|
-
return buildToolResult({
|
|
709
|
-
ok: true,
|
|
710
|
-
action: "diagnose_auth",
|
|
711
|
-
accountId: account.accountId,
|
|
712
|
-
canonicalDocId: params.docId,
|
|
713
|
-
docId: params.docId,
|
|
714
|
-
summary: summarizeDocAuthDiagnosis(diagnosis),
|
|
715
|
-
diagnosis,
|
|
716
|
-
raw: result.raw,
|
|
717
|
-
});
|
|
718
|
-
}
|
|
719
|
-
case "validate_share_link": {
|
|
720
|
-
const result = await inspectWecomShareLink({
|
|
721
|
-
shareUrl: params.shareUrl,
|
|
722
|
-
});
|
|
723
|
-
return buildToolResult({
|
|
724
|
-
ok: true,
|
|
725
|
-
action: "validate_share_link",
|
|
726
|
-
accountId: account.accountId,
|
|
727
|
-
url: result.diagnosis.finalUrl || params.shareUrl,
|
|
728
|
-
summary: summarizeShareLinkDiagnosis(result.diagnosis),
|
|
729
|
-
diagnosis: result.diagnosis,
|
|
730
|
-
raw: result.raw,
|
|
731
|
-
});
|
|
732
|
-
}
|
|
733
|
-
case "delete": {
|
|
734
|
-
const result = await docClient.deleteDoc({
|
|
735
|
-
agent: account,
|
|
736
|
-
docId: params.docId,
|
|
737
|
-
formId: params.formId,
|
|
738
|
-
});
|
|
739
|
-
return buildToolResult({
|
|
740
|
-
ok: true,
|
|
741
|
-
action: "delete",
|
|
742
|
-
accountId: account.accountId,
|
|
743
|
-
docId: result.docId || undefined,
|
|
744
|
-
formId: result.formId || undefined,
|
|
745
|
-
summary: result.formId ? "收集表已删除" : "文档已删除",
|
|
746
|
-
raw: result.raw,
|
|
747
|
-
});
|
|
748
|
-
}
|
|
749
|
-
case "set_join_rule": {
|
|
750
|
-
const result = await docClient.setDocJoinRule({
|
|
751
|
-
agent: account,
|
|
752
|
-
docId: params.docId,
|
|
753
|
-
request: params.request,
|
|
754
|
-
});
|
|
755
|
-
return buildToolResult({
|
|
756
|
-
ok: true,
|
|
757
|
-
action: "set_join_rule",
|
|
758
|
-
accountId: account.accountId,
|
|
759
|
-
docId: result.docId,
|
|
760
|
-
summary: "文档查看规则已更新",
|
|
761
|
-
raw: result.raw,
|
|
762
|
-
});
|
|
763
|
-
}
|
|
764
|
-
case "set_member_auth": {
|
|
765
|
-
const result = await docClient.setDocMemberAuth({
|
|
766
|
-
agent: account,
|
|
767
|
-
docId: params.docId,
|
|
768
|
-
request: params.request,
|
|
769
|
-
});
|
|
770
|
-
return buildToolResult({
|
|
771
|
-
ok: true,
|
|
772
|
-
action: "set_member_auth",
|
|
773
|
-
accountId: account.accountId,
|
|
774
|
-
docId: result.docId,
|
|
775
|
-
summary: "文档通知范围及成员权限已更新",
|
|
776
|
-
raw: result.raw,
|
|
777
|
-
});
|
|
778
|
-
}
|
|
779
|
-
case "grant_access": {
|
|
780
|
-
const result = await docClient.grantDocAccess({
|
|
781
|
-
agent: account,
|
|
782
|
-
docId: params.docId,
|
|
783
|
-
viewers: params.viewers,
|
|
784
|
-
collaborators: params.collaborators,
|
|
785
|
-
removeViewers: params.removeViewers,
|
|
786
|
-
removeCollaborators: params.removeCollaborators,
|
|
787
|
-
authLevel: params.auth,
|
|
788
|
-
});
|
|
789
|
-
return buildToolResult({
|
|
790
|
-
ok: true,
|
|
791
|
-
action: "grant_access",
|
|
792
|
-
accountId: account.accountId,
|
|
793
|
-
docId: result.docId,
|
|
794
|
-
summary: summarizeDocAccess(result),
|
|
795
|
-
raw: result.raw,
|
|
796
|
-
});
|
|
797
|
-
}
|
|
798
|
-
case "add_collaborators": {
|
|
799
|
-
const result = await docClient.addDocCollaborators({
|
|
800
|
-
agent: account,
|
|
801
|
-
docId: params.docId,
|
|
802
|
-
collaborators: params.collaborators,
|
|
803
|
-
auth: params.auth,
|
|
804
|
-
});
|
|
805
|
-
return buildToolResult({
|
|
806
|
-
ok: true,
|
|
807
|
-
action: "add_collaborators",
|
|
808
|
-
accountId: account.accountId,
|
|
809
|
-
docId: result.docId,
|
|
810
|
-
summary: `协作者已添加:${result.addedCollaboratorCount ?? 0}`,
|
|
811
|
-
raw: result.raw,
|
|
812
|
-
});
|
|
813
|
-
}
|
|
814
|
-
case "get_content": {
|
|
815
|
-
const result = await docClient.getDocContent({
|
|
816
|
-
agent: account,
|
|
817
|
-
docId: params.docId,
|
|
818
|
-
});
|
|
819
|
-
return buildToolResult({
|
|
820
|
-
ok: true,
|
|
821
|
-
action: "get_content",
|
|
822
|
-
accountId: account.accountId,
|
|
823
|
-
docId: params.docId,
|
|
824
|
-
summary: "文档内容已获取",
|
|
825
|
-
raw: result.raw,
|
|
826
|
-
});
|
|
827
|
-
}
|
|
828
|
-
case "update_content": {
|
|
829
|
-
const batchMode = params.batchMode === true;
|
|
830
|
-
|
|
831
|
-
const result = await docClient.updateDocContent({
|
|
832
|
-
agent: account,
|
|
833
|
-
docId: params.docId,
|
|
834
|
-
requests: params.requests,
|
|
835
|
-
version: params.version,
|
|
836
|
-
batchMode: batchMode,
|
|
837
|
-
});
|
|
838
|
-
|
|
839
|
-
return buildToolResult({
|
|
840
|
-
ok: true,
|
|
841
|
-
action: "update_content",
|
|
842
|
-
accountId: account.accountId,
|
|
843
|
-
docId: params.docId,
|
|
844
|
-
summary: `文档内容已更新(${batchMode ? '批量' : '顺序'}模式)`,
|
|
845
|
-
raw: result.raw,
|
|
846
|
-
});
|
|
847
|
-
}
|
|
848
|
-
case "set_safety_setting": {
|
|
849
|
-
const result = await docClient.setDocSafetySetting({
|
|
850
|
-
agent: account,
|
|
851
|
-
docId: params.docId,
|
|
852
|
-
request: params.request,
|
|
853
|
-
});
|
|
854
|
-
return buildToolResult({
|
|
855
|
-
ok: true,
|
|
856
|
-
action: "set_safety_setting",
|
|
857
|
-
accountId: account.accountId,
|
|
858
|
-
docId: result.docId,
|
|
859
|
-
summary: "文档安全设置已更新",
|
|
860
|
-
raw: result.raw,
|
|
861
|
-
});
|
|
862
|
-
}
|
|
863
|
-
case "get_doc_security_setting": {
|
|
864
|
-
const result = await docClient.getDocAuth({
|
|
865
|
-
agent: account,
|
|
866
|
-
docId: params.docId,
|
|
867
|
-
});
|
|
868
|
-
return buildToolResult({
|
|
869
|
-
ok: true,
|
|
870
|
-
action: "get_doc_security_setting",
|
|
871
|
-
accountId: account.accountId,
|
|
872
|
-
docId: params.docId,
|
|
873
|
-
summary: "文档安全设置已获取",
|
|
874
|
-
details: result.secureSetting,
|
|
875
|
-
raw: result.raw,
|
|
876
|
-
});
|
|
877
|
-
}
|
|
878
|
-
case "mod_doc_security_setting": {
|
|
879
|
-
// Alias to setDocSafetySetting logic
|
|
880
|
-
const result = await docClient.setDocSafetySetting({
|
|
881
|
-
agent: account,
|
|
882
|
-
docId: params.docId,
|
|
883
|
-
request: params.setting,
|
|
884
|
-
});
|
|
885
|
-
return buildToolResult({
|
|
886
|
-
ok: true,
|
|
887
|
-
action: "mod_doc_security_setting",
|
|
888
|
-
accountId: account.accountId,
|
|
889
|
-
docId: result.docId,
|
|
890
|
-
summary: "文档安全设置已更新",
|
|
891
|
-
raw: result.raw,
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
case "mod_doc_member_notified_scope": {
|
|
895
|
-
const result = await docClient.modDocMemberNotifiedScope({
|
|
896
|
-
agent: account,
|
|
897
|
-
docId: params.docId,
|
|
898
|
-
notified_scope_type: params.notified_scope_type,
|
|
899
|
-
notified_member_list: params.notified_member_list,
|
|
900
|
-
});
|
|
901
|
-
return buildToolResult({
|
|
902
|
-
ok: true,
|
|
903
|
-
action: "mod_doc_member_notified_scope",
|
|
904
|
-
accountId: account.accountId,
|
|
905
|
-
docId: params.docId,
|
|
906
|
-
summary: "文档成员通知范围已更新",
|
|
907
|
-
raw: result,
|
|
908
|
-
});
|
|
909
|
-
}
|
|
910
|
-
case "create_collect": {
|
|
911
|
-
// 创建收集表(表单)
|
|
912
|
-
// 参考 API 规范文档:E8_AF_B7_E4_B8_A5_E6_A0_BC_E6_8C_89_E7_85_A7_E4_BB_A5_E4_B8_---099c30ec-70bd-4e5b-ae03-212de0226a25.docx
|
|
913
|
-
try {
|
|
914
|
-
const result = await docClient.createCollect({
|
|
915
|
-
agent: account,
|
|
916
|
-
formInfo: params.formInfo,
|
|
917
|
-
spaceId: params.spaceId,
|
|
918
|
-
fatherId: params.fatherId,
|
|
919
|
-
});
|
|
920
|
-
const title = readString(result.title);
|
|
921
|
-
return buildToolResult({
|
|
922
|
-
ok: true,
|
|
923
|
-
action: "create_collect",
|
|
924
|
-
accountId: account.accountId,
|
|
925
|
-
formId: result.formId,
|
|
926
|
-
title: title || undefined,
|
|
927
|
-
summary: title ? `已创建收集表"${title}"(formId: ${result.formId})` : `已创建收集表(formId: ${result.formId})`,
|
|
928
|
-
raw: result.raw,
|
|
929
|
-
});
|
|
930
|
-
} catch (err) {
|
|
931
|
-
// 提供更详细的错误提示
|
|
932
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
933
|
-
const hint = `
|
|
934
|
-
创建收集表失败。请检查以下必填项:
|
|
935
|
-
- form_title: 收集表标题(必填)
|
|
936
|
-
- form_question.items: 问题数组(必填,≤200 个)
|
|
937
|
-
- 每个问题必须包含:question_id, title, pos, reply_type, must_reply
|
|
938
|
-
- 单选/多选/下拉列表必须提供 option_item 数组
|
|
939
|
-
- reply_type 对照表:1 文本,2 单选,3 多选,5 位置,9 图片,10 文件,11 日期,14 时间,15 下拉列表,16 体温,17 签名,18 部门,19 成员,22 时长
|
|
593
|
+
// Get the end index of the document
|
|
594
|
+
const docEndIndex = currentContent.document.end;
|
|
595
|
+
const currentVersion = currentContent.version;
|
|
940
596
|
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
action: "create_collect",
|
|
945
|
-
accountId: account.accountId,
|
|
946
|
-
error: errorMsg,
|
|
947
|
-
summary: "创建收集表失败",
|
|
948
|
-
hint: hint.trim(),
|
|
949
|
-
raw: {},
|
|
950
|
-
});
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
case "modify_collect": {
|
|
954
|
-
const result = await docClient.modifyCollect({
|
|
955
|
-
agent: account,
|
|
956
|
-
oper: params.oper,
|
|
957
|
-
formId: params.formId,
|
|
958
|
-
formInfo: params.formInfo,
|
|
959
|
-
});
|
|
960
|
-
const title = readString(result.title);
|
|
961
|
-
return buildToolResult({
|
|
962
|
-
ok: true,
|
|
963
|
-
action: "modify_collect",
|
|
964
|
-
accountId: account.accountId,
|
|
965
|
-
formId: result.formId,
|
|
966
|
-
title: title || undefined,
|
|
967
|
-
summary: title
|
|
968
|
-
? `收集表已更新(${result.oper}):"${title}"`
|
|
969
|
-
: `收集表已更新(${result.oper})`,
|
|
970
|
-
raw: result.raw,
|
|
971
|
-
});
|
|
972
|
-
}
|
|
973
|
-
case "get_form_info": {
|
|
974
|
-
const result = await docClient.getFormInfo({
|
|
975
|
-
agent: account,
|
|
976
|
-
formId: params.formId,
|
|
977
|
-
});
|
|
978
|
-
return buildToolResult({
|
|
979
|
-
ok: true,
|
|
980
|
-
action: "get_form_info",
|
|
981
|
-
accountId: account.accountId,
|
|
982
|
-
formId: params.formId,
|
|
983
|
-
title: readString(result.formInfo?.form_title) || undefined,
|
|
984
|
-
summary: summarizeFormInfo(result),
|
|
985
|
-
raw: result.raw,
|
|
986
|
-
});
|
|
987
|
-
}
|
|
988
|
-
case "get_form_answer": {
|
|
989
|
-
const result = await docClient.getFormAnswer({
|
|
990
|
-
agent: account,
|
|
991
|
-
repeatedId: params.repeatedId,
|
|
992
|
-
answerIds: params.answerIds,
|
|
993
|
-
});
|
|
994
|
-
return buildToolResult({
|
|
995
|
-
ok: true,
|
|
996
|
-
action: "get_form_answer",
|
|
997
|
-
accountId: account.accountId,
|
|
998
|
-
repeatedId: params.repeatedId,
|
|
999
|
-
summary: summarizeFormAnswer(result),
|
|
1000
|
-
raw: result.raw,
|
|
1001
|
-
});
|
|
1002
|
-
}
|
|
1003
|
-
case "get_form_statistic": {
|
|
1004
|
-
const result = await docClient.getFormStatistic({
|
|
1005
|
-
agent: account,
|
|
1006
|
-
requests: params.requests,
|
|
1007
|
-
});
|
|
1008
|
-
return buildToolResult({
|
|
1009
|
-
ok: true,
|
|
1010
|
-
action: "get_form_statistic",
|
|
1011
|
-
accountId: account.accountId,
|
|
1012
|
-
summary: summarizeFormStatistic(result),
|
|
1013
|
-
raw: result.raw,
|
|
1014
|
-
});
|
|
1015
|
-
}
|
|
1016
|
-
case "get_sheet_properties": {
|
|
1017
|
-
const result = await docClient.getSheetProperties({
|
|
1018
|
-
agent: account,
|
|
1019
|
-
docId: params.docId,
|
|
1020
|
-
});
|
|
1021
|
-
return buildToolResult({
|
|
1022
|
-
ok: true,
|
|
1023
|
-
action: "get_sheet_properties",
|
|
1024
|
-
accountId: account.accountId,
|
|
1025
|
-
docId: params.docId,
|
|
1026
|
-
summary: summarizeSheetProperties(result),
|
|
1027
|
-
raw: result.raw,
|
|
1028
|
-
});
|
|
1029
|
-
}
|
|
1030
|
-
case "edit_sheet_data": {
|
|
1031
|
-
const result = await docClient.editSheetData({
|
|
1032
|
-
agent: account,
|
|
1033
|
-
docId: params.docId,
|
|
1034
|
-
sheetId: params.sheetId,
|
|
1035
|
-
startRow: params.startRow ?? 0,
|
|
1036
|
-
startColumn: params.startColumn ?? 0,
|
|
1037
|
-
gridData: params.gridData,
|
|
1038
|
-
});
|
|
1039
|
-
return buildToolResult({
|
|
1040
|
-
ok: true,
|
|
1041
|
-
action: "edit_sheet_data",
|
|
1042
|
-
accountId: account.accountId,
|
|
1043
|
-
docId: result.docId,
|
|
1044
|
-
summary: "在线表格数据已编辑",
|
|
1045
|
-
raw: result.raw,
|
|
1046
|
-
});
|
|
1047
|
-
}
|
|
1048
|
-
case "get_sheet_data": {
|
|
1049
|
-
const result = await docClient.getSheetData({
|
|
1050
|
-
agent: account,
|
|
1051
|
-
docId: params.docId,
|
|
1052
|
-
sheetId: params.sheetId,
|
|
1053
|
-
range: params.range,
|
|
1054
|
-
});
|
|
1055
|
-
return buildToolResult({
|
|
1056
|
-
ok: true,
|
|
1057
|
-
action: "get_sheet_data",
|
|
1058
|
-
accountId: account.accountId,
|
|
1059
|
-
docId: params.docId,
|
|
1060
|
-
summary: "在线表格数据已读取",
|
|
1061
|
-
data: result.data,
|
|
1062
|
-
raw: result.raw,
|
|
1063
|
-
});
|
|
1064
|
-
}
|
|
1065
|
-
case "modify_sheet_properties": {
|
|
1066
|
-
const result = await docClient.modifySheetProperties({
|
|
1067
|
-
agent: account,
|
|
1068
|
-
docId: params.docId,
|
|
1069
|
-
requests: params.requests,
|
|
1070
|
-
});
|
|
1071
|
-
return buildToolResult({
|
|
1072
|
-
ok: true,
|
|
1073
|
-
action: "modify_sheet_properties",
|
|
1074
|
-
accountId: account.accountId,
|
|
1075
|
-
docId: result.docId,
|
|
1076
|
-
summary: "在线表格属性已修改",
|
|
1077
|
-
raw: result.raw,
|
|
1078
|
-
});
|
|
1079
|
-
}
|
|
1080
|
-
case "smartsheet_add_records": {
|
|
1081
|
-
const result = await docClient.smartTableOperate({
|
|
1082
|
-
agent: account,
|
|
1083
|
-
docId: params.docId,
|
|
1084
|
-
operation: "add_records",
|
|
1085
|
-
bodyData: params,
|
|
1086
|
-
});
|
|
1087
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格记录已添加", raw: result.raw });
|
|
1088
|
-
}
|
|
1089
|
-
case "smartsheet_update_records": {
|
|
1090
|
-
const result = await docClient.smartTableOperate({
|
|
1091
|
-
agent: account,
|
|
1092
|
-
docId: params.docId,
|
|
1093
|
-
operation: "update_records",
|
|
1094
|
-
bodyData: params,
|
|
1095
|
-
});
|
|
1096
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格记录已更新", raw: result.raw });
|
|
1097
|
-
}
|
|
1098
|
-
case "smartsheet_del_records": {
|
|
1099
|
-
const result = await docClient.smartTableOperate({
|
|
1100
|
-
agent: account,
|
|
1101
|
-
docId: params.docId,
|
|
1102
|
-
operation: "del_records",
|
|
1103
|
-
bodyData: params,
|
|
1104
|
-
});
|
|
1105
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格记录已删除", raw: result.raw });
|
|
1106
|
-
}
|
|
1107
|
-
case "smartsheet_get_records": {
|
|
1108
|
-
const result = await docClient.smartTableOperate({
|
|
1109
|
-
agent: account,
|
|
1110
|
-
docId: params.docId,
|
|
1111
|
-
operation: "get_records",
|
|
1112
|
-
bodyData: params,
|
|
1113
|
-
});
|
|
1114
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格记录已获取", raw: result.raw });
|
|
1115
|
-
}
|
|
1116
|
-
case "smartsheet_add_sheet": {
|
|
1117
|
-
const result = await docClient.smartTableAddSheet({ agent: account, ...params });
|
|
1118
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格子表已添加", raw: result.raw });
|
|
1119
|
-
}
|
|
1120
|
-
case "smartsheet_del_sheet": {
|
|
1121
|
-
const result = await docClient.smartTableDelSheet({ agent: account, ...params });
|
|
1122
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格子表已删除", raw: result.raw });
|
|
1123
|
-
}
|
|
1124
|
-
case "smartsheet_update_sheet": {
|
|
1125
|
-
const result = await docClient.smartTableUpdateSheet({ agent: account, ...params });
|
|
1126
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格子表已更新", raw: result.raw });
|
|
1127
|
-
}
|
|
1128
|
-
case "smartsheet_add_view": {
|
|
1129
|
-
const result = await docClient.smartTableAddView({ agent: account, ...params });
|
|
1130
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格视图已添加", raw: result.raw });
|
|
1131
|
-
}
|
|
1132
|
-
case "smartsheet_del_view": {
|
|
1133
|
-
const result = await docClient.smartTableDelView({ agent: account, ...params });
|
|
1134
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格视图已删除", raw: result.raw });
|
|
1135
|
-
}
|
|
1136
|
-
case "smartsheet_get_views": {
|
|
1137
|
-
const result = await docClient.smartTableOperate({ agent: account, docId: params.docId, operation: "get_views", bodyData: { sheet_id: params.sheetId } });
|
|
1138
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格视图列表已获取", raw: result.raw });
|
|
1139
|
-
}
|
|
1140
|
-
case "smartsheet_add_fields": {
|
|
1141
|
-
const result = await docClient.smartTableAddFields({ agent: account, ...params });
|
|
1142
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格字段已添加", raw: result.raw });
|
|
1143
|
-
}
|
|
1144
|
-
case "smartsheet_del_fields": {
|
|
1145
|
-
const result = await docClient.smartTableDelFields({ agent: account, ...params });
|
|
1146
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格字段已删除", raw: result.raw });
|
|
1147
|
-
}
|
|
1148
|
-
case "smartsheet_update_fields": {
|
|
1149
|
-
const result = await docClient.smartTableUpdateFields({ agent: account, ...params });
|
|
1150
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格字段已更新", raw: result.raw });
|
|
1151
|
-
}
|
|
1152
|
-
case "smartsheet_update_view": {
|
|
1153
|
-
const result = await docClient.smartTableUpdateView({ agent: account, ...params });
|
|
1154
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格视图已更新", raw: result.raw });
|
|
1155
|
-
}
|
|
1156
|
-
case "smartsheet_get_fields": {
|
|
1157
|
-
const result = await docClient.smartTableOperate({ agent: account, docId: params.docId, operation: "get_fields", bodyData: { sheet_id: params.sheetId, view_id: params.view_id } });
|
|
1158
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格字段列表已获取", raw: result.raw });
|
|
1159
|
-
}
|
|
1160
|
-
case "smartsheet_add_group": {
|
|
1161
|
-
const result = await docClient.smartTableAddGroup({ agent: account, ...params });
|
|
1162
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格编组已添加", raw: result.raw });
|
|
1163
|
-
}
|
|
1164
|
-
case "smartsheet_del_group": {
|
|
1165
|
-
const result = await docClient.smartTableDelGroup({ agent: account, ...params });
|
|
1166
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格编组已删除", raw: result.raw });
|
|
1167
|
-
}
|
|
1168
|
-
case "smartsheet_update_group": {
|
|
1169
|
-
const result = await docClient.smartTableUpdateGroup({ agent: account, ...params });
|
|
1170
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格编组已更新", raw: result.raw });
|
|
1171
|
-
}
|
|
1172
|
-
case "smartsheet_get_groups": {
|
|
1173
|
-
const result = await docClient.smartTableGetGroups({ agent: account, ...params });
|
|
1174
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格编组列表已获取", raw: result.raw });
|
|
1175
|
-
}
|
|
1176
|
-
case "smartsheet_add_external_records": {
|
|
1177
|
-
const result = await docClient.smartTableAddExternalRecords({ agent: account, ...params });
|
|
1178
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格外部记录已添加", raw: result.raw });
|
|
1179
|
-
}
|
|
1180
|
-
case "smartsheet_update_external_records": {
|
|
1181
|
-
const result = await docClient.smartTableUpdateExternalRecords({ agent: account, ...params });
|
|
1182
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格外部记录已更新", raw: result.raw });
|
|
1183
|
-
}
|
|
1184
|
-
case "smartsheet_add_records": {
|
|
1185
|
-
const result = await docClient.smartTableAddRecords({ agent: account, ...params });
|
|
1186
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格记录已添加", raw: result.raw });
|
|
1187
|
-
}
|
|
1188
|
-
case "smartsheet_update_records": {
|
|
1189
|
-
const result = await docClient.smartTableUpdateRecords({ agent: account, ...params });
|
|
1190
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格记录已更新", raw: result.raw });
|
|
1191
|
-
}
|
|
1192
|
-
case "smartsheet_del_records": {
|
|
1193
|
-
const result = await docClient.smartTableDelRecords({ agent: account, ...params });
|
|
1194
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格记录已删除", raw: result.raw });
|
|
1195
|
-
}
|
|
1196
|
-
case "smartsheet_get_records": {
|
|
1197
|
-
const result = await docClient.smartTableGetRecords({ agent: account, ...params });
|
|
1198
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格记录列表已获取", raw: result.raw });
|
|
1199
|
-
}
|
|
1200
|
-
case "smartsheet_get_sheets": {
|
|
1201
|
-
const result = await docClient.smartTableGetSheets({
|
|
1202
|
-
agent: account,
|
|
1203
|
-
docId: params.docId,
|
|
1204
|
-
});
|
|
1205
|
-
return buildToolResult({
|
|
1206
|
-
ok: true,
|
|
1207
|
-
action: "smartsheet_get_sheets",
|
|
1208
|
-
accountId: account.accountId,
|
|
1209
|
-
docId: params.docId,
|
|
1210
|
-
summary: `智能表格子表列表已获取:${result.sheets.length} 个`,
|
|
1211
|
-
raw: result.raw,
|
|
1212
|
-
});
|
|
1213
|
-
}
|
|
1214
|
-
case "smartsheet_get_sheet_priv": {
|
|
1215
|
-
const result = await docClient.smartTableGetSheetPriv({ agent: account, ...params });
|
|
1216
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格子表权限已获取", raw: result.raw });
|
|
1217
|
-
}
|
|
1218
|
-
case "smartsheet_update_sheet_priv": {
|
|
1219
|
-
const result = await docClient.smartTableUpdateSheetPriv({ agent: account, ...params });
|
|
1220
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格子表权限已更新", raw: result.raw });
|
|
1221
|
-
}
|
|
1222
|
-
case "smartsheet_create_rule": {
|
|
1223
|
-
const result = await docClient.smartTableCreateRule({ agent: account, ...params });
|
|
1224
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: `智能表格成员额外权限规则已创建 (rule_id: ${result.rule_id})`, raw: result.raw });
|
|
1225
|
-
}
|
|
1226
|
-
case "smartsheet_mod_rule_member": {
|
|
1227
|
-
const result = await docClient.smartTableModRuleMember({ agent: account, ...params });
|
|
1228
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格成员额外权限成员已更新", raw: result.raw });
|
|
1229
|
-
}
|
|
1230
|
-
case "smartsheet_delete_rule": {
|
|
1231
|
-
const result = await docClient.smartTableDeleteRule({ agent: account, ...params });
|
|
1232
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, docId: params.docId, summary: "智能表格成员额外权限规则已删除", raw: result.raw });
|
|
1233
|
-
}
|
|
1234
|
-
case "doc_assign_advanced_account": {
|
|
1235
|
-
const result = await docClient.assignDocAdvancedAccount({ agent: account, userid_list: params.userid_list });
|
|
1236
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, summary: summarizeAdvancedAccount(result.raw, "assign"), raw: result.raw });
|
|
1237
|
-
}
|
|
1238
|
-
case "doc_cancel_advanced_account": {
|
|
1239
|
-
const result = await docClient.cancelDocAdvancedAccount({ agent: account, userid_list: params.userid_list });
|
|
1240
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, summary: summarizeAdvancedAccount(result.raw, "cancel"), raw: result.raw });
|
|
1241
|
-
}
|
|
1242
|
-
case "doc_get_advanced_account_list": {
|
|
1243
|
-
const result = await docClient.getDocAdvancedAccountList({ agent: account, ...params });
|
|
1244
|
-
return buildToolResult({ ok: true, action, accountId: account.accountId, summary: summarizeAdvancedAccount(result, "list"), raw: result.raw });
|
|
1245
|
-
}
|
|
1246
|
-
case "upload_doc_image": {
|
|
1247
|
-
const filePath = params.file_path;
|
|
1248
|
-
if (!fs.existsSync(filePath)) {
|
|
1249
|
-
throw new Error(`File not found: ${filePath}`);
|
|
1250
|
-
}
|
|
1251
|
-
const fileContent = fs.readFileSync(filePath);
|
|
1252
|
-
const base64Content = fileContent.toString("base64");
|
|
597
|
+
if (isImageItem(item)) {
|
|
598
|
+
// Insert image
|
|
599
|
+
const imgUrl = getImageUrl(item);
|
|
1253
600
|
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
601
|
+
try {
|
|
602
|
+
// Upload image to WeCom
|
|
603
|
+
const base64 = await getImageAsBase64(imgUrl);
|
|
604
|
+
const uploadResult = await docClient.uploadDocImage({
|
|
605
|
+
agent: account,
|
|
606
|
+
docId: result.docId,
|
|
607
|
+
base64_content: base64,
|
|
1258
608
|
});
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
609
|
+
console.log(
|
|
610
|
+
`[wecom-doc] Item ${i} image uploaded: ${uploadResult.width}x${uploadResult.height}`,
|
|
611
|
+
);
|
|
612
|
+
|
|
613
|
+
// Step 2: Create new paragraph and insert image in one batch (2 operations ≤ 30)
|
|
614
|
+
// Per API spec: all indices are based on the same document snapshot
|
|
615
|
+
// insert_paragraph at docEndIndex creates a new paragraph
|
|
616
|
+
// insert_image at docEndIndex + 1 inserts into the newly created paragraph
|
|
617
|
+
await docClient.updateDocContent({
|
|
618
|
+
agent: account,
|
|
619
|
+
docId: result.docId,
|
|
620
|
+
version: currentVersion, // Pass version for concurrency control
|
|
621
|
+
requests: [
|
|
622
|
+
{
|
|
623
|
+
insert_paragraph: {
|
|
624
|
+
location: { index: docEndIndex },
|
|
625
|
+
},
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
insert_image: {
|
|
629
|
+
image_id: uploadResult.url,
|
|
630
|
+
location: { index: docEndIndex + 1 },
|
|
631
|
+
width: uploadResult.width,
|
|
632
|
+
height: uploadResult.height,
|
|
633
|
+
},
|
|
1269
634
|
},
|
|
1270
|
-
|
|
635
|
+
],
|
|
1271
636
|
});
|
|
637
|
+
} catch (uploadErr) {
|
|
638
|
+
console.error(`Failed to upload image ${imgUrl}:`, uploadErr);
|
|
639
|
+
throw new Error(
|
|
640
|
+
`Image upload failed: ${uploadErr instanceof Error ? uploadErr.message : String(uploadErr)}`,
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
} else {
|
|
644
|
+
const text = getText(item);
|
|
645
|
+
if (!text) continue;
|
|
646
|
+
|
|
647
|
+
// Insert text: create paragraph and insert text in one batch (2 operations ≤ 30)
|
|
648
|
+
// Per API spec: all indices are based on the same document snapshot
|
|
649
|
+
// insert_paragraph at docEndIndex creates a new paragraph
|
|
650
|
+
// insert_text at docEndIndex + 1 inserts into the newly created paragraph
|
|
651
|
+
await docClient.updateDocContent({
|
|
652
|
+
agent: account,
|
|
653
|
+
docId: result.docId,
|
|
654
|
+
version: currentVersion, // Pass version for concurrency control
|
|
655
|
+
requests: [
|
|
656
|
+
{
|
|
657
|
+
insert_paragraph: {
|
|
658
|
+
location: { index: docEndIndex },
|
|
659
|
+
},
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
insert_text: {
|
|
663
|
+
text: text,
|
|
664
|
+
location: { index: docEndIndex + 1 },
|
|
665
|
+
},
|
|
666
|
+
},
|
|
667
|
+
],
|
|
668
|
+
});
|
|
1272
669
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
670
|
+
}
|
|
671
|
+
contentResult = "init_content_populated";
|
|
672
|
+
} catch (err) {
|
|
673
|
+
contentResult = `content_failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
1275
674
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
let accessResult: any = null;
|
|
678
|
+
if (
|
|
679
|
+
(Array.isArray(params.viewers) && params.viewers.length > 0) ||
|
|
680
|
+
explicitCollaborators.length > 0
|
|
681
|
+
) {
|
|
682
|
+
try {
|
|
683
|
+
accessResult = await docClient.grantDocAccess({
|
|
684
|
+
agent: account,
|
|
685
|
+
docId: result.docId,
|
|
686
|
+
viewers: params.viewers,
|
|
687
|
+
collaborators: explicitCollaborators,
|
|
688
|
+
});
|
|
689
|
+
} catch (err) {
|
|
690
|
+
return buildToolResult({
|
|
691
|
+
ok: false,
|
|
692
|
+
partial: true,
|
|
693
|
+
action: "create",
|
|
694
|
+
accountId: account.accountId,
|
|
695
|
+
resourceType: result.docTypeLabel,
|
|
696
|
+
canonicalDocId: result.docId,
|
|
697
|
+
docId: result.docId,
|
|
698
|
+
title: readString(params.docName),
|
|
699
|
+
url: result.url || undefined,
|
|
700
|
+
summary: `已创建${mapDocTypeLabel(result.docType)}"${readString(params.docName)}"(docId: ${result.docId}),但权限授予失败`,
|
|
701
|
+
usageHint: buildDocIdUsageHint(result.docId) || undefined,
|
|
702
|
+
error: err instanceof Error ? err.message : String(err),
|
|
703
|
+
raw: { create: result.raw },
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
return buildToolResult({
|
|
708
|
+
ok: true,
|
|
709
|
+
action: "create",
|
|
710
|
+
accountId: account.accountId,
|
|
711
|
+
resourceType: result.docTypeLabel,
|
|
712
|
+
canonicalDocId: result.docId,
|
|
713
|
+
docId: result.docId,
|
|
714
|
+
title: readString(params.docName),
|
|
715
|
+
url: result.url || undefined,
|
|
716
|
+
summary: accessResult
|
|
717
|
+
? `已创建${mapDocTypeLabel(result.docType)}"${readString(params.docName)}"(docId: ${result.docId});${summarizeDocAccess(accessResult)}` +
|
|
718
|
+
(contentResult ? `;内容填充: ${contentResult}` : "")
|
|
719
|
+
: `已创建${mapDocTypeLabel(result.docType)}"${readString(params.docName)}"(docId: ${result.docId})` +
|
|
720
|
+
(contentResult ? `;内容填充: ${contentResult}` : ""),
|
|
721
|
+
usageHint: buildDocIdUsageHint(result.docId) || undefined,
|
|
722
|
+
raw: accessResult ? { create: result.raw, access: accessResult.raw } : result.raw,
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
case "rename": {
|
|
726
|
+
const result = await docClient.renameDoc({
|
|
727
|
+
agent: account,
|
|
728
|
+
docId: params.docId,
|
|
729
|
+
newName: params.newName,
|
|
730
|
+
});
|
|
731
|
+
return buildToolResult({
|
|
732
|
+
ok: true,
|
|
733
|
+
action: "rename",
|
|
734
|
+
accountId: account.accountId,
|
|
735
|
+
docId: result.docId,
|
|
736
|
+
title: result.newName,
|
|
737
|
+
summary: `文档已重命名为"${result.newName}"`,
|
|
738
|
+
raw: result.raw,
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
case "copy": {
|
|
742
|
+
const result = await docClient.copyDoc({
|
|
743
|
+
agent: account,
|
|
744
|
+
docId: params.docId,
|
|
745
|
+
newName: params.newName,
|
|
746
|
+
spaceId: params.spaceId,
|
|
747
|
+
fatherId: params.fatherId,
|
|
748
|
+
});
|
|
749
|
+
return buildToolResult({
|
|
750
|
+
ok: true,
|
|
751
|
+
action: "copy",
|
|
752
|
+
accountId: account.accountId,
|
|
753
|
+
docId: result.docId,
|
|
754
|
+
summary: `文档已成功复制,新 docId: ${result.docId}`,
|
|
755
|
+
raw: result.raw,
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
case "get_info": {
|
|
759
|
+
const result = await docClient.getDocBaseInfo({
|
|
760
|
+
agent: account,
|
|
761
|
+
docId: params.docId,
|
|
762
|
+
});
|
|
763
|
+
return buildToolResult({
|
|
764
|
+
ok: true,
|
|
765
|
+
action: "get_info",
|
|
766
|
+
accountId: account.accountId,
|
|
767
|
+
docId: params.docId,
|
|
768
|
+
title: readString(result.info?.doc_name) || undefined,
|
|
769
|
+
resourceType:
|
|
770
|
+
Number(result.info?.doc_type) === 10
|
|
771
|
+
? "smart_table"
|
|
772
|
+
: Number(result.info?.doc_type) === 4
|
|
773
|
+
? "spreadsheet"
|
|
774
|
+
: "doc",
|
|
775
|
+
summary: summarizeDocInfo(result.info),
|
|
776
|
+
raw: result.raw,
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
case "share": {
|
|
780
|
+
const result = await docClient.shareDoc({
|
|
781
|
+
agent: account,
|
|
782
|
+
docId: params.docId,
|
|
783
|
+
});
|
|
784
|
+
return buildToolResult({
|
|
785
|
+
ok: true,
|
|
786
|
+
action: "share",
|
|
787
|
+
accountId: account.accountId,
|
|
788
|
+
canonicalDocId: params.docId,
|
|
789
|
+
docId: params.docId,
|
|
790
|
+
url: result.shareUrl || undefined,
|
|
791
|
+
summary: result.shareUrl
|
|
792
|
+
? `文档分享链接已获取(docId: ${params.docId})`
|
|
793
|
+
: `文档分享接口调用成功(docId: ${params.docId})`,
|
|
794
|
+
usageHint: buildDocIdUsageHint(params.docId) || undefined,
|
|
795
|
+
raw: result.raw,
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
case "get_auth": {
|
|
799
|
+
const result = await docClient.getDocAuth({
|
|
800
|
+
agent: account,
|
|
801
|
+
docId: params.docId,
|
|
802
|
+
});
|
|
803
|
+
const diagnosis = buildDocAuthDiagnosis(result, toolContext?.senderId);
|
|
804
|
+
return buildToolResult({
|
|
805
|
+
ok: true,
|
|
806
|
+
action: "get_auth",
|
|
807
|
+
accountId: account.accountId,
|
|
808
|
+
canonicalDocId: params.docId,
|
|
809
|
+
docId: params.docId,
|
|
810
|
+
summary: summarizeDocAuth(result),
|
|
811
|
+
diagnosis,
|
|
812
|
+
raw: result.raw,
|
|
813
|
+
});
|
|
1287
814
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
815
|
+
case "diagnose_auth": {
|
|
816
|
+
const result = await docClient.getDocAuth({
|
|
817
|
+
agent: account,
|
|
818
|
+
docId: params.docId,
|
|
819
|
+
});
|
|
820
|
+
const diagnosis = buildDocAuthDiagnosis(result, toolContext?.senderId);
|
|
821
|
+
return buildToolResult({
|
|
822
|
+
ok: true,
|
|
823
|
+
action: "diagnose_auth",
|
|
824
|
+
accountId: account.accountId,
|
|
825
|
+
canonicalDocId: params.docId,
|
|
826
|
+
docId: params.docId,
|
|
827
|
+
summary: summarizeDocAuthDiagnosis(diagnosis),
|
|
828
|
+
diagnosis,
|
|
829
|
+
raw: result.raw,
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
case "validate_share_link": {
|
|
833
|
+
const result = await inspectWecomShareLink({
|
|
834
|
+
shareUrl: params.shareUrl,
|
|
835
|
+
});
|
|
836
|
+
return buildToolResult({
|
|
837
|
+
ok: true,
|
|
838
|
+
action: "validate_share_link",
|
|
839
|
+
accountId: account.accountId,
|
|
840
|
+
url: result.diagnosis.finalUrl || params.shareUrl,
|
|
841
|
+
summary: summarizeShareLinkDiagnosis(result.diagnosis),
|
|
842
|
+
diagnosis: result.diagnosis,
|
|
843
|
+
raw: result.raw,
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
case "delete": {
|
|
847
|
+
const result = await docClient.deleteDoc({
|
|
848
|
+
agent: account,
|
|
849
|
+
docId: params.docId,
|
|
850
|
+
formId: params.formId,
|
|
851
|
+
});
|
|
852
|
+
return buildToolResult({
|
|
853
|
+
ok: true,
|
|
854
|
+
action: "delete",
|
|
855
|
+
accountId: account.accountId,
|
|
856
|
+
docId: result.docId || undefined,
|
|
857
|
+
formId: result.formId || undefined,
|
|
858
|
+
summary: result.formId ? "收集表已删除" : "文档已删除",
|
|
859
|
+
raw: result.raw,
|
|
860
|
+
});
|
|
861
|
+
}
|
|
862
|
+
case "set_join_rule": {
|
|
863
|
+
const result = await docClient.setDocJoinRule({
|
|
864
|
+
agent: account,
|
|
865
|
+
docId: params.docId,
|
|
866
|
+
request: params.request,
|
|
867
|
+
});
|
|
868
|
+
return buildToolResult({
|
|
869
|
+
ok: true,
|
|
870
|
+
action: "set_join_rule",
|
|
871
|
+
accountId: account.accountId,
|
|
872
|
+
docId: result.docId,
|
|
873
|
+
summary: "文档查看规则已更新",
|
|
874
|
+
raw: result.raw,
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
case "set_member_auth": {
|
|
878
|
+
const result = await docClient.setDocMemberAuth({
|
|
879
|
+
agent: account,
|
|
880
|
+
docId: params.docId,
|
|
881
|
+
request: params.request,
|
|
882
|
+
});
|
|
883
|
+
return buildToolResult({
|
|
884
|
+
ok: true,
|
|
885
|
+
action: "set_member_auth",
|
|
886
|
+
accountId: account.accountId,
|
|
887
|
+
docId: result.docId,
|
|
888
|
+
summary: "文档通知范围及成员权限已更新",
|
|
889
|
+
raw: result.raw,
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
case "grant_access": {
|
|
893
|
+
const result = await docClient.grantDocAccess({
|
|
894
|
+
agent: account,
|
|
895
|
+
docId: params.docId,
|
|
896
|
+
viewers: params.viewers,
|
|
897
|
+
collaborators: params.collaborators,
|
|
898
|
+
removeViewers: params.removeViewers,
|
|
899
|
+
removeCollaborators: params.removeCollaborators,
|
|
900
|
+
authLevel: params.auth,
|
|
901
|
+
});
|
|
902
|
+
return buildToolResult({
|
|
903
|
+
ok: true,
|
|
904
|
+
action: "grant_access",
|
|
905
|
+
accountId: account.accountId,
|
|
906
|
+
docId: result.docId,
|
|
907
|
+
summary: summarizeDocAccess(result),
|
|
908
|
+
raw: result.raw,
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
case "add_collaborators": {
|
|
912
|
+
const result = await docClient.addDocCollaborators({
|
|
913
|
+
agent: account,
|
|
914
|
+
docId: params.docId,
|
|
915
|
+
collaborators: params.collaborators,
|
|
916
|
+
auth: params.auth,
|
|
917
|
+
});
|
|
918
|
+
return buildToolResult({
|
|
919
|
+
ok: true,
|
|
920
|
+
action: "add_collaborators",
|
|
921
|
+
accountId: account.accountId,
|
|
922
|
+
docId: result.docId,
|
|
923
|
+
summary: `协作者已添加:${result.addedCollaboratorCount ?? 0}`,
|
|
924
|
+
raw: result.raw,
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
case "get_content": {
|
|
928
|
+
const result = await docClient.getDocContent({
|
|
929
|
+
agent: account,
|
|
930
|
+
docId: params.docId,
|
|
931
|
+
});
|
|
932
|
+
return buildToolResult({
|
|
933
|
+
ok: true,
|
|
934
|
+
action: "get_content",
|
|
935
|
+
accountId: account.accountId,
|
|
936
|
+
docId: params.docId,
|
|
937
|
+
summary: "文档内容已获取",
|
|
938
|
+
raw: result.raw,
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
case "update_content": {
|
|
942
|
+
const result = await docClient.updateDocContent({
|
|
943
|
+
agent: account,
|
|
944
|
+
docId: params.docId,
|
|
945
|
+
requests: params.requests,
|
|
946
|
+
version: params.version,
|
|
947
|
+
});
|
|
948
|
+
|
|
949
|
+
const batchCount = result.batches ?? 1;
|
|
950
|
+
return buildToolResult({
|
|
951
|
+
ok: true,
|
|
952
|
+
action: "update_content",
|
|
953
|
+
accountId: account.accountId,
|
|
954
|
+
docId: params.docId,
|
|
955
|
+
summary:
|
|
956
|
+
batchCount > 1
|
|
957
|
+
? `文档内容已更新(自动分批,共${batchCount}批)`
|
|
958
|
+
: "文档内容已更新",
|
|
959
|
+
batches: batchCount,
|
|
960
|
+
raw: result.raw,
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
case "set_safety_setting": {
|
|
964
|
+
const result = await docClient.setDocSafetySetting({
|
|
965
|
+
agent: account,
|
|
966
|
+
docId: params.docId,
|
|
967
|
+
request: params.request,
|
|
968
|
+
});
|
|
969
|
+
return buildToolResult({
|
|
970
|
+
ok: true,
|
|
971
|
+
action: "set_safety_setting",
|
|
972
|
+
accountId: account.accountId,
|
|
973
|
+
docId: result.docId,
|
|
974
|
+
summary: "文档安全设置已更新",
|
|
975
|
+
raw: result.raw,
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
case "get_doc_security_setting": {
|
|
979
|
+
const result = await docClient.getDocAuth({
|
|
980
|
+
agent: account,
|
|
981
|
+
docId: params.docId,
|
|
982
|
+
});
|
|
983
|
+
return buildToolResult({
|
|
984
|
+
ok: true,
|
|
985
|
+
action: "get_doc_security_setting",
|
|
986
|
+
accountId: account.accountId,
|
|
987
|
+
docId: params.docId,
|
|
988
|
+
summary: "文档安全设置已获取",
|
|
989
|
+
details: result.secureSetting,
|
|
990
|
+
raw: result.raw,
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
case "mod_doc_security_setting": {
|
|
994
|
+
// Alias to setDocSafetySetting logic
|
|
995
|
+
const result = await docClient.setDocSafetySetting({
|
|
996
|
+
agent: account,
|
|
997
|
+
docId: params.docId,
|
|
998
|
+
request: params.setting,
|
|
999
|
+
});
|
|
1000
|
+
return buildToolResult({
|
|
1001
|
+
ok: true,
|
|
1002
|
+
action: "mod_doc_security_setting",
|
|
1003
|
+
accountId: account.accountId,
|
|
1004
|
+
docId: result.docId,
|
|
1005
|
+
summary: "文档安全设置已更新",
|
|
1006
|
+
raw: result.raw,
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
case "mod_doc_member_notified_scope": {
|
|
1010
|
+
const result = await docClient.modDocMemberNotifiedScope({
|
|
1011
|
+
agent: account,
|
|
1012
|
+
docId: params.docId,
|
|
1013
|
+
notified_scope_type: params.notified_scope_type,
|
|
1014
|
+
notified_member_list: params.notified_member_list,
|
|
1015
|
+
});
|
|
1016
|
+
return buildToolResult({
|
|
1017
|
+
ok: true,
|
|
1018
|
+
action: "mod_doc_member_notified_scope",
|
|
1019
|
+
accountId: account.accountId,
|
|
1020
|
+
docId: params.docId,
|
|
1021
|
+
summary: "文档成员通知范围已更新",
|
|
1022
|
+
raw: result,
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
case "create_form": {
|
|
1026
|
+
// 创建收集表(表单)
|
|
1027
|
+
try {
|
|
1028
|
+
const result = await docClient.createCollect({
|
|
1029
|
+
agent: account,
|
|
1030
|
+
formInfo: params.formInfo,
|
|
1031
|
+
spaceId: params.spaceId,
|
|
1032
|
+
fatherId: params.fatherId,
|
|
1033
|
+
});
|
|
1034
|
+
const title = readString(result.title);
|
|
1035
|
+
return buildToolResult({
|
|
1036
|
+
ok: true,
|
|
1037
|
+
action: "create_form",
|
|
1038
|
+
accountId: account.accountId,
|
|
1039
|
+
formId: result.formId,
|
|
1040
|
+
title: title || undefined,
|
|
1041
|
+
summary: title
|
|
1042
|
+
? `已创建收集表"${title}"(formId: ${result.formId})`
|
|
1043
|
+
: `已创建收集表(formId: ${result.formId})`,
|
|
1044
|
+
raw: result.raw,
|
|
1045
|
+
});
|
|
1046
|
+
} catch (err) {
|
|
1047
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
1048
|
+
return buildToolResult({
|
|
1049
|
+
ok: false,
|
|
1050
|
+
action: "create_form",
|
|
1051
|
+
accountId: account.accountId,
|
|
1052
|
+
error: errorMsg,
|
|
1053
|
+
summary: "创建收集表失败",
|
|
1054
|
+
raw: {},
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
case "modify_form": {
|
|
1059
|
+
const result = await docClient.modifyCollect({
|
|
1060
|
+
agent: account,
|
|
1061
|
+
oper: params.oper,
|
|
1062
|
+
formId: params.formId,
|
|
1063
|
+
formInfo: params.formInfo,
|
|
1064
|
+
});
|
|
1065
|
+
const title = readString(result.title);
|
|
1066
|
+
return buildToolResult({
|
|
1067
|
+
ok: true,
|
|
1068
|
+
action: "modify_form",
|
|
1069
|
+
accountId: account.accountId,
|
|
1070
|
+
formId: result.formId,
|
|
1071
|
+
title: title || undefined,
|
|
1072
|
+
summary: title
|
|
1073
|
+
? `收集表已更新(${result.oper}):"${title}"`
|
|
1074
|
+
: `收集表已更新(${result.oper})`,
|
|
1075
|
+
raw: result.raw,
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
case "get_form_info": {
|
|
1079
|
+
const result = await docClient.getFormInfo({
|
|
1080
|
+
agent: account,
|
|
1081
|
+
formId: params.formId,
|
|
1082
|
+
});
|
|
1083
|
+
return buildToolResult({
|
|
1084
|
+
ok: true,
|
|
1085
|
+
action: "get_form_info",
|
|
1086
|
+
accountId: account.accountId,
|
|
1087
|
+
formId: params.formId,
|
|
1088
|
+
title: readString(result.formInfo?.form_title) || undefined,
|
|
1089
|
+
summary: summarizeFormInfo(result),
|
|
1090
|
+
raw: result.raw,
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
case "get_form_answer": {
|
|
1094
|
+
const result = await docClient.getFormAnswer({
|
|
1095
|
+
agent: account,
|
|
1096
|
+
repeatedId: params.repeatedId,
|
|
1097
|
+
answerIds: params.answerIds,
|
|
1098
|
+
});
|
|
1099
|
+
return buildToolResult({
|
|
1100
|
+
ok: true,
|
|
1101
|
+
action: "get_form_answer",
|
|
1102
|
+
accountId: account.accountId,
|
|
1103
|
+
repeatedId: params.repeatedId,
|
|
1104
|
+
summary: summarizeFormAnswer(result),
|
|
1105
|
+
raw: result.raw,
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
case "get_form_statistic": {
|
|
1109
|
+
const result = await docClient.getFormStatistic({
|
|
1110
|
+
agent: account,
|
|
1111
|
+
requests: params.requests,
|
|
1112
|
+
});
|
|
1113
|
+
return buildToolResult({
|
|
1114
|
+
ok: true,
|
|
1115
|
+
action: "get_form_statistic",
|
|
1116
|
+
accountId: account.accountId,
|
|
1117
|
+
summary: summarizeFormStatistic(result),
|
|
1118
|
+
raw: result.raw,
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
case "get_sheet_properties": {
|
|
1122
|
+
const result = await docClient.getSheetProperties({
|
|
1123
|
+
agent: account,
|
|
1124
|
+
docId: params.docId,
|
|
1125
|
+
});
|
|
1126
|
+
return buildToolResult({
|
|
1127
|
+
ok: true,
|
|
1128
|
+
action: "get_sheet_properties",
|
|
1129
|
+
accountId: account.accountId,
|
|
1130
|
+
docId: params.docId,
|
|
1131
|
+
summary: summarizeSheetProperties(result),
|
|
1132
|
+
raw: result.raw,
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
case "edit_sheet_data": {
|
|
1136
|
+
const result = await docClient.editSheetData({
|
|
1137
|
+
agent: account,
|
|
1138
|
+
docId: params.docId,
|
|
1139
|
+
sheetId: params.sheetId,
|
|
1140
|
+
startRow: params.startRow ?? 0,
|
|
1141
|
+
startColumn: params.startColumn ?? 0,
|
|
1142
|
+
gridData: params.gridData,
|
|
1143
|
+
requests: params.requests, // Support direct requests for multiple operations
|
|
1144
|
+
});
|
|
1145
|
+
const summary = result.operations
|
|
1146
|
+
? `在线表格已更新(${result.operations}个操作)`
|
|
1147
|
+
: "在线表格数据已编辑";
|
|
1148
|
+
return buildToolResult({
|
|
1149
|
+
ok: true,
|
|
1150
|
+
action: "edit_sheet_data",
|
|
1151
|
+
accountId: account.accountId,
|
|
1152
|
+
docId: result.docId,
|
|
1153
|
+
summary: summary,
|
|
1154
|
+
operations: result.operations,
|
|
1155
|
+
updatedCells: result.updatedCells,
|
|
1156
|
+
raw: result.raw,
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
case "get_sheet_data": {
|
|
1160
|
+
const result = await docClient.getSheetData({
|
|
1161
|
+
agent: account,
|
|
1162
|
+
docId: params.docId,
|
|
1163
|
+
sheetId: params.sheetId,
|
|
1164
|
+
range: params.range,
|
|
1165
|
+
});
|
|
1166
|
+
return buildToolResult({
|
|
1167
|
+
ok: true,
|
|
1168
|
+
action: "get_sheet_data",
|
|
1169
|
+
accountId: account.accountId,
|
|
1170
|
+
docId: params.docId,
|
|
1171
|
+
summary: "在线表格数据已读取",
|
|
1172
|
+
data: result.data,
|
|
1173
|
+
raw: result.raw,
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
case "modify_sheet_properties": {
|
|
1177
|
+
const result = await docClient.modifySheetProperties({
|
|
1178
|
+
agent: account,
|
|
1179
|
+
docId: params.docId,
|
|
1180
|
+
requests: params.requests,
|
|
1181
|
+
});
|
|
1182
|
+
return buildToolResult({
|
|
1183
|
+
ok: true,
|
|
1184
|
+
action: "modify_sheet_properties",
|
|
1185
|
+
accountId: account.accountId,
|
|
1186
|
+
docId: result.docId,
|
|
1187
|
+
summary: "在线表格属性已修改",
|
|
1188
|
+
raw: result.raw,
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
case "smartsheet_add_records": {
|
|
1192
|
+
const result = await docClient.smartTableOperate({
|
|
1193
|
+
agent: account,
|
|
1194
|
+
docId: params.docId,
|
|
1195
|
+
operation: "add_records",
|
|
1196
|
+
bodyData: params,
|
|
1197
|
+
});
|
|
1198
|
+
return buildToolResult({
|
|
1199
|
+
ok: true,
|
|
1200
|
+
action,
|
|
1201
|
+
accountId: account.accountId,
|
|
1202
|
+
docId: params.docId,
|
|
1203
|
+
summary: "智能表格记录已添加",
|
|
1204
|
+
raw: result.raw,
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
case "smartsheet_update_records": {
|
|
1208
|
+
const result = await docClient.smartTableOperate({
|
|
1209
|
+
agent: account,
|
|
1210
|
+
docId: params.docId,
|
|
1211
|
+
operation: "update_records",
|
|
1212
|
+
bodyData: params,
|
|
1213
|
+
});
|
|
1214
|
+
return buildToolResult({
|
|
1215
|
+
ok: true,
|
|
1216
|
+
action,
|
|
1217
|
+
accountId: account.accountId,
|
|
1218
|
+
docId: params.docId,
|
|
1219
|
+
summary: "智能表格记录已更新",
|
|
1220
|
+
raw: result.raw,
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
case "smartsheet_del_records": {
|
|
1224
|
+
const result = await docClient.smartTableOperate({
|
|
1225
|
+
agent: account,
|
|
1226
|
+
docId: params.docId,
|
|
1227
|
+
operation: "del_records",
|
|
1228
|
+
bodyData: params,
|
|
1229
|
+
});
|
|
1230
|
+
return buildToolResult({
|
|
1231
|
+
ok: true,
|
|
1232
|
+
action,
|
|
1233
|
+
accountId: account.accountId,
|
|
1234
|
+
docId: params.docId,
|
|
1235
|
+
summary: "智能表格记录已删除",
|
|
1236
|
+
raw: result.raw,
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
1239
|
+
case "smartsheet_get_records": {
|
|
1240
|
+
const result = await docClient.smartTableGetRecords({ agent: account, ...params });
|
|
1241
|
+
return buildToolResult({
|
|
1242
|
+
ok: true,
|
|
1243
|
+
action,
|
|
1244
|
+
accountId: account.accountId,
|
|
1245
|
+
docId: params.docId,
|
|
1246
|
+
summary: result.records?.length
|
|
1247
|
+
? `智能表格记录已获取:${result.records.length} 条`
|
|
1248
|
+
: "智能表格记录列表已获取",
|
|
1249
|
+
total: result.total,
|
|
1250
|
+
has_more: result.has_more,
|
|
1251
|
+
ver: result.ver,
|
|
1252
|
+
raw: result.raw,
|
|
1253
|
+
});
|
|
1254
|
+
}
|
|
1255
|
+
case "smartsheet_get_views": {
|
|
1256
|
+
const result = await docClient.smartTableGetViews({ agent: account, ...params });
|
|
1257
|
+
return buildToolResult({
|
|
1258
|
+
ok: true,
|
|
1259
|
+
action,
|
|
1260
|
+
accountId: account.accountId,
|
|
1261
|
+
docId: params.docId,
|
|
1262
|
+
summary: result.views?.length
|
|
1263
|
+
? `智能表格视图已获取:${result.views.length} 个`
|
|
1264
|
+
: "智能表格视图列表已获取",
|
|
1265
|
+
total: result.total,
|
|
1266
|
+
has_more: result.has_more,
|
|
1267
|
+
raw: result.raw,
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
case "smartsheet_get_sheets": {
|
|
1271
|
+
const result = await docClient.smartTableGetSheets({
|
|
1272
|
+
agent: account,
|
|
1273
|
+
docId: params.docId,
|
|
1274
|
+
sheet_id: params.sheet_id,
|
|
1275
|
+
need_all_type_sheet: params.need_all_type_sheet,
|
|
1276
|
+
});
|
|
1277
|
+
return buildToolResult({
|
|
1278
|
+
ok: true,
|
|
1279
|
+
action: "smartsheet_get_sheets",
|
|
1280
|
+
accountId: account.accountId,
|
|
1281
|
+
docId: params.docId,
|
|
1282
|
+
summary: `智能表格子表列表已获取:${result.sheets.length} 个`,
|
|
1283
|
+
raw: result.raw,
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
case "smartsheet_add_sheet": {
|
|
1287
|
+
const result = await docClient.smartTableAddSheet({ agent: account, ...params });
|
|
1288
|
+
return buildToolResult({
|
|
1289
|
+
ok: true,
|
|
1290
|
+
action,
|
|
1291
|
+
accountId: account.accountId,
|
|
1292
|
+
docId: params.docId,
|
|
1293
|
+
summary: "智能表格子表已添加",
|
|
1294
|
+
raw: result.raw,
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
case "smartsheet_del_sheet": {
|
|
1298
|
+
const result = await docClient.smartTableDelSheet({ agent: account, ...params });
|
|
1299
|
+
return buildToolResult({
|
|
1300
|
+
ok: true,
|
|
1301
|
+
action,
|
|
1302
|
+
accountId: account.accountId,
|
|
1303
|
+
docId: params.docId,
|
|
1304
|
+
summary: "智能表格子表已删除",
|
|
1305
|
+
raw: result.raw,
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1308
|
+
case "smartsheet_update_sheet": {
|
|
1309
|
+
const result = await docClient.smartTableUpdateSheet({ agent: account, ...params });
|
|
1310
|
+
return buildToolResult({
|
|
1311
|
+
ok: true,
|
|
1312
|
+
action,
|
|
1313
|
+
accountId: account.accountId,
|
|
1314
|
+
docId: params.docId,
|
|
1315
|
+
summary: "智能表格子表已更新",
|
|
1316
|
+
raw: result.raw,
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
case "smartsheet_add_view": {
|
|
1320
|
+
const result = await docClient.smartTableAddView({ agent: account, ...params });
|
|
1321
|
+
return buildToolResult({
|
|
1322
|
+
ok: true,
|
|
1323
|
+
action,
|
|
1324
|
+
accountId: account.accountId,
|
|
1325
|
+
docId: params.docId,
|
|
1326
|
+
summary: `智能表格视图已添加:${result.view?.view_title || "未知"}`,
|
|
1327
|
+
raw: result.raw,
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
case "smartsheet_del_view": {
|
|
1331
|
+
const result = await docClient.smartTableDelView({ agent: account, ...params });
|
|
1332
|
+
return buildToolResult({
|
|
1333
|
+
ok: true,
|
|
1334
|
+
action,
|
|
1335
|
+
accountId: account.accountId,
|
|
1336
|
+
docId: params.docId,
|
|
1337
|
+
summary: `智能表格视图已删除:${params.view_ids?.length || 0} 个`,
|
|
1338
|
+
raw: result.raw,
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
case "smartsheet_update_view": {
|
|
1342
|
+
const result = await docClient.smartTableUpdateView({ agent: account, ...params });
|
|
1343
|
+
return buildToolResult({
|
|
1344
|
+
ok: true,
|
|
1345
|
+
action,
|
|
1346
|
+
accountId: account.accountId,
|
|
1347
|
+
docId: params.docId,
|
|
1348
|
+
summary: `智能表格视图已更新:${result.view?.view_title || "未知"}`,
|
|
1349
|
+
raw: result.raw,
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
case "smartsheet_add_fields": {
|
|
1353
|
+
const result = await docClient.smartTableAddFields({ agent: account, ...params });
|
|
1354
|
+
return buildToolResult({
|
|
1355
|
+
ok: true,
|
|
1356
|
+
action,
|
|
1357
|
+
accountId: account.accountId,
|
|
1358
|
+
docId: params.docId,
|
|
1359
|
+
summary: `智能表格字段已添加:${result.fields?.length || 0} 个`,
|
|
1360
|
+
raw: result.raw,
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
case "smartsheet_del_fields": {
|
|
1364
|
+
const result = await docClient.smartTableDelFields({ agent: account, ...params });
|
|
1365
|
+
return buildToolResult({
|
|
1366
|
+
ok: true,
|
|
1367
|
+
action,
|
|
1368
|
+
accountId: account.accountId,
|
|
1369
|
+
docId: params.docId,
|
|
1370
|
+
summary: `智能表格字段已删除:${params.field_ids?.length || 0} 个`,
|
|
1371
|
+
raw: result.raw,
|
|
1372
|
+
});
|
|
1373
|
+
}
|
|
1374
|
+
case "smartsheet_update_fields": {
|
|
1375
|
+
const result = await docClient.smartTableUpdateFields({ agent: account, ...params });
|
|
1376
|
+
return buildToolResult({
|
|
1377
|
+
ok: true,
|
|
1378
|
+
action,
|
|
1379
|
+
accountId: account.accountId,
|
|
1380
|
+
docId: params.docId,
|
|
1381
|
+
summary: `智能表格字段已更新:${result.fields?.length || 0} 个`,
|
|
1382
|
+
raw: result.raw,
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
case "smartsheet_get_fields": {
|
|
1386
|
+
const result = await docClient.smartTableGetFields({ agent: account, ...params });
|
|
1387
|
+
return buildToolResult({
|
|
1388
|
+
ok: true,
|
|
1389
|
+
action,
|
|
1390
|
+
accountId: account.accountId,
|
|
1391
|
+
docId: params.docId,
|
|
1392
|
+
summary: result.fields?.length
|
|
1393
|
+
? `智能表格字段已获取:${result.fields.length} 个`
|
|
1394
|
+
: "智能表格字段列表已获取",
|
|
1395
|
+
total: result.total,
|
|
1396
|
+
has_more: result.has_more,
|
|
1397
|
+
raw: result.raw,
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
case "smartsheet_add_group": {
|
|
1401
|
+
const result = await docClient.smartTableAddGroup({ agent: account, ...params });
|
|
1402
|
+
return buildToolResult({
|
|
1403
|
+
ok: true,
|
|
1404
|
+
action,
|
|
1405
|
+
accountId: account.accountId,
|
|
1406
|
+
docId: params.docId,
|
|
1407
|
+
summary: "智能表格编组已添加",
|
|
1408
|
+
raw: result.raw,
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
case "smartsheet_del_group": {
|
|
1412
|
+
const result = await docClient.smartTableDelGroup({ agent: account, ...params });
|
|
1413
|
+
return buildToolResult({
|
|
1414
|
+
ok: true,
|
|
1415
|
+
action,
|
|
1416
|
+
accountId: account.accountId,
|
|
1417
|
+
docId: params.docId,
|
|
1418
|
+
summary: "智能表格编组已删除",
|
|
1419
|
+
raw: result.raw,
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
case "smartsheet_update_group": {
|
|
1423
|
+
const result = await docClient.smartTableUpdateGroup({ agent: account, ...params });
|
|
1424
|
+
return buildToolResult({
|
|
1425
|
+
ok: true,
|
|
1426
|
+
action,
|
|
1427
|
+
accountId: account.accountId,
|
|
1428
|
+
docId: params.docId,
|
|
1429
|
+
summary: "智能表格编组已更新",
|
|
1430
|
+
raw: result.raw,
|
|
1431
|
+
});
|
|
1432
|
+
}
|
|
1433
|
+
case "smartsheet_get_groups": {
|
|
1434
|
+
const result = await docClient.smartTableGetGroups({ agent: account, ...params });
|
|
1435
|
+
return buildToolResult({
|
|
1436
|
+
ok: true,
|
|
1437
|
+
action,
|
|
1438
|
+
accountId: account.accountId,
|
|
1439
|
+
docId: params.docId,
|
|
1440
|
+
summary: "智能表格编组列表已获取",
|
|
1441
|
+
raw: result.raw,
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1444
|
+
case "smartsheet_add_external_records": {
|
|
1445
|
+
const result = await docClient.smartTableAddExternalRecords({
|
|
1446
|
+
agent: account,
|
|
1447
|
+
...params,
|
|
1448
|
+
});
|
|
1449
|
+
return buildToolResult({
|
|
1450
|
+
ok: true,
|
|
1451
|
+
action,
|
|
1452
|
+
accountId: account.accountId,
|
|
1453
|
+
docId: params.docId,
|
|
1454
|
+
summary: "智能表格外部记录已添加",
|
|
1455
|
+
raw: result.raw,
|
|
1456
|
+
});
|
|
1457
|
+
}
|
|
1458
|
+
case "smartsheet_update_external_records": {
|
|
1459
|
+
const result = await docClient.smartTableUpdateExternalRecords({
|
|
1460
|
+
agent: account,
|
|
1461
|
+
...params,
|
|
1462
|
+
});
|
|
1463
|
+
return buildToolResult({
|
|
1464
|
+
ok: true,
|
|
1465
|
+
action,
|
|
1466
|
+
accountId: account.accountId,
|
|
1467
|
+
docId: params.docId,
|
|
1468
|
+
summary: "智能表格外部记录已更新",
|
|
1469
|
+
raw: result.raw,
|
|
1470
|
+
});
|
|
1471
|
+
}
|
|
1472
|
+
case "smartsheet_get_sheet_priv": {
|
|
1473
|
+
const result = await docClient.smartTableGetSheetPriv({ agent: account, ...params });
|
|
1474
|
+
return buildToolResult({
|
|
1475
|
+
ok: true,
|
|
1476
|
+
action,
|
|
1477
|
+
accountId: account.accountId,
|
|
1478
|
+
docId: params.docId,
|
|
1479
|
+
summary: "智能表格子表权限已获取",
|
|
1480
|
+
raw: result.raw,
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
case "smartsheet_update_sheet_priv": {
|
|
1484
|
+
const result = await docClient.smartTableUpdateSheetPriv({
|
|
1485
|
+
agent: account,
|
|
1486
|
+
...params,
|
|
1487
|
+
});
|
|
1488
|
+
return buildToolResult({
|
|
1489
|
+
ok: true,
|
|
1490
|
+
action,
|
|
1491
|
+
accountId: account.accountId,
|
|
1492
|
+
docId: params.docId,
|
|
1493
|
+
summary: "智能表格子表权限已更新",
|
|
1494
|
+
raw: result.raw,
|
|
1495
|
+
});
|
|
1496
|
+
}
|
|
1497
|
+
case "smartsheet_create_rule": {
|
|
1498
|
+
const result = await docClient.smartTableCreateRule({ agent: account, ...params });
|
|
1499
|
+
return buildToolResult({
|
|
1500
|
+
ok: true,
|
|
1501
|
+
action,
|
|
1502
|
+
accountId: account.accountId,
|
|
1503
|
+
docId: params.docId,
|
|
1504
|
+
summary: `智能表格成员额外权限规则已创建 (rule_id: ${result.rule_id})`,
|
|
1505
|
+
raw: result.raw,
|
|
1506
|
+
});
|
|
1507
|
+
}
|
|
1508
|
+
case "smartsheet_mod_rule_member": {
|
|
1509
|
+
const result = await docClient.smartTableModRuleMember({ agent: account, ...params });
|
|
1510
|
+
return buildToolResult({
|
|
1511
|
+
ok: true,
|
|
1512
|
+
action,
|
|
1513
|
+
accountId: account.accountId,
|
|
1514
|
+
docId: params.docId,
|
|
1515
|
+
summary: "智能表格成员额外权限成员已更新",
|
|
1516
|
+
raw: result.raw,
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
case "smartsheet_delete_rule": {
|
|
1520
|
+
const result = await docClient.smartTableDeleteRule({ agent: account, ...params });
|
|
1521
|
+
return buildToolResult({
|
|
1522
|
+
ok: true,
|
|
1523
|
+
action,
|
|
1524
|
+
accountId: account.accountId,
|
|
1525
|
+
docId: params.docId,
|
|
1526
|
+
summary: "智能表格成员额外权限规则已删除",
|
|
1527
|
+
raw: result.raw,
|
|
1528
|
+
});
|
|
1529
|
+
}
|
|
1530
|
+
case "doc_assign_advanced_account": {
|
|
1531
|
+
const result = await docClient.assignDocAdvancedAccount({
|
|
1532
|
+
agent: account,
|
|
1533
|
+
userid_list: params.userid_list,
|
|
1534
|
+
});
|
|
1535
|
+
return buildToolResult({
|
|
1536
|
+
ok: true,
|
|
1537
|
+
action,
|
|
1538
|
+
accountId: account.accountId,
|
|
1539
|
+
summary: summarizeAdvancedAccount(result.raw, "assign"),
|
|
1540
|
+
raw: result.raw,
|
|
1541
|
+
});
|
|
1542
|
+
}
|
|
1543
|
+
case "doc_cancel_advanced_account": {
|
|
1544
|
+
const result = await docClient.cancelDocAdvancedAccount({
|
|
1545
|
+
agent: account,
|
|
1546
|
+
userid_list: params.userid_list,
|
|
1547
|
+
});
|
|
1548
|
+
return buildToolResult({
|
|
1549
|
+
ok: true,
|
|
1550
|
+
action,
|
|
1551
|
+
accountId: account.accountId,
|
|
1552
|
+
summary: summarizeAdvancedAccount(result.raw, "cancel"),
|
|
1553
|
+
raw: result.raw,
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
case "doc_get_advanced_account_list": {
|
|
1557
|
+
const result = await docClient.getDocAdvancedAccountList({
|
|
1558
|
+
agent: account,
|
|
1559
|
+
...params,
|
|
1560
|
+
});
|
|
1561
|
+
return buildToolResult({
|
|
1562
|
+
ok: true,
|
|
1563
|
+
action,
|
|
1564
|
+
accountId: account.accountId,
|
|
1565
|
+
summary: summarizeAdvancedAccount(result, "list"),
|
|
1566
|
+
raw: result.raw,
|
|
1567
|
+
});
|
|
1568
|
+
}
|
|
1569
|
+
case "upload_doc_image": {
|
|
1570
|
+
const filePath = params.file_path;
|
|
1571
|
+
if (!fs.existsSync(filePath)) {
|
|
1572
|
+
throw new Error(`File not found: ${filePath}`);
|
|
1573
|
+
}
|
|
1574
|
+
const fileContent = fs.readFileSync(filePath);
|
|
1575
|
+
const base64Content = fileContent.toString("base64");
|
|
1576
|
+
|
|
1577
|
+
const result = await docClient.uploadDocImage({
|
|
1578
|
+
agent: account,
|
|
1579
|
+
docId: params.docId,
|
|
1580
|
+
base64_content: base64Content,
|
|
1581
|
+
});
|
|
1582
|
+
return buildToolResult({
|
|
1583
|
+
ok: true,
|
|
1584
|
+
action,
|
|
1585
|
+
accountId: account.accountId,
|
|
1586
|
+
summary: "图片上传成功",
|
|
1587
|
+
details: {
|
|
1588
|
+
url: result.url,
|
|
1589
|
+
width: result.width,
|
|
1590
|
+
height: result.height,
|
|
1591
|
+
size: result.size,
|
|
1592
|
+
},
|
|
1593
|
+
raw: result.raw,
|
|
1594
|
+
});
|
|
1595
|
+
}
|
|
1596
|
+
default:
|
|
1597
|
+
throw new Error(`Unsupported action: ${String(action)}`);
|
|
1598
|
+
}
|
|
1599
|
+
} catch (err) {
|
|
1600
|
+
return {
|
|
1601
|
+
content: [
|
|
1602
|
+
{
|
|
1603
|
+
type: "text" as const,
|
|
1604
|
+
text: JSON.stringify(
|
|
1605
|
+
{
|
|
1606
|
+
ok: false,
|
|
1607
|
+
action: params?.action,
|
|
1608
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1609
|
+
},
|
|
1610
|
+
null,
|
|
1611
|
+
2,
|
|
1612
|
+
),
|
|
1613
|
+
},
|
|
1614
|
+
],
|
|
1615
|
+
details: {},
|
|
1616
|
+
isError: true,
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
},
|
|
1620
|
+
};
|
|
1621
|
+
});
|
|
1290
1622
|
}
|