gewe-openclaw 2026.1.30 → 2026.1.31

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 CHANGED
@@ -34,7 +34,7 @@ openclaw plugins install ./gewe-openclaw.tgz
34
34
 
35
35
  ## 配置
36
36
 
37
- 插件配置放在 `~/.openclaw/openclaw.json` 的 `channels.gewe`,并确保插件开启:
37
+ 插件配置放在 `~/.openclaw/openclaw.json` 的 `channels.gewe-openclaw`,并确保插件开启:
38
38
 
39
39
  ```json5
40
40
  {
@@ -44,7 +44,7 @@ openclaw plugins install ./gewe-openclaw.tgz
44
44
  }
45
45
  },
46
46
  "channels": {
47
- "gewe": {
47
+ "gewe-openclaw": {
48
48
  "enabled": true,
49
49
  "apiBaseUrl": "https://www.geweapi.com",
50
50
  "token": "<gewe-token>",
@@ -86,14 +86,14 @@ OpenClaw 支持外部插件目录(catalog)。放置到以下路径即可被
86
86
  "name": "gewe-openclaw",
87
87
  "openclaw": {
88
88
  "channel": {
89
- "id": "gewe",
89
+ "id": "gewe-openclaw",
90
90
  "label": "GeWe",
91
91
  "selectionLabel": "WeChat (GeWe)",
92
92
  "detailLabel": "WeChat (GeWe)",
93
- "docsPath": "/channels/gewe",
94
- "docsLabel": "gewe",
93
+ "docsPath": "/channels/gewe-openclaw",
94
+ "docsLabel": "gewe-openclaw",
95
95
  "blurb": "WeChat channel via GeWe API and webhook callbacks.",
96
- "aliases": ["wechat", "wx", "gewe"],
96
+ "aliases": ["gewe-openclaw", "gewe", "wechat", "wx"],
97
97
  "order": 72,
98
98
  "quickstartAllowFrom": true
99
99
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "gewe-openclaw",
3
3
  "channels": [
4
- "gewe"
4
+ "gewe-openclaw"
5
5
  ],
6
6
  "configSchema": {
7
7
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gewe-openclaw",
3
- "version": "2026.1.30",
3
+ "version": "2026.1.31",
4
4
  "type": "module",
5
5
  "description": "OpenClaw GeWe channel plugin",
6
6
  "license": "MIT",
@@ -9,17 +9,18 @@
9
9
  "./index.ts"
10
10
  ],
11
11
  "channel": {
12
- "id": "gewe",
12
+ "id": "gewe-openclaw",
13
13
  "label": "GeWe",
14
14
  "selectionLabel": "WeChat (GeWe)",
15
15
  "detailLabel": "WeChat (GeWe)",
16
- "docsPath": "/channels/gewe",
17
- "docsLabel": "gewe",
16
+ "docsPath": "/channels/gewe-openclaw",
17
+ "docsLabel": "gewe-openclaw",
18
18
  "blurb": "WeChat channel via GeWe API and webhook callbacks.",
19
19
  "aliases": [
20
+ "gewe-openclaw",
21
+ "gewe",
20
22
  "wechat",
21
- "wx",
22
- "gewe"
23
+ "wx"
23
24
  ],
24
25
  "order": 72,
25
26
  "quickstartAllowFrom": true
package/src/accounts.ts CHANGED
@@ -2,6 +2,7 @@ import { readFileSync } from "node:fs";
2
2
 
3
3
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk";
4
4
 
5
+ import { CHANNEL_CONFIG_KEY } from "./constants.js";
5
6
  import type { CoreConfig, GeweAccountConfig, GeweAppIdSource, GeweTokenSource } from "./types.js";
6
7
 
7
8
  const DEFAULT_API_BASE_URL = "http://api.geweapi.com";
@@ -18,7 +19,7 @@ export type ResolvedGeweAccount = {
18
19
  };
19
20
 
20
21
  function listConfiguredAccountIds(cfg: CoreConfig): string[] {
21
- const accounts = cfg.channels?.gewe?.accounts;
22
+ const accounts = cfg.channels?.[CHANNEL_CONFIG_KEY]?.accounts;
22
23
  if (!accounts || typeof accounts !== "object") return [];
23
24
  const ids = new Set<string>();
24
25
  for (const key of Object.keys(accounts)) {
@@ -41,7 +42,7 @@ export function resolveDefaultGeweAccountId(cfg: CoreConfig): string {
41
42
  }
42
43
 
43
44
  function resolveAccountConfig(cfg: CoreConfig, accountId: string): GeweAccountConfig | undefined {
44
- const accounts = cfg.channels?.gewe?.accounts;
45
+ const accounts = cfg.channels?.[CHANNEL_CONFIG_KEY]?.accounts;
45
46
  if (!accounts || typeof accounts !== "object") return undefined;
46
47
  const direct = accounts[accountId] as GeweAccountConfig | undefined;
47
48
  if (direct) return direct;
@@ -51,7 +52,7 @@ function resolveAccountConfig(cfg: CoreConfig, accountId: string): GeweAccountCo
51
52
  }
52
53
 
53
54
  function mergeGeweAccountConfig(cfg: CoreConfig, accountId: string): GeweAccountConfig {
54
- const { accounts: _ignored, ...base } = (cfg.channels?.gewe ?? {}) as GeweAccountConfig & {
55
+ const { accounts: _ignored, ...base } = (cfg.channels?.[CHANNEL_CONFIG_KEY] ?? {}) as GeweAccountConfig & {
55
56
  accounts?: unknown;
56
57
  };
57
58
  const account = resolveAccountConfig(cfg, accountId) ?? {};
@@ -117,7 +118,7 @@ export function resolveGeweAccount(params: {
117
118
  accountId?: string | null;
118
119
  }): ResolvedGeweAccount {
119
120
  const hasExplicitAccountId = Boolean(params.accountId?.trim());
120
- const baseEnabled = params.cfg.channels?.gewe?.enabled !== false;
121
+ const baseEnabled = params.cfg.channels?.[CHANNEL_CONFIG_KEY]?.enabled !== false;
121
122
 
122
123
  const resolve = (accountId: string): ResolvedGeweAccount => {
123
124
  const merged = mergeGeweAccountConfig(params.cfg, accountId);
@@ -161,4 +162,3 @@ export function listEnabledGeweAccounts(cfg: CoreConfig): ResolvedGeweAccount[]
161
162
  .map((accountId) => resolveGeweAccount({ cfg, accountId }))
162
163
  .filter((account) => account.enabled);
163
164
  }
164
-
package/src/channel.ts CHANGED
@@ -15,6 +15,14 @@ import {
15
15
 
16
16
  import { resolveGeweAccount, resolveDefaultGeweAccountId, listGeweAccountIds } from "./accounts.js";
17
17
  import { GeweConfigSchema } from "./config-schema.js";
18
+ import {
19
+ CHANNEL_ALIASES,
20
+ CHANNEL_CONFIG_KEY,
21
+ CHANNEL_DOCS_LABEL,
22
+ CHANNEL_DOCS_PATH,
23
+ CHANNEL_ID,
24
+ stripChannelPrefix,
25
+ } from "./constants.js";
18
26
  import { deliverGewePayload } from "./delivery.js";
19
27
  import { monitorGeweProvider } from "./monitor.js";
20
28
  import { looksLikeGeweTargetId, normalizeGeweMessagingTarget } from "./normalize.js";
@@ -24,14 +32,14 @@ import { sendTextGewe } from "./send.js";
24
32
  import type { CoreConfig, ResolvedGeweAccount } from "./types.js";
25
33
 
26
34
  const meta = {
27
- id: "gewe",
35
+ id: CHANNEL_ID,
28
36
  label: "GeWe",
29
37
  selectionLabel: "WeChat (GeWe)",
30
38
  detailLabel: "WeChat (GeWe)",
31
- docsPath: "/channels/gewe",
32
- docsLabel: "gewe",
39
+ docsPath: CHANNEL_DOCS_PATH,
40
+ docsLabel: CHANNEL_DOCS_LABEL,
33
41
  blurb: "WeChat channel via GeWe API and webhook callbacks.",
34
- aliases: ["wechat", "wx", "gewe"],
42
+ aliases: [...CHANNEL_ALIASES],
35
43
  order: 72,
36
44
  quickstartAllowFrom: true,
37
45
  };
@@ -45,11 +53,11 @@ type GeweSetupInput = ChannelSetupInput & {
45
53
  };
46
54
 
47
55
  export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
48
- id: "gewe",
56
+ id: CHANNEL_ID,
49
57
  meta,
50
58
  pairing: {
51
59
  idLabel: "wechatUserId",
52
- normalizeAllowEntry: (entry) => entry.replace(/^(gewe|wechat|wx):/i, ""),
60
+ normalizeAllowEntry: (entry) => stripChannelPrefix(entry),
53
61
  notifyApproval: async ({ cfg, id }) => {
54
62
  const account = resolveGeweAccount({ cfg: cfg as CoreConfig });
55
63
  if (!account.token || !account.appId) {
@@ -70,7 +78,7 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
70
78
  nativeCommands: false,
71
79
  blockStreaming: true,
72
80
  },
73
- reload: { configPrefixes: ["channels.gewe"] },
81
+ reload: { configPrefixes: [`channels.${CHANNEL_CONFIG_KEY}`] },
74
82
  configSchema: buildChannelConfigSchema(GeweConfigSchema),
75
83
  config: {
76
84
  listAccountIds: (cfg) => listGeweAccountIds(cfg as CoreConfig),
@@ -79,7 +87,7 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
79
87
  setAccountEnabled: ({ cfg, accountId, enabled }) =>
80
88
  setAccountEnabledInConfigSection({
81
89
  cfg,
82
- sectionKey: "gewe",
90
+ sectionKey: CHANNEL_CONFIG_KEY,
83
91
  accountId,
84
92
  enabled,
85
93
  allowTopLevel: true,
@@ -87,7 +95,7 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
87
95
  deleteAccount: ({ cfg, accountId }) =>
88
96
  deleteAccountFromConfigSection({
89
97
  cfg,
90
- sectionKey: "gewe",
98
+ sectionKey: CHANNEL_CONFIG_KEY,
91
99
  accountId,
92
100
  clearBaseFields: ["token", "tokenFile", "appId", "appIdFile", "name"],
93
101
  }),
@@ -108,24 +116,24 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
108
116
  allowFrom
109
117
  .map((entry) => String(entry).trim())
110
118
  .filter(Boolean)
111
- .map((entry) => entry.replace(/^(gewe|wechat|wx):/i, "")),
119
+ .map((entry) => stripChannelPrefix(entry)),
112
120
  },
113
121
  security: {
114
122
  resolveDmPolicy: ({ cfg, accountId, account }) => {
115
123
  const resolvedAccountId = accountId ?? account.accountId ?? DEFAULT_ACCOUNT_ID;
116
124
  const useAccountPath = Boolean(
117
- cfg.channels?.gewe?.accounts?.[resolvedAccountId],
125
+ cfg.channels?.[CHANNEL_CONFIG_KEY]?.accounts?.[resolvedAccountId],
118
126
  );
119
127
  const basePath = useAccountPath
120
- ? `channels.gewe.accounts.${resolvedAccountId}.`
121
- : "channels.gewe.";
128
+ ? `channels.${CHANNEL_CONFIG_KEY}.accounts.${resolvedAccountId}.`
129
+ : `channels.${CHANNEL_CONFIG_KEY}.`;
122
130
  return {
123
131
  policy: account.config.dmPolicy ?? "pairing",
124
132
  allowFrom: account.config.allowFrom ?? [],
125
133
  policyPath: `${basePath}dmPolicy`,
126
134
  allowFromPath: basePath,
127
- approveHint: formatPairingApproveHint("gewe"),
128
- normalizeEntry: (raw) => raw.replace(/^(gewe|wechat|wx):/i, ""),
135
+ approveHint: formatPairingApproveHint(CHANNEL_ID),
136
+ normalizeEntry: (raw) => stripChannelPrefix(raw),
129
137
  };
130
138
  },
131
139
  collectWarnings: ({ account, cfg }) => {
@@ -136,11 +144,11 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
136
144
  account.config.groups && Object.keys(account.config.groups).length > 0;
137
145
  if (groupAllowlistConfigured) {
138
146
  return [
139
- `- GeWe groups: groupPolicy="open" allows any member in allowed groups to trigger (mention-gated). Set channels.gewe.groupPolicy="allowlist" + channels.gewe.groupAllowFrom to restrict senders.`,
147
+ `- GeWe groups: groupPolicy="open" allows any member in allowed groups to trigger (mention-gated). Set channels.${CHANNEL_CONFIG_KEY}.groupPolicy="allowlist" + channels.${CHANNEL_CONFIG_KEY}.groupAllowFrom to restrict senders.`,
140
148
  ];
141
149
  }
142
150
  return [
143
- `- GeWe groups: groupPolicy="open" with no channels.gewe.groups allowlist; any group can add + ping (mention-gated). Set channels.gewe.groupPolicy="allowlist" + channels.gewe.groupAllowFrom or configure channels.gewe.groups.`,
151
+ `- GeWe groups: groupPolicy="open" with no channels.${CHANNEL_CONFIG_KEY}.groups allowlist; any group can add + ping (mention-gated). Set channels.${CHANNEL_CONFIG_KEY}.groupPolicy="allowlist" + channels.${CHANNEL_CONFIG_KEY}.groupAllowFrom or configure channels.${CHANNEL_CONFIG_KEY}.groups.`,
144
152
  ];
145
153
  },
146
154
  },
@@ -187,7 +195,10 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
187
195
  }
188
196
  return {
189
197
  ok: false,
190
- error: missingTargetError("GeWe", "<wxid|@chatroom> or channels.gewe.allowFrom[0]"),
198
+ error: missingTargetError(
199
+ "GeWe",
200
+ `<wxid|@chatroom> or channels.${CHANNEL_CONFIG_KEY}.allowFrom[0]`,
201
+ ),
191
202
  };
192
203
  }
193
204
  return { ok: true, to: normalized };
@@ -198,7 +209,10 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
198
209
  }
199
210
  return {
200
211
  ok: false,
201
- error: missingTargetError("GeWe", "<wxid|@chatroom> or channels.gewe.allowFrom[0]"),
212
+ error: missingTargetError(
213
+ "GeWe",
214
+ `<wxid|@chatroom> or channels.${CHANNEL_CONFIG_KEY}.allowFrom[0]`,
215
+ ),
202
216
  };
203
217
  },
204
218
  sendPayload: async ({ payload, cfg, to, accountId }) => {
@@ -210,7 +224,7 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
210
224
  toWxid: to,
211
225
  });
212
226
  return {
213
- channel: "gewe",
227
+ channel: CHANNEL_ID,
214
228
  messageId: result?.messageId ?? "ok",
215
229
  timestamp: result?.timestamp,
216
230
  meta: { newMessageId: result?.newMessageId },
@@ -225,7 +239,7 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
225
239
  toWxid: to,
226
240
  });
227
241
  return {
228
- channel: "gewe",
242
+ channel: CHANNEL_ID,
229
243
  messageId: result?.messageId ?? "ok",
230
244
  timestamp: result?.timestamp,
231
245
  meta: { newMessageId: result?.newMessageId },
@@ -240,7 +254,7 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
240
254
  toWxid: to,
241
255
  });
242
256
  return {
243
- channel: "gewe",
257
+ channel: CHANNEL_ID,
244
258
  messageId: result?.messageId ?? "ok",
245
259
  timestamp: result?.timestamp,
246
260
  meta: { newMessageId: result?.newMessageId },
@@ -307,7 +321,9 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
307
321
  },
308
322
  logoutAccount: async ({ accountId, cfg }) => {
309
323
  const nextCfg = { ...cfg } as OpenClawConfig;
310
- const nextSection = cfg.channels?.gewe ? { ...cfg.channels.gewe } : undefined;
324
+ const nextSection = cfg.channels?.[CHANNEL_CONFIG_KEY]
325
+ ? { ...(cfg.channels?.[CHANNEL_CONFIG_KEY] as Record<string, unknown>) }
326
+ : undefined;
311
327
  let cleared = false;
312
328
  let changed = false;
313
329
 
@@ -377,7 +393,7 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
377
393
  if (changed) {
378
394
  nextCfg.channels = {
379
395
  ...nextCfg.channels,
380
- gewe: nextSection,
396
+ [CHANNEL_CONFIG_KEY]: nextSection,
381
397
  };
382
398
  }
383
399
  }
@@ -390,7 +406,7 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
390
406
  applyAccountName: ({ cfg, accountId, name }) =>
391
407
  applyAccountNameToChannelSection({
392
408
  cfg: cfg as OpenClawConfig,
393
- channelKey: "gewe",
409
+ channelKey: CHANNEL_CONFIG_KEY,
394
410
  accountId,
395
411
  name,
396
412
  }),
@@ -411,11 +427,14 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
411
427
  const setupInput = input as GeweSetupInput;
412
428
  const namedConfig = applyAccountNameToChannelSection({
413
429
  cfg: cfg as OpenClawConfig,
414
- channelKey: "gewe",
430
+ channelKey: CHANNEL_CONFIG_KEY,
415
431
  accountId,
416
432
  name: setupInput.name,
417
433
  });
418
- const section = (namedConfig.channels?.gewe ?? {}) as Record<string, unknown>;
434
+ const section = (namedConfig.channels?.[CHANNEL_CONFIG_KEY] ?? {}) as Record<
435
+ string,
436
+ unknown
437
+ >;
419
438
  const useAccountPath = accountId !== DEFAULT_ACCOUNT_ID;
420
439
  const base = useAccountPath
421
440
  ? (section.accounts?.[accountId] as Record<string, unknown> | undefined) ?? {}
@@ -443,7 +462,7 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
443
462
  ...namedConfig,
444
463
  channels: {
445
464
  ...namedConfig.channels,
446
- gewe: nextEntry,
465
+ [CHANNEL_CONFIG_KEY]: nextEntry,
447
466
  },
448
467
  };
449
468
  }
@@ -451,7 +470,7 @@ export const gewePlugin: ChannelPlugin<ResolvedGeweAccount> = {
451
470
  ...namedConfig,
452
471
  channels: {
453
472
  ...namedConfig.channels,
454
- gewe: {
473
+ [CHANNEL_CONFIG_KEY]: {
455
474
  ...section,
456
475
  accounts: {
457
476
  ...(section.accounts as Record<string, unknown> | undefined),
@@ -81,25 +81,27 @@ export const GeweAccountSchemaBase = z
81
81
  });
82
82
 
83
83
  export const GeweAccountSchema = GeweAccountSchemaBase.superRefine((value, ctx) => {
84
+ const pathHint = "channels.gewe-openclaw";
84
85
  requireOpenAllowFrom({
85
86
  policy: value.dmPolicy,
86
87
  allowFrom: value.allowFrom,
87
88
  ctx,
88
89
  path: ["allowFrom"],
89
90
  message:
90
- 'channels.gewe.dmPolicy="open" requires channels.gewe.allowFrom to include "*"',
91
+ `${pathHint}.dmPolicy="open" requires ${pathHint}.allowFrom to include "*"`,
91
92
  });
92
93
  });
93
94
 
94
95
  export const GeweConfigSchema = GeweAccountSchemaBase.extend({
95
96
  accounts: z.record(z.string(), GeweAccountSchema.optional()).optional(),
96
97
  }).superRefine((value, ctx) => {
98
+ const pathHint = "channels.gewe-openclaw";
97
99
  requireOpenAllowFrom({
98
100
  policy: value.dmPolicy,
99
101
  allowFrom: value.allowFrom,
100
102
  ctx,
101
103
  path: ["allowFrom"],
102
104
  message:
103
- 'channels.gewe.dmPolicy="open" requires channels.gewe.allowFrom to include "*"',
105
+ `${pathHint}.dmPolicy="open" requires ${pathHint}.allowFrom to include "*"`,
104
106
  });
105
107
  });
@@ -0,0 +1,10 @@
1
+ export const CHANNEL_ID = "gewe-openclaw" as const;
2
+ export const CHANNEL_CONFIG_KEY = "gewe-openclaw" as const;
3
+ export const CHANNEL_DOCS_PATH = "/channels/gewe-openclaw" as const;
4
+ export const CHANNEL_DOCS_LABEL = "gewe-openclaw" as const;
5
+ export const CHANNEL_PREFIX_REGEX = /^(gewe-openclaw|gewe|wechat|wx):/i;
6
+ export const CHANNEL_ALIASES = ["gewe-openclaw", "gewe", "wechat", "wx"] as const;
7
+
8
+ export function stripChannelPrefix(value: string): string {
9
+ return value.replace(CHANNEL_PREFIX_REGEX, "");
10
+ }
package/src/delivery.ts CHANGED
@@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url";
5
5
 
6
6
  import type { OpenClawConfig, ReplyPayload } from "openclaw/plugin-sdk";
7
7
  import { extractOriginalFilename, extensionForMime } from "openclaw/plugin-sdk";
8
+ import { CHANNEL_ID } from "./constants.js";
8
9
  import { getGeweRuntime } from "./runtime.js";
9
10
  import {
10
11
  sendFileGewe,
@@ -97,8 +98,10 @@ function resolveMediaMaxBytes(account: ResolvedGeweAccount): number {
97
98
  }
98
99
 
99
100
  function resolveGeweData(payload: ReplyPayload): GeweChannelData | undefined {
100
- const data = payload.channelData as { gewe?: GeweChannelData } | undefined;
101
- return data?.gewe;
101
+ const data = payload.channelData as
102
+ | { "gewe-openclaw"?: GeweChannelData; gewe?: GeweChannelData }
103
+ | undefined;
104
+ return data?.[CHANNEL_ID] ?? data?.gewe;
102
105
  }
103
106
 
104
107
  function isSilkAudio(opts: { contentType?: string; fileName?: string }): boolean {
@@ -145,7 +148,7 @@ async function probeVideoDurationSeconds(params: {
145
148
  sourcePath: string;
146
149
  }): Promise<number | null> {
147
150
  const core = getGeweRuntime();
148
- const logger = core.logging.getChildLogger({ channel: "gewe", module: "video" });
151
+ const logger = core.logging.getChildLogger({ channel: CHANNEL_ID, module: "video" });
149
152
  const ffmpegPath = resolveVideoFfmpegPath(params.account);
150
153
  const ffprobePath = resolveVideoFfprobePath(params.account, ffmpegPath);
151
154
  const args = [
@@ -180,7 +183,7 @@ async function generateVideoThumbBuffer(params: {
180
183
  sourcePath: string;
181
184
  }): Promise<Buffer | null> {
182
185
  const core = getGeweRuntime();
183
- const logger = core.logging.getChildLogger({ channel: "gewe", module: "video" });
186
+ const logger = core.logging.getChildLogger({ channel: CHANNEL_ID, module: "video" });
184
187
  const ffmpegPath = resolveVideoFfmpegPath(params.account);
185
188
  const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gewe-video-"));
186
189
  const thumbPath = path.join(tmpDir, "thumb.png");
@@ -247,7 +250,7 @@ async function convertAudioToSilk(params: {
247
250
  sourcePath: string;
248
251
  }): Promise<{ buffer: Buffer; durationMs: number } | null> {
249
252
  const core = getGeweRuntime();
250
- const logger = core.logging.getChildLogger({ channel: "gewe", module: "voice" });
253
+ const logger = core.logging.getChildLogger({ channel: CHANNEL_ID, module: "voice" });
251
254
  if (!params.account.config.voiceAutoConvert) return null;
252
255
 
253
256
  const sampleRate = resolveVoiceSampleRate(params.account);
@@ -441,7 +444,7 @@ async function resolveLinkThumbUrl(params: {
441
444
  thumbUrl?: string;
442
445
  }): Promise<string> {
443
446
  const core = getGeweRuntime();
444
- const logger = core.logging.getChildLogger({ channel: "gewe", module: "thumb" });
447
+ const logger = core.logging.getChildLogger({ channel: CHANNEL_ID, module: "thumb" });
445
448
  const fallbackBuffer = await fs.readFile(DEFAULT_LINK_THUMB_PATH);
446
449
  const fallbackUrl = await stageThumbBuffer({
447
450
  account: params.account,
@@ -591,7 +594,7 @@ export async function deliverGewePayload(params: {
591
594
  thumbUrl,
592
595
  });
593
596
  core.channel.activity.record({
594
- channel: "gewe",
597
+ channel: CHANNEL_ID,
595
598
  accountId: account.accountId,
596
599
  direction: "outbound",
597
600
  });
@@ -625,7 +628,7 @@ export async function deliverGewePayload(params: {
625
628
  voiceDuration: declaredDuration,
626
629
  });
627
630
  core.channel.activity.record({
628
- channel: "gewe",
631
+ channel: CHANNEL_ID,
629
632
  accountId: account.accountId,
630
633
  direction: "outbound",
631
634
  });
@@ -657,7 +660,7 @@ export async function deliverGewePayload(params: {
657
660
  voiceDuration,
658
661
  });
659
662
  core.channel.activity.record({
660
- channel: "gewe",
663
+ channel: CHANNEL_ID,
661
664
  accountId: account.accountId,
662
665
  direction: "outbound",
663
666
  });
@@ -674,7 +677,7 @@ export async function deliverGewePayload(params: {
674
677
  imgUrl: staged.publicUrl,
675
678
  });
676
679
  core.channel.activity.record({
677
- channel: "gewe",
680
+ channel: CHANNEL_ID,
678
681
  accountId: account.accountId,
679
682
  direction: "outbound",
680
683
  });
@@ -683,7 +686,7 @@ export async function deliverGewePayload(params: {
683
686
  }
684
687
 
685
688
  if (!forceFile && kind === "video") {
686
- const logger = core.logging.getChildLogger({ channel: "gewe", module: "video" });
689
+ const logger = core.logging.getChildLogger({ channel: CHANNEL_ID, module: "video" });
687
690
  const video = geweData?.video;
688
691
  let thumbUrl = video?.thumbUrl;
689
692
  const fallbackThumbUrl = account.config.videoThumbUrl?.trim() || undefined;
@@ -755,7 +758,7 @@ export async function deliverGewePayload(params: {
755
758
  videoDuration: Math.floor(videoDuration),
756
759
  });
757
760
  core.channel.activity.record({
758
- channel: "gewe",
761
+ channel: CHANNEL_ID,
759
762
  accountId: account.accountId,
760
763
  direction: "outbound",
761
764
  });
@@ -780,7 +783,7 @@ export async function deliverGewePayload(params: {
780
783
  videoDuration: Math.floor(videoDuration),
781
784
  });
782
785
  core.channel.activity.record({
783
- channel: "gewe",
786
+ channel: CHANNEL_ID,
784
787
  accountId: account.accountId,
785
788
  direction: "outbound",
786
789
  });
@@ -803,7 +806,7 @@ export async function deliverGewePayload(params: {
803
806
  fileName: fallbackName,
804
807
  });
805
808
  core.channel.activity.record({
806
- channel: "gewe",
809
+ channel: CHANNEL_ID,
807
810
  accountId: account.accountId,
808
811
  direction: "outbound",
809
812
  });
@@ -814,7 +817,7 @@ export async function deliverGewePayload(params: {
814
817
  if (trimmedText) {
815
818
  const tableMode = core.channel.text.resolveMarkdownTableMode({
816
819
  cfg,
817
- channel: "gewe",
820
+ channel: CHANNEL_ID,
818
821
  accountId: account.accountId,
819
822
  });
820
823
  const content = core.channel.text.convertMarkdownTables(trimmedText, tableMode);
@@ -825,7 +828,7 @@ export async function deliverGewePayload(params: {
825
828
  ats: geweData?.ats,
826
829
  });
827
830
  core.channel.activity.record({
828
- channel: "gewe",
831
+ channel: CHANNEL_ID,
829
832
  accountId: account.accountId,
830
833
  direction: "outbound",
831
834
  });
package/src/inbound.ts CHANGED
@@ -19,8 +19,7 @@ import {
19
19
  } from "./policy.js";
20
20
  import type { CoreConfig, GeweInboundMessage, ResolvedGeweAccount } from "./types.js";
21
21
  import { extractAppMsgType, extractFileName, extractLinkDetails } from "./xml.js";
22
-
23
- const CHANNEL_ID = "gewe" as const;
22
+ import { CHANNEL_ID } from "./constants.js";
24
23
 
25
24
  type PreparedInbound = {
26
25
  rawBody: string;
@@ -103,7 +102,7 @@ async function decodeSilkVoice(params: {
103
102
  fileName?: string | null;
104
103
  }): Promise<DecodedVoice | null> {
105
104
  const core = getGeweRuntime();
106
- const logger = core.logging.getChildLogger({ channel: "gewe", module: "voice" });
105
+ const logger = core.logging.getChildLogger({ channel: CHANNEL_ID, module: "voice" });
107
106
  const decodeOutput = params.account.config.voiceDecodeOutput ?? "pcm";
108
107
  const sampleRate = resolveVoiceDecodeSampleRate(params.account);
109
108
  const ffmpegPath = params.account.config.voiceFfmpegPath?.trim() || "ffmpeg";
@@ -261,8 +260,10 @@ async function dispatchGeweInbound(params: {
261
260
  Body: body,
262
261
  RawBody: prepared.rawBody,
263
262
  CommandBody: prepared.rawBody,
264
- From: prepared.groupId ? `gewe:group:${prepared.groupId}` : `gewe:${prepared.senderId}`,
265
- To: `gewe:${prepared.toWxid}`,
263
+ From: prepared.groupId
264
+ ? `${CHANNEL_ID}:group:${prepared.groupId}`
265
+ : `${CHANNEL_ID}:${prepared.senderId}`,
266
+ To: `${CHANNEL_ID}:${prepared.toWxid}`,
266
267
  SessionKey: prepared.route.sessionKey,
267
268
  AccountId: prepared.route.accountId,
268
269
  ChatType: prepared.isGroup ? "group" : "direct",
@@ -272,16 +273,16 @@ async function dispatchGeweInbound(params: {
272
273
  SenderName: prepared.senderName || undefined,
273
274
  SenderId: prepared.senderId,
274
275
  CommandAuthorized: prepared.commandAuthorized,
275
- Provider: "gewe",
276
- Surface: "gewe",
276
+ Provider: CHANNEL_ID,
277
+ Surface: CHANNEL_ID,
277
278
  MessageSid: prepared.messageSid,
278
279
  MessageSidFull: prepared.messageSid,
279
280
  MediaPath: media?.path,
280
281
  MediaType: media?.contentType,
281
282
  MediaUrl: media?.path,
282
283
  GroupSystemPrompt: prepared.groupSystemPrompt,
283
- OriginatingChannel: "gewe",
284
- OriginatingTo: `gewe:${prepared.toWxid}`,
284
+ OriginatingChannel: CHANNEL_ID,
285
+ OriginatingTo: `${CHANNEL_ID}:${prepared.toWxid}`,
285
286
  });
286
287
 
287
288
  await core.channel.session.recordInboundSession({
@@ -523,7 +524,7 @@ export async function handleGeweInbound(params: {
523
524
  };
524
525
 
525
526
  core.channel.activity.record({
526
- channel: "gewe",
527
+ channel: CHANNEL_ID,
527
528
  accountId: account.accountId,
528
529
  direction: "inbound",
529
530
  });
package/src/normalize.ts CHANGED
@@ -1,17 +1,16 @@
1
1
  export function normalizeGeweMessagingTarget(target: string): string | null {
2
2
  const trimmed = target.trim();
3
3
  if (!trimmed) return null;
4
+ const prefix = /^(gewe-openclaw|gewe|wechat|wx):(group:|user:)?/i;
4
5
  return trimmed
5
- .replace(/^gewe:(group:|user:)?/i, "")
6
- .replace(/^wechat:(group:|user:)?/i, "")
7
- .replace(/^wx:/i, "")
6
+ .replace(prefix, "")
8
7
  .trim();
9
8
  }
10
9
 
11
10
  export function looksLikeGeweTargetId(id: string): boolean {
12
11
  const trimmed = id?.trim();
13
12
  if (!trimmed) return false;
14
- if (/^gewe:/i.test(trimmed)) return true;
13
+ if (/^(gewe-openclaw|gewe):/i.test(trimmed)) return true;
15
14
  if (/@chatroom$/i.test(trimmed)) return true;
16
15
  if (/^wxid_/i.test(trimmed)) return true;
17
16
  if (/^gh_/i.test(trimmed)) return true;
package/src/policy.ts CHANGED
@@ -7,10 +7,11 @@ import {
7
7
  resolveNestedAllowlistDecision,
8
8
  } from "openclaw/plugin-sdk";
9
9
 
10
+ import { CHANNEL_CONFIG_KEY, CHANNEL_PREFIX_REGEX } from "./constants.js";
10
11
  import type { GeweGroupConfig } from "./types.js";
11
12
 
12
13
  function normalizeAllowEntry(raw: string): string {
13
- return raw.trim().toLowerCase().replace(/^(gewe|wechat|wx):/i, "");
14
+ return raw.trim().toLowerCase().replace(CHANNEL_PREFIX_REGEX, "");
14
15
  }
15
16
 
16
17
  export function normalizeGeweAllowlist(values: Array<string | number> | undefined): string[] {
@@ -89,7 +90,7 @@ export function resolveGeweGroupToolPolicy(
89
90
  ): GeweGroupConfig["tools"] | undefined {
90
91
  const cfg = params.cfg as {
91
92
  channels?: {
92
- gewe?: {
93
+ "gewe-openclaw"?: {
93
94
  groups?: Record<string, GeweGroupConfig>;
94
95
  accounts?: Record<string, { groups?: Record<string, GeweGroupConfig> }>;
95
96
  };
@@ -99,10 +100,10 @@ export function resolveGeweGroupToolPolicy(
99
100
  if (!groupId) return undefined;
100
101
  const groupName = params.groupChannel?.trim() || undefined;
101
102
  const accountGroups =
102
- params.accountId && cfg.channels?.gewe?.accounts?.[params.accountId]?.groups
103
- ? cfg.channels?.gewe?.accounts?.[params.accountId]?.groups
103
+ params.accountId && cfg.channels?.[CHANNEL_CONFIG_KEY]?.accounts?.[params.accountId]?.groups
104
+ ? cfg.channels?.[CHANNEL_CONFIG_KEY]?.accounts?.[params.accountId]?.groups
104
105
  : undefined;
105
- const groups = accountGroups ?? cfg.channels?.gewe?.groups;
106
+ const groups = accountGroups ?? cfg.channels?.[CHANNEL_CONFIG_KEY]?.groups;
106
107
  const match = resolveGeweGroupMatch({
107
108
  groups,
108
109
  groupId,
package/src/types.ts CHANGED
@@ -67,7 +67,7 @@ export type GeweConfig = {
67
67
 
68
68
  export type CoreConfig = {
69
69
  channels?: {
70
- gewe?: GeweConfig;
70
+ "gewe-openclaw"?: GeweConfig;
71
71
  };
72
72
  [key: string]: unknown;
73
73
  };