@zzedbot/yunzhijia 1.0.12 → 1.0.13

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.

Potentially problematic release.


This version of @zzedbot/yunzhijia might be problematic. Click here for more details.

package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@zzedbot/yunzhijia",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "description": "YunzhiJia channel plugin for OpenClaw",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
5
+ "main": "src/index.ts",
6
+ "types": "src/index.ts",
7
7
  "scripts": {
8
8
  "build": "tsc",
9
9
  "test": "echo \"Error: no test specified\" && exit 1"
package/dist/channel.d.ts DELETED
@@ -1,45 +0,0 @@
1
- interface YunzhijiaConfig {
2
- appSecret: string;
3
- webhookUrl: string;
4
- receiveEndpoint: string;
5
- }
6
- export declare class YunzhijiaChannel {
7
- private app;
8
- private config;
9
- private sessions;
10
- constructor(config: YunzhijiaConfig);
11
- private setupRoutes;
12
- /**
13
- * 验证云之家请求的签名
14
- */
15
- private verifySignature;
16
- /**
17
- * 处理来自云之家的传入消息
18
- */
19
- private handleIncomingMessage;
20
- /**
21
- * 更新会话状态
22
- */
23
- private updateSession;
24
- /**
25
- * 通过OpenClaw网关处理消息
26
- */
27
- private processWithOpenClaw;
28
- /**
29
- * 模拟OpenClaw处理(实际实现中应替换为真实的API调用)
30
- */
31
- private simulateOpenClawProcessing;
32
- /**
33
- * 发送消息到云之家(通过Webhook)
34
- */
35
- sendMessageToYunzhijia(content: string, sessionId?: string): Promise<boolean>;
36
- /**
37
- * 启动服务器
38
- */
39
- start(port?: number): Promise<void>;
40
- /**
41
- * 开始会话清理任务
42
- */
43
- private startSessionCleanup;
44
- }
45
- export {};
package/dist/channel.js DELETED
@@ -1,228 +0,0 @@
1
- import express from 'express';
2
- import crypto from 'crypto';
3
- import axios from 'axios';
4
- export class YunzhijiaChannel {
5
- app;
6
- config;
7
- sessions = new Map();
8
- constructor(config) {
9
- this.config = config;
10
- this.app = express();
11
- // 解析JSON请求体
12
- this.app.use(express.json({
13
- verify: (req, res, buf) => {
14
- // 保存原始请求体以便签名验证
15
- req.rawBody = buf;
16
- }
17
- }));
18
- // 设置路由
19
- this.setupRoutes();
20
- }
21
- setupRoutes() {
22
- // 接收云之家消息的端点
23
- this.app.post(this.config.receiveEndpoint, this.handleIncomingMessage.bind(this));
24
- // 健康检查端点
25
- this.app.get('/health', (req, res) => {
26
- res.status(200).json({ status: 'OK', timestamp: Date.now() });
27
- });
28
- }
29
- /**
30
- * 验证云之家请求的签名
31
- */
32
- verifySignature(req) {
33
- const signature = req.headers['sign'];
34
- const sessionId = req.headers['sessionid'];
35
- if (!signature || !sessionId) {
36
- console.error('Missing signature or sessionId');
37
- return false;
38
- }
39
- // 获取原始请求体
40
- const rawBody = req.rawBody.toString();
41
- const message = JSON.parse(rawBody);
42
- // 构建签名字符串
43
- const summaryInfo = [
44
- message.robotId,
45
- message.robotName,
46
- message.operatorOpenid,
47
- message.operatorName,
48
- message.time.toString(),
49
- message.msgId,
50
- message.content
51
- ].join(',');
52
- // 使用HmacSHA1算法计算签名
53
- const hmac = crypto.createHmac('sha1', this.config.appSecret);
54
- hmac.update(summaryInfo);
55
- const expectedSignature = hmac.digest('base64');
56
- // 验证签名
57
- const isValid = crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature));
58
- if (!isValid) {
59
- console.error('Invalid signature:', {
60
- received: signature,
61
- expected: expectedSignature,
62
- summaryInfo
63
- });
64
- }
65
- return isValid;
66
- }
67
- /**
68
- * 处理来自云之家的传入消息
69
- */
70
- async handleIncomingMessage(req, res) {
71
- try {
72
- // 验证签名
73
- if (!this.verifySignature(req)) {
74
- res.status(401).json({ error: 'Invalid signature' });
75
- return;
76
- }
77
- const message = req.body;
78
- const sessionId = req.headers['sessionid'];
79
- console.log(`Received message from user ${message.operatorName} (${message.operatorOpenid}): ${message.content}`);
80
- // 更新或创建会话
81
- await this.updateSession(sessionId, message);
82
- // 调用OpenClaw网关处理消息
83
- const responseContent = await this.processWithOpenClaw(message, sessionId);
84
- // 发送响应给云之家
85
- const response = {
86
- success: true,
87
- data: {
88
- type: 2,
89
- content: responseContent
90
- }
91
- };
92
- res.json(response);
93
- }
94
- catch (error) {
95
- console.error('Error handling incoming message:', error);
96
- res.status(500).json({
97
- success: false,
98
- error: 'Internal server error'
99
- });
100
- }
101
- }
102
- /**
103
- * 更新会话状态
104
- */
105
- async updateSession(sessionId, message) {
106
- let session = this.sessions.get(sessionId);
107
- if (!session) {
108
- session = {
109
- id: sessionId,
110
- userId: message.operatorOpenid,
111
- lastActive: Date.now(),
112
- context: []
113
- };
114
- }
115
- // 更新最后活动时间
116
- session.lastActive = Date.now();
117
- // 保存消息到上下文(保留最近的10条消息)
118
- session.context.push({
119
- user: message.operatorName,
120
- content: message.content,
121
- timestamp: message.time
122
- });
123
- if (session.context.length > 10) {
124
- session.context.shift(); // 移除最旧的消息
125
- }
126
- this.sessions.set(sessionId, session);
127
- }
128
- /**
129
- * 通过OpenClaw网关处理消息
130
- */
131
- async processWithOpenClaw(message, sessionId) {
132
- try {
133
- // 这里应该调用OpenClaw的API或WebSocket接口
134
- // 由于我们不知道OpenClaw的内部API,这里模拟处理
135
- console.log(`Processing message with OpenClaw: ${message.content}`);
136
- // 模拟OpenClaw处理
137
- // 在实际实现中,这里应该通过某种方式与OpenClaw网关通信
138
- const processedContent = await this.simulateOpenClawProcessing(message.content);
139
- return processedContent;
140
- }
141
- catch (error) {
142
- console.error('Error processing with OpenClaw:', error);
143
- return '抱歉,处理您的消息时出现错误。';
144
- }
145
- }
146
- /**
147
- * 模拟OpenClaw处理(实际实现中应替换为真实的API调用)
148
- */
149
- async simulateOpenClawProcessing(content) {
150
- // 这里应该是与OpenClaw网关的真实交互
151
- // 为了演示,我们简单返回一个处理过的消息
152
- // 模拟延迟
153
- await new Promise(resolve => setTimeout(resolve, 500));
154
- // 简单的消息处理逻辑
155
- if (content.toLowerCase().includes('hello') || content.toLowerCase().includes('你好')) {
156
- return '您好!我是云之家机器人,很高兴为您服务。';
157
- }
158
- else if (content.toLowerCase().includes('help') || content.toLowerCase().includes('帮助')) {
159
- return '我可以帮您回答问题、提供信息或执行任务。请告诉我您需要什么帮助。';
160
- }
161
- else {
162
- return `我已收到您的消息:“${content}”。这是OpenClaw机器人的自动回复。`;
163
- }
164
- }
165
- /**
166
- * 发送消息到云之家(通过Webhook)
167
- */
168
- async sendMessageToYunzhijia(content, sessionId) {
169
- try {
170
- const response = {
171
- success: true,
172
- data: {
173
- type: 2,
174
- content: content
175
- }
176
- };
177
- // 在实际实现中,这里应该调用云之家的Webhook API
178
- // 根据提供的URL模板构建请求
179
- const webhookUrl = `https://www.yunzhijia.com/gateway/robot/webhook/send?yzjtype=12&yzjtoken=eb2ce932214c48b2a604cc7d4d6034b2`;
180
- console.log(`Sending message to Yunzhijia via webhook: ${content}`);
181
- // 发送请求到云之家Webhook
182
- const result = await axios.post(webhookUrl, response.data, {
183
- headers: {
184
- 'Content-Type': 'application/json',
185
- },
186
- timeout: 3000 // 3秒超时
187
- });
188
- return result.status === 200;
189
- }
190
- catch (error) {
191
- console.error('Error sending message to Yunzhijia:', error);
192
- return false;
193
- }
194
- }
195
- /**
196
- * 启动服务器
197
- */
198
- async start(port = 3000) {
199
- return new Promise((resolve) => {
200
- const server = this.app.listen(port, () => {
201
- console.log(`Yunzhijia Channel server running on port ${port}`);
202
- console.log(`Receive endpoint: http://localhost:${port}${this.config.receiveEndpoint}`);
203
- resolve();
204
- });
205
- // 处理会话清理的定时任务
206
- this.startSessionCleanup();
207
- });
208
- }
209
- /**
210
- * 开始会话清理任务
211
- */
212
- startSessionCleanup() {
213
- // 每10分钟清理一次过期会话(超过30分钟无活动)
214
- setInterval(() => {
215
- const now = Date.now();
216
- const expiredSessions = [];
217
- for (const [sessionId, session] of this.sessions) {
218
- if (now - session.lastActive > 30 * 60 * 1000) { // 30分钟
219
- expiredSessions.push(sessionId);
220
- }
221
- }
222
- for (const sessionId of expiredSessions) {
223
- this.sessions.delete(sessionId);
224
- console.log(`Expired session removed: ${sessionId}`);
225
- }
226
- }, 10 * 60 * 1000); // 10分钟
227
- }
228
- }
package/dist/config.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export declare const YunzhiJiaConfigSchema: any;
2
- export declare const yunzhijiaConfigSchema: any;
3
- export declare const DEFAULT_ACCOUNT_ID = "default";
package/dist/config.js DELETED
@@ -1,27 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_ACCOUNT_ID = exports.yunzhijiaConfigSchema = exports.YunzhiJiaConfigSchema = void 0;
4
- const zod_1 = require("zod");
5
- const plugin_sdk_1 = require("openclaw/plugin-sdk");
6
- // Define the configuration schema using Zod
7
- const YunzhiJiaAccountConfigSchema = zod_1.z.object({
8
- webhookToken: zod_1.z.string().optional(),
9
- appSecret: zod_1.z.string().optional(),
10
- skipSignatureVerification: zod_1.z.boolean().optional(),
11
- name: zod_1.z.string().optional(),
12
- enabled: zod_1.z.boolean().optional(),
13
- requireMention: zod_1.z.boolean().optional(),
14
- allowFrom: zod_1.z.array(zod_1.z.union([zod_1.z.string(), zod_1.z.number()])).optional(),
15
- });
16
- exports.YunzhiJiaConfigSchema = zod_1.z.object({
17
- webhookToken: zod_1.z.string().optional(),
18
- appSecret: zod_1.z.string().optional(),
19
- enabled: zod_1.z.boolean().optional(),
20
- name: zod_1.z.string().optional(),
21
- requireMention: zod_1.z.boolean().optional(),
22
- allowFrom: zod_1.z.array(zod_1.z.union([zod_1.z.string(), zod_1.z.number()])).optional(),
23
- accounts: zod_1.z.record(YunzhiJiaAccountConfigSchema).optional(),
24
- });
25
- // Export the channel config schema in OpenClaw format
26
- exports.yunzhijiaConfigSchema = (0, plugin_sdk_1.buildChannelConfigSchema)(exports.YunzhiJiaConfigSchema);
27
- exports.DEFAULT_ACCOUNT_ID = "default";
package/dist/http.d.ts DELETED
@@ -1,6 +0,0 @@
1
- import { type IncomingMessage, type ServerResponse } from "node:http";
2
- import type { YunzhiJiaConfig } from "./types.js";
3
- /**
4
- * Handle incoming YunzhiJia webhook requests
5
- */
6
- export declare function handleYunzhiJiaWebhook(req: IncomingMessage, res: ServerResponse, config: YunzhiJiaConfig): Promise<void>;
package/dist/http.js DELETED
@@ -1,214 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleYunzhiJiaWebhook = handleYunzhiJiaWebhook;
4
- const node_buffer_1 = require("node:buffer");
5
- const plugin_sdk_1 = require("openclaw/plugin-sdk");
6
- const utils_js_1 = require("./utils.js");
7
- const runtime_js_1 = require("./runtime.js");
8
- const meta = (0, plugin_sdk_1.getChatChannelMeta)("yunzhijia");
9
- /**
10
- * Handle incoming YunzhiJia webhook requests
11
- */
12
- async function handleYunzhiJiaWebhook(req, res, config) {
13
- try {
14
- // Read request body
15
- const buffers = [];
16
- for await (const chunk of req) {
17
- buffers.push(chunk);
18
- }
19
- const body = node_buffer_1.Buffer.concat(buffers).toString("utf-8");
20
- // Parse JSON payload
21
- let payload;
22
- try {
23
- payload = JSON.parse(body);
24
- }
25
- catch (error) {
26
- console.error("Invalid JSON payload:", error);
27
- res.writeHead(400, { "Content-Type": "application/json" });
28
- res.end(JSON.stringify({ error: "Invalid JSON" }));
29
- return;
30
- }
31
- // Get account configuration (use default account for now)
32
- const accountId = "default";
33
- const accountConfig = config.accounts?.[accountId] ?? {
34
- webhookToken: config.webhookToken,
35
- appSecret: config.appSecret,
36
- enabled: config.enabled,
37
- name: config.name,
38
- requireMention: config.requireMention ?? true,
39
- };
40
- // Verify signature based on skipSignatureVerification config
41
- const signature = req.headers["sign"];
42
- const skipSignatureVerification = accountConfig.skipSignatureVerification === true;
43
- if (!skipSignatureVerification && accountConfig.appSecret && signature) {
44
- // Note: Cloud之家 uses HmacSHA1 + Base64, but current implementation uses SHA256 + hex
45
- // Need to verify actual algorithm used by YunzhiJia
46
- if (!(0, utils_js_1.verifySignature)(body, signature, accountConfig.appSecret)) {
47
- console.error("Invalid signature");
48
- res.writeHead(401, { "Content-Type": "application/json" });
49
- res.end(JSON.stringify({ error: "Invalid signature" }));
50
- return;
51
- }
52
- }
53
- // Log when signature verification is skipped
54
- if (skipSignatureVerification) {
55
- console.warn("YunzhiJia signature verification skipped (skipSignatureVerification=true)");
56
- }
57
- // Extract user info
58
- const { userId, userName, messageId, content } = (0, utils_js_1.extractUserInfo)(payload);
59
- // Get session ID from header
60
- const sessionId = req.headers["sessionid"];
61
- // Immediately respond to meet YunzhiJia's 3-second requirement
62
- res.writeHead(200, { "Content-Type": "application/json" });
63
- res.end(JSON.stringify({ success: true, data: { type: 2, content: "" } }));
64
- // Process message asynchronously using OpenClaw Runtime
65
- try {
66
- await processIncomingMessageAsync({
67
- payload,
68
- sessionId,
69
- accountConfig,
70
- accountId,
71
- config,
72
- userId,
73
- userName,
74
- messageId,
75
- content,
76
- });
77
- }
78
- catch (error) {
79
- console.error("Async message processing failed:", error);
80
- }
81
- }
82
- catch (error) {
83
- console.error("Error handling YunzhiJia webhook:", error);
84
- if (!res.writableEnded) {
85
- res.writeHead(500, { "Content-Type": "application/json" });
86
- res.end(JSON.stringify({ error: "Internal server error" }));
87
- }
88
- }
89
- }
90
- async function processIncomingMessageAsync(params) {
91
- const { payload, sessionId, accountConfig, accountId, config, userId, userName, messageId, content } = params;
92
- const runtime = (0, runtime_js_1.getYunzhiJiaRuntime)();
93
- // Check mention requirement
94
- const robotName = String(payload.robotName || "");
95
- const requireMention = accountConfig.requireMention !== false;
96
- if (requireMention && !isBotMentioned(content, robotName)) {
97
- console.debug("Message does not mention bot, ignoring");
98
- return;
99
- }
100
- // Extract clean content (remove bot mention if needed)
101
- const cleanContent = extractCleanContent(content, robotName);
102
- // Create session key for conversation tracking
103
- const sessionKey = createSessionKey(sessionId, String(payload.robotId || ""));
104
- // Route to appropriate agent
105
- const route = runtime.channel.routing.resolveAgentRoute({
106
- cfg: config,
107
- channel: "yunzhijia",
108
- accountId,
109
- peer: {
110
- kind: "direct",
111
- id: userId,
112
- },
113
- });
114
- // Create message context
115
- const ctxPayload = {
116
- Body: cleanContent,
117
- RawBody: content,
118
- CommandBody: cleanContent,
119
- From: `yunzhijia:user:${userId}`,
120
- To: `yunzhijia:robot:${payload.robotId}`,
121
- SessionKey: sessionKey,
122
- AccountId: accountId,
123
- ChatType: "direct",
124
- ConversationLabel: userName,
125
- SenderName: userName,
126
- SenderId: userId,
127
- Provider: "yunzhijia",
128
- Surface: "yunzhijia",
129
- MessageSid: messageId,
130
- OriginatingChannel: "yunzhijia",
131
- OriginatingTo: `yunzhijia:robot:${payload.robotId}`,
132
- Timestamp: payload.time,
133
- };
134
- // Record inbound session
135
- const storePath = runtime.channel.session.resolveStorePath(config.session?.store, {
136
- agentId: route.agentId,
137
- });
138
- await runtime.channel.session.recordInboundSession({
139
- storePath,
140
- sessionKey: ctxPayload.SessionKey ?? sessionKey,
141
- ctx: ctxPayload,
142
- onRecordError: (err) => {
143
- console.error(`Failed updating session meta: ${String(err)}`);
144
- },
145
- });
146
- // Dispatch to agent for processing
147
- const prefixOptions = createReplyPrefixOptions({
148
- cfg: config,
149
- agentId: route.agentId,
150
- channel: "yunzhijia",
151
- accountId,
152
- });
153
- // Fire-and-forget processing
154
- void runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
155
- ctx: ctxPayload,
156
- cfg: config,
157
- dispatcherOptions: {
158
- ...prefixOptions,
159
- deliver: async (payload) => {
160
- if (!payload.text) {
161
- return;
162
- }
163
- await sendWebhookMessage(payload.text, accountConfig.webhookToken);
164
- },
165
- },
166
- }).catch((err) => {
167
- console.error(`Message processing failed: ${String(err)}`);
168
- });
169
- }
170
- // Helper functions that need to be implemented
171
- function isBotMentioned(content, robotName) {
172
- // Check if content contains @robotName or similar mention pattern
173
- return content.includes(`@${robotName}`) || content.trim().startsWith(robotName);
174
- }
175
- function extractCleanContent(content, robotName) {
176
- // Remove bot mention from content
177
- let clean = content;
178
- if (robotName) {
179
- clean = clean.replace(new RegExp(`@?${robotName}\\s*`, 'g'), '').trim();
180
- }
181
- return clean;
182
- }
183
- function createSessionKey(sessionId, robotId) {
184
- if (sessionId) {
185
- return `yunzhijia:${robotId}:${sessionId}`;
186
- }
187
- return `yunzhijia:${robotId}:${Date.now()}`;
188
- }
189
- async function sendWebhookMessage(content, webhookToken) {
190
- if (!webhookToken) {
191
- throw new Error("webhookToken is required");
192
- }
193
- const webhookUrl = `https://www.yunzhijia.com/gateway/robot/webhook/send?yzjtype=12&yzjtoken=${webhookToken}`;
194
- const message = {
195
- content: content,
196
- };
197
- const response = await fetch(webhookUrl, {
198
- method: 'POST',
199
- headers: {
200
- 'Content-Type': 'application/json',
201
- },
202
- body: JSON.stringify(message),
203
- });
204
- if (!response.ok) {
205
- throw new Error(`HTTP error! status: ${response.status}`);
206
- }
207
- }
208
- function createReplyPrefixOptions(params) {
209
- // Simplified version - in real implementation this would use proper OpenClaw helpers
210
- return {
211
- prefix: "",
212
- onModelSelected: () => { },
213
- };
214
- }
package/dist/index.d.ts DELETED
@@ -1 +0,0 @@
1
- export { yunzhijiaPlugin } from "./plugin.js";
package/dist/index.js DELETED
@@ -1,5 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.yunzhijiaPlugin = void 0;
4
- var plugin_js_1 = require("./plugin.js");
5
- Object.defineProperty(exports, "yunzhijiaPlugin", { enumerable: true, get: function () { return plugin_js_1.yunzhijiaPlugin; } });
@@ -1,3 +0,0 @@
1
- import { type ChannelPlugin } from "openclaw/plugin-sdk";
2
- import type { YunzhiJiaAccountConfig } from "./types.js";
3
- export declare const yunzhijiaPlugin: ChannelPlugin<YunzhiJiaAccountConfig>;
@@ -1,106 +0,0 @@
1
- import { buildChannelConfigSchema, DEFAULT_ACCOUNT_ID, } from "openclaw/plugin-sdk";
2
- import { getAccountConfig, isAccountConfigured, listAccountIds } from "./config.js";
3
- // Fixed plugin without getChatChannelMeta dependency
4
- const yunzhijiaMessageActions = {
5
- listActions: () => ["send"],
6
- extractToolSend: () => null,
7
- handleAction: async ({ action, params, accountId, cfg }) => {
8
- if (action === "send") {
9
- const account = getAccountConfig(cfg, accountId ?? DEFAULT_ACCOUNT_ID);
10
- if (!account) {
11
- throw new Error(`YunzhiJia account not found: ${accountId}`);
12
- }
13
- const { sendWebhookMessage } = await import("./webhook.js");
14
- const content = typeof params.message === "string" ? params.message : "";
15
- const result = await sendWebhookMessage(content, account.webhookToken);
16
- return { success: result.success };
17
- }
18
- throw new Error(`Action ${action} not supported for YunzhiJia`);
19
- },
20
- };
21
- export const yunzhijiaPlugin = {
22
- id: "yunzhijia",
23
- meta: {
24
- id: "yunzhijia",
25
- label: "YunzhiJia",
26
- selectionLabel: "YunzhiJia (Kingdee)",
27
- docsPath: "/channels/yunzhijia",
28
- blurb: "Kingdee YunzhiJia enterprise messaging integration",
29
- aliases: ["kingdee", "yzj"],
30
- },
31
- capabilities: {
32
- chatTypes: ["direct", "group"],
33
- media: false,
34
- },
35
- configSchema: buildChannelConfigSchema({
36
- type: "object",
37
- properties: {
38
- appSecret: { type: "string" },
39
- webhookToken: { type: "string" },
40
- allowFrom: { type: "array", items: { type: "string" } },
41
- requireMention: { type: "boolean" },
42
- responsePrefix: { type: "string" },
43
- },
44
- required: ["appSecret", "webhookToken"],
45
- }),
46
- config: {
47
- listAccountIds: (cfg) => listAccountIds(cfg),
48
- resolveAccount: (cfg, accountId) => getAccountConfig(cfg, accountId ?? DEFAULT_ACCOUNT_ID) ?? {
49
- appSecret: "",
50
- webhookToken: "",
51
- },
52
- defaultAccountId: () => DEFAULT_ACCOUNT_ID,
53
- isConfigured: (account) => isAccountConfigured(account),
54
- describeAccount: (account) => ({
55
- accountId: DEFAULT_ACCOUNT_ID,
56
- enabled: account?.enabled !== false,
57
- configured: isAccountConfigured(account),
58
- }),
59
- },
60
- security: {
61
- resolveDmPolicy: ({ account }) => ({
62
- policy: account.requireMention !== false ? "pairing" : "open",
63
- allowFrom: account.allowFrom ?? [],
64
- allowFromPath: "channels.yunzhijia.allowFrom",
65
- normalizeEntry: (raw) => raw.replace(/^(yunzhijia|yzj):/i, ""),
66
- }),
67
- },
68
- mentions: {
69
- stripPatterns: ({ ctx }) => {
70
- const robotName = ctx.To?.replace(/^yunzhijia:robot:/, "") || "";
71
- return [`@${robotName}`];
72
- },
73
- },
74
- actions: yunzhijiaMessageActions,
75
- outbound: {
76
- deliveryMode: "direct",
77
- textChunkLimit: 2000,
78
- sendText: async ({ to, text, accountId, cfg }) => {
79
- const account = getAccountConfig(cfg, accountId ?? DEFAULT_ACCOUNT_ID);
80
- if (!account) {
81
- throw new Error(`YunzhiJia account not found: ${accountId}`);
82
- }
83
- const { sendWebhookMessage } = await import("./webhook.js");
84
- const result = await sendWebhookMessage(text, account.webhookToken);
85
- return {
86
- channel: "yunzhijia",
87
- messageId: result.messageId,
88
- timestamp: Date.now(),
89
- to,
90
- };
91
- },
92
- sendMedia: async ({ to, text, mediaUrl, accountId, cfg }) => {
93
- const combinedText = mediaUrl ? `${text || ""} ${mediaUrl}`.trim() : text;
94
- return await yunzhijiaPlugin.outbound.sendText({
95
- to,
96
- text: combinedText,
97
- accountId,
98
- cfg,
99
- });
100
- },
101
- },
102
- gateway: {
103
- startAccount: async () => { },
104
- stopAccount: async () => { },
105
- },
106
- };
@@ -1,2 +0,0 @@
1
- import type { ChannelPlugin } from "openclaw/plugin-sdk";
2
- export declare const yunzhijiaPlugin: ChannelPlugin;