@xfxstudio/claworld 2026.4.22-testing.5 → 2026.4.22-testing.6
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 +7 -7
- package/package.json +1 -1
- package/skills/claworld-join-and-chat/SKILL.md +1 -1
- package/src/lib/relay/kickoff-progress.js +8 -0
- package/src/openclaw/plugin/config-schema.js +3 -3
- package/src/openclaw/plugin/register.js +3 -4
- package/src/openclaw/plugin/relay-client.js +16 -0
- package/src/openclaw/runtime/tool-contracts.js +6 -0
- package/src/openclaw/runtime/world-moderation-helper.js +11 -1
package/openclaw.plugin.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
],
|
|
9
9
|
"name": "Claworld Persona Relay",
|
|
10
10
|
"description": "Claworld relay world channel plugin for OpenClaw.",
|
|
11
|
-
"version": "2026.4.22-testing.
|
|
11
|
+
"version": "2026.4.22-testing.6",
|
|
12
12
|
"configSchema": {
|
|
13
13
|
"type": "object",
|
|
14
14
|
"additionalProperties": false,
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"world",
|
|
51
51
|
"full"
|
|
52
52
|
],
|
|
53
|
-
"description": "
|
|
53
|
+
"description": "Optional ignored profile selector. Current tool exposure is backend-defined."
|
|
54
54
|
},
|
|
55
55
|
"heartbeatSeconds": {
|
|
56
56
|
"type": "integer",
|
|
@@ -128,12 +128,12 @@
|
|
|
128
128
|
"agentId": {
|
|
129
129
|
"type": "string",
|
|
130
130
|
"minLength": 1,
|
|
131
|
-
"description": "
|
|
131
|
+
"description": "Optional relay agent id hint. The current flow resolves the binding from appToken at runtime."
|
|
132
132
|
},
|
|
133
133
|
"credentialToken": {
|
|
134
134
|
"type": "string",
|
|
135
135
|
"minLength": 1,
|
|
136
|
-
"description": "
|
|
136
|
+
"description": "Optional credential token for this account. appToken is the current field."
|
|
137
137
|
},
|
|
138
138
|
"defaultTargetAgentId": {
|
|
139
139
|
"type": "string",
|
|
@@ -197,7 +197,7 @@
|
|
|
197
197
|
"world",
|
|
198
198
|
"full"
|
|
199
199
|
],
|
|
200
|
-
"description": "
|
|
200
|
+
"description": "Optional ignored profile selector. Current tool exposure is backend-defined."
|
|
201
201
|
},
|
|
202
202
|
"heartbeatSeconds": {
|
|
203
203
|
"type": "integer",
|
|
@@ -275,12 +275,12 @@
|
|
|
275
275
|
"agentId": {
|
|
276
276
|
"type": "string",
|
|
277
277
|
"minLength": 1,
|
|
278
|
-
"description": "
|
|
278
|
+
"description": "Optional relay agent id hint. The current flow resolves the binding from appToken at runtime."
|
|
279
279
|
},
|
|
280
280
|
"credentialToken": {
|
|
281
281
|
"type": "string",
|
|
282
282
|
"minLength": 1,
|
|
283
|
-
"description": "
|
|
283
|
+
"description": "Optional credential token for this account. appToken is the current field."
|
|
284
284
|
},
|
|
285
285
|
"defaultTargetAgentId": {
|
|
286
286
|
"type": "string",
|
package/package.json
CHANGED
|
@@ -215,7 +215,7 @@ ANNOUNCE_SKIP
|
|
|
215
215
|
|
|
216
216
|
常见下一步是 `claworld_get_world_detail`,但不是写死的唯一下一步。
|
|
217
217
|
|
|
218
|
-
`claworld_list_worlds`
|
|
218
|
+
`claworld_list_worlds` 用于无关键词浏览 world。用户带有主题、意图、爱好、地点等关键词时,优先用 `claworld_search_worlds`。
|
|
219
219
|
|
|
220
220
|
## `claworld_get_world_detail`
|
|
221
221
|
|
|
@@ -121,6 +121,8 @@ export async function markAcceptedChatKickoffProgressWithDeps(deps, {
|
|
|
121
121
|
turnId = null,
|
|
122
122
|
deliveryId = null,
|
|
123
123
|
conversationKey = null,
|
|
124
|
+
sessionKey = null,
|
|
125
|
+
localSessionKey = null,
|
|
124
126
|
senderKickoffDeliveredAt = null,
|
|
125
127
|
openerAcceptedAt = null,
|
|
126
128
|
openerDeliveredAt = null,
|
|
@@ -141,6 +143,12 @@ export async function markAcceptedChatKickoffProgressWithDeps(deps, {
|
|
|
141
143
|
...(normalizeOptionalText(turnId) ? { turnId: normalizeOptionalText(turnId) } : {}),
|
|
142
144
|
...(normalizeOptionalText(deliveryId) ? { deliveryId: normalizeOptionalText(deliveryId) } : {}),
|
|
143
145
|
...(normalizeOptionalText(conversationKey) ? { conversationKey: normalizeOptionalText(conversationKey) } : {}),
|
|
146
|
+
...(normalizeOptionalText(sessionKey) ? { sessionKey: normalizeOptionalText(sessionKey) } : {}),
|
|
147
|
+
...(normalizeOptionalText(localSessionKey)
|
|
148
|
+
? { localSessionKey: normalizeOptionalText(localSessionKey) }
|
|
149
|
+
: normalizeOptionalText(sessionKey)
|
|
150
|
+
? { localSessionKey: normalizeOptionalText(sessionKey) }
|
|
151
|
+
: {}),
|
|
144
152
|
...(normalizeOptionalText(senderKickoffDeliveredAt)
|
|
145
153
|
? {
|
|
146
154
|
senderKickoffDeliveredAt: normalizeOptionalText(senderKickoffDeliveredAt),
|
|
@@ -40,12 +40,12 @@ export const MANUAL_RELAY_BINDING_SCHEMA = {
|
|
|
40
40
|
agentId: {
|
|
41
41
|
type: 'string',
|
|
42
42
|
minLength: 1,
|
|
43
|
-
description: '
|
|
43
|
+
description: 'Optional relay agent id hint. The current flow resolves the binding from appToken at runtime.',
|
|
44
44
|
},
|
|
45
45
|
credentialToken: {
|
|
46
46
|
type: 'string',
|
|
47
47
|
minLength: 1,
|
|
48
|
-
description: '
|
|
48
|
+
description: 'Optional credential token for this account. appToken is the current field.',
|
|
49
49
|
},
|
|
50
50
|
defaultTargetAgentId: {
|
|
51
51
|
type: 'string',
|
|
@@ -85,7 +85,7 @@ const SINGLE_ACCOUNT_PROPERTIES = {
|
|
|
85
85
|
toolProfile: {
|
|
86
86
|
type: 'string',
|
|
87
87
|
enum: ['minimal', 'default', 'world', 'full'],
|
|
88
|
-
description: '
|
|
88
|
+
description: 'Optional ignored profile selector. Current tool exposure is backend-defined.',
|
|
89
89
|
},
|
|
90
90
|
heartbeatSeconds: {
|
|
91
91
|
type: 'integer',
|
|
@@ -203,7 +203,6 @@ function buildRegisteredTools(api, plugin) {
|
|
|
203
203
|
'This is the main public discovery surface for worlds.',
|
|
204
204
|
'Leave query empty to browse by hot or latest; provide a query to search by free-form intent such as hobby, location, or relationship goal.',
|
|
205
205
|
'Expected behavior: returns paginated world summaries plus structured follow-up actions for detail and join.',
|
|
206
|
-
'claworld_list_worlds is only the compatibility browse alias for the empty-query branch.',
|
|
207
206
|
],
|
|
208
207
|
examples: [
|
|
209
208
|
{
|
|
@@ -278,12 +277,12 @@ function buildRegisteredTools(api, plugin) {
|
|
|
278
277
|
{
|
|
279
278
|
name: 'claworld_list_worlds',
|
|
280
279
|
label: 'Claworld List Worlds',
|
|
281
|
-
description: '
|
|
280
|
+
description: 'Browse worlds without a query. Use claworld_search_worlds when the user supplies topic, intent, hobby, location, or other keywords.',
|
|
282
281
|
metadata: buildToolMetadata({
|
|
283
282
|
category: 'world_discovery',
|
|
284
283
|
usageNotes: [
|
|
285
|
-
'
|
|
286
|
-
'
|
|
284
|
+
'This tool returns the no-query world browse result.',
|
|
285
|
+
'Use claworld_search_worlds when the user supplies topic, intent, hobby, location, or other keywords.',
|
|
287
286
|
],
|
|
288
287
|
examples: [
|
|
289
288
|
{
|
|
@@ -683,6 +683,7 @@ export class ClaworldRelayClient extends EventEmitter {
|
|
|
683
683
|
const cleanup = () => {
|
|
684
684
|
if (timeout) clearTimeout(timeout);
|
|
685
685
|
this.off('reply.accepted', onReplyAccepted);
|
|
686
|
+
this.off('command.accepted', onCommandAccepted);
|
|
686
687
|
this.off('disconnect', onDisconnect);
|
|
687
688
|
this.off('close', onDisconnect);
|
|
688
689
|
};
|
|
@@ -707,6 +708,20 @@ export class ClaworldRelayClient extends EventEmitter {
|
|
|
707
708
|
settleResolve(message);
|
|
708
709
|
};
|
|
709
710
|
|
|
711
|
+
const onCommandAccepted = (message = {}) => {
|
|
712
|
+
const command = message?.data?.command && typeof message.data.command === 'object'
|
|
713
|
+
? message.data.command
|
|
714
|
+
: {};
|
|
715
|
+
if (normalizeOptionalText(command.name) !== 'delivery.reply.requested') return;
|
|
716
|
+
const commandDeliveryId = [
|
|
717
|
+
command.deliveryId,
|
|
718
|
+
command.aggregateId,
|
|
719
|
+
command.partitionKey,
|
|
720
|
+
].map((value) => normalizeOptionalText(value)).find(Boolean) || null;
|
|
721
|
+
if (commandDeliveryId !== normalizedDeliveryId) return;
|
|
722
|
+
settleResolve(message);
|
|
723
|
+
};
|
|
724
|
+
|
|
710
725
|
const onDisconnect = (info = {}) => {
|
|
711
726
|
settleReject(createRuntimeBoundaryError({
|
|
712
727
|
code: 'relay_reply_ack_disconnected',
|
|
@@ -725,6 +740,7 @@ export class ClaworldRelayClient extends EventEmitter {
|
|
|
725
740
|
};
|
|
726
741
|
|
|
727
742
|
this.on('reply.accepted', onReplyAccepted);
|
|
743
|
+
this.on('command.accepted', onCommandAccepted);
|
|
728
744
|
this.on('disconnect', onDisconnect);
|
|
729
745
|
this.on('close', onDisconnect);
|
|
730
746
|
|
|
@@ -589,7 +589,12 @@ function projectToolWorldBroadcastFailureItem(item = {}) {
|
|
|
589
589
|
export function projectToolWorldBroadcastResponse(payload = {}, { accountId = null } = {}) {
|
|
590
590
|
return {
|
|
591
591
|
accountId: normalizeText(accountId, null),
|
|
592
|
+
accepted: payload.accepted === true,
|
|
592
593
|
status: normalizeText(payload.status, null),
|
|
594
|
+
commandId: normalizeText(payload.commandId, null),
|
|
595
|
+
command: payload.command && typeof payload.command === 'object' && !Array.isArray(payload.command)
|
|
596
|
+
? payload.command
|
|
597
|
+
: null,
|
|
593
598
|
worldId: normalizeText(payload.worldId, null),
|
|
594
599
|
senderAgentId: normalizeText(payload.senderAgentId, null),
|
|
595
600
|
senderRole: projectWorldRole(payload.senderRole, null),
|
|
@@ -597,6 +602,7 @@ export function projectToolWorldBroadcastResponse(payload = {}, { accountId = nu
|
|
|
597
602
|
excludeSelf: normalizeOptionalBoolean(payload.excludeSelf, null),
|
|
598
603
|
eligibility: normalizeText(payload.eligibility, null),
|
|
599
604
|
broadcastId: normalizeText(payload.broadcastId, null),
|
|
605
|
+
fanoutStatus: normalizeText(payload.fanoutStatus, null),
|
|
600
606
|
totalTargets: normalizeOptionalInteger(payload.totalTargets, null),
|
|
601
607
|
createdCount: normalizeOptionalInteger(payload.createdCount, null),
|
|
602
608
|
failedCount: normalizeOptionalInteger(payload.failedCount, null),
|
|
@@ -167,7 +167,12 @@ function normalizeWorldBroadcastFailureItem(item = {}) {
|
|
|
167
167
|
|
|
168
168
|
function normalizeWorldBroadcastResponse(payload = {}) {
|
|
169
169
|
return {
|
|
170
|
+
accepted: payload.accepted === true,
|
|
170
171
|
status: normalizeText(payload.status, null),
|
|
172
|
+
commandId: normalizeText(payload.commandId, null),
|
|
173
|
+
command: payload.command && typeof payload.command === 'object' && !Array.isArray(payload.command)
|
|
174
|
+
? payload.command
|
|
175
|
+
: null,
|
|
171
176
|
worldId: normalizeText(payload.worldId, null),
|
|
172
177
|
senderAgentId: normalizeText(payload.senderAgentId, null),
|
|
173
178
|
senderRole: normalizeWorldRole(payload.senderRole, null),
|
|
@@ -175,6 +180,7 @@ function normalizeWorldBroadcastResponse(payload = {}) {
|
|
|
175
180
|
excludeSelf: normalizeOptionalBoolean(payload.excludeSelf, null),
|
|
176
181
|
eligibility: normalizeText(payload.eligibility, null),
|
|
177
182
|
broadcastId: normalizeText(payload.broadcastId, null),
|
|
183
|
+
fanoutStatus: normalizeText(payload.fanoutStatus, null),
|
|
178
184
|
totalTargets: normalizeOptionalInteger(payload.totalTargets, null),
|
|
179
185
|
createdCount: normalizeOptionalInteger(payload.createdCount, null),
|
|
180
186
|
failedCount: normalizeOptionalInteger(payload.failedCount, null),
|
|
@@ -504,5 +510,9 @@ export async function broadcastModeratedWorld({
|
|
|
504
510
|
});
|
|
505
511
|
}
|
|
506
512
|
|
|
507
|
-
return normalizeWorldBroadcastResponse(
|
|
513
|
+
return normalizeWorldBroadcastResponse({
|
|
514
|
+
...result.body,
|
|
515
|
+
worldId: resolvedWorldId,
|
|
516
|
+
senderAgentId: resolvedAgentId,
|
|
517
|
+
});
|
|
508
518
|
}
|