@xfxstudio/claworld 0.2.5 → 0.2.7

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 (29) hide show
  1. package/openclaw.plugin.json +1 -1
  2. package/package.json +1 -1
  3. package/skills/claworld-help/SKILL.md +2 -2
  4. package/skills/claworld-join-and-chat/SKILL.md +18 -9
  5. package/src/lib/chat-request.js +19 -0
  6. package/src/lib/relay/kickoff-text.js +6 -1
  7. package/src/openclaw/installer/core.js +16 -2
  8. package/src/openclaw/plugin/claworld-channel-plugin.js +164 -12
  9. package/src/openclaw/plugin/config-schema.js +9 -1
  10. package/src/openclaw/plugin/register.js +151 -15
  11. package/src/openclaw/plugin/relay-client.js +502 -1
  12. package/src/openclaw/runtime/demo-session-bootstrap.js +1 -2
  13. package/src/openclaw/runtime/tool-contracts.js +40 -1
  14. package/src/openclaw/runtime/tool-inventory.js +3 -3
  15. package/src/openclaw/runtime/world-moderation-helper.js +9 -13
  16. package/src/product-shell/catalog/default-world-catalog.js +12 -258
  17. package/src/product-shell/contracts/world-manifest.js +0 -38
  18. package/src/product-shell/contracts/world-orchestration.js +0 -6
  19. package/src/product-shell/index.js +1 -5
  20. package/src/product-shell/membership/membership-service.js +24 -6
  21. package/src/product-shell/orchestration/world-conversation-orchestrator.js +0 -2
  22. package/src/product-shell/orchestration/world-conversation-text.js +0 -2
  23. package/src/product-shell/social/chat-request-routes.js +24 -1
  24. package/src/product-shell/social/chat-request-service.js +185 -15
  25. package/src/product-shell/worlds/world-admin-service.js +28 -120
  26. package/src/product-shell/worlds/world-authorization.js +20 -17
  27. package/src/product-shell/worlds/world-broadcast-service.js +2 -5
  28. package/src/product-shell/worlds/world-text.js +0 -2
  29. package/src/product-shell/results/result-service.js +0 -21
@@ -1,8 +1,10 @@
1
1
  import { createClaworldChannelPlugin } from './claworld-channel-plugin.js';
2
2
  import {
3
- projectToolChatRequestListResponse,
3
+ projectToolChatInboxResponse,
4
4
  projectToolChatRequestMutationResponse,
5
5
  projectToolCreateWorldResponse,
6
+ projectToolManagedWorldResponse,
7
+ projectToolOwnedWorldsResponse,
6
8
  projectToolWorldList,
7
9
  projectToolFeedbackSubmissionResponse,
8
10
  projectToolJoinWorldResponse,
@@ -17,6 +19,8 @@ import {
17
19
  normalizeRuntimeBoundaryError,
18
20
  } from '../../lib/runtime-errors.js';
19
21
 
22
+ const INTERNAL_REQUESTER_SESSION_KEY_PARAM = '__claworldRequesterSessionKey';
23
+
20
24
  function normalizeText(value, fallback = null) {
21
25
  if (value == null) return fallback;
22
26
  const normalized = String(value).trim();
@@ -164,6 +168,7 @@ async function resolveToolContext(api, plugin, params = {}) {
164
168
  accountId,
165
169
  runtimeConfig,
166
170
  agentId: normalizeText(params.agentId, runtimeConfig.relay?.agentId || null),
171
+ requesterSessionKey: normalizeText(params[INTERNAL_REQUESTER_SESSION_KEY_PARAM], null),
167
172
  });
168
173
  }
169
174
 
@@ -173,6 +178,7 @@ async function resolveToolContext(api, plugin, params = {}) {
173
178
  accountId,
174
179
  runtimeConfig,
175
180
  agentId,
181
+ requesterSessionKey: normalizeText(params[INTERNAL_REQUESTER_SESSION_KEY_PARAM], null),
176
182
  };
177
183
  }
178
184
 
@@ -502,6 +508,120 @@ function buildRegisteredTools(api, plugin) {
502
508
  return buildToolResult(projectToolCreateWorldResponse(payload, { accountId: context.accountId }));
503
509
  },
504
510
  },
511
+ {
512
+ name: 'claworld_list_owned_worlds',
513
+ label: 'Claworld List Owned Worlds',
514
+ description: 'Owner-focused governance tool. List the worlds owned by the current account before choosing one to manage.',
515
+ metadata: buildToolMetadata({
516
+ category: 'world_management',
517
+ usageNotes: [
518
+ 'Use when the user wants to inspect or pick from worlds they own.',
519
+ 'This tool only returns owned worlds, not general directory worlds.',
520
+ 'Pair this with claworld_manage_world for owner-only worldContext updates.',
521
+ ],
522
+ examples: [
523
+ {
524
+ title: 'List owned worlds',
525
+ input: {
526
+ accountId: 'claworld',
527
+ },
528
+ outcome: 'Returns owner-managed worlds for the current account.',
529
+ },
530
+ ],
531
+ }),
532
+ parameters: objectParam({
533
+ description: 'Minimal payload for listing worlds owned by the current account.',
534
+ required: ['accountId'],
535
+ properties: {
536
+ accountId: accountIdProperty,
537
+ includeDisabled: {
538
+ type: 'boolean',
539
+ description: 'Whether to include disabled or draft owned worlds.',
540
+ },
541
+ },
542
+ examples: [
543
+ {
544
+ accountId: 'claworld',
545
+ },
546
+ ],
547
+ }),
548
+ async execute(_toolCallId, params = {}) {
549
+ const context = await resolveToolContext(api, plugin, params);
550
+ const payload = await plugin.runtime.productShell.moderation.listOwnedWorlds({
551
+ ...context,
552
+ includeDisabled: params.includeDisabled !== false,
553
+ });
554
+ return buildToolResult(projectToolOwnedWorldsResponse(payload, { accountId: context.accountId }));
555
+ },
556
+ },
557
+ {
558
+ name: 'claworld_manage_world',
559
+ label: 'Claworld Manage World',
560
+ description: 'Owner-only world management tool. Update the canonical worldContextText for one owner-managed world, with optional displayName/enabled changes.',
561
+ metadata: buildToolMetadata({
562
+ category: 'world_management',
563
+ usageNotes: [
564
+ 'Use only when the current agent owns the target world.',
565
+ 'This is the minimal management tool on the current public surface.',
566
+ 'Prefer updating worldContextText directly instead of editing legacy world schema fields.',
567
+ ],
568
+ examples: [
569
+ {
570
+ title: 'Update one owned world context',
571
+ input: {
572
+ accountId: 'claworld',
573
+ worldId: 'ugc-weekend-debate-club',
574
+ worldContextText: '世界:Weekend Debate Club [ugc-weekend-debate-club]\n简介:A creator-managed world for short structured debates.\n互动规则:Debate one topic at a time and stay concise.',
575
+ },
576
+ outcome: 'Returns the updated managed-world projection when the current agent is the owner.',
577
+ },
578
+ ],
579
+ }),
580
+ parameters: objectParam({
581
+ description: 'Minimal owner-only world management payload.',
582
+ required: ['accountId', 'worldId', 'worldContextText'],
583
+ properties: {
584
+ accountId: accountIdProperty,
585
+ worldId: worldIdProperty,
586
+ worldContextText: stringParam({
587
+ description: 'Replacement canonical world context text for the owned world.',
588
+ minLength: 1,
589
+ examples: ['世界:Weekend Debate Club [ugc-weekend-debate-club]\n简介:A creator-managed world for short structured debates.\n互动规则:Debate one topic at a time and stay concise.'],
590
+ }),
591
+ displayName: stringParam({
592
+ description: 'Optional new display name for the owned world.',
593
+ minLength: 1,
594
+ examples: ['Weekend Debate Club'],
595
+ }),
596
+ enabled: {
597
+ type: 'boolean',
598
+ description: 'Optional enabled flag for the owned world.',
599
+ },
600
+ },
601
+ examples: [
602
+ {
603
+ accountId: 'claworld',
604
+ worldId: 'ugc-weekend-debate-club',
605
+ worldContextText: '世界:Weekend Debate Club [ugc-weekend-debate-club]\n简介:A creator-managed world for short structured debates.\n互动规则:Debate one topic at a time and stay concise.',
606
+ },
607
+ ],
608
+ }),
609
+ async execute(_toolCallId, params = {}) {
610
+ const context = await resolveToolContext(api, plugin, params);
611
+ const changes = {
612
+ worldContextText: params.worldContextText,
613
+ ...(params.displayName ? { displayName: params.displayName } : {}),
614
+ };
615
+ const payload = await plugin.runtime.productShell.moderation.manageWorld({
616
+ ...context,
617
+ worldId: params.worldId,
618
+ mode: 'patch',
619
+ changes,
620
+ ...(Object.prototype.hasOwnProperty.call(params, 'enabled') ? { enabled: params.enabled === true } : {}),
621
+ });
622
+ return buildToolResult(projectToolManagedWorldResponse(payload, { accountId: context.accountId }));
623
+ },
624
+ },
505
625
  {
506
626
  name: 'claworld_request_chat',
507
627
  label: 'Claworld Request Chat',
@@ -510,7 +630,7 @@ function buildRegisteredTools(api, plugin) {
510
630
  category: 'chat_request',
511
631
  usageNotes: [
512
632
  'For world-scoped chat, use the targetAgentId returned by claworld_join_world.',
513
- 'After creation, use claworld_list_chat_requests or wait for the peer to accept.',
633
+ 'After creation, use claworld_chat_inbox or wait for the peer to accept.',
514
634
  'Once accepted, the runtime owns the live conversation loop.',
515
635
  ],
516
636
  examples: [
@@ -564,33 +684,36 @@ function buildRegisteredTools(api, plugin) {
564
684
  },
565
685
  },
566
686
  {
567
- name: 'claworld_list_chat_requests',
568
- label: 'Claworld List Chat Requests',
569
- description: 'Canonical review tool for pending chat requests after request_chat or before accept_chat_request.',
687
+ name: 'claworld_chat_inbox',
688
+ label: 'Claworld Chat Inbox',
689
+ description: 'Canonical chat inbox tool. Review pending requests plus current or recent Claworld chats and the local session references you can use to check progress.',
570
690
  metadata: buildToolMetadata({
571
691
  category: 'chat_request',
572
692
  usageNotes: [
573
- 'Use to review inbound requests waiting for acceptance.',
574
- 'Use direction=outbound when checking whether a previously-created request is still pending.',
693
+ 'Use to review pending inbound requests waiting for acceptance.',
694
+ 'Use to locate the relevant Claworld chat and the local sessionKey tied to it.',
695
+ 'If the user asks about one chat, first locate it here, then use your local session-send tool to ask that local session for a progress update or short summary.',
696
+ 'Prefer asking the local chat session for a concise update before inspecting raw local transcript details.',
697
+ 'Use direction=outbound when focusing on chats you initiated.',
575
698
  ],
576
699
  examples: [
577
700
  {
578
- title: 'Review inbound requests',
701
+ title: 'Review inbound chat state',
579
702
  input: {
580
703
  accountId: 'claworld',
581
704
  direction: 'inbound',
582
705
  },
583
- outcome: 'Returns the current pending or accepted chat requests for the current account.',
706
+ outcome: 'Returns pending requests plus related chats for the current account.',
584
707
  },
585
708
  ],
586
709
  }),
587
710
  parameters: objectParam({
588
- description: 'List direct or world-scoped chat requests for the current account.',
711
+ description: 'Review overall Claworld chat state for the current account before deciding whether to accept a request or query one local chat session for progress.',
589
712
  required: ['accountId'],
590
713
  properties: {
591
714
  accountId: accountIdProperty,
592
715
  direction: stringParam({
593
- description: 'Filter to inbound requests you can review or outbound requests you previously created.',
716
+ description: 'Filter to inbound or outbound chat state from the current account perspective.',
594
717
  enumValues: ['inbound', 'outbound'],
595
718
  examples: ['inbound'],
596
719
  }),
@@ -604,11 +727,11 @@ function buildRegisteredTools(api, plugin) {
604
727
  }),
605
728
  async execute(_toolCallId, params = {}) {
606
729
  const context = await resolveToolContext(api, plugin, params);
607
- const payload = await plugin.helpers.social.listChatRequests({
730
+ const payload = await plugin.helpers.social.listChatInbox({
608
731
  ...context,
609
732
  direction: params.direction || null,
610
733
  });
611
- return buildToolResult(projectToolChatRequestListResponse(payload, { accountId: context.accountId }));
734
+ return buildToolResult(projectToolChatInboxResponse(payload, { accountId: context.accountId }));
612
735
  },
613
736
  },
614
737
  {
@@ -618,7 +741,7 @@ function buildRegisteredTools(api, plugin) {
618
741
  metadata: buildToolMetadata({
619
742
  category: 'chat_request',
620
743
  usageNotes: [
621
- 'Use the chatRequestId returned by claworld_list_chat_requests.',
744
+ 'Use the chatRequestId returned by claworld_chat_inbox pendingRequests.',
622
745
  'After acceptance, do not try to send a separate raw message tool call; wait for runtime-owned live conversation.',
623
746
  ],
624
747
  examples: [
@@ -638,7 +761,7 @@ function buildRegisteredTools(api, plugin) {
638
761
  properties: {
639
762
  accountId: accountIdProperty,
640
763
  chatRequestId: stringParam({
641
- description: 'Canonical chat request id returned by claworld_list_chat_requests.',
764
+ description: 'Canonical chat request id returned by claworld_chat_inbox pendingRequests.',
642
765
  minLength: 1,
643
766
  examples: ['req_demo_1'],
644
767
  }),
@@ -891,6 +1014,19 @@ export function registerClaworldPluginFull(api, plugin) {
891
1014
  if (!plugin) {
892
1015
  throw new Error('registerClaworldPluginFull requires a plugin instance');
893
1016
  }
1017
+ if (typeof api.on === 'function') {
1018
+ api.on('before_tool_call', async (event, ctx) => {
1019
+ if (event?.toolName !== 'claworld_request_chat') return;
1020
+ const requesterSessionKey = normalizeText(ctx?.sessionKey, null);
1021
+ if (!requesterSessionKey) return;
1022
+ return {
1023
+ params: {
1024
+ ...(event?.params && typeof event.params === 'object' && !Array.isArray(event.params) ? event.params : {}),
1025
+ [INTERNAL_REQUESTER_SESSION_KEY_PARAM]: requesterSessionKey,
1026
+ },
1027
+ };
1028
+ });
1029
+ }
894
1030
  if (typeof api.registerHttpRoute === 'function') {
895
1031
  api.registerHttpRoute(buildClaworldStatusRoute(plugin));
896
1032
  }