foliko 1.1.21 → 1.1.22
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/.agent/data/web/web-config.json +8 -1
- package/.agent/sessions/cli_default.json +384 -0
- package/.agent/sessions/default.json +822 -0
- package/.claude/settings.local.json +6 -1
- package/cli/src/commands/chat.js +1 -1
- package/cli/src/ui/chat-ui.js +15 -9
- package/examples/test-chat.js +7 -1
- package/package.json +1 -1
- package/plugins/telegram-plugin.js +8 -0
- package/plugins/weixin-plugin.js +1 -3
- package/src/core/agent-chat.js +13 -31
- package/src/utils/chat-queue.js +16 -25
- package/src/utils/logger.js +6 -3
- package/nul +0 -3
- package/undefined.svg +0 -8
- package/weixin-bot-poster-v2.png +0 -0
- package/weixin-bot-poster.png +0 -0
|
@@ -204,7 +204,12 @@
|
|
|
204
204
|
"Bash(node -e \"require\\('./src/core/agent-chat.js'\\); console.log\\('OK'\\)\" 2>&1)",
|
|
205
205
|
"Bash(node -e \"const ai = require\\('ai'\\); console.log\\('tool type:', typeof ai.tool\\)\")",
|
|
206
206
|
"Bash(taskkill //PID 26152 //F)",
|
|
207
|
-
"Bash(netstat -ano | grep 3000)"
|
|
207
|
+
"Bash(netstat -ano | grep 3000)",
|
|
208
|
+
"Bash(node test-error.js 2>&1)",
|
|
209
|
+
"Bash(node -c src/core/agent-chat.js && node -c src/utils/chat-queue.js && node -c cli/src/ui/chat-ui.js && node -c plugins/weixin-plugin.js && node -c plugins/telegram-plugin.js)",
|
|
210
|
+
"Bash(node -c plugins/weixin-plugin.js && node -c plugins/telegram-plugin.js && node -c cli/src/ui/chat-ui.js)",
|
|
211
|
+
"Bash(node -c src/utils/chat-queue.js)",
|
|
212
|
+
"Bash(node -c src/utils/logger.js)"
|
|
208
213
|
]
|
|
209
214
|
}
|
|
210
215
|
}
|
package/cli/src/commands/chat.js
CHANGED
|
@@ -126,7 +126,7 @@ async function runContinuousTest(agent, options) {
|
|
|
126
126
|
} else if (chunk.type === 'tool-call') {
|
|
127
127
|
console.log(`\n[工具调用] ${chunk.toolName} ${JSON.stringify(chunk.input)}`);
|
|
128
128
|
} else if (chunk.type === 'error') {
|
|
129
|
-
console.error(`\n[错误] ${chunk.error}`);
|
|
129
|
+
//console.error(`\n[错误] ${chunk.error}`);
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
console.log('\n' + '-'.repeat(50));
|
package/cli/src/ui/chat-ui.js
CHANGED
|
@@ -136,6 +136,8 @@ class ChatUI {
|
|
|
136
136
|
|
|
137
137
|
process.on('SIGINT', interruptHandler);
|
|
138
138
|
|
|
139
|
+
let hasError = false;
|
|
140
|
+
|
|
139
141
|
try {
|
|
140
142
|
const renderState = { inThink: false, inCodeBlock: false };
|
|
141
143
|
const { sessionId } = this;
|
|
@@ -150,7 +152,6 @@ class ChatUI {
|
|
|
150
152
|
// 创建 session scope 过滤事件
|
|
151
153
|
const sessionScope = this.agent.createSessionScope(sessionId);
|
|
152
154
|
|
|
153
|
-
// 监听流式数据
|
|
154
155
|
sessionScope.on('stream:chunk', ({ chunk }) => {
|
|
155
156
|
if (interrupted) return;
|
|
156
157
|
|
|
@@ -167,11 +168,15 @@ class ChatUI {
|
|
|
167
168
|
console.log(renderLine(line, renderState));
|
|
168
169
|
}
|
|
169
170
|
}
|
|
170
|
-
} else if (chunk.type === 'error') {
|
|
171
|
-
console.error(`\n${colored('[错误]', RED)} ${chunk.error}`);
|
|
172
171
|
}
|
|
173
172
|
});
|
|
174
173
|
|
|
174
|
+
// 监听 queue:failed 事件(处理队列级别的最终错误)
|
|
175
|
+
sessionScope.on('queue:failed', ({ error }) => {
|
|
176
|
+
hasError = true;
|
|
177
|
+
console.error(`\n${colored('[错误]', RED)} ${error}`);
|
|
178
|
+
});
|
|
179
|
+
|
|
175
180
|
// 调用 sendMessage 触发事件
|
|
176
181
|
const res = await this.agent.sendMessage(message, { sessionId });
|
|
177
182
|
// 清理
|
|
@@ -199,13 +204,14 @@ class ChatUI {
|
|
|
199
204
|
}
|
|
200
205
|
} catch (err) {
|
|
201
206
|
// 只打印简洁错误消息,不打印堆栈
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
+
// 避免与 message:error 事件重复打印
|
|
208
|
+
if (!hasError && !interrupted) {
|
|
209
|
+
const errName = err?.name || '';
|
|
210
|
+
const isRetryError = errName === 'AI_RetryError' || errName === 'RetryError';
|
|
211
|
+
const friendlyMessage = isRetryError
|
|
212
|
+
? 'AI 服务暂时不可用,请稍后重试'
|
|
213
|
+
: (err.message || '未知错误').split('\n')[0];
|
|
207
214
|
|
|
208
|
-
if (!interrupted) {
|
|
209
215
|
console.error(`\n${colored('[错误]', RED)} ${friendlyMessage}\n`);
|
|
210
216
|
}
|
|
211
217
|
} finally {
|
package/examples/test-chat.js
CHANGED
|
@@ -89,7 +89,9 @@ async function main() {
|
|
|
89
89
|
} else if (chunk.type === 'tool-result') {
|
|
90
90
|
console.log('\n[工具结果]', JSON.stringify(chunk.result).substring(0, 100));
|
|
91
91
|
} else if (chunk.type === 'error') {
|
|
92
|
-
|
|
92
|
+
throw new Error('sdfsdf');
|
|
93
|
+
|
|
94
|
+
//console.error('\n[错误]', chunk.error);
|
|
93
95
|
}
|
|
94
96
|
}
|
|
95
97
|
|
|
@@ -110,6 +112,10 @@ async function main() {
|
|
|
110
112
|
'请帮我注册一个 GET 路由:\n- 路径:/test\n- 处理函数:return "1232432"\n\n注册完成后,用 web_request 工具测试访问这个路由,确认返回 "1232432"'
|
|
111
113
|
);
|
|
112
114
|
|
|
115
|
+
await ask(
|
|
116
|
+
'关闭服务'
|
|
117
|
+
);
|
|
118
|
+
|
|
113
119
|
console.log('\n--- 测试完成,现在你可以继续对话 ---\n');
|
|
114
120
|
|
|
115
121
|
// 主循环
|
package/package.json
CHANGED
|
@@ -329,6 +329,14 @@ class TelegramPlugin extends Plugin {
|
|
|
329
329
|
}
|
|
330
330
|
})
|
|
331
331
|
|
|
332
|
+
// 监听错误事件
|
|
333
|
+
sessionScope.on('queue:failed', async ({ error }) => {
|
|
334
|
+
await this._bot.editMessageText(escapeMarkdown(`❌ ${error}`), {
|
|
335
|
+
chat_id: chatId,
|
|
336
|
+
message_id: thinkingMsg.message_id
|
|
337
|
+
})
|
|
338
|
+
})
|
|
339
|
+
|
|
332
340
|
await agent.sendMessage(text, { sessionId })
|
|
333
341
|
|
|
334
342
|
sessionScope.removeAllListeners()
|
package/plugins/weixin-plugin.js
CHANGED
|
@@ -537,8 +537,6 @@ class WeixinPlugin extends Plugin {
|
|
|
537
537
|
message+=colored(`[工具开始](${chunk.toolName})`,YELLOW)
|
|
538
538
|
}else if(chunk.type==='tool-result'){
|
|
539
539
|
message+=colored(`[工具结束](${chunk.toolName})`,YELLOW)
|
|
540
|
-
}else if(chunk.type==='error'){
|
|
541
|
-
message+=colored(`[错误](${chunk.error})`,RED)
|
|
542
540
|
}
|
|
543
541
|
while (message.includes('\n')) {
|
|
544
542
|
const nlIndex = message.indexOf('\n');
|
|
@@ -564,7 +562,7 @@ class WeixinPlugin extends Plugin {
|
|
|
564
562
|
lineBuffer = ''
|
|
565
563
|
message=''
|
|
566
564
|
})
|
|
567
|
-
sessionScope.on('
|
|
565
|
+
sessionScope.on('queue:failed', async ({error}) => {
|
|
568
566
|
this.stopTypingInterval()
|
|
569
567
|
await this._sendMessageBatch(originalMsg, userId, error, true)
|
|
570
568
|
lineBuffer = ''
|
package/src/core/agent-chat.js
CHANGED
|
@@ -56,7 +56,7 @@ class AgentChatHandler extends EventEmitter {
|
|
|
56
56
|
agent,
|
|
57
57
|
maxConcurrent: config.maxConcurrent || 1,
|
|
58
58
|
retryAttempts: config.retryAttempts || 3,
|
|
59
|
-
retryDelay: config.retryDelay ||
|
|
59
|
+
retryDelay: config.retryDelay || 10000,
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
// ToolExecutor: 工具管理
|
|
@@ -438,8 +438,13 @@ class AgentChatHandler extends EventEmitter {
|
|
|
438
438
|
prepareStep: this._createPrepareStep(),
|
|
439
439
|
});
|
|
440
440
|
|
|
441
|
+
// AI SDK 错误回调:仅记录日志,不在这里处理(统一由 catch/yield 处理)
|
|
442
|
+
const handleSDKError = ({ error }) => {
|
|
443
|
+
logger.debug(`[AgentChat] SDK onError: ${error?.message}`);
|
|
444
|
+
};
|
|
445
|
+
|
|
441
446
|
const result = await framework.runInSession(sessionId, {}, async () => {
|
|
442
|
-
return agent.stream({ messages, ...this.providerOptions });
|
|
447
|
+
return agent.stream({ messages, ...this.providerOptions, onError: handleSDKError });
|
|
443
448
|
});
|
|
444
449
|
|
|
445
450
|
const stream = result.fullStream;
|
|
@@ -458,7 +463,9 @@ class AgentChatHandler extends EventEmitter {
|
|
|
458
463
|
} else if (part.type === 'tool-result') {
|
|
459
464
|
yield { type: 'tool-result', toolName: part.toolName, result: part.output };
|
|
460
465
|
} else if (part.type === 'error') {
|
|
461
|
-
|
|
466
|
+
// 统一错误消息
|
|
467
|
+
const errMsg = part.error?.message || 'AI 服务错误';
|
|
468
|
+
yield { type: 'error', error: errMsg.split('\n')[0] };
|
|
462
469
|
}
|
|
463
470
|
}
|
|
464
471
|
|
|
@@ -472,35 +479,10 @@ class AgentChatHandler extends EventEmitter {
|
|
|
472
479
|
const userMsg = messages[messages.length - finishMessages.length - 1];
|
|
473
480
|
this.emit('message', { content: fullText, sessionId: sessionId, userMessage: userMsg });
|
|
474
481
|
} catch (err) {
|
|
475
|
-
//
|
|
476
|
-
const
|
|
477
|
-
const errName = err?.name || '';
|
|
478
|
-
|
|
479
|
-
// 使用 AI SDK 的错误类型判断
|
|
480
|
-
const isRetryError =
|
|
481
|
-
RetryError.isInstance?.(err) ||
|
|
482
|
-
errName === 'AI_RetryError' ||
|
|
483
|
-
errName === 'RetryError' ||
|
|
484
|
-
err?.reason === 'maxRetriesExceeded';
|
|
485
|
-
|
|
486
|
-
// AI SDK 的错误 map
|
|
487
|
-
const errorMessages = {
|
|
488
|
-
AI_RetryError: 'AI 服务暂时不可用,请稍后重试',
|
|
489
|
-
AI_APICallError: err?.isRetryable ? 'AI 服务暂时不可用,请稍后重试' : simpleMessage,
|
|
490
|
-
AI_NoContentGeneratedError: 'AI 未生成有效内容,请重试',
|
|
491
|
-
AI_NoOutputGeneratedError: 'AI 未生成有效内容,请重试',
|
|
492
|
-
AI_NoSuchModelError: '指定的 AI 模型不存在',
|
|
493
|
-
AI_NoSuchProviderError: 'AI 提供商配置错误',
|
|
494
|
-
AI_LoadAPIKeyError: 'AI API 密钥配置错误',
|
|
495
|
-
AI_InvalidPromptError: '输入内容格式错误',
|
|
496
|
-
AI_ToolCallRepairError: '工具调用处理失败,请重试',
|
|
497
|
-
};
|
|
498
|
-
|
|
499
|
-
const friendlyMessage =
|
|
500
|
-
errorMessages[errName] || (isRetryError ? 'AI 服务暂时不可用,请稍后重试' : simpleMessage);
|
|
482
|
+
// 统一错误处理:提取简洁消息并通过 yield 传递
|
|
483
|
+
const friendlyMessage = err?.message?.split('\n')[0] || '未知错误';
|
|
501
484
|
|
|
502
|
-
|
|
503
|
-
this.emit('message:error', { sessionId, error: friendlyMessage });
|
|
485
|
+
this.emit('message:error', { sessionId, error: friendlyMessage, originalError: err });
|
|
504
486
|
yield { type: 'error', error: friendlyMessage };
|
|
505
487
|
} finally {
|
|
506
488
|
const messageStore = this._getSessionMessageStore(sessionId);
|
package/src/utils/chat-queue.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const { EventEmitter } = require('./event-emitter');
|
|
2
2
|
const { cleanResponse } = require('./index');
|
|
3
|
+
const { logger } = require('./logger');
|
|
4
|
+
const log = logger.child('ChatQueue');
|
|
3
5
|
// ChatQueueManager.js
|
|
4
6
|
class ChatQueueManager extends EventEmitter {
|
|
5
7
|
constructor(options = {}) {
|
|
@@ -8,8 +10,9 @@ class ChatQueueManager extends EventEmitter {
|
|
|
8
10
|
this.isProcessing = false;
|
|
9
11
|
this.maxConcurrent = options.maxConcurrent || 1;
|
|
10
12
|
this.activeCount = 0;
|
|
11
|
-
this.retryAttempts = options.retryAttempts ||
|
|
13
|
+
this.retryAttempts = options.retryAttempts || 3;
|
|
12
14
|
this.retryDelay = options.retryDelay || 10000;
|
|
15
|
+
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
/**
|
|
@@ -72,13 +75,8 @@ class ChatQueueManager extends EventEmitter {
|
|
|
72
75
|
const result = await this.executeWithRetry(item);
|
|
73
76
|
// 检查 result 是否有错误(而不是通过 try/catch)
|
|
74
77
|
if (result.error) {
|
|
75
|
-
console.log('[ChatQueue] Rejecting with error from result:', result.error.message);
|
|
76
|
-
|
|
77
|
-
this.emit('queue:failed', {
|
|
78
|
-
requestId: item.id,
|
|
79
|
-
sessionId: item.sessionId,
|
|
80
|
-
error: result.error.message,
|
|
81
|
-
});
|
|
78
|
+
//console.log('[ChatQueue] Rejecting with error from result:', result.error.message);
|
|
79
|
+
throw result.error
|
|
82
80
|
} else {
|
|
83
81
|
item.resolve(result);
|
|
84
82
|
this.emit('queue:completed', {
|
|
@@ -88,7 +86,7 @@ class ChatQueueManager extends EventEmitter {
|
|
|
88
86
|
});
|
|
89
87
|
}
|
|
90
88
|
} catch (error) {
|
|
91
|
-
|
|
89
|
+
log.info('[ChatQueue] Rejecting Error:', error.message);
|
|
92
90
|
item.reject(error);
|
|
93
91
|
this.emit('queue:failed', {
|
|
94
92
|
requestId: item.id,
|
|
@@ -119,28 +117,21 @@ class ChatQueueManager extends EventEmitter {
|
|
|
119
117
|
|
|
120
118
|
// 检查是否有错误(通过返回的 result.error)
|
|
121
119
|
if (result.error) {
|
|
122
|
-
console.log(
|
|
123
|
-
'[ChatQueue] executeWithRetry: attempt',
|
|
124
|
-
attempt,
|
|
125
|
-
'got error:',
|
|
126
|
-
result.error.message
|
|
127
|
-
);
|
|
128
120
|
lastError = result.error;
|
|
129
121
|
if (attempt < this.retryAttempts && this.isRetryableError(lastError)) {
|
|
130
122
|
await this.sleep(this.retryDelay * Math.pow(2, attempt - 1));
|
|
131
123
|
continue;
|
|
132
124
|
}
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
return result;
|
|
125
|
+
// 重试耗尽,直接抛出 result.error
|
|
126
|
+
throw lastError;
|
|
136
127
|
}
|
|
137
128
|
|
|
138
129
|
return result;
|
|
139
130
|
} catch (error) {
|
|
140
|
-
|
|
141
|
-
'[ChatQueue] executeWithRetry:
|
|
131
|
+
log.info(
|
|
132
|
+
'[ChatQueue] executeWithRetry: ',
|
|
142
133
|
attempt,
|
|
143
|
-
'
|
|
134
|
+
'error:',
|
|
144
135
|
error.message
|
|
145
136
|
);
|
|
146
137
|
lastError = error;
|
|
@@ -161,7 +152,7 @@ class ChatQueueManager extends EventEmitter {
|
|
|
161
152
|
|
|
162
153
|
const friendlyError = new Error(friendlyMessage);
|
|
163
154
|
friendlyError.originalError = lastError;
|
|
164
|
-
|
|
155
|
+
//log.info('[ChatQueue] executeWithRetry: throwing friendly error:', friendlyMessage);
|
|
165
156
|
throw friendlyError;
|
|
166
157
|
}
|
|
167
158
|
|
|
@@ -196,8 +187,8 @@ class ChatQueueManager extends EventEmitter {
|
|
|
196
187
|
? 'AI 服务暂时不可用,请稍后重试'
|
|
197
188
|
: (err.message || err.toString()).split('\n')[0];
|
|
198
189
|
|
|
199
|
-
|
|
200
|
-
'[ChatQueue] executeStream
|
|
190
|
+
log.info(
|
|
191
|
+
'[ChatQueue] executeStream Error:',
|
|
201
192
|
friendlyMessage
|
|
202
193
|
);
|
|
203
194
|
chunks.push({ type: 'error', error: friendlyMessage });
|
|
@@ -217,7 +208,7 @@ class ChatQueueManager extends EventEmitter {
|
|
|
217
208
|
const error = new Error(errorChunk.error || 'Stream error');
|
|
218
209
|
error.chunks = chunks;
|
|
219
210
|
error.isStreamError = true;
|
|
220
|
-
|
|
211
|
+
log.info('[ChatQueue] executeStream Error:', error.message);
|
|
221
212
|
return {
|
|
222
213
|
chunks,
|
|
223
214
|
content: cleanResponse(''),
|
package/src/utils/logger.js
CHANGED
|
@@ -33,8 +33,9 @@ class Logger {
|
|
|
33
33
|
info: '\x1b[32m', // 绿色
|
|
34
34
|
warn: '\x1b[33m', // 黄色
|
|
35
35
|
error: '\x1b[31m', // 红色
|
|
36
|
+
grey: '\x1b[90m', // 暗灰色
|
|
36
37
|
reset: '\x1b[0m',
|
|
37
|
-
dim: '\x1b[2m', //
|
|
38
|
+
dim: '\x1b[2m', // 暗灰色
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -72,6 +73,7 @@ class Logger {
|
|
|
72
73
|
const color = this.colors[levelName.toLowerCase()] || '';
|
|
73
74
|
const reset = this.colors.reset;
|
|
74
75
|
const dim = this.colors.dim;
|
|
76
|
+
const grey=this.colors.grey;
|
|
75
77
|
|
|
76
78
|
const parts = [];
|
|
77
79
|
|
|
@@ -91,7 +93,8 @@ class Logger {
|
|
|
91
93
|
parts.push(levelName.padEnd(5));
|
|
92
94
|
}
|
|
93
95
|
|
|
94
|
-
//
|
|
96
|
+
// 消息(根据级别着色)
|
|
97
|
+
const msgColor = this.enableColors ? color : '';
|
|
95
98
|
const message = args
|
|
96
99
|
.map((arg) => {
|
|
97
100
|
if (arg instanceof Error) {
|
|
@@ -108,7 +111,7 @@ class Logger {
|
|
|
108
111
|
})
|
|
109
112
|
.join(' ');
|
|
110
113
|
|
|
111
|
-
parts.push(message);
|
|
114
|
+
parts.push(`${grey}${message}${reset}`);
|
|
112
115
|
return parts.join(' ');
|
|
113
116
|
}
|
|
114
117
|
|
package/nul
DELETED
package/undefined.svg
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="802" height="NaN" viewBox="-1,NaN,802,NaN"><defs><linearGradient x1="400" y1="600" x2="1000" y2="600" gradientUnits="userSpaceOnUse" id="color-1"><stop offset="0" stop-color="#f5f0e6"></stop><stop offset="1" stop-color="#ede8dc"></stop></linearGradient></defs><g fill="none" fill-rule="nonzero" stroke="none" stroke-width="none" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M0,1200v-1200h800v1200z" fill="url(#color-1)" stroke="none" stroke-width="1"></path><path d="M0,1200v-1200h800v1200z" fill="none" stroke="#000000" stroke-width="2"></path><path d="M40,1140v-1100h720v1100z" fill-opacity="0" fill="#000000" stroke="none" stroke-width="1"></path><text x="400" y="55" fill="#6b6459" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="14" text-anchor="middle">━━━━━━━━━━━━━━━ VOL.01 ━━━━━━━━━━━━━━━</text><text x="400" y="130" fill="#b85450" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="52" text-anchor="middle">微信 iLink 机器人</text><text x="400" y="195" fill="#6b6459" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="18" text-anchor="middle">零依赖 · 极简接入 · 高效稳定</text><text x="400" y="235" fill="#1a1a1a" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="16" text-anchor="middle">WEIXIN iLINK BOT SDK FOR NODE.JS</text><path d="M100,270h600" fill="none" stroke="#ffffff" stroke-width="2"></path><path d="M100,NaNc0,NaN 0,NaN 0,NaNh290c0,0 0,NaN 0,NaNc0,NaN -290,NaN -290,NaNz" fill="#ffffff" stroke="none" stroke-width="1"></path><text x="110" y="454" fill="#000000" stroke="none" stroke-width="1" font-family="Microsoft YaHei, msyh, PatuaOne-Regular, seguiemj, seguisym, SegUIVar, wryh, Segoe UI Emoji, sans-serif" font-weight="normal" font-size="24" text-anchor="start">[object Object]</text><text x="110" y="480" fill="#666666" stroke="none" stroke-width="1" font-family="Microsoft YaHei, msyh, PatuaOne-Regular, seguiemj, seguisym, SegUIVar, wryh, Segoe UI Emoji, sans-serif" font-weight="normal" font-size="16" text-anchor="start">[object Object]</text><path d="M105,480c-2.76142,0 -5,-2.23858 -5,-5v-50c0,-2.76142 2.23858,-5 5,-5h280c2.76142,0 5,2.23858 5,5v50c0,2.76142 -2.23858,5 -5,5z" fill="#ffffff" stroke="none" stroke-width="1"></path><text x="245" y="435" fill="#b85450" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="20" text-anchor="middle">ZERO DEPENDENCY</text><text x="245" y="460" fill="#6b6459" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="12" text-anchor="middle">零外部依赖 · 轻量安装</text><path d="M415,480c-2.76142,0 -5,-2.23858 -5,-5v-50c0,-2.76142 2.23858,-5 5,-5h280c2.76142,0 5,2.23858 5,5v50c0,2.76142 -2.23858,5 -5,5z" fill="#ffffff" stroke="none" stroke-width="1"></path><text x="555" y="435" fill="#b85450" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="20" text-anchor="middle">QR CODE AUTH</text><text x="555" y="460" fill="#6b6459" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="12" text-anchor="middle">扫码登录 · 安全认证</text><path d="M105,555c-2.76142,0 -5,-2.23858 -5,-5v-50c0,-2.76142 2.23858,-5 5,-5h280c2.76142,0 5,2.23858 5,5v50c0,2.76142 -2.23858,5 -5,5z" fill="#ffffff" stroke="none" stroke-width="1"></path><text x="245" y="510" fill="#b85450" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="20" text-anchor="middle">EVENT DRIVEN</text><text x="245" y="535" fill="#6b6459" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="12" text-anchor="middle">事件驱动 · 高效响应</text><path d="M415,555c-2.76142,0 -5,-2.23858 -5,-5v-50c0,-2.76142 2.23858,-5 5,-5h280c2.76142,0 5,2.23858 5,5v50c0,2.76142 -2.23858,5 -5,5z" fill="#ffffff" stroke="none" stroke-width="1"></path><text x="555" y="510" fill="#b85450" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="20" text-anchor="middle">RICH MEDIA</text><text x="555" y="535" fill="#6b6459" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="12" text-anchor="middle">多媒体消息 · 丰富交互</text><path d="M100,580h600" fill="none" stroke="#ffffff" stroke-width="2"></path><text x="400" y="600" fill="#1a1a1a" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="16" text-anchor="middle">QUICK START</text><path d="M108,830c-4.41828,0 -8,-3.58172 -8,-8v-184c0,-4.41828 3.58172,-8 8,-8h584c4.41828,0 8,3.58172 8,8v184c0,4.41828 -3.58172,8 -8,8z" fill="#2d2d2d" stroke="none" stroke-width="1"></path><text x="120" y="645" fill="#f8f8f2" stroke="none" stroke-width="1" font-family="Consolas, Microsoft YaHei, seguiemj, sans-serif" font-weight="normal" font-size="13" text-anchor="start">import { WeixinBot } from '@chnak/weixin-bot';
|
|
2
|
-
|
|
3
|
-
const bot = new WeixinBot({
|
|
4
|
-
onQRCode: (qr) => console.log(qr),
|
|
5
|
-
onMessage: (msg) => bot.sendText(msg.from, 'Hello!')
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
bot.start();</text><path d="M100,850h600" fill="none" stroke="#ffffff" stroke-width="2"></path><path d="M106,920c-3.31371,0 -6,-2.68629 -6,-6v-38c0,-3.31371 2.68629,-6 6,-6h588c3.31371,0 6,2.68629 6,6v38c0,3.31371 -2.68629,6 -6,6z" fill="#2d2d2d" stroke="none" stroke-width="1"></path><text x="400" y="885" fill="#50fa7b" stroke="none" stroke-width="1" font-family="Consolas, Microsoft YaHei, seguiemj, sans-serif" font-weight="normal" font-size="18" text-anchor="middle">$ npm install @chnak/weixin-bot</text><text x="400" y="950" fill="#6b6459" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="14" text-anchor="middle">v1.2.9 · MIT License · Node.js >= 14.0.0</text><text x="400" y="980" fill="#b85450" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="14" text-anchor="middle">npmjs.com/package/@chnak/weixin-bot</text><text x="400" y="1020" fill="#6b6459" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="14" text-anchor="middle">━━━━━━━━━━━━━━━ ◆ ━━━━━━━━━━━━━━━</text><text x="400" y="1045" fill="#6b6459" stroke="none" stroke-width="1" font-family="Microsoft YaHei, SimHei, KaiTi, seguiemj, sans-serif" font-weight="normal" font-size="12" text-anchor="middle">❖ ❖</text></g></svg>
|
package/weixin-bot-poster-v2.png
DELETED
|
Binary file
|
package/weixin-bot-poster.png
DELETED
|
Binary file
|