@xfxstudio/claworld 2026.4.27-testing.1 → 2026.4.28-testing

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.
@@ -3,7 +3,7 @@ import { buildRuntimeAuthHeaders } from '../plugin/account-identity.js';
3
3
  import { createRuntimeBoundaryError } from '../../lib/runtime-errors.js';
4
4
  import { extractBackendErrorContext } from './backend-error-context.js';
5
5
  import {
6
- buildWorldSelectionPrompt as buildBackendWorldSelectionPrompt,
6
+ buildCandidateDeliverySummary as buildBackendCandidateDeliverySummary,
7
7
  resolveWorldSelection as resolveBackendWorldSelection,
8
8
  } from '../../product-shell/contracts/world-orchestration.js';
9
9
 
@@ -203,6 +203,12 @@ function normalizeWorldDetail(payload = {}) {
203
203
  };
204
204
  }
205
205
 
206
+ function normalizeNumber(value, fallback = null) {
207
+ const parsed = Number(value);
208
+ if (!Number.isFinite(parsed)) return fallback;
209
+ return parsed;
210
+ }
211
+
206
212
  function normalizeProfileSummaryField(field = {}, index = 0) {
207
213
  const fieldId = normalizeText(field.fieldId || field.id, `field_${index + 1}`);
208
214
  const value = Array.isArray(field.value)
@@ -220,7 +226,7 @@ function normalizeProfileSummaryField(field = {}, index = 0) {
220
226
  };
221
227
  }
222
228
 
223
- function normalizeMemberProfileSummary(summary = {}) {
229
+ function normalizeCandidateProfileSummary(summary = {}) {
224
230
  return {
225
231
  displayName: normalizeText(summary.displayName, null),
226
232
  headline: normalizeText(summary.headline, null),
@@ -259,6 +265,102 @@ function normalizeBroadcastConfig(broadcast = null) {
259
265
  };
260
266
  }
261
267
 
268
+ function normalizeCompatibilitySignal(signal = {}, index = 0) {
269
+ return {
270
+ signalId: normalizeText(signal.signalId, `signal_${index + 1}`),
271
+ type: normalizeText(signal.type, 'world_ready'),
272
+ fieldIds: normalizeStringList(signal.fieldIds),
273
+ score: normalizeNumber(signal.score, 0),
274
+ summary: normalizeText(signal.summary, ''),
275
+ };
276
+ }
277
+
278
+ function normalizeDeliveryReason(reason = {}) {
279
+ return {
280
+ code: normalizeText(reason.code, null),
281
+ matchedFieldIds: normalizeStringList(reason.matchedFieldIds),
282
+ summary: normalizeText(reason.summary, ''),
283
+ };
284
+ }
285
+
286
+ function normalizeCandidate(candidate = {}, index = 0) {
287
+ const normalizedRank = normalizeNumber(candidate.rank, null);
288
+ const displayName = normalizeText(
289
+ candidate.displayName || candidate.profileSummary?.displayName || candidate.requestChat?.displayName,
290
+ null,
291
+ );
292
+ const agentCode = normalizeText(
293
+ candidate.agentCode || candidate.requestChat?.agentCode,
294
+ null,
295
+ )?.toUpperCase() || null;
296
+ const requestChat = displayName && agentCode
297
+ ? {
298
+ worldId: normalizeText(candidate.requestChat?.worldId, normalizeText(candidate.worldId, 'unknown-world')),
299
+ displayName,
300
+ agentCode,
301
+ }
302
+ : null;
303
+
304
+ return {
305
+ candidateId: normalizeText(candidate.candidateId, `candidate_${index + 1}`),
306
+ worldId: normalizeText(candidate.worldId, 'unknown-world'),
307
+ worldRole: normalizeWorldRole(candidate.worldRole, null),
308
+ sourceMembershipId: normalizeText(candidate.sourceMembershipId, null),
309
+ online: candidate.online === true,
310
+ displayName,
311
+ agentCode,
312
+ requestChat,
313
+ profileSummary: normalizeCandidateProfileSummary(candidate.profileSummary),
314
+ compatibilitySignals: Array.isArray(candidate.compatibilitySignals)
315
+ ? candidate.compatibilitySignals.map((signal, signalIndex) => normalizeCompatibilitySignal(signal, signalIndex))
316
+ : [],
317
+ deliveryReason: normalizeDeliveryReason(candidate.deliveryReason),
318
+ worldFeedbackSummary: candidate.worldFeedbackSummary && typeof candidate.worldFeedbackSummary === 'object'
319
+ ? {
320
+ likesReceived: normalizeInteger(candidate.worldFeedbackSummary.likesReceived, 0),
321
+ dislikesReceived: normalizeInteger(candidate.worldFeedbackSummary.dislikesReceived, 0),
322
+ }
323
+ : {
324
+ likesReceived: 0,
325
+ dislikesReceived: 0,
326
+ },
327
+ expiresAt: normalizeText(candidate.expiresAt, null),
328
+ joinedAt: normalizeText(candidate.joinedAt, null),
329
+ rank: normalizedRank == null ? null : Math.max(1, Math.trunc(normalizedRank)),
330
+ score: normalizeNumber(candidate.score, null),
331
+ };
332
+ }
333
+
334
+ function normalizeCandidateFeedResponse(payload = {}, { worldId = null, agentId = null } = {}) {
335
+ const candidates = Array.isArray(payload.candidates)
336
+ ? payload.candidates.map((candidate, index) => normalizeCandidate(candidate, index))
337
+ : [];
338
+
339
+ return {
340
+ worldId: normalizeText(payload.worldId, worldId || 'unknown-world'),
341
+ agentId: normalizeText(payload.agentId, agentId || null),
342
+ viewerMembershipId: normalizeText(payload.viewerMembershipId, null),
343
+ generatedAt: normalizeText(payload.generatedAt, null),
344
+ expiresAt: normalizeText(payload.expiresAt, null),
345
+ deliveryMode: normalizeText(payload.deliveryMode, 'agent_review_before_live_session'),
346
+ nextAction: normalizeText(
347
+ payload.nextAction,
348
+ candidates.length > 0 ? 'review_candidates_then_request_chat' : 'wait_for_more_candidates',
349
+ ),
350
+ candidateDelivery: payload.candidateDelivery && typeof payload.candidateDelivery === 'object'
351
+ ? payload.candidateDelivery
352
+ : null,
353
+ candidateSource: normalizeText(payload.candidateSource, 'active_memberships_online'),
354
+ candidateModel: payload.candidateModel && typeof payload.candidateModel === 'object' ? payload.candidateModel : {},
355
+ strategy: payload.strategy && typeof payload.strategy === 'object' ? payload.strategy : {},
356
+ limit: normalizeInteger(payload.limit, candidates.length),
357
+ totalCandidates: normalizeInteger(payload.totalCandidates, candidates.length),
358
+ status: normalizeText(payload.status, candidates.length > 0 ? 'feed_ready' : 'no_candidates_ready'),
359
+ candidates,
360
+ };
361
+ }
362
+
363
+
262
364
  function normalizeActionPayload(value = null) {
263
365
  return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
264
366
  }
@@ -311,6 +413,20 @@ function summarizeProfileFields(fields = []) {
311
413
  .filter(Boolean);
312
414
  }
313
415
 
416
+ function buildCandidateDeliverySummaryLine(candidateSummary = {}, index = 0) {
417
+ return `${index + 1}. ${candidateSummary.summary}`;
418
+ }
419
+
420
+ export function buildCandidateDeliverySummary(candidateFeed = {}, { worldDetail = null, limit = null } = {}) {
421
+ if (candidateFeed?.candidateDelivery && typeof candidateFeed.candidateDelivery === 'object') {
422
+ return candidateFeed.candidateDelivery;
423
+ }
424
+ if (worldDetail?.candidateDelivery && typeof worldDetail.candidateDelivery === 'object') {
425
+ return worldDetail.candidateDelivery;
426
+ }
427
+ return buildBackendCandidateDeliverySummary(candidateFeed, { worldDetail, limit });
428
+ }
429
+
314
430
  export function buildWorldSelectionPrompt(worldDirectory = {}) {
315
431
  return worldDirectory?.orchestration && typeof worldDirectory.orchestration === 'object'
316
432
  ? worldDirectory.orchestration
@@ -360,10 +476,7 @@ export function buildPostSetupWorldDirectory(payload = {}, {
360
476
  nextAction: normalizeText(payload.nextAction, items.length > 0 ? 'inspect_world_detail_or_join_world' : 'broaden_world_search'),
361
477
  orchestration: payload.orchestration && typeof payload.orchestration === 'object'
362
478
  ? payload.orchestration
363
- : buildBackendWorldSelectionPrompt({
364
- items,
365
- recommendedWorldId,
366
- }),
479
+ : null,
367
480
  };
368
481
  }
369
482
 
@@ -382,7 +495,7 @@ function normalizeWorldMemberSearchItem(item = {}) {
382
495
  matchedFieldIds: normalizeStringList(item.matchedFieldIds),
383
496
  reasonSummary: normalizeText(item.reasonSummary, null),
384
497
  joinedAt: normalizeText(item.joinedAt, null),
385
- profileSummary: normalizeMemberProfileSummary(item.profileSummary || {}),
498
+ profileSummary: normalizeCandidateProfileSummary(item.profileSummary || {}),
386
499
  worldFeedbackSummary: item.worldFeedbackSummary && typeof item.worldFeedbackSummary === 'object' && !Array.isArray(item.worldFeedbackSummary)
387
500
  ? {
388
501
  likesReceived: normalizeInteger(item.worldFeedbackSummary.likesReceived, 0),
@@ -406,10 +519,10 @@ export function normalizeWorldMemberSearchResponse(payload = {}, { accountId = n
406
519
  accountId: normalizeText(accountId, null),
407
520
  worldId: normalizeText(payload.worldId, null),
408
521
  query: normalizeText(payload.query, null),
409
- sort: normalizeText(payload.sort, 'relevance'),
522
+ sort: normalizeText(payload.sort, 'match'),
410
523
  limit: normalizeInteger(payload.limit, items.length),
411
524
  totalMatches: normalizeInteger(payload.totalMatches, items.length),
412
- nextAction: normalizeText(payload.nextAction, items.length > 0 ? 'request_chat_with_selected_result' : 'broaden_search'),
525
+ nextAction: normalizeText(payload.nextAction, items.length > 0 ? 'request_chat_with_selected_candidate' : 'broaden_search_or_refresh_candidate_feed'),
413
526
  items,
414
527
  };
415
528
  }
@@ -534,13 +647,6 @@ export async function searchWorlds({
534
647
  accountId = null,
535
648
  runtimeConfig = null,
536
649
  query = null,
537
- keywords = [],
538
- topics = [],
539
- location = null,
540
- timeWindow = null,
541
- intent = null,
542
- desiredInteraction = null,
543
- constraints = [],
544
650
  limit = null,
545
651
  sort = null,
546
652
  page = null,
@@ -562,13 +668,6 @@ export async function searchWorlds({
562
668
  }),
563
669
  body: JSON.stringify({
564
670
  query: normalizeText(query, null),
565
- keywords: normalizeStringList(keywords),
566
- topics: normalizeStringList(topics),
567
- location: normalizeText(location, null),
568
- timeWindow: normalizeText(timeWindow, null),
569
- intent: normalizeText(intent, null),
570
- desiredInteraction: normalizeText(desiredInteraction, null),
571
- constraints: normalizeStringList(constraints),
572
671
  sort: normalizeText(sort, null),
573
672
  limit: limit == null ? null : normalizeInteger(limit, 0),
574
673
  page: page == null ? null : normalizeInteger(page, 0),
@@ -600,13 +699,6 @@ export async function search({
600
699
  worldId = null,
601
700
  agentId = null,
602
701
  query = null,
603
- keywords = [],
604
- topics = [],
605
- location = null,
606
- timeWindow = null,
607
- intent = null,
608
- desiredInteraction = null,
609
- constraints = [],
610
702
  limit = null,
611
703
  sort = null,
612
704
  page = null,
@@ -631,13 +723,6 @@ export async function search({
631
723
  worldId: normalizeText(worldId, null),
632
724
  agentId: normalizeText(agentId, null),
633
725
  query: normalizeText(query, null),
634
- keywords: normalizeStringList(keywords),
635
- topics: normalizeStringList(topics),
636
- location: normalizeText(location, null),
637
- timeWindow: normalizeText(timeWindow, null),
638
- intent: normalizeText(intent, null),
639
- desiredInteraction: normalizeText(desiredInteraction, null),
640
- constraints: normalizeStringList(constraints),
641
726
  sort: normalizeText(sort, null),
642
727
  limit: limit == null ? null : normalizeInteger(limit, 0),
643
728
  page: page == null ? null : normalizeInteger(page, 0),
@@ -664,122 +749,94 @@ export async function search({
664
749
  };
665
750
  }
666
751
 
667
- export async function getPublicProfile({
752
+ export async function joinWorld({
668
753
  cfg = {},
669
754
  accountId = null,
670
755
  runtimeConfig = null,
756
+ worldId = null,
671
757
  agentId = null,
672
- viewerAgentId = null,
758
+ participantContextText = null,
673
759
  fetchImpl,
674
760
  logger = console,
675
761
  } = {}) {
676
762
  if (typeof fetchImpl !== 'function') {
677
- throw new Error('fetch is unavailable for claworld public-profile helper');
763
+ throw new Error('fetch is unavailable for claworld product-shell join helper');
678
764
  }
765
+
766
+ const resolvedWorldId = normalizeText(worldId, null);
767
+ if (!resolvedWorldId) {
768
+ throw new Error('claworld product-shell join helper requires worldId');
769
+ }
770
+
679
771
  const resolvedAgentId = normalizeText(agentId, null);
680
772
  if (!resolvedAgentId) {
681
- throw new Error('claworld public-profile helper requires agentId');
773
+ throw new Error('claworld product-shell join helper requires agentId');
682
774
  }
775
+
683
776
  const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
684
777
  const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
685
- const requestUrl = new URL(`${baseUrl}/v1/public-profiles/${encodeURIComponent(resolvedAgentId)}`);
686
- const resolvedViewerAgentId = normalizeText(viewerAgentId, null);
687
- if (resolvedViewerAgentId) requestUrl.searchParams.set('viewerAgentId', resolvedViewerAgentId);
688
- const profileResult = await fetchJson(fetchImpl, requestUrl.toString(), {
778
+ const joinResult = await fetchJson(fetchImpl, `${baseUrl}/v1/worlds/${encodeURIComponent(resolvedWorldId)}/join`, {
779
+ method: 'POST',
689
780
  headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
690
781
  accept: 'application/json',
782
+ 'content-type': 'application/json',
691
783
  ...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
692
784
  }),
693
- });
694
- if (!profileResult.ok) {
695
- logger.error?.('[claworld:product-shell] public profile fetch failed', {
696
- status: profileResult.status,
697
- accountId: resolvedRuntimeConfig.accountId || accountId || null,
785
+ body: JSON.stringify({
698
786
  agentId: resolvedAgentId,
699
- body: profileResult.body,
700
- });
701
- throw createProductShellHttpError('public_profile', profileResult, {
702
- accountId: resolvedRuntimeConfig.accountId || accountId || null,
703
- });
704
- }
705
- return {
706
- accountId: resolvedRuntimeConfig.accountId || accountId || null,
707
- ...profileResult.body,
708
- };
709
- }
710
-
711
- export async function lookupPublicProfile({
712
- cfg = {},
713
- accountId = null,
714
- runtimeConfig = null,
715
- identity = null,
716
- viewerAgentId = null,
717
- fetchImpl,
718
- logger = console,
719
- } = {}) {
720
- if (typeof fetchImpl !== 'function') {
721
- throw new Error('fetch is unavailable for claworld public-profile helper');
722
- }
723
- const resolvedIdentity = normalizeText(identity, null);
724
- if (!resolvedIdentity) {
725
- throw new Error('claworld public-profile lookup helper requires identity');
726
- }
727
- const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
728
- const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
729
- const requestUrl = new URL(`${baseUrl}/v1/public-profiles/lookup`);
730
- requestUrl.searchParams.set('identity', resolvedIdentity);
731
- const resolvedViewerAgentId = normalizeText(viewerAgentId, null);
732
- if (resolvedViewerAgentId) requestUrl.searchParams.set('viewerAgentId', resolvedViewerAgentId);
733
- const profileResult = await fetchJson(fetchImpl, requestUrl.toString(), {
734
- headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
735
- accept: 'application/json',
736
- ...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
787
+ participantContextText: normalizeText(participantContextText, null),
737
788
  }),
738
789
  });
739
- if (!profileResult.ok) {
740
- logger.error?.('[claworld:product-shell] public profile lookup failed', {
741
- status: profileResult.status,
790
+
791
+ if (!joinResult.ok) {
792
+ logger.error?.('[claworld:product-shell] world join failed', {
793
+ status: joinResult.status,
794
+ worldId: resolvedWorldId,
795
+ agentId: resolvedAgentId,
742
796
  accountId: resolvedRuntimeConfig.accountId || accountId || null,
743
- identity: resolvedIdentity,
744
- body: profileResult.body,
797
+ body: joinResult.body,
745
798
  });
746
- throw createProductShellHttpError('public_profile_lookup', profileResult, {
799
+ throw createProductShellHttpError('world_join', joinResult, {
747
800
  accountId: resolvedRuntimeConfig.accountId || accountId || null,
801
+ worldId: resolvedWorldId,
748
802
  });
749
803
  }
750
- return {
751
- accountId: resolvedRuntimeConfig.accountId || accountId || null,
752
- ...profileResult.body,
753
- };
804
+
805
+ return normalizeWorldJoinResponse(joinResult.body, {
806
+ worldId: resolvedWorldId,
807
+ agentId: resolvedAgentId,
808
+ });
754
809
  }
755
810
 
756
- export async function joinWorld({
811
+ export async function searchWorldMembers({
757
812
  cfg = {},
758
813
  accountId = null,
759
814
  runtimeConfig = null,
760
815
  worldId = null,
761
816
  agentId = null,
762
- participantContextText = null,
817
+ query = null,
818
+ sort = null,
819
+ limit = null,
763
820
  fetchImpl,
764
821
  logger = console,
765
822
  } = {}) {
766
823
  if (typeof fetchImpl !== 'function') {
767
- throw new Error('fetch is unavailable for claworld product-shell join helper');
824
+ throw new Error('fetch is unavailable for claworld product-shell member search helper');
768
825
  }
769
826
 
770
827
  const resolvedWorldId = normalizeText(worldId, null);
771
828
  if (!resolvedWorldId) {
772
- throw new Error('claworld product-shell join helper requires worldId');
829
+ throw new Error('claworld product-shell member search helper requires worldId');
773
830
  }
774
831
 
775
832
  const resolvedAgentId = normalizeText(agentId, null);
776
833
  if (!resolvedAgentId) {
777
- throw new Error('claworld product-shell join helper requires agentId');
834
+ throw new Error('claworld product-shell member search helper requires agentId');
778
835
  }
779
836
 
780
837
  const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
781
838
  const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
782
- const joinResult = await fetchJson(fetchImpl, `${baseUrl}/v1/worlds/${encodeURIComponent(resolvedWorldId)}/join`, {
839
+ const searchResult = await fetchJson(fetchImpl, `${baseUrl}/v1/worlds/${encodeURIComponent(resolvedWorldId)}/search`, {
783
840
  method: 'POST',
784
841
  headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
785
842
  accept: 'application/json',
@@ -788,65 +845,58 @@ export async function joinWorld({
788
845
  }),
789
846
  body: JSON.stringify({
790
847
  agentId: resolvedAgentId,
791
- participantContextText: normalizeText(participantContextText, null),
848
+ query: normalizeText(query, null),
849
+ sort: normalizeText(sort, null),
850
+ limit: limit == null ? null : normalizeInteger(limit, 0),
792
851
  }),
793
852
  });
794
853
 
795
- if (!joinResult.ok) {
796
- logger.error?.('[claworld:product-shell] world join failed', {
797
- status: joinResult.status,
854
+ if (!searchResult.ok) {
855
+ logger.error?.('[claworld:product-shell] world member search failed', {
856
+ status: searchResult.status,
798
857
  worldId: resolvedWorldId,
799
858
  agentId: resolvedAgentId,
800
859
  accountId: resolvedRuntimeConfig.accountId || accountId || null,
801
- body: joinResult.body,
860
+ body: searchResult.body,
802
861
  });
803
- throw createProductShellHttpError('world_join', joinResult, {
862
+ throw createProductShellHttpError('world_member_search', searchResult, {
804
863
  accountId: resolvedRuntimeConfig.accountId || accountId || null,
805
864
  worldId: resolvedWorldId,
806
865
  });
807
866
  }
808
867
 
809
- return normalizeWorldJoinResponse(joinResult.body, {
810
- worldId: resolvedWorldId,
811
- agentId: resolvedAgentId,
868
+ return normalizeWorldMemberSearchResponse(searchResult.body, {
869
+ accountId: resolvedRuntimeConfig.accountId || accountId || null,
812
870
  });
813
871
  }
814
872
 
815
- export async function searchWorldMembers({
873
+ export async function fetchWorldCandidateFeed({
816
874
  cfg = {},
817
875
  accountId = null,
818
876
  runtimeConfig = null,
819
877
  worldId = null,
820
878
  agentId = null,
821
- query = null,
822
- keywords = [],
823
- topics = [],
824
- location = null,
825
- timeWindow = null,
826
- intent = null,
827
- desiredInteraction = null,
828
- constraints = [],
829
- sort = null,
830
879
  limit = null,
831
880
  fetchImpl,
832
881
  logger = console,
833
882
  } = {}) {
834
883
  if (typeof fetchImpl !== 'function') {
835
- throw new Error('fetch is unavailable for claworld product-shell member search helper');
884
+ throw new Error('fetch is unavailable for claworld product-shell candidate feed helper');
836
885
  }
837
886
 
838
887
  const resolvedWorldId = normalizeText(worldId, null);
839
888
  if (!resolvedWorldId) {
840
- throw new Error('claworld product-shell member search helper requires worldId');
889
+ throw new Error('claworld product-shell candidate feed helper requires worldId');
841
890
  }
842
891
 
843
892
  const resolvedAgentId = normalizeText(agentId, null);
844
893
  if (!resolvedAgentId) {
845
- throw new Error('claworld product-shell member search helper requires agentId');
894
+ throw new Error('claworld product-shell candidate feed helper requires agentId');
846
895
  }
847
896
 
848
897
  const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
849
898
  const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
899
+ const normalizedLimit = normalizeInteger(limit, 0);
850
900
  const searchResult = await fetchJson(fetchImpl, `${baseUrl}/v1/worlds/${encodeURIComponent(resolvedWorldId)}/search`, {
851
901
  method: 'POST',
852
902
  headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
@@ -856,36 +906,60 @@ export async function searchWorldMembers({
856
906
  }),
857
907
  body: JSON.stringify({
858
908
  agentId: resolvedAgentId,
859
- query: normalizeText(query, null),
860
- keywords: normalizeStringList(keywords),
861
- topics: normalizeStringList(topics),
862
- location: normalizeText(location, null),
863
- timeWindow: normalizeText(timeWindow, null),
864
- intent: normalizeText(intent, null),
865
- desiredInteraction: normalizeText(desiredInteraction, null),
866
- constraints: normalizeStringList(constraints),
867
- sort: normalizeText(sort, null),
868
- limit: limit == null ? null : normalizeInteger(limit, 0),
909
+ query: null,
910
+ sort: 'match',
911
+ limit: normalizedLimit > 0 ? normalizedLimit : null,
869
912
  }),
870
913
  });
871
914
 
872
915
  if (!searchResult.ok) {
873
- logger.error?.('[claworld:product-shell] world member search failed', {
916
+ logger.error?.('[claworld:product-shell] candidate feed compatibility search failed', {
874
917
  status: searchResult.status,
875
918
  worldId: resolvedWorldId,
876
919
  agentId: resolvedAgentId,
877
920
  accountId: resolvedRuntimeConfig.accountId || accountId || null,
878
921
  body: searchResult.body,
879
922
  });
880
- throw createProductShellHttpError('world_member_search', searchResult, {
923
+ throw createProductShellHttpError('world_candidate_feed', searchResult, {
881
924
  accountId: resolvedRuntimeConfig.accountId || accountId || null,
882
925
  worldId: resolvedWorldId,
883
926
  });
884
927
  }
885
928
 
886
- return normalizeWorldMemberSearchResponse(searchResult.body, {
929
+ const searchPayload = searchResult.body && typeof searchResult.body === 'object' ? searchResult.body : {};
930
+ const normalizedSearch = normalizeWorldMemberSearchResponse(searchPayload, {
887
931
  accountId: resolvedRuntimeConfig.accountId || accountId || null,
888
932
  });
933
+ return normalizeCandidateFeedResponse({
934
+ worldId: resolvedWorldId,
935
+ agentId: resolvedAgentId,
936
+ viewerMembershipId: searchPayload.viewerMembershipId,
937
+ generatedAt: searchPayload.generatedAt,
938
+ limit: normalizedSearch.limit,
939
+ totalCandidates: normalizedSearch.totalMatches,
940
+ candidateSource: searchPayload.candidateSource || 'active_memberships',
941
+ status: normalizedSearch.items.length > 0 ? 'feed_ready' : 'no_candidates_ready',
942
+ nextAction: normalizedSearch.nextAction,
943
+ candidates: normalizedSearch.items.map((item, index) => ({
944
+ candidateId: item.membershipId || `candidate_${index + 1}`,
945
+ sourceMembershipId: item.membershipId || null,
946
+ worldId: item.worldId || resolvedWorldId,
947
+ online: item.online === true,
948
+ rank: index + 1,
949
+ score: item.score,
950
+ agentCode: item.agentCode,
951
+ requestChat: item.requestChat,
952
+ profileSummary: item.profileSummary,
953
+ deliveryReason: {
954
+ summary: item.reasonSummary || item.headline || null,
955
+ },
956
+ worldFeedbackSummary: item.worldFeedbackSummary,
957
+ joinedAt: item.joinedAt,
958
+ })),
959
+ }, {
960
+ worldId: resolvedWorldId,
961
+ agentId: resolvedAgentId,
962
+ });
889
963
  }
890
964
 
891
965
  export async function resolveWorldSelectionFlow({