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.
@@ -27,7 +27,6 @@ export declare class GroupMessageStore {
27
27
  private maxEventsPerGroup;
28
28
  private groups;
29
29
  private _indexDirty;
30
- private _flushIndexPromise;
31
30
  constructor(options: {
32
31
  persistMessages: boolean;
33
32
  basePath: string;
@@ -46,16 +45,16 @@ export declare class GroupMessageStore {
46
45
  getGroupList(): GroupRecord[];
47
46
  getGroup(groupId: string): GroupRecord | null;
48
47
  deleteGroup(groupId: string): Promise<boolean>;
49
- addMessage(groupId: string, msg: GroupMessage): Promise<void>;
50
- addMessages(groupId: string, msgs: GroupMessage[]): Promise<void>;
48
+ addMessage(groupId: string, msg: GroupMessage): void;
49
+ addMessages(groupId: string, msgs: GroupMessage[]): void;
51
50
  getMessages(groupId: string, options?: {
52
51
  afterMsgId?: number;
53
52
  beforeMsgId?: number;
54
53
  limit?: number;
55
54
  }): GroupMessage[];
56
55
  getLatestMessages(groupId: string, limit?: number): GroupMessage[];
57
- addEvent(groupId: string, evt: GroupEvent): Promise<void>;
58
- addEvents(groupId: string, evts: GroupEvent[]): Promise<void>;
56
+ addEvent(groupId: string, evt: GroupEvent): void;
57
+ addEvents(groupId: string, evts: GroupEvent[]): void;
59
58
  getEvents(groupId: string, options?: {
60
59
  afterEventId?: number;
61
60
  limit?: number;
@@ -64,7 +63,7 @@ export declare class GroupMessageStore {
64
63
  private writeJsonl;
65
64
  private flushMessages;
66
65
  private flushEvents;
67
- private flushIndexQueued;
66
+ private flushIndexAsync;
68
67
  flushIndex(): Promise<void>;
69
68
  flush(ownerAid: string): Promise<void>;
70
69
  flushAll(): Promise<void>;
@@ -11,13 +11,13 @@
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.GroupMessageStore = void 0;
13
13
  const websocket_1 = require("../websocket");
14
+ const utils_1 = require("../utils");
14
15
  class GroupMessageStore {
15
16
  constructor(options) {
16
17
  var _a, _b;
17
18
  this.ownerAid = '';
18
19
  this.groups = new Map();
19
20
  this._indexDirty = false;
20
- this._flushIndexPromise = null;
21
21
  this.persistMessages = options.persistMessages;
22
22
  this.basePath = options.basePath;
23
23
  this.maxMessagesPerGroup = (_a = options.maxMessagesPerGroup) !== null && _a !== void 0 ? _a : 5000;
@@ -44,12 +44,12 @@ class GroupMessageStore {
44
44
  const path = require('path');
45
45
  return path.join(this.getGroupDir(aid, groupId), 'events.jsonl');
46
46
  }
47
- async ensureDir(dir) {
47
+ ensureDir(dir) {
48
48
  if (!websocket_1.isNodeEnvironment)
49
49
  return;
50
50
  const fs = require('fs');
51
51
  if (!fs.existsSync(dir)) {
52
- await fs.promises.mkdir(dir, { recursive: true });
52
+ fs.mkdirSync(dir, { recursive: true });
53
53
  }
54
54
  }
55
55
  // ---- load ----
@@ -64,45 +64,41 @@ class GroupMessageStore {
64
64
  if (!fs.existsSync(indexPath))
65
65
  return;
66
66
  try {
67
- const raw = await fs.promises.readFile(indexPath, 'utf-8');
67
+ const raw = fs.readFileSync(indexPath, 'utf-8');
68
68
  const records = JSON.parse(raw);
69
69
  if (!Array.isArray(records))
70
70
  return;
71
71
  for (const r of records) {
72
- const messages = await this.readJsonl(this.getMessagesPath(ownerAid, r.groupId));
73
- const events = await this.readJsonl(this.getEventsPath(ownerAid, r.groupId));
72
+ const messages = this.readJsonl(this.getMessagesPath(ownerAid, r.groupId));
73
+ const events = this.readJsonl(this.getEventsPath(ownerAid, r.groupId));
74
74
  this.groups.set(r.groupId, { record: r, messages, events });
75
75
  }
76
76
  }
77
77
  catch (e) {
78
- console.error('[GroupMessageStore] 加载索引失败:', e);
78
+ utils_1.logger.error('[GroupMessageStore] 加载索引失败:', e);
79
79
  }
80
80
  }
81
- async readJsonl(filePath) {
81
+ readJsonl(filePath) {
82
82
  if (!websocket_1.isNodeEnvironment)
83
83
  return [];
84
84
  const fs = require('fs');
85
85
  if (!fs.existsSync(filePath))
86
86
  return [];
87
87
  try {
88
- const raw = await fs.promises.readFile(filePath, 'utf-8');
88
+ const raw = fs.readFileSync(filePath, 'utf-8');
89
89
  const items = [];
90
- const lines = raw.split('\n');
91
- for (let i = 0; i < lines.length; i++) {
92
- const l = lines[i].trim();
90
+ for (const line of raw.split('\n')) {
91
+ const l = line.trim();
93
92
  if (!l)
94
93
  continue;
95
94
  try {
96
95
  items.push(JSON.parse(l));
97
96
  }
98
- catch (lineErr) {
99
- console.warn(`[GroupMessageStore] JSONL 解析失败 (${filePath} 行${i + 1}): ${l.substring(0, 80)}`, lineErr);
100
- }
97
+ catch (_a) { }
101
98
  }
102
99
  return items;
103
100
  }
104
- catch (e) {
105
- console.warn(`[GroupMessageStore] 读取 JSONL 文件失败 (${filePath}):`, e);
101
+ catch (_b) {
106
102
  return [];
107
103
  }
108
104
  }
@@ -119,7 +115,7 @@ class GroupMessageStore {
119
115
  data = { record, messages: [], events: [] };
120
116
  this.groups.set(groupId, data);
121
117
  this._indexDirty = true;
122
- this.flushIndexQueued();
118
+ this.flushIndexAsync();
123
119
  }
124
120
  return data.record;
125
121
  }
@@ -147,17 +143,18 @@ class GroupMessageStore {
147
143
  }
148
144
  }
149
145
  catch (e) {
150
- console.error(`[GroupMessageStore] 删除群目录失败 (${groupId}):`, e);
146
+ utils_1.logger.error(`[GroupMessageStore] 删除群目录失败 (${groupId}):`, e);
151
147
  }
152
148
  await this.flushIndex();
153
149
  }
154
150
  return true;
155
151
  }
156
152
  // ---- message storage ----
157
- async addMessage(groupId, msg) {
153
+ addMessage(groupId, msg) {
158
154
  const data = this.groups.get(groupId);
159
155
  if (!data)
160
156
  return;
157
+ // dedup: skip if msg_id already seen
161
158
  if (msg.msg_id <= data.record.lastMsgId)
162
159
  return;
163
160
  data.messages.push(msg);
@@ -165,35 +162,39 @@ class GroupMessageStore {
165
162
  data.record.messageCount = data.messages.length;
166
163
  data.record.lastMessageAt = msg.timestamp || Date.now();
167
164
  this._indexDirty = true;
165
+ // truncate if over limit
168
166
  if (data.messages.length > this.maxMessagesPerGroup) {
169
167
  const excess = data.messages.length - this.maxMessagesPerGroup;
170
168
  data.messages.splice(0, excess);
171
169
  data.record.messageCount = data.messages.length;
172
- await this.flushMessages(groupId);
170
+ this.flushMessages(groupId);
173
171
  }
174
172
  else {
175
- await this.appendJsonl(this.getMessagesPath(this.ownerAid, groupId), msg);
173
+ this.appendJsonl(this.getMessagesPath(this.ownerAid, groupId), msg);
176
174
  }
177
- this.flushIndexQueued();
175
+ this.flushIndexAsync();
178
176
  }
179
- async addMessages(groupId, msgs) {
177
+ addMessages(groupId, msgs) {
180
178
  const data = this.groups.get(groupId);
181
- if (!data)
179
+ if (!data) {
180
+ utils_1.logger.warn(`[GroupMessageStore] addMessages: group=${groupId} NOT FOUND in store! Available groups: [${Array.from(this.groups.keys()).join(', ')}]`);
181
+ return;
182
+ }
183
+ if (!msgs || msgs.length === 0)
182
184
  return;
183
- const sorted = [...msgs].sort((a, b) => a.msg_id - b.msg_id);
184
- const existingIds = new Set(data.messages.map(m => m.msg_id));
185
+ utils_1.logger.log(`[GroupMessageStore] addMessages: group=${groupId} incoming=${msgs.length} currentLastMsgId=${data.record.lastMsgId} incomingMsgIds=[${msgs.map(m => m.msg_id).join(',')}]`);
185
186
  let added = 0;
186
- for (const msg of sorted) {
187
- if (existingIds.has(msg.msg_id))
187
+ for (const msg of msgs) {
188
+ if (msg.msg_id <= data.record.lastMsgId) {
189
+ utils_1.logger.log(`[GroupMessageStore] addMessages: SKIP duplicate msg_id=${msg.msg_id} <= lastMsgId=${data.record.lastMsgId}`);
188
190
  continue;
189
- data.messages.push(msg);
190
- existingIds.add(msg.msg_id);
191
- if (msg.msg_id > data.record.lastMsgId) {
192
- data.record.lastMsgId = msg.msg_id;
193
191
  }
192
+ data.messages.push(msg);
193
+ data.record.lastMsgId = msg.msg_id;
194
194
  data.record.lastMessageAt = msg.timestamp || Date.now();
195
195
  added++;
196
196
  }
197
+ utils_1.logger.log(`[GroupMessageStore] addMessages result: group=${groupId} added=${added}/${msgs.length} newLastMsgId=${data.record.lastMsgId} totalMessages=${data.messages.length}`);
197
198
  if (added === 0)
198
199
  return;
199
200
  data.record.messageCount = data.messages.length;
@@ -202,9 +203,12 @@ class GroupMessageStore {
202
203
  const excess = data.messages.length - this.maxMessagesPerGroup;
203
204
  data.messages.splice(0, excess);
204
205
  data.record.messageCount = data.messages.length;
206
+ this.flushMessages(groupId);
207
+ }
208
+ else {
209
+ this.flushMessages(groupId);
205
210
  }
206
- await this.flushMessages(groupId);
207
- this.flushIndexQueued();
211
+ this.flushIndexAsync();
208
212
  }
209
213
  getMessages(groupId, options) {
210
214
  const data = this.groups.get(groupId);
@@ -229,7 +233,7 @@ class GroupMessageStore {
229
233
  return data.messages.slice(-limit);
230
234
  }
231
235
  // ---- event storage ----
232
- async addEvent(groupId, evt) {
236
+ addEvent(groupId, evt) {
233
237
  const data = this.groups.get(groupId);
234
238
  if (!data)
235
239
  return;
@@ -243,14 +247,14 @@ class GroupMessageStore {
243
247
  const excess = data.events.length - this.maxEventsPerGroup;
244
248
  data.events.splice(0, excess);
245
249
  data.record.eventCount = data.events.length;
246
- await this.flushEvents(groupId);
250
+ this.flushEvents(groupId);
247
251
  }
248
252
  else {
249
- await this.appendJsonl(this.getEventsPath(this.ownerAid, groupId), evt);
253
+ this.appendJsonl(this.getEventsPath(this.ownerAid, groupId), evt);
250
254
  }
251
- this.flushIndexQueued();
255
+ this.flushIndexAsync();
252
256
  }
253
- async addEvents(groupId, evts) {
257
+ addEvents(groupId, evts) {
254
258
  const data = this.groups.get(groupId);
255
259
  if (!data)
256
260
  return;
@@ -271,8 +275,8 @@ class GroupMessageStore {
271
275
  data.events.splice(0, excess);
272
276
  data.record.eventCount = data.events.length;
273
277
  }
274
- await this.flushEvents(groupId);
275
- this.flushIndexQueued();
278
+ this.flushEvents(groupId);
279
+ this.flushIndexAsync();
276
280
  }
277
281
  getEvents(groupId, options) {
278
282
  const data = this.groups.get(groupId);
@@ -288,54 +292,47 @@ class GroupMessageStore {
288
292
  return result;
289
293
  }
290
294
  // ---- persistence ----
291
- async appendJsonl(filePath, item) {
295
+ appendJsonl(filePath, item) {
292
296
  if (!this.persistMessages || !websocket_1.isNodeEnvironment || !this.ownerAid)
293
297
  return;
294
298
  const fs = require('fs');
295
299
  const path = require('path');
296
- await this.ensureDir(path.dirname(filePath));
300
+ this.ensureDir(path.dirname(filePath));
297
301
  try {
298
- await fs.promises.appendFile(filePath, JSON.stringify(item) + '\n');
302
+ fs.appendFileSync(filePath, JSON.stringify(item) + '\n');
299
303
  }
300
304
  catch (e) {
301
- console.error(`[GroupMessageStore] 追加写入失败 (${filePath}):`, e);
305
+ utils_1.logger.error(`[GroupMessageStore] 追加写入失败 (${filePath}):`, e);
302
306
  }
303
307
  }
304
- async writeJsonl(filePath, items) {
308
+ writeJsonl(filePath, items) {
305
309
  if (!this.persistMessages || !websocket_1.isNodeEnvironment || !this.ownerAid)
306
310
  return;
307
311
  const fs = require('fs');
308
312
  const path = require('path');
309
- await this.ensureDir(path.dirname(filePath));
313
+ this.ensureDir(path.dirname(filePath));
310
314
  try {
311
315
  const lines = items.map(i => JSON.stringify(i)).join('\n');
312
- const content = lines ? lines + '\n' : '';
313
- const tmpPath = filePath + '.tmp';
314
- await fs.promises.writeFile(tmpPath, content);
315
- await fs.promises.rename(tmpPath, filePath);
316
+ fs.writeFileSync(filePath, lines ? lines + '\n' : '');
316
317
  }
317
318
  catch (e) {
318
- console.error(`[GroupMessageStore] 全量写入失败 (${filePath}):`, e);
319
+ utils_1.logger.error(`[GroupMessageStore] 全量写入失败 (${filePath}):`, e);
319
320
  }
320
321
  }
321
- async flushMessages(groupId) {
322
+ flushMessages(groupId) {
322
323
  const data = this.groups.get(groupId);
323
324
  if (!data || !this.ownerAid)
324
325
  return;
325
- await this.writeJsonl(this.getMessagesPath(this.ownerAid, groupId), data.messages);
326
+ this.writeJsonl(this.getMessagesPath(this.ownerAid, groupId), data.messages);
326
327
  }
327
- async flushEvents(groupId) {
328
+ flushEvents(groupId) {
328
329
  const data = this.groups.get(groupId);
329
330
  if (!data || !this.ownerAid)
330
331
  return;
331
- await this.writeJsonl(this.getEventsPath(this.ownerAid, groupId), data.events);
332
+ this.writeJsonl(this.getEventsPath(this.ownerAid, groupId), data.events);
332
333
  }
333
- flushIndexQueued() {
334
- var _a;
335
- const prev = (_a = this._flushIndexPromise) !== null && _a !== void 0 ? _a : Promise.resolve();
336
- this._flushIndexPromise = prev.then(() => this.flushIndex()).catch(e => {
337
- console.error('[GroupMessageStore] 索引刷盘失败:', e);
338
- });
334
+ flushIndexAsync() {
335
+ this.flushIndex().catch(() => { });
339
336
  }
340
337
  async flushIndex() {
341
338
  if (!this.persistMessages || !websocket_1.isNodeEnvironment || !this.ownerAid)
@@ -344,18 +341,15 @@ class GroupMessageStore {
344
341
  return;
345
342
  const fs = require('fs');
346
343
  const dir = this.getGroupsDir(this.ownerAid);
347
- await this.ensureDir(dir);
344
+ this.ensureDir(dir);
348
345
  const records = Array.from(this.groups.values())
349
346
  .map(d => d.record);
350
347
  try {
351
- const indexPath = this.getIndexPath(this.ownerAid);
352
- const tmpPath = indexPath + '.tmp';
353
- await fs.promises.writeFile(tmpPath, JSON.stringify(records, null, 2));
354
- await fs.promises.rename(tmpPath, indexPath);
348
+ fs.writeFileSync(this.getIndexPath(this.ownerAid), JSON.stringify(records, null, 2));
355
349
  this._indexDirty = false;
356
350
  }
357
351
  catch (e) {
358
- console.error('[GroupMessageStore] 写入索引失败:', e);
352
+ utils_1.logger.error('[GroupMessageStore] 写入索引失败:', e);
359
353
  }
360
354
  }
361
355
  async flush(ownerAid) {
@@ -363,9 +357,9 @@ class GroupMessageStore {
363
357
  return;
364
358
  this.ownerAid = ownerAid;
365
359
  await this.flushIndex();
366
- for (const [groupId] of this.groups) {
367
- await this.flushMessages(groupId);
368
- await this.flushEvents(groupId);
360
+ for (const [groupId, data] of this.groups) {
361
+ this.flushMessages(groupId);
362
+ this.flushEvents(groupId);
369
363
  }
370
364
  }
371
365
  async flushAll() {
@@ -3,7 +3,7 @@
3
3
  * Mirrors Python SDK: agentcp/group/operations.py
4
4
  */
5
5
  import { ACPGroupClient } from './client';
6
- import { CreateGroupResp, SendMessageResp, PullMessagesResp, PullEventsResp, CursorState, GroupInfoResp, BanlistResp, BatchReviewResp, PendingRequestsResp, RequestJoinResp, MembersResp, AdminsResp, RulesResp, AnnouncementResp, JoinRequirementsResp, MasterResp, InviteCodeResp, InviteCodeListResp, BroadcastLockResp, BroadcastPermissionResp, SyncStatusResp, SyncLogResp, ChecksumResp, PublicGroupInfoResp, SearchGroupsResp, DigestResp, ListMyGroupsResp, GetFileResp, GetSummaryResp, GetMetricsResp, DutyConfig, DutyStatusResp, DispatchDecisionParams } from './types';
6
+ import { CreateGroupResp, SendMessageResp, PullMessagesResp, PullEventsResp, CursorState, GroupInfoResp, BanlistResp, BatchReviewResp, PendingRequestsResp, RequestJoinResp, MembersResp, AdminsResp, RulesResp, AnnouncementResp, JoinRequirementsResp, MasterResp, InviteCodeResp, InviteCodeListResp, BroadcastLockResp, BroadcastPermissionResp, SyncStatusResp, SyncLogResp, ChecksumResp, PublicGroupInfoResp, SearchGroupsResp, DigestResp, ListMyGroupsResp, GetFileResp, GetSummaryResp, GetMetricsResp, DutyConfig, DutyStatusResp } from './types';
7
7
  /**
8
8
  * Callback interface for syncGroup.
9
9
  */
@@ -146,10 +146,6 @@ export declare class GroupOperations {
146
146
  * 获取值班状态,包含 config 和 state。
147
147
  */
148
148
  getDutyStatus(targetAid: string, groupId: string): Promise<DutyStatusResp>;
149
- /**
150
- * 值班 Agent 提交仲裁决策。
151
- */
152
- dispatchDecision(targetAid: string, groupId: string, params: DispatchDecisionParams): Promise<void>;
153
149
  /**
154
150
  * 重新获取所有成员的 agent.md 并更新 AgentType。
155
151
  */
@@ -207,9 +207,10 @@ class GroupOperations {
207
207
  let after = cursor.msg_cursor.current_msg_id;
208
208
  while (true) {
209
209
  const result = await this.pullMessages(targetAid, groupId, after, 50);
210
- if (result.messages.length > 0) {
211
- handler.onMessages(groupId, result.messages);
212
- const lastId = (_a = result.messages[result.messages.length - 1].msg_id) !== null && _a !== void 0 ? _a : after;
210
+ const messages = result.messages || [];
211
+ if (messages.length > 0) {
212
+ handler.onMessages(groupId, messages);
213
+ const lastId = (_a = messages[messages.length - 1].msg_id) !== null && _a !== void 0 ? _a : after;
213
214
  await this.ackMessages(targetAid, groupId, lastId);
214
215
  after = lastId;
215
216
  }
@@ -223,9 +224,10 @@ class GroupOperations {
223
224
  let after = cursor.event_cursor.current_event_id;
224
225
  while (true) {
225
226
  const result = await this.pullEvents(targetAid, groupId, after, 50);
226
- if (result.events.length > 0) {
227
- handler.onEvents(groupId, result.events);
228
- const lastId = (_a = result.events[result.events.length - 1].event_id) !== null && _a !== void 0 ? _a : after;
227
+ const events = result.events || [];
228
+ if (events.length > 0) {
229
+ handler.onEvents(groupId, events);
230
+ const lastId = (_a = events[events.length - 1].event_id) !== null && _a !== void 0 ? _a : after;
229
231
  await this.ackEvents(targetAid, groupId, lastId);
230
232
  after = lastId;
231
233
  }
@@ -634,11 +636,11 @@ class GroupOperations {
634
636
  params.shift_duration_ms = config.shift_duration_ms;
635
637
  if (config.max_messages_per_shift != null)
636
638
  params.max_messages_per_shift = config.max_messages_per_shift;
637
- if (config.dispatch_timeout_ms != null)
638
- params.dispatch_timeout_ms = config.dispatch_timeout_ms;
639
- if (config.timeout_fallback != null)
640
- params.timeout_fallback = config.timeout_fallback;
641
- const resp = await this._client.sendRequest(targetAid, groupId, "update_duty_config", params);
639
+ if (config.duty_priority_window_ms != null)
640
+ params.duty_priority_window_ms = config.duty_priority_window_ms;
641
+ if (config.enable_rule_prelude != null)
642
+ params.enable_rule_prelude = config.enable_rule_prelude;
643
+ const resp = await this._client.sendRequest(targetAid, groupId, "update_duty_config", { duty_config: params });
642
644
  this._check(resp, "update_duty_config");
643
645
  }
644
646
  /**
@@ -658,13 +660,6 @@ class GroupOperations {
658
660
  const d = resp.data || {};
659
661
  return { config: (_a = d.config) !== null && _a !== void 0 ? _a : {}, state: (_b = d.state) !== null && _b !== void 0 ? _b : {} };
660
662
  }
661
- /**
662
- * 值班 Agent 提交仲裁决策。
663
- */
664
- async dispatchDecision(targetAid, groupId, params) {
665
- const resp = await this._client.sendRequest(targetAid, groupId, "dispatch_decision", params);
666
- this._check(resp, "dispatch_decision");
667
- }
668
663
  /**
669
664
  * 重新获取所有成员的 agent.md 并更新 AgentType。
670
665
  */
@@ -20,8 +20,6 @@ export declare enum GroupErrorCode {
20
20
  ACTION_NOT_IMPL = 1099,
21
21
  DUTY_NOT_ENABLED = 1020,
22
22
  NOT_DUTY_AGENT = 1021,
23
- DISPATCH_NOT_FOUND = 1022,
24
- INVALID_DECISION = 1023,
25
23
  AGENT_MD_NOT_FOUND = 1024,
26
24
  AGENT_MD_INVALID = 1025
27
25
  }
@@ -258,8 +256,8 @@ export declare const NOTIFY_GROUP_INVITE = "group_invite";
258
256
  export declare const NOTIFY_JOIN_APPROVED = "join_approved";
259
257
  export declare const NOTIFY_JOIN_REJECTED = "join_rejected";
260
258
  export declare const NOTIFY_JOIN_REQUEST_RECEIVED = "join_request_received";
259
+ export declare const NOTIFY_GROUP_MESSAGE = "group_message";
261
260
  export declare const NOTIFY_GROUP_EVENT = "group_event";
262
- export declare const NOTIFY_DUTY_DISPATCH = "duty_dispatch";
263
261
  export declare const EVENT_MEMBER_JOINED = "member_joined";
264
262
  export declare const EVENT_MEMBER_REMOVED = "member_removed";
265
263
  export declare const EVENT_MEMBER_LEFT = "member_left";
@@ -275,37 +273,13 @@ export declare const EVENT_MEMBER_UNBANNED = "member_unbanned";
275
273
  export declare const EVENT_JOIN_REQUIREMENTS_UPDATED = "join_requirements_updated";
276
274
  export declare const EVENT_INVITE_CODE_CREATED = "invite_code_created";
277
275
  export declare const EVENT_INVITE_CODE_REVOKED = "invite_code_revoked";
278
- export interface DutyMemberInfo {
279
- agent_id: string;
280
- agent_type: string;
281
- }
282
- export interface DutyContext {
283
- needs_dispatch: boolean;
284
- original_msg_id: number;
285
- sender_id: string;
286
- sender_type: string;
287
- group_member_count: number;
288
- online_ai_members: DutyMemberInfo[];
289
- human_members: DutyMemberInfo[];
290
- }
291
- export interface DispatchDecisionParams {
292
- original_msg_id: number;
293
- type: "broadcast" | "selective" | "suppress";
294
- hint?: string;
295
- reply_mode?: string;
296
- }
297
- export interface DispatchMetadata {
298
- type: string;
299
- hint: string;
300
- reply_mode: string;
301
- }
302
276
  export interface DutyConfig {
303
277
  mode: "none" | "fixed" | "rotation";
304
278
  rotation_strategy?: "round_robin" | "random";
305
279
  shift_duration_ms?: number;
306
280
  max_messages_per_shift?: number;
307
- dispatch_timeout_ms?: number;
308
- timeout_fallback?: "broadcast" | "next_duty";
281
+ duty_priority_window_ms?: number;
282
+ enable_rule_prelude?: boolean;
309
283
  agents?: string[];
310
284
  }
311
285
  export interface DutyState {
@@ -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.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_DUTY_DISPATCH = 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;
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_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;
8
8
  exports.buildGroupRequest = buildGroupRequest;
9
9
  exports.groupRequestToJson = groupRequestToJson;
10
10
  exports.parseGroupResponse = parseGroupResponse;
@@ -34,8 +34,6 @@ var GroupErrorCode;
34
34
  // Duty error codes
35
35
  GroupErrorCode[GroupErrorCode["DUTY_NOT_ENABLED"] = 1020] = "DUTY_NOT_ENABLED";
36
36
  GroupErrorCode[GroupErrorCode["NOT_DUTY_AGENT"] = 1021] = "NOT_DUTY_AGENT";
37
- GroupErrorCode[GroupErrorCode["DISPATCH_NOT_FOUND"] = 1022] = "DISPATCH_NOT_FOUND";
38
- GroupErrorCode[GroupErrorCode["INVALID_DECISION"] = 1023] = "INVALID_DECISION";
39
37
  GroupErrorCode[GroupErrorCode["AGENT_MD_NOT_FOUND"] = 1024] = "AGENT_MD_NOT_FOUND";
40
38
  GroupErrorCode[GroupErrorCode["AGENT_MD_INVALID"] = 1025] = "AGENT_MD_INVALID";
41
39
  })(GroupErrorCode || (exports.GroupErrorCode = GroupErrorCode = {}));
@@ -56,8 +54,6 @@ const CODE_MESSAGES = {
56
54
  1013: "broadcast conflict",
57
55
  1020: "duty not enabled",
58
56
  1021: "not duty agent",
59
- 1022: "dispatch not found",
60
- 1023: "invalid decision",
61
57
  1024: "agent.md not found",
62
58
  1025: "agent.md invalid",
63
59
  1099: "action not implemented",
@@ -133,8 +129,8 @@ exports.NOTIFY_GROUP_INVITE = "group_invite";
133
129
  exports.NOTIFY_JOIN_APPROVED = "join_approved";
134
130
  exports.NOTIFY_JOIN_REJECTED = "join_rejected";
135
131
  exports.NOTIFY_JOIN_REQUEST_RECEIVED = "join_request_received";
132
+ exports.NOTIFY_GROUP_MESSAGE = "group_message";
136
133
  exports.NOTIFY_GROUP_EVENT = "group_event";
137
- exports.NOTIFY_DUTY_DISPATCH = "duty_dispatch";
138
134
  // Group Event Type Constants
139
135
  exports.EVENT_MEMBER_JOINED = "member_joined";
140
136
  exports.EVENT_MEMBER_REMOVED = "member_removed";