@zzedbot/yunzhijia 2.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zed
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,326 @@
1
+ # 🤖 云之家 Channel 插件
2
+
3
+ OpenClaw 金蝶云之家 (YunzhiJia) 消息渠道插件,支持在云之家中集成 OpenClaw AI 能力。
4
+
5
+ ![Version](https://img.shields.io/badge/version-2.0.0-blue)
6
+ ![License](https://img.shields.io/badge/license-MIT-green)
7
+
8
+ ---
9
+
10
+ ## 📋 简介
11
+
12
+ 云之家 Channel 插件允许你在金蝶云之家的群组或私聊中使用 OpenClaw AI 机器人。支持:
13
+
14
+ - ✅ Webhook 消息接收(HmacSHA1 签名验证)
15
+ - ✅ AI 智能回复(基于上下文的对话)
16
+ - ✅ 多账户支持
17
+ - ✅ 群组消息处理
18
+ - ✅ 访问控制(白名单机制)
19
+
20
+ ---
21
+
22
+ ## 🚀 快速开始
23
+
24
+ ### 方式一:安装已编译的插件(推荐)
25
+
26
+ ```bash
27
+ # 安装插件到 OpenClaw 扩展目录
28
+ openclaw plugins install <YOUR_WORKSPACE>/projects/yunzhijiachannel
29
+
30
+ # 或手动复制到扩展目录
31
+ cp -r <YOUR_WORKSPACE>/projects/yunzhijiachannel ~/.openclaw/extensions/yunzhijia
32
+
33
+ # 启用插件
34
+ openclaw plugins enable yunzhijia
35
+
36
+ # 重启 Gateway
37
+ openclaw gateway restart
38
+ ```
39
+
40
+ ### 方式二:从开发目录链接(开发者)
41
+
42
+ ```bash
43
+ # 开发模式下,直接链接到开发目录
44
+ openclaw plugins install -l <YOUR_WORKSPACE>/projects/yunzhijiachannel
45
+
46
+ # 重启 Gateway
47
+ openclaw gateway restart
48
+ ```
49
+
50
+ > 💡 **说明**:
51
+ > - 生产环境使用 **方式一**,插件安装在 `~/.openclaw/extensions/yunzhijia`
52
+ > - 开发环境使用 **方式二**,直接链接到开发目录 `<YOUR_WORKSPACE>/projects/yunzhijiachannel`
53
+
54
+ ---
55
+
56
+ ## ⚙️ 配置
57
+
58
+ ### 1. 获取云之家凭证
59
+
60
+ 登录 [云之家开放平台](https://open.yunzhijia.com/),创建对话机器人并获取:
61
+
62
+ | 凭证 | 获取位置 |
63
+ |------|---------|
64
+ | `appId` | 应用详情 |
65
+ | `appSecret` | 安全设置 |
66
+ | `token` | 消息配置 |
67
+ | `webhookToken` | Webhook 设置 |
68
+
69
+ ### 2. 配置 OpenClaw
70
+
71
+ 编辑 `~/.openclaw/openclaw.json`:
72
+
73
+ ```json5
74
+ {
75
+ "channels": {
76
+ "yunzhijia": {
77
+ "enabled": true,
78
+ "accounts": {
79
+ "default": {
80
+ "enabled": true,
81
+ "appId": "<YOUR_APP_ID>",
82
+ "appSecret": "<YOUR_APP_SECRET>",
83
+ "token": "<YOUR_TOKEN>",
84
+ "webhookToken": "<YOUR_WEBHOOK_TOKEN>",
85
+ "webhookPort": 18790,
86
+ "webhookHost": "0.0.0.0",
87
+ "dmPolicy": "allowlist",
88
+ "allowFrom": ["<USER_OPENID_1>", "<USER_OPENID_2>"]
89
+ }
90
+ }
91
+ }
92
+ },
93
+ "plugins": {
94
+ "allow": ["yunzhijia"],
95
+ "entries": {
96
+ "yunzhijia": {
97
+ "enabled": true
98
+ }
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ > ⚠️ **安全提示**:
105
+ > - 不要将真实密钥提交到 Git
106
+ > - 建议使用环境变量或密钥管理工具
107
+ > - 定期轮换密钥
108
+
109
+ ### 3. 配置云之家 Webhook
110
+
111
+ 在云之家机器人设置中配置消息接收地址:
112
+
113
+ ```
114
+ 消息接收地址:https://<YOUR_DOMAIN>/yunzhijia/webhook/default
115
+ ```
116
+
117
+ > 💡 如果使用内网部署,需要配置外网映射(如 Nginx 反向代理)
118
+
119
+ ### 4. 重启 Gateway
120
+
121
+ ```bash
122
+ openclaw gateway restart
123
+ ```
124
+
125
+ ---
126
+
127
+ ## 📖 配置说明
128
+
129
+ ### 必需字段
130
+
131
+ | 字段 | 说明 | 示例 |
132
+ |------|------|------|
133
+ | `appId` | 云之家应用 ID | `app_12345` |
134
+ | `appSecret` | 应用密钥(用于签名验证) | `abc123...` |
135
+ | `token` | 消息接收 Token | `token_xyz...` |
136
+ | `webhookToken` | Webhook 发送授权码 | `c7d28f...` |
137
+
138
+ ### 可选字段
139
+
140
+ | 字段 | 说明 | 默认值 |
141
+ |------|------|--------|
142
+ | `webhookPort` | Webhook 监听端口 | `18790` |
143
+ | `webhookHost` | Webhook 监听地址 | `0.0.0.0` |
144
+ | `webhookPath` | Webhook 路径 | `/yunzhijia/webhook/<accountId>` |
145
+ | `dmPolicy` | DM 策略 (`pairing` \| `allowlist` \| `open`) | `pairing` |
146
+ | `allowFrom` | 允许的用户 OpenID 列表 | `[]` |
147
+ | `groupPolicy` | 群组策略 (`allowlist` \| `open`) | `allowlist` |
148
+
149
+ ### 获取用户 OpenID
150
+
151
+ **方法 1**: 查看 Gateway 日志
152
+ ```bash
153
+ tail -f /tmp/openclaw/openclaw.log | grep operatorOpenid
154
+ ```
155
+
156
+ **方法 2**: 用户首次发消息后,从日志中提取 `operatorOpenid` 字段
157
+
158
+ ---
159
+
160
+ ## 🧪 测试
161
+
162
+ ### 1. 本地 Webhook 测试
163
+
164
+ ```bash
165
+ cd <YOUR_WORKSPACE>/projects/yunzhijiachannel
166
+ ./test-webhook.sh
167
+ ```
168
+
169
+ ### 2. 查看日志
170
+
171
+ ```bash
172
+ # 实时日志
173
+ tail -f /tmp/openclaw/openclaw.log | grep yunzhijia
174
+
175
+ # 最近 100 条
176
+ tail -100 /tmp/openclaw/openclaw.log | grep yunzhijia
177
+ ```
178
+
179
+ ### 3. 云之家测试
180
+
181
+ 1. 在云之家群组中 @机器人
182
+ 2. 发送消息:`你好`
183
+ 3. 查看是否收到 AI 回复
184
+
185
+ ---
186
+
187
+ ## 📚 文档导航
188
+
189
+ ### 部署与配置
190
+ - [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) - 详细部署指南
191
+ - [docs/PRODUCTION_CONFIG.md](docs/PRODUCTION_CONFIG.md) - 生产环境配置
192
+
193
+ ### 技术文档
194
+ - [docs/IMPLEMENTATION.md](docs/IMPLEMENTATION.md) - 实现说明
195
+ - [docs/AI_INTEGRATION_GUIDE.md](docs/AI_INTEGRATION_GUIDE.md) - AI 集成指南
196
+ - [docs/YUNZHIJIA_API.md](docs/YUNZHIJIA_API.md) - 云之家 API 文档
197
+
198
+ ### 开发文档
199
+ - [docs/development/](docs/development/) - 开发过程文档
200
+
201
+ ---
202
+
203
+ ## 🏗️ 项目结构
204
+
205
+ ```
206
+ yunzhijiachannel/
207
+ ├── src/ # 源代码
208
+ │ ├── channel.ts # Channel 核心实现
209
+ │ ├── webhook-server.ts # Webhook 服务器
210
+ │ ├── crypto.ts # 签名验证
211
+ │ ├── api.ts # 消息发送 API
212
+ │ └── ...
213
+ ├── docs/ # 文档目录
214
+ │ ├── DEPLOYMENT.md
215
+ │ ├── PRODUCTION_CONFIG.md
216
+ │ └── ...
217
+ ├── package.json # NPM 配置
218
+ ├── openclaw.plugin.json # OpenClaw 插件清单
219
+ └── tsconfig.json # TypeScript 配置
220
+ ```
221
+
222
+ ### 目录说明
223
+
224
+ | 目录 | 说明 |
225
+ |------|------|
226
+ | `src/` | TypeScript 源代码 |
227
+ | `docs/` | 项目文档 |
228
+ | `dist/` | 编译输出(自动忽略) |
229
+ | `node_modules/` | NPM 依赖(自动忽略) |
230
+
231
+ ---
232
+
233
+ ## 🛠️ 开发
234
+
235
+ ### 环境要求
236
+
237
+ - Node.js >= 18
238
+ - npm >= 9
239
+ - OpenClaw >= 2026.3.0
240
+
241
+ ### 安装依赖
242
+
243
+ ```bash
244
+ cd <YOUR_WORKSPACE>/projects/yunzhijiachannel
245
+ npm install
246
+ ```
247
+
248
+ ### 编译
249
+
250
+ ```bash
251
+ npm run build
252
+ ```
253
+
254
+ ### 开发模式
255
+
256
+ ```bash
257
+ npm run dev
258
+ ```
259
+
260
+ ### 测试
261
+
262
+ ```bash
263
+ npm test
264
+ ```
265
+
266
+ ---
267
+
268
+ ## 🔒 安全最佳实践
269
+
270
+ 1. **保护敏感信息**
271
+ - 不要将 `appSecret` 和 `webhookToken` 提交到 Git
272
+ - 使用环境变量或密钥管理工具
273
+ - 定期轮换密钥
274
+
275
+ 2. **访问控制**
276
+ - 使用 `allowFrom` 白名单限制用户
277
+ - 配置 `dmPolicy: "allowlist"`
278
+ - 群组启用 `requireMention: true`
279
+
280
+ 3. **网络安全**
281
+ - 使用 HTTPS 部署 Webhook
282
+ - 配置防火墙限制访问来源
283
+ - 定期审计日志
284
+
285
+ ---
286
+
287
+ ## 🐛 故障排查
288
+
289
+ ### 收不到消息
290
+
291
+ 1. 检查云之家 Webhook 地址是否正确
292
+ 2. 检查外网映射是否正常
293
+ 3. 检查防火墙设置
294
+ 4. 查看 Gateway 日志
295
+
296
+ ### 签名验证失败
297
+
298
+ ```bash
299
+ # 检查 appSecret 是否正确
300
+ tail /tmp/openclaw/openclaw.log | grep "Invalid signature"
301
+ ```
302
+
303
+ ### 无法发送回复
304
+
305
+ ```bash
306
+ # 检查 webhookToken 是否正确
307
+ tail /tmp/openclaw/openclaw.log | grep "发送失败"
308
+ ```
309
+
310
+ ---
311
+
312
+ ## 📄 许可证
313
+
314
+ MIT License
315
+
316
+ ---
317
+
318
+ ## 🤝 贡献
319
+
320
+ 欢迎提交 Issue 和 Pull Request!
321
+
322
+ ---
323
+
324
+ **版本**: v2.0.0
325
+ **最后更新**: 2026-03-07
326
+ **维护者**: Zed
package/dist/api.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ import type { YunzhiJiaSendResult } from "./types.js";
2
+ /**
3
+ * 发送文本消息
4
+ */
5
+ export declare function sendTextMessage(params: {
6
+ webhookToken: string;
7
+ content: string;
8
+ notifyParams?: Array<{
9
+ type: string;
10
+ values: string[];
11
+ }>;
12
+ }): Promise<YunzhiJiaSendResult>;
13
+ /**
14
+ * 发送应用类消息
15
+ */
16
+ export declare function sendAppMessage(params: {
17
+ webhookToken: string;
18
+ content: string;
19
+ param: {
20
+ appName: string;
21
+ title: string;
22
+ content?: string;
23
+ lightAppId?: string;
24
+ thumbUrl?: string;
25
+ webpageUrl?: string;
26
+ customStyle?: 0 | 1 | 2;
27
+ primaryContent?: string;
28
+ contentUrl?: string;
29
+ };
30
+ }): Promise<YunzhiJiaSendResult>;
31
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAKtD;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC1D,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA8B/B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA8B/B"}
package/dist/api.js ADDED
@@ -0,0 +1,66 @@
1
+ import axios from "axios";
2
+ const WEBHOOK_BASE_URL = "https://www.yunzhijia.com/gateway/robot/webhook/send";
3
+ const WEBHOOK_DEFAULT_PARAMS = "?yzjtype=12&yzjtoken=";
4
+ /**
5
+ * 发送文本消息
6
+ */
7
+ export async function sendTextMessage(params) {
8
+ const { webhookToken, content, notifyParams } = params;
9
+ // 使用配置的 yzjtype=12
10
+ const url = `${WEBHOOK_BASE_URL}${WEBHOOK_DEFAULT_PARAMS}${webhookToken}`;
11
+ const payload = { content };
12
+ if (notifyParams) {
13
+ payload.notifyParams = notifyParams;
14
+ }
15
+ try {
16
+ const response = await axios.post(url, payload, {
17
+ headers: {
18
+ "Content-Type": "application/json",
19
+ },
20
+ });
21
+ return {
22
+ messageId: `yj_${Date.now()}`,
23
+ success: true,
24
+ };
25
+ }
26
+ catch (error) {
27
+ const errorMessage = error instanceof Error ? error.message : String(error);
28
+ return {
29
+ messageId: `yj_${Date.now()}`,
30
+ success: false,
31
+ error: errorMessage,
32
+ };
33
+ }
34
+ }
35
+ /**
36
+ * 发送应用类消息
37
+ */
38
+ export async function sendAppMessage(params) {
39
+ const { webhookToken, content, param } = params;
40
+ const url = `${WEBHOOK_BASE_URL}?yzjtype=0&yzjtoken=${webhookToken}`;
41
+ const payload = {
42
+ content,
43
+ msgType: 1,
44
+ param,
45
+ };
46
+ try {
47
+ const response = await axios.post(url, payload, {
48
+ headers: {
49
+ "Content-Type": "application/json",
50
+ },
51
+ });
52
+ return {
53
+ messageId: `yj_${Date.now()}`,
54
+ success: true,
55
+ };
56
+ }
57
+ catch (error) {
58
+ const errorMessage = error instanceof Error ? error.message : String(error);
59
+ return {
60
+ messageId: `yj_${Date.now()}`,
61
+ success: false,
62
+ error: errorMessage,
63
+ };
64
+ }
65
+ }
66
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,gBAAgB,GAAG,sDAAsD,CAAC;AAChF,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AAEvD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAIrC;IACC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAEvD,mBAAmB;IACnB,MAAM,GAAG,GAAG,GAAG,gBAAgB,GAAG,sBAAsB,GAAG,YAAY,EAAE,CAAC;IAE1E,MAAM,OAAO,GAA4B,EAAE,OAAO,EAAE,CAAC;IACrD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,CAAC,YAAY,GAAG,YAAY,CAAC;IACtC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE;YAC9C,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC,CAAC;QAEH,OAAO;YACL,SAAS,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE;YAC7B,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,OAAO;YACL,SAAS,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE;YAC7B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,YAAY;SACpB,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAcpC;IACC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAEhD,MAAM,GAAG,GAAG,GAAG,gBAAgB,uBAAuB,YAAY,EAAE,CAAC;IAErE,MAAM,OAAO,GAAG;QACd,OAAO;QACP,OAAO,EAAE,CAAC;QACV,KAAK;KACN,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE;YAC9C,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC,CAAC;QAEH,OAAO;YACL,SAAS,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE;YAC7B,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,OAAO;YACL,SAAS,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE;YAC7B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,YAAY;SACpB,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
2
+ export default function register(api: OpenClawPluginApi): void;
3
+ //# sourceMappingURL=channel-simple.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-simple.d.ts","sourceRoot":"","sources":["../src/channel-simple.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAiB,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAwD5E,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,iBAAiB,QAGtD"}
@@ -0,0 +1,60 @@
1
+ // 简化的云之家 Channel 插件 - 框架版本
2
+ // 完整实现需要参考 Telegram 插件结构
3
+ import { setYunzhiJiaRuntime } from "./runtime.js";
4
+ const yunzhijiaPlugin = {
5
+ id: "yunzhijia",
6
+ meta: {
7
+ id: "yunzhijia",
8
+ label: "金蝶云之家",
9
+ selectionLabel: "金蝶云之家 (Webhook)",
10
+ docsPath: "/channels/yunzhijia",
11
+ blurb: "金蝶云之家企业消息平台",
12
+ aliases: ["yzj"],
13
+ },
14
+ capabilities: {
15
+ chatTypes: ["direct", "group"],
16
+ reactions: false,
17
+ threads: false,
18
+ media: false,
19
+ polls: false,
20
+ nativeCommands: false,
21
+ blockStreaming: false,
22
+ },
23
+ reload: { configPrefixes: ["channels.yunzhijia"] },
24
+ config: {
25
+ listAccountIds: (cfg) => {
26
+ const accounts = cfg.channels?.yunzhijia?.accounts;
27
+ return accounts ? Object.keys(accounts) : ["default"];
28
+ },
29
+ resolveAccount: (cfg, accountId) => {
30
+ const id = accountId ?? "default";
31
+ const accounts = cfg.channels?.yunzhijia?.accounts;
32
+ return accounts?.[id] ?? { accountId: id };
33
+ },
34
+ defaultAccountId: () => "default",
35
+ },
36
+ outbound: {
37
+ deliveryMode: "direct",
38
+ sendText: async ({ to, text }) => {
39
+ // TODO: 实现发送逻辑
40
+ return { channel: "yunzhijia", messageId: `yj_${Date.now()}` };
41
+ },
42
+ sendMedia: async () => {
43
+ throw new Error("媒体消息暂不支持");
44
+ },
45
+ },
46
+ gateway: {
47
+ startAccount: async (ctx) => {
48
+ ctx.log?.info?.(`[${ctx.accountId}] 云之家插件已加载 (框架版本)`);
49
+ // TODO: 实现 Webhook 服务器
50
+ return new Promise((resolve) => {
51
+ ctx.abortSignal?.addEventListener("abort", () => resolve());
52
+ });
53
+ },
54
+ },
55
+ };
56
+ export default function register(api) {
57
+ setYunzhiJiaRuntime(api.runtime);
58
+ api.registerChannel({ plugin: yunzhijiaPlugin });
59
+ }
60
+ //# sourceMappingURL=channel-simple.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-simple.js","sourceRoot":"","sources":["../src/channel-simple.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,yBAAyB;AAGzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,eAAe,GAAkB;IACrC,EAAE,EAAE,WAAW;IACf,IAAI,EAAE;QACJ,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,OAAO;QACd,cAAc,EAAE,iBAAiB;QACjC,QAAQ,EAAE,qBAAqB;QAC/B,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,CAAC,KAAK,CAAC;KACjB;IACD,YAAY,EAAE;QACZ,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC9B,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,KAAK;QACZ,KAAK,EAAE,KAAK;QACZ,cAAc,EAAE,KAAK;QACrB,cAAc,EAAE,KAAK;KACtB;IACD,MAAM,EAAE,EAAE,cAAc,EAAE,CAAC,oBAAoB,CAAC,EAAE;IAClD,MAAM,EAAE;QACN,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE;YACtB,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC;YACnD,OAAO,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACxD,CAAC;QACD,cAAc,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE;YACjC,MAAM,EAAE,GAAG,SAAS,IAAI,SAAS,CAAC;YAClC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC;YACnD,OAAO,QAAQ,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;QAC7C,CAAC;QACD,gBAAgB,EAAE,GAAG,EAAE,CAAC,SAAS;KAClC;IACD,QAAQ,EAAE;QACR,YAAY,EAAE,QAAQ;QACtB,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;YAC/B,eAAe;YACf,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC;QACjE,CAAC;QACD,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;QAC9B,CAAC;KACF;IACD,OAAO,EAAE;QACP,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC1B,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,GAAG,CAAC,SAAS,mBAAmB,CAAC,CAAC;YACtD,uBAAuB;YACvB,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBACnC,GAAG,CAAC,WAAW,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9D,CAAC,CAAC,CAAC;QACL,CAAC;KACF;CACF,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAsB;IACrD,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACjC,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { type ChannelPlugin } from "openclaw/plugin-sdk";
2
+ export interface YunzhiJiaAccount {
3
+ accountId: string;
4
+ name?: string;
5
+ enabled: boolean;
6
+ appId: string;
7
+ appSecret: string;
8
+ token: string;
9
+ webhookToken?: string;
10
+ encodingAesKey?: string;
11
+ webhookPath?: string;
12
+ webhookPort?: number;
13
+ webhookHost?: string;
14
+ config: {
15
+ dmPolicy?: "pairing" | "allowlist" | "open" | "disabled";
16
+ allowFrom?: string[];
17
+ groupPolicy?: "open" | "allowlist" | "disabled";
18
+ groupAllowFrom?: string[];
19
+ groups?: Record<string, {
20
+ requireMention?: boolean;
21
+ groupPolicy?: "open" | "allowlist";
22
+ }>;
23
+ };
24
+ }
25
+ export interface YunzhiJiaProbe {
26
+ ok: boolean;
27
+ appInfo?: {
28
+ name?: string;
29
+ id?: string;
30
+ };
31
+ error?: string;
32
+ }
33
+ export declare const yunzhijiaPlugin: ChannelPlugin;
34
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAWL,KAAK,aAAa,EAEnB,MAAM,qBAAqB,CAAC;AAW7B,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE;QACN,QAAQ,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;QACzD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;QAChD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,cAAc,CAAC,EAAE,OAAO,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;SAAE,CAAC,CAAC;KAC3F,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,EAAE,CAAC,EAAE,MAAM,CAAC;KACb,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA+DD,eAAO,MAAM,eAAe,EAAE,aAgX7B,CAAC"}