evolclaw 2.1.1 → 2.2.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/README.md +10 -3
- package/data/evolclaw.sample.json +9 -1
- package/dist/agents/claude-runner.js +612 -0
- package/dist/agents/codex-runner.js +310 -0
- package/dist/channels/aun.js +416 -9
- package/dist/channels/feishu.js +397 -104
- package/dist/channels/wechat.js +84 -2
- package/dist/cli.js +427 -126
- package/dist/config.js +102 -4
- package/dist/core/adapters/claude-session-file-adapter.js +144 -0
- package/dist/core/adapters/codex-session-file-adapter.js +196 -0
- package/dist/core/agent-loader.js +39 -0
- package/dist/core/channel-loader.js +60 -0
- package/dist/core/command-handler.js +908 -304
- package/dist/core/event-bus.js +32 -0
- package/dist/core/ipc-server.js +71 -0
- package/dist/core/message-bridge.js +187 -0
- package/dist/core/message-processor.js +370 -227
- package/dist/core/message-queue.js +153 -29
- package/dist/core/permission.js +58 -0
- package/dist/core/session-file-adapter.js +7 -0
- package/dist/core/session-manager.js +571 -223
- package/dist/core/stats-collector.js +86 -0
- package/dist/index.js +309 -243
- package/dist/paths.js +1 -0
- package/dist/utils/error-utils.js +4 -2
- package/dist/utils/init-feishu.js +2 -0
- package/dist/utils/init-wechat.js +2 -0
- package/dist/utils/init.js +285 -53
- package/dist/utils/ipc-client.js +36 -0
- package/dist/utils/migrate-project.js +122 -0
- package/dist/utils/{permission.js → permission-utils.js} +31 -3
- package/dist/utils/rich-content-renderer.js +228 -0
- package/dist/utils/session-file-health.js +11 -34
- package/dist/utils/stream-debouncer.js +122 -0
- package/dist/utils/stream-idle-monitor.js +1 -1
- package/package.json +3 -1
- package/dist/core/agent-runner.js +0 -348
- package/dist/core/message-stream.js +0 -59
- package/dist/index.js.bak +0 -340
- package/dist/utils/markdown-to-feishu.js +0 -94
- /package/dist/utils/{platform.js → cross-platform.js} +0 -0
- /package/dist/{core → utils}/message-cache.js +0 -0
package/dist/channels/wechat.js
CHANGED
|
@@ -132,6 +132,7 @@ export class WechatChannel {
|
|
|
132
132
|
config;
|
|
133
133
|
messageHandler;
|
|
134
134
|
abortController;
|
|
135
|
+
connected = false;
|
|
135
136
|
// 内部状态(不外泄到核心层)
|
|
136
137
|
contextTokenCache = new Map();
|
|
137
138
|
typingTicketCache = new Map();
|
|
@@ -181,16 +182,34 @@ export class WechatChannel {
|
|
|
181
182
|
if (this.abortController?.signal.aborted)
|
|
182
183
|
return;
|
|
183
184
|
logger.error('[WeChat] Poll loop fatal error:', err);
|
|
185
|
+
this.connected = false;
|
|
184
186
|
});
|
|
187
|
+
this.connected = true;
|
|
185
188
|
logger.info('[WeChat] Channel connected');
|
|
186
189
|
}
|
|
187
190
|
async disconnect() {
|
|
191
|
+
this.connected = false;
|
|
188
192
|
if (this.abortController) {
|
|
189
193
|
this.abortController.abort();
|
|
190
194
|
this.abortController = undefined;
|
|
191
195
|
}
|
|
192
196
|
logger.info('[WeChat] Channel disconnected');
|
|
193
197
|
}
|
|
198
|
+
/** Get current connection status */
|
|
199
|
+
getStatus() {
|
|
200
|
+
return { connected: this.connected };
|
|
201
|
+
}
|
|
202
|
+
/** Reconnect: disconnect then connect again */
|
|
203
|
+
async reconnect() {
|
|
204
|
+
await this.disconnect();
|
|
205
|
+
try {
|
|
206
|
+
await this.connect();
|
|
207
|
+
return '重连成功';
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
return `重连失败: ${err instanceof Error ? err.message : String(err)}`;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
194
213
|
async sendMessage(to, text) {
|
|
195
214
|
if (!text || text.trim() === '') {
|
|
196
215
|
logger.warn('[WeChat] Attempted to send empty message, skipping');
|
|
@@ -447,7 +466,7 @@ export class WechatChannel {
|
|
|
447
466
|
// 回调主流程
|
|
448
467
|
if (this.messageHandler) {
|
|
449
468
|
try {
|
|
450
|
-
await this.messageHandler(fromUserId, finalContent || '', fromUserId, media.images.length ? media.images : undefined);
|
|
469
|
+
await this.messageHandler(fromUserId, finalContent || '', fromUserId, media.images.length ? media.images : undefined, 'private');
|
|
451
470
|
}
|
|
452
471
|
catch (err) {
|
|
453
472
|
logger.error('[WeChat] Message handler error:', err);
|
|
@@ -529,7 +548,7 @@ export class WechatChannel {
|
|
|
529
548
|
const projectPath = this.projectPathResolver
|
|
530
549
|
? await this.projectPathResolver(channelId)
|
|
531
550
|
: process.cwd();
|
|
532
|
-
const uploadsDir = path.join(projectPath, '.
|
|
551
|
+
const uploadsDir = path.join(projectPath, '.evolclaw', 'uploads');
|
|
533
552
|
fs.mkdirSync(uploadsDir, { recursive: true });
|
|
534
553
|
const savePath = path.join(uploadsDir, fileName);
|
|
535
554
|
fs.writeFileSync(savePath, buf);
|
|
@@ -682,3 +701,66 @@ export class WechatChannel {
|
|
|
682
701
|
});
|
|
683
702
|
}
|
|
684
703
|
}
|
|
704
|
+
export class WechatChannelPlugin {
|
|
705
|
+
name = 'wechat';
|
|
706
|
+
isEnabled(config) {
|
|
707
|
+
return config.channels?.wechat?.enabled === true && !!config.channels?.wechat?.token;
|
|
708
|
+
}
|
|
709
|
+
async createChannel(config) {
|
|
710
|
+
const wechatConfig = config.channels?.wechat;
|
|
711
|
+
if (!wechatConfig?.token) {
|
|
712
|
+
throw new Error('WeChat config missing');
|
|
713
|
+
}
|
|
714
|
+
const channel = new WechatChannel({
|
|
715
|
+
baseUrl: wechatConfig.baseUrl || 'https://ilinkai.weixin.qq.com',
|
|
716
|
+
token: wechatConfig.token,
|
|
717
|
+
});
|
|
718
|
+
const adapter = {
|
|
719
|
+
name: 'wechat',
|
|
720
|
+
sendText: (id, text) => channel.sendMessage(id, text),
|
|
721
|
+
sendFile: (id, filePath) => channel.sendFile(id, filePath),
|
|
722
|
+
};
|
|
723
|
+
const policy = {
|
|
724
|
+
canSwitchProject: (chatType, identity) => identity === 'owner',
|
|
725
|
+
canListProjects: (chatType, identity) => identity === 'owner',
|
|
726
|
+
canCreateSession: (chatType, identity) => true,
|
|
727
|
+
canDeleteSession: (chatType, identity) => true,
|
|
728
|
+
canImportCliSession: (chatType, identity) => identity === 'owner',
|
|
729
|
+
messagePrefix: (chatType, peerName) => '',
|
|
730
|
+
showMiddleResult: (chatType, identity) => {
|
|
731
|
+
const mode = wechatConfig.showActivities ?? config.showActivities ?? 'all';
|
|
732
|
+
if (mode === 'none')
|
|
733
|
+
return false;
|
|
734
|
+
if (mode === 'dm-only')
|
|
735
|
+
return chatType === 'private';
|
|
736
|
+
if (mode === 'owner-dm-only')
|
|
737
|
+
return chatType === 'private' && identity === 'owner';
|
|
738
|
+
return true;
|
|
739
|
+
},
|
|
740
|
+
showIdleMonitor: (chatType, identity) => {
|
|
741
|
+
const mode = wechatConfig.showActivities ?? config.showActivities ?? 'all';
|
|
742
|
+
if (mode === 'none')
|
|
743
|
+
return false;
|
|
744
|
+
if (mode === 'dm-only')
|
|
745
|
+
return chatType === 'private';
|
|
746
|
+
if (mode === 'owner-dm-only')
|
|
747
|
+
return chatType === 'private' && identity === 'owner';
|
|
748
|
+
return true;
|
|
749
|
+
},
|
|
750
|
+
accumulateErrors: (chatType, identity) => true,
|
|
751
|
+
};
|
|
752
|
+
const options = {
|
|
753
|
+
fileMarkerPattern: /\[SEND_FILE:(?:(\w+):)?([^\]]+)\]/g,
|
|
754
|
+
flushDelay: wechatConfig.flushDelay ?? 3, // WeChat 默认 3s
|
|
755
|
+
};
|
|
756
|
+
return {
|
|
757
|
+
adapter,
|
|
758
|
+
channel,
|
|
759
|
+
policy,
|
|
760
|
+
options,
|
|
761
|
+
connect: () => channel.connect(),
|
|
762
|
+
disconnect: () => channel.disconnect(),
|
|
763
|
+
onProjectPathRequest: (channelId) => Promise.resolve(config.projects?.defaultPath || process.cwd()),
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
}
|