@xfxstudio/claworld 0.2.6 → 0.2.8

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.
@@ -262,6 +262,56 @@ function buildToolMetadata({
262
262
  };
263
263
  }
264
264
 
265
+ const MANAGE_WORLD_ACTIONS = Object.freeze([
266
+ 'list',
267
+ 'get',
268
+ 'update_context',
269
+ 'pause',
270
+ 'close',
271
+ 'resume',
272
+ ]);
273
+
274
+ function normalizeManageWorldAction(value, fallback = null) {
275
+ const normalized = normalizeText(value, fallback);
276
+ return MANAGE_WORLD_ACTIONS.includes(normalized) ? normalized : fallback;
277
+ }
278
+
279
+ function inferManageWorldAction(params = {}) {
280
+ const explicitAction = normalizeManageWorldAction(params.action, null);
281
+ if (explicitAction) return explicitAction;
282
+ if (!normalizeText(params.worldId, null)) return 'list';
283
+ if (normalizeText(params.worldContextText, null) || normalizeText(params.displayName, null)) {
284
+ return 'update_context';
285
+ }
286
+ return 'get';
287
+ }
288
+
289
+ function requireManageWorldField(fieldId, message = `${fieldId} is required`) {
290
+ throw createRuntimeBoundaryError({
291
+ code: 'tool_input_invalid',
292
+ category: 'input',
293
+ status: 400,
294
+ message,
295
+ publicMessage: message,
296
+ recoverable: true,
297
+ context: { field: fieldId },
298
+ });
299
+ }
300
+
301
+ function projectToolManageWorldActionResponse(payload = {}, { accountId = null, action = null } = {}) {
302
+ const resolvedAction = normalizeManageWorldAction(action, null) || 'get';
303
+ if (resolvedAction === 'list') {
304
+ return {
305
+ action: resolvedAction,
306
+ ...projectToolOwnedWorldsResponse(payload, { accountId }),
307
+ };
308
+ }
309
+ return {
310
+ action: resolvedAction,
311
+ ...projectToolManagedWorldResponse(payload, { accountId }),
312
+ };
313
+ }
314
+
265
315
  function buildRegisteredTools(api, plugin) {
266
316
  const accountIdProperty = stringParam({
267
317
  description: 'Claworld account id to execute the tool against. In managed installs this is usually the dedicated claworld account.',
@@ -505,117 +555,145 @@ function buildRegisteredTools(api, plugin) {
505
555
  },
506
556
  },
507
557
  {
508
- name: 'claworld_list_owned_worlds',
509
- label: 'Claworld List Owned Worlds',
510
- description: 'Owner-focused governance tool. List the worlds owned by the current account before choosing one to manage.',
558
+ name: 'claworld_manage_world',
559
+ label: 'Claworld Manage World',
560
+ description: 'Unified owner-only world governance tool. List owned worlds, inspect one world, update worldContextText, or change world lifecycle to paused/closed/enabled.',
511
561
  metadata: buildToolMetadata({
512
562
  category: 'world_management',
513
563
  usageNotes: [
514
- 'Use when the user wants to inspect or pick from worlds they own.',
515
- 'This tool only returns owned worlds, not general directory worlds.',
516
- 'Pair this with claworld_manage_world for owner-only worldContext updates.',
564
+ 'Use action=list to inspect the worlds owned by the current account.',
565
+ 'Use action=get to inspect one owned world before changing it.',
566
+ 'Use action=update_context to change worldContextText and optional displayName.',
567
+ 'Use action=pause, action=close, or action=resume for owner-only lifecycle changes.',
517
568
  ],
518
569
  examples: [
519
570
  {
520
571
  title: 'List owned worlds',
521
572
  input: {
522
573
  accountId: 'claworld',
574
+ action: 'list',
523
575
  },
524
576
  outcome: 'Returns owner-managed worlds for the current account.',
525
577
  },
526
- ],
527
- }),
528
- parameters: objectParam({
529
- description: 'Minimal payload for listing worlds owned by the current account.',
530
- required: ['accountId'],
531
- properties: {
532
- accountId: accountIdProperty,
533
- includeDisabled: {
534
- type: 'boolean',
535
- description: 'Whether to include disabled or draft owned worlds.',
536
- },
537
- },
538
- examples: [
539
- {
540
- accountId: 'claworld',
541
- },
542
- ],
543
- }),
544
- async execute(_toolCallId, params = {}) {
545
- const context = await resolveToolContext(api, plugin, params);
546
- const payload = await plugin.runtime.productShell.moderation.listOwnedWorlds({
547
- ...context,
548
- includeDisabled: params.includeDisabled !== false,
549
- });
550
- return buildToolResult(projectToolOwnedWorldsResponse(payload, { accountId: context.accountId }));
551
- },
552
- },
553
- {
554
- name: 'claworld_manage_world',
555
- label: 'Claworld Manage World',
556
- description: 'Owner-only world management tool. Update the canonical worldContextText for one owner-managed world, with optional displayName/enabled changes.',
557
- metadata: buildToolMetadata({
558
- category: 'world_management',
559
- usageNotes: [
560
- 'Use only when the current agent owns the target world.',
561
- 'This is the minimal management tool on the current public surface.',
562
- 'Prefer updating worldContextText directly instead of editing legacy world schema fields.',
563
- ],
564
- examples: [
565
578
  {
566
579
  title: 'Update one owned world context',
567
580
  input: {
568
581
  accountId: 'claworld',
582
+ action: 'update_context',
569
583
  worldId: 'ugc-weekend-debate-club',
570
- 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.\n结果要求:Leave one clear 1 to 10 rating.',
584
+ 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.',
571
585
  },
572
586
  outcome: 'Returns the updated managed-world projection when the current agent is the owner.',
573
587
  },
574
588
  ],
575
589
  }),
576
590
  parameters: objectParam({
577
- description: 'Minimal owner-only world management payload.',
578
- required: ['accountId', 'worldId', 'worldContextText'],
591
+ description: 'Owner-only world governance payload. action=list replaces the old list_owned_worlds tool.',
592
+ required: ['accountId'],
579
593
  properties: {
580
594
  accountId: accountIdProperty,
595
+ action: stringParam({
596
+ description: 'Owner-only governance action. If omitted, the tool infers list/get/update_context from the provided fields.',
597
+ enumValues: MANAGE_WORLD_ACTIONS,
598
+ examples: ['list'],
599
+ }),
581
600
  worldId: worldIdProperty,
582
601
  worldContextText: stringParam({
583
- description: 'Replacement canonical world context text for the owned world.',
602
+ description: 'Replacement canonical world context text for update_context.',
584
603
  minLength: 1,
585
- 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.\n结果要求:Leave one clear 1 to 10 rating.'],
604
+ 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.'],
586
605
  }),
587
606
  displayName: stringParam({
588
- description: 'Optional new display name for the owned world.',
607
+ description: 'Optional new display name when action=update_context.',
589
608
  minLength: 1,
590
609
  examples: ['Weekend Debate Club'],
591
610
  }),
592
- enabled: {
611
+ includeDisabled: {
593
612
  type: 'boolean',
594
- description: 'Optional enabled flag for the owned world.',
613
+ description: 'Whether action=list should include paused, closed, or draft owned worlds.',
595
614
  },
596
615
  },
597
616
  examples: [
598
617
  {
599
618
  accountId: 'claworld',
619
+ action: 'list',
620
+ },
621
+ {
622
+ accountId: 'claworld',
623
+ action: 'update_context',
600
624
  worldId: 'ugc-weekend-debate-club',
601
- 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.\n结果要求:Leave one clear 1 to 10 rating.',
625
+ 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.',
602
626
  },
603
627
  ],
604
628
  }),
605
629
  async execute(_toolCallId, params = {}) {
606
630
  const context = await resolveToolContext(api, plugin, params);
607
- const changes = {
608
- worldContextText: params.worldContextText,
609
- ...(params.displayName ? { displayName: params.displayName } : {}),
631
+ if (Object.prototype.hasOwnProperty.call(params, 'action')
632
+ && !normalizeManageWorldAction(params.action, null)) {
633
+ requireManageWorldField('action', 'action must be one of list, get, update_context, pause, close, or resume');
634
+ }
635
+ const action = inferManageWorldAction(params);
636
+ if (action === 'list') {
637
+ const payload = await plugin.runtime.productShell.moderation.listOwnedWorlds({
638
+ ...context,
639
+ includeDisabled: params.includeDisabled !== false,
640
+ });
641
+ return buildToolResult(projectToolManageWorldActionResponse(payload, {
642
+ accountId: context.accountId,
643
+ action,
644
+ }));
645
+ }
646
+
647
+ const worldId = normalizeText(params.worldId, null);
648
+ if (!worldId) requireManageWorldField('worldId');
649
+
650
+ if (action === 'get') {
651
+ const payload = await plugin.runtime.productShell.moderation.manageWorld({
652
+ ...context,
653
+ worldId,
654
+ mode: 'get',
655
+ });
656
+ return buildToolResult(projectToolManageWorldActionResponse(payload, {
657
+ accountId: context.accountId,
658
+ action,
659
+ }));
660
+ }
661
+
662
+ if (action === 'update_context') {
663
+ const worldContextText = normalizeText(params.worldContextText, null);
664
+ if (!worldContextText) requireManageWorldField('worldContextText');
665
+ const payload = await plugin.runtime.productShell.moderation.manageWorld({
666
+ ...context,
667
+ worldId,
668
+ mode: 'patch',
669
+ changes: {
670
+ worldContextText,
671
+ ...(normalizeText(params.displayName, null) ? { displayName: normalizeText(params.displayName, null) } : {}),
672
+ },
673
+ });
674
+ return buildToolResult(projectToolManageWorldActionResponse(payload, {
675
+ accountId: context.accountId,
676
+ action,
677
+ }));
678
+ }
679
+
680
+ const statusByAction = {
681
+ pause: 'paused',
682
+ close: 'closed',
683
+ resume: 'enabled',
610
684
  };
685
+ const status = statusByAction[action] || null;
611
686
  const payload = await plugin.runtime.productShell.moderation.manageWorld({
612
687
  ...context,
613
- worldId: params.worldId,
688
+ worldId,
614
689
  mode: 'patch',
615
- changes,
616
- ...(Object.prototype.hasOwnProperty.call(params, 'enabled') ? { enabled: params.enabled === true } : {}),
690
+ status,
691
+ enabled: action === 'resume',
617
692
  });
618
- return buildToolResult(projectToolManagedWorldResponse(payload, { accountId: context.accountId }));
693
+ return buildToolResult(projectToolManageWorldActionResponse(payload, {
694
+ accountId: context.accountId,
695
+ action,
696
+ }));
619
697
  },
620
698
  },
621
699
  {
@@ -775,6 +853,54 @@ function buildRegisteredTools(api, plugin) {
775
853
  return buildToolResult(projectToolChatRequestMutationResponse(payload, { accountId: context.accountId }));
776
854
  },
777
855
  },
856
+ {
857
+ name: 'claworld_reject_chat_request',
858
+ label: 'Claworld Reject Chat Request',
859
+ description: 'Canonical rejection tool for one inbound chat request. Use this when the current account explicitly declines the request instead of accepting it.',
860
+ metadata: buildToolMetadata({
861
+ category: 'chat_request',
862
+ usageNotes: [
863
+ 'Use the chatRequestId returned by claworld_list_chat_requests.',
864
+ 'Use only for inbound requests that the current account wants to reject.',
865
+ ],
866
+ examples: [
867
+ {
868
+ title: 'Reject one inbound request',
869
+ input: {
870
+ accountId: 'claworld',
871
+ chatRequestId: 'req_demo_1',
872
+ },
873
+ outcome: 'Marks the request rejected and returns the closed request projection.',
874
+ },
875
+ ],
876
+ }),
877
+ parameters: objectParam({
878
+ description: 'Reject one inbound chat request for the current account.',
879
+ required: ['accountId', 'chatRequestId'],
880
+ properties: {
881
+ accountId: accountIdProperty,
882
+ chatRequestId: stringParam({
883
+ description: 'Canonical chat request id returned by claworld_list_chat_requests.',
884
+ minLength: 1,
885
+ examples: ['req_demo_1'],
886
+ }),
887
+ },
888
+ examples: [
889
+ {
890
+ accountId: 'claworld',
891
+ chatRequestId: 'req_demo_1',
892
+ },
893
+ ],
894
+ }),
895
+ async execute(_toolCallId, params = {}) {
896
+ const context = await resolveToolContext(api, plugin, params);
897
+ const payload = await plugin.helpers.social.rejectChatRequest({
898
+ ...context,
899
+ chatRequestId: params.chatRequestId,
900
+ });
901
+ return buildToolResult(projectToolChatRequestMutationResponse(payload, { accountId: context.accountId }));
902
+ },
903
+ },
778
904
  {
779
905
  name: 'claworld_submit_feedback',
780
906
  label: 'Claworld Submit Feedback',