acp-ts 1.2.3 → 1.2.5

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/dist/utils.d.ts CHANGED
@@ -1,3 +1,9 @@
1
+ export declare const logger: {
2
+ log: (...args: any[]) => void;
3
+ warn: (...args: any[]) => void;
4
+ error: (...args: any[]) => void;
5
+ info: (...args: any[]) => void;
6
+ };
1
7
  export declare function getDecryptKey(aid: string, password: string): Promise<string | null>;
2
8
  export declare function savePrivateKey(aid: string, privateKey: string, password: string): Promise<void>;
3
9
  export declare function createAid(aid: string, apiUrl: string, seedPassword: string): Promise<boolean>;
package/dist/utils.js CHANGED
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logger = void 0;
3
4
  exports.getDecryptKey = getDecryptKey;
4
5
  exports.savePrivateKey = savePrivateKey;
5
6
  exports.createAid = createAid;
@@ -7,6 +8,22 @@ const datamanager_1 = require("./datamanager");
7
8
  const cert_1 = require("./cert");
8
9
  const jsrsasign_1 = require("jsrsasign");
9
10
  const api_1 = require("./api");
11
+ function getTimestamp() {
12
+ const now = new Date();
13
+ const y = now.getFullYear();
14
+ const m = String(now.getMonth() + 1).padStart(2, '0');
15
+ const d = String(now.getDate()).padStart(2, '0');
16
+ const h = String(now.getHours()).padStart(2, '0');
17
+ const min = String(now.getMinutes()).padStart(2, '0');
18
+ const s = String(now.getSeconds()).padStart(2, '0');
19
+ return `${y}/${m}/${d} ${h}:${min}:${s}`;
20
+ }
21
+ exports.logger = {
22
+ log: (...args) => console.log(`[${getTimestamp()}]`, ...args),
23
+ warn: (...args) => console.warn(`[${getTimestamp()}]`, ...args),
24
+ error: (...args) => console.error(`[${getTimestamp()}]`, ...args),
25
+ info: (...args) => console.info(`[${getTimestamp()}]`, ...args),
26
+ };
10
27
  // 解密私钥数据
11
28
  function decryptPrivateKey(encryptedData, password) {
12
29
  try {
@@ -16,7 +33,7 @@ function decryptPrivateKey(encryptedData, password) {
16
33
  return privateKeyPEM;
17
34
  }
18
35
  catch (err) {
19
- console.error('私钥解密失败:', err);
36
+ exports.logger.error('私钥解密失败:', err);
20
37
  return null;
21
38
  }
22
39
  }
@@ -29,7 +46,7 @@ function encryptPrivateKey(privateKeyPEM, password) {
29
46
  return encryptedPEM;
30
47
  }
31
48
  catch (err) {
32
- console.error('私钥加密失败:', err);
49
+ exports.logger.error('私钥加密失败:', err);
33
50
  return null;
34
51
  }
35
52
  }
@@ -26,17 +26,28 @@ declare class WSClient {
26
26
  private _isReconnecting;
27
27
  private options;
28
28
  private rawMessageCallback;
29
+ private reconnectNeededCallback;
30
+ private _isReconnectNeededRunning;
29
31
  constructor(options?: WSClientOptions);
30
32
  /**
31
33
  * 检查 WebSocket 是否已连接
32
34
  */
33
35
  private isConnected;
34
36
  connectToServer(wsServer: string, aid: string, sinature: string): Promise<void>;
37
+ /**
38
+ * 注册"快速重连全部失败"回调,通知上层需要重新鉴权
39
+ */
40
+ onReconnectNeeded(cb: () => void): void;
41
+ /**
42
+ * 更新 WebSocket URL(上层重新获取 signature 后调用)
43
+ */
44
+ updateWsUrl(url: string): void;
35
45
  /**
36
46
  * 重连 WebSocket(供外部调用,如心跳重连后触发)
37
47
  * 会关闭旧连接,重置状态,重新建立连接
48
+ * @param newUrl 可选,传入新的 wsUrl(重新鉴权后使用)
38
49
  */
39
- reconnect(): Promise<void>;
50
+ reconnect(newUrl?: string): Promise<void>;
40
51
  createSession(cb: (status: ACPMessageSessionResponse) => void): void;
41
52
  invite(receiver: string, sessionId: string, identifyingCode: string, cb?: (((status: InviteStatus) => void) | null)): void;
42
53
  onStatusChange(cb: (status: ConnectionStatus) => void): void;
package/dist/websocket.js CHANGED
@@ -40,6 +40,7 @@ exports.WSClient = exports.isNodeEnvironment = void 0;
40
40
  const uuid_1 = require("uuid");
41
41
  const mitt_1 = __importDefault(require("mitt"));
42
42
  const https = __importStar(require("https"));
43
+ const utils_1 = require("./utils");
43
44
  // 统一的环境检测函数
44
45
  exports.isNodeEnvironment = typeof process !== 'undefined' &&
45
46
  process.versions != null &&
@@ -67,8 +68,10 @@ class WSClient {
67
68
  this._isReconnecting = false;
68
69
  this.options = {};
69
70
  this.rawMessageCallback = null;
71
+ this.reconnectNeededCallback = null;
72
+ this._isReconnectNeededRunning = false;
70
73
  this.options = options || {};
71
- this.maxRetries = (_a = this.options.maxRetries) !== null && _a !== void 0 ? _a : 5;
74
+ this.maxRetries = (_a = this.options.maxRetries) !== null && _a !== void 0 ? _a : 2;
72
75
  }
73
76
  /**
74
77
  * 检查 WebSocket 是否已连接
@@ -87,21 +90,37 @@ class WSClient {
87
90
  await this.connect();
88
91
  }
89
92
  }
93
+ /**
94
+ * 注册"快速重连全部失败"回调,通知上层需要重新鉴权
95
+ */
96
+ onReconnectNeeded(cb) {
97
+ this.reconnectNeededCallback = cb;
98
+ }
99
+ /**
100
+ * 更新 WebSocket URL(上层重新获取 signature 后调用)
101
+ */
102
+ updateWsUrl(url) {
103
+ this.wsUrl = url;
104
+ }
90
105
  /**
91
106
  * 重连 WebSocket(供外部调用,如心跳重连后触发)
92
107
  * 会关闭旧连接,重置状态,重新建立连接
108
+ * @param newUrl 可选,传入新的 wsUrl(重新鉴权后使用)
93
109
  */
94
- async reconnect() {
110
+ async reconnect(newUrl) {
95
111
  if (this._isReconnecting) {
96
- console.log('[WS] 已在重连中,跳过');
112
+ utils_1.logger.log('[WS] 已在重连中,跳过');
97
113
  return;
98
114
  }
99
- if (!this.wsUrl) {
100
- console.error('[WS] 重连失败: wsUrl 为空,尚未进行过初始连接');
115
+ if (!this.wsUrl && !newUrl) {
116
+ utils_1.logger.error('[WS] 重连失败: wsUrl 为空,尚未进行过初始连接');
101
117
  return;
102
118
  }
103
119
  this._isReconnecting = true;
104
- console.log('[WS] 开始 WebSocket 重连...');
120
+ if (newUrl) {
121
+ this.wsUrl = newUrl;
122
+ }
123
+ utils_1.logger.log('[WS] 开始 WebSocket 重连...');
105
124
  try {
106
125
  // 关闭旧连接(标记为正常关闭,避免触发 onclose 重试)
107
126
  if (this.socket) {
@@ -116,10 +135,10 @@ class WSClient {
116
135
  this.updateStatus('reconnecting');
117
136
  // 重新建立连接
118
137
  await this.connect();
119
- console.log('[WS] WebSocket 重连成功');
138
+ utils_1.logger.log('[WS] WebSocket 重连成功');
120
139
  }
121
140
  catch (error) {
122
- console.error('[WS] WebSocket 重连失败:', error);
141
+ utils_1.logger.error('[WS] WebSocket 重连失败:', error);
123
142
  this.updateStatus('error');
124
143
  }
125
144
  finally {
@@ -174,7 +193,7 @@ class WSClient {
174
193
  sendRaw(message, to, sessionId) {
175
194
  var _a;
176
195
  if (!this.isConnected()) {
177
- console.error('[WS] sendRaw: WebSocket连接未建立或已断开');
196
+ utils_1.logger.error('[WS] sendRaw: WebSocket连接未建立或已断开');
178
197
  return false;
179
198
  }
180
199
  try {
@@ -195,14 +214,14 @@ class WSClient {
195
214
  return true;
196
215
  }
197
216
  catch (error) {
198
- console.error('发送原始消息失败:', error);
217
+ utils_1.logger.error('发送原始消息失败:', error);
199
218
  return false;
200
219
  }
201
220
  }
202
221
  send(message, to, sessionId, identifyingCode) {
203
222
  var _a;
204
223
  if (!message || message.trim().length === 0) {
205
- console.error('发送的消息不能为空');
224
+ utils_1.logger.error('发送的消息不能为空');
206
225
  return;
207
226
  }
208
227
  if (!this.isConnected()) {
@@ -250,7 +269,7 @@ class WSClient {
250
269
  (_a = this.socket) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify(msg));
251
270
  }
252
271
  catch (error) {
253
- console.error('发送消息失败:', error);
272
+ utils_1.logger.error('发送消息失败:', error);
254
273
  this.emitter.emit('message', {
255
274
  type: 'error',
256
275
  content: JSON.stringify([{ content: '发送消息失败' }])
@@ -289,7 +308,7 @@ class WSClient {
289
308
  this.handleMessage(data);
290
309
  }
291
310
  catch (error) {
292
- console.error('解析消息失败:', error);
311
+ utils_1.logger.error('解析消息失败:', error);
293
312
  }
294
313
  };
295
314
  this.socket.onclose = (event) => {
@@ -297,21 +316,35 @@ class WSClient {
297
316
  this.updateStatus('disconnected');
298
317
  if (!this.isNormalClose && !event.wasClean && retryCount < this.maxRetries) {
299
318
  retryCount++;
300
- const retryDelay = Math.min(retryCount * 1000, 10000);
301
- console.warn(`WebSocket连接断开,${retryDelay}ms后重试 (${retryCount}/${this.maxRetries})...`);
319
+ const retryDelay = retryCount * 1000;
320
+ utils_1.logger.warn(`WebSocket连接断开,${retryDelay}ms后快速重试 (${retryCount}/${this.maxRetries})...`);
302
321
  setTimeout(attemptConnect, retryDelay);
303
322
  }
304
323
  else if (!this.isNormalClose && retryCount >= this.maxRetries) {
305
324
  if (!resolved) {
325
+ // 首次连接就失败,直接 reject
306
326
  resolved = true;
307
327
  reject(new Error(`WebSocket连接失败,已达到最大重试次数 (${this.maxRetries})`));
308
328
  }
329
+ else if (this.reconnectNeededCallback
330
+ && !this._isReconnectNeededRunning
331
+ && !this._isReconnecting // 避免 reconnect() 内部的 connect() 失败再次触发,形成循环
332
+ ) {
333
+ // 曾经连接成功过、后来断开且快速重试耗尽 → 通知上层重新鉴权
334
+ utils_1.logger.warn('[WS] 快速重试耗尽,触发 onReconnectNeeded 回调');
335
+ this._isReconnectNeededRunning = true;
336
+ // 回调可能是异步的,用 Promise 确保标志位在异步完成后才重置
337
+ Promise.resolve()
338
+ .then(() => this.reconnectNeededCallback())
339
+ .catch((err) => utils_1.logger.error('[WS] onReconnectNeeded 回调执行失败:', err))
340
+ .finally(() => { this._isReconnectNeededRunning = false; });
341
+ }
309
342
  }
310
343
  this.isNormalClose = false;
311
344
  };
312
345
  this.socket.onerror = (error) => {
313
346
  var _a, _b;
314
- console.error('WebSocket 错误:', {
347
+ utils_1.logger.error('WebSocket 错误:', {
315
348
  error,
316
349
  readyState: (_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState,
317
350
  url: this.wsUrl,
@@ -324,12 +357,12 @@ class WSClient {
324
357
  };
325
358
  }
326
359
  catch (err) {
327
- console.error('创建 WebSocket 实例失败:', err);
360
+ utils_1.logger.error('创建 WebSocket 实例失败:', err);
328
361
  this.updateStatus('error');
329
362
  if (retryCount < this.maxRetries) {
330
363
  retryCount++;
331
364
  const retryDelay = retryCount * 1000;
332
- console.warn(`创建失败,${retryCount}秒后重试...`);
365
+ utils_1.logger.warn(`创建失败,${retryCount}秒后重试...`);
333
366
  setTimeout(attemptConnect, retryDelay);
334
367
  }
335
368
  else {
@@ -358,7 +391,7 @@ class WSClient {
358
391
  }
359
392
  createSessionId() {
360
393
  if (!this.isConnected()) {
361
- console.error('WebSocket连接未建立,无法创建会话');
394
+ utils_1.logger.error('WebSocket连接未建立,无法创建会话');
362
395
  return;
363
396
  }
364
397
  try {
@@ -375,17 +408,17 @@ class WSClient {
375
408
  this.socket.send(JSON.stringify(msg));
376
409
  }
377
410
  catch (error) {
378
- console.error('发送创建会话请求失败:', error);
411
+ utils_1.logger.error('发送创建会话请求失败:', error);
379
412
  }
380
413
  }
381
414
  sendInviteMessage(receiver, sessionId, identifyingCode) {
382
415
  var _a;
383
416
  if (!receiver || !sessionId || !identifyingCode) {
384
- console.error('邀请参数不完整');
417
+ utils_1.logger.error('邀请参数不完整');
385
418
  return;
386
419
  }
387
420
  if (!this.isConnected()) {
388
- console.error('WebSocket连接未建立,无法发送邀请');
421
+ utils_1.logger.error('WebSocket连接未建立,无法发送邀请');
389
422
  return;
390
423
  }
391
424
  try {
@@ -402,7 +435,7 @@ class WSClient {
402
435
  (_a = this.socket) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify(msg));
403
436
  }
404
437
  catch (error) {
405
- console.error('发送邀请失败:', error);
438
+ utils_1.logger.error('发送邀请失败:', error);
406
439
  }
407
440
  }
408
441
  handleMessage(message) {
@@ -434,7 +467,7 @@ class WSClient {
434
467
  else if (cmd === "invite_agent_req") {
435
468
  // 收到邀请请求,自动接受
436
469
  const { session_id, inviter_id, invite_code } = data;
437
- console.log(`收到来自 ${inviter_id} 的会话邀请,会话ID: ${session_id}`);
470
+ utils_1.logger.log(`收到来自 ${inviter_id} 的会话邀请,会话ID: ${session_id}`);
438
471
  this.acceptInvite(session_id, inviter_id, invite_code);
439
472
  }
440
473
  else if (cmd === "session_message") {
@@ -443,7 +476,7 @@ class WSClient {
443
476
  }
444
477
  acceptInvite(sessionId, inviterId, inviteCode) {
445
478
  if (!this.isConnected()) {
446
- console.error('WebSocket连接未建立,无法接受邀请');
479
+ utils_1.logger.error('WebSocket连接未建立,无法接受邀请');
447
480
  return;
448
481
  }
449
482
  try {
@@ -458,11 +491,11 @@ class WSClient {
458
491
  }
459
492
  };
460
493
  this.socket.send(JSON.stringify(msg));
461
- console.log(`已接受会话邀请: ${sessionId}`);
494
+ utils_1.logger.log(`已接受会话邀请: ${sessionId}`);
462
495
  this.isOnline = true;
463
496
  }
464
497
  catch (error) {
465
- console.error('接受邀请失败:', error);
498
+ utils_1.logger.error('接受邀请失败:', error);
466
499
  }
467
500
  }
468
501
  /**
@@ -470,7 +503,7 @@ class WSClient {
470
503
  * 当心跳客户端收到邀请时,调用此方法通过 WebSocket 加入会话
471
504
  */
472
505
  acceptInviteFromHeartbeat(sessionId, inviterId, inviteCode) {
473
- console.log(`[WebSocket] 通过心跳通道收到邀请,加入会话: ${sessionId}`);
506
+ utils_1.logger.log(`[WebSocket] 通过心跳通道收到邀请,加入会话: ${sessionId}`);
474
507
  this.acceptInvite(sessionId, inviterId, inviteCode);
475
508
  }
476
509
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "acp-ts",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "基于 ACP智能体通信协议 的智能体通信库,提供智能体身份管理和实时通信功能",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",