@xfxstudio/claworld 2026.6.3-testing.1 → 2026.6.3-testing.2

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.
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "name": "Claworld Persona Relay",
19
19
  "description": "Claworld relay world channel plugin for OpenClaw.",
20
- "version": "2026.6.3-testing.1",
20
+ "version": "2026.6.3-testing.2",
21
21
  "configSchema": {
22
22
  "type": "object",
23
23
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xfxstudio/claworld",
3
- "version": "2026.6.3-testing.1",
3
+ "version": "2026.6.3-testing.2",
4
4
  "description": "Claworld channel plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -88,6 +88,8 @@ Before joining a world, read the world context, rules, participant requirements,
88
88
 
89
89
  The joined-world profile is `participantContextText`: the world-scoped profile submitted with `claworld_manage_worlds(action=join_world)`. It tells this specific world who your human is here, what they want to do or meet, what context they bring, and what boundaries matter. It later affects member search, world-scoped conversations, and how other participants understand them.
90
90
 
91
+ join_world 前必须向用户展示你拟用的exact participantContextText 并获得确认。用户让你加入只代表启动加入流程。
92
+
91
93
  Treat `.claworld/context/PROFILE.md` as private stable memory that may help you ask better questions. Use it carefully, and ask before putting sensitive or context-dependent facts into a joined-world profile.
92
94
 
93
95
  Protect the human from invented participant context. If any important participant content is uncertain, ask the human first.
@@ -267,10 +267,6 @@ function normalizeClaworldText(value, fallback = null) {
267
267
  return normalized || fallback;
268
268
  }
269
269
 
270
- function isClaworldPlainObject(value) {
271
- return value && typeof value === 'object' && !Array.isArray(value);
272
- }
273
-
274
270
  function resolveNormalizedText(value, fallback = null) {
275
271
  return normalizeClaworldText(value, fallback);
276
272
  }
@@ -3313,196 +3309,48 @@ export function createClaworldChannelPlugin({
3313
3309
  return promise;
3314
3310
  }
3315
3311
 
3316
- function buildRuntimeAppTokenAccountConfig(existingAccount = {}, {
3317
- accountId,
3318
- appToken,
3319
- relayAgentId = null,
3320
- runtimeConfig = null,
3321
- } = {}) {
3322
- const account = isClaworldPlainObject(existingAccount) ? existingAccount : {};
3323
- const sourceRuntimeConfig = isClaworldPlainObject(runtimeConfig) ? runtimeConfig : {};
3324
- const existingRelay = isClaworldPlainObject(account.relay) ? account.relay : {};
3325
- const runtimeRelay = isClaworldPlainObject(sourceRuntimeConfig.relay) ? sourceRuntimeConfig.relay : {};
3326
- const normalizedAccountId = normalizeClaworldText(accountId, normalizeClaworldText(sourceRuntimeConfig.accountId, null));
3327
- const normalizedRelayAgentId = normalizeClaworldText(
3328
- relayAgentId,
3329
- normalizeClaworldText(existingRelay.agentId, normalizeClaworldText(runtimeRelay.agentId, null)),
3330
- );
3331
- const normalizedAppToken = normalizeClaworldText(appToken, resolveRuntimeAppToken(sourceRuntimeConfig));
3332
- const serverUrl = normalizeClaworldText(account.serverUrl, normalizeClaworldText(sourceRuntimeConfig.serverUrl, null));
3333
- const apiKey = normalizeClaworldText(account.apiKey, normalizeClaworldText(sourceRuntimeConfig.apiKey, null));
3334
- const name = normalizeClaworldText(account.name, normalizeClaworldText(sourceRuntimeConfig.name, null));
3335
- const toolProfile = normalizeClaworldText(account.toolProfile, normalizeClaworldText(sourceRuntimeConfig.toolProfile, null));
3336
- const heartbeatSeconds = Number.isInteger(account.heartbeatSeconds)
3337
- ? account.heartbeatSeconds
3338
- : (Number.isInteger(sourceRuntimeConfig.heartbeatSeconds) ? sourceRuntimeConfig.heartbeatSeconds : null);
3339
- const reconnect = typeof account.reconnect === 'boolean'
3340
- ? account.reconnect
3341
- : (typeof sourceRuntimeConfig.reconnect === 'boolean' ? sourceRuntimeConfig.reconnect : null);
3342
- const routing = isClaworldPlainObject(account.routing)
3343
- ? account.routing
3344
- : (isClaworldPlainObject(sourceRuntimeConfig.routing) ? sourceRuntimeConfig.routing : null);
3345
- const testing = isClaworldPlainObject(account.testing)
3346
- ? account.testing
3347
- : (isClaworldPlainObject(sourceRuntimeConfig.testing) ? sourceRuntimeConfig.testing : null);
3348
-
3349
- const nextAccount = {
3350
- ...account,
3351
- enabled: typeof account.enabled === 'boolean'
3352
- ? account.enabled
3353
- : (typeof sourceRuntimeConfig.enabled === 'boolean' ? sourceRuntimeConfig.enabled : true),
3354
- ...(serverUrl ? { serverUrl } : {}),
3355
- ...(apiKey ? { apiKey } : {}),
3356
- ...(normalizedAccountId ? { accountId: normalizedAccountId } : {}),
3357
- ...(normalizedAppToken ? { appToken: normalizedAppToken } : {}),
3358
- ...(name ? { name } : {}),
3359
- ...(toolProfile ? { toolProfile } : {}),
3360
- ...(heartbeatSeconds ? { heartbeatSeconds } : {}),
3361
- ...(typeof reconnect === 'boolean' ? { reconnect } : {}),
3362
- ...(routing ? { routing } : {}),
3363
- ...(testing ? { testing } : {}),
3364
- };
3365
-
3366
- const relayAppToken = normalizeClaworldText(existingRelay.appToken, normalizeClaworldText(runtimeRelay.appToken, null));
3367
- const relayCredentialToken = normalizeClaworldText(
3368
- existingRelay.credentialToken,
3369
- normalizeClaworldText(runtimeRelay.credentialToken, null),
3370
- );
3371
- const relayDefaultTargetAgentId = normalizeClaworldText(
3372
- existingRelay.defaultTargetAgentId,
3373
- normalizeClaworldText(runtimeRelay.defaultTargetAgentId, null),
3374
- );
3375
- const relay = {
3376
- ...(relayAppToken ? { appToken: relayAppToken } : {}),
3377
- ...(relayCredentialToken ? { credentialToken: relayCredentialToken } : {}),
3378
- ...(relayDefaultTargetAgentId ? { defaultTargetAgentId: relayDefaultTargetAgentId } : {}),
3379
- ...(normalizedRelayAgentId ? { agentId: normalizedRelayAgentId } : {}),
3380
- };
3381
- if (Object.keys(relay).length > 0) nextAccount.relay = relay;
3382
- else delete nextAccount.relay;
3383
- delete nextAccount.registration;
3384
-
3385
- const missingRequired = [];
3386
- if (typeof nextAccount.enabled !== 'boolean') missingRequired.push('enabled');
3387
- if (!normalizeClaworldText(nextAccount.serverUrl, null)) missingRequired.push('serverUrl');
3388
- if (!normalizeClaworldText(nextAccount.apiKey, null)) missingRequired.push('apiKey');
3389
- if (!normalizeClaworldText(nextAccount.accountId, null)) missingRequired.push('accountId');
3390
-
3391
- return { account: nextAccount, missingRequired };
3392
- }
3393
-
3394
- function applyRuntimeAppTokenConfigMutation(configDraft, {
3395
- accountId,
3396
- appToken,
3397
- relayAgentId = null,
3398
- runtimeConfig = null,
3399
- } = {}) {
3400
- if (!isClaworldPlainObject(configDraft)) {
3401
- return { skipped: true, reason: 'invalid_config_draft' };
3402
- }
3403
- const normalizedAccountId = normalizeClaworldText(accountId, normalizeClaworldText(runtimeConfig?.accountId, null));
3404
- if (!normalizedAccountId || !normalizeClaworldText(appToken, resolveRuntimeAppToken(runtimeConfig))) {
3405
- return { skipped: true, reason: 'missing_account_or_token' };
3406
- }
3407
-
3408
- configDraft.channels = isClaworldPlainObject(configDraft.channels) ? configDraft.channels : {};
3409
- const claworldRoot = isClaworldPlainObject(configDraft.channels.claworld)
3410
- ? configDraft.channels.claworld
3411
- : {};
3412
- const accounts = isClaworldPlainObject(claworldRoot.accounts) ? claworldRoot.accounts : {};
3413
- const currentAccount = isClaworldPlainObject(accounts[normalizedAccountId])
3414
- ? accounts[normalizedAccountId]
3415
- : {};
3416
- const built = buildRuntimeAppTokenAccountConfig(currentAccount, {
3417
- accountId: normalizedAccountId,
3418
- appToken,
3419
- relayAgentId,
3420
- runtimeConfig,
3421
- });
3422
- if (built.missingRequired.length > 0) {
3423
- return {
3424
- skipped: true,
3425
- reason: 'missing_required_config_fields',
3426
- accountId: normalizedAccountId,
3427
- missingRequired: built.missingRequired,
3428
- };
3429
- }
3430
-
3431
- if (JSON.stringify(currentAccount) === JSON.stringify(built.account)) {
3432
- return {
3433
- skipped: true,
3434
- reason: 'already_persisted',
3435
- accountId: normalizedAccountId,
3436
- };
3437
- }
3438
-
3439
- accounts[normalizedAccountId] = built.account;
3440
- claworldRoot.accounts = accounts;
3441
- if (!normalizeClaworldText(claworldRoot.defaultAccount, null)) {
3442
- claworldRoot.defaultAccount = normalizedAccountId;
3443
- }
3444
- configDraft.channels.claworld = claworldRoot;
3445
- return {
3446
- skipped: false,
3447
- ok: true,
3448
- accountId: normalizedAccountId,
3449
- };
3450
- }
3451
-
3452
- async function persistRuntimeAppToken({ runtime, accountId, appToken, relayAgentId = null, runtimeConfig = null }) {
3312
+ async function persistRuntimeAppToken({ runtime, accountId, appToken, relayAgentId = null }) {
3453
3313
  if (!accountId || !appToken) {
3454
3314
  return { skipped: true, reason: 'missing_account_or_token' };
3455
3315
  }
3456
3316
 
3457
3317
  let configPersistResult = { skipped: true, reason: 'missing_runtime_config_io' };
3458
- try {
3459
- if (typeof runtime?.config?.mutateConfigFile === 'function') {
3460
- let mutationOutcome = null;
3461
- const mutationParams = {
3462
- base: 'source',
3463
- afterWrite: { mode: 'auto' },
3464
- mutate: (draft) => {
3465
- mutationOutcome = applyRuntimeAppTokenConfigMutation(draft, {
3466
- accountId,
3467
- appToken,
3468
- relayAgentId,
3469
- runtimeConfig,
3470
- });
3471
- return mutationOutcome;
3472
- },
3473
- };
3474
- const mutationResult = await runtime.config.mutateConfigFile(mutationParams);
3475
- configPersistResult = {
3476
- ...(mutationResult?.result || mutationOutcome || { skipped: false, ok: true }),
3477
- method: 'mutateConfigFile',
3478
- };
3479
- } else if (runtime?.config?.loadConfig && runtime?.config?.writeConfigFile) {
3480
- const currentCfg = await runtime.config.loadConfig();
3481
- const nextCfg = JSON.parse(JSON.stringify(currentCfg || {}));
3482
- const mutationOutcome = applyRuntimeAppTokenConfigMutation(nextCfg, {
3483
- accountId,
3318
+ if (runtime?.config?.loadConfig && runtime?.config?.writeConfigFile) {
3319
+ const currentCfg = await runtime.config.loadConfig();
3320
+ const nextCfg = JSON.parse(JSON.stringify(currentCfg || {}));
3321
+ nextCfg.channels = nextCfg.channels && typeof nextCfg.channels === 'object' && !Array.isArray(nextCfg.channels)
3322
+ ? nextCfg.channels
3323
+ : {};
3324
+ const claworldRoot = nextCfg.channels.claworld && typeof nextCfg.channels.claworld === 'object' && !Array.isArray(nextCfg.channels.claworld)
3325
+ ? nextCfg.channels.claworld
3326
+ : {};
3327
+ const accounts = claworldRoot.accounts && typeof claworldRoot.accounts === 'object' && !Array.isArray(claworldRoot.accounts)
3328
+ ? claworldRoot.accounts
3329
+ : {};
3330
+ const account = accounts[accountId] && typeof accounts[accountId] === 'object' && !Array.isArray(accounts[accountId])
3331
+ ? accounts[accountId]
3332
+ : {};
3333
+
3334
+ const normalizedRelayAgentId = normalizeClaworldText(relayAgentId, normalizeClaworldText(account?.relay?.agentId, null));
3335
+ const currentAppToken = normalizeClaworldText(account.appToken, null);
3336
+ const currentRelayAgentId = normalizeClaworldText(account?.relay?.agentId, null);
3337
+ if (currentAppToken === appToken && currentRelayAgentId === normalizedRelayAgentId) {
3338
+ configPersistResult = { skipped: true, reason: 'already_persisted' };
3339
+ } else {
3340
+ accounts[accountId] = {
3341
+ ...account,
3484
3342
  appToken,
3485
- relayAgentId,
3486
- runtimeConfig,
3487
- });
3488
- configPersistResult = {
3489
- ...mutationOutcome,
3490
- method: 'loadConfig_writeConfigFile',
3343
+ relay: {
3344
+ ...(account?.relay && typeof account.relay === 'object' && !Array.isArray(account.relay) ? account.relay : {}),
3345
+ ...(normalizedRelayAgentId ? { agentId: normalizedRelayAgentId } : {}),
3346
+ },
3491
3347
  };
3492
- if (!mutationOutcome.skipped) {
3493
- await runtime.config.writeConfigFile(nextCfg);
3494
- }
3348
+ delete accounts[accountId].registration;
3349
+ claworldRoot.accounts = accounts;
3350
+ nextCfg.channels.claworld = claworldRoot;
3351
+ await runtime.config.writeConfigFile(nextCfg);
3352
+ configPersistResult = { skipped: false, ok: true };
3495
3353
  }
3496
- } catch (error) {
3497
- configPersistResult = {
3498
- skipped: true,
3499
- reason: 'config_persist_failed',
3500
- error: error?.message || String(error),
3501
- };
3502
- logger.warn?.(`[claworld:${accountId || 'default'}] failed to persist runtime appToken to OpenClaw config`, {
3503
- accountId,
3504
- error: configPersistResult.error,
3505
- });
3506
3354
  }
3507
3355
 
3508
3356
  let backupPersistResult = { skipped: true, reason: 'missing_runtime_config_loader' };
@@ -3510,9 +3358,6 @@ export function createClaworldChannelPlugin({
3510
3358
  backupPersistResult = await persistClaworldRuntimeBackup({
3511
3359
  runtime,
3512
3360
  accountId,
3513
- runtimeConfig,
3514
- appToken,
3515
- relayAgentId,
3516
3361
  });
3517
3362
  } catch (error) {
3518
3363
  backupPersistResult = {
@@ -3554,10 +3399,8 @@ export function createClaworldChannelPlugin({
3554
3399
  };
3555
3400
  }
3556
3401
 
3557
- const backupAgentId = normalizeClaworldText(backup?.agentId, null);
3558
3402
  const restoredRuntimeConfig = applyRuntimeIdentity(runtimeConfig, {
3559
3403
  appToken: backupToken,
3560
- agentId: backupAgentId,
3561
3404
  });
3562
3405
 
3563
3406
  try {
@@ -3565,8 +3408,6 @@ export function createClaworldChannelPlugin({
3565
3408
  runtime,
3566
3409
  accountId,
3567
3410
  appToken: backupToken,
3568
- relayAgentId: backupAgentId,
3569
- runtimeConfig: restoredRuntimeConfig,
3570
3411
  });
3571
3412
  } catch (error) {
3572
3413
  logger.warn?.(`[claworld:${accountId || 'default'}] failed to persist restored runtime appToken`, {
@@ -3780,7 +3621,6 @@ export function createClaworldChannelPlugin({
3780
3621
  accountId: runtimeConfig.accountId,
3781
3622
  appToken: resolveRuntimeAppToken(runtimeConfig),
3782
3623
  relayAgentId: runtimeConfig.relay?.agentId || null,
3783
- runtimeConfig,
3784
3624
  });
3785
3625
  if (!persisted.skipped || persisted.backup?.skipped === false) {
3786
3626
  logger.info?.(`[claworld:${runtimeAccountId}] persisted runtime binding state`, {
@@ -4034,7 +3874,6 @@ async function updateRuntimePublicIdentity(context = {}) {
4034
3874
  accountId: resolvedContext.accountId || boundRuntimeConfig.accountId || null,
4035
3875
  appToken: nextAppToken,
4036
3876
  relayAgentId: nextAgentId,
4037
- runtimeConfig: boundRuntimeConfig,
4038
3877
  });
4039
3878
  } catch (error) {
4040
3879
  logger.warn?.('[claworld:profile] failed to persist activated runtime binding', {
@@ -2061,16 +2061,14 @@ function buildRegisteredTools(api, plugin) {
2061
2061
  }));
2062
2062
  }
2063
2063
 
2064
- const context = await resolveToolContext(api, plugin, params);
2065
- const cfg = context.cfg || await loadCurrentConfig(api);
2066
- const accountId = context.accountId;
2067
- const runtimeConfig = context.runtimeConfig || plugin.config.resolveRuntimeConfig(cfg, accountId);
2064
+ const cfg = await loadCurrentConfig(api);
2065
+ const accountId = normalizeText(params.accountId, plugin.config.defaultAccountId(cfg) || null);
2066
+ const runtimeConfig = plugin.config.resolveRuntimeConfig(cfg, accountId);
2068
2067
  const identityPayload = await plugin.runtime.productShell.profile.getPublicIdentity({
2069
- ...context,
2070
2068
  cfg,
2071
2069
  accountId,
2072
2070
  runtimeConfig,
2073
- agentId: context.agentId || runtimeConfig.relay?.agentId || null,
2071
+ agentId: runtimeConfig.relay?.agentId || null,
2074
2072
  generateShareCard,
2075
2073
  expiresInSeconds: params.expiresInSeconds ?? null,
2076
2074
  });
@@ -8,7 +8,6 @@ import {
8
8
  setClaworldManagedRuntimeBackupState,
9
9
  stripClaworldManagedRuntimeConfig,
10
10
  } from './managed-config.js';
11
- import { resolveRuntimeAppToken } from './account-identity.js';
12
11
 
13
12
  function normalizeText(value, fallback = null) {
14
13
  if (value == null) return fallback;
@@ -68,53 +67,18 @@ export async function persistClaworldRuntimeBackup({
68
67
  runtime = null,
69
68
  accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
70
69
  configPath = resolveDefaultOpenClawConfigPath(),
71
- runtimeConfig = null,
72
- appToken = null,
73
- relayAgentId = null,
74
70
  } = {}) {
75
- if (!runtime?.config?.loadConfig && !runtimeConfig && !appToken) {
71
+ if (!runtime?.config?.loadConfig) {
76
72
  return { skipped: true, reason: 'missing_runtime_config_loader' };
77
73
  }
78
74
 
79
- let currentConfig = {};
80
- if (runtime?.config?.loadConfig) {
81
- try {
82
- currentConfig = await runtime.config.loadConfig();
83
- } catch (error) {
84
- if (!runtimeConfig && !appToken) throw error;
85
- currentConfig = {};
86
- }
87
- }
88
- const { backup: configBackup } = stripClaworldManagedRuntimeConfig(currentConfig, {
75
+ const currentConfig = await runtime.config.loadConfig();
76
+ const { backup } = stripClaworldManagedRuntimeConfig(currentConfig, {
89
77
  accountId,
90
78
  preserveBackup: true,
91
79
  });
92
- const explicitRuntimeConfig = runtimeConfig && typeof runtimeConfig === 'object' && !Array.isArray(runtimeConfig)
93
- ? runtimeConfig
94
- : {};
95
- const backup = {
96
- ...configBackup,
97
- version: configBackup?.version || 1,
98
- accountId: normalizeText(configBackup?.accountId, normalizeText(explicitRuntimeConfig.accountId, accountId)),
99
- agentId: normalizeText(relayAgentId, normalizeText(configBackup?.agentId, normalizeText(explicitRuntimeConfig?.relay?.agentId, null))),
100
- serverUrl: normalizeText(configBackup?.serverUrl, normalizeText(explicitRuntimeConfig.serverUrl, null)),
101
- apiKey: normalizeText(configBackup?.apiKey, normalizeText(explicitRuntimeConfig.apiKey, null)),
102
- appToken: normalizeText(appToken, normalizeText(configBackup?.appToken, resolveRuntimeAppToken(explicitRuntimeConfig))),
103
- displayName: normalizeText(
104
- configBackup?.displayName,
105
- normalizeText(explicitRuntimeConfig.name, normalizeText(explicitRuntimeConfig.registration?.displayName, null)),
106
- ),
107
- name: normalizeText(configBackup?.name, normalizeText(explicitRuntimeConfig.name, null)),
108
- registrationDisplayName: normalizeText(
109
- configBackup?.registrationDisplayName,
110
- normalizeText(explicitRuntimeConfig.registration?.displayName, null),
111
- ),
112
- sessionDmScope: normalizeText(configBackup?.sessionDmScope, null),
113
- toolProfile: normalizeText(configBackup?.toolProfile, null),
114
- preservedAt: new Date().toISOString(),
115
- };
116
80
 
117
- if (!backup.appToken) {
81
+ if (!backup?.appToken) {
118
82
  return { skipped: true, reason: 'missing_app_token', backup: null };
119
83
  }
120
84
 
@@ -193,6 +193,7 @@ function buildClaworldManagementStartupPrompt(options = {}) {
193
193
  '',
194
194
  '## First Rule',
195
195
  'When you receive a Claworld notification, management wake, lifecycle event, or recurring Claworld management task, read the `claworld-management-session` skill before deciding what to do.',
196
+ 'A pre-compaction memory flush is a maintenance turn only. It does not satisfy, replace, or change any Claworld notification. After the flush finishes, handle the pending or next Claworld notification from scratch: read the Claworld management skill first, then decide accordingly.',
196
197
  '',
197
198
  '## What To Trust',
198
199
  'Use Claworld tools when you need current product facts: account state, public profiles, worlds, memberships, chat requests, conversation status, feedback, and delivery state.',