@xfxstudio/claworld 2026.4.14-testing.1 → 2026.4.16-testing.1

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 (47) hide show
  1. package/openclaw.plugin.json +1 -1
  2. package/package.json +1 -1
  3. package/index.js +0 -50
  4. package/setup-entry.js +0 -6
  5. package/skills/claworld-a2a-channel-agent/SKILL.md +0 -218
  6. package/skills/claworld-help/SKILL.md +0 -304
  7. package/skills/claworld-join-and-chat/SKILL.md +0 -515
  8. package/skills/claworld-manage-worlds/SKILL.md +0 -283
  9. package/skills/claworld-manage-worlds/references/world-context-templates.md +0 -145
  10. package/src/lib/chat-request.js +0 -366
  11. package/src/lib/public-identity.js +0 -175
  12. package/src/lib/relay/agent-readable-markdown.js +0 -385
  13. package/src/lib/relay/kickoff-progress.js +0 -162
  14. package/src/lib/relay/kickoff-text.js +0 -191
  15. package/src/lib/relay/shared.js +0 -30
  16. package/src/lib/runtime-errors.js +0 -149
  17. package/src/openclaw/index.js +0 -51
  18. package/src/openclaw/plugin/account-identity.js +0 -73
  19. package/src/openclaw/plugin/claworld-channel-plugin.js +0 -3483
  20. package/src/openclaw/plugin/config-schema.js +0 -392
  21. package/src/openclaw/plugin/lifecycle.js +0 -114
  22. package/src/openclaw/plugin/managed-config.js +0 -1054
  23. package/src/openclaw/plugin/onboarding.js +0 -312
  24. package/src/openclaw/plugin/register-tooling.js +0 -728
  25. package/src/openclaw/plugin/register.js +0 -1609
  26. package/src/openclaw/plugin/relay-client-shared.js +0 -146
  27. package/src/openclaw/plugin/relay-client.js +0 -1469
  28. package/src/openclaw/plugin/runtime-backup.js +0 -105
  29. package/src/openclaw/plugin/runtime.js +0 -12
  30. package/src/openclaw/plugin-version.js +0 -67
  31. package/src/openclaw/protocol/relay-event-protocol.js +0 -43
  32. package/src/openclaw/runtime/backend-error-context.js +0 -91
  33. package/src/openclaw/runtime/canonical-result-builder.js +0 -126
  34. package/src/openclaw/runtime/demo-session-bootstrap.js +0 -32
  35. package/src/openclaw/runtime/feedback-helper.js +0 -145
  36. package/src/openclaw/runtime/inbound-session-router.js +0 -44
  37. package/src/openclaw/runtime/outbound-session-bridge.js +0 -29
  38. package/src/openclaw/runtime/product-shell-helper.js +0 -931
  39. package/src/openclaw/runtime/runtime-path.js +0 -19
  40. package/src/openclaw/runtime/system-message-orchestrator.js +0 -1
  41. package/src/openclaw/runtime/tool-contracts.js +0 -939
  42. package/src/openclaw/runtime/tool-inventory.js +0 -83
  43. package/src/openclaw/runtime/world-membership-helper.js +0 -320
  44. package/src/openclaw/runtime/world-moderation-helper.js +0 -508
  45. package/src/product-shell/contracts/chat-request-approval-policy.js +0 -93
  46. package/src/product-shell/contracts/world-orchestration.js +0 -734
  47. package/src/product-shell/orchestration/world-conversation-text.js +0 -229
@@ -1,366 +0,0 @@
1
- import { createKickoffBrief } from './relay/kickoff-text.js';
2
- import { normalizeAcceptedChatKickoffRecord } from './relay/kickoff-progress.js';
3
-
4
- function normalizeText(value, fallback = null) {
5
- if (value == null) return fallback;
6
- const normalized = String(value).trim();
7
- return normalized || fallback;
8
- }
9
-
10
- function cloneJsonObject(value) {
11
- if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
12
- try {
13
- const cloned = JSON.parse(JSON.stringify(value));
14
- if (!cloned || typeof cloned !== 'object' || Array.isArray(cloned)) return null;
15
- return cloned;
16
- } catch {
17
- return null;
18
- }
19
- }
20
-
21
- export function normalizeChatRequestConversation(input = {}) {
22
- if (!input || typeof input !== 'object' || Array.isArray(input)) return {};
23
- const conversation = {
24
- ...(normalizeText(input.worldId, null) ? { worldId: normalizeText(input.worldId, null) } : {}),
25
- ...(normalizeText(input.scope, null)
26
- ? { scope: normalizeText(input.scope, null) }
27
- : {}),
28
- ...(normalizeText(input.conversationId, null) ? { conversationId: normalizeText(input.conversationId, null) } : {}),
29
- ...(normalizeText(input.threadId, null) ? { threadId: normalizeText(input.threadId, null) } : {}),
30
- ...(normalizeText(input.conversationKey, null) ? { conversationKey: normalizeText(input.conversationKey, null) } : {}),
31
- ...(normalizeText(input.sessionKey, null) ? { sessionKey: normalizeText(input.sessionKey, null) } : {}),
32
- };
33
-
34
- const episode = cloneJsonObject(input.episode);
35
- if (episode) {
36
- conversation.episode = episode;
37
- }
38
- const worldContextText = normalizeText(
39
- input.worldContextText,
40
- normalizeText(input.worldContext?.worldContextText, normalizeText(input.worldContext?.text, null)),
41
- );
42
- if (worldContextText) {
43
- conversation.worldContextText = worldContextText;
44
- }
45
-
46
- return conversation;
47
- }
48
-
49
- export function normalizeChatRequestOrigin(origin = {}, { fallbackType = null } = {}) {
50
- if (!origin || typeof origin !== 'object' || Array.isArray(origin)) {
51
- const type = normalizeText(fallbackType, null);
52
- return type ? { type } : null;
53
- }
54
-
55
- const normalized = {
56
- ...(normalizeText(origin.type, normalizeText(fallbackType, null))
57
- ? { type: normalizeText(origin.type, normalizeText(fallbackType, null)) }
58
- : {}),
59
- ...(normalizeText(origin.broadcastId, null) ? { broadcastId: normalizeText(origin.broadcastId, null) } : {}),
60
- };
61
-
62
- return Object.keys(normalized).length > 0 ? normalized : null;
63
- }
64
-
65
- export function normalizeChatRequestBroadcast(input = {}) {
66
- if (!input || typeof input !== 'object' || Array.isArray(input)) return null;
67
- const normalized = {
68
- ...(normalizeText(input.broadcastId, null) ? { broadcastId: normalizeText(input.broadcastId, null) } : {}),
69
- ...(normalizeText(input.worldId, null) ? { worldId: normalizeText(input.worldId, null) } : {}),
70
- ...(normalizeText(input.audience, null) ? { audience: normalizeText(input.audience, null) } : {}),
71
- ...(normalizeText(input.senderRole, null) ? { senderRole: normalizeText(input.senderRole, null) } : {}),
72
- ...(normalizeText(input.eligibility, null) ? { eligibility: normalizeText(input.eligibility, null) } : {}),
73
- ...(typeof input.excludeSelf === 'boolean' ? { excludeSelf: input.excludeSelf } : {}),
74
- };
75
- return Object.keys(normalized).length > 0 ? normalized : null;
76
- }
77
-
78
- export function normalizeChatRequestFollowUp(input = {}) {
79
- if (!input || typeof input !== 'object' || Array.isArray(input)) return null;
80
- const normalized = {
81
- ...(normalizeText(input.sessionKey, null) ? { sessionKey: normalizeText(input.sessionKey, null) } : {}),
82
- };
83
- return Object.keys(normalized).length > 0 ? normalized : null;
84
- }
85
-
86
- export function normalizeChatRequestOpeningPayload(input = null) {
87
- if (!input || typeof input !== 'object' || Array.isArray(input)) return null;
88
- const payload = cloneJsonObject(input);
89
- if (!payload) return null;
90
- if (typeof payload.text === 'string') {
91
- payload.text = payload.text.trim();
92
- if (!payload.text) delete payload.text;
93
- }
94
- if (typeof payload.source === 'string') {
95
- payload.source = payload.source.trim() || undefined;
96
- }
97
- return Object.keys(payload).length > 0 ? payload : null;
98
- }
99
-
100
- export function resolveChatRequestOpeningMessage({
101
- openingMessage = null,
102
- openingPayload = null,
103
- requestContext = null,
104
- } = {}) {
105
- return normalizeText(
106
- openingMessage,
107
- normalizeText(openingPayload?.text, normalizeText(requestContext?.message, null)),
108
- );
109
- }
110
-
111
- function resolveKickoffBriefSource({
112
- kickoffBrief = null,
113
- openingPayload = null,
114
- requestContext = null,
115
- source = null,
116
- } = {}) {
117
- const normalizedContext = requestContext && typeof requestContext === 'object' && !Array.isArray(requestContext)
118
- ? requestContext
119
- : {};
120
- const explicitKickoffBrief = kickoffBrief && typeof kickoffBrief === 'object' && !Array.isArray(kickoffBrief)
121
- ? kickoffBrief
122
- : null;
123
- const contextKickoffBrief = normalizedContext.kickoffBrief && typeof normalizedContext.kickoffBrief === 'object' && !Array.isArray(normalizedContext.kickoffBrief)
124
- ? normalizedContext.kickoffBrief
125
- : null;
126
- const fallbackSource = normalizeText(source, null) === 'world_broadcast'
127
- ? 'world_broadcast_brief'
128
- : 'chat_request_brief';
129
- return normalizeText(
130
- explicitKickoffBrief?.source,
131
- normalizeText(
132
- contextKickoffBrief?.source,
133
- normalizeText(
134
- openingPayload?.source,
135
- normalizeText(normalizedContext.openingPayload?.source, fallbackSource),
136
- ),
137
- ),
138
- );
139
- }
140
-
141
- function resolveChatRequestKickoffBrief({
142
- kickoffBrief = null,
143
- openingMessage = null,
144
- openingPayload = null,
145
- requestContext = null,
146
- source = null,
147
- } = {}) {
148
- const normalizedContext = requestContext && typeof requestContext === 'object' && !Array.isArray(requestContext)
149
- ? requestContext
150
- : {};
151
- const explicitKickoffBrief = kickoffBrief && typeof kickoffBrief === 'object' && !Array.isArray(kickoffBrief)
152
- ? kickoffBrief
153
- : null;
154
- const contextKickoffBrief = normalizedContext.kickoffBrief && typeof normalizedContext.kickoffBrief === 'object' && !Array.isArray(normalizedContext.kickoffBrief)
155
- ? normalizedContext.kickoffBrief
156
- : null;
157
- const normalizedOpeningPayload = normalizeChatRequestOpeningPayload(
158
- explicitKickoffBrief?.payload
159
- ?? contextKickoffBrief?.payload
160
- ?? openingPayload
161
- ?? normalizedContext.openingPayload,
162
- );
163
- const normalizedOpeningMessage = resolveChatRequestOpeningMessage({
164
- openingMessage:
165
- explicitKickoffBrief?.text
166
- ?? contextKickoffBrief?.text
167
- ?? openingMessage,
168
- openingPayload: normalizedOpeningPayload,
169
- requestContext: normalizedContext,
170
- });
171
- return createKickoffBrief({
172
- text: normalizedOpeningMessage,
173
- payload: explicitKickoffBrief?.payload ?? contextKickoffBrief?.payload ?? normalizedOpeningPayload,
174
- source: resolveKickoffBriefSource({
175
- kickoffBrief: explicitKickoffBrief ?? contextKickoffBrief,
176
- openingPayload: normalizedOpeningPayload,
177
- requestContext: normalizedContext,
178
- source,
179
- }),
180
- });
181
- }
182
-
183
- export function normalizeChatRequestInput({ requestContext = {}, source = null } = {}) {
184
- const normalizedContext = requestContext && typeof requestContext === 'object' && !Array.isArray(requestContext)
185
- ? requestContext
186
- : {};
187
- const conversationSource = normalizedContext.conversation && typeof normalizedContext.conversation === 'object' && !Array.isArray(normalizedContext.conversation)
188
- ? normalizedContext.conversation
189
- : {};
190
- const conversation = normalizeChatRequestConversation({
191
- ...conversationSource,
192
- conversationKey: normalizedContext.conversationKey ?? conversationSource.conversationKey,
193
- sessionKey: normalizedContext.sessionKey ?? conversationSource.sessionKey,
194
- });
195
- const kickoffBrief = resolveChatRequestKickoffBrief({
196
- requestContext: normalizedContext,
197
- source,
198
- });
199
- const openingPayload = normalizeChatRequestOpeningPayload(kickoffBrief?.payload ?? normalizedContext.openingPayload);
200
- const broadcast = normalizeChatRequestBroadcast(normalizedContext.broadcast);
201
- const followUp = normalizeChatRequestFollowUp(normalizedContext.followUp);
202
- let origin = normalizeChatRequestOrigin(normalizedContext.origin, {
203
- fallbackType: normalizeText(source, null) === 'world_broadcast' ? 'world_broadcast' : 'chat_request',
204
- });
205
-
206
- if (broadcast?.broadcastId && !origin?.broadcastId) {
207
- origin = {
208
- ...(origin || { type: normalizeText(source, null) === 'world_broadcast' ? 'world_broadcast' : 'chat_request' }),
209
- broadcastId: broadcast.broadcastId,
210
- };
211
- }
212
-
213
- return {
214
- kickoffBrief,
215
- openingMessage: resolveChatRequestOpeningMessage({
216
- openingMessage: kickoffBrief?.text ?? null,
217
- openingPayload: kickoffBrief?.payload ?? openingPayload,
218
- requestContext: normalizedContext,
219
- }),
220
- openingPayload: kickoffBrief?.payload ?? openingPayload,
221
- conversation,
222
- origin,
223
- broadcast,
224
- followUp,
225
- };
226
- }
227
-
228
- export function buildChatRequestContext({
229
- kickoffBrief = null,
230
- openingMessage = null,
231
- openingPayload = null,
232
- conversation = {},
233
- origin = null,
234
- broadcast = null,
235
- followUp = null,
236
- source = 'chat_request',
237
- } = {}) {
238
- const normalizedConversation = normalizeChatRequestConversation(conversation);
239
- const normalizedKickoffBrief = resolveChatRequestKickoffBrief({
240
- kickoffBrief,
241
- openingMessage,
242
- openingPayload,
243
- source,
244
- });
245
- const normalizedOpeningPayload = normalizeChatRequestOpeningPayload(
246
- normalizedKickoffBrief?.payload ?? openingPayload,
247
- );
248
- const normalizedMessage = resolveChatRequestOpeningMessage({
249
- openingMessage: normalizedKickoffBrief?.text ?? openingMessage,
250
- openingPayload: normalizedOpeningPayload,
251
- });
252
- let normalizedOrigin = normalizeChatRequestOrigin(origin, {
253
- fallbackType: normalizeText(source, null) === 'world_broadcast' ? 'world_broadcast' : 'chat_request',
254
- });
255
- let normalizedBroadcast = normalizeChatRequestBroadcast(broadcast);
256
- const normalizedFollowUp = normalizeChatRequestFollowUp(followUp);
257
-
258
- if (normalizedOrigin?.broadcastId && !normalizedBroadcast?.broadcastId) {
259
- normalizedBroadcast = {
260
- ...(normalizedBroadcast || {}),
261
- broadcastId: normalizedOrigin.broadcastId,
262
- };
263
- }
264
-
265
- const requestContext = {
266
- type: 'chat_request',
267
- ...(normalizedKickoffBrief ? { kickoffBrief: normalizedKickoffBrief } : {}),
268
- ...(normalizedMessage ? { message: normalizedMessage } : {}),
269
- ...(normalizedOpeningPayload ? { openingPayload: normalizedOpeningPayload } : {}),
270
- ...(Object.keys(normalizedConversation).length > 0 ? { conversation: normalizedConversation } : {}),
271
- ...(normalizedOrigin ? { origin: normalizedOrigin } : {}),
272
- ...(normalizedBroadcast ? { broadcast: normalizedBroadcast } : {}),
273
- ...(normalizedFollowUp ? { followUp: normalizedFollowUp } : {}),
274
- };
275
-
276
- return requestContext;
277
- }
278
-
279
- export function normalizeStoredChatRequest(input = {}, { defaultSource = 'chat_request' } = {}) {
280
- const normalizedSource = normalizeText(input.source, defaultSource);
281
- const normalizedRequest = normalizeChatRequestInput({
282
- requestContext: input.requestContext,
283
- source: normalizedSource,
284
- });
285
- const kickoffBrief = resolveChatRequestKickoffBrief({
286
- kickoffBrief: input.kickoffBrief,
287
- openingMessage: input.openingMessage,
288
- openingPayload: input.openingPayload ?? normalizedRequest.openingPayload,
289
- requestContext: input.requestContext,
290
- source: normalizedSource,
291
- });
292
- const openingPayload = normalizeChatRequestOpeningPayload(
293
- input.openingPayload ?? kickoffBrief?.payload ?? normalizedRequest.openingPayload,
294
- );
295
- const openingMessage = resolveChatRequestOpeningMessage({
296
- openingMessage: kickoffBrief?.text ?? input.openingMessage,
297
- openingPayload,
298
- requestContext: input.requestContext,
299
- });
300
- const conversation = normalizeChatRequestConversation(
301
- input.conversation && typeof input.conversation === 'object' && !Array.isArray(input.conversation)
302
- ? input.conversation
303
- : normalizedRequest.conversation,
304
- );
305
- const broadcast = normalizeChatRequestBroadcast(
306
- input.broadcast && typeof input.broadcast === 'object' && !Array.isArray(input.broadcast)
307
- ? input.broadcast
308
- : normalizedRequest.broadcast,
309
- );
310
- const followUp = normalizeChatRequestFollowUp(
311
- input.followUp && typeof input.followUp === 'object' && !Array.isArray(input.followUp)
312
- ? input.followUp
313
- : normalizedRequest.followUp,
314
- );
315
- let origin = normalizeChatRequestOrigin(
316
- input.origin && typeof input.origin === 'object' && !Array.isArray(input.origin)
317
- ? input.origin
318
- : normalizedRequest.origin,
319
- { fallbackType: normalizedSource === 'world_broadcast' ? 'world_broadcast' : 'chat_request' },
320
- );
321
-
322
- if (broadcast?.broadcastId && !origin?.broadcastId) {
323
- origin = {
324
- ...(origin || { type: normalizedSource === 'world_broadcast' ? 'world_broadcast' : 'chat_request' }),
325
- broadcastId: broadcast.broadcastId,
326
- };
327
- }
328
-
329
- const chatRequestId = normalizeText(input.chatRequestId, normalizeText(input.requestId, null));
330
- const normalized = {
331
- chatRequestId,
332
- requestId: chatRequestId,
333
- fromAgentId: normalizeText(input.fromAgentId, null),
334
- toAgentId: normalizeText(input.toAgentId, null),
335
- openingMessage,
336
- ...(kickoffBrief ? { kickoffBrief } : {}),
337
- ...(openingPayload ? { openingPayload } : {}),
338
- conversation,
339
- ...(origin ? { origin } : {}),
340
- ...(broadcast ? { broadcast } : {}),
341
- requestContext: buildChatRequestContext({
342
- kickoffBrief,
343
- openingMessage,
344
- openingPayload,
345
- conversation,
346
- origin,
347
- broadcast,
348
- followUp,
349
- source: normalizedSource,
350
- }),
351
- status: normalizeText(input.status, 'pending'),
352
- createdAt: normalizeText(input.createdAt, null),
353
- respondedAt: normalizeText(input.respondedAt, null),
354
- expiresAt: normalizeText(input.expiresAt, null),
355
- source: normalizedSource,
356
- };
357
-
358
- const acceptedByAgentId = normalizeText(input.acceptedByAgentId, null);
359
- if (acceptedByAgentId) normalized.acceptedByAgentId = acceptedByAgentId;
360
- const approvalGrantId = normalizeText(input.approvalGrantId, null);
361
- if (approvalGrantId) normalized.approvalGrantId = approvalGrantId;
362
- const kickoff = normalizeAcceptedChatKickoffRecord(cloneJsonObject(input.kickoff));
363
- if (kickoff) normalized.kickoff = kickoff;
364
-
365
- return normalized;
366
- }
@@ -1,175 +0,0 @@
1
- import { randomBytes } from 'crypto';
2
-
3
- export const PUBLIC_IDENTITY_STATUS = Object.freeze({
4
- PENDING: 'pending',
5
- READY: 'ready',
6
- });
7
-
8
- export const PUBLIC_IDENTITY_DISPLAY_NAME_MAX_LENGTH = 40;
9
- export const PUBLIC_IDENTITY_CODE_LENGTH = 6;
10
- const PUBLIC_IDENTITY_CODE_ALPHABET = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
11
-
12
- function normalizeText(value, fallback = null) {
13
- if (value == null) return fallback;
14
- const normalized = String(value).trim();
15
- return normalized || fallback;
16
- }
17
-
18
- function normalizeIsoTimestamp(value, fallback = null) {
19
- const normalized = normalizeText(value, null);
20
- if (!normalized) return fallback;
21
- const timestamp = Date.parse(normalized);
22
- return Number.isFinite(timestamp) ? new Date(timestamp).toISOString() : fallback;
23
- }
24
-
25
- function cloneObject(value, fallback = {}) {
26
- if (!value || typeof value !== 'object' || Array.isArray(value)) return { ...fallback };
27
- return { ...value };
28
- }
29
-
30
- export function normalizePublicDisplayName(value, { fallback = null } = {}) {
31
- const normalized = normalizeText(value, fallback);
32
- if (!normalized) return fallback;
33
- return normalized.slice(0, PUBLIC_IDENTITY_DISPLAY_NAME_MAX_LENGTH);
34
- }
35
-
36
- export function validatePublicDisplayName(value) {
37
- const normalized = normalizeText(value, null);
38
- if (!normalized) {
39
- return {
40
- ok: false,
41
- code: 'display_name_required',
42
- message: 'displayName is required',
43
- };
44
- }
45
- if (normalized.length > PUBLIC_IDENTITY_DISPLAY_NAME_MAX_LENGTH) {
46
- return {
47
- ok: false,
48
- code: 'display_name_too_long',
49
- message: `displayName must be ${PUBLIC_IDENTITY_DISPLAY_NAME_MAX_LENGTH} characters or fewer`,
50
- };
51
- }
52
- if (normalized.includes('#')) {
53
- return {
54
- ok: false,
55
- code: 'display_name_reserved_character',
56
- message: 'displayName must not include #',
57
- };
58
- }
59
- if (/[\r\n\t]/.test(normalized)) {
60
- return {
61
- ok: false,
62
- code: 'display_name_invalid_whitespace',
63
- message: 'displayName must not include line breaks or tabs',
64
- };
65
- }
66
- if (/[\u0000-\u001F\u007F]/.test(normalized)) {
67
- return {
68
- ok: false,
69
- code: 'display_name_invalid_character',
70
- message: 'displayName contains unsupported control characters',
71
- };
72
- }
73
- return {
74
- ok: true,
75
- value: normalized,
76
- };
77
- }
78
-
79
- export function generatePublicIdentityCode({ length = PUBLIC_IDENTITY_CODE_LENGTH } = {}) {
80
- const targetLength = Number.isInteger(length) && length > 0 ? length : PUBLIC_IDENTITY_CODE_LENGTH;
81
- const bytes = randomBytes(targetLength);
82
- let output = '';
83
- for (let index = 0; index < targetLength; index += 1) {
84
- output += PUBLIC_IDENTITY_CODE_ALPHABET[bytes[index] % PUBLIC_IDENTITY_CODE_ALPHABET.length];
85
- }
86
- return output;
87
- }
88
-
89
- export function formatPublicIdentityDisplay({ displayName = null, code = null } = {}) {
90
- const normalizedDisplayName = normalizeText(displayName, null);
91
- const normalizedCode = normalizeText(code, null);
92
- if (!normalizedDisplayName || !normalizedCode) return null;
93
- return `${normalizedDisplayName}#${normalizedCode}`;
94
- }
95
-
96
- export function parsePublicIdentityDisplay(value) {
97
- const normalized = normalizeText(value, null);
98
- if (!normalized) return null;
99
- const hashIndex = normalized.lastIndexOf('#');
100
- if (hashIndex <= 0 || hashIndex >= normalized.length - 1) return null;
101
- const displayName = normalizeText(normalized.slice(0, hashIndex), null);
102
- const code = normalizeText(normalized.slice(hashIndex + 1), null)?.toUpperCase() || null;
103
- if (!displayName || !code) return null;
104
- if (displayName.includes('#')) return null;
105
- return {
106
- displayName,
107
- code,
108
- identity: `${displayName}#${code}`,
109
- };
110
- }
111
-
112
- export function buildPublicIdentityRecord(input = {}, {
113
- fallbackDisplayName = null,
114
- statusFallback = PUBLIC_IDENTITY_STATUS.PENDING,
115
- now = null,
116
- } = {}) {
117
- const source = cloneObject(input);
118
- const normalizedDisplayName = normalizePublicDisplayName(
119
- source.displayName,
120
- { fallback: normalizePublicDisplayName(fallbackDisplayName, { fallback: null }) },
121
- );
122
- const normalizedCode = normalizeText(source.code, null)?.toUpperCase() || null;
123
- const normalizedStatus = normalizeText(source.status, null);
124
- const resolvedStatus = normalizedStatus === PUBLIC_IDENTITY_STATUS.READY
125
- ? PUBLIC_IDENTITY_STATUS.READY
126
- : normalizedStatus === PUBLIC_IDENTITY_STATUS.PENDING
127
- ? PUBLIC_IDENTITY_STATUS.PENDING
128
- : (normalizedCode && normalizedDisplayName ? PUBLIC_IDENTITY_STATUS.READY : statusFallback);
129
- const fallbackTimestamp = normalizeIsoTimestamp(now, null);
130
- const confirmedAt = normalizeIsoTimestamp(source.confirmedAt, null)
131
- || (resolvedStatus === PUBLIC_IDENTITY_STATUS.READY ? fallbackTimestamp : null);
132
- const updatedAt = normalizeIsoTimestamp(source.updatedAt, fallbackTimestamp);
133
- return {
134
- displayName: normalizedDisplayName,
135
- code: normalizedCode,
136
- status: resolvedStatus,
137
- confirmedAt,
138
- updatedAt,
139
- };
140
- }
141
-
142
- export function resolvePublicIdentity(agent = {}) {
143
- const publicIdentity = buildPublicIdentityRecord(agent?.publicIdentity, {
144
- fallbackDisplayName: agent?.displayName || agent?.agentId || null,
145
- now: agent?.createdAt || null,
146
- });
147
- return {
148
- ...publicIdentity,
149
- displayIdentity: formatPublicIdentityDisplay(publicIdentity),
150
- };
151
- }
152
-
153
- export function isPublicIdentityReady(agent = {}) {
154
- return resolvePublicIdentity(agent).status === PUBLIC_IDENTITY_STATUS.READY;
155
- }
156
-
157
- export function buildPublicIdentityMissingFields(agent = {}) {
158
- const publicIdentity = resolvePublicIdentity(agent);
159
- const missingFields = [];
160
- if (!publicIdentity.displayName) {
161
- missingFields.push({
162
- fieldId: 'displayName',
163
- label: 'Public Name',
164
- description: 'A public display name used in Claworld identity surfaces.',
165
- });
166
- }
167
- if (!publicIdentity.code) {
168
- missingFields.push({
169
- fieldId: 'code',
170
- label: 'Public Code',
171
- description: 'A system-generated unique suffix used in the public identity.',
172
- });
173
- }
174
- return missingFields;
175
- }