xiaozuoassistant 0.1.93 → 0.1.95

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/bin/cli.js CHANGED
@@ -164,6 +164,11 @@ function getFlagValue(name) {
164
164
  }
165
165
 
166
166
  function getRegistry() {
167
+ if (hasFlag('-cn')) {
168
+ return 'https://registry.npmmirror.com';
169
+ } else if (hasFlag('-en')) {
170
+ return 'https://registry.npmjs.org';
171
+ }
167
172
  return getFlagValue('--registry') || process.env.npm_config_registry || 'https://registry.npmjs.org';
168
173
  }
169
174
 
@@ -804,6 +809,9 @@ if (command === 'start') {
804
809
  console.log(' doctor Check the health and configuration');
805
810
  console.log(' version Print package version and environment');
806
811
  console.log(' update Update xiaozuoassistant and auto-restart if running');
812
+ console.log(' Options:');
813
+ console.log(' -cn Use Chinese npm registry (https://registry.npmmirror.com)');
814
+ console.log(' -en Use English npm registry (https://registry.npmjs.org)');
807
815
  console.log(' remove Uninstall and delete data in current directory');
808
816
  console.log(' export Backup local data (config, memories) to a file');
809
817
  console.log(' import Restore data from a backup file');
@@ -9,7 +9,7 @@ export function createChannels({ app, io, config, pluginManager }) {
9
9
  new TerminalChannel(),
10
10
  new WebChannel(io),
11
11
  ...(config.channels?.telegram?.token ? [new TelegramChannel()] : []),
12
- ...(config.channels?.feishu?.appId ? [new FeishuChannel()] : []),
12
+ ...(config.channels?.feishu ? [new FeishuChannel()] : []),
13
13
  ...(config.channels?.dingtalk?.clientId ? [new DingTalkChannel(app)] : []),
14
14
  ...(config.channels?.wechat?.enabled ? [new WechatChannel()] : []),
15
15
  ...pluginManager.getChannels()
@@ -5,73 +5,92 @@ export class FeishuChannel extends BaseChannel {
5
5
  constructor() {
6
6
  super();
7
7
  this.name = 'feishu';
8
- this.client = null;
9
- this.wsClient = null;
10
- this.appId = config.channels?.feishu?.appId;
11
- this.appSecret = config.channels?.feishu?.appSecret;
8
+ this.bots = [];
12
9
  }
13
10
  async start() {
14
11
  // 每次 start 时重新读取最新配置,避免使用旧缓存
15
- this.appId = config.channels?.feishu?.appId;
16
- this.appSecret = config.channels?.feishu?.appSecret;
17
- if (!this.appId || !this.appSecret) {
18
- console.log('Feishu credentials not configured, skipping Feishu channel.');
12
+ const feishuConfig = config.channels?.feishu;
13
+ // 清空现有机器人
14
+ this.bots = [];
15
+ // 检查配置是否为数组
16
+ if (!Array.isArray(feishuConfig) || feishuConfig.length === 0) {
17
+ console.log('Feishu bots not configured, skipping Feishu channel.');
19
18
  return;
20
19
  }
21
- // Initialize Lark Client for API calls
22
- this.client = new lark.Client({
23
- appId: this.appId,
24
- appSecret: this.appSecret,
25
- appType: lark.AppType.SelfBuild,
26
- domain: lark.Domain.Feishu,
27
- });
28
- // Initialize WebSocket Client for receiving events
29
- this.wsClient = new lark.WSClient({
30
- appId: this.appId,
31
- appSecret: this.appSecret,
32
- });
33
- try {
34
- await this.wsClient.start({
35
- eventDispatcher: new lark.EventDispatcher({}).register({
36
- 'im.message.receive_v1': async (data) => {
37
- const event = data.message;
38
- if (!event || !data.sender)
39
- return;
40
- // Ignore bot messages
41
- if (data.sender.sender_type !== 'user')
42
- return;
43
- try {
44
- const content = JSON.parse(event.content).text;
45
- // Use chat_id for group chats, open_id/user_id for p2p?
46
- // Actually message.chat_id is universal for where the message comes from.
47
- const sessionId = `feishu:${event.chat_id}`;
48
- this.emitMessage(sessionId, content);
49
- }
50
- catch (e) {
51
- console.error('[Feishu] Failed to parse message content:', e);
20
+ // 为每个机器人初始化客户端
21
+ for (const botConfig of feishuConfig) {
22
+ const { name, appId, appSecret } = botConfig;
23
+ if (!name || !appId || !appSecret) {
24
+ console.warn(`Feishu bot ${name || 'unknown'} missing required config, skipping.`);
25
+ continue;
26
+ }
27
+ try {
28
+ // Initialize Lark Client for API calls
29
+ const client = new lark.Client({
30
+ appId,
31
+ appSecret,
32
+ appType: lark.AppType.SelfBuild,
33
+ domain: lark.Domain.Feishu,
34
+ });
35
+ // Initialize WebSocket Client for receiving events
36
+ const wsClient = new lark.WSClient({
37
+ appId,
38
+ appSecret,
39
+ });
40
+ // Start WebSocket client
41
+ await wsClient.start({
42
+ eventDispatcher: new lark.EventDispatcher({}).register({
43
+ 'im.message.receive_v1': async (data) => {
44
+ const event = data.message;
45
+ if (!event || !data.sender)
46
+ return;
47
+ // Ignore bot messages
48
+ if (data.sender.sender_type !== 'user')
49
+ return;
50
+ try {
51
+ const content = JSON.parse(event.content).text;
52
+ // Use chat_id for group chats, open_id/user_id for p2p?
53
+ // Actually message.chat_id is universal for where the message comes from.
54
+ const sessionId = `feishu:${name}:${event.chat_id}`;
55
+ this.emitMessage(sessionId, content);
56
+ }
57
+ catch (e) {
58
+ console.error(`[Feishu-${name}] Failed to parse message content:`, e);
59
+ }
52
60
  }
53
- }
54
- })
55
- });
56
- console.log('Feishu Channel Started (WebSocket Mode)');
57
- }
58
- catch (error) {
59
- console.error('[Feishu] Failed to start WebSocket client:', error);
61
+ })
62
+ });
63
+ this.bots.push({ name, client, wsClient });
64
+ console.log(`Feishu Bot ${name} Started (WebSocket Mode)`);
65
+ }
66
+ catch (error) {
67
+ console.error(`[Feishu-${name}] Failed to start WebSocket client:`, error);
68
+ }
60
69
  }
61
70
  }
62
71
  async stop() {
63
72
  // There is no explicit stop method for WSClient in the current SDK version exposed clearly,
64
73
  // but typically it persists until process exit.
65
- // If needed, we can just set clients to null.
66
- this.wsClient = null;
67
- this.client = null;
74
+ // If needed, we can just clear the bots array.
75
+ this.bots = [];
68
76
  }
69
77
  async send(sessionId, message) {
70
- if (!sessionId.startsWith('feishu:') || !this.client)
78
+ if (!sessionId.startsWith('feishu:'))
79
+ return;
80
+ // Parse sessionId: feishu:<botName>:<chatId>
81
+ const parts = sessionId.split(':');
82
+ if (parts.length < 3)
71
83
  return;
72
- const chatId = sessionId.split(':')[1];
84
+ const botName = parts[1];
85
+ const chatId = parts[2];
86
+ // Find the bot client
87
+ const bot = this.bots.find(b => b.name === botName);
88
+ if (!bot) {
89
+ console.error(`Feishu bot ${botName} not found`);
90
+ return;
91
+ }
73
92
  try {
74
- await this.client.im.message.create({
93
+ await bot.client.im.message.create({
75
94
  params: {
76
95
  receive_id_type: 'chat_id',
77
96
  },
@@ -83,7 +102,7 @@ export class FeishuChannel extends BaseChannel {
83
102
  });
84
103
  }
85
104
  catch (error) {
86
- console.error(`Failed to send Feishu message to ${chatId}:`, error);
105
+ console.error(`[Feishu-${botName}] Failed to send message to ${chatId}:`, error);
87
106
  }
88
107
  }
89
108
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xiaozuoassistant",
3
- "version": "0.1.93",
3
+ "version": "0.1.95",
4
4
  "description": "A local-first personal AI assistant with multi-channel support and enhanced memory.",
5
5
  "author": "mantle.lau",
6
6
  "license": "MIT",