@xfxstudio/claworld 0.2.13 → 0.2.15

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 (58) hide show
  1. package/README.md +4 -4
  2. package/index.js +0 -1
  3. package/openclaw.plugin.json +1 -97
  4. package/package.json +1 -1
  5. package/skills/claworld-help/SKILL.md +47 -27
  6. package/skills/claworld-join-and-chat/SKILL.md +13 -9
  7. package/src/openclaw/index.js +0 -3
  8. package/src/openclaw/plugin/account-identity.js +0 -1
  9. package/src/openclaw/plugin/claworld-channel-plugin.js +73 -319
  10. package/src/openclaw/plugin/config-schema.js +1 -55
  11. package/src/openclaw/plugin/managed-config.js +1 -42
  12. package/src/openclaw/plugin/onboarding.js +1 -1
  13. package/src/openclaw/plugin/register.js +302 -233
  14. package/src/openclaw/plugin/relay-client.js +9 -6
  15. package/src/openclaw/runtime/product-shell-helper.js +11 -364
  16. package/src/openclaw/runtime/tool-contracts.js +0 -182
  17. package/src/openclaw/runtime/tool-inventory.js +4 -27
  18. package/src/lib/agent-profile.js +0 -74
  19. package/src/lib/http-auth.js +0 -151
  20. package/src/lib/policy.js +0 -114
  21. package/src/openclaw/installer/constants.js +0 -14
  22. package/src/product-shell/agent-cards/card-routes.js +0 -64
  23. package/src/product-shell/agent-cards/card-service.js +0 -287
  24. package/src/product-shell/agent-cards/spec-builder.js +0 -167
  25. package/src/product-shell/agent-cards/storage/image-host-storage.js +0 -192
  26. package/src/product-shell/agent-cards/storage/local-public-storage.js +0 -74
  27. package/src/product-shell/agent-cards/svg-renderer.js +0 -325
  28. package/src/product-shell/agent-cards/template-registry.js +0 -131
  29. package/src/product-shell/catalog/default-world-catalog.js +0 -38
  30. package/src/product-shell/contracts/candidate-feed.js +0 -393
  31. package/src/product-shell/contracts/world-manifest.js +0 -369
  32. package/src/product-shell/conversation-feedback/conversation-feedback-service.js +0 -261
  33. package/src/product-shell/feedback/feedback-contract.js +0 -13
  34. package/src/product-shell/feedback/feedback-routes.js +0 -98
  35. package/src/product-shell/feedback/feedback-service.js +0 -252
  36. package/src/product-shell/index.js +0 -212
  37. package/src/product-shell/matching/matchmaking-service.js +0 -395
  38. package/src/product-shell/membership/membership-service.js +0 -284
  39. package/src/product-shell/onboarding/onboarding-routes.js +0 -37
  40. package/src/product-shell/onboarding/onboarding-service.js +0 -222
  41. package/src/product-shell/orchestration/world-conversation-orchestrator.js +0 -28
  42. package/src/product-shell/profile/profile-service.js +0 -142
  43. package/src/product-shell/profile/public-identity-routes.js +0 -160
  44. package/src/product-shell/profile/public-identity-service.js +0 -192
  45. package/src/product-shell/search/search-service.js +0 -393
  46. package/src/product-shell/social/chat-request-approval-policy.js +0 -332
  47. package/src/product-shell/social/chat-request-routes.js +0 -130
  48. package/src/product-shell/social/chat-request-service.js +0 -723
  49. package/src/product-shell/social/friend-routes.js +0 -82
  50. package/src/product-shell/social/friend-service.js +0 -557
  51. package/src/product-shell/social/social-routes.js +0 -21
  52. package/src/product-shell/social/social-service.js +0 -136
  53. package/src/product-shell/worlds/world-admin-service.js +0 -486
  54. package/src/product-shell/worlds/world-authorization.js +0 -136
  55. package/src/product-shell/worlds/world-broadcast-service.js +0 -296
  56. package/src/product-shell/worlds/world-routes.js +0 -403
  57. package/src/product-shell/worlds/world-service.js +0 -89
  58. package/src/product-shell/worlds/world-text.js +0 -75
@@ -34,37 +34,6 @@ function normalizeStringList(values = []) {
34
34
  .filter(Boolean);
35
35
  }
36
36
 
37
- function summarizeProfileSnippet(profileSummary = {}) {
38
- const headline = normalizeText(profileSummary.headline, null);
39
- if (headline) return headline;
40
-
41
- const required = Array.isArray(profileSummary.requiredFields) ? profileSummary.requiredFields : [];
42
- const optional = Array.isArray(profileSummary.optionalFields) ? profileSummary.optionalFields : [];
43
- const allFields = [...required, ...optional]
44
- .map((field) => {
45
- const label = normalizeText(field.label, field.fieldId || 'Field');
46
- const value = Array.isArray(field.value) ? field.value.join(', ') : normalizeText(field.value, null);
47
- if (!value) return null;
48
- return `${label}: ${value}`;
49
- })
50
- .filter(Boolean);
51
-
52
- return allFields[0] || null;
53
- }
54
-
55
- function projectSearchMatchReasons(item = {}) {
56
- if (Array.isArray(item.matchedFields) && item.matchedFields.length > 0) {
57
- return item.matchedFields.map((field) => {
58
- if (field.matchType === 'overlap' && Array.isArray(field.sharedValues) && field.sharedValues.length > 0) {
59
- return `${field.label}: ${field.sharedValues.join(', ')}`;
60
- }
61
- return `${field.label} matches`;
62
- });
63
- }
64
-
65
- return [normalizeText(item.reasonSummary, 'Recently active online world member.')];
66
- }
67
-
68
37
  function projectParticipantContextField(field = null) {
69
38
  if (!field || typeof field !== 'object' || Array.isArray(field)) return null;
70
39
  return {
@@ -347,52 +316,6 @@ export function projectToolJoinWorldResponse(
347
316
  };
348
317
  }
349
318
 
350
- export function projectToolSearchWorldResponse(searchResult = {}, { accountId = null } = {}) {
351
- const compatibilityMessage = 'Compatibility-only manual world search. Candidate feed review is the canonical path before request_chat.';
352
- if (searchResult.status === 'not_joined') {
353
- return {
354
- status: 'not_joined',
355
- worldId: searchResult.worldId,
356
- accountId: normalizeText(accountId, null),
357
- discoveryMode: 'compatibility_search',
358
- canonicalDiscoveryMode: 'candidate_feed',
359
- query: searchResult.query || {},
360
- limit: normalizeInteger(searchResult.limit, 10),
361
- results: [],
362
- message: normalizeText(
363
- searchResult.message,
364
- 'Join the world first. Candidate feed review is the canonical path before request_chat; search remains compatibility-only.',
365
- ),
366
- };
367
- }
368
-
369
- const results = Array.isArray(searchResult.results)
370
- ? searchResult.results.map((item) => ({
371
- agentId: normalizeText(item.agentId, normalizeText(item.playerId, null)),
372
- playerId: normalizeText(item.playerId, normalizeText(item.agentId, null)),
373
- displayName: item.displayName,
374
- headline: item.headline || null,
375
- score: normalizeInteger(item.score, 0),
376
- matchReasons: projectSearchMatchReasons(item),
377
- profileSnippet: summarizeProfileSnippet(item.profileSummary),
378
- online: item.online === true,
379
- worldFeedbackSummary: projectWorldFeedbackSummary(item.worldFeedbackSummary),
380
- }))
381
- : [];
382
-
383
- return {
384
- status: results.length > 0 ? 'ready' : 'empty',
385
- worldId: searchResult.worldId,
386
- accountId: normalizeText(accountId, null),
387
- discoveryMode: 'compatibility_search',
388
- canonicalDiscoveryMode: 'candidate_feed',
389
- query: searchResult.query || {},
390
- limit: normalizeInteger(searchResult.limit, results.length || 10),
391
- message: compatibilityMessage,
392
- results,
393
- };
394
- }
395
-
396
319
  export function projectToolCreateWorldResponse(world = {}, { accountId = null } = {}) {
397
320
  return {
398
321
  worldId: world.worldId,
@@ -448,47 +371,6 @@ export function projectToolManagedWorldResponse(world = {}, { accountId = null }
448
371
  };
449
372
  }
450
373
 
451
- export function projectToolBroadcastWorldResponse(result = {}, { accountId = null } = {}) {
452
- const requests = Array.isArray(result.requests)
453
- ? result.requests.map((request) => ({
454
- agentId: normalizeText(
455
- request.agentId,
456
- request.chatRequest?.toAgent?.agentId || request.chatRequest?.counterparty?.agentId || null,
457
- ),
458
- status: normalizeText(request.status, 'created'),
459
- chatRequest: projectChatRequestItem(request.chatRequest),
460
- }))
461
- : [];
462
- const failures = Array.isArray(result.failures)
463
- ? result.failures.map((failure) => ({
464
- agentId: normalizeText(failure.agentId, null),
465
- status: normalizeText(failure.status, 'failed'),
466
- httpStatus: normalizeInteger(failure.httpStatus, 0),
467
- error: normalizeText(failure.error, null),
468
- reason: normalizeText(failure.reason, null),
469
- message: normalizeText(failure.message, null),
470
- }))
471
- : [];
472
-
473
- return {
474
- status: normalizeText(result.status, null),
475
- accountId: normalizeText(accountId, null),
476
- worldId: normalizeText(result.worldId, null),
477
- senderAgentId: normalizeText(result.senderAgentId, null),
478
- senderRole: normalizeText(result.senderRole, null),
479
- audience: normalizeText(result.audience, null),
480
- excludeSelf: normalizeOptionalBoolean(result.excludeSelf, null),
481
- eligibility: normalizeText(result.eligibility, null),
482
- broadcastId: normalizeText(result.broadcastId, null),
483
- totalTargets: normalizeInteger(result.totalTargets, requests.length + failures.length),
484
- createdCount: normalizeInteger(result.createdCount, requests.length),
485
- failedCount: normalizeInteger(result.failedCount, failures.length),
486
- nextAction: normalizeText(result.nextAction, null),
487
- requests,
488
- failures,
489
- };
490
- }
491
-
492
374
  export function projectToolFeedbackSubmissionResponse(result = {}) {
493
375
  const feedback = result.feedback && typeof result.feedback === 'object' ? result.feedback : {};
494
376
  const reporter = feedback.reporter && typeof feedback.reporter === 'object' ? feedback.reporter : {};
@@ -534,18 +416,6 @@ function projectToolAgentSummary(agent = {}) {
534
416
  };
535
417
  }
536
418
 
537
- function projectFriendshipSummary(friendship = {}) {
538
- if (!friendship || typeof friendship !== 'object') return null;
539
- return {
540
- friendshipId: normalizeText(friendship.friendshipId, null),
541
- status: normalizeText(friendship.status, null),
542
- peerAgentId: normalizeText(friendship.peerAgentId, null),
543
- peerAgent: projectToolAgentSummary(friendship.peerAgent),
544
- acceptedAt: normalizeText(friendship.acceptedAt, null),
545
- updatedAt: normalizeText(friendship.updatedAt, null),
546
- };
547
- }
548
-
549
419
  function projectToolWorldSummary(world = {}) {
550
420
  if (!world || typeof world !== 'object') return null;
551
421
  return {
@@ -566,20 +436,6 @@ function normalizeConversationScopeDetails(input = {}) {
566
436
  };
567
437
  }
568
438
 
569
- function projectFriendRequestItem(request = {}) {
570
- if (!request || typeof request !== 'object') return null;
571
- return {
572
- friendRequestId: normalizeText(request.friendRequestId, null),
573
- status: normalizeText(request.status, 'pending'),
574
- direction: normalizeText(request.direction, null),
575
- message: normalizeText(request.message, null),
576
- createdAt: normalizeText(request.createdAt, null),
577
- respondedAt: normalizeText(request.respondedAt, null),
578
- fromAgent: projectToolAgentSummary(request.fromAgent),
579
- toAgent: projectToolAgentSummary(request.toAgent),
580
- };
581
- }
582
-
583
439
  function projectChatRequestKickoff(kickoff = {}) {
584
440
  if (!kickoff || typeof kickoff !== 'object') return null;
585
441
  return {
@@ -661,34 +517,6 @@ function projectChatInboxChatItem(chat = {}) {
661
517
  };
662
518
  }
663
519
 
664
- export function projectToolFriendRequestMutationResponse(result = {}, { accountId = null } = {}) {
665
- return {
666
- status: result.alreadyFriends === true
667
- ? 'already_friends'
668
- : normalizeText(result.request?.status, 'pending'),
669
- accountId: normalizeText(accountId, null),
670
- created: result.created === true,
671
- alreadyFriends: result.alreadyFriends === true,
672
- request: projectFriendRequestItem(result.request),
673
- friendship: projectFriendshipSummary(result.friendship),
674
- nextAction: result.alreadyFriends === true
675
- ? 'friendship_active'
676
- : normalizeText(result.request?.status, 'pending') === 'pending'
677
- ? 'wait_for_peer_friend_request_decision'
678
- : 'friendship_active',
679
- };
680
- }
681
-
682
- export function projectToolFriendRequestListResponse(result = {}, { accountId = null } = {}) {
683
- const items = Array.isArray(result.items)
684
- ? result.items.map((request) => projectFriendRequestItem(request)).filter(Boolean)
685
- : [];
686
- return {
687
- accountId: normalizeText(accountId, null),
688
- items,
689
- };
690
- }
691
-
692
520
  export function projectToolChatRequestMutationResponse(result = {}, { accountId = null } = {}) {
693
521
  const request = result.chatRequest && typeof result.chatRequest === 'object'
694
522
  ? result.chatRequest
@@ -720,16 +548,6 @@ export function projectToolChatRequestMutationResponse(result = {}, { accountId
720
548
  };
721
549
  }
722
550
 
723
- export function projectToolChatRequestListResponse(result = {}, { accountId = null } = {}) {
724
- const items = Array.isArray(result.items)
725
- ? result.items.map((request) => projectChatRequestItem(request)).filter(Boolean)
726
- : [];
727
- return {
728
- accountId: normalizeText(accountId, null),
729
- items,
730
- };
731
- }
732
-
733
551
  export function projectToolChatInboxResponse(result = {}, { accountId = null } = {}) {
734
552
  const pendingRequests = Array.isArray(result.pendingRequests)
735
553
  ? result.pendingRequests.map((request) => projectChatRequestItem(request)).filter(Boolean)
@@ -3,16 +3,10 @@ export const CLAWORLD_TOOL_CONTRACT_VERSION = 'v1';
3
3
  export const CLAWORLD_CHAT_REQUEST_TOOL_NAMES = Object.freeze([
4
4
  'claworld_request_chat',
5
5
  'claworld_chat_inbox',
6
- 'claworld_accept_chat_request',
7
- 'claworld_reject_chat_request',
8
6
  ]);
9
7
 
10
- export const CLAWORLD_BOOTSTRAP_TOOL_NAMES = Object.freeze([
11
- 'claworld_pair_agent',
12
- ]);
13
-
14
- export const CLAWORLD_PROFILE_TOOL_NAMES = Object.freeze([
15
- 'claworld_profile',
8
+ export const CLAWORLD_ACCOUNT_TOOL_NAMES = Object.freeze([
9
+ 'claworld_account',
16
10
  ]);
17
11
 
18
12
  export const CLAWORLD_FEEDBACK_TOOL_NAMES = Object.freeze([
@@ -30,24 +24,8 @@ export const CLAWORLD_WORLD_ADMIN_PUBLIC_TOOL_NAMES = Object.freeze([
30
24
  'claworld_manage_world',
31
25
  ]);
32
26
 
33
- export const CLAWORLD_COMPATIBILITY_TOOL_NAMES = Object.freeze([
34
- 'claworld_list_owned_worlds',
35
- 'claworld_prepare_world_join',
36
- 'claworld_search_world',
37
- ]);
38
-
39
- export const CLAWORLD_RETIRED_PUBLIC_TOOL_NAMES = Object.freeze([
40
- 'claworld_send_friend_request',
41
- 'claworld_list_friend_requests',
42
- 'claworld_accept_friend_request',
43
- 'claworld_reject_friend_request',
44
- 'claworld_broadcast_world',
45
- 'claworld_resolve_agent',
46
- ]);
47
-
48
27
  export const CLAWORLD_REGISTERED_TOOL_NAMES = Object.freeze([
49
- ...CLAWORLD_BOOTSTRAP_TOOL_NAMES,
50
- ...CLAWORLD_PROFILE_TOOL_NAMES,
28
+ ...CLAWORLD_ACCOUNT_TOOL_NAMES,
51
29
  ...CLAWORLD_WORLD_TOOL_NAMES,
52
30
  ...CLAWORLD_WORLD_ADMIN_PUBLIC_TOOL_NAMES,
53
31
  ...CLAWORLD_CHAT_REQUEST_TOOL_NAMES,
@@ -71,8 +49,7 @@ export const CLAWORLD_READ_ONLY_OPENCLAW_TOOL_NAMES = Object.freeze([
71
49
  ]);
72
50
 
73
51
  export const CLAWORLD_PLUGIN_SMOKE_REQUIRED_TOOL_NAMES = Object.freeze([
74
- ...CLAWORLD_BOOTSTRAP_TOOL_NAMES,
75
- ...CLAWORLD_PROFILE_TOOL_NAMES,
52
+ ...CLAWORLD_ACCOUNT_TOOL_NAMES,
76
53
  ...CLAWORLD_WORLD_TOOL_NAMES,
77
54
  ...CLAWORLD_WORLD_ADMIN_PUBLIC_TOOL_NAMES,
78
55
  ...CLAWORLD_CHAT_REQUEST_TOOL_NAMES,
@@ -1,74 +0,0 @@
1
- import { resolvePublicIdentity } from './public-identity.js';
2
-
3
- function normalizeOptionalString(value, { maxLength = 280 } = {}) {
4
- if (value == null) return null;
5
- const normalized = String(value).trim();
6
- if (!normalized) return null;
7
- return normalized.slice(0, maxLength);
8
- }
9
-
10
- function normalizeTagList(rawTags, { maxItems = 8, maxLength = 24 } = {}) {
11
- if (!Array.isArray(rawTags)) return [];
12
- const seen = new Set();
13
- const tags = [];
14
- for (const value of rawTags) {
15
- const normalized = normalizeOptionalString(value, { maxLength });
16
- if (!normalized) continue;
17
- const key = normalized.toLowerCase();
18
- if (seen.has(key)) continue;
19
- seen.add(key);
20
- tags.push(normalized);
21
- if (tags.length >= maxItems) break;
22
- }
23
- return tags;
24
- }
25
-
26
- function normalizeBooleanFlag(value, fallback = true) {
27
- if (typeof value === 'boolean') return value;
28
- if (typeof value === 'number') {
29
- if (value === 1) return true;
30
- if (value === 0) return false;
31
- }
32
- if (typeof value === 'string') {
33
- const normalized = value.trim().toLowerCase();
34
- if (normalized === 'true' || normalized === '1') return true;
35
- if (normalized === 'false' || normalized === '0') return false;
36
- }
37
- return fallback;
38
- }
39
-
40
- export function resolveAgentDisplayName(agent = {}) {
41
- const publicIdentityDisplayName = normalizeOptionalString(resolvePublicIdentity(agent).displayName, { maxLength: 80 });
42
- if (publicIdentityDisplayName) return publicIdentityDisplayName;
43
- const displayName = normalizeOptionalString(agent.displayName, { maxLength: 80 });
44
- if (displayName) return displayName;
45
- return normalizeOptionalString(agent.agentId, { maxLength: 80 })
46
- || 'agent';
47
- }
48
-
49
- export function normalizeAgentProfile(profile) {
50
- const source = profile && typeof profile === 'object' ? profile : {};
51
- return {
52
- headline: normalizeOptionalString(source.headline, { maxLength: 120 }),
53
- bio: normalizeOptionalString(source.bio, { maxLength: 300 }),
54
- avatarUrl: normalizeOptionalString(source.avatarUrl, { maxLength: 512 }),
55
- tags: normalizeTagList(source.tags),
56
- };
57
- }
58
-
59
- export function resolveAgentVisibility(agent = {}) {
60
- const discoverable = normalizeBooleanFlag(agent.discoverable, true);
61
- const requestedContactable = normalizeBooleanFlag(agent.contactable, true);
62
- return {
63
- discoverable,
64
- contactable: discoverable ? requestedContactable : false,
65
- };
66
- }
67
-
68
- export function normalizeAgentInputMetadata({ displayName, profile, discoverable, contactable } = {}) {
69
- return {
70
- displayName: resolveAgentDisplayName({ displayName }),
71
- profile: normalizeAgentProfile(profile),
72
- ...resolveAgentVisibility({ discoverable, contactable }),
73
- };
74
- }
@@ -1,151 +0,0 @@
1
- function unauthorized(reason) {
2
- return {
3
- error: 'not_authenticated',
4
- reason,
5
- };
6
- }
7
-
8
- function forbidden(reason, extra = {}) {
9
- return {
10
- error: 'forbidden',
11
- reason,
12
- ...extra,
13
- };
14
- }
15
-
16
- function isExpired(isoTs, nowMs = Date.now()) {
17
- if (!isoTs) return false;
18
- const expiresAtMs = Date.parse(isoTs);
19
- if (Number.isNaN(expiresAtMs)) return false;
20
- return expiresAtMs <= nowMs;
21
- }
22
-
23
- function normalizeHeaderValue(value) {
24
- if (Array.isArray(value)) {
25
- const [first] = value;
26
- return typeof first === 'string' ? first.trim() : '';
27
- }
28
- if (typeof value === 'string') return value.trim();
29
- return '';
30
- }
31
-
32
- export function readAppTokenFromRequest(req) {
33
- const authorization = normalizeHeaderValue(req?.headers?.authorization);
34
- if (/^bearer\s+/i.test(authorization)) {
35
- const token = authorization.replace(/^bearer\s+/i, '').trim();
36
- if (token) return { token, source: 'authorization' };
37
- }
38
-
39
- const appTokenHeader = normalizeHeaderValue(req?.headers?.['x-claworld-app-token']);
40
- if (appTokenHeader) return { token: appTokenHeader, source: 'x-claworld-app-token' };
41
-
42
- const legacyRelayToken = normalizeHeaderValue(req?.headers?.['x-relay-token']);
43
- if (legacyRelayToken) return { token: legacyRelayToken, source: 'x-relay-token' };
44
-
45
- return { token: null, source: null };
46
- }
47
-
48
- export function authenticateAppTokenRequest({ store, req }) {
49
- const { token, source } = readAppTokenFromRequest(req);
50
- if (!token) {
51
- return {
52
- present: false,
53
- ok: false,
54
- source: null,
55
- token: null,
56
- agent: null,
57
- credential: null,
58
- error: null,
59
- };
60
- }
61
-
62
- const credential = store.getCredentialByToken(token);
63
- if (!credential) {
64
- return {
65
- present: true,
66
- ok: false,
67
- source,
68
- token,
69
- agent: null,
70
- credential: null,
71
- error: unauthorized('credential_invalid'),
72
- };
73
- }
74
- if (credential.status !== 'active' || credential.revokedAt) {
75
- return {
76
- present: true,
77
- ok: false,
78
- source,
79
- token,
80
- agent: null,
81
- credential,
82
- error: unauthorized('credential_revoked'),
83
- };
84
- }
85
- if (isExpired(credential.expiresAt)) {
86
- return {
87
- present: true,
88
- ok: false,
89
- source,
90
- token,
91
- agent: null,
92
- credential,
93
- error: unauthorized('credential_expired'),
94
- };
95
- }
96
-
97
- const agent = store.getAgent(credential.agentId);
98
- if (!agent) {
99
- return {
100
- present: true,
101
- ok: false,
102
- source,
103
- token,
104
- agent: null,
105
- credential,
106
- error: unauthorized('credential_invalid'),
107
- };
108
- }
109
-
110
- return {
111
- present: true,
112
- ok: true,
113
- source,
114
- token,
115
- agent,
116
- credential,
117
- error: null,
118
- };
119
- }
120
-
121
- export function resolveAuthenticatedAgentId({ store, req, providedAgentId = null, fieldName = 'agentId' } = {}) {
122
- const auth = authenticateAppTokenRequest({ store, req });
123
- if (auth.present && !auth.ok) {
124
- return {
125
- ok: false,
126
- status: 401,
127
- body: auth.error,
128
- };
129
- }
130
-
131
- const explicitAgentId = String(providedAgentId || '').trim() || null;
132
- const authenticatedAgentId = auth.ok ? auth.agent.agentId : null;
133
-
134
- if (explicitAgentId && authenticatedAgentId && explicitAgentId !== authenticatedAgentId) {
135
- return {
136
- ok: false,
137
- status: 403,
138
- body: forbidden('agent_identity_mismatch', {
139
- field: fieldName,
140
- authenticatedAgentId,
141
- providedAgentId: explicitAgentId,
142
- }),
143
- };
144
- }
145
-
146
- return {
147
- ok: true,
148
- auth,
149
- agentId: explicitAgentId || authenticatedAgentId || null,
150
- };
151
- }
package/src/lib/policy.js DELETED
@@ -1,114 +0,0 @@
1
- import { resolveAgentVisibility } from './agent-profile.js';
2
- const ALLOW_DECISION = Object.freeze({ allowed: true });
3
- const EMPTY_SET = Object.freeze(new Set());
4
-
5
- function parsePolicyCsvSet(rawValue) {
6
- if (typeof rawValue !== 'string') return EMPTY_SET;
7
- const values = rawValue
8
- .split(',')
9
- .map((value) => value.trim().toLowerCase())
10
- .filter(Boolean);
11
- return values.length > 0 ? new Set(values) : EMPTY_SET;
12
- }
13
-
14
- function buildRequestDenyPolicyFromEnv(env) {
15
- return Object.freeze({
16
- blockedAgentIds: parsePolicyCsvSet(env.RELAY_POLICY_BLOCKED_AGENT_IDS),
17
- deniedAgentIds: parsePolicyCsvSet(env.RELAY_POLICY_DENIED_AGENT_IDS),
18
- });
19
- }
20
-
21
- function agentInPolicySet(values, candidate) {
22
- const normalized = String(candidate || '').trim().toLowerCase();
23
- return normalized ? values.has(normalized) : false;
24
- }
25
-
26
- const requestDenyPolicy = buildRequestDenyPolicyFromEnv(process.env);
27
-
28
- function deny(status, error, extras = {}) {
29
- return { allowed: false, status, error, ...extras };
30
- }
31
-
32
- export function defaultCanRequest({ fromAgentId, fromAgent, toAgent }) {
33
- const visibility = resolveAgentVisibility(toAgent);
34
- if (agentInPolicySet(requestDenyPolicy.blockedAgentIds, fromAgentId)) {
35
- return deny(403, 'request_blocked_by_policy');
36
- }
37
- if (agentInPolicySet(requestDenyPolicy.deniedAgentIds, fromAgentId)) {
38
- return deny(403, 'request_denied_by_policy');
39
- }
40
- if (toAgent.agentId === fromAgentId) return deny(400, 'self_request_not_allowed');
41
- if (!visibility.discoverable) return deny(403, 'target_not_discoverable');
42
- if (!visibility.contactable) return deny(403, 'target_not_contactable');
43
- return ALLOW_DECISION;
44
- }
45
-
46
- export function defaultCanAccept() {
47
- return ALLOW_DECISION;
48
- }
49
-
50
- export function defaultCanStartSession() {
51
- return ALLOW_DECISION;
52
- }
53
-
54
- export function defaultCanDeliverTurn({ session, roundBudget, fromAgentId }) {
55
- if (session.state !== 'active') {
56
- const terminationReason = typeof session?.terminationReason === 'string' && session.terminationReason.trim()
57
- ? session.terminationReason.trim()
58
- : null;
59
- return deny(terminationReason === 'session_timeout' ? 409 : 400, terminationReason || 'session_not_active');
60
- }
61
- if (roundBudget?.hasExplicitBudget && Number(roundBudget.remainingTurns) <= 0) {
62
- return deny(400, 'max_turns_reached');
63
- }
64
- if (fromAgentId !== session.currentSpeakerAgentId) return deny(400, 'not_current_speaker');
65
- return ALLOW_DECISION;
66
- }
67
-
68
- export function createRelayPolicyHooks(policy) {
69
- const hooks = policy && typeof policy === 'object' ? policy : {};
70
- return {
71
- canRequest: typeof hooks.canRequest === 'function' ? hooks.canRequest : defaultCanRequest,
72
- canAccept: typeof hooks.canAccept === 'function' ? hooks.canAccept : defaultCanAccept,
73
- canStartSession: typeof hooks.canStartSession === 'function' ? hooks.canStartSession : defaultCanStartSession,
74
- canDeliverTurn: typeof hooks.canDeliverTurn === 'function' ? hooks.canDeliverTurn : defaultCanDeliverTurn,
75
- };
76
- }
77
-
78
- export function resolvePolicyDecision(decision, { defaultStatus = 403, defaultError = 'forbidden' } = {}) {
79
- if (decision == null || decision === true) return { allowed: true };
80
- if (decision === false) return { allowed: false, status: defaultStatus, body: { error: defaultError } };
81
- if (typeof decision !== 'object') return { allowed: true };
82
-
83
- const hasDenyShape = decision.allowed === false
84
- || (decision.allowed === undefined && (decision.status !== undefined || decision.error !== undefined || decision.body !== undefined));
85
-
86
- if (!hasDenyShape) return { allowed: true };
87
-
88
- const status = Number.isInteger(decision.status) ? decision.status : defaultStatus;
89
- if (decision.body && typeof decision.body === 'object') return { allowed: false, status, body: decision.body };
90
- const error = typeof decision.error === 'string' && decision.error.trim() ? decision.error : defaultError;
91
- return { allowed: false, status, body: { error } };
92
- }
93
-
94
- export function evaluatePolicyHook({
95
- hook,
96
- context,
97
- hookName,
98
- defaultStatus = 403,
99
- defaultError = 'forbidden',
100
- }) {
101
- try {
102
- return resolvePolicyDecision(hook(context), { defaultStatus, defaultError });
103
- } catch (error) {
104
- return {
105
- allowed: false,
106
- status: 500,
107
- body: {
108
- error: 'policy_hook_error',
109
- hook: hookName,
110
- message: error instanceof Error ? error.message : String(error),
111
- },
112
- };
113
- }
114
- }
@@ -1,14 +0,0 @@
1
- import { createRequire } from 'module';
2
-
3
- const require = createRequire(import.meta.url);
4
- const installerPackageJson = require('../../../package.json');
5
-
6
- export const CLAWORLD_INSTALLER_BIN_NAME = 'claworld';
7
- export const CLAWORLD_INSTALLER_PACKAGE_NAME = '@xfxstudio/claworld';
8
- export const CLAWORLD_INSTALLER_PACKAGE_VERSION = installerPackageJson.version;
9
- export const CLAWORLD_INSTALLER_DEFAULT_PLUGIN_SOURCE = `${CLAWORLD_INSTALLER_PACKAGE_NAME}@${CLAWORLD_INSTALLER_PACKAGE_VERSION}`;
10
- export const CLAWORLD_INSTALLER_COMMAND = 'npx -y @xfxstudio/claworld install';
11
- export const CLAWORLD_DOCTOR_COMMAND = 'npx -y @xfxstudio/claworld doctor';
12
- export const CLAWORLD_UPDATE_COMMAND = 'npx -y @xfxstudio/claworld update';
13
- export const CLAWORLD_UNINSTALL_COMMAND = 'npx -y @xfxstudio/claworld uninstall';
14
- export const CLAWORLD_OPENCLAW_MIN_HOST_VERSION = '>=2026.3.22';