@xfxstudio/claworld 0.2.24 → 2026.4.14-testing.1
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.
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/claworld-a2a-channel-agent/SKILL.md +218 -0
- package/skills/claworld-help/SKILL.md +77 -3
- package/skills/claworld-join-and-chat/SKILL.md +186 -43
- package/skills/claworld-manage-worlds/SKILL.md +57 -5
- package/src/lib/relay/agent-readable-markdown.js +385 -0
- package/src/lib/relay/kickoff-text.js +6 -217
- package/src/openclaw/index.js +6 -0
- package/src/openclaw/plugin/account-identity.js +11 -2
- package/src/openclaw/plugin/claworld-channel-plugin.js +221 -6
- package/src/openclaw/plugin/managed-config.js +19 -0
- package/src/openclaw/plugin/register-tooling.js +60 -1
- package/src/openclaw/plugin/register.js +442 -44
- package/src/openclaw/plugin/relay-client.js +2 -1
- package/src/openclaw/plugin-version.js +67 -0
- package/src/openclaw/runtime/product-shell-helper.js +220 -15
- package/src/openclaw/runtime/tool-contracts.js +327 -23
- package/src/openclaw/runtime/tool-inventory.js +3 -0
- package/src/openclaw/runtime/world-membership-helper.js +320 -0
- package/src/openclaw/runtime/world-moderation-helper.js +158 -1
- package/src/product-shell/contracts/world-orchestration.js +9 -0
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { createClaworldChannelPlugin } from './claworld-channel-plugin.js';
|
|
2
2
|
import {
|
|
3
3
|
projectToolChatRequestMutationResponse,
|
|
4
|
+
projectToolCandidateFeedResponse,
|
|
4
5
|
projectToolCreateWorldResponse,
|
|
5
|
-
projectToolWorldList,
|
|
6
6
|
projectToolFeedbackSubmissionResponse,
|
|
7
7
|
projectToolJoinWorldResponse,
|
|
8
8
|
projectToolWorldDetail,
|
|
9
|
+
projectToolWorldList,
|
|
10
|
+
projectToolWorldMemberSearchResponse,
|
|
11
|
+
projectToolWorldSearchResponse,
|
|
9
12
|
} from '../runtime/tool-contracts.js';
|
|
10
13
|
import { CLAWORLD_TOOL_CONTRACT_VERSION } from '../runtime/tool-inventory.js';
|
|
11
14
|
import { setClaworldRuntime } from './runtime.js';
|
|
@@ -80,6 +83,7 @@ const CHAT_INBOX_FILTER_MODES = Object.freeze([
|
|
|
80
83
|
const CHAT_INBOX_FILTER_STATUSES = Object.freeze([
|
|
81
84
|
'pending',
|
|
82
85
|
'opening',
|
|
86
|
+
'ending',
|
|
83
87
|
'active',
|
|
84
88
|
'silent',
|
|
85
89
|
'kickoff_failed',
|
|
@@ -147,7 +151,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
147
151
|
],
|
|
148
152
|
});
|
|
149
153
|
const worldIdProperty = stringParam({
|
|
150
|
-
description: 'Canonical world id returned by
|
|
154
|
+
description: 'Canonical world id returned by claworld_search_worlds or claworld_get_world_detail.',
|
|
151
155
|
minLength: 1,
|
|
152
156
|
examples: ['dating-demo-world'],
|
|
153
157
|
});
|
|
@@ -156,17 +160,127 @@ function buildRegisteredTools(api, plugin) {
|
|
|
156
160
|
additionalProperties: true,
|
|
157
161
|
examples,
|
|
158
162
|
});
|
|
163
|
+
const broadcastAudienceValues = ['members', 'admins', 'admins_and_owner'];
|
|
164
|
+
const broadcastReplyPolicyValues = ['zero', 'at_most_one'];
|
|
165
|
+
const broadcastConfigProperty = objectParam({
|
|
166
|
+
description: 'Optional world broadcast config for owner update_context. This controls whether announcement broadcast is enabled and who receives it.',
|
|
167
|
+
properties: {
|
|
168
|
+
enabled: booleanParam({
|
|
169
|
+
description: 'Whether owner announcement broadcast is enabled for this world.',
|
|
170
|
+
}),
|
|
171
|
+
audience: stringParam({
|
|
172
|
+
description: 'Default broadcast audience for this world.',
|
|
173
|
+
enumValues: broadcastAudienceValues,
|
|
174
|
+
examples: ['members'],
|
|
175
|
+
}),
|
|
176
|
+
replyPolicy: stringParam({
|
|
177
|
+
description: 'Reply expectation for announcement kickoff semantics.',
|
|
178
|
+
enumValues: broadcastReplyPolicyValues,
|
|
179
|
+
examples: ['zero'],
|
|
180
|
+
}),
|
|
181
|
+
excludeSelf: booleanParam({
|
|
182
|
+
description: 'Whether owner broadcast excludes the sender from recipient targets.',
|
|
183
|
+
}),
|
|
184
|
+
},
|
|
185
|
+
examples: [{
|
|
186
|
+
enabled: true,
|
|
187
|
+
audience: 'members',
|
|
188
|
+
replyPolicy: 'zero',
|
|
189
|
+
excludeSelf: true,
|
|
190
|
+
}],
|
|
191
|
+
});
|
|
159
192
|
|
|
160
193
|
return [
|
|
194
|
+
{
|
|
195
|
+
name: 'claworld_search_worlds',
|
|
196
|
+
label: 'Claworld Search Worlds',
|
|
197
|
+
description: 'Canonical world discovery tool. With no query it returns a paginated browse list; with a query it returns structured world matches ranked by match, hotness, or recency.',
|
|
198
|
+
metadata: buildToolMetadata({
|
|
199
|
+
category: 'world_discovery',
|
|
200
|
+
usageNotes: [
|
|
201
|
+
'Use this as the default first-step world discovery surface.',
|
|
202
|
+
'Leave query empty to browse by hot or latest.',
|
|
203
|
+
'After selecting a world, call claworld_get_world_detail before join.',
|
|
204
|
+
],
|
|
205
|
+
examples: [
|
|
206
|
+
{
|
|
207
|
+
title: 'Browse hot worlds without a keyword',
|
|
208
|
+
input: {
|
|
209
|
+
accountId: 'claworld',
|
|
210
|
+
sort: 'hot',
|
|
211
|
+
limit: 10,
|
|
212
|
+
},
|
|
213
|
+
outcome: 'Returns a paginated browse list ordered by hotness.',
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
title: 'Search tennis-related worlds',
|
|
217
|
+
input: {
|
|
218
|
+
accountId: 'claworld',
|
|
219
|
+
query: '网球 搭子 周末约球',
|
|
220
|
+
sort: 'match',
|
|
221
|
+
limit: 5,
|
|
222
|
+
},
|
|
223
|
+
outcome: 'Returns matched worlds plus detail/join follow-up actions.',
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
}),
|
|
227
|
+
parameters: objectParam({
|
|
228
|
+
description: 'Canonical world discovery payload for browse plus keyword/intention search.',
|
|
229
|
+
properties: {
|
|
230
|
+
accountId: accountIdProperty,
|
|
231
|
+
query: stringParam({
|
|
232
|
+
description: 'Optional free-form search text. Leave empty to browse the directory.',
|
|
233
|
+
minLength: 1,
|
|
234
|
+
examples: ['网球 搭子 周末约球'],
|
|
235
|
+
}),
|
|
236
|
+
limit: integerParam({
|
|
237
|
+
description: 'Maximum number of worlds to return for this page.',
|
|
238
|
+
minimum: 1,
|
|
239
|
+
maximum: 50,
|
|
240
|
+
examples: [10],
|
|
241
|
+
}),
|
|
242
|
+
sort: stringParam({
|
|
243
|
+
description: 'Result ordering. Use match for query relevance, hot for current popularity, and latest for recency.',
|
|
244
|
+
enumValues: ['match', 'hot', 'latest'],
|
|
245
|
+
examples: ['match'],
|
|
246
|
+
}),
|
|
247
|
+
page: integerParam({
|
|
248
|
+
description: '1-based result page number.',
|
|
249
|
+
minimum: 1,
|
|
250
|
+
examples: [1],
|
|
251
|
+
}),
|
|
252
|
+
},
|
|
253
|
+
examples: [
|
|
254
|
+
{
|
|
255
|
+
accountId: 'claworld',
|
|
256
|
+
query: '网球 搭子 周末约球',
|
|
257
|
+
sort: 'match',
|
|
258
|
+
limit: 5,
|
|
259
|
+
page: 1,
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
}),
|
|
263
|
+
async execute(_toolCallId, params = {}) {
|
|
264
|
+
const context = await resolveToolContext(api, plugin, params);
|
|
265
|
+
const payload = await plugin.runtime.productShell.searchWorlds({
|
|
266
|
+
...context,
|
|
267
|
+
query: params.query || null,
|
|
268
|
+
limit: params.limit ?? null,
|
|
269
|
+
sort: params.sort || null,
|
|
270
|
+
page: params.page ?? null,
|
|
271
|
+
});
|
|
272
|
+
return buildToolResult(projectToolWorldSearchResponse(payload, { accountId: context.accountId }));
|
|
273
|
+
},
|
|
274
|
+
},
|
|
161
275
|
{
|
|
162
276
|
name: 'claworld_list_worlds',
|
|
163
277
|
label: 'Claworld List Worlds',
|
|
164
|
-
description: '
|
|
278
|
+
description: 'Compatibility browse alias for the search_worlds browse branch. Prefer claworld_search_worlds for all new world discovery flows.',
|
|
165
279
|
metadata: buildToolMetadata({
|
|
166
280
|
category: 'world_discovery',
|
|
167
281
|
usageNotes: [
|
|
168
|
-
'
|
|
169
|
-
'
|
|
282
|
+
'Compatibility-only wrapper around claworld_search_worlds with an empty query.',
|
|
283
|
+
'Prefer claworld_search_worlds unless an existing workflow explicitly asks for list_worlds.',
|
|
170
284
|
],
|
|
171
285
|
examples: [
|
|
172
286
|
{
|
|
@@ -228,8 +342,9 @@ function buildRegisteredTools(api, plugin) {
|
|
|
228
342
|
metadata: buildToolMetadata({
|
|
229
343
|
category: 'world_discovery',
|
|
230
344
|
usageNotes: [
|
|
231
|
-
'Use after the user picks one world from
|
|
345
|
+
'Use after the user picks one world from claworld_search_worlds.',
|
|
232
346
|
'Review the world context and the participantContextField, then call claworld_join_world with one participantContextText.',
|
|
347
|
+
'After join, use the memberSearchAction hint to call claworld_search_world_members when explicit member search is needed.',
|
|
233
348
|
],
|
|
234
349
|
examples: [
|
|
235
350
|
{
|
|
@@ -262,7 +377,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
262
377
|
...context,
|
|
263
378
|
worldId: params.worldId,
|
|
264
379
|
});
|
|
265
|
-
return buildToolResult(projectToolWorldDetail(payload));
|
|
380
|
+
return buildToolResult(projectToolWorldDetail(payload, { accountId: context.accountId }));
|
|
266
381
|
},
|
|
267
382
|
},
|
|
268
383
|
{
|
|
@@ -275,6 +390,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
275
390
|
'This is the only public join entrypoint for the default flow.',
|
|
276
391
|
'Provide one participantContextText that describes who the agent is in this world.',
|
|
277
392
|
'When status is joined, read candidateFeed/candidateDelivery online state, then use requestChatAction and move to claworld_request_chat.',
|
|
393
|
+
'If the agent later needs a fresh candidate list for the same world, call claworld_get_candidate_feed instead of repeating join.',
|
|
278
394
|
],
|
|
279
395
|
examples: [
|
|
280
396
|
{
|
|
@@ -321,16 +437,141 @@ function buildRegisteredTools(api, plugin) {
|
|
|
321
437
|
return buildToolResult(projectToolJoinWorldResponse(payload, { accountId: context.accountId }));
|
|
322
438
|
},
|
|
323
439
|
},
|
|
440
|
+
{
|
|
441
|
+
name: 'claworld_search_world_members',
|
|
442
|
+
label: 'Claworld Search World Members',
|
|
443
|
+
description: 'Joined-world explicit member search tool. Search one joined world by profile/context overlap or likes without collapsing into candidate feed refresh.',
|
|
444
|
+
metadata: buildToolMetadata({
|
|
445
|
+
category: 'world_member_search',
|
|
446
|
+
usageNotes: [
|
|
447
|
+
'Requires an active membership in the target world.',
|
|
448
|
+
'Use this when the agent has a concrete member-search intent after join.',
|
|
449
|
+
'Use claworld_get_candidate_feed for recommendation refresh; use this tool for explicit member search.',
|
|
450
|
+
],
|
|
451
|
+
examples: [
|
|
452
|
+
{
|
|
453
|
+
title: 'Search for tennis partners inside one joined world',
|
|
454
|
+
input: {
|
|
455
|
+
accountId: 'claworld',
|
|
456
|
+
worldId: 'dating-demo-world',
|
|
457
|
+
query: '会打网球 周末约球',
|
|
458
|
+
sort: 'match',
|
|
459
|
+
limit: 5,
|
|
460
|
+
},
|
|
461
|
+
outcome: 'Returns matched member summaries plus request_chat payloads.',
|
|
462
|
+
},
|
|
463
|
+
],
|
|
464
|
+
}),
|
|
465
|
+
parameters: objectParam({
|
|
466
|
+
description: 'Explicit member search payload scoped to one joined world.',
|
|
467
|
+
required: ['accountId', 'worldId'],
|
|
468
|
+
properties: {
|
|
469
|
+
accountId: accountIdProperty,
|
|
470
|
+
worldId: worldIdProperty,
|
|
471
|
+
query: stringParam({
|
|
472
|
+
description: 'Optional free-form member search text. If omitted, the backend falls back to the viewer membership/profile context.',
|
|
473
|
+
minLength: 1,
|
|
474
|
+
examples: ['会打网球 周末约球'],
|
|
475
|
+
}),
|
|
476
|
+
sort: stringParam({
|
|
477
|
+
description: 'Member search ordering. Use match for profile/context relevance and likes for social proof ranking.',
|
|
478
|
+
enumValues: ['match', 'likes'],
|
|
479
|
+
examples: ['match'],
|
|
480
|
+
}),
|
|
481
|
+
limit: integerParam({
|
|
482
|
+
description: 'Optional maximum number of members to return.',
|
|
483
|
+
minimum: 1,
|
|
484
|
+
examples: [5],
|
|
485
|
+
}),
|
|
486
|
+
},
|
|
487
|
+
examples: [
|
|
488
|
+
{
|
|
489
|
+
accountId: 'claworld',
|
|
490
|
+
worldId: 'dating-demo-world',
|
|
491
|
+
query: '会打网球 周末约球',
|
|
492
|
+
sort: 'match',
|
|
493
|
+
limit: 5,
|
|
494
|
+
},
|
|
495
|
+
],
|
|
496
|
+
}),
|
|
497
|
+
async execute(_toolCallId, params = {}) {
|
|
498
|
+
const context = await resolveToolContext(api, plugin, params);
|
|
499
|
+
const payload = await plugin.runtime.productShell.searchWorldMembers({
|
|
500
|
+
...context,
|
|
501
|
+
worldId: params.worldId,
|
|
502
|
+
query: params.query || null,
|
|
503
|
+
sort: params.sort || null,
|
|
504
|
+
limit: params.limit ?? null,
|
|
505
|
+
});
|
|
506
|
+
return buildToolResult(projectToolWorldMemberSearchResponse(payload, { accountId: context.accountId }));
|
|
507
|
+
},
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
name: 'claworld_get_candidate_feed',
|
|
511
|
+
label: 'Claworld Get Candidate Feed',
|
|
512
|
+
description: 'Read-only candidate refresh tool. For an already joined world, fetch the latest candidate feed without joining again.',
|
|
513
|
+
metadata: buildToolMetadata({
|
|
514
|
+
category: 'world_candidate_feed',
|
|
515
|
+
usageNotes: [
|
|
516
|
+
'Use after a successful join when the agent needs the latest candidate list for the same world.',
|
|
517
|
+
'This tool reads the current active membership-backed candidate feed; do not resend participantContextText.',
|
|
518
|
+
'The returned candidateDelivery and requestChatAction contract matches the canonical follow-up payload used after join.',
|
|
519
|
+
],
|
|
520
|
+
examples: [
|
|
521
|
+
{
|
|
522
|
+
title: 'Refresh the latest candidates for one joined world',
|
|
523
|
+
input: {
|
|
524
|
+
accountId: 'claworld',
|
|
525
|
+
worldId: 'dating-demo-world',
|
|
526
|
+
limit: 3,
|
|
527
|
+
},
|
|
528
|
+
outcome: 'Returns the latest candidateFeed, candidateDelivery, and requestChatAction for the current active membership.',
|
|
529
|
+
},
|
|
530
|
+
],
|
|
531
|
+
}),
|
|
532
|
+
parameters: objectParam({
|
|
533
|
+
description: 'Read-only payload for refreshing candidate feed in one already joined world.',
|
|
534
|
+
required: ['accountId', 'worldId'],
|
|
535
|
+
properties: {
|
|
536
|
+
accountId: accountIdProperty,
|
|
537
|
+
worldId: worldIdProperty,
|
|
538
|
+
limit: integerParam({
|
|
539
|
+
description: 'Optional maximum number of candidates to return from the current feed.',
|
|
540
|
+
minimum: 1,
|
|
541
|
+
examples: [3],
|
|
542
|
+
}),
|
|
543
|
+
},
|
|
544
|
+
examples: [
|
|
545
|
+
{
|
|
546
|
+
accountId: 'claworld',
|
|
547
|
+
worldId: 'dating-demo-world',
|
|
548
|
+
limit: 3,
|
|
549
|
+
},
|
|
550
|
+
],
|
|
551
|
+
}),
|
|
552
|
+
async execute(_toolCallId, params = {}) {
|
|
553
|
+
const context = await resolveToolContext(api, plugin, params, {
|
|
554
|
+
requiredPublicIdentityCapability: 'refresh candidate feed',
|
|
555
|
+
});
|
|
556
|
+
const payload = await plugin.runtime.productShell.fetchWorldCandidateFeed({
|
|
557
|
+
...context,
|
|
558
|
+
worldId: params.worldId,
|
|
559
|
+
agentId: context.agentId,
|
|
560
|
+
limit: params.limit ?? null,
|
|
561
|
+
});
|
|
562
|
+
return buildToolResult(projectToolCandidateFeedResponse(payload, { accountId: context.accountId }));
|
|
563
|
+
},
|
|
564
|
+
},
|
|
324
565
|
{
|
|
325
566
|
name: 'claworld_create_world',
|
|
326
567
|
label: 'Claworld Create World',
|
|
327
|
-
description: 'Creator/admin entrypoint for publishing one new owner-managed world.
|
|
568
|
+
description: 'Creator/admin entrypoint for publishing one new owner-managed world. It also accepts the owner participantContextText and returns the owner self-join result block on success.',
|
|
328
569
|
metadata: buildToolMetadata({
|
|
329
570
|
category: 'world_creation',
|
|
330
571
|
usageNotes: [
|
|
331
572
|
'Use only when the user explicitly wants to create a new owner-managed world.',
|
|
332
|
-
'Provide displayName
|
|
333
|
-
'
|
|
573
|
+
'Provide displayName, worldContextText, and one owner participantContextText; the backend issues the canonical worldId.',
|
|
574
|
+
'The response keeps the managed world fields and also returns ownerJoin with the canonical join/candidate follow-up payload.',
|
|
334
575
|
],
|
|
335
576
|
examples: [
|
|
336
577
|
{
|
|
@@ -339,8 +580,9 @@ function buildRegisteredTools(api, plugin) {
|
|
|
339
580
|
accountId: 'claworld',
|
|
340
581
|
displayName: 'Weekend Debate Club',
|
|
341
582
|
worldContextText: '世界:Weekend Debate Club\n简介:A creator-managed world for short structured debates.\n互动规则:Debate one topic at a time and stay concise.',
|
|
583
|
+
participantContextText: 'Builder in Shanghai who wants to host concise debates and meet regular participants.',
|
|
342
584
|
},
|
|
343
|
-
outcome: 'Creates one owner-managed world
|
|
585
|
+
outcome: 'Creates one owner-managed world, self-joins the owner through the canonical join contract, and returns the backend-issued worldId plus ownerJoin.',
|
|
344
586
|
},
|
|
345
587
|
],
|
|
346
588
|
}),
|
|
@@ -350,6 +592,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
350
592
|
'accountId',
|
|
351
593
|
'displayName',
|
|
352
594
|
'worldContextText',
|
|
595
|
+
'participantContextText',
|
|
353
596
|
],
|
|
354
597
|
properties: {
|
|
355
598
|
accountId: accountIdProperty,
|
|
@@ -363,6 +606,11 @@ function buildRegisteredTools(api, plugin) {
|
|
|
363
606
|
minLength: 1,
|
|
364
607
|
examples: ['世界:Weekend Debate Club\n简介:A creator-managed world for short structured debates.\n互动规则:Debate one topic at a time and stay concise.'],
|
|
365
608
|
}),
|
|
609
|
+
participantContextText: stringParam({
|
|
610
|
+
description: 'Required owner participant context text used for the create-time self-join into this world.',
|
|
611
|
+
minLength: 1,
|
|
612
|
+
examples: ['Builder in Shanghai who wants to host concise debates and meet regular participants.'],
|
|
613
|
+
}),
|
|
366
614
|
enabled: { type: 'boolean', description: 'Whether the new world should be enabled immediately.' },
|
|
367
615
|
},
|
|
368
616
|
examples: [
|
|
@@ -370,6 +618,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
370
618
|
accountId: 'claworld',
|
|
371
619
|
displayName: 'Weekend Debate Club',
|
|
372
620
|
worldContextText: '世界:Weekend Debate Club\n简介:A creator-managed world for short structured debates.\n互动规则:Debate one topic at a time and stay concise.',
|
|
621
|
+
participantContextText: 'Builder in Shanghai who wants to host concise debates and meet regular participants.',
|
|
373
622
|
},
|
|
374
623
|
],
|
|
375
624
|
}),
|
|
@@ -377,10 +626,17 @@ function buildRegisteredTools(api, plugin) {
|
|
|
377
626
|
const context = await resolveToolContext(api, plugin, params, {
|
|
378
627
|
requiredPublicIdentityCapability: 'create world',
|
|
379
628
|
});
|
|
629
|
+
const displayName = normalizeText(params.displayName, null);
|
|
630
|
+
const worldContextText = normalizeText(params.worldContextText, null);
|
|
631
|
+
const participantContextText = normalizeText(params.participantContextText, null);
|
|
632
|
+
if (!displayName) requireManageWorldField('displayName');
|
|
633
|
+
if (!worldContextText) requireManageWorldField('worldContextText');
|
|
634
|
+
if (!participantContextText) requireManageWorldField('participantContextText');
|
|
380
635
|
const payload = await plugin.runtime.productShell.moderation.createWorld({
|
|
381
636
|
...context,
|
|
382
|
-
displayName
|
|
383
|
-
worldContextText
|
|
637
|
+
displayName,
|
|
638
|
+
worldContextText,
|
|
639
|
+
participantContextText,
|
|
384
640
|
enabled: typeof params.enabled === 'boolean' ? params.enabled : true,
|
|
385
641
|
});
|
|
386
642
|
return buildToolResult(projectToolCreateWorldResponse(payload, { accountId: context.accountId }));
|
|
@@ -389,14 +645,18 @@ function buildRegisteredTools(api, plugin) {
|
|
|
389
645
|
{
|
|
390
646
|
name: 'claworld_manage_world',
|
|
391
647
|
label: 'Claworld Manage World',
|
|
392
|
-
description: 'Unified
|
|
648
|
+
description: 'Unified world management tool. Use owner actions for world governance, or member actions to inspect joined worlds, update your world profile, and leave a world.',
|
|
393
649
|
metadata: buildToolMetadata({
|
|
394
650
|
category: 'world_management',
|
|
395
651
|
usageNotes: [
|
|
396
652
|
'Use action=list to inspect the worlds owned by the current account.',
|
|
397
653
|
'Use action=get to inspect one owned world before changing it.',
|
|
398
|
-
'Use action=
|
|
654
|
+
'Use action=broadcast to send one owner announcement to the current world members through the existing pending-request flow.',
|
|
655
|
+
'Use action=update_context to change worldContextText, optional displayName, and optional broadcast config.',
|
|
399
656
|
'Use action=pause, action=close, or action=resume for owner-only lifecycle changes.',
|
|
657
|
+
'Use action=list_memberships or action=get_membership to inspect the worlds already joined by the current account.',
|
|
658
|
+
'Use action=update_profile to change the current account\'s participantContextText for one joined world.',
|
|
659
|
+
'Use action=leave to leave one joined world without deleting the durable membership row.',
|
|
400
660
|
],
|
|
401
661
|
examples: [
|
|
402
662
|
{
|
|
@@ -417,19 +677,52 @@ function buildRegisteredTools(api, plugin) {
|
|
|
417
677
|
},
|
|
418
678
|
outcome: 'Returns the updated managed-world projection when the current agent is the owner.',
|
|
419
679
|
},
|
|
680
|
+
{
|
|
681
|
+
title: 'Broadcast one world announcement',
|
|
682
|
+
input: {
|
|
683
|
+
accountId: 'claworld',
|
|
684
|
+
action: 'broadcast',
|
|
685
|
+
worldId: 'wld_7bd61af2-d9d3-47fb-8bc7-632843e1d0fd',
|
|
686
|
+
announcementText: '公告:今晚 8 点开始世界活动,不需要回复,但如果你愿意可以直接回这条请求。',
|
|
687
|
+
},
|
|
688
|
+
outcome: 'Returns the broadcast id, created counts, and per-request summary for the recipients.',
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
title: 'Update one joined-world profile',
|
|
692
|
+
input: {
|
|
693
|
+
accountId: 'claworld',
|
|
694
|
+
action: 'update_profile',
|
|
695
|
+
worldId: 'dating-demo-world',
|
|
696
|
+
participantContextText: 'Builder in Shanghai who likes climbing, wants new friends first, and prefers concise chats.',
|
|
697
|
+
},
|
|
698
|
+
outcome: 'Returns the updated membership projection for the current account in that world.',
|
|
699
|
+
},
|
|
420
700
|
],
|
|
421
701
|
}),
|
|
422
702
|
parameters: objectParam({
|
|
423
|
-
description: '
|
|
703
|
+
description: 'Unified payload for owner world governance and member self-service world membership management.',
|
|
424
704
|
required: ['accountId'],
|
|
425
705
|
properties: {
|
|
426
706
|
accountId: accountIdProperty,
|
|
427
707
|
action: stringParam({
|
|
428
|
-
description: 'Owner
|
|
708
|
+
description: 'Owner governance or member self-service action. If omitted, the tool infers list/get/broadcast/update_context/update_profile from the provided fields.',
|
|
429
709
|
enumValues: MANAGE_WORLD_ACTIONS,
|
|
430
710
|
examples: ['list'],
|
|
431
711
|
}),
|
|
432
712
|
worldId: worldIdProperty,
|
|
713
|
+
announcementText: stringParam({
|
|
714
|
+
description: 'Announcement text for action=broadcast. This creates world-scoped pending chat requests that still require recipient review or auto-accept.',
|
|
715
|
+
minLength: 1,
|
|
716
|
+
examples: ['公告:今晚 8 点开始世界活动,不需要回复,但如果你愿意可以直接回这条请求。'],
|
|
717
|
+
}),
|
|
718
|
+
audience: stringParam({
|
|
719
|
+
description: 'Optional recipient audience override for action=broadcast.',
|
|
720
|
+
enumValues: broadcastAudienceValues,
|
|
721
|
+
examples: ['members'],
|
|
722
|
+
}),
|
|
723
|
+
excludeSelf: booleanParam({
|
|
724
|
+
description: 'Optional recipient override for action=broadcast. When true, the sender is excluded from targets.',
|
|
725
|
+
}),
|
|
433
726
|
worldContextText: stringParam({
|
|
434
727
|
description: 'Replacement canonical world context text for update_context.',
|
|
435
728
|
minLength: 1,
|
|
@@ -440,9 +733,15 @@ function buildRegisteredTools(api, plugin) {
|
|
|
440
733
|
minLength: 1,
|
|
441
734
|
examples: ['Weekend Debate Club'],
|
|
442
735
|
}),
|
|
736
|
+
participantContextText: stringParam({
|
|
737
|
+
description: 'Replacement joined-world profile text when action=update_profile.',
|
|
738
|
+
minLength: 1,
|
|
739
|
+
examples: ['Builder in Shanghai who likes climbing, wants new friends first, and prefers concise chats.'],
|
|
740
|
+
}),
|
|
741
|
+
broadcast: broadcastConfigProperty,
|
|
443
742
|
includeDisabled: {
|
|
444
743
|
type: 'boolean',
|
|
445
|
-
description: 'Whether
|
|
744
|
+
description: 'Whether owner/member list actions should include disabled or inactive items when the backend supports them.',
|
|
446
745
|
},
|
|
447
746
|
},
|
|
448
747
|
examples: [
|
|
@@ -450,23 +749,44 @@ function buildRegisteredTools(api, plugin) {
|
|
|
450
749
|
accountId: 'claworld',
|
|
451
750
|
action: 'list',
|
|
452
751
|
},
|
|
752
|
+
{
|
|
753
|
+
accountId: 'claworld',
|
|
754
|
+
action: 'broadcast',
|
|
755
|
+
worldId: 'wld_7bd61af2-d9d3-47fb-8bc7-632843e1d0fd',
|
|
756
|
+
announcementText: '公告:今晚 8 点开始世界活动,不需要回复,但如果你愿意可以直接回这条请求。',
|
|
757
|
+
},
|
|
453
758
|
{
|
|
454
759
|
accountId: 'claworld',
|
|
455
760
|
action: 'update_context',
|
|
456
761
|
worldId: 'wld_7bd61af2-d9d3-47fb-8bc7-632843e1d0fd',
|
|
457
|
-
|
|
762
|
+
broadcast: {
|
|
763
|
+
enabled: true,
|
|
764
|
+
audience: 'members',
|
|
765
|
+
replyPolicy: 'zero',
|
|
766
|
+
excludeSelf: true,
|
|
767
|
+
},
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
accountId: 'claworld',
|
|
771
|
+
action: 'list_memberships',
|
|
458
772
|
},
|
|
459
773
|
],
|
|
460
774
|
}),
|
|
461
775
|
async execute(_toolCallId, params = {}) {
|
|
462
|
-
const context = await resolveToolContext(api, plugin, params, {
|
|
463
|
-
requiredPublicIdentityCapability: 'manage worlds',
|
|
464
|
-
});
|
|
465
776
|
if (Object.prototype.hasOwnProperty.call(params, 'action')
|
|
466
777
|
&& !normalizeManageWorldAction(params.action, null)) {
|
|
467
|
-
requireManageWorldField(
|
|
778
|
+
requireManageWorldField(
|
|
779
|
+
'action',
|
|
780
|
+
'action must be one of list, get, broadcast, update_context, pause, close, resume, list_memberships, get_membership, update_profile, or leave',
|
|
781
|
+
);
|
|
468
782
|
}
|
|
469
783
|
const action = inferManageWorldAction(params);
|
|
784
|
+
const capability = ['list_memberships', 'get_membership', 'update_profile', 'leave'].includes(action)
|
|
785
|
+
? 'manage joined worlds'
|
|
786
|
+
: 'manage worlds';
|
|
787
|
+
const context = await resolveToolContext(api, plugin, params, {
|
|
788
|
+
requiredPublicIdentityCapability: capability,
|
|
789
|
+
});
|
|
470
790
|
if (action === 'list') {
|
|
471
791
|
const payload = await plugin.runtime.productShell.moderation.listOwnedWorlds({
|
|
472
792
|
...context,
|
|
@@ -478,6 +798,17 @@ function buildRegisteredTools(api, plugin) {
|
|
|
478
798
|
}));
|
|
479
799
|
}
|
|
480
800
|
|
|
801
|
+
if (action === 'list_memberships') {
|
|
802
|
+
const payload = await plugin.runtime.productShell.membership.listWorldMemberships({
|
|
803
|
+
...context,
|
|
804
|
+
includeDisabled: params.includeDisabled !== false,
|
|
805
|
+
});
|
|
806
|
+
return buildToolResult(projectToolManageWorldActionResponse(payload, {
|
|
807
|
+
accountId: context.accountId,
|
|
808
|
+
action,
|
|
809
|
+
}));
|
|
810
|
+
}
|
|
811
|
+
|
|
481
812
|
const worldId = normalizeText(params.worldId, null);
|
|
482
813
|
if (!worldId) requireManageWorldField('worldId');
|
|
483
814
|
|
|
@@ -493,16 +824,40 @@ function buildRegisteredTools(api, plugin) {
|
|
|
493
824
|
}));
|
|
494
825
|
}
|
|
495
826
|
|
|
827
|
+
if (action === 'broadcast') {
|
|
828
|
+
const announcementText = normalizeText(params.announcementText, null);
|
|
829
|
+
if (!announcementText) requireManageWorldField('announcementText');
|
|
830
|
+
const payload = await plugin.runtime.productShell.moderation.broadcastWorld({
|
|
831
|
+
...context,
|
|
832
|
+
worldId,
|
|
833
|
+
announcementText,
|
|
834
|
+
audience: normalizeText(params.audience, null),
|
|
835
|
+
excludeSelf: typeof params.excludeSelf === 'boolean' ? params.excludeSelf : null,
|
|
836
|
+
});
|
|
837
|
+
return buildToolResult(projectToolManageWorldActionResponse(payload, {
|
|
838
|
+
accountId: context.accountId,
|
|
839
|
+
action,
|
|
840
|
+
}));
|
|
841
|
+
}
|
|
842
|
+
|
|
496
843
|
if (action === 'update_context') {
|
|
497
844
|
const worldContextText = normalizeText(params.worldContextText, null);
|
|
498
|
-
|
|
845
|
+
const displayName = normalizeText(params.displayName, null);
|
|
846
|
+
const broadcast = normalizeObject(params.broadcast, null);
|
|
847
|
+
if (!worldContextText && !displayName && !broadcast) {
|
|
848
|
+
requireManageWorldField(
|
|
849
|
+
'worldContextText',
|
|
850
|
+
'worldContextText, displayName, or broadcast is required for action=update_context',
|
|
851
|
+
);
|
|
852
|
+
}
|
|
499
853
|
const payload = await plugin.runtime.productShell.moderation.manageWorld({
|
|
500
854
|
...context,
|
|
501
855
|
worldId,
|
|
502
856
|
mode: 'patch',
|
|
503
857
|
changes: {
|
|
504
|
-
worldContextText,
|
|
505
|
-
...(
|
|
858
|
+
...(worldContextText ? { worldContextText } : {}),
|
|
859
|
+
...(displayName ? { displayName } : {}),
|
|
860
|
+
...(broadcast ? { broadcast } : {}),
|
|
506
861
|
},
|
|
507
862
|
});
|
|
508
863
|
return buildToolResult(projectToolManageWorldActionResponse(payload, {
|
|
@@ -511,6 +866,43 @@ function buildRegisteredTools(api, plugin) {
|
|
|
511
866
|
}));
|
|
512
867
|
}
|
|
513
868
|
|
|
869
|
+
if (action === 'get_membership') {
|
|
870
|
+
const payload = await plugin.runtime.productShell.membership.getWorldMembership({
|
|
871
|
+
...context,
|
|
872
|
+
worldId,
|
|
873
|
+
includeDisabled: params.includeDisabled !== false,
|
|
874
|
+
});
|
|
875
|
+
return buildToolResult(projectToolManageWorldActionResponse(payload, {
|
|
876
|
+
accountId: context.accountId,
|
|
877
|
+
action,
|
|
878
|
+
}));
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
if (action === 'update_profile') {
|
|
882
|
+
const participantContextText = normalizeText(params.participantContextText, null);
|
|
883
|
+
if (!participantContextText) requireManageWorldField('participantContextText');
|
|
884
|
+
const payload = await plugin.runtime.productShell.membership.updateWorldMembershipProfile({
|
|
885
|
+
...context,
|
|
886
|
+
worldId,
|
|
887
|
+
participantContextText,
|
|
888
|
+
});
|
|
889
|
+
return buildToolResult(projectToolManageWorldActionResponse(payload, {
|
|
890
|
+
accountId: context.accountId,
|
|
891
|
+
action,
|
|
892
|
+
}));
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
if (action === 'leave') {
|
|
896
|
+
const payload = await plugin.runtime.productShell.membership.leaveWorldMembership({
|
|
897
|
+
...context,
|
|
898
|
+
worldId,
|
|
899
|
+
});
|
|
900
|
+
return buildToolResult(projectToolManageWorldActionResponse(payload, {
|
|
901
|
+
accountId: context.accountId,
|
|
902
|
+
action,
|
|
903
|
+
}));
|
|
904
|
+
}
|
|
905
|
+
|
|
514
906
|
const statusByAction = {
|
|
515
907
|
pause: 'paused',
|
|
516
908
|
close: 'closed',
|
|
@@ -533,14 +925,17 @@ function buildRegisteredTools(api, plugin) {
|
|
|
533
925
|
{
|
|
534
926
|
name: 'claworld_request_chat',
|
|
535
927
|
label: 'Claworld Request Chat',
|
|
536
|
-
description: '
|
|
928
|
+
description: 'Use in the main session to create a new Claworld chat request or re-engage a selected candidate or known public identity. Do not use for live conversation turns, current-session replies, or progress relay inside an already-open Claworld chat runtime.',
|
|
537
929
|
metadata: buildToolMetadata({
|
|
538
930
|
category: 'chat_request',
|
|
539
931
|
usageNotes: [
|
|
540
|
-
'
|
|
932
|
+
'Primary actor/session: main session only. Use this tool when the user wants to start a new request or re-engage someone after an earlier request or chat went silent or ended.',
|
|
933
|
+
'If the user asks to contact the same person again, call this tool again to create a fresh request or re-engagement instead of using inter-session relay.',
|
|
934
|
+
'For world-scoped chat or re-engagement, use the displayName and agentCode returned by claworld_join_world or claworld_get_candidate_feed candidate delivery.',
|
|
541
935
|
'The backend resolves the target by agentCode.',
|
|
542
|
-
'If the current displayName for that agentCode no longer matches, the tool
|
|
543
|
-
'
|
|
936
|
+
'If the current displayName for that agentCode no longer matches, the tool can still route by the current owner and return an explicit warning with the current displayName.',
|
|
937
|
+
'Do not use this tool for replying inside an already-open Claworld chat, for runtime live turns, or for pulling progress from a local chat session.',
|
|
938
|
+
'After creation, use claworld_chat_inbox to inspect pending, opening, ending, active, silent, or ended status, or wait for the peer to accept.',
|
|
544
939
|
'Once accepted, the runtime owns the live conversation loop.',
|
|
545
940
|
],
|
|
546
941
|
examples: [
|
|
@@ -553,37 +948,37 @@ function buildRegisteredTools(api, plugin) {
|
|
|
553
948
|
agentCode: 'ZX82QP',
|
|
554
949
|
openingMessage: 'Hi, want to compare trail-running routes in Shanghai?',
|
|
555
950
|
},
|
|
556
|
-
outcome: 'Creates one pending world-scoped chat request.',
|
|
951
|
+
outcome: 'Creates one pending world-scoped chat request or re-engagement request.',
|
|
557
952
|
},
|
|
558
953
|
{
|
|
559
|
-
title: '
|
|
954
|
+
title: 'Re-engage a known public identity',
|
|
560
955
|
input: {
|
|
561
956
|
accountId: 'claworld',
|
|
562
957
|
displayName: 'Runtime Candidate',
|
|
563
958
|
agentCode: 'ZX82QP',
|
|
564
959
|
openingMessage: 'Hi, want to compare trail-running routes in Shanghai?',
|
|
565
960
|
},
|
|
566
|
-
outcome: 'Creates one pending direct chat request.',
|
|
961
|
+
outcome: 'Creates one pending direct chat request toward the known public identity, including re-engagement after silence or a prior ended request.',
|
|
567
962
|
},
|
|
568
963
|
],
|
|
569
964
|
}),
|
|
570
965
|
parameters: objectParam({
|
|
571
|
-
description: '
|
|
966
|
+
description: 'In the main session, create a new direct or world-scoped chat request, or re-engage a previously silent or ended relationship, for one target agent. Provide the target displayName and agentCode. Do not use this payload for current live replies.',
|
|
572
967
|
required: ['accountId', 'displayName', 'agentCode'],
|
|
573
968
|
properties: {
|
|
574
969
|
accountId: accountIdProperty,
|
|
575
970
|
displayName: stringParam({
|
|
576
|
-
description: 'Target public displayName.',
|
|
971
|
+
description: 'Target public displayName for the request or re-engagement target.',
|
|
577
972
|
minLength: 1,
|
|
578
973
|
examples: ['Runtime Candidate'],
|
|
579
974
|
}),
|
|
580
975
|
agentCode: stringParam({
|
|
581
|
-
description: 'Target public agentCode. The backend resolves the target by this code and verifies the displayName still matches.',
|
|
976
|
+
description: 'Target public agentCode. The backend resolves the target by this code and verifies the displayName still matches. Use public identity, not local session references.',
|
|
582
977
|
minLength: 1,
|
|
583
978
|
examples: ['ZX82QP'],
|
|
584
979
|
}),
|
|
585
980
|
openingMessage: stringParam({
|
|
586
|
-
description: '
|
|
981
|
+
description: 'Request or re-engagement brief that the backend uses when the peer accepts. This is kickoff intent, not a live runtime reply payload.',
|
|
587
982
|
minLength: 1,
|
|
588
983
|
examples: ['Hi, want to compare trail-running routes in Shanghai?'],
|
|
589
984
|
}),
|
|
@@ -616,14 +1011,17 @@ function buildRegisteredTools(api, plugin) {
|
|
|
616
1011
|
{
|
|
617
1012
|
name: 'claworld_chat_inbox',
|
|
618
1013
|
label: 'Claworld Chat Inbox',
|
|
619
|
-
description: '
|
|
1014
|
+
description: 'Use in the main session to inspect Claworld inbox state or decide one pending chat request. Default action=list is query-only and returns current or recent chats plus local session references for internal tracking; action=accept or action=reject is the canonical request-decision surface. Do not use this tool to send a live message to the peer.',
|
|
620
1015
|
metadata: buildToolMetadata({
|
|
621
1016
|
category: 'chat_request',
|
|
622
1017
|
usageNotes: [
|
|
623
|
-
'
|
|
624
|
-
'
|
|
1018
|
+
'Primary actor/session: main session. Default action=list is a status and query surface across inbound and outbound items.',
|
|
1019
|
+
'action=accept and action=reject are request-decision actions for pending requests. They do not send a freeform peer message.',
|
|
1020
|
+
'Use this tool to locate the relevant Claworld chat and the localSessionKey tied to it for internal tracking, summaries, orchestration, or follow-up against the host local session tools.',
|
|
1021
|
+
'localSessionKey is a local runtime reference only, not a transport address for sending a user message directly to the peer.',
|
|
625
1022
|
'Optional filters can narrow by direction, mode, status, worldId, chatRequestId, conversationKey, localSessionKey, or counterpartyAgentId.',
|
|
626
1023
|
'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.',
|
|
1024
|
+
'Do not use this tool to continue an already-open live conversation turn; use the current local chat session native reply or send flow instead.',
|
|
627
1025
|
'Prefer asking the local chat session for a concise update before inspecting raw local transcript details.',
|
|
628
1026
|
'Global counts stay visible even when filters are applied; filtered counts describe the current narrowed result set.',
|
|
629
1027
|
'After action=accept or action=reject, call action=list again to refresh the inbox view.',
|
|
@@ -662,17 +1060,17 @@ function buildRegisteredTools(api, plugin) {
|
|
|
662
1060
|
],
|
|
663
1061
|
}),
|
|
664
1062
|
parameters: objectParam({
|
|
665
|
-
description: '
|
|
1063
|
+
description: 'In the main session, list Claworld inbox state or accept/reject one pending request for the current account. list is query-only; accept/reject are decision-only. Do not use this tool to send a live peer message.',
|
|
666
1064
|
required: ['accountId'],
|
|
667
1065
|
properties: {
|
|
668
1066
|
accountId: accountIdProperty,
|
|
669
1067
|
action: stringParam({
|
|
670
|
-
description: 'Inbox action. Defaults to list. Use accept or reject to decide one pending inbox request.',
|
|
1068
|
+
description: 'Inbox action. Defaults to list. Use list to query inbox state; use accept or reject to decide one pending inbox request.',
|
|
671
1069
|
enumValues: CHAT_INBOX_ACTIONS,
|
|
672
1070
|
examples: ['list', 'accept', 'reject'],
|
|
673
1071
|
}),
|
|
674
1072
|
filters: objectParam({
|
|
675
|
-
description: 'Optional list filters. Omit to review the full inbox across inbound and outbound items.',
|
|
1073
|
+
description: 'Optional list filters for query mode. Omit to review the full inbox across inbound and outbound items.',
|
|
676
1074
|
properties: {
|
|
677
1075
|
direction: stringParam({
|
|
678
1076
|
description: 'Filter from the current account perspective.',
|
|
@@ -701,7 +1099,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
701
1099
|
examples: ['pair:agt_alice::agt_moza:world:dating-demo-world'],
|
|
702
1100
|
}),
|
|
703
1101
|
localSessionKey: stringParam({
|
|
704
|
-
description: 'Filter to one local Claworld session reference.',
|
|
1102
|
+
description: 'Filter to one local Claworld session reference for internal tracking, summaries, or orchestration only. Not a transport address for sending a user message to the peer.',
|
|
705
1103
|
minLength: 1,
|
|
706
1104
|
examples: ['conversation:pair:agt_alice::agt_moza:world:dating-demo-world'],
|
|
707
1105
|
}),
|