gewe-openclaw 2026.3.13 → 2026.3.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +455 -3
- package/index.ts +39 -1
- package/package.json +12 -1
- package/skills/gewe-agent-tools/SKILL.md +113 -0
- package/skills/gewe-channel-rules/SKILL.md +7 -0
- package/src/accounts.ts +51 -5
- package/src/api-tools.ts +1264 -0
- package/src/api.ts +37 -2
- package/src/binary-command.ts +65 -0
- package/src/channel-actions.ts +536 -0
- package/src/channel-allowlist.ts +150 -0
- package/src/channel-directory.ts +419 -0
- package/src/channel-status.ts +186 -0
- package/src/channel.ts +155 -58
- package/src/config-edit.ts +94 -0
- package/src/config-schema.ts +78 -3
- package/src/contacts-api.ts +113 -0
- package/src/delivery.ts +502 -62
- package/src/directory-cache.ts +164 -0
- package/src/gewe-account-api.ts +27 -0
- package/src/group-allowlist-tool.ts +242 -0
- package/src/group-binding-tool.ts +154 -0
- package/src/group-binding.ts +405 -0
- package/src/groups-api.ts +146 -0
- package/src/inbound-batch.ts +5 -2
- package/src/inbound.ts +248 -41
- package/src/media-server.ts +73 -93
- package/src/moments-api.ts +138 -0
- package/src/monitor.ts +81 -24
- package/src/onboarding.ts +9 -4
- package/src/openclaw-compat.ts +1070 -0
- package/src/pairing-store.ts +478 -0
- package/src/personal-api.ts +45 -0
- package/src/policy.ts +130 -22
- package/src/quote-context-cache.ts +97 -0
- package/src/reply-options.ts +101 -2
- package/src/s3.ts +1 -1
- package/src/send.ts +235 -16
- package/src/setup-wizard-types.ts +162 -0
- package/src/setup-wizard.ts +464 -0
- package/src/silk.ts +2 -1
- package/src/state-paths.ts +55 -14
- package/src/types.ts +66 -7
- package/src/xml.ts +158 -0
package/src/api-tools.ts
ADDED
|
@@ -0,0 +1,1264 @@
|
|
|
1
|
+
import type { AnyAgentTool, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
import { resolveGeweAccount } from "./accounts.js";
|
|
5
|
+
import {
|
|
6
|
+
addContactsGewe,
|
|
7
|
+
addImContactGewe,
|
|
8
|
+
checkRelationGewe,
|
|
9
|
+
deleteFriendGewe,
|
|
10
|
+
fetchContactsListCacheGewe,
|
|
11
|
+
fetchContactsListGewe,
|
|
12
|
+
getBriefInfoGewe,
|
|
13
|
+
getDetailInfoGewe,
|
|
14
|
+
getImContactDetailGewe,
|
|
15
|
+
getPhoneAddressListGewe,
|
|
16
|
+
searchContactGewe,
|
|
17
|
+
searchImContactGewe,
|
|
18
|
+
setFriendPermissionsGewe,
|
|
19
|
+
setFriendRemarkGewe,
|
|
20
|
+
syncImContactsGewe,
|
|
21
|
+
uploadPhoneAddressListGewe,
|
|
22
|
+
} from "./contacts-api.js";
|
|
23
|
+
import {
|
|
24
|
+
addGroupMemberAsFriendGewe,
|
|
25
|
+
adminOperateGewe,
|
|
26
|
+
agreeJoinRoomGewe,
|
|
27
|
+
createChatroomGewe,
|
|
28
|
+
disbandChatroomGewe,
|
|
29
|
+
getChatroomAnnouncementGewe,
|
|
30
|
+
getChatroomInfoGewe,
|
|
31
|
+
getChatroomMemberDetailGewe,
|
|
32
|
+
getChatroomMemberListGewe,
|
|
33
|
+
getChatroomQrCodeGewe,
|
|
34
|
+
inviteMemberGewe,
|
|
35
|
+
joinRoomUsingQRCodeGewe,
|
|
36
|
+
modifyChatroomNameGewe,
|
|
37
|
+
modifyChatroomNickNameForSelfGewe,
|
|
38
|
+
modifyChatroomRemarkGewe,
|
|
39
|
+
pinChatGewe,
|
|
40
|
+
quitChatroomGewe,
|
|
41
|
+
removeMemberGewe,
|
|
42
|
+
roomAccessApplyCheckApproveGewe,
|
|
43
|
+
saveContractListGewe,
|
|
44
|
+
setChatroomAnnouncementGewe,
|
|
45
|
+
setMsgSilenceGewe,
|
|
46
|
+
} from "./groups-api.js";
|
|
47
|
+
import { inferCurrentGeweGroupId, normalizeGeweBindingConversationId } from "./group-binding.js";
|
|
48
|
+
import {
|
|
49
|
+
commentSnsGewe,
|
|
50
|
+
contactsSnsListGewe,
|
|
51
|
+
delSnsGewe,
|
|
52
|
+
downloadSnsVideoGewe,
|
|
53
|
+
forwardSnsGewe,
|
|
54
|
+
likeSnsGewe,
|
|
55
|
+
sendImgSnsGewe,
|
|
56
|
+
sendTextSnsGewe,
|
|
57
|
+
sendUrlSnsGewe,
|
|
58
|
+
sendVideoSnsGewe,
|
|
59
|
+
snsDetailsGewe,
|
|
60
|
+
snsListGewe,
|
|
61
|
+
snsSetPrivacyGewe,
|
|
62
|
+
snsVisibleScopeGewe,
|
|
63
|
+
strangerVisibilityEnabledGewe,
|
|
64
|
+
uploadSnsImageGewe,
|
|
65
|
+
uploadSnsVideoGewe,
|
|
66
|
+
} from "./moments-api.js";
|
|
67
|
+
import { normalizeGeweMessagingTarget } from "./normalize.js";
|
|
68
|
+
import { normalizeAccountId, type OpenClawConfig } from "./openclaw-compat.js";
|
|
69
|
+
import {
|
|
70
|
+
getProfileGewe,
|
|
71
|
+
getQrCodeGewe,
|
|
72
|
+
getSafetyInfoGewe,
|
|
73
|
+
privacySettingsGewe,
|
|
74
|
+
updateHeadImgGewe,
|
|
75
|
+
updateProfileGewe,
|
|
76
|
+
} from "./personal-api.js";
|
|
77
|
+
import type { CoreConfig, ResolvedGeweAccount } from "./types.js";
|
|
78
|
+
|
|
79
|
+
const ContactsActionSchema = z.enum([
|
|
80
|
+
"list",
|
|
81
|
+
"list_cache",
|
|
82
|
+
"brief",
|
|
83
|
+
"detail",
|
|
84
|
+
"search",
|
|
85
|
+
"search_im",
|
|
86
|
+
"im_detail",
|
|
87
|
+
"check_relation",
|
|
88
|
+
"set_remark",
|
|
89
|
+
"set_only_chat",
|
|
90
|
+
"delete",
|
|
91
|
+
"add",
|
|
92
|
+
"add_im",
|
|
93
|
+
"sync_im",
|
|
94
|
+
"phones_get",
|
|
95
|
+
"phones_upload",
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
const GroupsActionSchema = z.enum([
|
|
99
|
+
"info",
|
|
100
|
+
"announcement",
|
|
101
|
+
"members",
|
|
102
|
+
"member_detail",
|
|
103
|
+
"qr_code",
|
|
104
|
+
"set_self_nickname",
|
|
105
|
+
"rename",
|
|
106
|
+
"set_remark",
|
|
107
|
+
"create",
|
|
108
|
+
"remove_members",
|
|
109
|
+
"agree_join",
|
|
110
|
+
"join_via_qr",
|
|
111
|
+
"add_member_as_friend",
|
|
112
|
+
"approve_join_request",
|
|
113
|
+
"admin_operate",
|
|
114
|
+
"save_to_contacts",
|
|
115
|
+
"pin",
|
|
116
|
+
"disband",
|
|
117
|
+
"set_silence",
|
|
118
|
+
"set_announcement",
|
|
119
|
+
"quit",
|
|
120
|
+
"invite",
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
const MomentsActionSchema = z.enum([
|
|
124
|
+
"list_self",
|
|
125
|
+
"list_contact",
|
|
126
|
+
"detail",
|
|
127
|
+
"download_video",
|
|
128
|
+
"upload_image",
|
|
129
|
+
"upload_video",
|
|
130
|
+
"delete",
|
|
131
|
+
"post_text",
|
|
132
|
+
"post_image",
|
|
133
|
+
"post_video",
|
|
134
|
+
"post_link",
|
|
135
|
+
"set_stranger_visibility",
|
|
136
|
+
"set_visible_scope",
|
|
137
|
+
"set_privacy",
|
|
138
|
+
"like",
|
|
139
|
+
"comment",
|
|
140
|
+
"forward",
|
|
141
|
+
]);
|
|
142
|
+
|
|
143
|
+
const PersonalActionSchema = z.enum([
|
|
144
|
+
"profile",
|
|
145
|
+
"qrcode",
|
|
146
|
+
"safety_info",
|
|
147
|
+
"update_profile",
|
|
148
|
+
"update_avatar",
|
|
149
|
+
"privacy",
|
|
150
|
+
]);
|
|
151
|
+
|
|
152
|
+
const FlexibleObjectSchema = z.object({}).catchall(z.unknown());
|
|
153
|
+
|
|
154
|
+
const ContactsToolSchema = z
|
|
155
|
+
.object({
|
|
156
|
+
action: ContactsActionSchema,
|
|
157
|
+
accountId: z.string().optional(),
|
|
158
|
+
wxid: z.string().optional(),
|
|
159
|
+
wxids: z.array(z.string()).optional(),
|
|
160
|
+
scene: z.number().int().optional(),
|
|
161
|
+
option: z.number().int().optional(),
|
|
162
|
+
content: z.string().optional(),
|
|
163
|
+
v3: z.string().optional(),
|
|
164
|
+
v4: z.string().optional(),
|
|
165
|
+
toUserName: z.string().optional(),
|
|
166
|
+
phones: z.array(z.string()).optional(),
|
|
167
|
+
opType: z.number().int().optional(),
|
|
168
|
+
remark: z.string().optional(),
|
|
169
|
+
onlyChat: z.boolean().optional(),
|
|
170
|
+
contactsInfo: z.string().optional(),
|
|
171
|
+
})
|
|
172
|
+
.strict();
|
|
173
|
+
|
|
174
|
+
const GroupsToolSchema = z
|
|
175
|
+
.object({
|
|
176
|
+
action: GroupsActionSchema,
|
|
177
|
+
accountId: z.string().optional(),
|
|
178
|
+
groupId: z.string().optional(),
|
|
179
|
+
nickName: z.string().optional(),
|
|
180
|
+
chatroomName: z.string().optional(),
|
|
181
|
+
remark: z.string().optional(),
|
|
182
|
+
wxids: z.array(z.string()).optional(),
|
|
183
|
+
memberWxids: z.array(z.string()).optional(),
|
|
184
|
+
memberWxid: z.string().optional(),
|
|
185
|
+
url: z.string().optional(),
|
|
186
|
+
qrUrl: z.string().optional(),
|
|
187
|
+
content: z.string().optional(),
|
|
188
|
+
msgContent: z.string().optional(),
|
|
189
|
+
newMsgId: z.union([z.string(), z.number().int()]).optional(),
|
|
190
|
+
operType: z.number().int().optional(),
|
|
191
|
+
top: z.union([z.boolean(), z.number().int()]).optional(),
|
|
192
|
+
silence: z.union([z.boolean(), z.number().int()]).optional(),
|
|
193
|
+
reason: z.string().optional(),
|
|
194
|
+
})
|
|
195
|
+
.strict();
|
|
196
|
+
|
|
197
|
+
const MomentsToolSchema = z
|
|
198
|
+
.object({
|
|
199
|
+
action: MomentsActionSchema,
|
|
200
|
+
accountId: z.string().optional(),
|
|
201
|
+
wxid: z.string().optional(),
|
|
202
|
+
snsId: z.string().optional(),
|
|
203
|
+
snsXml: z.string().optional(),
|
|
204
|
+
imgUrls: z.array(z.string()).optional(),
|
|
205
|
+
thumbUrl: z.string().optional(),
|
|
206
|
+
videoUrl: z.string().optional(),
|
|
207
|
+
imgInfos: z.array(FlexibleObjectSchema).optional(),
|
|
208
|
+
videoInfo: FlexibleObjectSchema.optional(),
|
|
209
|
+
content: z.string().optional(),
|
|
210
|
+
linkUrl: z.string().optional(),
|
|
211
|
+
title: z.string().optional(),
|
|
212
|
+
description: z.string().optional(),
|
|
213
|
+
enabled: z.boolean().optional(),
|
|
214
|
+
option: z.number().int().optional(),
|
|
215
|
+
open: z.boolean().optional(),
|
|
216
|
+
operType: z.number().int().optional(),
|
|
217
|
+
commentId: z.union([z.string(), z.number().int()]).optional(),
|
|
218
|
+
allowWxIds: z.array(z.string()).optional(),
|
|
219
|
+
atWxIds: z.array(z.string()).optional(),
|
|
220
|
+
disableWxIds: z.array(z.string()).optional(),
|
|
221
|
+
privacy: z.number().int().optional(),
|
|
222
|
+
allowTagIds: z.array(z.union([z.string(), z.number().int()])).optional(),
|
|
223
|
+
disableTagIds: z.array(z.union([z.string(), z.number().int()])).optional(),
|
|
224
|
+
maxId: z.union([z.string(), z.number().int()]).optional(),
|
|
225
|
+
decrypt: z.boolean().optional(),
|
|
226
|
+
firstPageMd5: z.string().optional(),
|
|
227
|
+
})
|
|
228
|
+
.strict();
|
|
229
|
+
|
|
230
|
+
const PersonalToolSchema = z
|
|
231
|
+
.object({
|
|
232
|
+
action: PersonalActionSchema,
|
|
233
|
+
accountId: z.string().optional(),
|
|
234
|
+
country: z.string().optional(),
|
|
235
|
+
province: z.string().optional(),
|
|
236
|
+
city: z.string().optional(),
|
|
237
|
+
nickName: z.string().optional(),
|
|
238
|
+
sex: z.number().int().optional(),
|
|
239
|
+
signature: z.string().optional(),
|
|
240
|
+
headImgUrl: z.string().optional(),
|
|
241
|
+
option: z.number().int().optional(),
|
|
242
|
+
open: z.boolean().optional(),
|
|
243
|
+
})
|
|
244
|
+
.strict();
|
|
245
|
+
|
|
246
|
+
type ContactsToolParams = z.infer<typeof ContactsToolSchema>;
|
|
247
|
+
type GroupsToolParams = z.infer<typeof GroupsToolSchema>;
|
|
248
|
+
type MomentsToolParams = z.infer<typeof MomentsToolSchema>;
|
|
249
|
+
type PersonalToolParams = z.infer<typeof PersonalToolSchema>;
|
|
250
|
+
|
|
251
|
+
function jsonToolResult(details: Record<string, unknown>) {
|
|
252
|
+
return {
|
|
253
|
+
content: [{ type: "text" as const, text: JSON.stringify(details, null, 2) }],
|
|
254
|
+
details,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function unknownToolActionResult(tool: string, action: unknown) {
|
|
259
|
+
return jsonToolResult({
|
|
260
|
+
ok: false,
|
|
261
|
+
tool,
|
|
262
|
+
error: `Unknown action: ${String(action)}`,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function toolExecutionErrorResult(tool: string, action: unknown, error: unknown) {
|
|
267
|
+
return jsonToolResult({
|
|
268
|
+
ok: false,
|
|
269
|
+
tool,
|
|
270
|
+
action: typeof action === "string" ? action : undefined,
|
|
271
|
+
error: error instanceof Error ? error.message : String(error),
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function resolveToolConfig(ctx: OpenClawPluginToolContext): OpenClawConfig {
|
|
276
|
+
return (ctx.config ?? {}) as OpenClawConfig;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function resolveGeweToolAccount(params: {
|
|
280
|
+
ctx: OpenClawPluginToolContext;
|
|
281
|
+
rawAccountId?: string;
|
|
282
|
+
}): { cfg: OpenClawConfig; account: ResolvedGeweAccount } {
|
|
283
|
+
const cfg = resolveToolConfig(params.ctx);
|
|
284
|
+
const account = resolveGeweAccount({
|
|
285
|
+
cfg: cfg as CoreConfig,
|
|
286
|
+
accountId: normalizeAccountId(params.rawAccountId ?? params.ctx.agentAccountId ?? "default"),
|
|
287
|
+
});
|
|
288
|
+
if (!account.token || !account.appId) {
|
|
289
|
+
throw new Error(`GeWe account "${account.accountId}" is not fully configured with token and appId.`);
|
|
290
|
+
}
|
|
291
|
+
return { cfg, account };
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function dedupeStrings(values: readonly unknown[]): string[] {
|
|
295
|
+
const result: string[] = [];
|
|
296
|
+
const seen = new Set<string>();
|
|
297
|
+
for (const value of values) {
|
|
298
|
+
const normalized = String(value ?? "").trim();
|
|
299
|
+
if (!normalized || seen.has(normalized)) {
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
seen.add(normalized);
|
|
303
|
+
result.push(normalized);
|
|
304
|
+
}
|
|
305
|
+
return result;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function normalizeWxidList(values: readonly unknown[]): string[] {
|
|
309
|
+
const result: string[] = [];
|
|
310
|
+
const seen = new Set<string>();
|
|
311
|
+
for (const value of values) {
|
|
312
|
+
const normalized = normalizeGeweMessagingTarget(String(value ?? "").trim());
|
|
313
|
+
if (!normalized || normalized.endsWith("@chatroom") || seen.has(normalized)) {
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
seen.add(normalized);
|
|
317
|
+
result.push(normalized);
|
|
318
|
+
}
|
|
319
|
+
return result;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function extractSessionScopedTarget(
|
|
323
|
+
sessionKey: string | undefined,
|
|
324
|
+
markers: string[],
|
|
325
|
+
): string | undefined {
|
|
326
|
+
const raw = sessionKey?.trim();
|
|
327
|
+
if (!raw) {
|
|
328
|
+
return undefined;
|
|
329
|
+
}
|
|
330
|
+
const lowered = raw.toLowerCase();
|
|
331
|
+
for (const marker of markers) {
|
|
332
|
+
const index = lowered.indexOf(marker);
|
|
333
|
+
if (index === -1) {
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
const value = raw.slice(index + marker.length).trim();
|
|
337
|
+
if (value) {
|
|
338
|
+
return value;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return undefined;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function inferCurrentGeweDirectWxid(ctx: OpenClawPluginToolContext): string | undefined {
|
|
345
|
+
const fromSession = extractSessionScopedTarget(ctx.sessionKey, [
|
|
346
|
+
":gewe-openclaw:direct:",
|
|
347
|
+
":gewe-openclaw:dm:",
|
|
348
|
+
":gewe:direct:",
|
|
349
|
+
":gewe:dm:",
|
|
350
|
+
]);
|
|
351
|
+
const normalizedSession = normalizeGeweMessagingTarget(fromSession ?? "");
|
|
352
|
+
if (normalizedSession && !normalizedSession.endsWith("@chatroom")) {
|
|
353
|
+
return normalizedSession;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const normalizedRequester = normalizeGeweMessagingTarget(ctx.requesterSenderId ?? "");
|
|
357
|
+
if (normalizedRequester && !normalizedRequester.endsWith("@chatroom")) {
|
|
358
|
+
return normalizedRequester;
|
|
359
|
+
}
|
|
360
|
+
return undefined;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function resolveDirectWxids(params: {
|
|
364
|
+
ctx: OpenClawPluginToolContext;
|
|
365
|
+
wxids?: readonly string[];
|
|
366
|
+
}): string[] {
|
|
367
|
+
const explicit = normalizeWxidList(params.wxids ?? []);
|
|
368
|
+
if (explicit.length > 0) {
|
|
369
|
+
return explicit;
|
|
370
|
+
}
|
|
371
|
+
const inferred = inferCurrentGeweDirectWxid(params.ctx);
|
|
372
|
+
if (!inferred) {
|
|
373
|
+
throw new Error("This action requires wxids, or a current GeWe direct-message session to infer one.");
|
|
374
|
+
}
|
|
375
|
+
return [inferred];
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function resolveSingleWxid(params: {
|
|
379
|
+
ctx: OpenClawPluginToolContext;
|
|
380
|
+
rawWxid?: string;
|
|
381
|
+
fieldLabel: string;
|
|
382
|
+
}): string {
|
|
383
|
+
const explicit = normalizeWxidList([params.rawWxid ?? ""]);
|
|
384
|
+
if (explicit.length > 0) {
|
|
385
|
+
return explicit[0]!;
|
|
386
|
+
}
|
|
387
|
+
const inferred = inferCurrentGeweDirectWxid(params.ctx);
|
|
388
|
+
if (!inferred) {
|
|
389
|
+
throw new Error(
|
|
390
|
+
`This action requires ${params.fieldLabel}, or a current GeWe direct-message session to infer one.`,
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
return inferred;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function resolveGroupId(params: {
|
|
397
|
+
cfg: OpenClawConfig;
|
|
398
|
+
accountId: string;
|
|
399
|
+
ctx: OpenClawPluginToolContext;
|
|
400
|
+
rawGroupId?: string;
|
|
401
|
+
}): string {
|
|
402
|
+
const explicit = normalizeGeweBindingConversationId(params.rawGroupId);
|
|
403
|
+
if (explicit) {
|
|
404
|
+
return explicit;
|
|
405
|
+
}
|
|
406
|
+
const inferred = inferCurrentGeweGroupId({
|
|
407
|
+
cfg: params.cfg,
|
|
408
|
+
accountId: params.accountId,
|
|
409
|
+
sessionKey: params.ctx.sessionKey,
|
|
410
|
+
});
|
|
411
|
+
if (!inferred) {
|
|
412
|
+
throw new Error("This action requires groupId, or a current GeWe group session that can infer one.");
|
|
413
|
+
}
|
|
414
|
+
return inferred;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function requireString(value: string | undefined, label: string): string {
|
|
418
|
+
const trimmed = value?.trim();
|
|
419
|
+
if (!trimmed) {
|
|
420
|
+
throw new Error(`${label} is required for this action.`);
|
|
421
|
+
}
|
|
422
|
+
return trimmed;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function requireNumber(value: number | undefined, label: string): number {
|
|
426
|
+
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
427
|
+
throw new Error(`${label} is required for this action.`);
|
|
428
|
+
}
|
|
429
|
+
return value;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function requireBoolean(value: boolean | undefined, label: string): boolean {
|
|
433
|
+
if (typeof value !== "boolean") {
|
|
434
|
+
throw new Error(`${label} is required for this action.`);
|
|
435
|
+
}
|
|
436
|
+
return value;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function requireStringArray(values: readonly string[] | undefined, label: string): string[] {
|
|
440
|
+
const normalized = dedupeStrings(values ?? []);
|
|
441
|
+
if (normalized.length === 0) {
|
|
442
|
+
throw new Error(`${label} is required for this action.`);
|
|
443
|
+
}
|
|
444
|
+
return normalized;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function requireWxidArray(values: readonly string[] | undefined, label: string): string[] {
|
|
448
|
+
const normalized = normalizeWxidList(values ?? []);
|
|
449
|
+
if (normalized.length === 0) {
|
|
450
|
+
throw new Error(`${label} is required for this action.`);
|
|
451
|
+
}
|
|
452
|
+
return normalized;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function requireObjectArray(
|
|
456
|
+
values: Array<Record<string, unknown>> | undefined,
|
|
457
|
+
label: string,
|
|
458
|
+
): Array<Record<string, unknown>> {
|
|
459
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
460
|
+
throw new Error(`${label} is required for this action.`);
|
|
461
|
+
}
|
|
462
|
+
return values;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function requireObject(value: Record<string, unknown> | undefined, label: string): Record<string, unknown> {
|
|
466
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
467
|
+
throw new Error(`${label} is required for this action.`);
|
|
468
|
+
}
|
|
469
|
+
return value;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function buildMomentsVisibilityInput(params: MomentsToolParams) {
|
|
473
|
+
return {
|
|
474
|
+
...(params.allowWxIds ? { allowWxIds: dedupeStrings(params.allowWxIds) } : {}),
|
|
475
|
+
...(params.atWxIds ? { atWxIds: dedupeStrings(params.atWxIds) } : {}),
|
|
476
|
+
...(params.disableWxIds ? { disableWxIds: dedupeStrings(params.disableWxIds) } : {}),
|
|
477
|
+
...(typeof params.privacy === "number" ? { privacy: params.privacy } : {}),
|
|
478
|
+
...(params.allowTagIds ? { allowTagIds: params.allowTagIds } : {}),
|
|
479
|
+
...(params.disableTagIds ? { disableTagIds: params.disableTagIds } : {}),
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
async function executeContactsTool(
|
|
484
|
+
ctx: OpenClawPluginToolContext,
|
|
485
|
+
params: ContactsToolParams,
|
|
486
|
+
) {
|
|
487
|
+
const { account } = resolveGeweToolAccount({
|
|
488
|
+
ctx,
|
|
489
|
+
rawAccountId: params.accountId,
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
switch (params.action) {
|
|
493
|
+
case "list":
|
|
494
|
+
return {
|
|
495
|
+
input: {},
|
|
496
|
+
data: await fetchContactsListGewe({ account }),
|
|
497
|
+
};
|
|
498
|
+
case "list_cache":
|
|
499
|
+
return {
|
|
500
|
+
input: {},
|
|
501
|
+
data: await fetchContactsListCacheGewe({ account }),
|
|
502
|
+
};
|
|
503
|
+
case "brief": {
|
|
504
|
+
const wxids = resolveDirectWxids({ ctx, wxids: params.wxids });
|
|
505
|
+
return {
|
|
506
|
+
input: { wxids },
|
|
507
|
+
data: await getBriefInfoGewe({ account, wxids }),
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
case "detail": {
|
|
511
|
+
const wxids = resolveDirectWxids({ ctx, wxids: params.wxids });
|
|
512
|
+
return {
|
|
513
|
+
input: { wxids },
|
|
514
|
+
data: await getDetailInfoGewe({ account, wxids }),
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
case "search":
|
|
518
|
+
return {
|
|
519
|
+
input: { contactsInfo: requireString(params.contactsInfo, "contactsInfo") },
|
|
520
|
+
data: await searchContactGewe({
|
|
521
|
+
account,
|
|
522
|
+
contactsInfo: requireString(params.contactsInfo, "contactsInfo"),
|
|
523
|
+
}),
|
|
524
|
+
};
|
|
525
|
+
case "search_im":
|
|
526
|
+
return {
|
|
527
|
+
input: {
|
|
528
|
+
scene: requireNumber(params.scene, "scene"),
|
|
529
|
+
content: requireString(params.content, "content"),
|
|
530
|
+
},
|
|
531
|
+
data: await searchImContactGewe({
|
|
532
|
+
account,
|
|
533
|
+
scene: requireNumber(params.scene, "scene"),
|
|
534
|
+
content: requireString(params.content, "content"),
|
|
535
|
+
}),
|
|
536
|
+
};
|
|
537
|
+
case "im_detail":
|
|
538
|
+
return {
|
|
539
|
+
input: { toUserName: requireString(params.toUserName, "toUserName") },
|
|
540
|
+
data: await getImContactDetailGewe({
|
|
541
|
+
account,
|
|
542
|
+
toUserName: requireString(params.toUserName, "toUserName"),
|
|
543
|
+
}),
|
|
544
|
+
};
|
|
545
|
+
case "check_relation": {
|
|
546
|
+
const wxids = resolveDirectWxids({ ctx, wxids: params.wxids });
|
|
547
|
+
return {
|
|
548
|
+
input: { wxids },
|
|
549
|
+
data: await checkRelationGewe({ account, wxids }),
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
case "set_remark": {
|
|
553
|
+
const wxid = resolveSingleWxid({
|
|
554
|
+
ctx,
|
|
555
|
+
rawWxid: params.wxid,
|
|
556
|
+
fieldLabel: "wxid",
|
|
557
|
+
});
|
|
558
|
+
const remark = requireString(params.remark, "remark");
|
|
559
|
+
return {
|
|
560
|
+
input: { wxid, remark },
|
|
561
|
+
data: await setFriendRemarkGewe({ account, wxid, remark }),
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
case "set_only_chat": {
|
|
565
|
+
const wxid = resolveSingleWxid({
|
|
566
|
+
ctx,
|
|
567
|
+
rawWxid: params.wxid,
|
|
568
|
+
fieldLabel: "wxid",
|
|
569
|
+
});
|
|
570
|
+
const onlyChat = requireBoolean(params.onlyChat, "onlyChat");
|
|
571
|
+
return {
|
|
572
|
+
input: { wxid, onlyChat },
|
|
573
|
+
data: await setFriendPermissionsGewe({ account, wxid, onlyChat }),
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
case "delete": {
|
|
577
|
+
const wxid = resolveSingleWxid({
|
|
578
|
+
ctx,
|
|
579
|
+
rawWxid: params.wxid,
|
|
580
|
+
fieldLabel: "wxid",
|
|
581
|
+
});
|
|
582
|
+
return {
|
|
583
|
+
input: { wxid },
|
|
584
|
+
data: await deleteFriendGewe({ account, wxid }),
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
case "add":
|
|
588
|
+
return {
|
|
589
|
+
input: {
|
|
590
|
+
scene: requireNumber(params.scene, "scene"),
|
|
591
|
+
option: requireNumber(params.option, "option"),
|
|
592
|
+
v3: requireString(params.v3, "v3"),
|
|
593
|
+
v4: requireString(params.v4, "v4"),
|
|
594
|
+
content: requireString(params.content, "content"),
|
|
595
|
+
},
|
|
596
|
+
data: await addContactsGewe({
|
|
597
|
+
account,
|
|
598
|
+
scene: requireNumber(params.scene, "scene"),
|
|
599
|
+
option: requireNumber(params.option, "option"),
|
|
600
|
+
v3: requireString(params.v3, "v3"),
|
|
601
|
+
v4: requireString(params.v4, "v4"),
|
|
602
|
+
content: requireString(params.content, "content"),
|
|
603
|
+
}),
|
|
604
|
+
};
|
|
605
|
+
case "add_im":
|
|
606
|
+
return {
|
|
607
|
+
input: {
|
|
608
|
+
v3: requireString(params.v3, "v3"),
|
|
609
|
+
v4: requireString(params.v4, "v4"),
|
|
610
|
+
},
|
|
611
|
+
data: await addImContactGewe({
|
|
612
|
+
account,
|
|
613
|
+
v3: requireString(params.v3, "v3"),
|
|
614
|
+
v4: requireString(params.v4, "v4"),
|
|
615
|
+
}),
|
|
616
|
+
};
|
|
617
|
+
case "sync_im":
|
|
618
|
+
return {
|
|
619
|
+
input: {},
|
|
620
|
+
data: await syncImContactsGewe({ account }),
|
|
621
|
+
};
|
|
622
|
+
case "phones_get":
|
|
623
|
+
return {
|
|
624
|
+
input: {
|
|
625
|
+
...(params.phones ? { phones: dedupeStrings(params.phones) } : {}),
|
|
626
|
+
},
|
|
627
|
+
data: await getPhoneAddressListGewe({
|
|
628
|
+
account,
|
|
629
|
+
...(params.phones ? { phones: dedupeStrings(params.phones) } : {}),
|
|
630
|
+
}),
|
|
631
|
+
};
|
|
632
|
+
case "phones_upload": {
|
|
633
|
+
const phones = requireStringArray(params.phones, "phones");
|
|
634
|
+
const opType = requireNumber(params.opType, "opType");
|
|
635
|
+
return {
|
|
636
|
+
input: { phones, opType },
|
|
637
|
+
data: await uploadPhoneAddressListGewe({ account, phones, opType }),
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
default:
|
|
641
|
+
return unknownToolActionResult("gewe_contacts", params.action);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
async function executeGroupsTool(
|
|
646
|
+
ctx: OpenClawPluginToolContext,
|
|
647
|
+
params: GroupsToolParams,
|
|
648
|
+
) {
|
|
649
|
+
const { cfg, account } = resolveGeweToolAccount({
|
|
650
|
+
ctx,
|
|
651
|
+
rawAccountId: params.accountId,
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
const resolveCurrentGroupId = () =>
|
|
655
|
+
resolveGroupId({
|
|
656
|
+
cfg,
|
|
657
|
+
accountId: account.accountId,
|
|
658
|
+
ctx,
|
|
659
|
+
rawGroupId: params.groupId,
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
switch (params.action) {
|
|
663
|
+
case "info": {
|
|
664
|
+
const groupId = resolveCurrentGroupId();
|
|
665
|
+
return {
|
|
666
|
+
input: { groupId },
|
|
667
|
+
data: await getChatroomInfoGewe({ account, chatroomId: groupId }),
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
case "announcement": {
|
|
671
|
+
const groupId = resolveCurrentGroupId();
|
|
672
|
+
return {
|
|
673
|
+
input: { groupId },
|
|
674
|
+
data: await getChatroomAnnouncementGewe({ account, chatroomId: groupId }),
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
case "members": {
|
|
678
|
+
const groupId = resolveCurrentGroupId();
|
|
679
|
+
return {
|
|
680
|
+
input: { groupId },
|
|
681
|
+
data: await getChatroomMemberListGewe({ account, chatroomId: groupId }),
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
case "member_detail": {
|
|
685
|
+
const groupId = resolveCurrentGroupId();
|
|
686
|
+
const memberWxids = requireWxidArray(params.memberWxids, "memberWxids");
|
|
687
|
+
return {
|
|
688
|
+
input: { groupId, memberWxids },
|
|
689
|
+
data: await getChatroomMemberDetailGewe({ account, chatroomId: groupId, memberWxids }),
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
case "qr_code": {
|
|
693
|
+
const groupId = resolveCurrentGroupId();
|
|
694
|
+
return {
|
|
695
|
+
input: { groupId },
|
|
696
|
+
data: await getChatroomQrCodeGewe({ account, chatroomId: groupId }),
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
case "set_self_nickname": {
|
|
700
|
+
const groupId = resolveCurrentGroupId();
|
|
701
|
+
const nickName = requireString(params.nickName, "nickName");
|
|
702
|
+
return {
|
|
703
|
+
input: { groupId, nickName },
|
|
704
|
+
data: await modifyChatroomNickNameForSelfGewe({ account, chatroomId: groupId, nickName }),
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
case "rename": {
|
|
708
|
+
const groupId = resolveCurrentGroupId();
|
|
709
|
+
const chatroomName = requireString(params.chatroomName, "chatroomName");
|
|
710
|
+
return {
|
|
711
|
+
input: { groupId, chatroomName },
|
|
712
|
+
data: await modifyChatroomNameGewe({ account, chatroomId: groupId, chatroomName }),
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
case "set_remark": {
|
|
716
|
+
const groupId = resolveCurrentGroupId();
|
|
717
|
+
const chatroomRemark = requireString(params.remark, "remark");
|
|
718
|
+
return {
|
|
719
|
+
input: { groupId, chatroomRemark },
|
|
720
|
+
data: await modifyChatroomRemarkGewe({ account, chatroomId: groupId, chatroomRemark }),
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
case "create": {
|
|
724
|
+
const wxids = requireWxidArray(params.wxids, "wxids");
|
|
725
|
+
return {
|
|
726
|
+
input: { wxids },
|
|
727
|
+
data: await createChatroomGewe({ account, wxids }),
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
case "remove_members": {
|
|
731
|
+
const groupId = resolveCurrentGroupId();
|
|
732
|
+
const wxids = requireWxidArray(params.wxids, "wxids");
|
|
733
|
+
return {
|
|
734
|
+
input: { groupId, wxids },
|
|
735
|
+
data: await removeMemberGewe({ account, chatroomId: groupId, wxids }),
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
case "agree_join":
|
|
739
|
+
return {
|
|
740
|
+
input: { url: requireString(params.url, "url") },
|
|
741
|
+
data: await agreeJoinRoomGewe({ account, url: requireString(params.url, "url") }),
|
|
742
|
+
};
|
|
743
|
+
case "join_via_qr":
|
|
744
|
+
return {
|
|
745
|
+
input: { qrUrl: requireString(params.qrUrl, "qrUrl") },
|
|
746
|
+
data: await joinRoomUsingQRCodeGewe({ account, qrUrl: requireString(params.qrUrl, "qrUrl") }),
|
|
747
|
+
};
|
|
748
|
+
case "add_member_as_friend": {
|
|
749
|
+
const groupId = resolveCurrentGroupId();
|
|
750
|
+
const memberWxid = resolveSingleWxid({
|
|
751
|
+
ctx,
|
|
752
|
+
rawWxid: params.memberWxid,
|
|
753
|
+
fieldLabel: "memberWxid",
|
|
754
|
+
});
|
|
755
|
+
const content = requireString(params.content, "content");
|
|
756
|
+
return {
|
|
757
|
+
input: { groupId, memberWxid, content },
|
|
758
|
+
data: await addGroupMemberAsFriendGewe({
|
|
759
|
+
account,
|
|
760
|
+
chatroomId: groupId,
|
|
761
|
+
memberWxid,
|
|
762
|
+
content,
|
|
763
|
+
}),
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
case "approve_join_request": {
|
|
767
|
+
const groupId = resolveCurrentGroupId();
|
|
768
|
+
const newMsgId = params.newMsgId;
|
|
769
|
+
if (typeof newMsgId !== "string" && typeof newMsgId !== "number") {
|
|
770
|
+
throw new Error("newMsgId is required for this action.");
|
|
771
|
+
}
|
|
772
|
+
const msgContent = requireString(params.msgContent, "msgContent");
|
|
773
|
+
return {
|
|
774
|
+
input: { groupId, newMsgId, msgContent },
|
|
775
|
+
data: await roomAccessApplyCheckApproveGewe({
|
|
776
|
+
account,
|
|
777
|
+
chatroomId: groupId,
|
|
778
|
+
newMsgId,
|
|
779
|
+
msgContent,
|
|
780
|
+
}),
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
case "admin_operate": {
|
|
784
|
+
const groupId = resolveCurrentGroupId();
|
|
785
|
+
const operType = requireNumber(params.operType, "operType");
|
|
786
|
+
const wxids = requireWxidArray(params.wxids, "wxids");
|
|
787
|
+
return {
|
|
788
|
+
input: { groupId, operType, wxids },
|
|
789
|
+
data: await adminOperateGewe({ account, chatroomId: groupId, operType, wxids }),
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
case "save_to_contacts": {
|
|
793
|
+
const groupId = resolveCurrentGroupId();
|
|
794
|
+
const operType = requireNumber(params.operType, "operType");
|
|
795
|
+
return {
|
|
796
|
+
input: { groupId, operType },
|
|
797
|
+
data: await saveContractListGewe({ account, chatroomId: groupId, operType }),
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
case "pin": {
|
|
801
|
+
const groupId = resolveCurrentGroupId();
|
|
802
|
+
if (typeof params.top !== "boolean" && typeof params.top !== "number") {
|
|
803
|
+
throw new Error("top is required for this action.");
|
|
804
|
+
}
|
|
805
|
+
return {
|
|
806
|
+
input: { groupId, top: params.top },
|
|
807
|
+
data: await pinChatGewe({ account, chatroomId: groupId, top: params.top }),
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
case "disband": {
|
|
811
|
+
const groupId = resolveCurrentGroupId();
|
|
812
|
+
return {
|
|
813
|
+
input: { groupId },
|
|
814
|
+
data: await disbandChatroomGewe({ account, chatroomId: groupId }),
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
case "set_silence": {
|
|
818
|
+
const groupId = resolveCurrentGroupId();
|
|
819
|
+
if (typeof params.silence !== "boolean" && typeof params.silence !== "number") {
|
|
820
|
+
throw new Error("silence is required for this action.");
|
|
821
|
+
}
|
|
822
|
+
return {
|
|
823
|
+
input: { groupId, silence: params.silence },
|
|
824
|
+
data: await setMsgSilenceGewe({ account, chatroomId: groupId, silence: params.silence }),
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
case "set_announcement": {
|
|
828
|
+
const groupId = resolveCurrentGroupId();
|
|
829
|
+
const content = requireString(params.content, "content");
|
|
830
|
+
return {
|
|
831
|
+
input: { groupId, content },
|
|
832
|
+
data: await setChatroomAnnouncementGewe({ account, chatroomId: groupId, content }),
|
|
833
|
+
};
|
|
834
|
+
}
|
|
835
|
+
case "quit": {
|
|
836
|
+
const groupId = resolveCurrentGroupId();
|
|
837
|
+
return {
|
|
838
|
+
input: { groupId },
|
|
839
|
+
data: await quitChatroomGewe({ account, chatroomId: groupId }),
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
case "invite": {
|
|
843
|
+
const groupId = resolveCurrentGroupId();
|
|
844
|
+
const wxids = requireWxidArray(params.wxids, "wxids");
|
|
845
|
+
const reason = requireString(params.reason, "reason");
|
|
846
|
+
return {
|
|
847
|
+
input: { groupId, wxids, reason },
|
|
848
|
+
data: await inviteMemberGewe({ account, chatroomId: groupId, wxids, reason }),
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
default:
|
|
852
|
+
return unknownToolActionResult("gewe_groups", params.action);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
async function executeMomentsTool(
|
|
857
|
+
ctx: OpenClawPluginToolContext,
|
|
858
|
+
params: MomentsToolParams,
|
|
859
|
+
) {
|
|
860
|
+
const { account } = resolveGeweToolAccount({
|
|
861
|
+
ctx,
|
|
862
|
+
rawAccountId: params.accountId,
|
|
863
|
+
});
|
|
864
|
+
const visibilityInput = buildMomentsVisibilityInput(params);
|
|
865
|
+
|
|
866
|
+
switch (params.action) {
|
|
867
|
+
case "list_self":
|
|
868
|
+
return {
|
|
869
|
+
input: {
|
|
870
|
+
...(params.maxId !== undefined ? { maxId: params.maxId } : {}),
|
|
871
|
+
...(params.decrypt !== undefined ? { decrypt: params.decrypt } : {}),
|
|
872
|
+
...(params.firstPageMd5 ? { firstPageMd5: params.firstPageMd5 } : {}),
|
|
873
|
+
},
|
|
874
|
+
data: await snsListGewe({
|
|
875
|
+
account,
|
|
876
|
+
...(params.maxId !== undefined ? { maxId: params.maxId } : {}),
|
|
877
|
+
...(params.decrypt !== undefined ? { decrypt: params.decrypt } : {}),
|
|
878
|
+
...(params.firstPageMd5 ? { firstPageMd5: params.firstPageMd5 } : {}),
|
|
879
|
+
}),
|
|
880
|
+
};
|
|
881
|
+
case "list_contact": {
|
|
882
|
+
const wxid = resolveSingleWxid({
|
|
883
|
+
ctx,
|
|
884
|
+
rawWxid: params.wxid,
|
|
885
|
+
fieldLabel: "wxid",
|
|
886
|
+
});
|
|
887
|
+
return {
|
|
888
|
+
input: {
|
|
889
|
+
wxid,
|
|
890
|
+
...(params.maxId !== undefined ? { maxId: params.maxId } : {}),
|
|
891
|
+
...(params.decrypt !== undefined ? { decrypt: params.decrypt } : {}),
|
|
892
|
+
...(params.firstPageMd5 ? { firstPageMd5: params.firstPageMd5 } : {}),
|
|
893
|
+
},
|
|
894
|
+
data: await contactsSnsListGewe({
|
|
895
|
+
account,
|
|
896
|
+
wxid,
|
|
897
|
+
...(params.maxId !== undefined ? { maxId: params.maxId } : {}),
|
|
898
|
+
...(params.decrypt !== undefined ? { decrypt: params.decrypt } : {}),
|
|
899
|
+
...(params.firstPageMd5 ? { firstPageMd5: params.firstPageMd5 } : {}),
|
|
900
|
+
}),
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
case "detail": {
|
|
904
|
+
const snsId = requireString(params.snsId, "snsId");
|
|
905
|
+
return {
|
|
906
|
+
input: { snsId },
|
|
907
|
+
data: await snsDetailsGewe({ account, snsId }),
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
case "download_video": {
|
|
911
|
+
const snsXml = requireString(params.snsXml, "snsXml");
|
|
912
|
+
return {
|
|
913
|
+
input: { snsXml },
|
|
914
|
+
data: await downloadSnsVideoGewe({ account, snsXml }),
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
case "upload_image": {
|
|
918
|
+
const imgUrls = requireStringArray(params.imgUrls, "imgUrls");
|
|
919
|
+
return {
|
|
920
|
+
input: { imgUrls },
|
|
921
|
+
data: await uploadSnsImageGewe({ account, imgUrls }),
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
case "upload_video": {
|
|
925
|
+
const thumbUrl = requireString(params.thumbUrl, "thumbUrl");
|
|
926
|
+
const videoUrl = requireString(params.videoUrl, "videoUrl");
|
|
927
|
+
return {
|
|
928
|
+
input: { thumbUrl, videoUrl },
|
|
929
|
+
data: await uploadSnsVideoGewe({ account, thumbUrl, videoUrl }),
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
case "delete": {
|
|
933
|
+
const snsId = requireString(params.snsId, "snsId");
|
|
934
|
+
return {
|
|
935
|
+
input: { snsId },
|
|
936
|
+
data: await delSnsGewe({ account, snsId }),
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
case "post_text": {
|
|
940
|
+
const content = requireString(params.content, "content");
|
|
941
|
+
return {
|
|
942
|
+
input: { content, ...visibilityInput },
|
|
943
|
+
data: await sendTextSnsGewe({ account, content, ...visibilityInput }),
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
case "post_image": {
|
|
947
|
+
const imgInfos = requireObjectArray(params.imgInfos, "imgInfos");
|
|
948
|
+
return {
|
|
949
|
+
input: {
|
|
950
|
+
imgInfos,
|
|
951
|
+
...(params.content ? { content: params.content } : {}),
|
|
952
|
+
...visibilityInput,
|
|
953
|
+
},
|
|
954
|
+
data: await sendImgSnsGewe({
|
|
955
|
+
account,
|
|
956
|
+
imgInfos,
|
|
957
|
+
...(params.content ? { content: params.content } : {}),
|
|
958
|
+
...visibilityInput,
|
|
959
|
+
}),
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
case "post_video": {
|
|
963
|
+
const videoInfo = requireObject(params.videoInfo, "videoInfo");
|
|
964
|
+
return {
|
|
965
|
+
input: {
|
|
966
|
+
videoInfo,
|
|
967
|
+
...(params.content ? { content: params.content } : {}),
|
|
968
|
+
...visibilityInput,
|
|
969
|
+
},
|
|
970
|
+
data: await sendVideoSnsGewe({
|
|
971
|
+
account,
|
|
972
|
+
videoInfo,
|
|
973
|
+
...(params.content ? { content: params.content } : {}),
|
|
974
|
+
...visibilityInput,
|
|
975
|
+
}),
|
|
976
|
+
};
|
|
977
|
+
}
|
|
978
|
+
case "post_link": {
|
|
979
|
+
const thumbUrl = requireString(params.thumbUrl, "thumbUrl");
|
|
980
|
+
const linkUrl = requireString(params.linkUrl, "linkUrl");
|
|
981
|
+
const title = requireString(params.title, "title");
|
|
982
|
+
const description = requireString(params.description, "description");
|
|
983
|
+
return {
|
|
984
|
+
input: {
|
|
985
|
+
thumbUrl,
|
|
986
|
+
linkUrl,
|
|
987
|
+
title,
|
|
988
|
+
description,
|
|
989
|
+
...(params.content ? { content: params.content } : {}),
|
|
990
|
+
...visibilityInput,
|
|
991
|
+
},
|
|
992
|
+
data: await sendUrlSnsGewe({
|
|
993
|
+
account,
|
|
994
|
+
thumbUrl,
|
|
995
|
+
linkUrl,
|
|
996
|
+
title,
|
|
997
|
+
description,
|
|
998
|
+
...(params.content ? { content: params.content } : {}),
|
|
999
|
+
...visibilityInput,
|
|
1000
|
+
}),
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
case "set_stranger_visibility": {
|
|
1004
|
+
const enabled = requireBoolean(params.enabled, "enabled");
|
|
1005
|
+
return {
|
|
1006
|
+
input: { enabled },
|
|
1007
|
+
data: await strangerVisibilityEnabledGewe({ account, enabled }),
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
1010
|
+
case "set_visible_scope": {
|
|
1011
|
+
const option = requireNumber(params.option, "option");
|
|
1012
|
+
return {
|
|
1013
|
+
input: { option },
|
|
1014
|
+
data: await snsVisibleScopeGewe({ account, option }),
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
case "set_privacy": {
|
|
1018
|
+
const snsId = requireString(params.snsId, "snsId");
|
|
1019
|
+
const open = requireBoolean(params.open, "open");
|
|
1020
|
+
return {
|
|
1021
|
+
input: { snsId, open },
|
|
1022
|
+
data: await snsSetPrivacyGewe({ account, snsId, open }),
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
case "like": {
|
|
1026
|
+
const snsId = requireString(params.snsId, "snsId");
|
|
1027
|
+
const operType = requireNumber(params.operType, "operType");
|
|
1028
|
+
const wxid = resolveSingleWxid({
|
|
1029
|
+
ctx,
|
|
1030
|
+
rawWxid: params.wxid,
|
|
1031
|
+
fieldLabel: "wxid",
|
|
1032
|
+
});
|
|
1033
|
+
return {
|
|
1034
|
+
input: { snsId, operType, wxid },
|
|
1035
|
+
data: await likeSnsGewe({ account, snsId, operType, wxid }),
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
case "comment": {
|
|
1039
|
+
const snsId = requireString(params.snsId, "snsId");
|
|
1040
|
+
const operType = requireNumber(params.operType, "operType");
|
|
1041
|
+
const wxid = resolveSingleWxid({
|
|
1042
|
+
ctx,
|
|
1043
|
+
rawWxid: params.wxid,
|
|
1044
|
+
fieldLabel: "wxid",
|
|
1045
|
+
});
|
|
1046
|
+
return {
|
|
1047
|
+
input: {
|
|
1048
|
+
snsId,
|
|
1049
|
+
operType,
|
|
1050
|
+
wxid,
|
|
1051
|
+
...(params.commentId !== undefined ? { commentId: params.commentId } : {}),
|
|
1052
|
+
...(params.content ? { content: params.content } : {}),
|
|
1053
|
+
},
|
|
1054
|
+
data: await commentSnsGewe({
|
|
1055
|
+
account,
|
|
1056
|
+
snsId,
|
|
1057
|
+
operType,
|
|
1058
|
+
wxid,
|
|
1059
|
+
...(params.commentId !== undefined ? { commentId: params.commentId } : {}),
|
|
1060
|
+
...(params.content ? { content: params.content } : {}),
|
|
1061
|
+
}),
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
case "forward": {
|
|
1065
|
+
const snsXml = requireString(params.snsXml, "snsXml");
|
|
1066
|
+
return {
|
|
1067
|
+
input: { snsXml, ...visibilityInput },
|
|
1068
|
+
data: await forwardSnsGewe({ account, snsXml, ...visibilityInput }),
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
default:
|
|
1072
|
+
return unknownToolActionResult("gewe_moments", params.action);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
async function executePersonalTool(
|
|
1077
|
+
ctx: OpenClawPluginToolContext,
|
|
1078
|
+
params: PersonalToolParams,
|
|
1079
|
+
) {
|
|
1080
|
+
const { account } = resolveGeweToolAccount({
|
|
1081
|
+
ctx,
|
|
1082
|
+
rawAccountId: params.accountId,
|
|
1083
|
+
});
|
|
1084
|
+
|
|
1085
|
+
switch (params.action) {
|
|
1086
|
+
case "profile":
|
|
1087
|
+
return {
|
|
1088
|
+
input: {},
|
|
1089
|
+
data: await getProfileGewe({ account }),
|
|
1090
|
+
};
|
|
1091
|
+
case "qrcode":
|
|
1092
|
+
return {
|
|
1093
|
+
input: {},
|
|
1094
|
+
data: await getQrCodeGewe({ account }),
|
|
1095
|
+
};
|
|
1096
|
+
case "safety_info":
|
|
1097
|
+
return {
|
|
1098
|
+
input: {},
|
|
1099
|
+
data: await getSafetyInfoGewe({ account }),
|
|
1100
|
+
};
|
|
1101
|
+
case "update_profile": {
|
|
1102
|
+
const country = requireString(params.country, "country");
|
|
1103
|
+
const province = requireString(params.province, "province");
|
|
1104
|
+
const nickName = requireString(params.nickName, "nickName");
|
|
1105
|
+
const sex = requireNumber(params.sex, "sex");
|
|
1106
|
+
const signature = requireString(params.signature, "signature");
|
|
1107
|
+
return {
|
|
1108
|
+
input: {
|
|
1109
|
+
country,
|
|
1110
|
+
province,
|
|
1111
|
+
nickName,
|
|
1112
|
+
sex,
|
|
1113
|
+
signature,
|
|
1114
|
+
...(params.city ? { city: params.city.trim() } : {}),
|
|
1115
|
+
},
|
|
1116
|
+
data: await updateProfileGewe({
|
|
1117
|
+
account,
|
|
1118
|
+
country,
|
|
1119
|
+
province,
|
|
1120
|
+
nickName,
|
|
1121
|
+
sex,
|
|
1122
|
+
signature,
|
|
1123
|
+
...(params.city ? { city: params.city.trim() } : {}),
|
|
1124
|
+
}),
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
case "update_avatar": {
|
|
1128
|
+
const headImgUrl = requireString(params.headImgUrl, "headImgUrl");
|
|
1129
|
+
return {
|
|
1130
|
+
input: { headImgUrl },
|
|
1131
|
+
data: await updateHeadImgGewe({ account, headImgUrl }),
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
case "privacy": {
|
|
1135
|
+
const open = requireBoolean(params.open, "open");
|
|
1136
|
+
return {
|
|
1137
|
+
input: {
|
|
1138
|
+
open,
|
|
1139
|
+
...(typeof params.option === "number" ? { option: params.option } : {}),
|
|
1140
|
+
},
|
|
1141
|
+
data: await privacySettingsGewe({
|
|
1142
|
+
account,
|
|
1143
|
+
open,
|
|
1144
|
+
...(typeof params.option === "number" ? { option: params.option } : {}),
|
|
1145
|
+
}),
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
default:
|
|
1149
|
+
return unknownToolActionResult("gewe_personal", params.action);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
export function createGeweApiTools(ctx: OpenClawPluginToolContext): AnyAgentTool[] {
|
|
1154
|
+
return [
|
|
1155
|
+
{
|
|
1156
|
+
name: "gewe_contacts",
|
|
1157
|
+
label: "GeWe Contacts",
|
|
1158
|
+
description:
|
|
1159
|
+
"GeWe contacts operations. Actions: list, list_cache, brief, detail, search, search_im, im_detail, check_relation, set_remark, set_only_chat, delete, add, add_im, sync_im, phones_get, phones_upload.",
|
|
1160
|
+
ownerOnly: true,
|
|
1161
|
+
parameters: ContactsToolSchema,
|
|
1162
|
+
execute: async (_toolCallId, rawParams) => {
|
|
1163
|
+
const params = ContactsToolSchema.parse(rawParams ?? {});
|
|
1164
|
+
try {
|
|
1165
|
+
const result = await executeContactsTool(ctx, params);
|
|
1166
|
+
if ("details" in result) {
|
|
1167
|
+
return result;
|
|
1168
|
+
}
|
|
1169
|
+
return jsonToolResult({
|
|
1170
|
+
ok: true,
|
|
1171
|
+
tool: "gewe_contacts",
|
|
1172
|
+
action: params.action,
|
|
1173
|
+
accountId: resolveGeweToolAccount({ ctx, rawAccountId: params.accountId }).account.accountId,
|
|
1174
|
+
input: result.input,
|
|
1175
|
+
data: result.data,
|
|
1176
|
+
});
|
|
1177
|
+
} catch (error) {
|
|
1178
|
+
return toolExecutionErrorResult("gewe_contacts", params.action, error);
|
|
1179
|
+
}
|
|
1180
|
+
},
|
|
1181
|
+
},
|
|
1182
|
+
{
|
|
1183
|
+
name: "gewe_groups",
|
|
1184
|
+
label: "GeWe Groups",
|
|
1185
|
+
description:
|
|
1186
|
+
"GeWe group operations. Actions: info, announcement, members, member_detail, qr_code, set_self_nickname, rename, set_remark, create, remove_members, agree_join, join_via_qr, add_member_as_friend, approve_join_request, admin_operate, save_to_contacts, pin, disband, set_silence, set_announcement, quit, invite.",
|
|
1187
|
+
ownerOnly: true,
|
|
1188
|
+
parameters: GroupsToolSchema,
|
|
1189
|
+
execute: async (_toolCallId, rawParams) => {
|
|
1190
|
+
const params = GroupsToolSchema.parse(rawParams ?? {});
|
|
1191
|
+
try {
|
|
1192
|
+
const result = await executeGroupsTool(ctx, params);
|
|
1193
|
+
if ("details" in result) {
|
|
1194
|
+
return result;
|
|
1195
|
+
}
|
|
1196
|
+
return jsonToolResult({
|
|
1197
|
+
ok: true,
|
|
1198
|
+
tool: "gewe_groups",
|
|
1199
|
+
action: params.action,
|
|
1200
|
+
accountId: resolveGeweToolAccount({ ctx, rawAccountId: params.accountId }).account.accountId,
|
|
1201
|
+
input: result.input,
|
|
1202
|
+
data: result.data,
|
|
1203
|
+
});
|
|
1204
|
+
} catch (error) {
|
|
1205
|
+
return toolExecutionErrorResult("gewe_groups", params.action, error);
|
|
1206
|
+
}
|
|
1207
|
+
},
|
|
1208
|
+
},
|
|
1209
|
+
{
|
|
1210
|
+
name: "gewe_moments",
|
|
1211
|
+
label: "GeWe Moments",
|
|
1212
|
+
description:
|
|
1213
|
+
"GeWe Moments operations. Actions: list_self, list_contact, detail, download_video, upload_image, upload_video, delete, post_text, post_image, post_video, post_link, set_stranger_visibility, set_visible_scope, set_privacy, like, comment, forward.",
|
|
1214
|
+
ownerOnly: true,
|
|
1215
|
+
parameters: MomentsToolSchema,
|
|
1216
|
+
execute: async (_toolCallId, rawParams) => {
|
|
1217
|
+
const params = MomentsToolSchema.parse(rawParams ?? {});
|
|
1218
|
+
try {
|
|
1219
|
+
const result = await executeMomentsTool(ctx, params);
|
|
1220
|
+
if ("details" in result) {
|
|
1221
|
+
return result;
|
|
1222
|
+
}
|
|
1223
|
+
return jsonToolResult({
|
|
1224
|
+
ok: true,
|
|
1225
|
+
tool: "gewe_moments",
|
|
1226
|
+
action: params.action,
|
|
1227
|
+
accountId: resolveGeweToolAccount({ ctx, rawAccountId: params.accountId }).account.accountId,
|
|
1228
|
+
input: result.input,
|
|
1229
|
+
data: result.data,
|
|
1230
|
+
});
|
|
1231
|
+
} catch (error) {
|
|
1232
|
+
return toolExecutionErrorResult("gewe_moments", params.action, error);
|
|
1233
|
+
}
|
|
1234
|
+
},
|
|
1235
|
+
},
|
|
1236
|
+
{
|
|
1237
|
+
name: "gewe_personal",
|
|
1238
|
+
label: "GeWe Personal",
|
|
1239
|
+
description:
|
|
1240
|
+
"GeWe personal-account operations. Actions: profile, qrcode, safety_info, update_profile, update_avatar, privacy.",
|
|
1241
|
+
ownerOnly: true,
|
|
1242
|
+
parameters: PersonalToolSchema,
|
|
1243
|
+
execute: async (_toolCallId, rawParams) => {
|
|
1244
|
+
const params = PersonalToolSchema.parse(rawParams ?? {});
|
|
1245
|
+
try {
|
|
1246
|
+
const result = await executePersonalTool(ctx, params);
|
|
1247
|
+
if ("details" in result) {
|
|
1248
|
+
return result;
|
|
1249
|
+
}
|
|
1250
|
+
return jsonToolResult({
|
|
1251
|
+
ok: true,
|
|
1252
|
+
tool: "gewe_personal",
|
|
1253
|
+
action: params.action,
|
|
1254
|
+
accountId: resolveGeweToolAccount({ ctx, rawAccountId: params.accountId }).account.accountId,
|
|
1255
|
+
input: result.input,
|
|
1256
|
+
data: result.data,
|
|
1257
|
+
});
|
|
1258
|
+
} catch (error) {
|
|
1259
|
+
return toolExecutionErrorResult("gewe_personal", params.action, error);
|
|
1260
|
+
}
|
|
1261
|
+
},
|
|
1262
|
+
},
|
|
1263
|
+
];
|
|
1264
|
+
}
|