@xfxstudio/claworld 0.1.4 → 0.2.0

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 (55) hide show
  1. package/README.md +12 -29
  2. package/openclaw.plugin.json +9 -33
  3. package/package.json +2 -10
  4. package/skills/claworld-help/SKILL.md +86 -160
  5. package/skills/claworld-join-and-chat/SKILL.md +107 -203
  6. package/skills/claworld-manage-worlds/SKILL.md +75 -392
  7. package/src/lib/chat-request.js +347 -0
  8. package/src/lib/{accepted-chat-kickoff.js → relay/kickoff-text.js} +67 -26
  9. package/src/openclaw/index.js +0 -5
  10. package/src/openclaw/installer/cli.js +14 -16
  11. package/src/openclaw/installer/core.js +13 -14
  12. package/src/openclaw/installer/doctor.js +69 -31
  13. package/src/openclaw/installer/workspace-contract.js +33 -9
  14. package/src/openclaw/plugin/claworld-channel-plugin.js +156 -625
  15. package/src/openclaw/plugin/config-schema.js +4 -16
  16. package/src/openclaw/plugin/managed-config.js +127 -75
  17. package/src/openclaw/plugin/onboarding.js +7 -3
  18. package/src/openclaw/plugin/register.js +40 -339
  19. package/src/openclaw/plugin/relay-client.js +112 -102
  20. package/src/openclaw/protocol/relay-event-protocol.js +34 -22
  21. package/src/openclaw/runtime/canonical-result-builder.js +15 -5
  22. package/src/openclaw/runtime/demo-session-bootstrap.js +0 -4
  23. package/src/openclaw/runtime/feedback-helper.js +3 -2
  24. package/src/openclaw/runtime/inbound-session-router.js +28 -20
  25. package/src/openclaw/runtime/outbound-session-bridge.js +21 -9
  26. package/src/openclaw/runtime/product-shell-helper.js +45 -637
  27. package/src/openclaw/runtime/runtime-path.js +2 -2
  28. package/src/openclaw/runtime/system-message-orchestrator.js +1 -1
  29. package/src/openclaw/runtime/tool-contracts.js +36 -258
  30. package/src/openclaw/runtime/world-moderation-helper.js +11 -65
  31. package/src/product-shell/catalog/default-world-catalog.js +15 -33
  32. package/src/product-shell/contracts/candidate-feed.js +40 -5
  33. package/src/product-shell/contracts/chat-request-approval-policy.js +3 -3
  34. package/src/product-shell/contracts/world-manifest.js +134 -161
  35. package/src/product-shell/contracts/world-orchestration.js +55 -326
  36. package/src/product-shell/feedback/feedback-routes.js +4 -3
  37. package/src/product-shell/feedback/feedback-service.js +11 -8
  38. package/src/product-shell/index.js +6 -7
  39. package/src/product-shell/matching/matchmaking-service.js +39 -5
  40. package/src/product-shell/membership/membership-service.js +125 -147
  41. package/src/product-shell/onboarding/onboarding-service.js +2 -2
  42. package/src/product-shell/orchestration/world-conversation-orchestrator.js +30 -0
  43. package/src/product-shell/orchestration/world-conversation-text.js +231 -0
  44. package/src/product-shell/results/result-service.js +9 -3
  45. package/src/product-shell/search/search-service.js +28 -1
  46. package/src/product-shell/social/chat-request-routes.js +0 -1
  47. package/src/product-shell/social/chat-request-service.js +1 -102
  48. package/src/product-shell/worlds/world-admin-service.js +86 -277
  49. package/src/product-shell/worlds/world-authorization.js +3 -5
  50. package/src/product-shell/worlds/world-routes.js +8 -38
  51. package/src/product-shell/worlds/world-service.js +3 -3
  52. package/src/product-shell/worlds/world-text.js +77 -0
  53. package/src/lib/runtime-guidance.js +0 -457
  54. package/src/openclaw/runtime/world-session-startup.js +0 -1
  55. package/src/product-shell/orchestration/session-orchestrator.js +0 -38
@@ -99,7 +99,7 @@ const SINGLE_ACCOUNT_PROPERTIES = {
99
99
  toolProfile: {
100
100
  type: 'string',
101
101
  enum: ['minimal', 'default', 'world', 'full'],
102
- description: 'Managed Claworld tool visibility profile. Legacy "world" normalizes to "default".',
102
+ description: 'Legacy ignored field retained for backward-compatible config parsing.',
103
103
  },
104
104
  heartbeatSeconds: {
105
105
  type: 'integer',
@@ -119,7 +119,7 @@ const SINGLE_ACCOUNT_PROPERTIES = {
119
119
  sessionTarget: {
120
120
  type: 'string',
121
121
  enum: ['subagent', 'mainagent'],
122
- default: 'subagent',
122
+ default: 'mainagent',
123
123
  },
124
124
  fallbackTarget: {
125
125
  type: 'string',
@@ -169,18 +169,6 @@ const SINGLE_ACCOUNT_PROPERTIES = {
169
169
  description: 'Legacy alias. `true` maps to `approval.mode = "open"` and `false` maps to `approval.mode = "manual_review"`.',
170
170
  default: false,
171
171
  },
172
- maxTurns: {
173
- type: 'integer',
174
- minimum: 1,
175
- description: 'Legacy ignored field. Approval policy no longer carries session turn controls.',
176
- default: 4,
177
- },
178
- turnTimeoutMs: {
179
- type: 'integer',
180
- minimum: 1000,
181
- description: 'Legacy ignored field. Approval policy no longer carries session timeout controls.',
182
- default: 30000,
183
- },
184
172
  },
185
173
  },
186
174
  testing: {
@@ -230,7 +218,7 @@ export const claworldChannelConfigSchema = {
230
218
  description:
231
219
  '最小 OpenClaw claworld channel 配置;支持单账号或 accounts.<id> 多账号模式。canonical flow uses appToken + registration, while relay/localAgent fields remain compatibility aliases.',
232
220
  routingShape: {
233
- sessionTarget: 'subagent',
221
+ sessionTarget: 'mainagent',
234
222
  fallbackTarget: 'mainagent',
235
223
  allowHumanInterrupt: true,
236
224
  },
@@ -344,7 +332,7 @@ export function validateClaworldChannelConfig(config = {}, accountId = null) {
344
332
  errors.push({ code: 'invalid_heartbeat_seconds', value: candidate.heartbeatSeconds });
345
333
  }
346
334
 
347
- const sessionTarget = candidate.routing?.sessionTarget || 'subagent';
335
+ const sessionTarget = candidate.routing?.sessionTarget || 'mainagent';
348
336
  const fallbackTarget = candidate.routing?.fallbackTarget || 'mainagent';
349
337
  if (!['subagent', 'mainagent'].includes(sessionTarget)) {
350
338
  errors.push({ code: 'invalid_session_target', value: sessionTarget });
@@ -13,13 +13,15 @@ import {
13
13
  normalizeChatRequestApprovalMode,
14
14
  } from '../../product-shell/contracts/chat-request-approval-policy.js';
15
15
 
16
- export const DEFAULT_CLAWORLD_SERVER_URL = 'https://claworld.zy-sj.com';
16
+ export const DEFAULT_CLAWORLD_SERVER_URL = 'https://clawold.love';
17
17
  export const DEFAULT_CLAWORLD_API_KEY = 'local-test';
18
- export const DEFAULT_CLAWORLD_AGENT_ID = 'claworld';
18
+ export const DEFAULT_CLAWORLD_AGENT_ID = 'main';
19
19
  export const DEFAULT_CLAWORLD_ACCOUNT_ID = 'claworld';
20
20
  export const DEFAULT_CLAWORLD_TOOL_PROFILE = 'default';
21
21
  export const DEFAULT_CLAWORLD_DM_SCOPE = 'per-channel-peer';
22
22
  export const DEFAULT_CLAWORLD_APPROVAL_MODE = DEFAULT_CHAT_REQUEST_APPROVAL_POLICY_MODE;
23
+ export const DEFAULT_CLAWORLD_SESSION_TARGET = 'mainagent';
24
+ export const DEFAULT_CLAWORLD_FALLBACK_TARGET = 'mainagent';
23
25
 
24
26
  export const TOOL_PROFILES = CLAWORLD_TOOL_PROFILES;
25
27
 
@@ -107,24 +109,61 @@ function findManagedAccountEntry(config = {}, accountId) {
107
109
  return {};
108
110
  }
109
111
 
112
+ function inferExistingAgentId(config = {}, accountId = DEFAULT_CLAWORLD_ACCOUNT_ID) {
113
+ const bindings = Array.isArray(config?.bindings) ? config.bindings : [];
114
+ const bindingMatch = bindings
115
+ .map((item) => ensureObject(item))
116
+ .find((item) => ensureObject(item.match).channel === 'claworld'
117
+ && normalizeText(ensureObject(item.match).accountId, null) === accountId
118
+ && normalizeText(item.agentId, null));
119
+ if (bindingMatch?.agentId) return normalizeText(bindingMatch.agentId, null);
120
+
121
+ const agents = Array.isArray(config?.agents?.list) ? config.agents.list : [];
122
+ if (agents.some((item) => ensureObject(item).id === DEFAULT_CLAWORLD_AGENT_ID)) {
123
+ return DEFAULT_CLAWORLD_AGENT_ID;
124
+ }
125
+ if (agents.length === 1) {
126
+ return normalizeText(ensureObject(agents[0]).id, DEFAULT_CLAWORLD_AGENT_ID);
127
+ }
128
+ return DEFAULT_CLAWORLD_AGENT_ID;
129
+ }
130
+
131
+ const MANAGED_LEGACY_BUNDLED_SKILL_NAMES = Object.freeze([
132
+ 'claworld-join-and-chat',
133
+ 'claworld-manage-worlds',
134
+ 'claworld-help',
135
+ ]);
136
+
137
+ function hasOnlyManagedBundledSkills(value) {
138
+ if (!Array.isArray(value) || value.length === 0) return false;
139
+ return value.every((skillName) => MANAGED_LEGACY_BUNDLED_SKILL_NAMES.includes(skillName));
140
+ }
141
+
110
142
  function buildManagedAgentEntry(options = {}) {
111
- const managedSkills = resolveManagedAgentSkills({ toolProfile: options.toolProfile });
112
143
  return {
113
144
  id: options.agentId,
114
145
  workspace: options.workspace,
115
- ...(managedSkills === undefined ? {} : { skills: managedSkills }),
116
146
  ...(options.agentDirExplicit && options.agentDir ? { agentDir: options.agentDir } : {}),
117
147
  };
118
148
  }
119
149
 
150
+ function buildManagedRoutingEntry(options = {}, existingRouting = {}) {
151
+ return {
152
+ ...ensureObject(existingRouting),
153
+ sessionTarget: normalizeText(options.sessionTarget, DEFAULT_CLAWORLD_SESSION_TARGET),
154
+ fallbackTarget: normalizeText(options.fallbackTarget, DEFAULT_CLAWORLD_FALLBACK_TARGET),
155
+ allowHumanInterrupt: existingRouting?.allowHumanInterrupt !== false,
156
+ };
157
+ }
158
+
120
159
  function buildManagedAccountEntry(options = {}) {
121
160
  const base = {
122
161
  enabled: true,
123
162
  serverUrl: options.serverUrl,
124
163
  apiKey: options.apiKey,
125
164
  accountId: options.accountId,
126
- toolProfile: options.toolProfile,
127
165
  name: normalizeText(options.name, normalizeText(options.displayName, null)),
166
+ routing: buildManagedRoutingEntry(options),
128
167
  approval: {
129
168
  mode: normalizeChatRequestApprovalMode(options.approvalMode, DEFAULT_CLAWORLD_APPROVAL_MODE),
130
169
  },
@@ -162,8 +201,8 @@ function buildMergedAccountEntry(existingAccount = {}, options = {}) {
162
201
  serverUrl: options.serverUrl,
163
202
  apiKey: options.apiKey,
164
203
  accountId: options.accountId,
165
- toolProfile: options.toolProfile,
166
204
  name: normalizeText(options.name, normalizeText(existingAccount.name, normalizeText(options.displayName, null))),
205
+ routing: buildManagedRoutingEntry(options, existingAccount.routing),
167
206
  approval: {
168
207
  ...existingApproval,
169
208
  mode: normalizeChatRequestApprovalMode(options.approvalMode, DEFAULT_CLAWORLD_APPROVAL_MODE),
@@ -179,6 +218,7 @@ function buildMergedAccountEntry(existingAccount = {}, options = {}) {
179
218
  ? { relay: existingRelay }
180
219
  : {}),
181
220
  };
221
+ delete merged.toolProfile;
182
222
 
183
223
  if (options.appToken) {
184
224
  return {
@@ -344,7 +384,7 @@ ${identityLine}
344
384
 
345
385
  Use this file for durable Claworld-specific notes only.
346
386
 
347
- - keep world rules, pairing context, and recurring counterpart preferences here when they help future Claworld sessions
387
+ - keep world rules, pairing context, and recurring counterpart preferences here when they help future Claworld conversations
348
388
  - do not duplicate a full standalone OpenClaw bootstrap/persona here
349
389
  - prefer channel/world-specific memory over general-purpose assistant memory
350
390
  `;
@@ -380,15 +420,24 @@ export function resolveClaworldManagedRuntimeOptions({
380
420
  overrides = {},
381
421
  } = {}) {
382
422
  const resolvedAccountId = normalizeText(accountId, DEFAULT_CLAWORLD_ACCOUNT_ID);
383
- const agentId = normalizeText(overrides.agentId, resolvedAccountId);
423
+ const attachToExistingAgent = overrides.attachToExistingAgent !== false;
424
+ const inferredAgentId = inferExistingAgentId(cfg, resolvedAccountId);
425
+ const agentId = normalizeText(overrides.agentId, inferredAgentId);
384
426
  const existingAgent = findAgentEntry(cfg, agentId);
385
427
  const existingAccount = findManagedAccountEntry(cfg, resolvedAccountId);
386
428
  const replaceManagedRuntime = overrides.replaceManagedRuntime !== false;
387
- const defaultWorkspace = resolveDefaultManagedWorkspace(agentId);
429
+ const explicitWorkspace = normalizeText(overrides.workspace, null);
430
+ const manageAgentEntry = overrides.manageAgentEntry === true
431
+ || overrides.agentDirExplicit === true
432
+ || attachToExistingAgent !== true;
433
+ const manageWorkspace = overrides.manageWorkspace === true
434
+ || Boolean(explicitWorkspace)
435
+ || attachToExistingAgent !== true;
436
+ const defaultWorkspace = manageWorkspace ? resolveDefaultManagedWorkspace(agentId) : null;
388
437
  const workspace = normalizeText(
389
- overrides.workspace,
438
+ explicitWorkspace,
390
439
  replaceManagedRuntime
391
- ? defaultWorkspace
440
+ ? normalizeText(existingAgent?.workspace, defaultWorkspace)
392
441
  : normalizeText(existingAgent?.workspace, defaultWorkspace),
393
442
  );
394
443
  const serverUrl = normalizeText(
@@ -421,10 +470,6 @@ export function resolveClaworldManagedRuntimeOptions({
421
470
  normalizeText(input.name, resolveDefaultManagedDisplayName(resolvedAccountId)),
422
471
  );
423
472
  const name = normalizeText(overrides.name, displayName);
424
- const explicitToolProfile = normalizeText(
425
- overrides.toolProfile,
426
- normalizeText(input.toolProfile, null),
427
- );
428
473
  const existingRegistrationAgentCode = normalizeRegistrationAgentCode(
429
474
  existingAccount?.registration?.agentCode,
430
475
  normalizeRegistrationAgentCode(existingAccount?.localAgent?.agentCode, null),
@@ -449,9 +494,12 @@ export function resolveClaworldManagedRuntimeOptions({
449
494
 
450
495
  return {
451
496
  repoRoot: normalizeText(overrides.repoRoot, null),
497
+ attachToExistingAgent,
452
498
  agentId,
453
499
  accountId: resolvedAccountId,
454
500
  workspace,
501
+ manageAgentEntry,
502
+ manageWorkspace,
455
503
  agentDir: normalizeText(overrides.agentDir, null),
456
504
  agentDirExplicit: overrides.agentDirExplicit === true,
457
505
  serverUrl,
@@ -461,11 +509,6 @@ export function resolveClaworldManagedRuntimeOptions({
461
509
  displayName,
462
510
  name,
463
511
  defaultToAddress: normalizeText(overrides.defaultToAddress, null),
464
- toolProfile: resolveManagedToolProfile({
465
- cfg,
466
- existingAccount,
467
- explicitToolProfile,
468
- }),
469
512
  approvalMode,
470
513
  sessionDmScope: normalizeText(
471
514
  overrides.sessionDmScope,
@@ -476,37 +519,45 @@ export function resolveClaworldManagedRuntimeOptions({
476
519
  forceDefaultAccount: overrides.forceDefaultAccount === true,
477
520
  pluginInstallMode: normalizeText(overrides.pluginInstallMode, 'skip'),
478
521
  installPlugin: overrides.installPlugin !== false,
522
+ sessionTarget: normalizeText(overrides.sessionTarget, DEFAULT_CLAWORLD_SESSION_TARGET),
523
+ fallbackTarget: normalizeText(overrides.fallbackTarget, DEFAULT_CLAWORLD_FALLBACK_TARGET),
479
524
  };
480
525
  }
481
526
 
482
527
  export function applyClaworldManagedRuntimeConfig(inputConfig = {}, options = {}) {
483
528
  const config = JSON.parse(JSON.stringify(ensureObject(inputConfig)));
484
- const toolProfile = normalizeClaworldToolProfile(options.toolProfile);
485
- const toolNames = resolveToolNames({ toolProfile });
486
529
  const summary = [];
487
530
  const replaceManagedRuntime = options.replaceManagedRuntime !== false;
488
531
  const preserveDefaultAccount = options.preserveDefaultAccount === true;
489
532
  const sessionDmScope = normalizeText(options.sessionDmScope, DEFAULT_CLAWORLD_DM_SCOPE);
533
+ const manageAgentEntry = options.manageAgentEntry === true;
490
534
 
491
535
  if (!options.appToken && !normalizeText(options.registrationAgentCode, null)) {
492
536
  throw new Error('claworld registration agentCode is required when appToken is absent');
493
537
  }
494
538
 
495
- config.tools = ensureObject(config.tools);
496
539
  const removedManagedToolNames = new Set([
540
+ ...CLAWORLD_PUBLIC_TOOL_NAMES,
497
541
  ...CLAWORLD_COMPATIBILITY_TOOL_NAMES,
498
542
  ...CLAWORLD_RETIRED_PUBLIC_TOOL_NAMES,
499
543
  ]);
500
- const existingAllow = asStringArray(config.tools.allow);
501
- const removedHelperTools = existingAllow.filter((toolName) => removedManagedToolNames.has(toolName));
502
- config.tools.allow = uniqueStrings([
503
- ...existingAllow.filter((toolName) => !removedManagedToolNames.has(toolName)),
504
- ...toolNames,
505
- ]);
506
- if (removedHelperTools.length > 0) {
507
- summary.push(`tools.allow removed optional helper entries (${removedHelperTools.join(',')})`);
544
+ if (inputConfig?.tools && typeof inputConfig.tools === 'object') {
545
+ config.tools = ensureObject(config.tools);
546
+ const existingAllow = asStringArray(config.tools.allow);
547
+ const filteredAllow = existingAllow.filter((toolName) => !removedManagedToolNames.has(toolName));
548
+ const removedManagedTools = existingAllow.filter((toolName) => removedManagedToolNames.has(toolName));
549
+ if (removedManagedTools.length > 0) {
550
+ if (filteredAllow.length > 0) {
551
+ config.tools.allow = uniqueStrings(filteredAllow);
552
+ } else {
553
+ delete config.tools.allow;
554
+ }
555
+ summary.push(`tools.allow removed managed claworld entries (${removedManagedTools.join(',')})`);
556
+ }
557
+ if (Object.keys(config.tools).length === 0) {
558
+ delete config.tools;
559
+ }
508
560
  }
509
- summary.push(`tools.allow updated for ${toolProfile} profile (${describeToolAllowEntries(toolNames)})`);
510
561
 
511
562
  config.session = ensureObject(config.session);
512
563
  if (!Object.prototype.hasOwnProperty.call(config.session, 'dmScope')) {
@@ -516,51 +567,53 @@ export function applyClaworldManagedRuntimeConfig(inputConfig = {}, options = {}
516
567
 
517
568
  config.agents = ensureObject(config.agents);
518
569
  const existingAgentList = Array.isArray(config.agents.list) ? [...config.agents.list] : [];
519
- const managedAgentEntry = buildManagedAgentEntry(options);
520
- if (replaceManagedRuntime) {
521
- const removedAgentEntries = existingAgentList.filter((item) => ensureObject(item).id === options.agentId).length;
522
- config.agents.list = [
523
- ...existingAgentList.filter((item) => ensureObject(item).id !== options.agentId),
524
- managedAgentEntry,
525
- ];
526
- summary.push(
527
- removedAgentEntries > 0
528
- ? `replaced managed agent entry ${options.agentId}`
529
- : `added workspace-scoped agent entry ${options.agentId}`,
530
- );
531
- } else {
532
- const agentIndex = findAgentIndex(existingAgentList, options.agentId);
533
- if (agentIndex >= 0) {
534
- const existingAgent = ensureObject(existingAgentList[agentIndex]);
535
- const existingAgentDir = normalizeText(existingAgent.agentDir, null);
536
- const managedSkills = resolveManagedAgentSkills({ toolProfile: options.toolProfile });
537
- const keepExistingAgentDir = Boolean(
538
- existingAgentDir
539
- && (
540
- options.agentDirExplicit
541
- || existingAgentDir !== normalizeText(options.agentDir, null)
542
- ),
570
+ if (manageAgentEntry) {
571
+ const managedAgentEntry = buildManagedAgentEntry(options);
572
+ if (replaceManagedRuntime) {
573
+ const removedAgentEntries = existingAgentList.filter((item) => ensureObject(item).id === options.agentId).length;
574
+ config.agents.list = [
575
+ ...existingAgentList.filter((item) => ensureObject(item).id !== options.agentId),
576
+ managedAgentEntry,
577
+ ];
578
+ summary.push(
579
+ removedAgentEntries > 0
580
+ ? `replaced managed agent entry ${options.agentId}`
581
+ : `added workspace-scoped agent entry ${options.agentId}`,
543
582
  );
544
- const nextAgentEntry = {
545
- ...existingAgent,
546
- id: options.agentId,
547
- workspace: normalizeText(existingAgent.workspace, options.workspace),
548
- ...(keepExistingAgentDir ? { agentDir: existingAgentDir } : {}),
549
- ...(managedSkills === undefined ? {} : { skills: managedSkills }),
550
- };
551
- if (!keepExistingAgentDir) {
552
- delete nextAgentEntry.agentDir;
553
- }
554
- if (managedSkills === undefined) {
555
- delete nextAgentEntry.skills;
556
- }
557
- existingAgentList[agentIndex] = nextAgentEntry;
558
- summary.push(`updated existing agent entry ${options.agentId}`);
559
583
  } else {
560
- existingAgentList.push(managedAgentEntry);
561
- summary.push(`added workspace-scoped agent entry ${options.agentId}`);
584
+ const agentIndex = findAgentIndex(existingAgentList, options.agentId);
585
+ if (agentIndex >= 0) {
586
+ const existingAgent = ensureObject(existingAgentList[agentIndex]);
587
+ const existingAgentDir = normalizeText(existingAgent.agentDir, null);
588
+ const keepExistingAgentDir = Boolean(
589
+ existingAgentDir
590
+ && (
591
+ options.agentDirExplicit
592
+ || existingAgentDir !== normalizeText(options.agentDir, null)
593
+ ),
594
+ );
595
+ const nextAgentEntry = {
596
+ ...existingAgent,
597
+ id: options.agentId,
598
+ workspace: normalizeText(existingAgent.workspace, options.workspace),
599
+ ...(keepExistingAgentDir ? { agentDir: existingAgentDir } : {}),
600
+ };
601
+ if (!keepExistingAgentDir) {
602
+ delete nextAgentEntry.agentDir;
603
+ }
604
+ if (hasOnlyManagedBundledSkills(existingAgent.skills)) {
605
+ delete nextAgentEntry.skills;
606
+ }
607
+ existingAgentList[agentIndex] = nextAgentEntry;
608
+ summary.push(`updated existing agent entry ${options.agentId}`);
609
+ } else {
610
+ existingAgentList.push(managedAgentEntry);
611
+ summary.push(`added workspace-scoped agent entry ${options.agentId}`);
612
+ }
613
+ config.agents.list = existingAgentList;
562
614
  }
563
- config.agents.list = existingAgentList;
615
+ } else {
616
+ summary.push(`attached claworld account ${options.accountId} to existing local agent ${options.agentId}`);
564
617
  }
565
618
 
566
619
  config.channels = ensureObject(config.channels);
@@ -619,7 +672,6 @@ export function applyClaworldManagedRuntimeConfig(inputConfig = {}, options = {}
619
672
 
620
673
  return {
621
674
  config,
622
- toolNames,
623
675
  summary,
624
676
  canonicalAgentCode: canonicalRelayAgentCode(
625
677
  options.registrationAgentCode,
@@ -200,15 +200,19 @@ async function applyManagedOnboardingConfig({
200
200
  } = {}) {
201
201
  const managedOptions = resolveManagedOptionsFromContext({ cfg, accountId, input });
202
202
  const next = applyClaworldManagedRuntimeConfig(cfg, managedOptions);
203
- await ensureManagedWorkspaceSeed(managedOptions);
203
+ if (managedOptions.manageWorkspace) {
204
+ await ensureManagedWorkspaceSeed(managedOptions);
205
+ }
204
206
 
205
207
  const noteLines = [
206
- `Managed local agent/account: ${managedOptions.agentId}`,
208
+ `Bound local agent/account: ${managedOptions.agentId}`,
207
209
  `Remote backend: ${managedOptions.serverUrl}`,
208
210
  managedOptions.registrationAgentCode
209
211
  ? `Bootstrap mode: registration (${managedOptions.registrationAgentCode})`
210
212
  : 'Bootstrap mode: appToken/manual binding',
211
- 'This flow only refreshes plugin-side config and workspace files. It does not start a backend service.',
213
+ managedOptions.manageWorkspace
214
+ ? 'This flow refreshes plugin-side config and the dedicated claworld workspace contract. It does not start a backend service.'
215
+ : 'This flow refreshes plugin-side config and binds claworld onto the existing local agent. It does not start a backend service.',
212
216
  ];
213
217
  await prompter.note(
214
218
  noteLines.join('\n'),