gewe-openclaw 2026.3.26 → 2026.3.27
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/index.ts +13 -1
- package/package.json +3 -1
- package/setup-entry.ts +9 -0
- package/src/api-tools.ts +7 -2
- package/src/channel-actions.ts +1 -1
- package/src/channel-allowlist.ts +5 -3
- package/src/channel-common.ts +184 -0
- package/src/channel-directory.ts +6 -3
- package/src/channel-status.ts +6 -3
- package/src/channel.setup.ts +9 -0
- package/src/channel.ts +2 -161
- package/src/group-allowlist-tool.ts +7 -2
- package/src/group-binding-tool.ts +7 -2
- package/src/group-claim-tool.ts +6 -2
- package/src/openclaw-compat.ts +11 -0
- package/src/runtime.ts +1 -1
- package/src/setup-wizard-types.ts +1 -1
- package/src/tool-visibility.ts +1 -1
package/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { OpenClawPluginApi } from "openclaw
|
|
1
|
+
import type { OpenClawPluginApi } from "./src/openclaw-compat.js";
|
|
2
2
|
|
|
3
3
|
import { createGeweApiTools } from "./src/api-tools.js";
|
|
4
4
|
import { gewePlugin } from "./src/channel.js";
|
|
@@ -7,6 +7,11 @@ import { createGeweSyncGroupBindingTool } from "./src/group-binding-tool.js";
|
|
|
7
7
|
import { createGeweIssueGroupClaimCodeTool } from "./src/group-claim-tool.js";
|
|
8
8
|
import { setGeweRuntime } from "./src/runtime.js";
|
|
9
9
|
|
|
10
|
+
type CompatRegistrationMode = "full" | "setup-only" | "setup-runtime";
|
|
11
|
+
type CompatOpenClawPluginApi = OpenClawPluginApi & {
|
|
12
|
+
registrationMode?: CompatRegistrationMode;
|
|
13
|
+
};
|
|
14
|
+
|
|
10
15
|
function emptyPluginConfigSchema() {
|
|
11
16
|
return {
|
|
12
17
|
safeParse(value: unknown) {
|
|
@@ -41,8 +46,15 @@ const plugin = {
|
|
|
41
46
|
description: "OpenClaw GeWe channel plugin",
|
|
42
47
|
configSchema: emptyPluginConfigSchema(),
|
|
43
48
|
register(api: OpenClawPluginApi) {
|
|
49
|
+
const compatApi = api as CompatOpenClawPluginApi;
|
|
50
|
+
|
|
44
51
|
setGeweRuntime(api.runtime);
|
|
45
52
|
api.registerChannel({ plugin: gewePlugin });
|
|
53
|
+
|
|
54
|
+
if (compatApi.registrationMode && compatApi.registrationMode !== "full") {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
46
58
|
api.registerTool((ctx) => createGeweApiTools(ctx));
|
|
47
59
|
api.registerTool((ctx) => createGeweSyncGroupBindingTool(ctx));
|
|
48
60
|
api.registerTool((ctx) => createGeweIssueGroupClaimCodeTool(ctx));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gewe-openclaw",
|
|
3
|
-
"version": "2026.3.
|
|
3
|
+
"version": "2026.3.27",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OpenClaw GeWe channel plugin",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"index.ts",
|
|
13
|
+
"setup-entry.ts",
|
|
13
14
|
"openclaw.plugin.json",
|
|
14
15
|
"assets/gewe-rs_logo.jpeg",
|
|
15
16
|
"skills/**",
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
"extensions": [
|
|
21
22
|
"./index.ts"
|
|
22
23
|
],
|
|
24
|
+
"setupEntry": "./setup-entry.ts",
|
|
23
25
|
"channel": {
|
|
24
26
|
"id": "gewe-openclaw",
|
|
25
27
|
"label": "GeWe",
|
package/setup-entry.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { geweSetupPlugin } from "./src/channel.setup.js";
|
|
2
|
+
|
|
3
|
+
export { geweSetupPlugin } from "./src/channel.setup.js";
|
|
4
|
+
|
|
5
|
+
// Keep the setup entry as a plain `{ plugin }` export so newer OpenClaw can
|
|
6
|
+
// load the channel surface without requiring newer runtime helpers at import time.
|
|
7
|
+
export default {
|
|
8
|
+
plugin: geweSetupPlugin,
|
|
9
|
+
};
|
package/src/api-tools.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { AnyAgentTool, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
|
|
2
1
|
import { z } from "zod";
|
|
3
2
|
|
|
4
3
|
import { resolveGeweAccount } from "./accounts.js";
|
|
@@ -65,7 +64,13 @@ import {
|
|
|
65
64
|
uploadSnsVideoGewe,
|
|
66
65
|
} from "./moments-api.js";
|
|
67
66
|
import { normalizeGeweMessagingTarget } from "./normalize.js";
|
|
68
|
-
import {
|
|
67
|
+
import {
|
|
68
|
+
buildJsonSchema,
|
|
69
|
+
normalizeAccountId,
|
|
70
|
+
type AnyAgentTool,
|
|
71
|
+
type OpenClawConfig,
|
|
72
|
+
type OpenClawPluginToolContext,
|
|
73
|
+
} from "./openclaw-compat.js";
|
|
69
74
|
import {
|
|
70
75
|
getProfileGewe,
|
|
71
76
|
getQrCodeGewe,
|
package/src/channel-actions.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type {
|
|
|
3
3
|
ChannelMessageActionAdapter,
|
|
4
4
|
ChannelMessageActionName,
|
|
5
5
|
ChannelMessageToolSchemaContribution,
|
|
6
|
-
} from "openclaw
|
|
6
|
+
} from "./openclaw-compat.js";
|
|
7
7
|
|
|
8
8
|
import { listEnabledGeweAccounts, resolveGeweAccount } from "./accounts.js";
|
|
9
9
|
import { deliverGewePayload } from "./delivery.js";
|
package/src/channel-allowlist.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import type { ChannelAllowlistAdapter } from "openclaw/plugin-sdk/channel-runtime";
|
|
2
|
-
|
|
3
1
|
import { resolveGeweAccount } from "./accounts.js";
|
|
4
2
|
import { collectKnownGeweGroupEntries } from "./channel-directory.js";
|
|
5
3
|
import { cleanupEmptyObject, ensureGeweWriteSectionInPlace } from "./config-edit.js";
|
|
6
4
|
import { CHANNEL_CONFIG_KEY, stripChannelPrefix } from "./constants.js";
|
|
7
5
|
import { normalizeGeweMessagingTarget } from "./normalize.js";
|
|
8
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
normalizeAccountId,
|
|
8
|
+
type ChannelAllowlistAdapter,
|
|
9
|
+
type OpenClawConfig,
|
|
10
|
+
} from "./openclaw-compat.js";
|
|
9
11
|
import type { CoreConfig } from "./types.js";
|
|
10
12
|
import { resolveCachedGeweName } from "./directory-cache.js";
|
|
11
13
|
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyAccountNameToChannelSection,
|
|
3
|
+
buildChannelConfigSchema,
|
|
4
|
+
DEFAULT_ACCOUNT_ID,
|
|
5
|
+
deleteAccountFromConfigSection,
|
|
6
|
+
normalizeAccountId,
|
|
7
|
+
setAccountEnabledInConfigSection,
|
|
8
|
+
type ChannelPlugin,
|
|
9
|
+
type ChannelSetupInput,
|
|
10
|
+
type OpenClawConfig,
|
|
11
|
+
} from "./openclaw-compat.js";
|
|
12
|
+
|
|
13
|
+
import { resolveDefaultGeweAccountId, listGeweAccountIds, resolveGeweAccount } from "./accounts.js";
|
|
14
|
+
import { GeweConfigSchema } from "./config-schema.js";
|
|
15
|
+
import {
|
|
16
|
+
CHANNEL_ALIASES,
|
|
17
|
+
CHANNEL_CONFIG_KEY,
|
|
18
|
+
CHANNEL_DOCS_LABEL,
|
|
19
|
+
CHANNEL_DOCS_PATH,
|
|
20
|
+
CHANNEL_ID,
|
|
21
|
+
stripChannelPrefix,
|
|
22
|
+
} from "./constants.js";
|
|
23
|
+
import { geweSetupWizard } from "./setup-wizard.js";
|
|
24
|
+
import type { CoreConfig, ResolvedGeweAccount } from "./types.js";
|
|
25
|
+
|
|
26
|
+
type GeweSetupInput = ChannelSetupInput & {
|
|
27
|
+
token?: string;
|
|
28
|
+
tokenFile?: string;
|
|
29
|
+
appId?: string;
|
|
30
|
+
appIdFile?: string;
|
|
31
|
+
apiBaseUrl?: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const geweChannelMeta = {
|
|
35
|
+
id: CHANNEL_ID,
|
|
36
|
+
label: "GeWe",
|
|
37
|
+
selectionLabel: "WeChat (GeWe)",
|
|
38
|
+
detailLabel: "WeChat (GeWe)",
|
|
39
|
+
docsPath: CHANNEL_DOCS_PATH,
|
|
40
|
+
docsLabel: CHANNEL_DOCS_LABEL,
|
|
41
|
+
blurb: "WeChat channel via GeWe API and webhook callbacks.",
|
|
42
|
+
aliases: [...CHANNEL_ALIASES],
|
|
43
|
+
order: 72,
|
|
44
|
+
quickstartAllowFrom: true,
|
|
45
|
+
} as const;
|
|
46
|
+
|
|
47
|
+
export const geweSetupAdapter: NonNullable<ChannelPlugin<ResolvedGeweAccount>["setup"]> = {
|
|
48
|
+
resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
|
|
49
|
+
applyAccountName: ({ cfg, accountId, name }) =>
|
|
50
|
+
applyAccountNameToChannelSection({
|
|
51
|
+
cfg: cfg as OpenClawConfig,
|
|
52
|
+
channelKey: CHANNEL_CONFIG_KEY,
|
|
53
|
+
accountId,
|
|
54
|
+
name,
|
|
55
|
+
}),
|
|
56
|
+
validateInput: ({ accountId, input }) => {
|
|
57
|
+
const setupInput = input as GeweSetupInput;
|
|
58
|
+
if (setupInput.useEnv && accountId !== DEFAULT_ACCOUNT_ID) {
|
|
59
|
+
return "GEWE_TOKEN/GEWE_APP_ID can only be used for the default account.";
|
|
60
|
+
}
|
|
61
|
+
if (!setupInput.useEnv && !setupInput.token && !setupInput.tokenFile) {
|
|
62
|
+
return "GeWe requires --token or --token-file (or --use-env).";
|
|
63
|
+
}
|
|
64
|
+
if (!setupInput.useEnv && !setupInput.appId && !setupInput.appIdFile) {
|
|
65
|
+
return "GeWe requires --app-id or --app-id-file (or --use-env).";
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
},
|
|
69
|
+
applyAccountConfig: ({ cfg, accountId, input }) => {
|
|
70
|
+
const setupInput = input as GeweSetupInput;
|
|
71
|
+
const namedConfig = applyAccountNameToChannelSection({
|
|
72
|
+
cfg: cfg as OpenClawConfig,
|
|
73
|
+
channelKey: CHANNEL_CONFIG_KEY,
|
|
74
|
+
accountId,
|
|
75
|
+
name: setupInput.name,
|
|
76
|
+
});
|
|
77
|
+
const section = (namedConfig.channels?.[CHANNEL_CONFIG_KEY] ?? {}) as Record<
|
|
78
|
+
string,
|
|
79
|
+
unknown
|
|
80
|
+
> & {
|
|
81
|
+
accounts?: Record<string, Record<string, unknown>>;
|
|
82
|
+
};
|
|
83
|
+
const useAccountPath = accountId !== DEFAULT_ACCOUNT_ID;
|
|
84
|
+
const base = useAccountPath ? section.accounts?.[accountId] ?? {} : section;
|
|
85
|
+
const nextEntry = {
|
|
86
|
+
...base,
|
|
87
|
+
...(setupInput.apiBaseUrl ? { apiBaseUrl: setupInput.apiBaseUrl } : {}),
|
|
88
|
+
...(setupInput.useEnv
|
|
89
|
+
? {}
|
|
90
|
+
: setupInput.token
|
|
91
|
+
? { token: setupInput.token }
|
|
92
|
+
: setupInput.tokenFile
|
|
93
|
+
? { tokenFile: setupInput.tokenFile }
|
|
94
|
+
: {}),
|
|
95
|
+
...(setupInput.useEnv
|
|
96
|
+
? {}
|
|
97
|
+
: setupInput.appId
|
|
98
|
+
? { appId: setupInput.appId }
|
|
99
|
+
: setupInput.appIdFile
|
|
100
|
+
? { appIdFile: setupInput.appIdFile }
|
|
101
|
+
: {}),
|
|
102
|
+
};
|
|
103
|
+
if (!useAccountPath) {
|
|
104
|
+
return {
|
|
105
|
+
...namedConfig,
|
|
106
|
+
channels: {
|
|
107
|
+
...namedConfig.channels,
|
|
108
|
+
[CHANNEL_CONFIG_KEY]: nextEntry,
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
...namedConfig,
|
|
114
|
+
channels: {
|
|
115
|
+
...namedConfig.channels,
|
|
116
|
+
[CHANNEL_CONFIG_KEY]: {
|
|
117
|
+
...section,
|
|
118
|
+
accounts: {
|
|
119
|
+
...(section.accounts as Record<string, unknown> | undefined),
|
|
120
|
+
[accountId]: nextEntry,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const geweChannelPluginCommon = {
|
|
129
|
+
meta: geweChannelMeta,
|
|
130
|
+
setupWizard: geweSetupWizard,
|
|
131
|
+
capabilities: {
|
|
132
|
+
chatTypes: ["direct", "group"],
|
|
133
|
+
reactions: false,
|
|
134
|
+
threads: false,
|
|
135
|
+
media: true,
|
|
136
|
+
nativeCommands: false,
|
|
137
|
+
blockStreaming: true,
|
|
138
|
+
},
|
|
139
|
+
reload: { configPrefixes: [`channels.${CHANNEL_CONFIG_KEY}`] },
|
|
140
|
+
configSchema: buildChannelConfigSchema(GeweConfigSchema),
|
|
141
|
+
config: {
|
|
142
|
+
listAccountIds: (cfg: OpenClawConfig) => listGeweAccountIds(cfg as CoreConfig),
|
|
143
|
+
resolveAccount: (cfg: OpenClawConfig, accountId?: string | null) =>
|
|
144
|
+
resolveGeweAccount({ cfg: cfg as CoreConfig, accountId }),
|
|
145
|
+
defaultAccountId: (cfg: OpenClawConfig) => resolveDefaultGeweAccountId(cfg as CoreConfig),
|
|
146
|
+
setAccountEnabled: ({ cfg, accountId, enabled }: { cfg: OpenClawConfig; accountId: string; enabled: boolean }) =>
|
|
147
|
+
setAccountEnabledInConfigSection({
|
|
148
|
+
cfg,
|
|
149
|
+
sectionKey: CHANNEL_CONFIG_KEY,
|
|
150
|
+
accountId,
|
|
151
|
+
enabled,
|
|
152
|
+
allowTopLevel: true,
|
|
153
|
+
}),
|
|
154
|
+
deleteAccount: ({ cfg, accountId }: { cfg: OpenClawConfig; accountId: string }) =>
|
|
155
|
+
deleteAccountFromConfigSection({
|
|
156
|
+
cfg,
|
|
157
|
+
sectionKey: CHANNEL_CONFIG_KEY,
|
|
158
|
+
accountId,
|
|
159
|
+
clearBaseFields: ["token", "tokenFile", "appId", "appIdFile", "name"],
|
|
160
|
+
}),
|
|
161
|
+
isConfigured: (account: ResolvedGeweAccount) => Boolean(account.token?.trim() && account.appId?.trim()),
|
|
162
|
+
describeAccount: (account: ResolvedGeweAccount) => ({
|
|
163
|
+
accountId: account.accountId,
|
|
164
|
+
name: account.name,
|
|
165
|
+
enabled: account.enabled,
|
|
166
|
+
configured: Boolean(account.token?.trim() && account.appId?.trim()),
|
|
167
|
+
tokenSource: account.tokenSource,
|
|
168
|
+
baseUrl: account.config.apiBaseUrl ? "[set]" : "[missing]",
|
|
169
|
+
}),
|
|
170
|
+
resolveAllowFrom: ({ cfg, accountId }: { cfg: OpenClawConfig; accountId?: string | null }) =>
|
|
171
|
+
(resolveGeweAccount({ cfg: cfg as CoreConfig, accountId }).config.allowFrom ?? []).map(
|
|
172
|
+
(entry) => String(entry),
|
|
173
|
+
),
|
|
174
|
+
formatAllowFrom: ({ allowFrom }: { allowFrom: Array<string | number> }) =>
|
|
175
|
+
allowFrom
|
|
176
|
+
.map((entry) => String(entry).trim())
|
|
177
|
+
.filter(Boolean)
|
|
178
|
+
.map((entry) => stripChannelPrefix(entry)),
|
|
179
|
+
},
|
|
180
|
+
setup: geweSetupAdapter,
|
|
181
|
+
} satisfies Pick<
|
|
182
|
+
ChannelPlugin<ResolvedGeweAccount>,
|
|
183
|
+
"meta" | "setupWizard" | "capabilities" | "reload" | "configSchema" | "config" | "setup"
|
|
184
|
+
>;
|
package/src/channel-directory.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { ChannelDirectoryAdapter, ChannelDirectoryEntry } from "openclaw/plugin-sdk/channel-runtime";
|
|
2
|
-
|
|
3
1
|
import { resolveGeweAccount } from "./accounts.js";
|
|
4
2
|
import {
|
|
5
3
|
fetchContactsListCacheGewe,
|
|
@@ -14,7 +12,12 @@ import {
|
|
|
14
12
|
normalizeGeweBindingConversationId,
|
|
15
13
|
} from "./group-binding.js";
|
|
16
14
|
import { normalizeGeweMessagingTarget } from "./normalize.js";
|
|
17
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
normalizeAccountId,
|
|
17
|
+
type ChannelDirectoryAdapter,
|
|
18
|
+
type ChannelDirectoryEntry,
|
|
19
|
+
type OpenClawConfig,
|
|
20
|
+
} from "./openclaw-compat.js";
|
|
18
21
|
import type { CoreConfig } from "./types.js";
|
|
19
22
|
import {
|
|
20
23
|
listCachedGeweGroups,
|
package/src/channel-status.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import type { ChannelStatusAdapter, ChannelStatusIssue } from "openclaw/plugin-sdk/channel-runtime";
|
|
2
|
-
|
|
3
1
|
import type { ResolvedGeweAccount } from "./accounts.js";
|
|
4
2
|
import { collectKnownGeweGroupEntries, collectKnownGewePeerEntries } from "./channel-directory.js";
|
|
5
3
|
import { getGeweDirectoryCacheCounts } from "./directory-cache.js";
|
|
6
4
|
import { CHANNEL_CONFIG_KEY } from "./constants.js";
|
|
7
5
|
import { getGeweProfile } from "./group-binding.js";
|
|
8
6
|
import { normalizeGeweBindingConversationId } from "./group-binding.js";
|
|
9
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
normalizeAccountId,
|
|
9
|
+
type ChannelStatusAdapter,
|
|
10
|
+
type ChannelStatusIssue,
|
|
11
|
+
type OpenClawConfig,
|
|
12
|
+
} from "./openclaw-compat.js";
|
|
10
13
|
import { readGeweAllowFromStore } from "./pairing-store.js";
|
|
11
14
|
|
|
12
15
|
type GeweStatusProbe = {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CHANNEL_ID } from "./constants.js";
|
|
2
|
+
import { geweChannelPluginCommon } from "./channel-common.js";
|
|
3
|
+
import type { GeweChannelPlugin } from "./setup-wizard-types.js";
|
|
4
|
+
import type { ResolvedGeweAccount } from "./types.js";
|
|
5
|
+
|
|
6
|
+
export const geweSetupPlugin: GeweChannelPlugin<ResolvedGeweAccount> = {
|
|
7
|
+
id: CHANNEL_ID,
|
|
8
|
+
...geweChannelPluginCommon,
|
|
9
|
+
};
|
package/src/channel.ts
CHANGED
|
@@ -1,28 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyAccountNameToChannelSection,
|
|
3
|
-
buildChannelConfigSchema,
|
|
4
3
|
DEFAULT_ACCOUNT_ID,
|
|
5
4
|
deleteAccountFromConfigSection,
|
|
6
5
|
missingTargetError,
|
|
7
|
-
normalizeAccountId,
|
|
8
6
|
PAIRING_APPROVED_MESSAGE,
|
|
9
7
|
setAccountEnabledInConfigSection,
|
|
10
8
|
type OpenClawConfig,
|
|
11
|
-
type ChannelSetupInput,
|
|
12
9
|
type ReplyPayload,
|
|
13
10
|
} from "./openclaw-compat.js";
|
|
14
11
|
|
|
15
12
|
import { resolveGeweAccount, resolveDefaultGeweAccountId, listGeweAccountIds } from "./accounts.js";
|
|
16
13
|
import { geweMessageActions } from "./channel-actions.js";
|
|
14
|
+
import { geweChannelPluginCommon } from "./channel-common.js";
|
|
17
15
|
import { geweAllowlist } from "./channel-allowlist.js";
|
|
18
16
|
import { geweDirectory } from "./channel-directory.js";
|
|
19
17
|
import { geweStatus } from "./channel-status.js";
|
|
20
|
-
import { GeweConfigSchema } from "./config-schema.js";
|
|
21
18
|
import {
|
|
22
|
-
CHANNEL_ALIASES,
|
|
23
19
|
CHANNEL_CONFIG_KEY,
|
|
24
|
-
CHANNEL_DOCS_LABEL,
|
|
25
|
-
CHANNEL_DOCS_PATH,
|
|
26
20
|
CHANNEL_ID,
|
|
27
21
|
stripChannelPrefix,
|
|
28
22
|
} from "./constants.js";
|
|
@@ -32,32 +26,10 @@ import { looksLikeGeweTargetId, normalizeGeweMessagingTarget } from "./normalize
|
|
|
32
26
|
import { resolveGeweGroupToolPolicy, resolveGeweRequireMention } from "./policy.js";
|
|
33
27
|
import { getGeweRuntime } from "./runtime.js";
|
|
34
28
|
import { sendTextGewe } from "./send.js";
|
|
35
|
-
import { geweSetupWizard } from "./setup-wizard.js";
|
|
36
29
|
import type { GeweChannelPlugin } from "./setup-wizard-types.js";
|
|
37
30
|
import { normalizeGeweBindingConversationId } from "./group-binding.js";
|
|
38
31
|
import type { CoreConfig, ResolvedGeweAccount } from "./types.js";
|
|
39
32
|
|
|
40
|
-
const meta = {
|
|
41
|
-
id: CHANNEL_ID,
|
|
42
|
-
label: "GeWe",
|
|
43
|
-
selectionLabel: "WeChat (GeWe)",
|
|
44
|
-
detailLabel: "WeChat (GeWe)",
|
|
45
|
-
docsPath: CHANNEL_DOCS_PATH,
|
|
46
|
-
docsLabel: CHANNEL_DOCS_LABEL,
|
|
47
|
-
blurb: "WeChat channel via GeWe API and webhook callbacks.",
|
|
48
|
-
aliases: [...CHANNEL_ALIASES],
|
|
49
|
-
order: 72,
|
|
50
|
-
quickstartAllowFrom: true,
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
type GeweSetupInput = ChannelSetupInput & {
|
|
54
|
-
token?: string;
|
|
55
|
-
tokenFile?: string;
|
|
56
|
-
appId?: string;
|
|
57
|
-
appIdFile?: string;
|
|
58
|
-
apiBaseUrl?: string;
|
|
59
|
-
};
|
|
60
|
-
|
|
61
33
|
const GEWE_QUOTE_PARTIAL_DIRECTIVE_RE = /(?:\r?\n)?\s*\[\[GEWE_QUOTE_PARTIAL:([\s\S]*?)\]\]\s*$/;
|
|
62
34
|
|
|
63
35
|
function asRecord(value: unknown): Record<string, unknown> | null {
|
|
@@ -168,57 +140,8 @@ const gewePairing = {
|
|
|
168
140
|
|
|
169
141
|
export const gewePlugin: GeweChannelPlugin<ResolvedGeweAccount> = {
|
|
170
142
|
id: CHANNEL_ID,
|
|
171
|
-
|
|
172
|
-
setupWizard: geweSetupWizard,
|
|
143
|
+
...geweChannelPluginCommon,
|
|
173
144
|
pairing: gewePairing as GeweChannelPlugin<ResolvedGeweAccount>["pairing"],
|
|
174
|
-
capabilities: {
|
|
175
|
-
chatTypes: ["direct", "group"],
|
|
176
|
-
reactions: false,
|
|
177
|
-
threads: false,
|
|
178
|
-
media: true,
|
|
179
|
-
nativeCommands: false,
|
|
180
|
-
blockStreaming: true,
|
|
181
|
-
},
|
|
182
|
-
reload: { configPrefixes: [`channels.${CHANNEL_CONFIG_KEY}`] },
|
|
183
|
-
configSchema: buildChannelConfigSchema(GeweConfigSchema),
|
|
184
|
-
config: {
|
|
185
|
-
listAccountIds: (cfg) => listGeweAccountIds(cfg as CoreConfig),
|
|
186
|
-
resolveAccount: (cfg, accountId) => resolveGeweAccount({ cfg: cfg as CoreConfig, accountId }),
|
|
187
|
-
defaultAccountId: (cfg) => resolveDefaultGeweAccountId(cfg as CoreConfig),
|
|
188
|
-
setAccountEnabled: ({ cfg, accountId, enabled }) =>
|
|
189
|
-
setAccountEnabledInConfigSection({
|
|
190
|
-
cfg,
|
|
191
|
-
sectionKey: CHANNEL_CONFIG_KEY,
|
|
192
|
-
accountId,
|
|
193
|
-
enabled,
|
|
194
|
-
allowTopLevel: true,
|
|
195
|
-
}),
|
|
196
|
-
deleteAccount: ({ cfg, accountId }) =>
|
|
197
|
-
deleteAccountFromConfigSection({
|
|
198
|
-
cfg,
|
|
199
|
-
sectionKey: CHANNEL_CONFIG_KEY,
|
|
200
|
-
accountId,
|
|
201
|
-
clearBaseFields: ["token", "tokenFile", "appId", "appIdFile", "name"],
|
|
202
|
-
}),
|
|
203
|
-
isConfigured: (account) => Boolean(account.token?.trim() && account.appId?.trim()),
|
|
204
|
-
describeAccount: (account) => ({
|
|
205
|
-
accountId: account.accountId,
|
|
206
|
-
name: account.name,
|
|
207
|
-
enabled: account.enabled,
|
|
208
|
-
configured: Boolean(account.token?.trim() && account.appId?.trim()),
|
|
209
|
-
tokenSource: account.tokenSource,
|
|
210
|
-
baseUrl: account.config.apiBaseUrl ? "[set]" : "[missing]",
|
|
211
|
-
}),
|
|
212
|
-
resolveAllowFrom: ({ cfg, accountId }) =>
|
|
213
|
-
(resolveGeweAccount({ cfg: cfg as CoreConfig, accountId }).config.allowFrom ?? []).map(
|
|
214
|
-
(entry) => String(entry),
|
|
215
|
-
),
|
|
216
|
-
formatAllowFrom: ({ allowFrom }) =>
|
|
217
|
-
allowFrom
|
|
218
|
-
.map((entry) => String(entry).trim())
|
|
219
|
-
.filter(Boolean)
|
|
220
|
-
.map((entry) => stripChannelPrefix(entry)),
|
|
221
|
-
},
|
|
222
145
|
allowlist: geweAllowlist,
|
|
223
146
|
security: {
|
|
224
147
|
resolveDmPolicy: ({ cfg, accountId, account }) => {
|
|
@@ -498,86 +421,4 @@ export const gewePlugin: GeweChannelPlugin<ResolvedGeweAccount> = {
|
|
|
498
421
|
return { cleared, loggedOut: cleared, nextCfg };
|
|
499
422
|
},
|
|
500
423
|
},
|
|
501
|
-
setup: {
|
|
502
|
-
resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
|
|
503
|
-
applyAccountName: ({ cfg, accountId, name }) =>
|
|
504
|
-
applyAccountNameToChannelSection({
|
|
505
|
-
cfg: cfg as OpenClawConfig,
|
|
506
|
-
channelKey: CHANNEL_CONFIG_KEY,
|
|
507
|
-
accountId,
|
|
508
|
-
name,
|
|
509
|
-
}),
|
|
510
|
-
validateInput: ({ accountId, input }) => {
|
|
511
|
-
const setupInput = input as GeweSetupInput;
|
|
512
|
-
if (setupInput.useEnv && accountId !== DEFAULT_ACCOUNT_ID) {
|
|
513
|
-
return "GEWE_TOKEN/GEWE_APP_ID can only be used for the default account.";
|
|
514
|
-
}
|
|
515
|
-
if (!setupInput.useEnv && !setupInput.token && !setupInput.tokenFile) {
|
|
516
|
-
return "GeWe requires --token or --token-file (or --use-env).";
|
|
517
|
-
}
|
|
518
|
-
if (!setupInput.useEnv && !setupInput.appId && !setupInput.appIdFile) {
|
|
519
|
-
return "GeWe requires --app-id or --app-id-file (or --use-env).";
|
|
520
|
-
}
|
|
521
|
-
return null;
|
|
522
|
-
},
|
|
523
|
-
applyAccountConfig: ({ cfg, accountId, input }) => {
|
|
524
|
-
const setupInput = input as GeweSetupInput;
|
|
525
|
-
const namedConfig = applyAccountNameToChannelSection({
|
|
526
|
-
cfg: cfg as OpenClawConfig,
|
|
527
|
-
channelKey: CHANNEL_CONFIG_KEY,
|
|
528
|
-
accountId,
|
|
529
|
-
name: setupInput.name,
|
|
530
|
-
});
|
|
531
|
-
const section = (namedConfig.channels?.[CHANNEL_CONFIG_KEY] ?? {}) as Record<
|
|
532
|
-
string,
|
|
533
|
-
unknown
|
|
534
|
-
> & {
|
|
535
|
-
accounts?: Record<string, Record<string, unknown>>;
|
|
536
|
-
};
|
|
537
|
-
const useAccountPath = accountId !== DEFAULT_ACCOUNT_ID;
|
|
538
|
-
const base = useAccountPath
|
|
539
|
-
? section.accounts?.[accountId] ?? {}
|
|
540
|
-
: section;
|
|
541
|
-
const nextEntry = {
|
|
542
|
-
...base,
|
|
543
|
-
...(setupInput.apiBaseUrl ? { apiBaseUrl: setupInput.apiBaseUrl } : {}),
|
|
544
|
-
...(setupInput.useEnv
|
|
545
|
-
? {}
|
|
546
|
-
: setupInput.token
|
|
547
|
-
? { token: setupInput.token }
|
|
548
|
-
: setupInput.tokenFile
|
|
549
|
-
? { tokenFile: setupInput.tokenFile }
|
|
550
|
-
: {}),
|
|
551
|
-
...(setupInput.useEnv
|
|
552
|
-
? {}
|
|
553
|
-
: setupInput.appId
|
|
554
|
-
? { appId: setupInput.appId }
|
|
555
|
-
: setupInput.appIdFile
|
|
556
|
-
? { appIdFile: setupInput.appIdFile }
|
|
557
|
-
: {}),
|
|
558
|
-
};
|
|
559
|
-
if (!useAccountPath) {
|
|
560
|
-
return {
|
|
561
|
-
...namedConfig,
|
|
562
|
-
channels: {
|
|
563
|
-
...namedConfig.channels,
|
|
564
|
-
[CHANNEL_CONFIG_KEY]: nextEntry,
|
|
565
|
-
},
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
return {
|
|
569
|
-
...namedConfig,
|
|
570
|
-
channels: {
|
|
571
|
-
...namedConfig.channels,
|
|
572
|
-
[CHANNEL_CONFIG_KEY]: {
|
|
573
|
-
...section,
|
|
574
|
-
accounts: {
|
|
575
|
-
...(section.accounts as Record<string, unknown> | undefined),
|
|
576
|
-
[accountId]: nextEntry,
|
|
577
|
-
},
|
|
578
|
-
},
|
|
579
|
-
},
|
|
580
|
-
};
|
|
581
|
-
},
|
|
582
|
-
},
|
|
583
424
|
};
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import type { AnyAgentTool, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
|
|
2
1
|
import { z } from "zod";
|
|
3
2
|
|
|
4
3
|
import { resolveGeweAccount } from "./accounts.js";
|
|
5
4
|
import { ensureGeweWriteSection } from "./config-edit.js";
|
|
6
5
|
import { normalizeGeweBindingConversationId, inferCurrentGeweGroupId } from "./group-binding.js";
|
|
7
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
buildJsonSchema,
|
|
8
|
+
normalizeAccountId,
|
|
9
|
+
type AnyAgentTool,
|
|
10
|
+
type OpenClawConfig,
|
|
11
|
+
type OpenClawPluginToolContext,
|
|
12
|
+
} from "./openclaw-compat.js";
|
|
8
13
|
import { shouldExposeGeweAgentTool } from "./tool-visibility.js";
|
|
9
14
|
import type { GeweGroupConfig } from "./types.js";
|
|
10
15
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { AnyAgentTool, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
|
|
2
1
|
import { z } from "zod";
|
|
3
2
|
|
|
4
3
|
import {
|
|
@@ -15,7 +14,13 @@ import {
|
|
|
15
14
|
resolveGeweBindingIdentityConfigForGroup,
|
|
16
15
|
resolveGeweCurrentSelfNickname,
|
|
17
16
|
} from "./group-binding.js";
|
|
18
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
buildJsonSchema,
|
|
19
|
+
normalizeAccountId,
|
|
20
|
+
type AnyAgentTool,
|
|
21
|
+
type OpenClawConfig,
|
|
22
|
+
type OpenClawPluginToolContext,
|
|
23
|
+
} from "./openclaw-compat.js";
|
|
19
24
|
import { shouldExposeGeweAgentTool } from "./tool-visibility.js";
|
|
20
25
|
|
|
21
26
|
const GeweSyncGroupBindingToolSchema = z
|
package/src/group-claim-tool.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import type { AnyAgentTool, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
|
|
2
1
|
import { z } from "zod";
|
|
3
2
|
|
|
4
3
|
import { normalizeGeweMessagingTarget } from "./normalize.js";
|
|
5
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
buildJsonSchema,
|
|
6
|
+
normalizeAccountId,
|
|
7
|
+
type AnyAgentTool,
|
|
8
|
+
type OpenClawPluginToolContext,
|
|
9
|
+
} from "./openclaw-compat.js";
|
|
6
10
|
import { issueGeweGroupClaimCode } from "./pairing-store.js";
|
|
7
11
|
import { shouldExposeGeweAgentTool } from "./tool-visibility.js";
|
|
8
12
|
|
package/src/openclaw-compat.ts
CHANGED
|
@@ -23,6 +23,17 @@ export type {
|
|
|
23
23
|
RuntimeEnv,
|
|
24
24
|
WizardPrompter,
|
|
25
25
|
};
|
|
26
|
+
export type { AnyAgentTool, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
|
|
27
|
+
export type {
|
|
28
|
+
ChannelAllowlistAdapter,
|
|
29
|
+
ChannelDirectoryAdapter,
|
|
30
|
+
ChannelDirectoryEntry,
|
|
31
|
+
ChannelMessageActionAdapter,
|
|
32
|
+
ChannelMessageActionName,
|
|
33
|
+
ChannelMessageToolSchemaContribution,
|
|
34
|
+
ChannelStatusAdapter,
|
|
35
|
+
ChannelStatusIssue,
|
|
36
|
+
} from "openclaw/plugin-sdk/channel-runtime";
|
|
26
37
|
|
|
27
38
|
export const DEFAULT_ACCOUNT_ID = "default";
|
|
28
39
|
export const DEFAULT_WEBHOOK_MAX_BODY_BYTES = 1024 * 1024;
|
package/src/runtime.ts
CHANGED
package/src/tool-visibility.ts
CHANGED