@xfxstudio/claworld 0.2.12 → 0.2.14

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 (62) hide show
  1. package/README.md +45 -19
  2. package/index.js +0 -1
  3. package/openclaw.plugin.json +1 -1
  4. package/package.json +1 -5
  5. package/skills/claworld-help/SKILL.md +84 -91
  6. package/skills/claworld-join-and-chat/SKILL.md +9 -9
  7. package/src/openclaw/index.js +0 -3
  8. package/src/openclaw/plugin/account-identity.js +0 -1
  9. package/src/openclaw/plugin/claworld-channel-plugin.js +8 -253
  10. package/src/openclaw/plugin/managed-config.js +1 -7
  11. package/src/openclaw/plugin/onboarding.js +128 -103
  12. package/src/openclaw/plugin/register.js +183 -232
  13. package/src/openclaw/plugin/relay-client.js +8 -5
  14. package/src/openclaw/runtime/product-shell-helper.js +11 -364
  15. package/src/openclaw/runtime/tool-contracts.js +0 -182
  16. package/src/openclaw/runtime/tool-inventory.js +4 -27
  17. package/bin/claworld.mjs +0 -9
  18. package/src/lib/agent-profile.js +0 -74
  19. package/src/lib/http-auth.js +0 -151
  20. package/src/lib/policy.js +0 -114
  21. package/src/openclaw/installer/cli.js +0 -406
  22. package/src/openclaw/installer/constants.js +0 -14
  23. package/src/openclaw/installer/core.js +0 -2122
  24. package/src/openclaw/installer/doctor.js +0 -876
  25. package/src/openclaw/installer/workspace-contract.js +0 -427
  26. package/src/product-shell/agent-cards/card-routes.js +0 -64
  27. package/src/product-shell/agent-cards/card-service.js +0 -287
  28. package/src/product-shell/agent-cards/spec-builder.js +0 -167
  29. package/src/product-shell/agent-cards/storage/image-host-storage.js +0 -192
  30. package/src/product-shell/agent-cards/storage/local-public-storage.js +0 -74
  31. package/src/product-shell/agent-cards/svg-renderer.js +0 -325
  32. package/src/product-shell/agent-cards/template-registry.js +0 -131
  33. package/src/product-shell/catalog/default-world-catalog.js +0 -38
  34. package/src/product-shell/contracts/candidate-feed.js +0 -393
  35. package/src/product-shell/contracts/world-manifest.js +0 -369
  36. package/src/product-shell/conversation-feedback/conversation-feedback-service.js +0 -261
  37. package/src/product-shell/feedback/feedback-contract.js +0 -13
  38. package/src/product-shell/feedback/feedback-routes.js +0 -98
  39. package/src/product-shell/feedback/feedback-service.js +0 -252
  40. package/src/product-shell/index.js +0 -212
  41. package/src/product-shell/matching/matchmaking-service.js +0 -395
  42. package/src/product-shell/membership/membership-service.js +0 -284
  43. package/src/product-shell/onboarding/onboarding-routes.js +0 -37
  44. package/src/product-shell/onboarding/onboarding-service.js +0 -220
  45. package/src/product-shell/orchestration/world-conversation-orchestrator.js +0 -28
  46. package/src/product-shell/profile/profile-service.js +0 -142
  47. package/src/product-shell/profile/public-identity-routes.js +0 -160
  48. package/src/product-shell/profile/public-identity-service.js +0 -192
  49. package/src/product-shell/search/search-service.js +0 -393
  50. package/src/product-shell/social/chat-request-approval-policy.js +0 -332
  51. package/src/product-shell/social/chat-request-routes.js +0 -130
  52. package/src/product-shell/social/chat-request-service.js +0 -723
  53. package/src/product-shell/social/friend-routes.js +0 -82
  54. package/src/product-shell/social/friend-service.js +0 -557
  55. package/src/product-shell/social/social-routes.js +0 -21
  56. package/src/product-shell/social/social-service.js +0 -136
  57. package/src/product-shell/worlds/world-admin-service.js +0 -486
  58. package/src/product-shell/worlds/world-authorization.js +0 -136
  59. package/src/product-shell/worlds/world-broadcast-service.js +0 -296
  60. package/src/product-shell/worlds/world-routes.js +0 -403
  61. package/src/product-shell/worlds/world-service.js +0 -89
  62. package/src/product-shell/worlds/world-text.js +0 -75
@@ -36,12 +36,9 @@ import {
36
36
  buildWorldSelectionPrompt,
37
37
  buildCandidateDeliverySummary,
38
38
  buildPostSetupWorldDirectory,
39
- broadcastWorld,
40
- fetchWorldSearch,
41
39
  fetchWorldCandidateFeed,
42
40
  fetchWorldDetail,
43
41
  joinWorld,
44
- submitWorldSearch,
45
42
  resolveWorldSelection,
46
43
  resolveWorldSelectionFlow,
47
44
  } from '../runtime/product-shell-helper.js';
@@ -53,7 +50,6 @@ import {
53
50
  serializeRuntimeBoundaryError,
54
51
  } from '../../lib/runtime-errors.js';
55
52
  import { PUBLIC_IDENTITY_STATUS } from '../../lib/public-identity.js';
56
- import { v4 as uuidv4 } from 'uuid';
57
53
 
58
54
  function normalizeRelayHttpBaseUrl(serverUrl) {
59
55
  const parsed = new URL(serverUrl);
@@ -70,8 +66,12 @@ function normalizePluginOptionalText(value) {
70
66
  return normalized || null;
71
67
  }
72
68
 
73
- function resolveClientMessageId(value = null) {
74
- return normalizePluginOptionalText(value) || `cmsg_${uuidv4()}`;
69
+ function requireClientMessageId(value = null) {
70
+ const normalized = normalizePluginOptionalText(value);
71
+ if (!normalized) {
72
+ throw new Error('claworld outbound clientMessageId is required for POST /v1/messages');
73
+ }
74
+ return normalized;
75
75
  }
76
76
 
77
77
  function buildRelayAgentSummary(item = {}) {
@@ -338,7 +338,7 @@ async function deliverRelayMessage({ runtimeConfig, to, text, fetchImpl, logger,
338
338
  }
339
339
  payload.source = normalizeClaworldText(payload.source, 'openclaw-claworld');
340
340
  payload.accountId = normalizeClaworldText(payload.accountId, runtimeConfig.accountId);
341
- const clientMessageId = resolveClientMessageId(
341
+ const clientMessageId = requireClientMessageId(
342
342
  outboundContext.clientMessageId || outboundContext.metadata?.clientMessageId || null
343
343
  );
344
344
 
@@ -433,129 +433,6 @@ function createRelayRouteError({
433
433
  });
434
434
  }
435
435
 
436
- async function createFriendRequest({
437
- runtimeConfig,
438
- fromAgentId,
439
- targetAgentId,
440
- message = null,
441
- metadata = {},
442
- fetchImpl,
443
- }) {
444
- const baseUrl = normalizeRelayHttpBaseUrl(runtimeConfig.serverUrl);
445
- const result = await fetchJson(fetchImpl, `${baseUrl}/v1/friend-requests`, {
446
- method: 'POST',
447
- headers: {
448
- 'content-type': 'application/json',
449
- ...(runtimeConfig.apiKey ? { 'x-api-key': runtimeConfig.apiKey } : {}),
450
- ...buildRuntimeAuthHeaders(runtimeConfig),
451
- },
452
- body: JSON.stringify({
453
- fromAgentId,
454
- targetAgentId,
455
- message: normalizeClaworldText(message, null),
456
- metadata: metadata && typeof metadata === 'object' && !Array.isArray(metadata) ? metadata : {},
457
- }),
458
- });
459
- if (!result.ok) {
460
- createRelayRouteError({
461
- result,
462
- runtimeConfig,
463
- code: 'friend_request_failed',
464
- publicMessage: 'failed to create friend request',
465
- context: { fromAgentId, targetAgentId },
466
- });
467
- }
468
- return result.body || {};
469
- }
470
-
471
- async function listFriendRequests({
472
- runtimeConfig,
473
- agentId,
474
- direction = null,
475
- status = null,
476
- fetchImpl,
477
- }) {
478
- const baseUrl = normalizeRelayHttpBaseUrl(runtimeConfig.serverUrl);
479
- const path = buildRelayJsonPath('/v1/friend-requests', {
480
- agentId,
481
- direction,
482
- status,
483
- });
484
- const result = await fetchJson(fetchImpl, `${baseUrl}${path}`, {
485
- method: 'GET',
486
- headers: {
487
- ...(runtimeConfig.apiKey ? { 'x-api-key': runtimeConfig.apiKey } : {}),
488
- ...buildRuntimeAuthHeaders(runtimeConfig),
489
- },
490
- });
491
- if (!result.ok) {
492
- createRelayRouteError({
493
- result,
494
- runtimeConfig,
495
- code: 'friend_request_list_failed',
496
- publicMessage: 'failed to list friend requests',
497
- context: { agentId, direction, status },
498
- });
499
- }
500
- return result.body || {};
501
- }
502
-
503
- async function acceptFriendRequest({
504
- runtimeConfig,
505
- actorAgentId,
506
- friendRequestId,
507
- fetchImpl,
508
- }) {
509
- const baseUrl = normalizeRelayHttpBaseUrl(runtimeConfig.serverUrl);
510
- const result = await fetchJson(fetchImpl, `${baseUrl}/v1/friend-requests/${encodeURIComponent(friendRequestId)}/accept`, {
511
- method: 'POST',
512
- headers: {
513
- 'content-type': 'application/json',
514
- ...(runtimeConfig.apiKey ? { 'x-api-key': runtimeConfig.apiKey } : {}),
515
- ...buildRuntimeAuthHeaders(runtimeConfig),
516
- },
517
- body: JSON.stringify({ actorAgentId }),
518
- });
519
- if (!result.ok) {
520
- createRelayRouteError({
521
- result,
522
- runtimeConfig,
523
- code: 'friend_request_accept_failed',
524
- publicMessage: 'failed to accept friend request',
525
- context: { actorAgentId, friendRequestId },
526
- });
527
- }
528
- return result.body || {};
529
- }
530
-
531
- async function rejectFriendRequest({
532
- runtimeConfig,
533
- actorAgentId,
534
- friendRequestId,
535
- fetchImpl,
536
- }) {
537
- const baseUrl = normalizeRelayHttpBaseUrl(runtimeConfig.serverUrl);
538
- const result = await fetchJson(fetchImpl, `${baseUrl}/v1/friend-requests/${encodeURIComponent(friendRequestId)}/reject`, {
539
- method: 'POST',
540
- headers: {
541
- 'content-type': 'application/json',
542
- ...(runtimeConfig.apiKey ? { 'x-api-key': runtimeConfig.apiKey } : {}),
543
- ...buildRuntimeAuthHeaders(runtimeConfig),
544
- },
545
- body: JSON.stringify({ actorAgentId }),
546
- });
547
- if (!result.ok) {
548
- createRelayRouteError({
549
- result,
550
- runtimeConfig,
551
- code: 'friend_request_reject_failed',
552
- publicMessage: 'failed to reject friend request',
553
- context: { actorAgentId, friendRequestId },
554
- });
555
- }
556
- return result.body || {};
557
- }
558
-
559
436
  async function createChatRequest({
560
437
  runtimeConfig,
561
438
  fromAgentId,
@@ -932,7 +809,7 @@ async function fetchPublicIdentity({
932
809
  recommendedDisplayName,
933
810
  nextAction: 'set_public_identity',
934
811
  requiredAction: 'set_public_identity',
935
- nextTool: 'claworld_profile',
812
+ nextTool: 'claworld_account',
936
813
  missingFields: [
937
814
  {
938
815
  fieldId: 'displayName',
@@ -2748,45 +2625,6 @@ export function createClaworldChannelPlugin({
2748
2625
  }),
2749
2626
  },
2750
2627
  social: {
2751
- sendFriendRequest: async (context = {}) => {
2752
- const resolvedContext = await resolveBoundRuntimeContext(context);
2753
- return createFriendRequest({
2754
- runtimeConfig: resolvedContext.runtimeConfig,
2755
- fromAgentId: resolvedContext.agentId || null,
2756
- targetAgentId: context.targetAgentId || null,
2757
- message: context.message || null,
2758
- metadata: context.metadata || {},
2759
- fetchImpl,
2760
- });
2761
- },
2762
- listFriendRequests: async (context = {}) => {
2763
- const resolvedContext = await resolveBoundRuntimeContext(context);
2764
- return listFriendRequests({
2765
- runtimeConfig: resolvedContext.runtimeConfig,
2766
- agentId: resolvedContext.agentId || null,
2767
- direction: context.direction || null,
2768
- status: context.status || null,
2769
- fetchImpl,
2770
- });
2771
- },
2772
- acceptFriendRequest: async (context = {}) => {
2773
- const resolvedContext = await resolveBoundRuntimeContext(context);
2774
- return acceptFriendRequest({
2775
- runtimeConfig: resolvedContext.runtimeConfig,
2776
- actorAgentId: resolvedContext.agentId || null,
2777
- friendRequestId: context.friendRequestId || null,
2778
- fetchImpl,
2779
- });
2780
- },
2781
- rejectFriendRequest: async (context = {}) => {
2782
- const resolvedContext = await resolveBoundRuntimeContext(context);
2783
- return rejectFriendRequest({
2784
- runtimeConfig: resolvedContext.runtimeConfig,
2785
- actorAgentId: resolvedContext.agentId || null,
2786
- friendRequestId: context.friendRequestId || null,
2787
- fetchImpl,
2788
- });
2789
- },
2790
2628
  requestChat: async (context = {}) => {
2791
2629
  const resolvedContext = await resolveBoundRuntimeContext(context);
2792
2630
  const requestContext = resolvedContext.requesterSessionKey
@@ -2815,15 +2653,6 @@ export function createClaworldChannelPlugin({
2815
2653
  fetchImpl,
2816
2654
  });
2817
2655
  },
2818
- listChatRequests: async (context = {}) => {
2819
- const resolvedContext = await resolveBoundRuntimeContext(context);
2820
- return listChatInbox({
2821
- runtimeConfig: resolvedContext.runtimeConfig,
2822
- agentId: resolvedContext.agentId || null,
2823
- direction: context.direction || null,
2824
- fetchImpl,
2825
- });
2826
- },
2827
2656
  acceptChatRequest: async (context = {}) => {
2828
2657
  const resolvedContext = await resolveBoundRuntimeContext(context);
2829
2658
  return acceptChatRequest({
@@ -2899,34 +2728,6 @@ export function createClaworldChannelPlugin({
2899
2728
  logger,
2900
2729
  });
2901
2730
  },
2902
- fetchWorldSearch: async (context = {}) => {
2903
- const resolvedContext = await resolveBoundRuntimeContext(context);
2904
- return fetchWorldSearch({
2905
- cfg: resolvedContext.cfg || {},
2906
- accountId: resolvedContext.accountId || null,
2907
- runtimeConfig: resolvedContext.runtimeConfig || null,
2908
- worldId: context.worldId || null,
2909
- agentId: resolvedContext.agentId || null,
2910
- query: context.query || {},
2911
- limit: context.limit ?? null,
2912
- fetchImpl,
2913
- logger,
2914
- });
2915
- },
2916
- submitWorldSearch: async (context = {}) => {
2917
- const resolvedContext = await resolveBoundRuntimeContext(context);
2918
- return submitWorldSearch({
2919
- cfg: resolvedContext.cfg || {},
2920
- accountId: resolvedContext.accountId || null,
2921
- runtimeConfig: resolvedContext.runtimeConfig || null,
2922
- worldId: context.worldId || null,
2923
- agentId: resolvedContext.agentId || null,
2924
- query: context.query || {},
2925
- limit: context.limit ?? null,
2926
- fetchImpl,
2927
- logger,
2928
- });
2929
- },
2930
2731
  resolveWorldSelection: (context = {}) => resolveWorldSelection(
2931
2732
  context.worldDirectory || {},
2932
2733
  context.selection ?? context.userChoice ?? null,
@@ -3054,52 +2855,6 @@ export function createClaworldChannelPlugin({
3054
2855
  logger,
3055
2856
  });
3056
2857
  },
3057
- fetchWorldSearch: async (context = {}) => {
3058
- const resolvedContext = await resolveBoundRuntimeContext(context);
3059
- return fetchWorldSearch({
3060
- cfg: resolvedContext.cfg || {},
3061
- accountId: resolvedContext.accountId || null,
3062
- runtimeConfig: resolvedContext.runtimeConfig || null,
3063
- worldId: context.worldId || null,
3064
- agentId: resolvedContext.agentId || null,
3065
- query: context.query || {},
3066
- limit: context.limit ?? null,
3067
- fetchImpl,
3068
- logger,
3069
- });
3070
- },
3071
- submitWorldSearch: async (context = {}) => {
3072
- const resolvedContext = await resolveBoundRuntimeContext(context);
3073
- return submitWorldSearch({
3074
- cfg: resolvedContext.cfg || {},
3075
- accountId: resolvedContext.accountId || null,
3076
- runtimeConfig: resolvedContext.runtimeConfig || null,
3077
- worldId: context.worldId || null,
3078
- agentId: resolvedContext.agentId || null,
3079
- query: context.query || {},
3080
- limit: context.limit ?? null,
3081
- fetchImpl,
3082
- logger,
3083
- });
3084
- },
3085
- broadcastWorld: async (context = {}) => {
3086
- const resolvedContext = await resolveBoundRuntimeContext(context);
3087
- return broadcastWorld({
3088
- cfg: resolvedContext.cfg || {},
3089
- accountId: resolvedContext.accountId || null,
3090
- runtimeConfig: resolvedContext.runtimeConfig || null,
3091
- worldId: context.worldId || null,
3092
- agentId: resolvedContext.agentId || null,
3093
- message: context.message || null,
3094
- payload: context.payload || {},
3095
- audience: context.audience || null,
3096
- replyPolicy: context.replyPolicy || null,
3097
- ...(Object.prototype.hasOwnProperty.call(context, 'excludeSelf') ? { excludeSelf: context.excludeSelf } : {}),
3098
- conversation: context.conversation || {},
3099
- fetchImpl,
3100
- logger,
3101
- });
3102
- },
3103
2858
  resolveWorldSelection,
3104
2859
  buildCandidateDeliverySummary,
3105
2860
  resolveWorldSelectionFlow: async (context = {}) => {
@@ -2,10 +2,8 @@ import os from 'os';
2
2
  import path from 'path';
3
3
  import {
4
4
  CLAWORLD_MINIMAL_OPENCLAW_TOOL_NAMES,
5
- CLAWORLD_COMPATIBILITY_TOOL_NAMES,
6
5
  CLAWORLD_PUBLIC_TOOL_NAMES,
7
6
  CLAWORLD_READ_ONLY_OPENCLAW_TOOL_NAMES,
8
- CLAWORLD_RETIRED_PUBLIC_TOOL_NAMES,
9
7
  CLAWORLD_TOOL_PROFILES,
10
8
  } from '../runtime/tool-inventory.js';
11
9
  import {
@@ -725,11 +723,7 @@ export function applyClaworldManagedRuntimeConfig(inputConfig = {}, options = {}
725
723
  const sessionDmScope = normalizeText(options.sessionDmScope, DEFAULT_CLAWORLD_DM_SCOPE);
726
724
  const manageAgentEntry = options.manageAgentEntry === true;
727
725
 
728
- const removedManagedToolNames = new Set([
729
- ...CLAWORLD_PUBLIC_TOOL_NAMES,
730
- ...CLAWORLD_COMPATIBILITY_TOOL_NAMES,
731
- ...CLAWORLD_RETIRED_PUBLIC_TOOL_NAMES,
732
- ]);
726
+ const removedManagedToolNames = new Set(CLAWORLD_PUBLIC_TOOL_NAMES);
733
727
  if (inputConfig?.tools && typeof inputConfig.tools === 'object') {
734
728
  config.tools = ensureObject(config.tools);
735
729
  const existingAllow = asStringArray(config.tools.allow);
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  DEFAULT_CLAWORLD_ACCOUNT_ID,
3
- DEFAULT_CLAWORLD_SERVER_URL,
4
3
  applyClaworldManagedRuntimeConfig,
5
4
  ensureObject,
6
5
  normalizeText,
@@ -11,15 +10,11 @@ import {
11
10
  inspectClaworldChannelAccount,
12
11
  listClaworldAccountIds,
13
12
  } from './config-schema.js';
14
- import {
15
- buildManagedOnboardingStatus as buildClaworldOnboardingStatus,
16
- inspectManagedClaworldInstall,
17
- seedManagedWorkspace as ensureManagedWorkspaceSeed,
18
- } from '../installer/core.js';
19
13
 
20
14
  function collectUnsupportedSetupFlags(input = {}) {
21
15
  const unsupported = [];
22
16
  const flagMap = [
17
+ ['appToken', '--app-token'],
23
18
  ['token', '--token'],
24
19
  ['tokenFile', '--token-file'],
25
20
  ['botToken', '--bot-token'],
@@ -54,89 +49,143 @@ function collectUnsupportedSetupFlags(input = {}) {
54
49
  return unsupported;
55
50
  }
56
51
 
57
- function validateClaworldSetupInput({ cfg = {}, accountId = null, input = {} } = {}) {
52
+ export function validateClaworldSetupInput({ input = {} } = {}) {
58
53
  const unsupportedFlags = collectUnsupportedSetupFlags(input);
59
54
  if (unsupportedFlags.length > 0) {
60
55
  return (
61
- 'Claworld setup only supports --name, --http-url/--url, and --app-token. ' +
62
- `Unsupported flag(s): ${unsupportedFlags.join(', ')}.`
56
+ 'Claworld host-native setup only supports an optional local account label and --http-url/--url overrides. '
57
+ + `Unsupported flag(s): ${unsupportedFlags.join(', ')}.`
63
58
  );
64
59
  }
65
60
 
66
- const inspected = inspectClaworldChannelAccount(cfg, accountId);
67
- const appToken = normalizeText(
68
- input.appToken,
69
- normalizeText(inspected?.appToken, null),
70
- );
71
-
72
61
  const serverUrl = normalizeText(input.httpUrl, normalizeText(input.url, null));
73
- if (serverUrl) {
74
- try {
75
- const parsed = new URL(serverUrl);
76
- if (!['http:', 'https:', 'ws:', 'wss:'].includes(parsed.protocol)) {
77
- return `Unsupported Claworld server URL protocol: ${parsed.protocol}`;
78
- }
79
- } catch {
80
- return `Invalid Claworld server URL: ${serverUrl}`;
81
- }
62
+ if (!serverUrl) {
63
+ return null;
82
64
  }
83
65
 
84
- const registrationDisplayName = normalizeText(
85
- input.name,
86
- normalizeText(
87
- inspected?.name,
88
- normalizeText(
89
- inspected?.registration?.displayName,
90
- normalizeText(inspected?.localAgent?.displayName, null),
91
- ),
92
- ),
93
- );
94
- if (!appToken && !registrationDisplayName) {
95
- return 'Claworld public display name is required unless you already have an appToken. Use --name <display-name> or --app-token <token>.';
66
+ try {
67
+ const parsed = new URL(serverUrl);
68
+ if (!['http:', 'https:', 'ws:', 'wss:'].includes(parsed.protocol)) {
69
+ return `Unsupported Claworld server URL protocol: ${parsed.protocol}`;
70
+ }
71
+ } catch {
72
+ return `Invalid Claworld server URL: ${serverUrl}`;
96
73
  }
97
74
 
98
75
  return null;
99
76
  }
100
77
 
101
- function currentManagedIdentityInput({ cfg = {}, accountId = null } = {}) {
102
- const inspected = inspectClaworldChannelAccount(cfg, accountId);
103
- const appToken = normalizeText(inspected?.appToken, null);
104
- if (appToken) {
105
- return {
106
- appToken,
107
- };
108
- }
78
+ function findAgentEntry(config = {}, agentId) {
79
+ const normalizedAgentId = normalizeText(agentId, null);
80
+ if (!normalizedAgentId) return null;
81
+ const list = Array.isArray(config?.agents?.list) ? config.agents.list : [];
82
+ return list
83
+ .map((entry) => ensureObject(entry))
84
+ .find((entry) => entry.id === normalizedAgentId) || null;
85
+ }
109
86
 
110
- const currentDisplayName = normalizeText(
111
- inspected?.name,
112
- normalizeText(
113
- inspected?.registration?.displayName,
114
- normalizeText(inspected?.localAgent?.displayName, null),
115
- ),
87
+ function hasClaworldBinding(config = {}, { agentId, accountId } = {}) {
88
+ const normalizedAgentId = normalizeText(agentId, null);
89
+ const normalizedAccountId = normalizeText(accountId, DEFAULT_CLAWORLD_ACCOUNT_ID);
90
+ const resolvedDefaultAccountId = defaultClaworldAccountId(config) || DEFAULT_CLAWORLD_ACCOUNT_ID;
91
+ const bindings = Array.isArray(config?.bindings) ? config.bindings : [];
92
+ return bindings.some((binding) => {
93
+ const candidate = ensureObject(binding);
94
+ const match = ensureObject(candidate.match);
95
+ const bindingChannel = normalizeText(match.channel, null);
96
+ const bindingAccountId = normalizeText(match.accountId, null);
97
+ const bindingAgentId = normalizeText(candidate.agentId, null);
98
+ if (bindingChannel !== 'claworld') return false;
99
+ if (normalizedAgentId && bindingAgentId !== normalizedAgentId) return false;
100
+ if (bindingAccountId === normalizedAccountId) return true;
101
+ return !bindingAccountId && resolvedDefaultAccountId === normalizedAccountId;
102
+ });
103
+ }
104
+
105
+ function isRelayBootstrapReady(account = {}) {
106
+ return Boolean(
107
+ account?.configured
108
+ && normalizeText(account?.appToken, null),
116
109
  );
117
- return currentDisplayName
118
- ? { name: currentDisplayName }
119
- : {};
120
110
  }
121
111
 
122
- async function collectManagedIdentityInput({ cfg = {}, prompter, accountId = null } = {}) {
123
- const currentInput = currentManagedIdentityInput({ cfg, accountId });
124
- if (currentInput.appToken) {
125
- return currentInput;
112
+ export function inspectManagedClaworldInstall({
113
+ cfg = {},
114
+ accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
115
+ input = {},
116
+ overrides = {},
117
+ } = {}) {
118
+ const configuredAccountIds = listClaworldAccountIds(cfg);
119
+ const hasAnyConfig = configuredAccountIds.length > 0 || cfg?.channels?.claworld != null;
120
+ const managedOptions = resolveClaworldManagedRuntimeOptions({
121
+ cfg,
122
+ accountId,
123
+ input,
124
+ overrides,
125
+ });
126
+ const managedAgentPresent = Boolean(findAgentEntry(cfg, managedOptions.agentId));
127
+ const managedBindingPresent = hasClaworldBinding(cfg, managedOptions);
128
+ const managedAccountPresent = configuredAccountIds.includes(managedOptions.accountId);
129
+ const accountStatus = managedAccountPresent
130
+ ? inspectClaworldChannelAccount(cfg, managedOptions.accountId)
131
+ : inspectClaworldChannelAccount({}, managedOptions.accountId);
132
+ const activationReady = isRelayBootstrapReady(accountStatus);
133
+ const setupReady = Boolean(
134
+ managedAccountPresent
135
+ && managedBindingPresent
136
+ && (managedOptions.manageAgentEntry !== true || managedAgentPresent)
137
+ );
138
+
139
+ let statusLabel = 'needs setup';
140
+ let selectionHint = 'remote relay world channel';
141
+ let quickstartScore = 5;
142
+
143
+ if (setupReady && activationReady) {
144
+ statusLabel = 'configured';
145
+ selectionHint = 'configured · ready';
146
+ quickstartScore = 2;
147
+ } else if (setupReady) {
148
+ statusLabel = 'configured (activation pending)';
149
+ selectionHint = 'configured · activation pending';
150
+ quickstartScore = 3;
151
+ } else if (managedAccountPresent && !managedBindingPresent) {
152
+ statusLabel = 'configured (binding pending)';
153
+ selectionHint = 'configured · binding pending';
154
+ quickstartScore = 4;
155
+ } else if (hasAnyConfig) {
156
+ statusLabel = 'configured (refresh recommended)';
157
+ selectionHint = 'configured · refresh recommended';
158
+ quickstartScore = 4;
126
159
  }
127
160
 
128
- const name = await prompter.text({
129
- message: 'Choose the public display name to bootstrap this Claworld agent',
130
- initialValue: currentInput.name || '',
131
- placeholder: 'Claworld Agent',
132
- validate: (value) => {
133
- const message = validateClaworldSetupInput({ input: { name: value } });
134
- return message || undefined;
135
- },
136
- });
161
+ return {
162
+ hasAnyConfig,
163
+ configuredAccountIds,
164
+ defaultAccountId: defaultClaworldAccountId(cfg) || null,
165
+ managedOptions,
166
+ managedAccountPresent,
167
+ managedAgentPresent,
168
+ managedBindingPresent,
169
+ accountStatus,
170
+ activationReady,
171
+ setupReady,
172
+ statusLabel,
173
+ selectionHint,
174
+ quickstartScore,
175
+ };
176
+ }
137
177
 
178
+ export function buildClaworldOnboardingStatus({
179
+ cfg = {},
180
+ accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
181
+ } = {}) {
182
+ const inspection = inspectManagedClaworldInstall({ cfg, accountId });
138
183
  return {
139
- name,
184
+ configured: inspection.setupReady,
185
+ statusLines: [`Claworld: ${inspection.statusLabel}`],
186
+ selectionHint: inspection.selectionHint,
187
+ quickstartScore: inspection.quickstartScore,
188
+ activationReady: inspection.activationReady,
140
189
  };
141
190
  }
142
191
 
@@ -178,7 +227,7 @@ function resolveManagedOptionsFromContext({ cfg = {}, accountId = null, input =
178
227
  input: resolvedInput,
179
228
  overrides: {
180
229
  ...overrides,
181
- ...(normalizeText(normalizedInput.name, null) ? { displayName: normalizedInput.name } : {}),
230
+ ...(normalizeText(normalizedInput.name, null) ? { name: normalizedInput.name } : {}),
182
231
  },
183
232
  });
184
233
  }
@@ -192,19 +241,14 @@ async function applyManagedOnboardingConfig({
192
241
  } = {}) {
193
242
  const managedOptions = resolveManagedOptionsFromContext({ cfg, accountId, input });
194
243
  const next = applyClaworldManagedRuntimeConfig(cfg, managedOptions);
195
- if (managedOptions.manageWorkspace) {
196
- await ensureManagedWorkspaceSeed(managedOptions);
197
- }
198
244
 
199
245
  const noteLines = [
200
246
  `Bound local agent/account: ${managedOptions.agentId}`,
201
247
  `Remote backend: ${managedOptions.serverUrl}`,
202
248
  managedOptions.appToken
203
249
  ? 'Activation state: ready via configured appToken'
204
- : 'Activation state: pending until claworld_profile runs',
205
- managedOptions.manageWorkspace
206
- ? 'This flow refreshes plugin-side config and the dedicated claworld workspace contract. It does not start a backend service.'
207
- : 'This flow refreshes plugin-side config and binds claworld onto the existing local agent. It does not start a backend service.',
250
+ : 'Activation state: pending until claworld_account(action=update_identity) runs',
251
+ 'This flow refreshes plugin-side config and binds claworld onto the selected local agent. It does not run installer commands or start a backend service.',
208
252
  ];
209
253
  await prompter.note(
210
254
  noteLines.join('\n'),
@@ -230,7 +274,7 @@ export const claworldSetupAdapter = {
230
274
  return accountIds.length > 0 ? defaultClaworldAccountId(cfg) : DEFAULT_CLAWORLD_ACCOUNT_ID;
231
275
  },
232
276
  applyAccountName: ({ cfg, accountId, name }) => applyManagedAccountName({ cfg, accountId, name }),
233
- validateInput: ({ cfg, accountId, input }) => validateClaworldSetupInput({ cfg, accountId, input }),
277
+ validateInput: ({ input }) => validateClaworldSetupInput({ input }),
234
278
  applyAccountConfig: ({ cfg, accountId, input }) => {
235
279
  const managedOptions = resolveManagedOptionsFromContext({ cfg, accountId, input });
236
280
  return applyClaworldManagedRuntimeConfig(cfg, managedOptions).config;
@@ -249,39 +293,20 @@ export const claworldOnboardingAdapter = {
249
293
  }),
250
294
  };
251
295
  },
252
- configure: async ({ cfg, prompter, accountOverrides }) => {
253
- const input = await collectManagedIdentityInput({
254
- cfg,
255
- prompter,
256
- accountId: accountOverrides?.claworld,
257
- });
258
- return await applyManagedOnboardingConfig({
296
+ configure: async ({ cfg, prompter, accountOverrides }) =>
297
+ applyManagedOnboardingConfig({
259
298
  cfg,
260
299
  prompter,
261
300
  accountId: accountOverrides?.claworld,
262
301
  phase: 'setup',
263
- input,
264
- });
265
- },
266
- configureWhenConfigured: async ({ cfg, prompter, accountOverrides }) => {
267
- const input = await collectManagedIdentityInput({
268
- cfg,
269
- prompter,
270
- accountId: accountOverrides?.claworld,
271
- });
272
- return await applyManagedOnboardingConfig({
302
+ input: {},
303
+ }),
304
+ configureWhenConfigured: async ({ cfg, prompter, accountOverrides }) =>
305
+ applyManagedOnboardingConfig({
273
306
  cfg,
274
307
  prompter,
275
308
  accountId: accountOverrides?.claworld,
276
309
  phase: 'refresh',
277
- input,
278
- });
279
- },
280
- };
281
-
282
- export {
283
- buildClaworldOnboardingStatus,
284
- ensureManagedWorkspaceSeed,
285
- inspectManagedClaworldInstall,
286
- validateClaworldSetupInput,
310
+ input: {},
311
+ }),
287
312
  };