acp-ts 1.1.9 → 1.2.1
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/assets/topic-context-partitioning.md +871 -0
- package/dist/agentcp.d.ts +11 -10
- package/dist/agentcp.js +50 -34
- package/dist/group/client.js +26 -22
- package/dist/group/cursor_store.d.ts +9 -4
- package/dist/group/cursor_store.js +39 -10
- package/dist/group/events.d.ts +2 -2
- package/dist/group/events.js +0 -3
- package/dist/group/index.d.ts +1 -1
- package/dist/group/index.js +3 -2
- package/dist/group/message_store.d.ts +6 -5
- package/dist/group/message_store.js +66 -51
- package/dist/group/operations.d.ts +0 -1
- package/dist/group/operations.js +0 -8
- package/dist/group/types.d.ts +7 -1
- package/dist/group/types.js +5 -2
- package/dist/interfaces.d.ts +2 -2
- package/dist/server.js +51 -20
- package/package.json +1 -1
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
|
-
* -
|
|
93
|
+
* - onGroupMessageBatch: 自动存储消息 + watermark ACK
|
|
94
94
|
* - onJoinApproved: 自动注册到 Home AP + 存储群组
|
|
95
95
|
* 外部可通过 setGroupEventHandler 覆盖。
|
|
96
96
|
*/
|
|
97
97
|
private _createDefaultGroupEventHandler;
|
|
98
98
|
/**
|
|
99
|
-
*
|
|
99
|
+
* 处理批量推送消息:排序、存储、ACK 最后一条。
|
|
100
|
+
* 返回排序后的消息列表,供上层使用(如推送给浏览器)。
|
|
100
101
|
*/
|
|
101
|
-
|
|
102
|
+
processAndAckBatch(groupId: string, batch: GroupMessageBatch): Promise<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
|
*/
|
|
@@ -157,11 +158,11 @@ declare class AgentCP implements IAgentCP {
|
|
|
157
158
|
/**
|
|
158
159
|
* 添加群消息到本地存储
|
|
159
160
|
*/
|
|
160
|
-
addGroupMessageToStore(groupId: string, msg: GroupMessage): void
|
|
161
|
+
addGroupMessageToStore(groupId: string, msg: GroupMessage): Promise<void>;
|
|
161
162
|
/**
|
|
162
163
|
* 批量添加群消息到本地存储
|
|
163
164
|
*/
|
|
164
|
-
addGroupMessagesToStore(groupId: string, msgs: GroupMessage[]): void
|
|
165
|
+
addGroupMessagesToStore(groupId: string, msgs: GroupMessage[]): Promise<void>;
|
|
165
166
|
/**
|
|
166
167
|
* 获取本地存储中群组的最新消息ID(用于增量拉取)
|
|
167
168
|
*/
|
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 =
|
|
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 :
|
|
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
|
-
* -
|
|
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,11 @@ class AgentCP {
|
|
|
445
443
|
onJoinRequestReceived(groupId, agentId, message) {
|
|
446
444
|
console.log(`[Group][DefaultHandler] onJoinRequestReceived: group=${groupId} agent=${agentId}`);
|
|
447
445
|
},
|
|
448
|
-
|
|
449
|
-
console.log(`[Group][DefaultHandler]
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
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).catch(e => {
|
|
449
|
+
console.error(`[Group][DefaultHandler] processAndAckBatch failed: group=${groupId}`, e);
|
|
450
|
+
});
|
|
454
451
|
},
|
|
455
452
|
onGroupEvent(groupId, evt) {
|
|
456
453
|
console.log(`[Group][DefaultHandler] onGroupEvent: group=${groupId} event=${evt.event_type}`);
|
|
@@ -458,13 +455,27 @@ class AgentCP {
|
|
|
458
455
|
};
|
|
459
456
|
}
|
|
460
457
|
/**
|
|
461
|
-
*
|
|
458
|
+
* 处理批量推送消息:排序、存储、ACK 最后一条。
|
|
459
|
+
* 返回排序后的消息列表,供上层使用(如推送给浏览器)。
|
|
460
|
+
*/
|
|
461
|
+
async processAndAckBatch(groupId, batch) {
|
|
462
|
+
const sorted = [...batch.messages].sort((a, b) => a.msg_id - b.msg_id);
|
|
463
|
+
await this.addGroupMessagesToStore(groupId, sorted);
|
|
464
|
+
// ACK batch 中最后一条消息
|
|
465
|
+
if (sorted.length > 0) {
|
|
466
|
+
const lastMsgId = sorted[sorted.length - 1].msg_id;
|
|
467
|
+
this._ackMessage(groupId, lastMsgId);
|
|
468
|
+
}
|
|
469
|
+
return sorted;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* 异步 ACK 消息(不阻塞调用方)
|
|
462
473
|
*/
|
|
463
|
-
|
|
474
|
+
_ackMessage(groupId, msgId) {
|
|
464
475
|
if (!this.groupOps || !this._groupTargetAid)
|
|
465
476
|
return;
|
|
466
477
|
this.groupOps.ackMessages(this._groupTargetAid, groupId, msgId).catch(e => {
|
|
467
|
-
console.warn(`[Group]
|
|
478
|
+
console.warn(`[Group] ack failed: group=${groupId} msgId=${msgId}`, e.message || e);
|
|
468
479
|
});
|
|
469
480
|
}
|
|
470
481
|
/**
|
|
@@ -552,6 +563,17 @@ class AgentCP {
|
|
|
552
563
|
this.groupMessageStore.getOrCreateGroup(membership.group_id, this._groupTargetAid, name);
|
|
553
564
|
}
|
|
554
565
|
}
|
|
566
|
+
// 清理本地有但服务端已不存在的群组
|
|
567
|
+
if (this.groupMessageStore) {
|
|
568
|
+
const serverGroupIds = new Set(result.groups.map(g => g.group_id));
|
|
569
|
+
const localGroups = this.groupMessageStore.getGroupList();
|
|
570
|
+
for (const local of localGroups) {
|
|
571
|
+
if (!serverGroupIds.has(local.groupId)) {
|
|
572
|
+
await this.groupMessageStore.deleteGroup(local.groupId);
|
|
573
|
+
console.log(`[Group] syncGroupList: 清理本地已退出群组 ${local.groupId}`);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
555
577
|
return groups;
|
|
556
578
|
}
|
|
557
579
|
/**
|
|
@@ -574,20 +596,6 @@ class AgentCP {
|
|
|
574
596
|
return;
|
|
575
597
|
this.groupMessageStore.getOrCreateGroup(groupId, this._groupTargetAid, name);
|
|
576
598
|
}
|
|
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
599
|
/**
|
|
592
600
|
* 从本地存储删除群组
|
|
593
601
|
*/
|
|
@@ -610,18 +618,18 @@ class AgentCP {
|
|
|
610
618
|
/**
|
|
611
619
|
* 添加群消息到本地存储
|
|
612
620
|
*/
|
|
613
|
-
addGroupMessageToStore(groupId, msg) {
|
|
621
|
+
async addGroupMessageToStore(groupId, msg) {
|
|
614
622
|
if (!this.groupMessageStore)
|
|
615
623
|
return;
|
|
616
|
-
this.groupMessageStore.addMessage(groupId, msg);
|
|
624
|
+
await this.groupMessageStore.addMessage(groupId, msg);
|
|
617
625
|
}
|
|
618
626
|
/**
|
|
619
627
|
* 批量添加群消息到本地存储
|
|
620
628
|
*/
|
|
621
|
-
addGroupMessagesToStore(groupId, msgs) {
|
|
629
|
+
async addGroupMessagesToStore(groupId, msgs) {
|
|
622
630
|
if (!this.groupMessageStore)
|
|
623
631
|
return;
|
|
624
|
-
this.groupMessageStore.addMessages(groupId, msgs);
|
|
632
|
+
await this.groupMessageStore.addMessages(groupId, msgs);
|
|
625
633
|
}
|
|
626
634
|
/**
|
|
627
635
|
* 获取本地存储中群组的最新消息ID(用于增量拉取)
|
|
@@ -664,7 +672,7 @@ class AgentCP {
|
|
|
664
672
|
metadata: (_f = m.metadata) !== null && _f !== void 0 ? _f : null,
|
|
665
673
|
});
|
|
666
674
|
});
|
|
667
|
-
this.addGroupMessagesToStore(groupId, msgs);
|
|
675
|
+
await this.addGroupMessagesToStore(groupId, msgs);
|
|
668
676
|
// ACK 这批消息中的最后一条
|
|
669
677
|
const lastMsgId = msgs[msgs.length - 1].msg_id;
|
|
670
678
|
await this.groupOps.ackMessages(this._groupTargetAid, groupId, lastMsgId);
|
|
@@ -697,7 +705,15 @@ class AgentCP {
|
|
|
697
705
|
await this.groupOps.registerOnline(this._groupTargetAid);
|
|
698
706
|
this._onlineGroups.add(groupId);
|
|
699
707
|
console.log(`[Group] joinGroupSession: group=${groupId}`);
|
|
700
|
-
// Step 2:
|
|
708
|
+
// Step 2: 冷启动同步 — 拉取历史消息对齐,再进入批推送接收
|
|
709
|
+
try {
|
|
710
|
+
const lastMsgId = this.getGroupLastMsgId(groupId);
|
|
711
|
+
await this.pullAndStoreGroupMessages(groupId, lastMsgId, 50);
|
|
712
|
+
}
|
|
713
|
+
catch (e) {
|
|
714
|
+
console.warn(`[Group] cold-start sync failed: group=${groupId}`, e.message || e);
|
|
715
|
+
}
|
|
716
|
+
// Step 3: 启动心跳定时器(首次加入群组时启动)
|
|
701
717
|
this._ensureHeartbeat();
|
|
702
718
|
}
|
|
703
719
|
/**
|
package/dist/group/client.js
CHANGED
|
@@ -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
|
|
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
|
|
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 ===
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
142
|
+
this._handler.onGroupMessageBatch(groupId, batch);
|
|
141
143
|
}
|
|
142
144
|
else {
|
|
143
|
-
console.warn(`[GroupClient] !!!
|
|
145
|
+
console.warn(`[GroupClient] !!! message_batch_push dropped: no event handler registered.`);
|
|
144
146
|
}
|
|
145
147
|
return;
|
|
146
148
|
}
|
|
@@ -158,7 +160,9 @@ class ACPGroupClient {
|
|
|
158
160
|
this._pendingReqs.clear();
|
|
159
161
|
if (this._cursorStore != null) {
|
|
160
162
|
try {
|
|
161
|
-
this._cursorStore.close()
|
|
163
|
+
this._cursorStore.close().catch(e => {
|
|
164
|
+
console.error("[ACPGroupClient] cursor store close error:", e);
|
|
165
|
+
});
|
|
162
166
|
}
|
|
163
167
|
catch (e) {
|
|
164
168
|
console.error("[ACPGroupClient] cursor store close error:", e);
|
|
@@ -10,8 +10,8 @@ export interface CursorStore {
|
|
|
10
10
|
saveEventCursor(groupId: string, eventCursor: number): void;
|
|
11
11
|
loadCursor(groupId: string): [number, number];
|
|
12
12
|
removeCursor(groupId: string): void;
|
|
13
|
-
flush(): void
|
|
14
|
-
close(): void
|
|
13
|
+
flush(): Promise<void>;
|
|
14
|
+
close(): Promise<void>;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* In-memory + JSON file cursor store.
|
|
@@ -24,13 +24,18 @@ export declare class LocalCursorStore implements CursorStore {
|
|
|
24
24
|
private _cursors;
|
|
25
25
|
private _filePath;
|
|
26
26
|
private _dirty;
|
|
27
|
+
private _flushTimer;
|
|
28
|
+
private _flushPromise;
|
|
29
|
+
private _loaded;
|
|
27
30
|
constructor(filePath?: string);
|
|
31
|
+
init(): Promise<void>;
|
|
28
32
|
saveMsgCursor(groupId: string, msgCursor: number): void;
|
|
29
33
|
saveEventCursor(groupId: string, eventCursor: number): void;
|
|
30
34
|
loadCursor(groupId: string): [number, number];
|
|
31
35
|
removeCursor(groupId: string): void;
|
|
32
|
-
flush(): void
|
|
33
|
-
close(): void
|
|
36
|
+
flush(): Promise<void>;
|
|
37
|
+
close(): Promise<void>;
|
|
38
|
+
private _flushDebounced;
|
|
34
39
|
private _write;
|
|
35
40
|
private _load;
|
|
36
41
|
}
|
|
@@ -17,9 +17,15 @@ class LocalCursorStore {
|
|
|
17
17
|
constructor(filePath = "") {
|
|
18
18
|
this._cursors = {};
|
|
19
19
|
this._dirty = false;
|
|
20
|
+
this._flushTimer = null;
|
|
21
|
+
this._flushPromise = null;
|
|
22
|
+
this._loaded = false;
|
|
20
23
|
this._filePath = filePath;
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
}
|
|
25
|
+
async init() {
|
|
26
|
+
if (this._filePath && websocket_1.isNodeEnvironment && !this._loaded) {
|
|
27
|
+
await this._load();
|
|
28
|
+
this._loaded = true;
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
saveMsgCursor(groupId, msgCursor) {
|
|
@@ -29,6 +35,7 @@ class LocalCursorStore {
|
|
|
29
35
|
if (msgCursor > this._cursors[groupId].msg_cursor) {
|
|
30
36
|
this._cursors[groupId].msg_cursor = msgCursor;
|
|
31
37
|
this._dirty = true;
|
|
38
|
+
this._flushDebounced();
|
|
32
39
|
}
|
|
33
40
|
}
|
|
34
41
|
saveEventCursor(groupId, eventCursor) {
|
|
@@ -38,6 +45,7 @@ class LocalCursorStore {
|
|
|
38
45
|
if (eventCursor > this._cursors[groupId].event_cursor) {
|
|
39
46
|
this._cursors[groupId].event_cursor = eventCursor;
|
|
40
47
|
this._dirty = true;
|
|
48
|
+
this._flushDebounced();
|
|
41
49
|
}
|
|
42
50
|
}
|
|
43
51
|
loadCursor(groupId) {
|
|
@@ -51,37 +59,58 @@ class LocalCursorStore {
|
|
|
51
59
|
if (groupId in this._cursors) {
|
|
52
60
|
delete this._cursors[groupId];
|
|
53
61
|
this._dirty = true;
|
|
62
|
+
this._flushDebounced();
|
|
54
63
|
}
|
|
55
64
|
}
|
|
56
|
-
flush() {
|
|
65
|
+
async flush() {
|
|
57
66
|
if (!this._filePath || !websocket_1.isNodeEnvironment) {
|
|
58
67
|
return;
|
|
59
68
|
}
|
|
60
69
|
if (!this._dirty) {
|
|
61
70
|
return;
|
|
62
71
|
}
|
|
63
|
-
this._write();
|
|
72
|
+
await this._write();
|
|
73
|
+
}
|
|
74
|
+
async close() {
|
|
75
|
+
if (this._flushTimer) {
|
|
76
|
+
clearTimeout(this._flushTimer);
|
|
77
|
+
this._flushTimer = null;
|
|
78
|
+
}
|
|
79
|
+
await this.flush();
|
|
64
80
|
}
|
|
65
|
-
|
|
66
|
-
this.
|
|
81
|
+
_flushDebounced() {
|
|
82
|
+
if (this._flushTimer)
|
|
83
|
+
return;
|
|
84
|
+
this._flushTimer = setTimeout(async () => {
|
|
85
|
+
this._flushTimer = null;
|
|
86
|
+
try {
|
|
87
|
+
await this.flush();
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
console.error('[CursorStore] debounced flush failed:', e);
|
|
91
|
+
}
|
|
92
|
+
}, 500);
|
|
67
93
|
}
|
|
68
|
-
_write() {
|
|
94
|
+
async _write() {
|
|
69
95
|
try {
|
|
70
96
|
const fs = require('fs');
|
|
71
|
-
|
|
97
|
+
const content = JSON.stringify(this._cursors, null, 2);
|
|
98
|
+
const tmpPath = this._filePath + '.tmp';
|
|
99
|
+
await fs.promises.writeFile(tmpPath, content, 'utf-8');
|
|
100
|
+
await fs.promises.rename(tmpPath, this._filePath);
|
|
72
101
|
this._dirty = false;
|
|
73
102
|
}
|
|
74
103
|
catch (e) {
|
|
75
104
|
console.error(`[CursorStore] write to ${this._filePath} failed:`, e);
|
|
76
105
|
}
|
|
77
106
|
}
|
|
78
|
-
_load() {
|
|
107
|
+
async _load() {
|
|
79
108
|
try {
|
|
80
109
|
const fs = require('fs');
|
|
81
110
|
if (!fs.existsSync(this._filePath)) {
|
|
82
111
|
return;
|
|
83
112
|
}
|
|
84
|
-
const content = fs.
|
|
113
|
+
const content = await fs.promises.readFile(this._filePath, 'utf-8');
|
|
85
114
|
if (content) {
|
|
86
115
|
this._cursors = JSON.parse(content);
|
|
87
116
|
}
|
package/dist/group/events.d.ts
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
16
|
+
onGroupMessageBatch(groupId: string, batch: GroupMessageBatch): void;
|
|
17
17
|
onGroupEvent(groupId: string, evt: GroupEvent): void;
|
|
18
18
|
}
|
|
19
19
|
/**
|
package/dist/group/events.js
CHANGED
|
@@ -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
|
}
|
package/dist/group/index.d.ts
CHANGED
|
@@ -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,
|
|
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';
|
package/dist/group/index.js
CHANGED
|
@@ -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.
|
|
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; } });
|
|
@@ -27,6 +27,7 @@ export declare class GroupMessageStore {
|
|
|
27
27
|
private maxEventsPerGroup;
|
|
28
28
|
private groups;
|
|
29
29
|
private _indexDirty;
|
|
30
|
+
private _flushIndexPromise;
|
|
30
31
|
constructor(options: {
|
|
31
32
|
persistMessages: boolean;
|
|
32
33
|
basePath: string;
|
|
@@ -45,16 +46,16 @@ export declare class GroupMessageStore {
|
|
|
45
46
|
getGroupList(): GroupRecord[];
|
|
46
47
|
getGroup(groupId: string): GroupRecord | null;
|
|
47
48
|
deleteGroup(groupId: string): Promise<boolean>;
|
|
48
|
-
addMessage(groupId: string, msg: GroupMessage): void
|
|
49
|
-
addMessages(groupId: string, msgs: GroupMessage[]): void
|
|
49
|
+
addMessage(groupId: string, msg: GroupMessage): Promise<void>;
|
|
50
|
+
addMessages(groupId: string, msgs: GroupMessage[]): Promise<void>;
|
|
50
51
|
getMessages(groupId: string, options?: {
|
|
51
52
|
afterMsgId?: number;
|
|
52
53
|
beforeMsgId?: number;
|
|
53
54
|
limit?: number;
|
|
54
55
|
}): GroupMessage[];
|
|
55
56
|
getLatestMessages(groupId: string, limit?: number): GroupMessage[];
|
|
56
|
-
addEvent(groupId: string, evt: GroupEvent): void
|
|
57
|
-
addEvents(groupId: string, evts: GroupEvent[]): void
|
|
57
|
+
addEvent(groupId: string, evt: GroupEvent): Promise<void>;
|
|
58
|
+
addEvents(groupId: string, evts: GroupEvent[]): Promise<void>;
|
|
58
59
|
getEvents(groupId: string, options?: {
|
|
59
60
|
afterEventId?: number;
|
|
60
61
|
limit?: number;
|
|
@@ -63,7 +64,7 @@ export declare class GroupMessageStore {
|
|
|
63
64
|
private writeJsonl;
|
|
64
65
|
private flushMessages;
|
|
65
66
|
private flushEvents;
|
|
66
|
-
private
|
|
67
|
+
private flushIndexQueued;
|
|
67
68
|
flushIndex(): Promise<void>;
|
|
68
69
|
flush(ownerAid: string): Promise<void>;
|
|
69
70
|
flushAll(): Promise<void>;
|