acp-ts 1.1.9 → 1.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/dist/agentcp.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { IAgentCP, IAgentIdentity } from "./interfaces";
2
2
  import { MessageStore } from "./messagestore";
3
3
  import { AgentMdOptions } from "./agentmd";
4
- import { ACPGroupClient, GroupOperations, ACPGroupEventHandler, CursorStore, GroupMessageStore, GroupMessage } from "./group";
4
+ import { ACPGroupClient, GroupOperations, ACPGroupEventHandler, CursorStore, GroupMessageStore, GroupMessage, GroupMessageBatch } from "./group";
5
5
  declare class AgentCP implements IAgentCP {
6
6
  private seedPassword;
7
7
  private apUrl;
@@ -90,15 +90,20 @@ declare class AgentCP implements IAgentCP {
90
90
  setGroupEventHandler(handler: ACPGroupEventHandler): void;
91
91
  /**
92
92
  * 创建默认的群组事件处理器。
93
- * - onGroupMessage: 自动存储消息到 GroupMessageStore + 自动 ACK
93
+ * - onGroupMessageBatch: 自动存储消息 + watermark ACK
94
94
  * - onJoinApproved: 自动注册到 Home AP + 存储群组
95
95
  * 外部可通过 setGroupEventHandler 覆盖。
96
96
  */
97
97
  private _createDefaultGroupEventHandler;
98
98
  /**
99
- * 自动 ACK 消息(SDK 内部行为,对上层透明)
99
+ * 处理批量推送消息:排序、存储、ACK 最后一条。
100
+ * 返回排序后的消息列表,供上层使用(如推送给浏览器)。
100
101
  */
101
- private _autoAckMessage;
102
+ processAndAckBatch(groupId: string, batch: GroupMessageBatch): GroupMessage[];
103
+ /**
104
+ * 异步 ACK 消息(不阻塞调用方)
105
+ */
106
+ private _ackMessage;
102
107
  /**
103
108
  * 设置群组游标存储
104
109
  */
@@ -142,10 +147,6 @@ declare class AgentCP implements IAgentCP {
142
147
  * 添加群组到本地存储
143
148
  */
144
149
  addGroupToStore(groupId: string, name: string): void;
145
- /**
146
- * 将加入的群组注册到 Home AP(内部方法)
147
- */
148
- registerGroupToHomeAP(groupId: string, groupUrl: string, role?: string): Promise<void>;
149
150
  /**
150
151
  * 从本地存储删除群组
151
152
  */
package/dist/agentcp.js CHANGED
@@ -61,7 +61,7 @@ class AgentCP {
61
61
  this.groupMessageStore = null;
62
62
  this._groupTargetAid = '';
63
63
  this._groupSessionId = '';
64
- this._persistGroupMessages = false;
64
+ this._persistGroupMessages = true;
65
65
  // Group lifecycle management
66
66
  this._onlineGroups = new Set();
67
67
  this._heartbeatTimer = null;
@@ -80,7 +80,7 @@ class AgentCP {
80
80
  this._basePath = basePath || process.cwd();
81
81
  this.apUrl = `${baseUrl}/api/accesspoint`;
82
82
  this.msgUrl = `${baseUrl}/api/message`;
83
- this._persistGroupMessages = (_a = options === null || options === void 0 ? void 0 : options.persistGroupMessages) !== null && _a !== void 0 ? _a : false;
83
+ this._persistGroupMessages = (_a = options === null || options === void 0 ? void 0 : options.persistGroupMessages) !== null && _a !== void 0 ? _a : true;
84
84
  this._messageStore = new messagestore_1.MessageStore({
85
85
  persistMessages: (_b = options === null || options === void 0 ? void 0 : options.persistMessages) !== null && _b !== void 0 ? _b : false,
86
86
  basePath: this._basePath,
@@ -401,7 +401,7 @@ class AgentCP {
401
401
  }
402
402
  /**
403
403
  * 创建默认的群组事件处理器。
404
- * - onGroupMessage: 自动存储消息到 GroupMessageStore + 自动 ACK
404
+ * - onGroupMessageBatch: 自动存储消息 + watermark ACK
405
405
  * - onJoinApproved: 自动注册到 Home AP + 存储群组
406
406
  * 外部可通过 setGroupEventHandler 覆盖。
407
407
  */
@@ -431,8 +431,6 @@ class AgentCP {
431
431
  }
432
432
  catch (_) { }
433
433
  this.addGroupToStore(groupId, groupName);
434
- const groupUrl = groupAddress || `https://${this._groupTargetAid}/${groupId}`;
435
- await this.registerGroupToHomeAP(groupId, groupUrl);
436
434
  }
437
435
  catch (e) {
438
436
  console.error(`[Group][DefaultHandler] onJoinApproved processing failed: group=${groupId}`, e.message);
@@ -445,12 +443,9 @@ class AgentCP {
445
443
  onJoinRequestReceived(groupId, agentId, message) {
446
444
  console.log(`[Group][DefaultHandler] onJoinRequestReceived: group=${groupId} agent=${agentId}`);
447
445
  },
448
- onGroupMessage: (groupId, msg) => {
449
- console.log(`[Group][DefaultHandler] onGroupMessage: group=${groupId} msgId=${msg.msg_id} sender=${msg.sender}`);
450
- // 自动存储消息到本地
451
- this.addGroupMessageToStore(groupId, msg);
452
- // 自动 ACK(异步,不阻塞回调)
453
- this._autoAckMessage(groupId, msg.msg_id);
446
+ onGroupMessageBatch: (groupId, batch) => {
447
+ console.log(`[Group][DefaultHandler] onGroupMessageBatch: group=${groupId} count=${batch.count} range=[${batch.start_msg_id}, ${batch.latest_msg_id}]`);
448
+ this.processAndAckBatch(groupId, batch);
454
449
  },
455
450
  onGroupEvent(groupId, evt) {
456
451
  console.log(`[Group][DefaultHandler] onGroupEvent: group=${groupId} event=${evt.event_type}`);
@@ -458,13 +453,27 @@ class AgentCP {
458
453
  };
459
454
  }
460
455
  /**
461
- * 自动 ACK 消息(SDK 内部行为,对上层透明)
456
+ * 处理批量推送消息:排序、存储、ACK 最后一条。
457
+ * 返回排序后的消息列表,供上层使用(如推送给浏览器)。
462
458
  */
463
- _autoAckMessage(groupId, msgId) {
459
+ processAndAckBatch(groupId, batch) {
460
+ const sorted = [...batch.messages].sort((a, b) => a.msg_id - b.msg_id);
461
+ this.addGroupMessagesToStore(groupId, sorted);
462
+ // ACK batch 中最后一条消息
463
+ if (sorted.length > 0) {
464
+ const lastMsgId = sorted[sorted.length - 1].msg_id;
465
+ this._ackMessage(groupId, lastMsgId);
466
+ }
467
+ return sorted;
468
+ }
469
+ /**
470
+ * 异步 ACK 消息(不阻塞调用方)
471
+ */
472
+ _ackMessage(groupId, msgId) {
464
473
  if (!this.groupOps || !this._groupTargetAid)
465
474
  return;
466
475
  this.groupOps.ackMessages(this._groupTargetAid, groupId, msgId).catch(e => {
467
- console.warn(`[Group] auto ack failed: group=${groupId} msgId=${msgId}`, e.message || e);
476
+ console.warn(`[Group] ack failed: group=${groupId} msgId=${msgId}`, e.message || e);
468
477
  });
469
478
  }
470
479
  /**
@@ -574,20 +583,6 @@ class AgentCP {
574
583
  return;
575
584
  this.groupMessageStore.getOrCreateGroup(groupId, this._groupTargetAid, name);
576
585
  }
577
- /**
578
- * 将加入的群组注册到 Home AP(内部方法)
579
- */
580
- async registerGroupToHomeAP(groupId, groupUrl, role = 'member') {
581
- if (!this.groupOps || !this._groupTargetAid)
582
- return;
583
- try {
584
- await this.groupOps.registerMembership(this._groupTargetAid, groupId, groupUrl, this._groupTargetAid, this._groupSessionId, role);
585
- console.log(`[Group] registerGroupToHomeAP success: group=${groupId}`);
586
- }
587
- catch (e) {
588
- console.error(`[Group] registerGroupToHomeAP failed: group=${groupId}`, e.message);
589
- }
590
- }
591
586
  /**
592
587
  * 从本地存储删除群组
593
588
  */
@@ -697,7 +692,15 @@ class AgentCP {
697
692
  await this.groupOps.registerOnline(this._groupTargetAid);
698
693
  this._onlineGroups.add(groupId);
699
694
  console.log(`[Group] joinGroupSession: group=${groupId}`);
700
- // Step 2: 启动心跳定时器(首次加入群组时启动)
695
+ // Step 2: 冷启动同步 — 拉取历史消息对齐,再进入批推送接收
696
+ try {
697
+ const lastMsgId = this.getGroupLastMsgId(groupId);
698
+ await this.pullAndStoreGroupMessages(groupId, lastMsgId, 50);
699
+ }
700
+ catch (e) {
701
+ console.warn(`[Group] cold-start sync failed: group=${groupId}`, e.message || e);
702
+ }
703
+ // Step 3: 启动心跳定时器(首次加入群组时启动)
701
704
  this._ensureHeartbeat();
702
705
  }
703
706
  /**
@@ -74,7 +74,7 @@ class ACPGroupClient {
74
74
  * Called by the message dispatch chain in AgentCP.
75
75
  */
76
76
  handleIncoming(payload) {
77
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
77
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
78
78
  let data;
79
79
  try {
80
80
  data = JSON.parse(payload);
@@ -116,31 +116,33 @@ class ACPGroupClient {
116
116
  }
117
117
  return;
118
118
  }
119
- // Handle action-based push messages from group.ap (e.g. message_push)
120
- // These have action field but no event/request_id, need to be mapped to notification events
119
+ // Handle batch push from group.ap
121
120
  const action = (_d = data.action) !== null && _d !== void 0 ? _d : "";
122
- if (action === "message_push" && data.data) {
123
- console.log(`[GroupClient] message_push -> group_message: group=${data.group_id} msg_id=${data.data.msg_id}`);
124
- const msgData = data.data;
125
- const notify = {
126
- action: "group_notify",
127
- group_id: (_e = data.group_id) !== null && _e !== void 0 ? _e : "",
128
- event: types_1.NOTIFY_GROUP_MESSAGE,
129
- data: {
130
- msg_id: (_f = msgData.msg_id) !== null && _f !== void 0 ? _f : 0,
131
- sender: (_g = msgData.sender) !== null && _g !== void 0 ? _g : "",
132
- content: (_h = msgData.content) !== null && _h !== void 0 ? _h : "",
133
- content_type: (_j = msgData.content_type) !== null && _j !== void 0 ? _j : "text",
134
- timestamp: (_k = msgData.timestamp) !== null && _k !== void 0 ? _k : 0,
135
- metadata: (_l = msgData.metadata) !== null && _l !== void 0 ? _l : null,
136
- },
137
- timestamp: (_m = msgData.timestamp) !== null && _m !== void 0 ? _m : 0,
121
+ if (action === types_1.ACTION_MESSAGE_BATCH_PUSH && data.data) {
122
+ const batchData = data.data;
123
+ const batch = {
124
+ messages: ((_e = batchData.messages) !== null && _e !== void 0 ? _e : []).map((m) => {
125
+ var _a, _b, _c, _d, _e, _f;
126
+ return ({
127
+ msg_id: (_a = m.msg_id) !== null && _a !== void 0 ? _a : 0,
128
+ sender: (_b = m.sender) !== null && _b !== void 0 ? _b : "",
129
+ content: (_c = m.content) !== null && _c !== void 0 ? _c : "",
130
+ content_type: (_d = m.content_type) !== null && _d !== void 0 ? _d : "text/plain",
131
+ timestamp: (_e = m.timestamp) !== null && _e !== void 0 ? _e : 0,
132
+ metadata: (_f = m.metadata) !== null && _f !== void 0 ? _f : null,
133
+ });
134
+ }),
135
+ start_msg_id: (_f = batchData.start_msg_id) !== null && _f !== void 0 ? _f : 0,
136
+ latest_msg_id: (_g = batchData.latest_msg_id) !== null && _g !== void 0 ? _g : 0,
137
+ count: (_h = batchData.count) !== null && _h !== void 0 ? _h : 0,
138
138
  };
139
+ const groupId = (_j = data.group_id) !== null && _j !== void 0 ? _j : "";
140
+ console.log(`[GroupClient] message_batch_push: group=${groupId} count=${batch.count} range=[${batch.start_msg_id}, ${batch.latest_msg_id}]`);
139
141
  if (this._handler != null) {
140
- (0, events_1.dispatchAcpNotify)(this._handler, notify);
142
+ this._handler.onGroupMessageBatch(groupId, batch);
141
143
  }
142
144
  else {
143
- console.warn(`[GroupClient] !!! message_push dropped: no event handler registered.`);
145
+ console.warn(`[GroupClient] !!! message_batch_push dropped: no event handler registered.`);
144
146
  }
145
147
  return;
146
148
  }
@@ -2,7 +2,7 @@
2
2
  * Group event handler interfaces and dispatch logic.
3
3
  * Mirrors Python SDK: agentcp/group/events.py
4
4
  */
5
- import { GroupNotify, GroupMessage, GroupEvent } from './types';
5
+ import { GroupNotify, GroupEvent, GroupMessageBatch } from './types';
6
6
  /**
7
7
  * Abstract handler for ACP group notifications.
8
8
  */
@@ -13,7 +13,7 @@ export interface ACPGroupEventHandler {
13
13
  onJoinApproved(groupId: string, groupAddress: string): void;
14
14
  onJoinRejected(groupId: string, reason: string): void;
15
15
  onJoinRequestReceived(groupId: string, agentId: string, message: string): void;
16
- onGroupMessage(groupId: string, msg: GroupMessage): void;
16
+ onGroupMessageBatch(groupId: string, batch: GroupMessageBatch): void;
17
17
  onGroupEvent(groupId: string, evt: GroupEvent): void;
18
18
  }
19
19
  /**
@@ -38,9 +38,6 @@ function dispatchAcpNotify(handler, notify) {
38
38
  else if (event === types_1.NOTIFY_JOIN_REQUEST_RECEIVED) {
39
39
  handler.onJoinRequestReceived(gid, (_l = data.agent_id) !== null && _l !== void 0 ? _l : "", (_m = data.message) !== null && _m !== void 0 ? _m : "");
40
40
  }
41
- else if (event === types_1.NOTIFY_GROUP_MESSAGE) {
42
- handler.onGroupMessage(gid, data);
43
- }
44
41
  else if (event === types_1.NOTIFY_GROUP_EVENT) {
45
42
  handler.onGroupEvent(gid, data);
46
43
  }
@@ -2,7 +2,7 @@
2
2
  * ACP Group Operations package.
3
3
  * Mirrors Python SDK: agentcp/group/__init__.py
4
4
  */
5
- export { GroupErrorCode, GroupError, GroupRequest, GroupResponse, GroupNotify, buildGroupRequest, groupRequestToJson, parseGroupResponse, parseGroupNotify, GroupMessage, GroupEvent, MsgCursor, EventCursor, CursorState, createMsgCursor, createEventCursor, CreateGroupResp, SendMessageResp, PullMessagesResp, PullEventsResp, GroupInfoResp, BanlistResp, BatchReviewResp, PendingRequestsResp, MembersResp, AdminsResp, RulesResp, AnnouncementResp, JoinRequirementsResp, MasterResp, InviteCodeResp, InviteCodeListResp, BroadcastLockResp, BroadcastPermissionResp, SyncStatusResp, SyncLogResp, ChecksumResp, PublicGroupInfoResp, SearchGroupsResp, DigestResp, MembershipInfo, ListMyGroupsResp, GetFileResp, GetSummaryResp, GetMetricsResp, NOTIFY_NEW_MESSAGE, NOTIFY_NEW_EVENT, NOTIFY_GROUP_INVITE, NOTIFY_JOIN_APPROVED, NOTIFY_JOIN_REJECTED, NOTIFY_JOIN_REQUEST_RECEIVED, NOTIFY_GROUP_MESSAGE, NOTIFY_GROUP_EVENT, EVENT_MEMBER_JOINED, EVENT_MEMBER_REMOVED, EVENT_MEMBER_LEFT, EVENT_MEMBER_BANNED, EVENT_META_UPDATED, EVENT_RULES_UPDATED, EVENT_ANNOUNCEMENT_UPDATED, EVENT_GROUP_DISSOLVED, EVENT_MASTER_TRANSFERRED, EVENT_GROUP_SUSPENDED, EVENT_GROUP_RESUMED, EVENT_MEMBER_UNBANNED, EVENT_JOIN_REQUIREMENTS_UPDATED, EVENT_INVITE_CODE_CREATED, EVENT_INVITE_CODE_REVOKED, } from './types';
5
+ export { GroupErrorCode, GroupError, GroupRequest, GroupResponse, GroupNotify, buildGroupRequest, groupRequestToJson, parseGroupResponse, parseGroupNotify, GroupMessage, GroupEvent, MsgCursor, EventCursor, CursorState, createMsgCursor, createEventCursor, CreateGroupResp, SendMessageResp, PullMessagesResp, PullEventsResp, GroupInfoResp, BanlistResp, BatchReviewResp, PendingRequestsResp, MembersResp, AdminsResp, RulesResp, AnnouncementResp, JoinRequirementsResp, MasterResp, InviteCodeResp, InviteCodeListResp, BroadcastLockResp, BroadcastPermissionResp, SyncStatusResp, SyncLogResp, ChecksumResp, PublicGroupInfoResp, SearchGroupsResp, DigestResp, MembershipInfo, ListMyGroupsResp, GetFileResp, GetSummaryResp, GetMetricsResp, NOTIFY_NEW_MESSAGE, NOTIFY_NEW_EVENT, NOTIFY_GROUP_INVITE, NOTIFY_JOIN_APPROVED, NOTIFY_JOIN_REJECTED, NOTIFY_JOIN_REQUEST_RECEIVED, NOTIFY_GROUP_EVENT, EVENT_MEMBER_JOINED, EVENT_MEMBER_REMOVED, EVENT_MEMBER_LEFT, EVENT_MEMBER_BANNED, EVENT_META_UPDATED, EVENT_RULES_UPDATED, EVENT_ANNOUNCEMENT_UPDATED, EVENT_GROUP_DISSOLVED, EVENT_MASTER_TRANSFERRED, EVENT_GROUP_SUSPENDED, EVENT_GROUP_RESUMED, EVENT_MEMBER_UNBANNED, EVENT_JOIN_REQUIREMENTS_UPDATED, EVENT_INVITE_CODE_CREATED, EVENT_INVITE_CODE_REVOKED, ACTION_MESSAGE_BATCH_PUSH, GroupMessageBatch, } from './types';
6
6
  export { ACPGroupClient, SendFunc } from './client';
7
7
  export { GroupOperations, SyncHandler } from './operations';
8
8
  export { ACPGroupEventHandler, EventProcessor, dispatchAcpNotify, dispatchEvent, } from './events';
@@ -4,7 +4,7 @@
4
4
  * Mirrors Python SDK: agentcp/group/__init__.py
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.GroupMessageStore = exports.LocalCursorStore = exports.dispatchAcpNotify = exports.GroupOperations = exports.ACPGroupClient = exports.EVENT_INVITE_CODE_REVOKED = exports.EVENT_INVITE_CODE_CREATED = exports.EVENT_JOIN_REQUIREMENTS_UPDATED = exports.EVENT_MEMBER_UNBANNED = exports.EVENT_GROUP_RESUMED = exports.EVENT_GROUP_SUSPENDED = exports.EVENT_MASTER_TRANSFERRED = exports.EVENT_GROUP_DISSOLVED = exports.EVENT_ANNOUNCEMENT_UPDATED = exports.EVENT_RULES_UPDATED = exports.EVENT_META_UPDATED = exports.EVENT_MEMBER_BANNED = exports.EVENT_MEMBER_LEFT = exports.EVENT_MEMBER_REMOVED = exports.EVENT_MEMBER_JOINED = exports.NOTIFY_GROUP_EVENT = exports.NOTIFY_GROUP_MESSAGE = exports.NOTIFY_JOIN_REQUEST_RECEIVED = exports.NOTIFY_JOIN_REJECTED = exports.NOTIFY_JOIN_APPROVED = exports.NOTIFY_GROUP_INVITE = exports.NOTIFY_NEW_EVENT = exports.NOTIFY_NEW_MESSAGE = exports.createEventCursor = exports.createMsgCursor = exports.parseGroupNotify = exports.parseGroupResponse = exports.groupRequestToJson = exports.buildGroupRequest = exports.GroupError = exports.GroupErrorCode = void 0;
7
+ exports.GroupMessageStore = exports.LocalCursorStore = exports.dispatchAcpNotify = exports.GroupOperations = exports.ACPGroupClient = exports.ACTION_MESSAGE_BATCH_PUSH = exports.EVENT_INVITE_CODE_REVOKED = exports.EVENT_INVITE_CODE_CREATED = exports.EVENT_JOIN_REQUIREMENTS_UPDATED = exports.EVENT_MEMBER_UNBANNED = exports.EVENT_GROUP_RESUMED = exports.EVENT_GROUP_SUSPENDED = exports.EVENT_MASTER_TRANSFERRED = exports.EVENT_GROUP_DISSOLVED = exports.EVENT_ANNOUNCEMENT_UPDATED = exports.EVENT_RULES_UPDATED = exports.EVENT_META_UPDATED = exports.EVENT_MEMBER_BANNED = exports.EVENT_MEMBER_LEFT = exports.EVENT_MEMBER_REMOVED = exports.EVENT_MEMBER_JOINED = exports.NOTIFY_GROUP_EVENT = exports.NOTIFY_JOIN_REQUEST_RECEIVED = exports.NOTIFY_JOIN_REJECTED = exports.NOTIFY_JOIN_APPROVED = exports.NOTIFY_GROUP_INVITE = exports.NOTIFY_NEW_EVENT = exports.NOTIFY_NEW_MESSAGE = exports.createEventCursor = exports.createMsgCursor = exports.parseGroupNotify = exports.parseGroupResponse = exports.groupRequestToJson = exports.buildGroupRequest = exports.GroupError = exports.GroupErrorCode = void 0;
8
8
  // Types
9
9
  var types_1 = require("./types");
10
10
  Object.defineProperty(exports, "GroupErrorCode", { enumerable: true, get: function () { return types_1.GroupErrorCode; } });
@@ -22,7 +22,6 @@ Object.defineProperty(exports, "NOTIFY_GROUP_INVITE", { enumerable: true, get: f
22
22
  Object.defineProperty(exports, "NOTIFY_JOIN_APPROVED", { enumerable: true, get: function () { return types_1.NOTIFY_JOIN_APPROVED; } });
23
23
  Object.defineProperty(exports, "NOTIFY_JOIN_REJECTED", { enumerable: true, get: function () { return types_1.NOTIFY_JOIN_REJECTED; } });
24
24
  Object.defineProperty(exports, "NOTIFY_JOIN_REQUEST_RECEIVED", { enumerable: true, get: function () { return types_1.NOTIFY_JOIN_REQUEST_RECEIVED; } });
25
- Object.defineProperty(exports, "NOTIFY_GROUP_MESSAGE", { enumerable: true, get: function () { return types_1.NOTIFY_GROUP_MESSAGE; } });
26
25
  Object.defineProperty(exports, "NOTIFY_GROUP_EVENT", { enumerable: true, get: function () { return types_1.NOTIFY_GROUP_EVENT; } });
27
26
  // Group event type constants
28
27
  Object.defineProperty(exports, "EVENT_MEMBER_JOINED", { enumerable: true, get: function () { return types_1.EVENT_MEMBER_JOINED; } });
@@ -40,6 +39,8 @@ Object.defineProperty(exports, "EVENT_MEMBER_UNBANNED", { enumerable: true, get:
40
39
  Object.defineProperty(exports, "EVENT_JOIN_REQUIREMENTS_UPDATED", { enumerable: true, get: function () { return types_1.EVENT_JOIN_REQUIREMENTS_UPDATED; } });
41
40
  Object.defineProperty(exports, "EVENT_INVITE_CODE_CREATED", { enumerable: true, get: function () { return types_1.EVENT_INVITE_CODE_CREATED; } });
42
41
  Object.defineProperty(exports, "EVENT_INVITE_CODE_REVOKED", { enumerable: true, get: function () { return types_1.EVENT_INVITE_CODE_REVOKED; } });
42
+ // Batch push
43
+ Object.defineProperty(exports, "ACTION_MESSAGE_BATCH_PUSH", { enumerable: true, get: function () { return types_1.ACTION_MESSAGE_BATCH_PUSH; } });
43
44
  // Client
44
45
  var client_1 = require("./client");
45
46
  Object.defineProperty(exports, "ACPGroupClient", { enumerable: true, get: function () { return client_1.ACPGroupClient; } });
@@ -126,7 +126,6 @@ export declare class GroupOperations {
126
126
  }): Promise<SearchGroupsResp>;
127
127
  generateDigest(targetAid: string, groupId: string, date: string, period: string): Promise<DigestResp>;
128
128
  getDigest(targetAid: string, groupId: string, date: string, period: string): Promise<DigestResp>;
129
- registerMembership(targetAid: string, groupId: string, groupUrl: string, groupServer: string, sessionId: string, role: string): Promise<void>;
130
129
  listMyGroups(targetAid: string, status?: number): Promise<ListMyGroupsResp>;
131
130
  unregisterMembership(targetAid: string, groupId: string): Promise<void>;
132
131
  changeMemberRole(targetAid: string, groupId: string, agentId: string, newRole: string): Promise<void>;
@@ -558,14 +558,6 @@ class GroupOperations {
558
558
  // ============================================================
559
559
  // Phase 5: Home AP Membership Index
560
560
  // ============================================================
561
- async registerMembership(targetAid, groupId, groupUrl, groupServer, sessionId, role) {
562
- const params = {
563
- group_id: groupId, group_url: groupUrl,
564
- group_server: groupServer, session_id: sessionId, role,
565
- };
566
- const resp = await this._client.sendRequest(targetAid, groupId, "register_membership", params);
567
- this._check(resp, "register_membership");
568
- }
569
561
  async listMyGroups(targetAid, status = 0) {
570
562
  var _a, _b;
571
563
  const params = {};
@@ -247,7 +247,6 @@ export declare const NOTIFY_GROUP_INVITE = "group_invite";
247
247
  export declare const NOTIFY_JOIN_APPROVED = "join_approved";
248
248
  export declare const NOTIFY_JOIN_REJECTED = "join_rejected";
249
249
  export declare const NOTIFY_JOIN_REQUEST_RECEIVED = "join_request_received";
250
- export declare const NOTIFY_GROUP_MESSAGE = "group_message";
251
250
  export declare const NOTIFY_GROUP_EVENT = "group_event";
252
251
  export declare const EVENT_MEMBER_JOINED = "member_joined";
253
252
  export declare const EVENT_MEMBER_REMOVED = "member_removed";
@@ -264,3 +263,10 @@ export declare const EVENT_MEMBER_UNBANNED = "member_unbanned";
264
263
  export declare const EVENT_JOIN_REQUIREMENTS_UPDATED = "join_requirements_updated";
265
264
  export declare const EVENT_INVITE_CODE_CREATED = "invite_code_created";
266
265
  export declare const EVENT_INVITE_CODE_REVOKED = "invite_code_revoked";
266
+ export declare const ACTION_MESSAGE_BATCH_PUSH = "message_batch_push";
267
+ export interface GroupMessageBatch {
268
+ messages: GroupMessage[];
269
+ start_msg_id: number;
270
+ latest_msg_id: number;
271
+ count: number;
272
+ }
@@ -4,7 +4,7 @@
4
4
  * Mirrors Python SDK: agentcp/group/types.py
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.EVENT_INVITE_CODE_REVOKED = exports.EVENT_INVITE_CODE_CREATED = exports.EVENT_JOIN_REQUIREMENTS_UPDATED = exports.EVENT_MEMBER_UNBANNED = exports.EVENT_GROUP_RESUMED = exports.EVENT_GROUP_SUSPENDED = exports.EVENT_MASTER_TRANSFERRED = exports.EVENT_GROUP_DISSOLVED = exports.EVENT_ANNOUNCEMENT_UPDATED = exports.EVENT_RULES_UPDATED = exports.EVENT_META_UPDATED = exports.EVENT_MEMBER_BANNED = exports.EVENT_MEMBER_LEFT = exports.EVENT_MEMBER_REMOVED = exports.EVENT_MEMBER_JOINED = exports.NOTIFY_GROUP_EVENT = exports.NOTIFY_GROUP_MESSAGE = exports.NOTIFY_JOIN_REQUEST_RECEIVED = exports.NOTIFY_JOIN_REJECTED = exports.NOTIFY_JOIN_APPROVED = exports.NOTIFY_GROUP_INVITE = exports.NOTIFY_NEW_EVENT = exports.NOTIFY_NEW_MESSAGE = exports.GroupError = exports.GroupErrorCode = void 0;
7
+ exports.ACTION_MESSAGE_BATCH_PUSH = exports.EVENT_INVITE_CODE_REVOKED = exports.EVENT_INVITE_CODE_CREATED = exports.EVENT_JOIN_REQUIREMENTS_UPDATED = exports.EVENT_MEMBER_UNBANNED = exports.EVENT_GROUP_RESUMED = exports.EVENT_GROUP_SUSPENDED = exports.EVENT_MASTER_TRANSFERRED = exports.EVENT_GROUP_DISSOLVED = exports.EVENT_ANNOUNCEMENT_UPDATED = exports.EVENT_RULES_UPDATED = exports.EVENT_META_UPDATED = exports.EVENT_MEMBER_BANNED = exports.EVENT_MEMBER_LEFT = exports.EVENT_MEMBER_REMOVED = exports.EVENT_MEMBER_JOINED = exports.NOTIFY_GROUP_EVENT = exports.NOTIFY_JOIN_REQUEST_RECEIVED = exports.NOTIFY_JOIN_REJECTED = exports.NOTIFY_JOIN_APPROVED = exports.NOTIFY_GROUP_INVITE = exports.NOTIFY_NEW_EVENT = exports.NOTIFY_NEW_MESSAGE = exports.GroupError = exports.GroupErrorCode = void 0;
8
8
  exports.buildGroupRequest = buildGroupRequest;
9
9
  exports.groupRequestToJson = groupRequestToJson;
10
10
  exports.parseGroupResponse = parseGroupResponse;
@@ -120,7 +120,6 @@ exports.NOTIFY_GROUP_INVITE = "group_invite";
120
120
  exports.NOTIFY_JOIN_APPROVED = "join_approved";
121
121
  exports.NOTIFY_JOIN_REJECTED = "join_rejected";
122
122
  exports.NOTIFY_JOIN_REQUEST_RECEIVED = "join_request_received";
123
- exports.NOTIFY_GROUP_MESSAGE = "group_message";
124
123
  exports.NOTIFY_GROUP_EVENT = "group_event";
125
124
  // Group Event Type Constants
126
125
  exports.EVENT_MEMBER_JOINED = "member_joined";
@@ -138,3 +137,7 @@ exports.EVENT_MEMBER_UNBANNED = "member_unbanned";
138
137
  exports.EVENT_JOIN_REQUIREMENTS_UPDATED = "join_requirements_updated";
139
138
  exports.EVENT_INVITE_CODE_CREATED = "invite_code_created";
140
139
  exports.EVENT_INVITE_CODE_REVOKED = "invite_code_revoked";
140
+ // ============================================================
141
+ // Batch Push Constants & Types
142
+ // ============================================================
143
+ exports.ACTION_MESSAGE_BATCH_PUSH = "message_batch_push";
package/dist/server.js CHANGED
@@ -304,8 +304,6 @@ async function ensureGroupClient(instance) {
304
304
  }
305
305
  catch (_) { }
306
306
  instance.agentCP.addGroupToStore(groupId, groupName);
307
- const groupUrl = groupAddress || `https://${instance.groupTargetAid}/${groupId}`;
308
- await instance.agentCP.registerGroupToHomeAP(groupId, groupUrl);
309
307
  // 新加入的群也立即注册在线
310
308
  await instance.agentCP.joinGroupSession(groupId);
311
309
  }
@@ -327,19 +325,18 @@ async function ensureGroupClient(instance) {
327
325
  console.log(`[Group] onJoinRequestReceived: group=${groupId} agent=${agentId} msg=${message}`);
328
326
  broadcastToBrowser({ type: 'join_request', group_id: groupId, agent_id: agentId, message });
329
327
  },
330
- onGroupMessage(groupId, msg) {
331
- var _a;
332
- console.log(`[Group] onGroupMessage: group=${groupId} msgId=${msg.msg_id} sender=${msg.sender}`);
333
- // 存储消息到本地 + 自动 ACK
334
- instance.agentCP.addGroupMessageToStore(groupId, msg);
335
- (_a = instance.agentCP.groupOps) === null || _a === void 0 ? void 0 : _a.ackMessages(instance.groupTargetAid, groupId, msg.msg_id).catch(e => {
336
- console.warn(`[Group] auto ack failed: group=${groupId} msgId=${msg.msg_id}`, e.message || e);
337
- });
338
- // 推送给浏览器
328
+ onGroupMessageBatch(groupId, batch) {
329
+ console.log(`[Group] onGroupMessageBatch: group=${groupId} count=${batch.count} range=[${batch.start_msg_id}, ${batch.latest_msg_id}]`);
330
+ // 存储 + ACK(统一由 agentcp 处理)
331
+ const sorted = instance.agentCP.processAndAckBatch(groupId, batch);
332
+ // 推送消息列表给浏览器
339
333
  broadcastToBrowser({
340
- type: 'group_message',
334
+ type: 'group_message_batch',
341
335
  group_id: groupId,
342
- message: msg,
336
+ messages: sorted,
337
+ count: batch.count,
338
+ start_msg_id: batch.start_msg_id,
339
+ latest_msg_id: batch.latest_msg_id,
343
340
  });
344
341
  },
345
342
  onGroupEvent(groupId, evt) {
@@ -1667,6 +1664,24 @@ const chatHtml = `<!DOCTYPE html>
1667
1664
  renderGroupMsgs(_lastGroupMsgs);
1668
1665
  }
1669
1666
  }
1667
+ } else if(data.type==='group_message_batch'){
1668
+ // 批量推送的消息列表
1669
+ var gid=data.group_id;
1670
+ var msgs=data.messages||[];
1671
+ if(gid===S.activeGroupId&&S.tab==='group'){
1672
+ var changed=false;
1673
+ msgs.forEach(function(msg){
1674
+ var exists=_lastGroupMsgs.some(function(m){ return m.msg_id===msg.msg_id; });
1675
+ if(!exists){
1676
+ _lastGroupMsgs.push(msg);
1677
+ changed=true;
1678
+ }
1679
+ });
1680
+ if(changed){
1681
+ _lastGroupMsgSig=''; // 强制重新渲染
1682
+ renderGroupMsgs(_lastGroupMsgs);
1683
+ }
1684
+ }
1670
1685
  } else if(data.type==='new_message_notify'){
1671
1686
  // 轻量通知:如果是当前活跃群组,拉取最新消息(本地读取,很快)
1672
1687
  if(data.group_id===S.activeGroupId&&S.tab==='group'){
@@ -2676,9 +2691,6 @@ async function handleRequest(req, res) {
2676
2691
  }
2677
2692
  catch (_) { }
2678
2693
  instance.agentCP.addGroupToStore(groupId, groupName);
2679
- // 注册到 Home AP
2680
- const registrationUrl = `https://${targetAid}/${groupId}`;
2681
- await instance.agentCP.registerGroupToHomeAP(groupId, registrationUrl);
2682
2694
  sendJson(res, { success: true, group_id: groupId });
2683
2695
  }
2684
2696
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "acp-ts",
3
- "version": "1.1.9",
3
+ "version": "1.2.0",
4
4
  "description": "基于 ACP智能体通信协议 的智能体通信库,提供智能体身份管理和实时通信功能",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",