@zhin.js/adapter-wechat-mp 1.1.0 → 1.1.2
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/CHANGELOG.md +84 -0
- package/README.md +5 -4
- package/adapters/{wechat-mp.js → wechat-mp/index.js} +6 -6
- package/adapters/{wechat-mp.ts → wechat-mp/index.ts} +10 -10
- package/commands/{endpoint/add/[id].js → wechat-mp/endpoint/add/[id]/index.js} +1 -1
- package/commands/wechat-mp/endpoint/add/[id]/index.ts +3 -0
- package/{lib/wechat-mp-endpoint-commands.js → commands/wechat-mp/endpoint/definition.js} +4 -3
- package/{src/wechat-mp-endpoint-commands.ts → commands/wechat-mp/endpoint/definition.ts} +3 -3
- package/commands/{endpoint/list.js → wechat-mp/endpoint/list/index.js} +1 -1
- package/commands/wechat-mp/endpoint/list/index.ts +3 -0
- package/commands/{endpoint/remove/[id].js → wechat-mp/endpoint/remove/[id]/index.js} +1 -1
- package/commands/wechat-mp/endpoint/remove/[id]/index.ts +3 -0
- package/lib/index.d.ts +1 -1
- package/lib/media-upload.d.ts +1 -1
- package/lib/media-upload.js +1 -1
- package/lib/protocol.d.ts +7 -10
- package/lib/protocol.js +21 -20
- package/lib/wechat-mp-runtime-state.js +1 -1
- package/package.json +19 -14
- package/plugin.js +1 -1
- package/schema.json +29 -1
- package/src/index.ts +1 -1
- package/src/media-upload.ts +1 -1
- package/src/protocol.ts +32 -31
- package/src/wechat-mp-runtime-state.ts +1 -1
- package/agent/skills/wechat-mp.md +0 -33
- package/commands/endpoint/add/[id].ts +0 -3
- package/commands/endpoint/list.ts +0 -3
- package/commands/endpoint/remove/[id].ts +0 -3
- package/lib/wechat-mp-endpoint-commands.d.ts +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,89 @@
|
|
|
1
1
|
# @zhin.js/adapter-wechat-mp
|
|
2
2
|
|
|
3
|
+
## 1.1.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a9e4a40: Derive Command user routes only from explicit `commands/**/*/index.ts(x)` entry paths instead of prepending the plugin owner. Child plugins can now publish top-level static or dynamic commands, while duplicate routes across owners fail during generation construction. Adapter endpoint commands move to explicit paths such as `commands/qq/endpoint/list/index.ts` and are invoked as `qq endpoint list`.
|
|
8
|
+
- 8740059: Standardize TypeScript capabilities on named module directories such as `commands/foo/index.ts`, `middlewares/audit/index.ts`, `handlers/message-receive/index.ts`, `pages/workroom/index.tsx`, and `mcps/filesystem/index.ts`. Only the fixed `index` entry is discovered; sibling files remain private helpers.
|
|
9
|
+
|
|
10
|
+
Command route segments come from directories, while `[name]`, `[[name]]`, `[...name]`, and `[[...name]]` directories declare dynamic parameters. Plugin owners do not enter the route unless their config explicitly sets `commandNamespace`; Endpoint `commandPrefix` remains platform-owned and defaults to an empty string.
|
|
11
|
+
|
|
12
|
+
Migrate the built-in adapters, plugins, examples, generators, migration tooling, hot reload classification, Agent authoring surfaces, documentation, and release artifacts to the explicit entry convention.
|
|
13
|
+
|
|
14
|
+
Make Tool ownership and progressive disclosure explicit across all four supported locations: plugin-public `tools/`, Agent-private `agents/<name>/tools/`, Skill-private `skills/<name>/tools/`, and Agent-Skill-private `agents/<name>/skills/<name>/tools/`. Move adapter and group-suite operations that require domain instructions into their owning Skills so `load_skill` is the only path that unlocks their schemas.
|
|
15
|
+
|
|
16
|
+
Remove the package-root `agent/` convention. Public capabilities now use named package-root directories, schedules use `schedules/<name>/index.ts` or `plugin.ts` injection, MCP connections use `mcps/<name>/index.ts`, Prompt Sections use `prompt-sections/<name>/index.ts`, Agent definitions use `agents/<name>/`, and permission vocabulary is published as `PERMITS.md`.
|
|
17
|
+
|
|
18
|
+
- 25a845a: Unify Skills on `skills/<name>/SKILL.md`, support Agent-private Skills and nested Skill-private Tools, publish and mount existing plugin Skills, add governed Skill metadata and Turn access filtering, unlock only already-admitted same-owner Tools, and make `on-risk` and `once` approval behavior precise.
|
|
19
|
+
- 4380cf9: Colocate adapter command definitions and Agent Skill handlers with their owning capabilities, and provide a shared validated platform permission constructor.
|
|
20
|
+
- 224f267: Require one canonical expanded WeChat MP endpoint configuration. The protocol no longer reinterprets nested `endpoints` or reads endpoint identity and credentials from `process.env`.
|
|
21
|
+
- 5c3858e: Make `@zhin.js/im-contract` the explicit zero-dependency owner of transport identities, canonical segments, media guards, conversation facts, stores, and delivery contracts. Platform adapters now read media contracts from that foundation instead of reaching through Core.
|
|
22
|
+
- Updated dependencies [c861789]
|
|
23
|
+
- Updated dependencies [1414ccb]
|
|
24
|
+
- Updated dependencies [743d470]
|
|
25
|
+
- Updated dependencies [62dee52]
|
|
26
|
+
- Updated dependencies [cd54131]
|
|
27
|
+
- Updated dependencies [244e475]
|
|
28
|
+
- Updated dependencies [a9e4a40]
|
|
29
|
+
- Updated dependencies [5855db7]
|
|
30
|
+
- Updated dependencies [ec921d2]
|
|
31
|
+
- Updated dependencies [8740059]
|
|
32
|
+
- Updated dependencies [25a845a]
|
|
33
|
+
- Updated dependencies [103f2c3]
|
|
34
|
+
- Updated dependencies [9110ab8]
|
|
35
|
+
- Updated dependencies [cd2a888]
|
|
36
|
+
- Updated dependencies [eb3227a]
|
|
37
|
+
- Updated dependencies [b853dba]
|
|
38
|
+
- Updated dependencies [e561309]
|
|
39
|
+
- Updated dependencies [d4c6175]
|
|
40
|
+
- Updated dependencies [7a0e1ca]
|
|
41
|
+
- Updated dependencies [103b5d3]
|
|
42
|
+
- Updated dependencies [5a7a7f7]
|
|
43
|
+
- Updated dependencies [b076eae]
|
|
44
|
+
- Updated dependencies [73a24b7]
|
|
45
|
+
- Updated dependencies [2dbbc15]
|
|
46
|
+
- Updated dependencies [1cb1163]
|
|
47
|
+
- Updated dependencies [be3061e]
|
|
48
|
+
- Updated dependencies [75f8332]
|
|
49
|
+
- Updated dependencies [81935e2]
|
|
50
|
+
- Updated dependencies [f9ed01b]
|
|
51
|
+
- Updated dependencies [ac0ab50]
|
|
52
|
+
- Updated dependencies [5140ce1]
|
|
53
|
+
- Updated dependencies [522d75f]
|
|
54
|
+
- Updated dependencies [a7611b3]
|
|
55
|
+
- Updated dependencies [8823044]
|
|
56
|
+
- Updated dependencies [379439b]
|
|
57
|
+
- Updated dependencies [11c9352]
|
|
58
|
+
- Updated dependencies [6b70e46]
|
|
59
|
+
- Updated dependencies [135ac91]
|
|
60
|
+
- Updated dependencies [140cf0f]
|
|
61
|
+
- Updated dependencies [251e4d2]
|
|
62
|
+
- Updated dependencies [203ad34]
|
|
63
|
+
- Updated dependencies [e6c5113]
|
|
64
|
+
- Updated dependencies [e0f6478]
|
|
65
|
+
- Updated dependencies [baef56b]
|
|
66
|
+
- Updated dependencies [da0a8e3]
|
|
67
|
+
- Updated dependencies [2fd8017]
|
|
68
|
+
- Updated dependencies [5c3858e]
|
|
69
|
+
- Updated dependencies [507d602]
|
|
70
|
+
- Updated dependencies [df9f76b]
|
|
71
|
+
- @zhin.js/core@1.1.37
|
|
72
|
+
- @zhin.js/host-http@1.1.1
|
|
73
|
+
- @zhin.js/adapter@1.1.14
|
|
74
|
+
- @zhin.js/feature-kit@1.1.1
|
|
75
|
+
- @zhin.js/skill@1.1.1
|
|
76
|
+
- @zhin.js/logger@1.1.1
|
|
77
|
+
- @zhin.js/im-contract@1.1.1
|
|
78
|
+
|
|
79
|
+
## 1.1.1
|
|
80
|
+
|
|
81
|
+
### Patch Changes
|
|
82
|
+
|
|
83
|
+
- Updated dependencies [769e67f]
|
|
84
|
+
- @zhin.js/adapter@1.1.13
|
|
85
|
+
- @zhin.js/core@1.1.36
|
|
86
|
+
|
|
3
87
|
## 1.1.0
|
|
4
88
|
|
|
5
89
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ pnpm add @zhin.js/adapter-wechat-mp
|
|
|
18
18
|
|
|
19
19
|
## Plugin Runtime
|
|
20
20
|
|
|
21
|
-
- `@zhin.js/adapter` — 约定式 `adapters/wechat-mp.ts`(`defineAdapter`)
|
|
21
|
+
- `@zhin.js/adapter` — 约定式 `adapters/wechat-mp/index.ts`(`defineAdapter`)
|
|
22
22
|
- `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
|
|
23
23
|
- `@zhin.js/host-http` — `httpHostToken` 注册 Webhook 路由(**非** legacy host-router/Koa)
|
|
24
24
|
- `zhin.js` — `plugin.ts`(`definePlugin`)
|
|
@@ -38,7 +38,8 @@ pnpm add @zhin.js/adapter-wechat-mp
|
|
|
38
38
|
| **回复模式** | 默认 `replyMode: passive`(订阅号被动回复);服务号可设 `customer_service` |
|
|
39
39
|
| **消息加密** | 可选;`encrypt: true` + `encodingAESKey`;`encryptMode: compatible`(默认)或 `secure` |
|
|
40
40
|
|
|
41
|
-
必填字段(`endpoints[i]`):`
|
|
41
|
+
必填字段(`endpoints[i]`):`id`、`appId`、`appSecret`、`token`。运行时由 AdapterIndex
|
|
42
|
+
把实例级默认值与每个 endpoint 合并;协议实现只接收一份展开后的 endpoint 配置。
|
|
42
43
|
|
|
43
44
|
## 最小配置
|
|
44
45
|
|
|
@@ -48,7 +49,7 @@ plugins:
|
|
|
48
49
|
wechat-mp:
|
|
49
50
|
path: /wechat/webhook
|
|
50
51
|
endpoints:
|
|
51
|
-
-
|
|
52
|
+
- id: my-wechat-bot
|
|
52
53
|
appId: "${WECHAT_APP_ID}"
|
|
53
54
|
appSecret: "${WECHAT_APP_SECRET}"
|
|
54
55
|
token: "${WECHAT_TOKEN}"
|
|
@@ -84,7 +85,7 @@ Runtime Host(`http`)须已 listen,Webhook 才可达。
|
|
|
84
85
|
|
|
85
86
|
## AI 工具
|
|
86
87
|
|
|
87
|
-
技能说明见 `
|
|
88
|
+
技能说明见 `skills/wechat-mp/SKILL.md`。
|
|
88
89
|
|
|
89
90
|
## 文档链接
|
|
90
91
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
/**
|
|
3
|
-
* Convention entry: discover `adapters/wechat-mp.ts` → defineAdapter.
|
|
3
|
+
* Convention entry: discover `adapters/wechat-mp/index.ts` → defineAdapter.
|
|
4
4
|
*/
|
|
5
5
|
import { defineAdapter } from 'zhin.js/adapter';
|
|
6
6
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
7
|
-
import { WeChatMpEndpoint } from "
|
|
8
|
-
import { resolveWeChatMpConfig, } from "
|
|
9
|
-
import { wechatMpRuntimeStateToken } from "
|
|
10
|
-
export { WeChatMpEndpoint } from "
|
|
7
|
+
import { WeChatMpEndpoint } from "../../lib/endpoint.js";
|
|
8
|
+
import { resolveWeChatMpConfig, } from "../../lib/protocol.js";
|
|
9
|
+
import { wechatMpRuntimeStateToken } from "../../lib/wechat-mp-runtime-state.js";
|
|
10
|
+
export { WeChatMpEndpoint } from "../../lib/endpoint.js";
|
|
11
11
|
export default defineAdapter({
|
|
12
12
|
capabilities: ['inbound', 'outbound'],
|
|
13
13
|
// 客服消息媒体统一经 /cgi-bin/media/upload 物化为 media_id(url 下载后上传,
|
|
@@ -18,7 +18,7 @@ export default defineAdapter({
|
|
|
18
18
|
},
|
|
19
19
|
create(context) {
|
|
20
20
|
const config = resolveWeChatMpConfig(context.config);
|
|
21
|
-
// 注册到插件运行时状态(wechat-mp
|
|
21
|
+
// 注册到插件运行时状态(wechat-mp endpoint list 的"运行中"数据源)
|
|
22
22
|
context.use(wechatMpRuntimeStateToken).endpoints.set(config.id, {
|
|
23
23
|
id: config.id,
|
|
24
24
|
mode: 'webhook',
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Convention entry: discover `adapters/wechat-mp.ts` → defineAdapter.
|
|
2
|
+
* Convention entry: discover `adapters/wechat-mp/index.ts` → defineAdapter.
|
|
3
3
|
*/
|
|
4
4
|
import { defineAdapter } from 'zhin.js/adapter';
|
|
5
5
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
6
|
-
import { WeChatMpEndpoint } from '
|
|
6
|
+
import { WeChatMpEndpoint } from '../../src/endpoint.js';
|
|
7
7
|
import {
|
|
8
8
|
resolveWeChatMpConfig,
|
|
9
|
-
type
|
|
10
|
-
} from '
|
|
11
|
-
import { wechatMpRuntimeStateToken } from '
|
|
9
|
+
type WeChatMpEndpointConfig,
|
|
10
|
+
} from '../../src/protocol.js';
|
|
11
|
+
import { wechatMpRuntimeStateToken } from '../../src/wechat-mp-runtime-state.js';
|
|
12
12
|
|
|
13
|
-
export { WeChatMpEndpoint } from '
|
|
14
|
-
export type { WeChatMpEndpointOptions } from '
|
|
15
|
-
export type { WeChatMpFetch } from '
|
|
13
|
+
export { WeChatMpEndpoint } from '../../src/endpoint.js';
|
|
14
|
+
export type { WeChatMpEndpointOptions } from '../../src/endpoint.js';
|
|
15
|
+
export type { WeChatMpFetch } from '../../src/client.js';
|
|
16
16
|
|
|
17
|
-
export default defineAdapter<
|
|
17
|
+
export default defineAdapter<WeChatMpEndpointConfig>({
|
|
18
18
|
capabilities: ['inbound', 'outbound'],
|
|
19
19
|
// 客服消息媒体统一经 /cgi-bin/media/upload 物化为 media_id(url 下载后上传,
|
|
20
20
|
// kind=file 的 MediaRef 视为既有 media_id 直传);公众号无卡片交互面,交互段降级纯文本。
|
|
@@ -24,7 +24,7 @@ export default defineAdapter<WeChatMpAdapterConfig>({
|
|
|
24
24
|
},
|
|
25
25
|
create(context) {
|
|
26
26
|
const config = resolveWeChatMpConfig(context.config);
|
|
27
|
-
// 注册到插件运行时状态(wechat-mp
|
|
27
|
+
// 注册到插件运行时状态(wechat-mp endpoint list 的"运行中"数据源)
|
|
28
28
|
context.use(wechatMpRuntimeStateToken).endpoints.set(config.id, {
|
|
29
29
|
id: config.id,
|
|
30
30
|
mode: 'webhook',
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
1
2
|
/**
|
|
2
|
-
* `wechat-mp
|
|
3
|
-
* commands/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
3
|
+
* `wechat-mp endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
|
|
4
|
+
* commands/wechat-mp/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
4
5
|
*/
|
|
5
6
|
import { createEndpointCommands } from 'zhin.js/adapter';
|
|
6
7
|
import { defineCommand } from 'zhin.js/command';
|
|
7
|
-
import { wechatMpRuntimeStateToken } from
|
|
8
|
+
import { wechatMpRuntimeStateToken } from "../../../lib/wechat-mp-runtime-state.js";
|
|
8
9
|
export const wechatMpEndpointCommands = createEndpointCommands({
|
|
9
10
|
adapterKey: 'wechat-mp',
|
|
10
11
|
adapterDisplayName: 'WeChat MP',
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `wechat-mp
|
|
3
|
-
* commands/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
2
|
+
* `wechat-mp endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
|
|
3
|
+
* commands/wechat-mp/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
4
4
|
*/
|
|
5
5
|
import { createEndpointCommands } from 'zhin.js/adapter';
|
|
6
6
|
import { defineCommand } from 'zhin.js/command';
|
|
7
|
-
import { wechatMpRuntimeStateToken } from '
|
|
7
|
+
import { wechatMpRuntimeStateToken } from '../../../src/wechat-mp-runtime-state.js';
|
|
8
8
|
|
|
9
9
|
export const wechatMpEndpointCommands = createEndpointCommands({
|
|
10
10
|
adapterKey: 'wechat-mp',
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { buildTextReply, computeSignatureHash, decryptEchostr, decryptMessage, encryptMessage, extractOutboundText, formatCustomerServiceBody, formatInboundContent, formatInboundId, isEncryptedEchostr, normalizeEchostrParam, parseXMLMessage, queryParam, readTextBody, resolveEventPassiveReply, resolveWeChatMpConfig, verifySignature, type ResolvedWeChatMpConfig, type TokenResponse, type WeChatAPIResponse, type WeChatMessage, type
|
|
1
|
+
export { buildTextReply, computeSignatureHash, decryptEchostr, decryptMessage, encryptMessage, extractOutboundText, formatCustomerServiceBody, formatInboundContent, formatInboundId, isEncryptedEchostr, normalizeEchostrParam, parseXMLMessage, queryParam, readTextBody, resolveEventPassiveReply, resolveWeChatMpConfig, verifySignature, type ResolvedWeChatMpConfig, type TokenResponse, type WeChatAPIResponse, type WeChatMessage, type WeChatMpEndpointConfig, type WeChatWireSegment, } from './protocol.js';
|
|
2
2
|
export { getPassiveReplyCapture, recordPassiveReplyText, runWithPassiveReplyCapture, type PassiveReplyCapture, } from './passive-reply.js';
|
|
3
3
|
export { WeChatMpClient, wechatMpClient, type WeChatMpClientEventMap, type WeChatMpFetch, } from './client.js';
|
|
4
4
|
export { WeChatMpEndpoint, type WeChatMpEndpointOptions, } from './endpoint.js';
|
package/lib/media-upload.d.ts
CHANGED
package/lib/media-upload.js
CHANGED
package/lib/protocol.d.ts
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { IncomingMessage } from 'node:http';
|
|
6
6
|
import type { ConversationRef } from '@zhin.js/im-contract';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
readonly
|
|
10
|
-
readonly
|
|
11
|
-
readonly
|
|
7
|
+
/** One endpoint config after AdapterIndex expands `plugins.<instanceKey>.endpoints`. */
|
|
8
|
+
export interface WeChatMpEndpointConfig {
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly appId: string;
|
|
11
|
+
readonly appSecret: string;
|
|
12
|
+
readonly token: string;
|
|
12
13
|
readonly encodingAESKey?: string;
|
|
13
14
|
readonly path?: string;
|
|
14
15
|
readonly encrypt?: boolean;
|
|
@@ -25,10 +26,6 @@ export interface WeChatMpAdapterConfig {
|
|
|
25
26
|
readonly replyMode?: 'passive' | 'customer_service';
|
|
26
27
|
/** 被动回复等待入站处理的最长时间(毫秒),默认 4500 */
|
|
27
28
|
readonly passiveReplyTimeoutMs?: number;
|
|
28
|
-
/** Transitional: legacy root `endpoints[]` with `context: wechat-mp`. */
|
|
29
|
-
readonly endpoints?: ReadonlyArray<Partial<ResolvedWeChatMpConfig> & {
|
|
30
|
-
readonly context?: string;
|
|
31
|
-
}>;
|
|
32
29
|
}
|
|
33
30
|
export interface ResolvedWeChatMpConfig {
|
|
34
31
|
readonly context: 'wechat-mp';
|
|
@@ -79,7 +76,7 @@ export interface WeChatWireSegment {
|
|
|
79
76
|
readonly type: string;
|
|
80
77
|
readonly data?: Record<string, unknown>;
|
|
81
78
|
}
|
|
82
|
-
export declare function resolveWeChatMpConfig(config
|
|
79
|
+
export declare function resolveWeChatMpConfig(config: WeChatMpEndpointConfig): ResolvedWeChatMpConfig;
|
|
83
80
|
export declare function queryParam(value: string | null | undefined): string;
|
|
84
81
|
/** URL 查询里的 Base64 可能把 `+` 解码成空格 */
|
|
85
82
|
export declare function normalizeEchostrParam(echostr: string): string;
|
package/lib/protocol.js
CHANGED
|
@@ -4,26 +4,17 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { createHash, createDecipheriv, createCipheriv, randomBytes } from 'node:crypto';
|
|
6
6
|
import * as xml2js from 'xml2js';
|
|
7
|
-
export function resolveWeChatMpConfig(config
|
|
8
|
-
const
|
|
9
|
-
const appId = config.appId
|
|
10
|
-
const appSecret = config.appSecret
|
|
11
|
-
const token = config.token
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|| 'wechat-mp-bot';
|
|
19
|
-
const path = config.path ?? entry?.path ?? '/wechat/webhook';
|
|
20
|
-
const encodingAESKey = config.encodingAESKey ?? entry?.encodingAESKey;
|
|
21
|
-
const encrypt = config.encrypt ?? entry?.encrypt ?? false;
|
|
22
|
-
const encryptMode = config.encryptMode ?? entry?.encryptMode ?? (encrypt ? 'compatible' : 'plain');
|
|
23
|
-
const replyMode = config.replyMode ?? entry?.replyMode ?? 'passive';
|
|
24
|
-
const passiveReplyTimeoutMs = config.passiveReplyTimeoutMs
|
|
25
|
-
?? entry?.passiveReplyTimeoutMs
|
|
26
|
-
?? 4500;
|
|
7
|
+
export function resolveWeChatMpConfig(config) {
|
|
8
|
+
const id = requiredEndpointField(config.id, 'id');
|
|
9
|
+
const appId = requiredEndpointField(config.appId, 'appId');
|
|
10
|
+
const appSecret = requiredEndpointField(config.appSecret, 'appSecret');
|
|
11
|
+
const token = requiredEndpointField(config.token, 'token');
|
|
12
|
+
const path = optionalEndpointField(config.path) ?? '/wechat/webhook';
|
|
13
|
+
const encodingAESKey = optionalEndpointField(config.encodingAESKey);
|
|
14
|
+
const encrypt = config.encrypt ?? false;
|
|
15
|
+
const encryptMode = config.encryptMode ?? (encrypt ? 'compatible' : 'plain');
|
|
16
|
+
const replyMode = config.replyMode ?? 'passive';
|
|
17
|
+
const passiveReplyTimeoutMs = config.passiveReplyTimeoutMs ?? 4500;
|
|
27
18
|
return {
|
|
28
19
|
context: 'wechat-mp',
|
|
29
20
|
id,
|
|
@@ -38,6 +29,16 @@ export function resolveWeChatMpConfig(config = {}) {
|
|
|
38
29
|
passiveReplyTimeoutMs,
|
|
39
30
|
};
|
|
40
31
|
}
|
|
32
|
+
function requiredEndpointField(value, field) {
|
|
33
|
+
const resolved = optionalEndpointField(value);
|
|
34
|
+
if (!resolved) {
|
|
35
|
+
throw new TypeError(`WeChat MP endpoint requires a non-empty ${field}`);
|
|
36
|
+
}
|
|
37
|
+
return resolved;
|
|
38
|
+
}
|
|
39
|
+
function optionalEndpointField(value) {
|
|
40
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
41
|
+
}
|
|
41
42
|
export function queryParam(value) {
|
|
42
43
|
return value ?? '';
|
|
43
44
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WeChat MP 插件实例的运行时状态:adapter create() 注册的 endpoint 列表。
|
|
3
|
-
* 由 plugin.ts setup() provide,adapter create 与 `wechat-mp
|
|
3
|
+
* 由 plugin.ts setup() provide,adapter create 与 `wechat-mp endpoint` 命令共享(同一 owner generation)。
|
|
4
4
|
*/
|
|
5
5
|
import { defineEndpointRuntimeStateToken } from 'zhin.js/adapter';
|
|
6
6
|
export const wechatMpRuntimeStateToken = defineEndpointRuntimeStateToken('wechat-mp');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-wechat-mp",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Zhin.js WeChat Official Account adapter for Plugin Runtime (HTTP webhook)",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -8,19 +8,20 @@
|
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"axios": "^1.19.0",
|
|
10
10
|
"xml2js": "^0.6.2",
|
|
11
|
-
"@zhin.js/adapter": "1.1.
|
|
12
|
-
"@zhin.js/core": "1.1.
|
|
13
|
-
"@zhin.js/feature-kit": "1.1.
|
|
14
|
-
"@zhin.js/host-http": "1.1.
|
|
15
|
-
"@zhin.js/im-contract": "1.1.
|
|
16
|
-
"@zhin.js/logger": "1.1.
|
|
11
|
+
"@zhin.js/adapter": "1.1.14",
|
|
12
|
+
"@zhin.js/core": "1.1.37",
|
|
13
|
+
"@zhin.js/feature-kit": "1.1.1",
|
|
14
|
+
"@zhin.js/host-http": "1.1.1",
|
|
15
|
+
"@zhin.js/im-contract": "1.1.1",
|
|
16
|
+
"@zhin.js/logger": "1.1.1",
|
|
17
|
+
"@zhin.js/skill": "1.1.1"
|
|
17
18
|
},
|
|
18
19
|
"peerDependencies": {
|
|
19
|
-
"@zhin.js/adapter": "^1.1.
|
|
20
|
-
"@zhin.js/command": "^1.1.
|
|
21
|
-
"@zhin.js/core": "^1.1.
|
|
22
|
-
"@zhin.js/host-http": "^1.1.
|
|
23
|
-
"zhin.js": "^1.1.
|
|
20
|
+
"@zhin.js/adapter": "^1.1.14",
|
|
21
|
+
"@zhin.js/command": "^1.1.1",
|
|
22
|
+
"@zhin.js/core": "^1.1.37",
|
|
23
|
+
"@zhin.js/host-http": "^1.1.1",
|
|
24
|
+
"zhin.js": "^1.1.2"
|
|
24
25
|
},
|
|
25
26
|
"peerDependenciesMeta": {
|
|
26
27
|
"@zhin.js/command": {
|
|
@@ -35,7 +36,7 @@
|
|
|
35
36
|
"@types/xml2js": "^0.4.14",
|
|
36
37
|
"typescript": "^6.0.3",
|
|
37
38
|
"vitest": "^4.1.10",
|
|
38
|
-
"zhin.js": "1.1.
|
|
39
|
+
"zhin.js": "1.1.2"
|
|
39
40
|
},
|
|
40
41
|
"keywords": [
|
|
41
42
|
"zhin",
|
|
@@ -67,7 +68,7 @@
|
|
|
67
68
|
"schema.json",
|
|
68
69
|
"src",
|
|
69
70
|
"lib",
|
|
70
|
-
"
|
|
71
|
+
"skills",
|
|
71
72
|
"README.md",
|
|
72
73
|
"CHANGELOG.md"
|
|
73
74
|
],
|
|
@@ -99,6 +100,10 @@
|
|
|
99
100
|
{
|
|
100
101
|
"package": "@zhin.js/command",
|
|
101
102
|
"api": "^1.0.0"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"package": "@zhin.js/skill",
|
|
106
|
+
"api": "^1.0.0"
|
|
102
107
|
}
|
|
103
108
|
],
|
|
104
109
|
"plugins": []
|
package/plugin.js
CHANGED
|
@@ -8,7 +8,7 @@ export default definePlugin({
|
|
|
8
8
|
displayName: 'WeChat Official Account Adapter',
|
|
9
9
|
},
|
|
10
10
|
setup(context) {
|
|
11
|
-
// 运行中 endpoint 注册表(wechat-mp
|
|
11
|
+
// 运行中 endpoint 注册表(wechat-mp endpoint list 的"运行中"数据源)
|
|
12
12
|
context.resources.provide(wechatMpRuntimeStateToken, createEndpointRuntimeState());
|
|
13
13
|
},
|
|
14
14
|
});
|
package/schema.json
CHANGED
|
@@ -52,10 +52,11 @@
|
|
|
52
52
|
},
|
|
53
53
|
"endpoints": {
|
|
54
54
|
"type": "array",
|
|
55
|
+
"minItems": 1,
|
|
55
56
|
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(id 必填,其余覆盖顶层)",
|
|
56
57
|
"items": {
|
|
57
58
|
"type": "object",
|
|
58
|
-
"additionalProperties":
|
|
59
|
+
"additionalProperties": false,
|
|
59
60
|
"properties": {
|
|
60
61
|
"master": {
|
|
61
62
|
"type": [
|
|
@@ -91,6 +92,33 @@
|
|
|
91
92
|
"type": "string",
|
|
92
93
|
"description": "WeChat MP encoding AES key"
|
|
93
94
|
},
|
|
95
|
+
"path": {
|
|
96
|
+
"type": "string"
|
|
97
|
+
},
|
|
98
|
+
"encrypt": {
|
|
99
|
+
"type": "boolean"
|
|
100
|
+
},
|
|
101
|
+
"encryptMode": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"enum": [
|
|
104
|
+
"plain",
|
|
105
|
+
"compatible",
|
|
106
|
+
"secure"
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
"replyMode": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"enum": [
|
|
112
|
+
"passive",
|
|
113
|
+
"customer_service"
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
"passiveReplyTimeoutMs": {
|
|
117
|
+
"type": "number"
|
|
118
|
+
},
|
|
119
|
+
"commandPrefix": {
|
|
120
|
+
"type": "string"
|
|
121
|
+
},
|
|
94
122
|
"id": {
|
|
95
123
|
"type": "string",
|
|
96
124
|
"description": "WeChat MP bot name"
|
package/src/index.ts
CHANGED
package/src/media-upload.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { readFile } from 'node:fs/promises';
|
|
8
8
|
import { basename } from 'node:path';
|
|
9
|
-
import { isMediaRef, type MediaRef } from '@zhin.js/
|
|
9
|
+
import { isMediaRef, type MediaRef } from '@zhin.js/im-contract';
|
|
10
10
|
|
|
11
11
|
export interface MediaBinary {
|
|
12
12
|
readonly data: Buffer;
|
package/src/protocol.ts
CHANGED
|
@@ -8,11 +8,12 @@ import type { IncomingMessage } from 'node:http';
|
|
|
8
8
|
import * as xml2js from 'xml2js';
|
|
9
9
|
import type { ConversationRef } from '@zhin.js/im-contract';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
readonly
|
|
14
|
-
readonly
|
|
15
|
-
readonly
|
|
11
|
+
/** One endpoint config after AdapterIndex expands `plugins.<instanceKey>.endpoints`. */
|
|
12
|
+
export interface WeChatMpEndpointConfig {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly appId: string;
|
|
15
|
+
readonly appSecret: string;
|
|
16
|
+
readonly token: string;
|
|
16
17
|
readonly encodingAESKey?: string;
|
|
17
18
|
readonly path?: string;
|
|
18
19
|
readonly encrypt?: boolean;
|
|
@@ -29,10 +30,6 @@ export interface WeChatMpAdapterConfig {
|
|
|
29
30
|
readonly replyMode?: 'passive' | 'customer_service';
|
|
30
31
|
/** 被动回复等待入站处理的最长时间(毫秒),默认 4500 */
|
|
31
32
|
readonly passiveReplyTimeoutMs?: number;
|
|
32
|
-
/** Transitional: legacy root `endpoints[]` with `context: wechat-mp`. */
|
|
33
|
-
readonly endpoints?: ReadonlyArray<Partial<ResolvedWeChatMpConfig> & {
|
|
34
|
-
readonly context?: string;
|
|
35
|
-
}>;
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
export interface ResolvedWeChatMpConfig {
|
|
@@ -89,28 +86,17 @@ export interface WeChatWireSegment {
|
|
|
89
86
|
readonly data?: Record<string, unknown>;
|
|
90
87
|
}
|
|
91
88
|
|
|
92
|
-
export function resolveWeChatMpConfig(config:
|
|
93
|
-
const
|
|
94
|
-
const appId = config.appId
|
|
95
|
-
const appSecret = config.appSecret
|
|
96
|
-
const token = config.token
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|| (typeof entry?.id === 'string' && entry.id)
|
|
104
|
-
|| process.env.WECHAT_BOT_NAME
|
|
105
|
-
|| 'wechat-mp-bot';
|
|
106
|
-
const path = config.path ?? entry?.path ?? '/wechat/webhook';
|
|
107
|
-
const encodingAESKey = config.encodingAESKey ?? entry?.encodingAESKey;
|
|
108
|
-
const encrypt = config.encrypt ?? entry?.encrypt ?? false;
|
|
109
|
-
const encryptMode = config.encryptMode ?? entry?.encryptMode ?? (encrypt ? 'compatible' : 'plain');
|
|
110
|
-
const replyMode = config.replyMode ?? entry?.replyMode ?? 'passive';
|
|
111
|
-
const passiveReplyTimeoutMs = config.passiveReplyTimeoutMs
|
|
112
|
-
?? entry?.passiveReplyTimeoutMs
|
|
113
|
-
?? 4500;
|
|
89
|
+
export function resolveWeChatMpConfig(config: WeChatMpEndpointConfig): ResolvedWeChatMpConfig {
|
|
90
|
+
const id = requiredEndpointField(config.id, 'id');
|
|
91
|
+
const appId = requiredEndpointField(config.appId, 'appId');
|
|
92
|
+
const appSecret = requiredEndpointField(config.appSecret, 'appSecret');
|
|
93
|
+
const token = requiredEndpointField(config.token, 'token');
|
|
94
|
+
const path = optionalEndpointField(config.path) ?? '/wechat/webhook';
|
|
95
|
+
const encodingAESKey = optionalEndpointField(config.encodingAESKey);
|
|
96
|
+
const encrypt = config.encrypt ?? false;
|
|
97
|
+
const encryptMode = config.encryptMode ?? (encrypt ? 'compatible' : 'plain');
|
|
98
|
+
const replyMode = config.replyMode ?? 'passive';
|
|
99
|
+
const passiveReplyTimeoutMs = config.passiveReplyTimeoutMs ?? 4500;
|
|
114
100
|
return {
|
|
115
101
|
context: 'wechat-mp',
|
|
116
102
|
id,
|
|
@@ -126,6 +112,21 @@ export function resolveWeChatMpConfig(config: WeChatMpAdapterConfig = {}): Resol
|
|
|
126
112
|
};
|
|
127
113
|
}
|
|
128
114
|
|
|
115
|
+
function requiredEndpointField(
|
|
116
|
+
value: unknown,
|
|
117
|
+
field: 'id' | 'appId' | 'appSecret' | 'token',
|
|
118
|
+
): string {
|
|
119
|
+
const resolved = optionalEndpointField(value);
|
|
120
|
+
if (!resolved) {
|
|
121
|
+
throw new TypeError(`WeChat MP endpoint requires a non-empty ${field}`);
|
|
122
|
+
}
|
|
123
|
+
return resolved;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function optionalEndpointField(value: unknown): string | undefined {
|
|
127
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
128
|
+
}
|
|
129
|
+
|
|
129
130
|
export function queryParam(value: string | null | undefined): string {
|
|
130
131
|
return value ?? '';
|
|
131
132
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WeChat MP 插件实例的运行时状态:adapter create() 注册的 endpoint 列表。
|
|
3
|
-
* 由 plugin.ts setup() provide,adapter create 与 `wechat-mp
|
|
3
|
+
* 由 plugin.ts setup() provide,adapter create 与 `wechat-mp endpoint` 命令共享(同一 owner generation)。
|
|
4
4
|
*/
|
|
5
5
|
import { defineEndpointRuntimeStateToken } from 'zhin.js/adapter';
|
|
6
6
|
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wechat-mp
|
|
3
|
-
platforms:
|
|
4
|
-
- wechat-mp
|
|
5
|
-
description: >-
|
|
6
|
-
微信公众号适配器:通过 Webhook 接收用户消息、自动管理 Access Token、
|
|
7
|
-
支持 XML 消息解析和 AES 消息加解密。纯消息通道,无额外 AI 工具。
|
|
8
|
-
当上下文涉及微信公众号消息交互时可参考此技能了解能力边界。
|
|
9
|
-
keywords:
|
|
10
|
-
- wechat
|
|
11
|
-
- weixin
|
|
12
|
-
- adapter:wechat-mp
|
|
13
|
-
- 微信
|
|
14
|
-
- 公众号
|
|
15
|
-
- official-account
|
|
16
|
-
- mp
|
|
17
|
-
tags:
|
|
18
|
-
- wechat
|
|
19
|
-
- adapter
|
|
20
|
-
- social
|
|
21
|
-
tools: []
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
# 微信公众号适配器
|
|
25
|
-
|
|
26
|
-
纯消息通道,收发微信公众号用户消息。无 AI 工具可调用。
|
|
27
|
-
|
|
28
|
-
## 能力
|
|
29
|
-
|
|
30
|
-
- 通过 HTTP 回调接收微信推送的用户消息事件
|
|
31
|
-
- 自动刷新 Access Token,无需手动维护
|
|
32
|
-
- 支持签名验证和 AES 消息加解密
|
|
33
|
-
- 回复通过常规 `$reply` 发送
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const wechatMpEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage, string | undefined>>>;
|