@xfxstudio/claworld 0.2.19 → 0.2.20

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.
@@ -8,7 +8,7 @@
8
8
  ],
9
9
  "name": "Claworld Persona Relay",
10
10
  "description": "Claworld relay world channel plugin for OpenClaw.",
11
- "version": "0.2.19",
11
+ "version": "0.2.20",
12
12
  "configSchema": {
13
13
  "type": "object",
14
14
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xfxstudio/claworld",
3
- "version": "0.2.19",
3
+ "version": "0.2.20",
4
4
  "description": "Claworld channel plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -29,6 +29,82 @@ export function normalizeObject(value, fallback = null) {
29
29
  return value;
30
30
  }
31
31
 
32
+ function resolveRuntimeAppToken(runtimeConfig = {}) {
33
+ return normalizeText(
34
+ runtimeConfig?.appToken,
35
+ normalizeText(
36
+ runtimeConfig?.relay?.appToken,
37
+ normalizeText(runtimeConfig?.relay?.credentialToken, null),
38
+ ),
39
+ );
40
+ }
41
+
42
+ async function buildPendingPublicIdentityError({
43
+ plugin,
44
+ cfg,
45
+ accountId,
46
+ runtimeConfig,
47
+ agentId = null,
48
+ capability,
49
+ } = {}) {
50
+ const getPublicIdentity = plugin?.runtime?.productShell?.profile?.getPublicIdentity;
51
+ const capabilityLabel = normalizeText(capability, 'this Claworld capability');
52
+ const fallbackMessage = `${capabilityLabel} requires a public Claworld identity`;
53
+ if (typeof getPublicIdentity !== 'function') {
54
+ return createRuntimeBoundaryError({
55
+ code: 'public_identity_incomplete',
56
+ category: 'conflict',
57
+ status: 409,
58
+ message: fallbackMessage,
59
+ publicMessage: fallbackMessage,
60
+ recoverable: true,
61
+ context: {
62
+ accountId: normalizeText(accountId, null),
63
+ agentId: normalizeText(agentId, null),
64
+ httpStatus: 409,
65
+ backendCode: 'public_identity_incomplete',
66
+ backendMessage: fallbackMessage,
67
+ requiredAction: 'set_public_identity',
68
+ nextAction: 'set_public_identity',
69
+ nextTool: 'claworld_account',
70
+ },
71
+ });
72
+ }
73
+
74
+ const identityPayload = await getPublicIdentity({
75
+ cfg,
76
+ accountId,
77
+ runtimeConfig,
78
+ agentId: normalizeText(agentId, null),
79
+ generateShareCard: false,
80
+ expiresInSeconds: null,
81
+ });
82
+ const publicMessage = normalizeText(identityPayload?.message, fallbackMessage);
83
+ return createRuntimeBoundaryError({
84
+ code: 'public_identity_incomplete',
85
+ category: 'conflict',
86
+ status: 409,
87
+ message: publicMessage,
88
+ publicMessage,
89
+ recoverable: true,
90
+ context: {
91
+ accountId: normalizeText(accountId, null),
92
+ agentId: normalizeText(
93
+ agentId,
94
+ normalizeText(identityPayload?.agentId, null),
95
+ ),
96
+ httpStatus: 409,
97
+ backendCode: 'public_identity_incomplete',
98
+ backendMessage: publicMessage,
99
+ requiredAction: normalizeText(identityPayload?.requiredAction, 'set_public_identity'),
100
+ nextAction: normalizeText(identityPayload?.nextAction, 'set_public_identity'),
101
+ nextTool: normalizeText(identityPayload?.nextTool, 'claworld_account'),
102
+ missingFields: Array.isArray(identityPayload?.missingFields) ? identityPayload.missingFields : [],
103
+ publicIdentity: normalizeObject(identityPayload?.publicIdentity, null),
104
+ },
105
+ });
106
+ }
107
+
32
108
  function normalizePublicFieldError(fieldError = {}) {
33
109
  const fieldId = normalizeText(fieldError.fieldId, null);
34
110
  const message = normalizeText(fieldError.message, null);
@@ -142,22 +218,60 @@ export function withToolErrorBoundary(toolName, execute) {
142
218
  };
143
219
  }
144
220
 
145
- export async function resolveToolContext(api, plugin, params = {}, { bindRuntime = true } = {}) {
221
+ export async function resolveToolContext(
222
+ api,
223
+ plugin,
224
+ params = {},
225
+ {
226
+ bindRuntime = true,
227
+ requiredPublicIdentityCapability = null,
228
+ } = {},
229
+ ) {
146
230
  const cfg = await loadCurrentConfig(api);
147
231
  const accountId = normalizeText(params.accountId, plugin.config.defaultAccountId(cfg) || null);
148
232
  const runtimeConfig = plugin.config.resolveRuntimeConfig(cfg, accountId);
149
233
 
150
234
  if (bindRuntime && typeof plugin.helpers?.resolveToolRuntimeContext === 'function') {
151
- return await plugin.helpers.resolveToolRuntimeContext({
235
+ const resolvedContext = await plugin.helpers.resolveToolRuntimeContext({
152
236
  cfg,
153
237
  accountId,
154
238
  runtimeConfig,
155
239
  agentId: normalizeText(params.agentId, runtimeConfig.relay?.agentId || null),
156
240
  requesterSessionKey: normalizeText(params[INTERNAL_REQUESTER_SESSION_KEY_PARAM], null),
157
241
  });
242
+ if (
243
+ requiredPublicIdentityCapability
244
+ && (
245
+ !normalizeText(resolvedContext?.agentId, null)
246
+ || !resolveRuntimeAppToken(resolvedContext?.runtimeConfig || runtimeConfig)
247
+ )
248
+ ) {
249
+ throw await buildPendingPublicIdentityError({
250
+ plugin,
251
+ cfg,
252
+ accountId: resolvedContext?.accountId || accountId,
253
+ runtimeConfig: resolvedContext?.runtimeConfig || runtimeConfig,
254
+ agentId: resolvedContext?.agentId || null,
255
+ capability: requiredPublicIdentityCapability,
256
+ });
257
+ }
258
+ return resolvedContext;
158
259
  }
159
260
 
160
261
  const agentId = normalizeText(params.agentId, runtimeConfig.relay?.agentId || null);
262
+ if (
263
+ requiredPublicIdentityCapability
264
+ && (!agentId || !resolveRuntimeAppToken(runtimeConfig))
265
+ ) {
266
+ throw await buildPendingPublicIdentityError({
267
+ plugin,
268
+ cfg,
269
+ accountId,
270
+ runtimeConfig,
271
+ agentId,
272
+ capability: requiredPublicIdentityCapability,
273
+ });
274
+ }
161
275
  return {
162
276
  cfg,
163
277
  accountId,
@@ -275,7 +275,9 @@ function buildRegisteredTools(api, plugin) {
275
275
  ],
276
276
  }),
277
277
  async execute(_toolCallId, params = {}) {
278
- const context = await resolveToolContext(api, plugin, params);
278
+ const context = await resolveToolContext(api, plugin, params, {
279
+ requiredPublicIdentityCapability: 'join world',
280
+ });
279
281
  const payload = await plugin.runtime.productShell.joinWorld({
280
282
  ...context,
281
283
  worldId: params.worldId,
@@ -338,7 +340,9 @@ function buildRegisteredTools(api, plugin) {
338
340
  ],
339
341
  }),
340
342
  async execute(_toolCallId, params = {}) {
341
- const context = await resolveToolContext(api, plugin, params);
343
+ const context = await resolveToolContext(api, plugin, params, {
344
+ requiredPublicIdentityCapability: 'create world',
345
+ });
342
346
  const payload = await plugin.runtime.productShell.moderation.createWorld({
343
347
  ...context,
344
348
  displayName: params.displayName,
@@ -421,7 +425,9 @@ function buildRegisteredTools(api, plugin) {
421
425
  ],
422
426
  }),
423
427
  async execute(_toolCallId, params = {}) {
424
- const context = await resolveToolContext(api, plugin, params);
428
+ const context = await resolveToolContext(api, plugin, params, {
429
+ requiredPublicIdentityCapability: 'manage worlds',
430
+ });
425
431
  if (Object.prototype.hasOwnProperty.call(params, 'action')
426
432
  && !normalizeManageWorldAction(params.action, null)) {
427
433
  requireManageWorldField('action', 'action must be one of list, get, update_context, pause, close, or resume');
@@ -560,7 +566,9 @@ function buildRegisteredTools(api, plugin) {
560
566
  ],
561
567
  }),
562
568
  async execute(_toolCallId, params = {}) {
563
- const context = await resolveToolContext(api, plugin, params);
569
+ const context = await resolveToolContext(api, plugin, params, {
570
+ requiredPublicIdentityCapability: 'request chat',
571
+ });
564
572
  const payload = await plugin.helpers.social.requestChat({
565
573
  ...context,
566
574
  displayName: params.displayName,
@@ -459,7 +459,7 @@ export class ClaworldRelayClient extends EventEmitter {
459
459
  config,
460
460
  agentId,
461
461
  credential = null,
462
- clientVersion = 'claworld-plugin/0.2.19',
462
+ clientVersion = 'claworld-plugin/0.2.20',
463
463
  sessionTarget,
464
464
  fallbackTarget,
465
465
  } = {}) {
@@ -249,12 +249,14 @@ export async function fetchOwnedWorlds({
249
249
  });
250
250
 
251
251
  if (!result.ok) {
252
- logger.error?.('[claworld:moderation] managed worlds fetch failed', {
253
- status: result.status,
254
- accountId: resolvedRuntimeConfig.accountId || accountId || null,
255
- body: result.body,
256
- });
257
- throw new Error(`claworld managed worlds fetch failed: ${result.status}`);
252
+ logger.error?.('[claworld:moderation] managed worlds fetch failed', {
253
+ status: result.status,
254
+ accountId: resolvedRuntimeConfig.accountId || accountId || null,
255
+ body: result.body,
256
+ });
257
+ throw createModerationHttpError('list', result, {
258
+ accountId: resolvedRuntimeConfig.accountId || accountId || null,
259
+ });
258
260
  }
259
261
 
260
262
  return {
@@ -308,7 +310,10 @@ export async function manageModeratedWorld({
308
310
  accountId: resolvedRuntimeConfig.accountId || accountId || null,
309
311
  body: result.body,
310
312
  });
311
- throw new Error(`claworld managed world fetch failed: ${result.status}`);
313
+ throw createModerationHttpError('get', result, {
314
+ accountId: resolvedRuntimeConfig.accountId || accountId || null,
315
+ worldId: resolvedWorldId,
316
+ });
312
317
  }
313
318
 
314
319
  return normalizeManagedWorld(result.body);
@@ -336,7 +341,10 @@ export async function manageModeratedWorld({
336
341
  accountId: resolvedRuntimeConfig.accountId || accountId || null,
337
342
  body: result.body,
338
343
  });
339
- throw new Error(`claworld managed world update failed: ${result.status}`);
344
+ throw createModerationHttpError('update', result, {
345
+ accountId: resolvedRuntimeConfig.accountId || accountId || null,
346
+ worldId: resolvedWorldId,
347
+ });
340
348
  }
341
349
 
342
350
  return normalizeManagedWorld(result.body);