acp-ts 1.1.6 → 1.1.7

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
@@ -132,6 +132,10 @@ declare class AgentCP implements IAgentCP {
132
132
  * 添加群组到本地存储
133
133
  */
134
134
  addGroupToStore(groupId: string, name: string): void;
135
+ /**
136
+ * 将加入的群组注册到 Home AP(内部方法)
137
+ */
138
+ registerGroupToHomeAP(groupId: string, groupUrl: string, role?: string): Promise<void>;
135
139
  /**
136
140
  * 从本地存储删除群组
137
141
  */
package/dist/agentcp.js CHANGED
@@ -412,8 +412,28 @@ class AgentCP {
412
412
  onGroupInvite(groupId, groupAddress, invitedBy) {
413
413
  console.log(`[Group][DefaultHandler] onGroupInvite: group=${groupId} address=${groupAddress} invitedBy=${invitedBy}`);
414
414
  },
415
- onJoinApproved(groupId, groupAddress) {
415
+ onJoinApproved: (groupId, groupAddress) => {
416
416
  console.log(`[Group][DefaultHandler] onJoinApproved: group=${groupId} address=${groupAddress}`);
417
+ (async () => {
418
+ try {
419
+ if (!this.groupOps || !this._groupTargetAid) {
420
+ console.warn(`[Group][DefaultHandler] onJoinApproved skipped: groupOps or targetAid not available`);
421
+ return;
422
+ }
423
+ let groupName = groupId;
424
+ try {
425
+ const info = await this.groupOps.getGroupInfo(this._groupTargetAid, groupId);
426
+ groupName = info.name || groupId;
427
+ }
428
+ catch (_) { }
429
+ this.addGroupToStore(groupId, groupName);
430
+ const groupUrl = groupAddress || `https://${this._groupTargetAid}/${groupId}`;
431
+ await this.registerGroupToHomeAP(groupId, groupUrl);
432
+ }
433
+ catch (e) {
434
+ console.error(`[Group][DefaultHandler] onJoinApproved processing failed: group=${groupId}`, e.message);
435
+ }
436
+ })();
417
437
  },
418
438
  onJoinRejected(groupId, reason) {
419
439
  console.log(`[Group][DefaultHandler] onJoinRejected: group=${groupId} reason=${reason}`);
@@ -533,6 +553,20 @@ class AgentCP {
533
553
  return;
534
554
  this.groupMessageStore.getOrCreateGroup(groupId, this._groupTargetAid, name);
535
555
  }
556
+ /**
557
+ * 将加入的群组注册到 Home AP(内部方法)
558
+ */
559
+ async registerGroupToHomeAP(groupId, groupUrl, role = 'member') {
560
+ if (!this.groupOps || !this._groupTargetAid)
561
+ return;
562
+ try {
563
+ await this.groupOps.registerMembership(this._groupTargetAid, groupId, groupUrl, this._groupTargetAid, this._groupSessionId, role);
564
+ console.log(`[Group] registerGroupToHomeAP success: group=${groupId}`);
565
+ }
566
+ catch (e) {
567
+ console.error(`[Group] registerGroupToHomeAP failed: group=${groupId}`, e.message);
568
+ }
569
+ }
536
570
  /**
537
571
  * 从本地存储删除群组
538
572
  */
package/dist/server.js CHANGED
@@ -241,6 +241,27 @@ async function ensureGroupClient(instance) {
241
241
  },
242
242
  onJoinApproved(groupId, groupAddress) {
243
243
  console.log(`[Group] onJoinApproved: group=${groupId} address=${groupAddress}`);
244
+ // 审核通过:获取群信息、添加本地存储、注册到 Home AP
245
+ (async () => {
246
+ try {
247
+ if (!instance.agentCP.groupOps) {
248
+ console.warn(`[Group] onJoinApproved skipped: groupOps not available`);
249
+ return;
250
+ }
251
+ let groupName = groupId;
252
+ try {
253
+ const info = await instance.agentCP.groupOps.getGroupInfo(instance.groupTargetAid, groupId);
254
+ groupName = info.name || groupId;
255
+ }
256
+ catch (_) { }
257
+ instance.agentCP.addGroupToStore(groupId, groupName);
258
+ const groupUrl = groupAddress || `https://${instance.groupTargetAid}/${groupId}`;
259
+ await instance.agentCP.registerGroupToHomeAP(groupId, groupUrl);
260
+ }
261
+ catch (e) {
262
+ console.error(`[Group] onJoinApproved processing failed: group=${groupId}`, e.message);
263
+ }
264
+ })();
244
265
  },
245
266
  onJoinRejected(groupId, reason) {
246
267
  console.log(`[Group] onJoinRejected: group=${groupId} reason=${reason}`);
@@ -453,19 +474,19 @@ const indexHtml = `<!DOCTYPE html>
453
474
  .container { background: white; padding: 32px; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); max-width: 560px; width: 100%; }
454
475
  h1 { color: #333; margin-bottom: 24px; text-align: center; font-size: 22px; }
455
476
  .hint { text-align: center; color: #999; font-size: 13px; margin-bottom: 20px; }
456
- .create-section { margin-bottom: 24px; }
457
- .create-section .aid-input-row { display: flex; gap: 8px; margin-bottom: 10px; align-items: center; }
477
+ .create-section { margin-bottom: 24px; display: flex; flex-direction: column; gap: 12px; }
478
+ .create-section .aid-input-row { display: flex; gap: 8px; align-items: center; }
458
479
  .create-section .aid-input-row input { flex: 1; padding: 10px 14px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px; min-width: 0; }
459
480
  .create-section .aid-input-row input:focus { outline: none; border-color: #007bff; }
460
481
  .create-section .aid-input-row .dot-separator { color: #999; font-size: 16px; flex-shrink: 0; }
461
- .create-section .aid-input-row select {
462
- padding: 10px 30px 10px 14px;
463
- border: 1px solid #ddd;
464
- border-radius: 8px;
465
- font-size: 14px;
466
- background: white;
467
- flex-shrink: 0;
468
- cursor: pointer;
482
+ .create-section .aid-input-row select {
483
+ padding: 10px 30px 10px 14px;
484
+ border: 1px solid #ddd;
485
+ border-radius: 8px;
486
+ font-size: 14px;
487
+ background: white;
488
+ flex-shrink: 0;
489
+ cursor: pointer;
469
490
  appearance: none;
470
491
  -webkit-appearance: none;
471
492
  -moz-appearance: none;
@@ -475,6 +496,9 @@ const indexHtml = `<!DOCTYPE html>
475
496
  background-size: 10px auto;
476
497
  }
477
498
  .create-section .aid-input-row select:focus { outline: none; border-color: #007bff; }
499
+ .create-section .extra-fields { display: flex; gap: 8px; }
500
+ .create-section .extra-fields input { flex: 1; padding: 10px 14px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px; min-width: 0; }
501
+ .create-section .extra-fields input:focus { outline: none; border-color: #007bff; }
478
502
  .btn { display: block; width: 100%; padding: 12px; border: none; border-radius: 8px; font-size: 15px; cursor: pointer; transition: background 0.2s; }
479
503
  .btn-primary { background: #007bff; color: white; }
480
504
  .btn-primary:hover { background: #0056b3; }
@@ -520,9 +544,9 @@ const indexHtml = `<!DOCTYPE html>
520
544
  <span class="dot-separator">.</span>
521
545
  <select id="apSelect"></select>
522
546
  </div>
523
- <div style="display:flex;gap:8px;margin-top:8px;">
524
- <input type="text" id="aidNickname" placeholder="昵称(选填)" style="flex:1;padding:8px 12px;border:1px solid #ddd;border-radius:6px;font-size:14px;">
525
- <input type="text" id="aidDescription" placeholder="描述(选填)" style="flex:2;padding:8px 12px;border:1px solid #ddd;border-radius:6px;font-size:14px;">
547
+ <div class="extra-fields">
548
+ <input type="text" id="aidNickname" placeholder="昵称(选填)">
549
+ <input type="text" id="aidDescription" placeholder="描述(选填)" style="flex:2;">
526
550
  </div>
527
551
  <button class="btn btn-primary" onclick="createAid()">注册 AID</button>
528
552
  </div>
@@ -901,6 +925,7 @@ const chatHtml = `<!DOCTYPE html>
901
925
  <div class="group-actions">
902
926
  <div class="gbtn" onclick="showCreateGroupModal()">创建群组</div>
903
927
  <div class="gbtn" onclick="showJoinGroupModal()">加入群组</div>
928
+ <div class="gbtn" onclick="showMyGroups()">我的群</div>
904
929
  </div>
905
930
  <div class="group-list" id="groupList"><div style="padding:20px;text-align:center;color:#999;font-size:12px;">暂无群组</div></div>
906
931
  </div>
@@ -1003,6 +1028,15 @@ const chatHtml = `<!DOCTYPE html>
1003
1028
  </div>
1004
1029
  </div>
1005
1030
  </div>
1031
+ <div class="modal-overlay" id="myGroupsModal">
1032
+ <div class="modal" style="max-width:560px;">
1033
+ <h3>我的群</h3>
1034
+ <div id="myGroupsContent" style="max-height:420px;overflow-y:auto;margin-bottom:16px;font-size:13px;"></div>
1035
+ <div class="modal-btns">
1036
+ <button class="mbtn mbtn-cancel" onclick="hideMyGroupsModal()">关闭</button>
1037
+ </div>
1038
+ </div>
1039
+ </div>
1006
1040
  <script>
1007
1041
  var S = { aid:'', sid:null, sessions:[], status:'disconnected', expanded:{}, sidebarOpen:true, aidList:[], closed:false, tab:'p2p', activeGroupId:null, groups:[], groupMsgs:[], groupTargetAid:'', isGroupCreator:false };
1008
1042
  var D = {};
@@ -1782,6 +1816,39 @@ const chatHtml = `<!DOCTYPE html>
1782
1816
  } catch(e){ alert('退出失败: '+e.message); }
1783
1817
  }
1784
1818
 
1819
+ // ============================================================
1820
+ // 我的群 Functions
1821
+ // ============================================================
1822
+ function showMyGroupsModal(){ $('myGroupsModal').classList.add('show'); }
1823
+ function hideMyGroupsModal(){ $('myGroupsModal').classList.remove('show'); }
1824
+ async function showMyGroups(){
1825
+ showMyGroupsModal();
1826
+ $('myGroupsContent').innerHTML='<div style="text-align:center;padding:20px;color:#999;">加载中...</div>';
1827
+ try {
1828
+ var r=await fetch('/api/group/my-groups');
1829
+ var d=await r.json();
1830
+ if(!d.success){ $('myGroupsContent').innerHTML='<div style="text-align:center;padding:20px;color:#e74c3c;">'+escH(d.error||'获取失败')+'</div>'; return; }
1831
+ var groups=d.groups||[];
1832
+ if(!groups.length){ $('myGroupsContent').innerHTML='<div style="text-align:center;padding:20px;color:#999;">暂无群组</div>'; return; }
1833
+ var html='<table style="width:100%;border-collapse:collapse;font-size:12px;">';
1834
+ html+='<tr style="background:#f8fafc;"><th style="padding:8px 6px;text-align:left;border-bottom:1px solid #e2e8f0;">群名称</th><th style="padding:8px 6px;text-align:left;border-bottom:1px solid #e2e8f0;">群ID</th><th style="padding:8px 6px;text-align:center;border-bottom:1px solid #e2e8f0;">角色</th><th style="padding:8px 6px;text-align:center;border-bottom:1px solid #e2e8f0;">状态</th></tr>';
1835
+ groups.forEach(function(g){
1836
+ var statusText=g.status===1?'正常':g.status===0?'待审核':'未知('+g.status+')';
1837
+ var statusColor=g.status===1?'#10b981':g.status===0?'#f59e0b':'#94a3b8';
1838
+ var shortId=g.group_id.length>16?g.group_id.substring(0,16)+'...':g.group_id;
1839
+ html+='<tr style="border-bottom:1px solid #f1f5f9;cursor:pointer;" onmouseover="this.style.background=\\'#f0f9ff\\'" onmouseout="this.style.background=\\'\\'">';
1840
+ html+='<td style="padding:8px 6px;font-weight:500;">'+escH(g.name||g.group_id)+'</td>';
1841
+ html+='<td style="padding:8px 6px;color:#64748b;" title="'+escH(g.group_id)+'">'+escH(shortId)+'</td>';
1842
+ html+='<td style="padding:8px 6px;text-align:center;">'+escH(g.role||'-')+'</td>';
1843
+ html+='<td style="padding:8px 6px;text-align:center;"><span style="color:'+statusColor+';font-weight:500;">'+escH(statusText)+'</span></td>';
1844
+ html+='</tr>';
1845
+ });
1846
+ html+='</table>';
1847
+ html+='<div style="margin-top:8px;font-size:11px;color:#94a3b8;text-align:right;">共 '+d.total+' 个群组</div>';
1848
+ $('myGroupsContent').innerHTML=html;
1849
+ } catch(e){ $('myGroupsContent').innerHTML='<div style="text-align:center;padding:20px;color:#e74c3c;">请求失败: '+escH(e.message)+'</div>'; }
1850
+ }
1851
+
1785
1852
  // 扩展轮询:群组模式下也轮询群消息
1786
1853
  var _origPoll=poll;
1787
1854
  poll=async function(){
@@ -2389,6 +2456,9 @@ async function handleRequest(req, res) {
2389
2456
  }
2390
2457
  catch (_) { }
2391
2458
  instance.agentCP.addGroupToStore(groupId, groupName);
2459
+ // 注册到 Home AP
2460
+ const registrationUrl = `https://${targetAid}/${groupId}`;
2461
+ await instance.agentCP.registerGroupToHomeAP(groupId, registrationUrl);
2392
2462
  sendJson(res, { success: true, group_id: groupId });
2393
2463
  }
2394
2464
  else {
@@ -2454,6 +2524,31 @@ async function handleRequest(req, res) {
2454
2524
  }
2455
2525
  return;
2456
2526
  }
2527
+ if (pathname === '/api/group/my-groups' && method === 'GET') {
2528
+ try {
2529
+ const instance = await ensureOnline();
2530
+ await ensureGroupClient(instance);
2531
+ const ops = instance.agentCP.groupOps;
2532
+ const target = instance.groupTargetAid;
2533
+ const result = await ops.listMyGroups(target);
2534
+ // 尝试获取每个群的详细信息(名称等)
2535
+ const groups = [];
2536
+ for (const m of result.groups) {
2537
+ let name = m.group_id;
2538
+ try {
2539
+ const info = await ops.getGroupInfo(target, m.group_id);
2540
+ name = info.name || m.group_id;
2541
+ }
2542
+ catch (_) { }
2543
+ groups.push(Object.assign(Object.assign({}, m), { name }));
2544
+ }
2545
+ sendJson(res, { success: true, groups, total: result.total });
2546
+ }
2547
+ catch (e) {
2548
+ sendJson(res, { success: false, error: e.message, groups: [] });
2549
+ }
2550
+ return;
2551
+ }
2457
2552
  if (pathname === '/api/group/leave' && method === 'POST') {
2458
2553
  try {
2459
2554
  const body = await parseBody(req);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "acp-ts",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "description": "基于 ACP智能体通信协议 的智能体通信库,提供智能体身份管理和实时通信功能",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",