@xfxstudio/claworld 0.2.3 → 0.2.4

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.3",
11
+ "version": "0.2.4",
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.3",
3
+ "version": "0.2.4",
4
4
  "description": "Claworld channel plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -36,6 +36,72 @@ export const DEFAULT_VERIFICATION_DELAY_MS = 1_000;
36
36
  export const seedManagedWorkspace = seedManagedWorkspaceContract;
37
37
  const TRACKED_PLUGIN_UPDATEABLE_SOURCES = new Set(['npm', 'marketplace']);
38
38
 
39
+ function normalizeComparablePath(value) {
40
+ if (!value) return null;
41
+ return path.resolve(String(value));
42
+ }
43
+
44
+ async function resolveLocalPluginInstallTarget({
45
+ installMode = 'npm',
46
+ installSource = CLAWORLD_INSTALLER_PACKAGE_NAME,
47
+ repoRoot = null,
48
+ commandRunner = defaultCommandRunner,
49
+ cwd = process.cwd(),
50
+ env = process.env,
51
+ dryRun = false,
52
+ } = {}) {
53
+ if (installMode === 'npm') {
54
+ return {
55
+ installSource,
56
+ managedRepoRoot: repoRoot,
57
+ stagedPackageRoot: null,
58
+ };
59
+ }
60
+
61
+ const resolvedRepoRoot = normalizeComparablePath(repoRoot);
62
+ const resolvedInstallSource = normalizeComparablePath(installSource);
63
+ const derivedRepoRoot = resolvedRepoRoot
64
+ || (
65
+ resolvedInstallSource?.endsWith(`${path.sep}packages${path.sep}openclaw-plugin`)
66
+ ? path.resolve(resolvedInstallSource, '..', '..')
67
+ : null
68
+ );
69
+ const shouldStageRepo = Boolean(
70
+ derivedRepoRoot
71
+ && (
72
+ resolvedInstallSource === derivedRepoRoot
73
+ || resolvedInstallSource === path.join(derivedRepoRoot, 'packages', 'openclaw-plugin')
74
+ || resolvedInstallSource === CLAWORLD_INSTALLER_PACKAGE_NAME
75
+ ),
76
+ );
77
+
78
+ if (!shouldStageRepo) {
79
+ return {
80
+ installSource,
81
+ managedRepoRoot: installMode === 'link' ? installSource : repoRoot,
82
+ stagedPackageRoot: null,
83
+ };
84
+ }
85
+
86
+ const stagedPackageRoot = path.join(derivedRepoRoot, '.tmp', 'openclaw-plugin-package');
87
+ const buildScriptPath = path.join(derivedRepoRoot, 'scripts', 'build-openclaw-plugin-package.mjs');
88
+ if (!dryRun) {
89
+ await executeCommand({
90
+ commandRunner,
91
+ bin: process.execPath,
92
+ args: [buildScriptPath, '--output-dir', stagedPackageRoot],
93
+ cwd,
94
+ env,
95
+ dryRun,
96
+ });
97
+ }
98
+ return {
99
+ installSource: stagedPackageRoot,
100
+ managedRepoRoot: stagedPackageRoot,
101
+ stagedPackageRoot,
102
+ };
103
+ }
104
+
39
105
  function listBindings(config = {}) {
40
106
  return Array.isArray(config.bindings) ? config.bindings : [];
41
107
  }
@@ -829,6 +895,7 @@ export async function ensureClaworldPluginInstalled({
829
895
  action: before.installed ? 'refreshed_plugin_install' : 'installed_plugin',
830
896
  plugin: after,
831
897
  pluginConfig,
898
+ installSource,
832
899
  };
833
900
  } finally {
834
901
  if (bootstrap) {
@@ -1498,6 +1565,16 @@ export async function runClaworldInstallerInstall({
1498
1565
  );
1499
1566
  }
1500
1567
 
1568
+ const localPluginInstall = await resolveLocalPluginInstallTarget({
1569
+ installMode: pluginInstallMode,
1570
+ installSource: pluginInstallSource,
1571
+ repoRoot,
1572
+ commandRunner,
1573
+ cwd,
1574
+ env,
1575
+ dryRun,
1576
+ });
1577
+
1501
1578
  const plugin = await ensureClaworldPluginInstalled({
1502
1579
  openclawBin,
1503
1580
  configPath: resolvedConfigPath,
@@ -1508,7 +1585,7 @@ export async function runClaworldInstallerInstall({
1508
1585
  env,
1509
1586
  dryRun,
1510
1587
  installMode: pluginInstallMode,
1511
- installSource: pluginInstallSource,
1588
+ installSource: localPluginInstall.installSource,
1512
1589
  refresh: false,
1513
1590
  });
1514
1591
  const currentConfig = mergePluginMetadata(
@@ -1531,7 +1608,7 @@ export async function runClaworldInstallerInstall({
1531
1608
  toolProfile,
1532
1609
  approvalMode,
1533
1610
  sessionDmScope,
1534
- repoRoot,
1611
+ repoRoot: localPluginInstall.managedRepoRoot,
1535
1612
  fetchImpl,
1536
1613
  commandRunner,
1537
1614
  cwd,
@@ -1488,6 +1488,41 @@ function createDeliveryReplyDispatcher({
1488
1488
  };
1489
1489
  }
1490
1490
 
1491
+ function resolveBoundLocalAgentId({ cfg = {}, runtimeConfig = {}, relayClient } = {}) {
1492
+ const accountId = resolveNormalizedText(runtimeConfig.accountId, null);
1493
+ const bindings = Array.isArray(cfg?.bindings) ? cfg.bindings : [];
1494
+ for (const rawBinding of bindings) {
1495
+ const binding = rawBinding && typeof rawBinding === 'object' && !Array.isArray(rawBinding)
1496
+ ? rawBinding
1497
+ : {};
1498
+ const match = binding.match && typeof binding.match === 'object' && !Array.isArray(binding.match)
1499
+ ? binding.match
1500
+ : {};
1501
+ if (
1502
+ resolveNormalizedText(match.channel, null) === 'claworld'
1503
+ && resolveNormalizedText(match.accountId, null) === accountId
1504
+ && resolveNormalizedText(binding.agentId, null)
1505
+ ) {
1506
+ return resolveNormalizedText(binding.agentId, null);
1507
+ }
1508
+ }
1509
+
1510
+ const agentList = Array.isArray(cfg?.agents?.list) ? cfg.agents.list : [];
1511
+ if (agentList.length === 1) {
1512
+ const onlyAgent = agentList[0] && typeof agentList[0] === 'object' && !Array.isArray(agentList[0])
1513
+ ? agentList[0]
1514
+ : {};
1515
+ const onlyAgentId = resolveNormalizedText(onlyAgent.id, null);
1516
+ if (onlyAgentId) {
1517
+ return onlyAgentId;
1518
+ }
1519
+ }
1520
+
1521
+ return resolveNormalizedText(relayClient?.boundAgentId, null)
1522
+ || resolveNormalizedText(runtimeConfig.agentId, null)
1523
+ || 'main';
1524
+ }
1525
+
1491
1526
  async function maybeBridgeRuntimeDelivery({
1492
1527
  relayClient,
1493
1528
  runtimeConfig,
@@ -1590,10 +1625,35 @@ async function maybeBridgeRuntimeDelivery({
1590
1625
  RelayFromAgentId: fromAgentId,
1591
1626
  UntrustedContext: ContextLines,
1592
1627
  });
1628
+ const localAgentId = resolveBoundLocalAgentId({
1629
+ cfg: currentCfg,
1630
+ runtimeConfig,
1631
+ relayClient,
1632
+ });
1633
+
1634
+ if (runtime?.channel?.session?.recordInboundSession && runtime?.channel?.session?.resolveStorePath && localAgentId) {
1635
+ const storePath = runtime.channel.session.resolveStorePath(currentCfg.session?.store, {
1636
+ agentId: localAgentId,
1637
+ });
1638
+ await runtime.channel.session.recordInboundSession({
1639
+ storePath,
1640
+ sessionKey: inboundCtx.SessionKey || sessionKey,
1641
+ ctx: inboundCtx,
1642
+ onRecordError: (error) => {
1643
+ logger.error?.(`[claworld:${runtimeAccountId}] failed to record inbound session`, {
1644
+ deliveryId,
1645
+ sessionKey,
1646
+ localAgentId,
1647
+ error: error?.message || String(error),
1648
+ });
1649
+ },
1650
+ });
1651
+ }
1593
1652
 
1594
1653
  logger.info?.(`[claworld:${runtimeAccountId}] routing delivery into runtime session`, {
1595
1654
  deliveryId,
1596
1655
  sessionKey,
1656
+ localAgentId,
1597
1657
  remoteIdentity: remoteAddress,
1598
1658
  routeStatus: routed?.status || null,
1599
1659
  bodyPreview: String(Body || '').slice(0, 240),
@@ -1608,7 +1668,7 @@ async function maybeBridgeRuntimeDelivery({
1608
1668
  relayClient,
1609
1669
  deliveryId,
1610
1670
  sessionKey,
1611
- localAgentId: runtimeConfig.relay?.agentId || relayClient?.boundAgentId || null,
1671
+ localAgentId,
1612
1672
  allowReply: metadata.allowReply !== false,
1613
1673
  logger,
1614
1674
  runtimeAccountId,
@@ -202,6 +202,7 @@ function buildWorldRecord({
202
202
  status = null,
203
203
  schemaVersion = 1,
204
204
  existingMetrics = null,
205
+ existingConversationTemplate = null,
205
206
  } = {}) {
206
207
  const resolvedStatus = status || (enabled ? 'enabled' : 'draft');
207
208
  const participantContextField = buildDefaultEntryProfileField();
@@ -489,6 +490,7 @@ export function createWorldAdminService({ worldService, worldAuthorizationServic
489
490
  : (normalizeBoolean(enabled, false) ? 'enabled' : 'disabled'),
490
491
  schemaVersion: nextSchemaVersion,
491
492
  existingMetrics: existingWorld.metrics || null,
493
+ existingConversationTemplate: existingWorld.conversationTemplate || null,
492
494
  });
493
495
  } else if (enabled != null) {
494
496
  nextRecord = {