@xfxstudio/claworld 0.2.8 → 0.2.10-beta.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.
Files changed (50) hide show
  1. package/README.md +1 -1
  2. package/openclaw.plugin.json +7 -63
  3. package/package.json +6 -2
  4. package/skills/claworld-help/SKILL.md +7 -3
  5. package/skills/claworld-join-and-chat/SKILL.md +38 -9
  6. package/skills/claworld-manage-worlds/SKILL.md +81 -10
  7. package/src/lib/agent-profile.js +8 -3
  8. package/src/lib/chat-request.js +19 -1
  9. package/src/lib/policy.js +2 -6
  10. package/src/lib/public-identity.js +175 -0
  11. package/src/lib/relay/kickoff-text.js +7 -1
  12. package/src/openclaw/installer/cli.js +46 -1
  13. package/src/openclaw/installer/constants.js +1 -0
  14. package/src/openclaw/installer/core.js +234 -3
  15. package/src/openclaw/installer/doctor.js +2 -2
  16. package/src/openclaw/plugin/account-identity.js +1 -2
  17. package/src/openclaw/plugin/claworld-channel-plugin.js +302 -266
  18. package/src/openclaw/plugin/config-schema.js +9 -23
  19. package/src/openclaw/plugin/managed-config.js +284 -79
  20. package/src/openclaw/plugin/onboarding.js +22 -42
  21. package/src/openclaw/plugin/register.js +144 -25
  22. package/src/openclaw/plugin/relay-client.js +237 -18
  23. package/src/openclaw/runtime/backend-error-context.js +91 -0
  24. package/src/openclaw/runtime/feedback-helper.js +1 -2
  25. package/src/openclaw/runtime/product-shell-helper.js +43 -9
  26. package/src/openclaw/runtime/tool-contracts.js +65 -3
  27. package/src/openclaw/runtime/tool-inventory.js +8 -1
  28. package/src/openclaw/runtime/world-moderation-helper.js +3 -19
  29. package/src/product-shell/contracts/candidate-feed.js +7 -0
  30. package/src/product-shell/contracts/world-manifest.js +0 -1
  31. package/src/product-shell/contracts/world-orchestration.js +10 -1
  32. package/src/product-shell/conversation-feedback/conversation-feedback-service.js +261 -0
  33. package/src/product-shell/feedback/feedback-routes.js +0 -1
  34. package/src/product-shell/feedback/feedback-service.js +4 -9
  35. package/src/product-shell/index.js +40 -7
  36. package/src/product-shell/matching/matchmaking-service.js +22 -1
  37. package/src/product-shell/membership/membership-service.js +5 -1
  38. package/src/product-shell/onboarding/onboarding-service.js +10 -21
  39. package/src/product-shell/profile/public-identity-routes.js +60 -0
  40. package/src/product-shell/profile/public-identity-service.js +190 -0
  41. package/src/product-shell/search/search-service.js +9 -2
  42. package/src/product-shell/social/chat-request-routes.js +4 -1
  43. package/src/product-shell/social/chat-request-service.js +184 -22
  44. package/src/product-shell/social/friend-routes.js +1 -1
  45. package/src/product-shell/social/friend-service.js +16 -19
  46. package/src/product-shell/social/social-routes.js +2 -2
  47. package/src/product-shell/social/social-service.js +31 -35
  48. package/src/product-shell/worlds/world-admin-service.js +31 -10
  49. package/src/product-shell/worlds/world-broadcast-service.js +2 -2
  50. package/src/lib/agent-address.js +0 -46
@@ -1,4 +1,6 @@
1
1
  import { normalizeAgentProfile, resolveAgentDisplayName, resolveAgentVisibility } from '../../lib/agent-profile.js';
2
+ import { normalizeChatRequestInput } from '../../lib/chat-request.js';
3
+ import { resolvePublicIdentity } from '../../lib/public-identity.js';
2
4
  import { createKickoffBrief, resolveStoredKickoffBrief } from '../../lib/relay/kickoff-text.js';
3
5
  import { WORLD_ACTIONS } from '../worlds/world-authorization.js';
4
6
  import { normalizeChatRequestApprovalPolicy } from '../contracts/chat-request-approval-policy.js';
@@ -66,7 +68,7 @@ function createAgentNotFoundError(agentId) {
66
68
  return error;
67
69
  }
68
70
 
69
- function createTargetAddressNotFoundError(targetAgentId) {
71
+ function createTargetAgentNotFoundError(targetAgentId) {
70
72
  const error = new Error(`chat_request_target_not_found:${targetAgentId}`);
71
73
  error.code = 'chat_request_target_not_found';
72
74
  error.status = 404;
@@ -123,10 +125,8 @@ function projectAgent(store, agentId, presence = null) {
123
125
  const presenceState = presence?.getPresence?.(agent.agentId) || store.getPresence(agent.agentId);
124
126
  return {
125
127
  agentId: agent.agentId,
126
- agentCode: agent.agentCode,
127
- domain: agent.domain,
128
- address: agent.address,
129
128
  displayName: resolveAgentDisplayName(agent),
129
+ publicIdentity: resolvePublicIdentity(agent),
130
130
  profile: normalizeAgentProfile(agent.profile),
131
131
  discoverable: visibility.discoverable,
132
132
  contactable: visibility.contactable,
@@ -281,12 +281,100 @@ function projectChatRequestOrigin(request = {}) {
281
281
  };
282
282
  }
283
283
 
284
+ function hasConversationScope(conversation = null) {
285
+ return Boolean(conversation && typeof conversation === 'object' && !Array.isArray(conversation) && Object.keys(conversation).length > 0);
286
+ }
287
+
288
+ function resolveConversationLinkRequest(requests = [], conversation = {}) {
289
+ const conversationMeta = conversation?.meta && typeof conversation.meta === 'object' && !Array.isArray(conversation.meta)
290
+ ? conversation.meta
291
+ : {};
292
+ const approvalRequestId = normalizeText(conversationMeta.approvalRequestId, null);
293
+ if (approvalRequestId) {
294
+ return requests.find((request) => normalizeText(request.chatRequestId || request.requestId, null) === approvalRequestId) || null;
295
+ }
296
+
297
+ const conversationKey = normalizeText(conversation?.conversationKey, null);
298
+ if (!conversationKey) return null;
299
+
300
+ return requests.find((request) => {
301
+ const kickoff = request?.kickoff && typeof request.kickoff === 'object' && !Array.isArray(request.kickoff)
302
+ ? request.kickoff
303
+ : {};
304
+ return normalizeText(kickoff.conversationKey, null) === conversationKey
305
+ || normalizeText(request?.conversation?.conversationKey, null) === conversationKey;
306
+ }) || null;
307
+ }
308
+
309
+ function resolveInboxChatDirection(viewerAgentId, request = null) {
310
+ if (!request) return null;
311
+ if (viewerAgentId === request.fromAgentId) return 'outbound';
312
+ if (viewerAgentId === request.toAgentId) return 'inbound';
313
+ return 'related';
314
+ }
315
+
316
+ function resolveInboxChatCounterpartyAgentId(viewerAgentId, request = null, conversation = null) {
317
+ if (request) {
318
+ if (viewerAgentId === request.fromAgentId) return request.toAgentId;
319
+ if (viewerAgentId === request.toAgentId) return request.fromAgentId;
320
+ }
321
+
322
+ const participantIds = Array.isArray(conversation?.participantIds) ? conversation.participantIds : [];
323
+ return participantIds.find((participantId) => participantId && participantId !== viewerAgentId) || null;
324
+ }
325
+
326
+ function resolveInboxChatStatus(conversation = {}, request = null) {
327
+ const kickoffStatus = normalizeText(request?.kickoff?.status, null);
328
+ if (kickoffStatus === 'sent') return 'opening';
329
+ if (kickoffStatus === 'kept_silent') return 'silent';
330
+ if (kickoffStatus === 'failed') return 'kickoff_failed';
331
+ const conversationStatus = normalizeText(conversation?.status, 'active');
332
+ if (conversationStatus === 'active') return 'active';
333
+ if (conversationStatus === 'closed') return 'ended';
334
+ return conversationStatus;
335
+ }
336
+
337
+ function resolveInboxConversationWorldSummary(worldService, request = {}, conversation = {}) {
338
+ const requestContext = request?.requestContext && typeof request.requestContext === 'object' && !Array.isArray(request.requestContext)
339
+ ? request.requestContext
340
+ : {};
341
+ const requestConversation = request?.conversation && typeof request.conversation === 'object' && !Array.isArray(request.conversation)
342
+ ? request.conversation
343
+ : {};
344
+ const conversationMeta = conversation?.meta && typeof conversation.meta === 'object' && !Array.isArray(conversation.meta)
345
+ ? conversation.meta
346
+ : {};
347
+ const worldMeta = conversationMeta.world && typeof conversationMeta.world === 'object' && !Array.isArray(conversationMeta.world)
348
+ ? conversationMeta.world
349
+ : {};
350
+ const worldId = normalizeConversationWorldId(requestConversation.worldId)
351
+ || normalizeConversationWorldId(requestContext.conversation?.worldId)
352
+ || normalizeConversationWorldId(worldMeta.worldId)
353
+ || normalizeConversationWorldId(conversationMeta.worldId);
354
+
355
+ if (!worldId) {
356
+ return {
357
+ mode: 'direct',
358
+ worldId: null,
359
+ world: null,
360
+ };
361
+ }
362
+
363
+ return {
364
+ mode: 'world',
365
+ worldId,
366
+ world: projectWorldSummary(worldService, worldId),
367
+ };
368
+ }
369
+
284
370
  export function createChatRequestService({
285
371
  store = null,
286
372
  relay = null,
287
373
  presence = null,
288
374
  worldService = null,
289
375
  worldAuthorizationService = null,
376
+ publicIdentityService = null,
377
+ conversationFeedbackService = null,
290
378
  } = {}) {
291
379
  function assertStore() {
292
380
  if (!store) throw createConfigurationError('chat_request_store_unavailable');
@@ -350,8 +438,37 @@ export function createChatRequestService({
350
438
  };
351
439
  }
352
440
 
441
+ function projectChatInboxChat(conversation = {}, viewerAgentId = null, request = null) {
442
+ const direction = resolveInboxChatDirection(viewerAgentId, request);
443
+ const counterpartyAgentId = resolveInboxChatCounterpartyAgentId(viewerAgentId, request, conversation);
444
+ const feedbackSummary = conversationFeedbackService?.summarizeConversation?.({
445
+ conversationKey: conversation.conversationKey,
446
+ viewerAgentId,
447
+ }) || {
448
+ likeCount: 0,
449
+ dislikeCount: 0,
450
+ viewerGave: null,
451
+ viewerReceived: null,
452
+ };
453
+
454
+ return {
455
+ chatRequestId: normalizeText(request?.chatRequestId || request?.requestId, null),
456
+ status: resolveInboxChatStatus(conversation, request),
457
+ ...(direction ? { direction } : {}),
458
+ createdAt: normalizeText(conversation.createdAt, normalizeText(request?.createdAt, null)),
459
+ updatedAt: normalizeText(conversation.updatedAt, null),
460
+ lastTurnAt: normalizeText(conversation.lastTurnAt, null),
461
+ conversationKey: normalizeText(conversation.conversationKey, null),
462
+ localSessionKey: normalizeText(conversation.sessionKey, null),
463
+ counterparty: projectAgent(assertStore(), counterpartyAgentId, presence),
464
+ conversation: resolveInboxConversationWorldSummary(worldService, request, conversation),
465
+ feedbackSummary,
466
+ };
467
+ }
468
+
353
469
  return {
354
470
  projectChatRequest,
471
+ projectChatInboxChat,
355
472
  async syncApprovalPolicy({
356
473
  actorAgentId,
357
474
  credentialId = null,
@@ -389,39 +506,51 @@ export function createChatRequestService({
389
506
  openingMessage = null,
390
507
  openingPayload = null,
391
508
  worldId = null,
509
+ requestContext = null,
392
510
  origin = null,
393
511
  broadcast = null,
394
512
  source = 'chat_request',
395
513
  } = {}) {
396
514
  requireAgent(fromAgentId);
515
+ publicIdentityService?.assertPublicIdentityReady?.({
516
+ agentId: fromAgentId,
517
+ capability: 'request chat',
518
+ });
397
519
  const normalizedTargetAgentId = normalizeText(targetAgentId, null);
398
520
  if (!normalizedTargetAgentId) {
399
521
  throw createInvalidChatRequestError('chat_request_target_required', 'chat request target requires targetAgentId');
400
522
  }
401
523
  const targetAgent = requireAgent(normalizedTargetAgentId);
402
- const normalizedWorldId = normalizeConversationWorldId(worldId);
403
- if (!targetAgent?.address) {
404
- throw createTargetAddressNotFoundError(normalizedTargetAgentId);
524
+ const normalizedSource = normalizeText(source, 'chat_request');
525
+ const normalizedRequestInput = normalizeChatRequestInput({
526
+ requestContext,
527
+ source: normalizedSource,
528
+ });
529
+ const normalizedWorldId = normalizeConversationWorldId(worldId)
530
+ || normalizeConversationWorldId(normalizedRequestInput.conversation?.worldId);
531
+ if (!targetAgent?.agentId) {
532
+ throw createTargetAgentNotFoundError(normalizedTargetAgentId);
405
533
  }
406
- const normalizedOpeningPayload = cloneJsonObject(openingPayload);
534
+ const normalizedOpeningPayload = cloneJsonObject(openingPayload) || cloneJsonObject(normalizedRequestInput.openingPayload);
407
535
  const normalizedKickoffBrief = createKickoffBrief({
408
536
  text: typeof kickoffBrief === 'object' && kickoffBrief !== null && !Array.isArray(kickoffBrief)
409
537
  ? kickoffBrief.text
410
- : openingMessage,
538
+ : normalizeText(openingMessage, normalizeText(normalizedRequestInput.openingMessage, null)),
411
539
  payload: typeof kickoffBrief === 'object' && kickoffBrief !== null && !Array.isArray(kickoffBrief)
412
540
  ? kickoffBrief.payload
413
541
  : normalizedOpeningPayload,
414
542
  source: typeof kickoffBrief === 'object' && kickoffBrief !== null && !Array.isArray(kickoffBrief)
415
543
  ? kickoffBrief.source
416
- : source === 'world_broadcast'
544
+ : normalizedSource === 'world_broadcast'
417
545
  ? 'world_broadcast_brief'
418
546
  : 'chat_request_brief',
419
547
  });
420
- const normalizedOrigin = normalizeChatRequestOrigin(origin);
421
- const normalizedBroadcast = normalizeChatRequestBroadcastMetadata(broadcast);
548
+ const normalizedOrigin = normalizeChatRequestOrigin(origin) || normalizeChatRequestOrigin(normalizedRequestInput.origin);
549
+ const normalizedBroadcast = normalizeChatRequestBroadcastMetadata(broadcast)
550
+ || normalizeChatRequestBroadcastMetadata(normalizedRequestInput.broadcast);
422
551
  if (normalizedWorldId) {
423
552
  worldService?.requireWorld?.(normalizedWorldId);
424
- if (normalizeText(source, 'chat_request') !== 'world_broadcast') {
553
+ if (normalizedSource !== 'world_broadcast') {
425
554
  const authorization = worldAuthorizationService.evaluateWorldAction({
426
555
  worldId: normalizedWorldId,
427
556
  actorAgentId: fromAgentId,
@@ -435,7 +564,7 @@ export function createChatRequestService({
435
564
 
436
565
  const result = await assertRelay('createChatRequest').createChatRequest({
437
566
  fromAgentId,
438
- toAddress: targetAgent.address,
567
+ targetAgentId: targetAgent.agentId,
439
568
  kickoffBrief: normalizedKickoffBrief,
440
569
  openingMessage: normalizeText(
441
570
  normalizedKickoffBrief?.text,
@@ -445,9 +574,10 @@ export function createChatRequestService({
445
574
  conversation: {
446
575
  ...(normalizedWorldId ? { worldId: normalizedWorldId } : {}),
447
576
  },
577
+ requestContext: cloneJsonObject(requestContext),
448
578
  origin: normalizedOrigin,
449
579
  broadcast: normalizedBroadcast,
450
- source: normalizeText(source, 'chat_request'),
580
+ source: normalizedSource,
451
581
  });
452
582
  if (result.status < 200 || result.status >= 300) {
453
583
  throw createRelayResponseError(result, 'chat_request_create_failed');
@@ -495,23 +625,55 @@ export function createChatRequestService({
495
625
  };
496
626
  },
497
627
 
498
- listChatRequests({ agentId, direction = null } = {}) {
628
+ listChatInbox({ agentId, direction = null } = {}) {
499
629
  requireAgent(agentId);
500
630
  const normalizedDirection = normalizeDirection(direction);
501
- let items = assertStore().listChatRequests ? assertStore().listChatRequests() : [];
502
- items = items.filter((request) => request.status === 'pending');
503
- items = items.filter((request) => request.fromAgentId === agentId || request.toAgentId === agentId);
631
+ let requests = assertStore().listChatRequests ? assertStore().listChatRequests() : [];
632
+ requests = requests.filter((request) => request.fromAgentId === agentId || request.toAgentId === agentId);
504
633
  if (normalizedDirection === 'inbound') {
505
- items = items.filter((request) => request.toAgentId === agentId);
634
+ requests = requests.filter((request) => request.toAgentId === agentId);
506
635
  } else if (normalizedDirection === 'outbound') {
507
- items = items.filter((request) => request.fromAgentId === agentId);
636
+ requests = requests.filter((request) => request.fromAgentId === agentId);
508
637
  }
509
638
 
639
+ const pendingRequests = sortByRecency(
640
+ requests.filter((request) => request.status === 'pending'),
641
+ 'createdAt',
642
+ ).map((request) => projectChatRequest(request, agentId));
643
+
644
+ const conversations = assertStore().listConversations
645
+ ? assertStore().listConversations({ participantId: agentId })
646
+ : [];
647
+ const chats = sortByRecency(
648
+ conversations
649
+ .map((conversation) => {
650
+ const linkedRequest = resolveConversationLinkRequest(requests, conversation);
651
+ if (!linkedRequest && !normalizeText(conversation?.meta?.approvalRequestId, null)) return null;
652
+ const projected = projectChatInboxChat(conversation, agentId, linkedRequest);
653
+ if (!projected) return null;
654
+ if (normalizedDirection && projected.direction !== normalizedDirection) return null;
655
+ return projected;
656
+ })
657
+ .filter(Boolean),
658
+ 'lastTurnAt',
659
+ 'updatedAt',
660
+ 'createdAt',
661
+ );
662
+
510
663
  return {
511
- items: sortByRecency(items, 'createdAt').map((request) => projectChatRequest(request, agentId)),
664
+ counts: {
665
+ pendingRequestCount: pendingRequests.length,
666
+ chatCount: chats.length,
667
+ },
668
+ pendingRequests,
669
+ chats,
512
670
  };
513
671
  },
514
672
 
673
+ listChatRequests({ agentId, direction = null } = {}) {
674
+ return this.listChatInbox({ agentId, direction });
675
+ },
676
+
515
677
  async acceptChatRequest(chatRequestId, { actorAgentId } = {}) {
516
678
  requireAgent(actorAgentId);
517
679
  const normalizedChatRequestId = normalizeText(chatRequestId, null);
@@ -12,7 +12,7 @@ export function registerFriendRoutes(app, { friendService }) {
12
12
  try {
13
13
  const result = await friendService.createFriendRequest({
14
14
  fromAgentId: req.body?.fromAgentId,
15
- toAddress: req.body?.toAddress,
15
+ targetAgentId: req.body?.targetAgentId,
16
16
  message: req.body?.message,
17
17
  metadata: req.body?.metadata,
18
18
  });
@@ -1,16 +1,12 @@
1
1
  import { normalizeAgentProfile, resolveAgentDisplayName, resolveAgentVisibility } from '../../lib/agent-profile.js';
2
2
  import { createRelayPolicyHooks, evaluatePolicyHook } from '../../lib/policy.js';
3
+ import { resolvePublicIdentity } from '../../lib/public-identity.js';
3
4
 
4
5
  function normalizeAgentId(agentId) {
5
6
  const normalized = String(agentId || '').trim();
6
7
  return normalized || null;
7
8
  }
8
9
 
9
- function normalizeAddress(address) {
10
- const normalized = String(address || '').trim().toLowerCase();
11
- return normalized || null;
12
- }
13
-
14
10
  function normalizeDirection(direction) {
15
11
  const normalized = String(direction || '').trim().toLowerCase();
16
12
  return normalized === 'inbound' || normalized === 'outbound' ? normalized : null;
@@ -54,8 +50,8 @@ function createAgentNotFoundError(agentId) {
54
50
  return error;
55
51
  }
56
52
 
57
- function createTargetNotFoundError(address) {
58
- const error = new Error(`friend_target_not_found:${address}`);
53
+ function createTargetNotFoundError(targetAgentId) {
54
+ const error = new Error(`friend_target_not_found:${targetAgentId}`);
59
55
  error.code = 'friend_target_not_found';
60
56
  error.status = 404;
61
57
  return error;
@@ -131,10 +127,8 @@ function projectAgent(store, agentId) {
131
127
  const visibility = resolveAgentVisibility(agent);
132
128
  return {
133
129
  agentId: agent.agentId,
134
- agentCode: agent.agentCode,
135
- domain: agent.domain,
136
- address: agent.address,
137
130
  displayName: resolveAgentDisplayName(agent),
131
+ publicIdentity: resolvePublicIdentity(agent),
138
132
  profile: normalizeAgentProfile(agent.profile),
139
133
  discoverable: visibility.discoverable,
140
134
  contactable: visibility.contactable,
@@ -149,7 +143,7 @@ function resolvePeerAgentId(friendship, viewerAgentId) {
149
143
  return null;
150
144
  }
151
145
 
152
- export function createFriendService({ store = null, policy = null } = {}) {
146
+ export function createFriendService({ store = null, policy = null, publicIdentityService = null } = {}) {
153
147
  const relayPolicy = createRelayPolicyHooks(policy);
154
148
 
155
149
  function assertStore() {
@@ -307,23 +301,27 @@ export function createFriendService({ store = null, policy = null } = {}) {
307
301
  }
308
302
 
309
303
  return {
310
- async createFriendRequest({ fromAgentId, toAddress, message = null, metadata = {} } = {}) {
304
+ async createFriendRequest({ fromAgentId, targetAgentId, message = null, metadata = {} } = {}) {
311
305
  const friendshipStore = assertStore();
312
306
  const fromAgent = requireAgent(fromAgentId);
313
- const normalizedToAddress = normalizeAddress(toAddress);
314
- if (!normalizedToAddress) {
315
- throw createTargetNotFoundError(toAddress);
307
+ publicIdentityService?.assertPublicIdentityReady?.({
308
+ agentId: fromAgent.agentId,
309
+ capability: 'send friend request',
310
+ });
311
+ const normalizedTargetAgentId = normalizeAgentId(targetAgentId);
312
+ if (!normalizedTargetAgentId) {
313
+ throw createTargetNotFoundError(targetAgentId);
316
314
  }
317
315
 
318
- const toAgent = friendshipStore.resolveAddress(normalizedToAddress);
319
- if (!toAgent) throw createTargetNotFoundError(normalizedToAddress);
316
+ const toAgent = friendshipStore.getAgent(normalizedTargetAgentId);
317
+ if (!toAgent) throw createTargetNotFoundError(normalizedTargetAgentId);
320
318
 
321
319
  const canRequest = evaluatePolicyHook({
322
320
  hook: relayPolicy.canRequest,
323
321
  context: {
324
322
  fromAgentId: fromAgent.agentId,
325
323
  fromAgent,
326
- toAddress: normalizedToAddress,
324
+ targetAgentId: normalizedTargetAgentId,
327
325
  toAgent,
328
326
  requestContext: {
329
327
  type: 'friend_request',
@@ -382,7 +380,6 @@ export function createFriendService({ store = null, policy = null } = {}) {
382
380
  const request = await friendshipStore.createFriendRequest({
383
381
  fromAgentId: fromAgent.agentId,
384
382
  toAgentId: toAgent.agentId,
385
- toAddress: toAgent.address,
386
383
  message: normalizeMessage(message),
387
384
  metadata,
388
385
  });
@@ -10,8 +10,8 @@ function sendSocialError(res, error) {
10
10
  export function registerSocialRoutes(app, { socialService }) {
11
11
  app.get('/v1/social/agents/lookup', (req, res) => {
12
12
  try {
13
- const result = socialService.lookupAgentByCode({
14
- agentCode: req.query.agentCode,
13
+ const result = socialService.lookupAgentByIdentity({
14
+ identity: req.query.identity,
15
15
  });
16
16
  res.json(result);
17
17
  } catch (error) {
@@ -3,7 +3,7 @@ import {
3
3
  resolveAgentDisplayName,
4
4
  resolveAgentVisibility,
5
5
  } from '../../lib/agent-profile.js';
6
- import { parseAgentHandle } from '../../lib/agent-address.js';
6
+ import { parsePublicIdentityDisplay, resolvePublicIdentity } from '../../lib/public-identity.js';
7
7
 
8
8
  function normalizeText(value, fallback = null) {
9
9
  if (value == null) return fallback;
@@ -11,18 +11,6 @@ function normalizeText(value, fallback = null) {
11
11
  return normalized || fallback;
12
12
  }
13
13
 
14
- function parseCanonicalAgentCode(value) {
15
- const parsed = parseAgentHandle(value);
16
- if (!parsed?.canonical) return null;
17
-
18
- return {
19
- agentCode: parsed.address,
20
- relayLocalCode: parsed.localPart,
21
- domain: parsed.domain,
22
- address: parsed.address,
23
- };
24
- }
25
-
26
14
  function createConfigurationError() {
27
15
  const error = new Error('social_lookup_store_unavailable');
28
16
  error.code = 'social_lookup_store_unavailable';
@@ -30,44 +18,44 @@ function createConfigurationError() {
30
18
  return error;
31
19
  }
32
20
 
33
- function createInvalidAgentCodeError(agentCode) {
34
- const error = new Error('invalid_agent_code');
35
- error.code = 'invalid_agent_code';
21
+ function createInvalidPublicIdentityError(identity) {
22
+ const error = new Error('invalid_public_identity');
23
+ error.code = 'invalid_public_identity';
36
24
  error.status = 400;
37
25
  error.responseBody = {
38
26
  error: error.code,
39
- message: 'agentCode must use canonical local@namespace schema',
40
- agentCode: normalizeText(agentCode, null),
27
+ message: 'identity must use displayName#code',
28
+ identity: normalizeText(identity, null),
41
29
  fieldErrors: [
42
30
  {
43
- fieldId: 'agentCode',
44
- message: 'agentCode must use canonical local@namespace schema',
31
+ fieldId: 'identity',
32
+ message: 'identity must use displayName#code',
45
33
  },
46
34
  ],
47
35
  };
48
36
  return error;
49
37
  }
50
38
 
51
- function createAgentNotFoundError(agentCode) {
52
- const error = new Error(`agent_not_found:${agentCode}`);
39
+ function createAgentNotFoundError(identity) {
40
+ const error = new Error(`agent_not_found:${identity}`);
53
41
  error.code = 'agent_not_found';
54
42
  error.status = 404;
55
43
  error.responseBody = {
56
44
  error: error.code,
57
- message: 'no agent found for canonical agentCode',
58
- agentCode,
45
+ message: 'no agent found for public identity',
46
+ identity,
59
47
  };
60
48
  return error;
61
49
  }
62
50
 
63
- function createNotDiscoverableError(agentCode) {
64
- const error = new Error(`not_discoverable:${agentCode}`);
51
+ function createNotDiscoverableError(identity) {
52
+ const error = new Error(`not_discoverable:${identity}`);
65
53
  error.code = 'not_discoverable';
66
54
  error.status = 403;
67
55
  error.responseBody = {
68
56
  error: error.code,
69
57
  message: 'agent is not discoverable',
70
- agentCode,
58
+ identity,
71
59
  };
72
60
  return error;
73
61
  }
@@ -94,21 +82,27 @@ export function createSocialService({ worldService, store = null } = {}) {
94
82
  }
95
83
 
96
84
  return {
97
- lookupAgentByCode({ agentCode } = {}) {
85
+ lookupAgentByIdentity({ identity } = {}) {
98
86
  const socialStore = assertStore();
99
- const parsedAgentCode = parseCanonicalAgentCode(agentCode);
100
- if (!parsedAgentCode) {
101
- throw createInvalidAgentCodeError(agentCode);
87
+ const parsedIdentity = parsePublicIdentityDisplay(identity);
88
+ if (!parsedIdentity) {
89
+ throw createInvalidPublicIdentityError(identity);
102
90
  }
103
91
 
104
- const agent = socialStore.resolveAddress(parsedAgentCode.address);
92
+ const agent = socialStore
93
+ .listAgents()
94
+ .find((candidate) => {
95
+ const candidateIdentity = resolvePublicIdentity(candidate);
96
+ return candidateIdentity.status === 'ready'
97
+ && candidateIdentity.code === parsedIdentity.code;
98
+ }) || null;
105
99
  if (!agent) {
106
- throw createAgentNotFoundError(parsedAgentCode.agentCode);
100
+ throw createAgentNotFoundError(parsedIdentity.identity);
107
101
  }
108
102
 
109
103
  const visibility = resolveAgentVisibility(agent);
110
104
  if (!visibility.discoverable) {
111
- throw createNotDiscoverableError(parsedAgentCode.agentCode);
105
+ throw createNotDiscoverableError(parsedIdentity.identity);
112
106
  }
113
107
 
114
108
  const activeWorlds = socialStore
@@ -124,8 +118,10 @@ export function createSocialService({ worldService, store = null } = {}) {
124
118
  return {
125
119
  status: 'found',
126
120
  publicProfile: {
127
- agentCode: agent.address || parsedAgentCode.agentCode,
121
+ agentId: agent.agentId,
122
+ identity: resolvePublicIdentity(agent).displayIdentity || parsedIdentity.identity,
128
123
  displayName: resolveAgentDisplayName(agent),
124
+ code: resolvePublicIdentity(agent).code,
129
125
  profile: normalizeAgentProfile(agent.profile),
130
126
  discoverable: visibility.discoverable,
131
127
  contactable: visibility.contactable,