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.
Files changed (44) hide show
  1. package/README.md +455 -3
  2. package/index.ts +39 -1
  3. package/package.json +12 -1
  4. package/skills/gewe-agent-tools/SKILL.md +113 -0
  5. package/skills/gewe-channel-rules/SKILL.md +7 -0
  6. package/src/accounts.ts +51 -5
  7. package/src/api-tools.ts +1264 -0
  8. package/src/api.ts +37 -2
  9. package/src/binary-command.ts +65 -0
  10. package/src/channel-actions.ts +536 -0
  11. package/src/channel-allowlist.ts +150 -0
  12. package/src/channel-directory.ts +419 -0
  13. package/src/channel-status.ts +186 -0
  14. package/src/channel.ts +155 -58
  15. package/src/config-edit.ts +94 -0
  16. package/src/config-schema.ts +78 -3
  17. package/src/contacts-api.ts +113 -0
  18. package/src/delivery.ts +502 -62
  19. package/src/directory-cache.ts +164 -0
  20. package/src/gewe-account-api.ts +27 -0
  21. package/src/group-allowlist-tool.ts +242 -0
  22. package/src/group-binding-tool.ts +154 -0
  23. package/src/group-binding.ts +405 -0
  24. package/src/groups-api.ts +146 -0
  25. package/src/inbound-batch.ts +5 -2
  26. package/src/inbound.ts +248 -41
  27. package/src/media-server.ts +73 -93
  28. package/src/moments-api.ts +138 -0
  29. package/src/monitor.ts +81 -24
  30. package/src/onboarding.ts +9 -4
  31. package/src/openclaw-compat.ts +1070 -0
  32. package/src/pairing-store.ts +478 -0
  33. package/src/personal-api.ts +45 -0
  34. package/src/policy.ts +130 -22
  35. package/src/quote-context-cache.ts +97 -0
  36. package/src/reply-options.ts +101 -2
  37. package/src/s3.ts +1 -1
  38. package/src/send.ts +235 -16
  39. package/src/setup-wizard-types.ts +162 -0
  40. package/src/setup-wizard.ts +464 -0
  41. package/src/silk.ts +2 -1
  42. package/src/state-paths.ts +55 -14
  43. package/src/types.ts +66 -7
  44. package/src/xml.ts +158 -0
package/README.md CHANGED
@@ -48,6 +48,8 @@ openclaw onboard
48
48
 
49
49
  直接编辑 `~/.openclaw/openclaw.json` 的 `channels.gewe-openclaw` 段落(见下方示例)。
50
50
 
51
+ 完整配置手册见:[docs/openclaw-json-config.md](docs/openclaw-json-config.md)
52
+
51
53
  ## 配置
52
54
 
53
55
  插件配置放在 `~/.openclaw/openclaw.json` 的 `channels.gewe-openclaw`,并确保通道开启(示例仅保留必填/常用字段):
@@ -107,14 +109,440 @@ openclaw onboard
107
109
  - `voiceSilkPipe`:是否启用 ffmpeg+rust-silk 的 stdin/stdout 管道(默认关闭;失败会回退到临时文件)。
108
110
  - 低频/非高并发且磁盘压力不高时,推荐临时文件方案(更稳定/更快)。
109
111
  - 高频/多并发或磁盘压力大时,推荐 pipe 方案(减少磁盘 IO)。
110
- - `voiceDecodePath`/`voiceDecodeArgs`/`voiceDecodeOutput`:自定义 silk 解码器(入站语音转写用)。
111
- - `mediaMaxMb`:上传媒体大小上限(默认 20MB)。
112
- - `downloadMinDelayMs`/`downloadMaxDelayMs`:入站媒体下载节流。
112
+ - `voiceDecodePath`/`voiceDecodeArgs`/`voiceDecodeOutput`:自定义 silk 解码器(入站语音转写用)。
113
+ - `mediaMaxMb`:上传媒体大小上限(默认 20MB)。
114
+ - `downloadMinDelayMs`/`downloadMaxDelayMs`:入站媒体下载节流。
115
+ - `autoQuoteReply`:是否开启 `replyToId + 纯文本` 自动引用回复(默认开启;设为 `false` 可关闭)。
116
+
117
+ ## 群聊/私聊触发与回复规则
118
+
119
+ `groups` 和 `dms` 都支持 `*` 默认项 + 精确项覆写:
120
+
121
+ - `groups["*"]` / `groups["<roomId>@chatroom"]`
122
+ - `dms["*"]` / `dms["<wxid>"]`
123
+
124
+ 局部规则可继续搭配既有字段一起使用,例如 `allowFrom`、`skills`、`systemPrompt`、`tools`(仅群聊)。
125
+
126
+ ### 群聊触发
127
+
128
+ `groups[*].trigger.mode` 支持:
129
+
130
+ - `at`:只有被 `@` 时触发
131
+ - `quote`:只有引用机器人消息时触发
132
+ - `at_or_quote`:`@` 或引用机器人消息都触发
133
+ - `any_message`:任何消息都触发
134
+
135
+ 群聊默认值是 `at`。
136
+
137
+ ### 群聊回复
138
+
139
+ `groups[*].reply.mode` 支持:
140
+
141
+ - `plain`:普通回复
142
+ - `quote_source`:首条回复自动引用当前入站消息
143
+ - `at_sender`:首条文本回复自动 `@` 发送者
144
+ - `quote_and_at`:首条文本回复同时引用并 `@`;非文本回复会自动退化为 `quote_source`
145
+
146
+ 群聊默认值会跟随 `autoQuoteReply`:
147
+
148
+ - 未配置或为 `true`:默认 `quote_source`
149
+ - 显式设为 `false`:默认 `plain`
150
+
151
+ ### 私聊触发与回复
152
+
153
+ `dms[*].trigger.mode` 支持:
154
+
155
+ - `any_message`
156
+ - `quote`
157
+
158
+ `dms[*].reply.mode` 支持:
159
+
160
+ - `plain`
161
+ - `quote_source`
162
+
163
+ 私聊默认触发是 `any_message`。私聊默认回复也会跟随 `autoQuoteReply` 回退到 `quote_source` 或 `plain`。
164
+
165
+ ### 兼容旧配置
166
+
167
+ - `requireMention: true/false` 仍然可用,会分别映射到群聊 `trigger.mode = "at"` / `"any_message"`
168
+ - 新的 `trigger` / `reply` 配置优先级更高
169
+ - `autoQuoteReply` 现在主要用于“未显式配置 `reply.mode` 时”的默认值回退
170
+
171
+ 示例:
172
+
173
+ ```json5
174
+ {
175
+ "channels": {
176
+ "gewe-openclaw": {
177
+ "groupPolicy": "open",
178
+ "groups": {
179
+ "*": {
180
+ "trigger": { "mode": "at" },
181
+ "reply": { "mode": "quote_source" }
182
+ },
183
+ "project-room@chatroom": {
184
+ "trigger": { "mode": "at_or_quote" },
185
+ "reply": { "mode": "quote_and_at" },
186
+ "skills": ["project-skill"]
187
+ },
188
+ "ops-room@chatroom": {
189
+ "trigger": { "mode": "any_message" },
190
+ "reply": { "mode": "plain" }
191
+ }
192
+ },
193
+ "dms": {
194
+ "*": {
195
+ "reply": { "mode": "quote_source" }
196
+ },
197
+ "wxid_special": {
198
+ "trigger": { "mode": "quote" },
199
+ "systemPrompt": "Only handle quoted follow-ups."
200
+ }
201
+ }
202
+ }
203
+ }
204
+ }
205
+ ```
206
+
207
+ ## 目录、Allowlist 与状态
208
+
209
+ GeWe 现在补齐了目录、标准 allowlist 适配和状态摘要。
210
+
211
+ ### 目录
212
+
213
+ 目录会混合这些来源:
214
+
215
+ - `allowFrom`、`groupAllowFrom`、`dms`、`groups`
216
+ - 顶层 `bindings[]` 里命中的 GeWe 群
217
+ - 运行中见过的私聊对象、群、群成员
218
+
219
+ 支持的目录能力:
220
+
221
+ - `self`:查看当前账号自己的 `wxid` 和昵称
222
+ - `listPeers`:查看已知私聊对象
223
+ - `listGroups`:查看已知群
224
+ - `listGroupMembers`:按需读取某个群的实时成员列表
225
+
226
+ 其中 `listGroupMembers` 会 live 调用 GeWe 的 `getChatroomInfo`,结果也会反哺后续名字解析。
227
+
228
+ ### Allowlist
229
+
230
+ 标准 `/allowlist` 入口负责顶层两类名单:
231
+
232
+ - 私聊:`allowFrom`
233
+ - 群发言人:`groupAllowFrom`
234
+
235
+ 如果你要管理“某一个群自己的 `groups.<groupId>.allowFrom` 覆盖”,请用插件工具:
236
+
237
+ - `gewe_manage_group_allowlist`
238
+
239
+ 它支持:
240
+
241
+ - `inspect`
242
+ - `add`
243
+ - `remove`
244
+ - `replace`
245
+ - `clear`
246
+
247
+ 示例:
248
+
249
+ ```json5
250
+ {
251
+ "mode": "replace",
252
+ "groupId": "ops-room@chatroom",
253
+ "entries": ["wxid_admin_1", "wxid_admin_2"]
254
+ }
255
+ ```
256
+
257
+ 如果你就在目标群里调用,`groupId` 可以省略;工具会自动用当前群。
258
+
259
+ ### 状态
260
+
261
+ GeWe 的状态页现在会额外显示:
262
+
263
+ - API 是否可达、探测延迟
264
+ - 当前账号自己的 `wxid` / 昵称
265
+ - 已知私聊对象数、已知群数、已缓存群成员数
266
+ - 显式 `bindings[]` 数量
267
+ - 群局部 allowlist 覆盖数量
268
+ - pairing 本地 allow-from 数量
269
+
270
+ ## 把群绑定到 Agent / ACP
271
+
272
+ 除了 `channels.gewe-openclaw` 这一段插件配置,GeWe 还支持配合 OpenClaw 顶层 `bindings[]` 使用。
273
+
274
+ 可以把它理解成两层:
275
+
276
+ - 顶层 `bindings[]` 决定“这个群/私聊归哪个 agent,或者归哪个 ACP 持久会话”
277
+ - `groups.<groupId>.bindingIdentity` 决定“绑定以后,机器人在这个群里显示成什么身份”
278
+
279
+ ### 绑定到普通 Agent
280
+
281
+ 下面这个例子表示:`ops-room@chatroom` 这个群固定交给 `ops` agent 处理。
282
+
283
+ ```json5
284
+ {
285
+ "bindings": [
286
+ {
287
+ "type": "route",
288
+ "agentId": "ops",
289
+ "match": {
290
+ "channel": "gewe-openclaw",
291
+ "accountId": "work",
292
+ "peer": {
293
+ "kind": "group",
294
+ "id": "ops-room@chatroom"
295
+ }
296
+ }
297
+ }
298
+ ],
299
+ "channels": {
300
+ "gewe-openclaw": {
301
+ "accounts": {
302
+ "work": {
303
+ "groups": {
304
+ "ops-room@chatroom": {
305
+ "trigger": { "mode": "at_or_quote" },
306
+ "reply": { "mode": "quote_and_at" }
307
+ }
308
+ }
309
+ }
310
+ }
311
+ }
312
+ }
313
+ }
314
+ ```
315
+
316
+ 说明:
317
+
318
+ - `match.channel` 写 `gewe-openclaw`
319
+ - `match.accountId` 可写具体账号,也可以写 `"*"`
320
+ - 群聊 `peer.kind` 写 `"group"`,`peer.id` 直接写 `群ID@chatroom`
321
+ - `bindings[]` 用于描述群或私聊与 agent 的绑定关系
322
+
323
+ ### 绑定到 ACP 持久会话
324
+
325
+ 下面这个例子表示:这个群固定进入 `codex` agent 的一个 ACP 持久会话。
326
+
327
+ ```json5
328
+ {
329
+ "bindings": [
330
+ {
331
+ "type": "acp",
332
+ "agentId": "codex",
333
+ "match": {
334
+ "channel": "gewe-openclaw",
335
+ "accountId": "work",
336
+ "peer": {
337
+ "kind": "group",
338
+ "id": "repo-room@chatroom"
339
+ }
340
+ },
341
+ "acp": {
342
+ "label": "repo-room",
343
+ "mode": "persistent",
344
+ "cwd": "/workspace/repo-a",
345
+ "backend": "acpx"
346
+ }
347
+ }
348
+ ]
349
+ }
350
+ ```
351
+
352
+ 说明:
353
+
354
+ - GeWe 群没有 Telegram topic / Feishu thread 这种层级,所以 ACP 绑定语义是“整群共享一个 ACP 会话”
355
+ - 同一个群只配置一种绑定方式,不要同时配置普通 route binding 和 ACP binding
356
+
357
+ ### 群里的绑定身份
358
+
359
+ `groups.<groupId>.bindingIdentity` 用来描述“这个群已经绑定到 agent 后,机器人在群里应该显示成什么样”。
360
+
361
+ 当前只同步两项:
362
+
363
+ - 机器人自己的群昵称 `selfNickname`
364
+ - 这个群在机器人侧的备注 `remark`
365
+
366
+ 不会改群名。
367
+
368
+ ```json5
369
+ {
370
+ "channels": {
371
+ "gewe-openclaw": {
372
+ "groups": {
373
+ "*": {
374
+ "bindingIdentity": {
375
+ "enabled": true,
376
+ "selfNickname": { "source": "agent_name" },
377
+ "remark": { "source": "agent_id" }
378
+ }
379
+ },
380
+ "repo-room@chatroom": {
381
+ "bindingIdentity": {
382
+ "remark": { "source": "name_and_id" }
383
+ }
384
+ }
385
+ }
386
+ }
387
+ }
388
+ }
389
+ ```
390
+
391
+ 默认值:
392
+
393
+ - `enabled = true`
394
+ - `selfNickname.source = "agent_name"`
395
+ - `remark.source = "agent_id"`
396
+
397
+ 可选值:
398
+
399
+ - `selfNickname.source`: `agent_name | agent_id | literal`
400
+ - `remark.source`: `agent_id | agent_name | name_and_id | literal`
401
+
402
+ 当 `source = "literal"` 时,需要额外提供 `value`。
403
+
404
+ ### 手动同步群绑定身份
405
+
406
+ 插件提供了一个仅 owner 可用的工具:`gewe_sync_group_binding`。
407
+
408
+ 它不会在启动时自动改微信群信息,而是采用手动同步流程:
409
+
410
+ 1. 先配置顶层 `bindings[]`
411
+ 2. 再按需配置 `groups.<groupId>.bindingIdentity`
412
+ 3. 最后由 owner 调用 `gewe_sync_group_binding`
413
+
414
+ 工具参数:
415
+
416
+ ```json5
417
+ {
418
+ "mode": "inspect", // inspect | dry_run | apply
419
+ "groupId": "repo-room@chatroom", // 可选;在当前绑定群里可自动推断
420
+ "accountId": "work", // 可选;默认当前账号
421
+ "syncSelfNickname": true,
422
+ "syncRemark": true
423
+ }
424
+ ```
425
+
426
+ 三个模式的区别:
427
+
428
+ - `inspect`:查看当前值、期望值、会改哪些字段
429
+ - `dry_run`:和 `inspect` 类似,但明确用于“准备执行前预演”
430
+ - `apply`:只在字段真的发生变化时调用 GeWe API
431
+
432
+ 使用限制:
433
+
434
+ - 只接受“有显式 binding 的群”,不会对仅靠默认 main route 命中的群做推断同步
435
+ - `bindingIdentity.enabled = false` 的群不能执行同步
436
+ - 在非群上下文里调用时,必须显式传 `groupId`
113
437
 
114
438
  发送媒体时的 URL 策略:
115
439
  - 本地文件:优先上传 S3,失败回退 `mediaPublicUrl` 本地反代。
116
440
  - 公网 URL:先尝试原 URL 发送,失败后再尝试上传 S3,仍失败回退本地反代。
117
441
 
442
+ ## 富消息与消息复用
443
+
444
+ 除了直接构造 `channelData["gewe-openclaw"]`,现在也可以通过共享 `message` 工具走标准动作:
445
+
446
+ - `send`
447
+ - `reply`
448
+ - `unsend`
449
+
450
+ 并在参数里附带一个 `gewe` 对象来表达微信专属语义。
451
+
452
+ 示例:在当前群里回复并做部分引用
453
+
454
+ ```json5
455
+ {
456
+ "action": "reply",
457
+ "message": "收到,我接着处理",
458
+ "gewe": {
459
+ "quote": {
460
+ "partialText": "需要继续跟进的那一段"
461
+ }
462
+ }
463
+ }
464
+ ```
465
+
466
+ 示例:撤回一条已经发出的消息
467
+
468
+ ```json5
469
+ {
470
+ "action": "unsend",
471
+ "to": "ops-room@chatroom",
472
+ "messageId": "10001",
473
+ "newMessageId": "10002",
474
+ "createTime": "1710000002"
475
+ }
476
+ ```
477
+
478
+ 插件支持通过 `channelData["gewe-openclaw"]` 传入 GeWe 专有消息语义。结构如下:
479
+
480
+ - `appMsg: { appmsg }`:直接发送 `<appmsg>` XML。
481
+ - `quoteReply: { svrid?, title?, atWxid? }`:发送引用回复;未提供 `svrid` 时会回退到宿主 `replyToId`。
482
+ - `emoji: { emojiMd5, emojiSize }`:发送表情。
483
+ - `nameCard: { nickName, nameCardWxid }`:发送名片。
484
+ - `miniApp: { miniAppId, displayName, pagePath, coverImgUrl, title, userName }`:发送小程序。
485
+ - `revoke: { msgId, newMsgId, createTime }`:撤回指定消息。
486
+ - `forward: { kind, xml, coverImgUrl? }`:复用已存在消息 XML 进行二次转发。
487
+ - `kind` 支持 `image | video | file | link | miniApp`
488
+ - `miniApp` 转发额外需要 `coverImgUrl`
489
+
490
+ 示例:
491
+
492
+ ```json
493
+ {
494
+ "channelData": {
495
+ "gewe-openclaw": {
496
+ "forward": {
497
+ "kind": "link",
498
+ "xml": "<msg>...</msg>"
499
+ }
500
+ }
501
+ }
502
+ }
503
+ ```
504
+
505
+ 引用回复示例:
506
+
507
+ ```json
508
+ {
509
+ "channelData": {
510
+ "gewe-openclaw": {
511
+ "quoteReply": {
512
+ "svrid": "208008054840614808",
513
+ "title": "这条是引用回复",
514
+ "atWxid": "wxid_member_optional"
515
+ }
516
+ }
517
+ }
518
+ }
519
+ ```
520
+
521
+ 另外,普通文本回复如果带有宿主 `replyToId`,插件默认会自动映射为 GeWe 的引用回复气泡;媒体、链接、小程序、撤回、转发等既有富消息分支不会被这条自动桥接抢占。若不希望自动引用,可在配置里设置 `autoQuoteReply: false`。
522
+
523
+ 如果希望让模型主动发“部分引用”,GeWe 通道会识别回复末尾的一行隐藏指令:
524
+
525
+ ```text
526
+ [[GEWE_QUOTE_PARTIAL:要引用的原文片段]]
527
+ ```
528
+
529
+ 插件会在发送前剥离这行指令,并自动转成 `quoteReply.partialText`。通常配合宿主 `replyToId` 一起使用,用来引用当前正在回复的那条消息中的某一段文字。
530
+
531
+ 入站 `appmsg` 现在会尽量保留复用素材,并在上下文中附带:
532
+
533
+ - `MsgType`:原始 GeWe `msgType`
534
+ - `GeWeXml`:原始 XML
535
+ - `GeWeAppMsgXml`:`appmsg` XML
536
+ - `GeWeAppMsgType`:`appmsg` 的 `type`
537
+ - `GeWeQuoteXml`:引用消息原始 XML(当 `type=57` 时)
538
+ - `GeWeQuoteTitle`:引用回复正文
539
+ - `GeWeQuoteType`:被引用消息类型
540
+ - `GeWeQuoteSvrid`:被引用消息 sid
541
+ - `GeWeQuoteFromUsr` / `GeWeQuoteChatUsr` / `GeWeQuoteDisplayName`
542
+ - `GeWeQuoteContent` / `GeWeQuoteMsgSource`
543
+
544
+ 这意味着收到链接、文件通知、引用消息或其他未专门解析的 `appmsg` 后,可以直接取上下文里的 XML 和引用元数据,再走 `forward` / `appMsg` / `quoteReply` 能力完成复用或继续回复。
545
+
118
546
  > 配置变更后需重启 Gateway。
119
547
 
120
548
  ## 高级用法:让未安装插件也出现在 onboarding 列表
@@ -160,6 +588,30 @@ openclaw onboard
160
588
 
161
589
  ## 依赖
162
590
 
591
+ ## 发布(维护者)
592
+
593
+ 仓库已内置 tag 驱动的 npm 发布工作流:
594
+
595
+ - 工作流文件:`.github/workflows/publish-npm.yml`
596
+ - 触发方式:推送 `v*` tag
597
+ - 发布前会自动校验:
598
+ - tag 版本号与 `package.json.version` 一致
599
+ - `CHANGELOG.md` 已包含对应版本标题
600
+ - `npm ci`、`npm test`、`npm pack --dry-run` 全部通过
601
+
602
+ 首次启用前,还需要在 npm 包设置里把这个仓库配置成 Trusted Publisher:
603
+
604
+ - Repository:`Wangnov/gewe-openclaw`
605
+ - Workflow filename:`publish-npm.yml`
606
+
607
+ 日常发版流程:
608
+
609
+ ```bash
610
+ git commit -m "release: 2026.3.23"
611
+ git tag v2026.3.23
612
+ git push origin main v2026.3.23
613
+ ```
614
+
163
615
  ### npm 依赖
164
616
 
165
617
  - `zod`
package/index.ts CHANGED
@@ -1,9 +1,39 @@
1
1
  import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
2
- import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
3
2
 
3
+ import { createGeweApiTools } from "./src/api-tools.js";
4
4
  import { gewePlugin } from "./src/channel.js";
5
+ import { createGeweManageGroupAllowlistTool } from "./src/group-allowlist-tool.js";
6
+ import { createGeweSyncGroupBindingTool } from "./src/group-binding-tool.js";
5
7
  import { setGeweRuntime } from "./src/runtime.js";
6
8
 
9
+ function emptyPluginConfigSchema() {
10
+ return {
11
+ safeParse(value: unknown) {
12
+ if (value === undefined) {
13
+ return { success: true as const, data: undefined };
14
+ }
15
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
16
+ return {
17
+ success: false as const,
18
+ error: { issues: [{ path: [], message: "expected config object" }] },
19
+ };
20
+ }
21
+ if (Object.keys(value as Record<string, unknown>).length > 0) {
22
+ return {
23
+ success: false as const,
24
+ error: { issues: [{ path: [], message: "config must be empty" }] },
25
+ };
26
+ }
27
+ return { success: true as const, data: value };
28
+ },
29
+ jsonSchema: {
30
+ type: "object",
31
+ additionalProperties: false,
32
+ properties: {},
33
+ },
34
+ };
35
+ }
36
+
7
37
  const plugin = {
8
38
  id: "gewe-openclaw",
9
39
  name: "GeWe",
@@ -12,6 +42,14 @@ const plugin = {
12
42
  register(api: OpenClawPluginApi) {
13
43
  setGeweRuntime(api.runtime);
14
44
  api.registerChannel({ plugin: gewePlugin });
45
+ api.registerTool((ctx) => createGeweApiTools(ctx));
46
+ api.registerTool((ctx) => createGeweSyncGroupBindingTool(ctx));
47
+ api.registerTool((ctx) =>
48
+ createGeweManageGroupAllowlistTool(ctx, {
49
+ readConfig: () => api.runtime.config.loadConfig() as never,
50
+ writeConfigFile: async (next) => await api.runtime.config.writeConfigFile(next),
51
+ }),
52
+ );
15
53
  },
16
54
  };
17
55
 
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "gewe-openclaw",
3
- "version": "2026.3.13",
3
+ "version": "2026.3.23",
4
4
  "type": "module",
5
5
  "description": "OpenClaw GeWe channel plugin",
6
6
  "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Wangnov/gewe-openclaw.git"
10
+ },
7
11
  "files": [
8
12
  "index.ts",
9
13
  "openclaw.plugin.json",
@@ -39,11 +43,18 @@
39
43
  "defaultChoice": "npm"
40
44
  }
41
45
  },
46
+ "scripts": {
47
+ "test": "tsx --test src/*.test.ts",
48
+ "release:check": "npm pack --dry-run"
49
+ },
42
50
  "dependencies": {
43
51
  "@aws-sdk/client-s3": "^3.922.0",
44
52
  "@aws-sdk/s3-request-presigner": "^3.922.0",
45
53
  "zod": "^4.3.6"
46
54
  },
55
+ "devDependencies": {
56
+ "tsx": "^4.21.0"
57
+ },
47
58
  "peerDependencies": {
48
59
  "openclaw": ">=2026.1.29"
49
60
  }
@@ -0,0 +1,113 @@
1
+ ---
2
+ name: gewe-agent-tools
3
+ description: Use when an agent needs to inspect or operate GeWe or WeChat contacts, groups, Moments, or the logged-in personal account through the bundled GeWe tools. Triggers include looking up a current DM contact, checking a current group, managing group members, reading or posting Moments, or inspecting the current account profile and QR code.
4
+ metadata:
5
+ {
6
+ "openclaw":
7
+ {
8
+ "emoji": "🟢",
9
+ "skillKey": "gewe-agent-tools",
10
+ "requires": { "config": ["channels.gewe-openclaw"] },
11
+ },
12
+ }
13
+ ---
14
+
15
+ # GeWe Agent Tools
16
+
17
+ 优先把这四个工具当成 GeWe 的正式操作面:
18
+
19
+ - `gewe_contacts`
20
+ - `gewe_groups`
21
+ - `gewe_moments`
22
+ - `gewe_personal`
23
+
24
+ ## 什么时候用哪个
25
+
26
+ - 处理联系人、好友、企业微信联系人、手机号通讯录:用 `gewe_contacts`
27
+ - 处理群资料、群成员、群公告、群管理:用 `gewe_groups`
28
+ - 处理朋友圈浏览、点赞、评论、发布、转发:用 `gewe_moments`
29
+ - 处理当前登录微信自己的资料、二维码、安全信息、隐私设置:用 `gewe_personal`
30
+
31
+ 如果只是想知道“现在这个私聊对象是谁”,优先用 `gewe_contacts`。
32
+ 如果只是想知道“现在这个群是谁、有哪些成员”,优先用 `gewe_groups`。
33
+
34
+ ## 当前会话推断
35
+
36
+ 有些 action 可以少填参数,优先利用当前会话:
37
+
38
+ - 在当前私聊会话里,`gewe_contacts` 的 `brief`、`detail`、`check_relation`,以及部分单人 action,可以从当前私聊会话推断 `wxid`
39
+ - 在当前群会话里,`gewe_groups` 的 `info`、`announcement`、`members`、`member_detail`、`qr_code`,以及多数群管理 action,可以从当前群会话推断 `groupId`
40
+ - 如果当前上下文不是对应会话,或者要操作的不是当前对象,就显式传 `wxid`、`wxids`、`groupId`
41
+
42
+ 实用原则:
43
+
44
+ - 当前私聊里查对方资料:先试 `gewe_contacts` + `action: "brief"`,通常不用再填 `wxids`
45
+ - 当前群里查群信息:先试 `gewe_groups` + `action: "info"`,通常不用再填 `groupId`
46
+
47
+ ## 推荐顺序
48
+
49
+ 先读后写,先确认对象再执行变更。
50
+
51
+ 推荐顺序:
52
+
53
+ 1. 先用只读 action 确认目标对象
54
+ 2. 再决定是否执行写操作
55
+ 3. 写操作完成后,再用只读 action 复查结果
56
+
57
+ 常见只读 action:
58
+
59
+ - `gewe_contacts`: `list` `list_cache` `brief` `detail` `search` `search_im` `im_detail` `check_relation` `phones_get`
60
+ - `gewe_groups`: `info` `announcement` `members` `member_detail` `qr_code`
61
+ - `gewe_moments`: `list_self` `list_contact` `detail` `download_video`
62
+ - `gewe_personal`: `profile` `qrcode` `safety_info`
63
+
64
+ ## 写操作要谨慎
65
+
66
+ 下面这些 action 会改真实微信状态。除非用户明确要求,否则不要主动调用:
67
+
68
+ - `gewe_contacts`: `set_remark` `set_only_chat` `delete` `add` `add_im` `phones_upload`
69
+ - `gewe_groups`: `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`
70
+ - `gewe_moments`: `upload_image` `upload_video` `delete` `post_text` `post_image` `post_video` `post_link` `set_stranger_visibility` `set_visible_scope` `set_privacy` `like` `comment` `forward`
71
+ - `gewe_personal`: `update_profile` `update_avatar` `privacy`
72
+
73
+ 看到“加好友、删好友、拉群、退群、改备注、发朋友圈、改隐私、改资料”这类动作时,要默认它们会改真实账号状态。
74
+
75
+ ## 常用调用套路
76
+
77
+ 查看当前私聊对象:
78
+
79
+ - `gewe_contacts` with `action: "brief"`
80
+
81
+ 查看当前群:
82
+
83
+ - `gewe_groups` with `action: "info"`
84
+
85
+ 查看当前群成员:
86
+
87
+ - `gewe_groups` with `action: "members"`
88
+
89
+ 查看某个联系人朋友圈:
90
+
91
+ - `gewe_moments` with `action: "list_contact"` and explicit `wxid`
92
+
93
+ 查看自己账号资料:
94
+
95
+ - `gewe_personal` with `action: "profile"`
96
+
97
+ 查看自己二维码:
98
+
99
+ - `gewe_personal` with `action: "qrcode"`
100
+
101
+ ## 参数习惯
102
+
103
+ - 多联系人优先传 `wxids`
104
+ - 单联系人优先传 `wxid`
105
+ - 群优先传 `groupId`
106
+ - 要切账号时传 `accountId`
107
+ - 工具返回里会带 `input`,可以用来确认本次实际命中的目标
108
+
109
+ ## 失败时怎么想
110
+
111
+ - 报“requires wxid/wxids/groupId”时,通常是因为当前会话不足以推断目标,需要显式补参数
112
+ - 报账号未配置时,优先检查 `accountId` 是否正确,以及该账号是否配置了 `token` 和 `appId`
113
+ - 如果只是想查名字,不要直接上写操作,先用 `brief`、`detail`、`info`、`members` 这类只读 action
@@ -18,3 +18,10 @@ metadata: { "openclaw": { "always": true, "skillKey": "gewe-channel-rules" } }
18
18
  - 优先用几句自然短句完成回复,不写冗长总结。
19
19
  - 如果内容已经偏长,先在聊天里给出简短结论,再补图片或文件。
20
20
  - 需要列点时,用 `1.` `2.` `3.` 或短横线的纯文本即可。
21
+
22
+ ## GeWe 部分引用
23
+
24
+ - 如果用户明确要求“引用这条消息中的某几个字”“部分引用”“只引用其中一段”,先正常写出要发送的正文,再在最后单独追加一行隐藏指令:
25
+ `[[GEWE_QUOTE_PARTIAL:要引用的原文片段]]`
26
+ - `要引用的原文片段` 必须直接复制自当前正在回复的那条消息,保持原样,不要改写。
27
+ - 这行隐藏指令会被 GeWe 插件剥离,不会直接发到微信里。