@xfxstudio/claworld 2026.4.29-testing.1 → 2026.4.30-runtime-binding-fix.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.
@@ -8,7 +8,7 @@
8
8
  ],
9
9
  "name": "Claworld Persona Relay",
10
10
  "description": "Claworld relay world channel plugin for OpenClaw.",
11
- "version": "2026.4.29-testing.1",
11
+ "version": "2026.4.30-runtime-binding-fix.1",
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": "2026.4.29-testing.1",
3
+ "version": "2026.4.30-runtime-binding-fix.1",
4
4
  "description": "Claworld channel plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -2479,6 +2479,75 @@ export function createClaworldChannelPlugin({
2479
2479
  });
2480
2480
  }
2481
2481
 
2482
+ function resolveCachedAccountBinding({ runtimeConfig, accountId = null }) {
2483
+ const normalizedRuntimeConfig = applyRuntimeIdentity(runtimeConfig);
2484
+ const accountKey = resolveAccountBindingKey(normalizedRuntimeConfig, accountId || null);
2485
+ const cachedBinding = accountBindingStates.get(accountKey)?.binding || null;
2486
+ if (
2487
+ !cachedBinding
2488
+ || !cachedBinding.runtimeConfig?.serverUrl
2489
+ || cachedBinding.runtimeConfig.serverUrl !== normalizedRuntimeConfig.serverUrl
2490
+ ) {
2491
+ return null;
2492
+ }
2493
+
2494
+ return {
2495
+ ...cachedBinding,
2496
+ runtimeConfig: mergeBoundRuntimeConfig(normalizedRuntimeConfig, cachedBinding.runtimeConfig),
2497
+ bindingSource: cachedBinding.bindingSource || 'binding_cache',
2498
+ };
2499
+ }
2500
+
2501
+ function commitRuntimeBinding({
2502
+ context = {},
2503
+ runtime = null,
2504
+ runtimeSource = null,
2505
+ accountId = null,
2506
+ runtimeConfig = {},
2507
+ bindingSource = 'configured_app_token',
2508
+ relayAgent = null,
2509
+ } = {}) {
2510
+ const normalizedRuntimeConfig = applyRuntimeIdentity(runtimeConfig);
2511
+ const normalizedAccountId = normalizeClaworldText(
2512
+ normalizedRuntimeConfig.accountId,
2513
+ normalizeClaworldText(accountId, normalizeClaworldText(context.accountId, 'default')),
2514
+ );
2515
+ const accountKey = resolveAccountBindingKey(normalizedRuntimeConfig, normalizedAccountId);
2516
+ const runtimeResolution = runtimeSource
2517
+ ? { runtime, runtimeSource }
2518
+ : resolvePluginRuntimeCandidate(runtime || context.runtime || null);
2519
+ const currentRuntimeContext = accountRuntimeContexts.get(accountKey)
2520
+ || accountRuntimeContexts.get(normalizedAccountId)
2521
+ || null;
2522
+
2523
+ rememberAccountBinding({
2524
+ runtimeConfig: normalizedRuntimeConfig,
2525
+ accountId: normalizedAccountId,
2526
+ bindingSource,
2527
+ relayAgent,
2528
+ });
2529
+
2530
+ accountRuntimeContexts.set(accountKey, {
2531
+ ...(currentRuntimeContext || {}),
2532
+ runtime: currentRuntimeContext?.runtime || runtimeResolution.runtime || null,
2533
+ runtimeSource: currentRuntimeContext?.runtimeSource || runtimeResolution.runtimeSource || null,
2534
+ cfg: currentRuntimeContext?.cfg || context.cfg || null,
2535
+ accountId: normalizedAccountId,
2536
+ runtimeConfig: normalizedRuntimeConfig,
2537
+ relayAgent: relayAgent || currentRuntimeContext?.relayAgent || null,
2538
+ bindingSource,
2539
+ deferredFailure: null,
2540
+ deferredErrorMessage: null,
2541
+ });
2542
+
2543
+ return {
2544
+ accountKey,
2545
+ accountId: normalizedAccountId,
2546
+ runtimeConfig: normalizedRuntimeConfig,
2547
+ bindingSource,
2548
+ };
2549
+ }
2550
+
2482
2551
  async function ensureAccountRelayBinding({ runtimeConfig, accountId = null }) {
2483
2552
  const normalizedRuntimeConfig = applyRuntimeIdentity(runtimeConfig);
2484
2553
  const accountKey = resolveAccountBindingKey(normalizedRuntimeConfig, accountId || null);
@@ -2493,9 +2562,7 @@ export function createClaworldChannelPlugin({
2493
2562
  return {
2494
2563
  ...cachedBinding,
2495
2564
  runtimeConfig: mergeBoundRuntimeConfig(normalizedRuntimeConfig, cachedBinding.runtimeConfig),
2496
- bindingSource: cachedBinding.bindingSource === 'configured_app_token'
2497
- ? 'configured_app_token'
2498
- : 'binding_cache',
2565
+ bindingSource: cachedBinding.bindingSource || 'binding_cache',
2499
2566
  };
2500
2567
  }
2501
2568
 
@@ -2616,8 +2683,13 @@ export function createClaworldChannelPlugin({
2616
2683
  };
2617
2684
  }
2618
2685
 
2686
+ const backupAgentId = normalizeClaworldText(
2687
+ backup?.agentId,
2688
+ normalizeClaworldText(runtimeConfig?.relay?.agentId, null),
2689
+ );
2619
2690
  const restoredRuntimeConfig = applyRuntimeIdentity(runtimeConfig, {
2620
2691
  appToken: backupToken,
2692
+ agentId: backupAgentId,
2621
2693
  });
2622
2694
 
2623
2695
  try {
@@ -2625,6 +2697,7 @@ export function createClaworldChannelPlugin({
2625
2697
  runtime,
2626
2698
  accountId,
2627
2699
  appToken: backupToken,
2700
+ relayAgentId: backupAgentId,
2628
2701
  });
2629
2702
  } catch (error) {
2630
2703
  logger.warn?.(`[claworld:${accountId || 'default'}] failed to persist restored runtime appToken`, {
@@ -2652,16 +2725,89 @@ export function createClaworldChannelPlugin({
2652
2725
  accountId: runtimeConfig.accountId || accountId || null,
2653
2726
  runtimeConfig,
2654
2727
  agentId: context.agentId || runtimeConfig.relay?.agentId || null,
2655
- bindingSource: runtimeContext?.deferredFailure ? 'runtime_context_deferred' : 'runtime_context',
2728
+ bindingSource: runtimeContext?.deferredFailure
2729
+ ? 'runtime_context_deferred'
2730
+ : (runtimeContext?.bindingSource || 'runtime_context'),
2656
2731
  };
2657
2732
  }
2658
2733
 
2659
- async function resolveBoundRuntimeContext(context = {}) {
2734
+ async function resolveAccountViewRuntimeContext(context = {}) {
2660
2735
  const configuredContext = resolveConfiguredRuntimeContext(context);
2661
2736
  const cfg = configuredContext.cfg || {};
2662
2737
  const accountId = configuredContext.accountId || null;
2663
2738
  let runtimeConfig = configuredContext.runtimeConfig;
2664
- const runtimeResolution = resolvePluginRuntimeCandidate(context.runtime || null);
2739
+ const runtimeResolution = resolvePluginRuntimeCandidate(
2740
+ context.runtime || configuredContext.runtime || null,
2741
+ );
2742
+ let bindingSource = configuredContext.bindingSource || null;
2743
+ let relayAgent = configuredContext.relayAgent || null;
2744
+
2745
+ const runtimeContext = accountRuntimeContexts.get(
2746
+ resolveAccountBindingKey(runtimeConfig, accountId || null),
2747
+ ) || accountRuntimeContexts.get(accountId || 'default') || null;
2748
+ if (runtimeContext?.runtimeConfig && !runtimeContext?.deferredFailure) {
2749
+ runtimeConfig = mergeBoundRuntimeConfig(runtimeConfig, runtimeContext.runtimeConfig);
2750
+ bindingSource = runtimeContext.bindingSource || bindingSource || 'runtime_context';
2751
+ relayAgent = runtimeContext.relayAgent || relayAgent;
2752
+ }
2753
+
2754
+ const cachedBinding = resolveCachedAccountBinding({ runtimeConfig, accountId });
2755
+ if (cachedBinding && resolveRuntimeAppToken(cachedBinding.runtimeConfig)) {
2756
+ runtimeConfig = cachedBinding.runtimeConfig;
2757
+ bindingSource = cachedBinding.bindingSource || bindingSource || 'binding_cache';
2758
+ relayAgent = cachedBinding.relayAgent || relayAgent;
2759
+ }
2760
+
2761
+ if (!resolveRuntimeAppToken(runtimeConfig)) {
2762
+ const restoredBinding = await maybeRestoreRuntimeAppToken({
2763
+ runtime: runtimeResolution.runtime,
2764
+ accountId,
2765
+ runtimeConfig,
2766
+ });
2767
+ if (restoredBinding.restored) {
2768
+ runtimeConfig = restoredBinding.runtimeConfig;
2769
+ bindingSource = 'installer_state_backup';
2770
+ logger.info?.(`[claworld:${accountId || 'default'}] restored runtime binding from installer state`, {
2771
+ installerStatePath: restoredBinding.installerStatePath || null,
2772
+ relayAgentId: runtimeConfig?.relay?.agentId || null,
2773
+ });
2774
+ commitRuntimeBinding({
2775
+ context: configuredContext,
2776
+ runtime: runtimeResolution.runtime,
2777
+ runtimeSource: runtimeResolution.runtimeSource,
2778
+ accountId,
2779
+ runtimeConfig,
2780
+ bindingSource,
2781
+ relayAgent,
2782
+ });
2783
+ }
2784
+ }
2785
+
2786
+ if (resolveRuntimeAppToken(runtimeConfig) && (!bindingSource || bindingSource === 'runtime_context')) {
2787
+ bindingSource = 'configured_app_token';
2788
+ }
2789
+
2790
+ return {
2791
+ ...configuredContext,
2792
+ cfg: runtimeContext?.cfg || cfg,
2793
+ accountId: runtimeConfig.accountId || accountId || null,
2794
+ runtimeConfig,
2795
+ runtime: runtimeResolution.runtime,
2796
+ runtimeSource: runtimeResolution.runtimeSource,
2797
+ agentId: configuredContext.agentId || runtimeConfig.relay?.agentId || null,
2798
+ bindingSource,
2799
+ relayAgent,
2800
+ };
2801
+ }
2802
+
2803
+ async function resolveBoundRuntimeContext(context = {}) {
2804
+ const configuredContext = await resolveAccountViewRuntimeContext(context);
2805
+ const cfg = configuredContext.cfg || {};
2806
+ const accountId = configuredContext.accountId || null;
2807
+ let runtimeConfig = configuredContext.runtimeConfig;
2808
+ const runtimeResolution = resolvePluginRuntimeCandidate(
2809
+ context.runtime || configuredContext.runtime || null,
2810
+ );
2665
2811
  const restoredBinding = await maybeRestoreRuntimeAppToken({
2666
2812
  runtime: runtimeResolution.runtime,
2667
2813
  accountId,
@@ -2684,7 +2830,7 @@ export function createClaworldChannelPlugin({
2684
2830
  runtime: runtimeResolution.runtime,
2685
2831
  runtimeSource: runtimeResolution.runtimeSource,
2686
2832
  agentId: configuredContext.agentId || runtimeConfig.relay?.agentId || null,
2687
- bindingSource: 'runtime_context',
2833
+ bindingSource: configuredContext.bindingSource || runtimeContext.bindingSource || 'runtime_context',
2688
2834
  };
2689
2835
  }
2690
2836
  const binding = await ensureAccountRelayBinding({ runtimeConfig, accountId });
@@ -3021,7 +3167,7 @@ export function createClaworldChannelPlugin({
3021
3167
  }
3022
3168
 
3023
3169
  async function getRuntimePublicIdentity(context = {}) {
3024
- const resolvedContext = resolveConfiguredRuntimeContext(context);
3170
+ const resolvedContext = await resolveAccountViewRuntimeContext(context);
3025
3171
  return fetchPublicIdentity({
3026
3172
  runtimeConfig: resolvedContext.runtimeConfig,
3027
3173
  agentId: resolvedContext.agentId || null,
@@ -3032,7 +3178,10 @@ export function createClaworldChannelPlugin({
3032
3178
  }
3033
3179
 
3034
3180
  async function updateRuntimePublicIdentity(context = {}) {
3035
- const resolvedContext = resolveConfiguredRuntimeContext(context);
3181
+ const resolvedContext = await resolveAccountViewRuntimeContext(context);
3182
+ const runtimeResolution = resolvePluginRuntimeCandidate(
3183
+ context.runtime || resolvedContext.runtime || null,
3184
+ );
3036
3185
  const updateResult = await updatePublicIdentity({
3037
3186
  runtimeConfig: resolvedContext.runtimeConfig,
3038
3187
  agentId: resolvedContext.agentId || null,
@@ -3073,7 +3222,6 @@ async function updateRuntimePublicIdentity(context = {}) {
3073
3222
  );
3074
3223
 
3075
3224
  if (shouldPersistRuntimeBinding) {
3076
- const runtimeResolution = resolvePluginRuntimeCandidate(context.runtime || null);
3077
3225
  try {
3078
3226
  await persistRuntimeAppToken({
3079
3227
  runtime: runtimeResolution.runtime,
@@ -3087,23 +3235,19 @@ async function updateRuntimePublicIdentity(context = {}) {
3087
3235
  error: error?.message || String(error),
3088
3236
  });
3089
3237
  }
3238
+ }
3090
3239
 
3091
- rememberAccountBinding({
3240
+ if (resolveRuntimeAppToken(boundRuntimeConfig) && nextAgentId) {
3241
+ commitRuntimeBinding({
3242
+ context: resolvedContext,
3243
+ runtime: runtimeResolution.runtime,
3244
+ runtimeSource: runtimeResolution.runtimeSource,
3092
3245
  runtimeConfig: boundRuntimeConfig,
3093
3246
  accountId: resolvedContext.accountId || boundRuntimeConfig.accountId || null,
3094
- bindingSource: runtimeActivation ? 'activated_app_token' : 'configured_app_token',
3247
+ bindingSource: runtimeActivation
3248
+ ? 'activated_app_token'
3249
+ : (resolvedContext.bindingSource || 'configured_app_token'),
3095
3250
  });
3096
-
3097
- const accountKey = resolveAccountBindingKey(boundRuntimeConfig, resolvedContext.accountId || null);
3098
- const currentRuntimeContext = accountRuntimeContexts.get(accountKey) || null;
3099
- if (currentRuntimeContext) {
3100
- accountRuntimeContexts.set(accountKey, {
3101
- ...currentRuntimeContext,
3102
- runtimeConfig: boundRuntimeConfig,
3103
- deferredFailure: null,
3104
- deferredErrorMessage: null,
3105
- });
3106
- }
3107
3251
  }
3108
3252
 
3109
3253
  const payload = updateResult && typeof updateResult === 'object' && !Array.isArray(updateResult)
@@ -3289,6 +3433,7 @@ async function generateRuntimeProfileCard(context = {}) {
3289
3433
  },
3290
3434
  helpers: {
3291
3435
  resolveToolRuntimeContext: resolveBoundRuntimeContext,
3436
+ resolveToolAccountViewContext: resolveAccountViewRuntimeContext,
3292
3437
  pairing: {
3293
3438
  resolveAgentIdentity: async (context = {}) => resolveRelayAgentSummary({
3294
3439
  runtimeConfig: context.runtimeConfig || resolveClaworldRuntimeConfig(context.cfg || {}, context.accountId || null),
@@ -278,6 +278,7 @@ export async function resolveToolContext(
278
278
  }
279
279
  return {
280
280
  cfg,
281
+ runtime: api?.runtime || null,
281
282
  accountId,
282
283
  runtimeConfig,
283
284
  agentId,
@@ -673,7 +673,18 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
673
673
  ...context,
674
674
  agentId: normalizeText(params.agentId, context.agentId),
675
675
  });
676
- return buildTerminalActionResult({ tool: publicProfileTool, action, payload });
676
+ const responsePayload = action === 'get_profile'
677
+ && params.generateShareCard === true
678
+ && typeof plugin.runtime.productShell.profile?.generateShareCard === 'function'
679
+ ? {
680
+ ...payload,
681
+ shareCard: await plugin.runtime.productShell.profile.generateShareCard({
682
+ ...context,
683
+ expiresInSeconds: params.expiresInSeconds ?? null,
684
+ }),
685
+ }
686
+ : payload;
687
+ return buildTerminalActionResult({ tool: publicProfileTool, action, payload: responsePayload });
677
688
  },
678
689
  },
679
690
  {
@@ -1958,12 +1969,29 @@ function buildRegisteredTools(api, plugin) {
1958
1969
 
1959
1970
  const cfg = await loadCurrentConfig(api);
1960
1971
  const accountId = normalizeText(params.accountId, plugin.config.defaultAccountId(cfg) || null);
1961
- const runtimeConfig = plugin.config.resolveRuntimeConfig(cfg, accountId);
1972
+ const rawRuntimeConfig = plugin.config.resolveRuntimeConfig(cfg, accountId);
1973
+ const viewContext = typeof plugin.helpers?.resolveToolAccountViewContext === 'function'
1974
+ ? await plugin.helpers.resolveToolAccountViewContext({
1975
+ cfg,
1976
+ runtime: api?.runtime || null,
1977
+ accountId,
1978
+ runtimeConfig: rawRuntimeConfig,
1979
+ agentId: normalizeText(params.agentId, rawRuntimeConfig.relay?.agentId || null),
1980
+ })
1981
+ : {
1982
+ cfg,
1983
+ runtime: api?.runtime || null,
1984
+ accountId,
1985
+ runtimeConfig: rawRuntimeConfig,
1986
+ agentId: normalizeText(params.agentId, rawRuntimeConfig.relay?.agentId || null),
1987
+ bindingSource: null,
1988
+ };
1989
+ const runtimeConfig = viewContext.runtimeConfig || rawRuntimeConfig;
1962
1990
  const identityPayload = await plugin.runtime.productShell.profile.getPublicIdentity({
1963
- cfg,
1964
- accountId,
1991
+ ...viewContext,
1965
1992
  runtimeConfig,
1966
- agentId: runtimeConfig.relay?.agentId || null,
1993
+ accountId,
1994
+ agentId: normalizeText(viewContext.agentId, runtimeConfig.relay?.agentId || null),
1967
1995
  generateShareCard,
1968
1996
  expiresInSeconds: params.expiresInSeconds ?? null,
1969
1997
  });
@@ -1995,7 +2023,7 @@ function buildRegisteredTools(api, plugin) {
1995
2023
  ? (pairedAgentId ? null : 'missing_agent_id')
1996
2024
  : 'missing_app_token',
1997
2025
  bindingSource: hasConfiguredAppToken
1998
- ? 'configured_app_token'
2026
+ ? normalizeText(viewContext.bindingSource, 'configured_app_token')
1999
2027
  : (runtimeConfig.registration?.enabled === true ? 'registration_pending' : 'unbound'),
2000
2028
  runtimeConfig: pairedAgentId
2001
2029
  ? {