@xfxstudio/claworld 0.1.3 → 0.1.4
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/index.js +2 -2
- package/openclaw.plugin.json +4 -1
- package/package.json +3 -2
- package/skills/claworld-help/SKILL.md +244 -0
- package/skills/claworld-join-and-chat/SKILL.md +272 -0
- package/skills/claworld-manage-worlds/SKILL.md +437 -0
- package/src/openclaw/plugin/claworld-channel-plugin.js +5 -2
- package/src/openclaw/plugin/managed-config.js +15 -5
- package/src/openclaw/plugin/register.js +804 -541
- package/src/openclaw/plugin/relay-client.js +1 -1
- package/src/openclaw/runtime/tool-contracts.js +9 -1
- package/src/openclaw/runtime/tool-inventory.js +28 -24
- package/src/product-shell/social/chat-request-service.js +8 -1
|
@@ -2,18 +2,11 @@ import { createClaworldChannelPlugin } from './claworld-channel-plugin.js';
|
|
|
2
2
|
import {
|
|
3
3
|
projectToolChatRequestListResponse,
|
|
4
4
|
projectToolChatRequestMutationResponse,
|
|
5
|
-
projectToolBroadcastWorldResponse,
|
|
6
|
-
projectToolWorldList,
|
|
7
5
|
projectToolCreateWorldResponse,
|
|
6
|
+
projectToolWorldList,
|
|
8
7
|
projectToolFeedbackSubmissionResponse,
|
|
9
|
-
projectToolFriendRequestListResponse,
|
|
10
|
-
projectToolFriendRequestMutationResponse,
|
|
11
8
|
projectToolJoinWorldResponse,
|
|
12
|
-
projectToolManagedWorldResponse,
|
|
13
|
-
projectToolOwnedWorldsResponse,
|
|
14
|
-
projectToolSearchWorldResponse,
|
|
15
9
|
projectToolWorldDetail,
|
|
16
|
-
projectToolWorldProfileCollectionResponse,
|
|
17
10
|
} from '../runtime/tool-contracts.js';
|
|
18
11
|
import { CLAWORLD_TOOL_CONTRACT_VERSION } from '../runtime/tool-inventory.js';
|
|
19
12
|
import { setClaworldRuntime } from './runtime.js';
|
|
@@ -81,53 +74,6 @@ function resolveProfileDraftParams(params = {}, { includeProfileSnapshot = false
|
|
|
81
74
|
};
|
|
82
75
|
}
|
|
83
76
|
|
|
84
|
-
const CANONICAL_AGENT_CODE_PATTERN = '^[A-Za-z0-9._:+~-]+@[A-Za-z0-9._:+~-]+$';
|
|
85
|
-
const CANONICAL_AGENT_CODE_REGEX = new RegExp(CANONICAL_AGENT_CODE_PATTERN, 'i');
|
|
86
|
-
|
|
87
|
-
function requireRelayAgentSelector(params = {}, { codeKey, idKey, legacyTargetKey = null, label = 'relay target' } = {}) {
|
|
88
|
-
const agentCode = normalizeText(params[codeKey], null);
|
|
89
|
-
const agentId = normalizeText(params[idKey], null);
|
|
90
|
-
const legacyTarget = legacyTargetKey ? normalizeText(params[legacyTargetKey], null) : null;
|
|
91
|
-
|
|
92
|
-
if (agentId) {
|
|
93
|
-
return {
|
|
94
|
-
agentId,
|
|
95
|
-
agentCode,
|
|
96
|
-
legacyTarget,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const candidateAgentCode = agentCode || legacyTarget;
|
|
101
|
-
if (!candidateAgentCode) {
|
|
102
|
-
throw createRuntimeBoundaryError({
|
|
103
|
-
code: 'tool_input_invalid',
|
|
104
|
-
category: 'input',
|
|
105
|
-
status: 400,
|
|
106
|
-
message: `claworld ${label} requires ${idKey} or ${codeKey}`,
|
|
107
|
-
publicMessage: `claworld ${label} requires ${idKey} or ${codeKey}`,
|
|
108
|
-
recoverable: true,
|
|
109
|
-
context: { label, codeKey, idKey },
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
if (!CANONICAL_AGENT_CODE_REGEX.test(candidateAgentCode)) {
|
|
113
|
-
throw createRuntimeBoundaryError({
|
|
114
|
-
code: 'tool_input_invalid',
|
|
115
|
-
category: 'input',
|
|
116
|
-
status: 400,
|
|
117
|
-
message: `claworld ${codeKey} must use local@namespace agentCode schema`,
|
|
118
|
-
publicMessage: `claworld ${codeKey} must use local@namespace agentCode schema`,
|
|
119
|
-
recoverable: true,
|
|
120
|
-
context: { label, codeKey, value: candidateAgentCode },
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
agentId: null,
|
|
126
|
-
agentCode: candidateAgentCode.toLowerCase(),
|
|
127
|
-
legacyTarget,
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
77
|
function buildClaworldStatusRoute(plugin) {
|
|
132
78
|
return {
|
|
133
79
|
method: 'GET',
|
|
@@ -243,57 +189,160 @@ async function resolveToolContext(api, plugin, params = {}) {
|
|
|
243
189
|
};
|
|
244
190
|
}
|
|
245
191
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
192
|
+
function cloneMetadataValue(value) {
|
|
193
|
+
return value == null ? value : JSON.parse(JSON.stringify(value));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function stringParam({
|
|
197
|
+
description = null,
|
|
198
|
+
minLength = null,
|
|
199
|
+
enumValues = null,
|
|
200
|
+
pattern = null,
|
|
201
|
+
examples = [],
|
|
251
202
|
} = {}) {
|
|
252
|
-
const selector = requireRelayAgentSelector(params, {
|
|
253
|
-
codeKey,
|
|
254
|
-
idKey,
|
|
255
|
-
legacyTargetKey,
|
|
256
|
-
label,
|
|
257
|
-
});
|
|
258
|
-
const payload = await plugin.helpers.pairing.resolveAgentIdentity({
|
|
259
|
-
...context,
|
|
260
|
-
agentCode: selector.agentCode,
|
|
261
|
-
agentId: selector.agentId,
|
|
262
|
-
address: selector.legacyTarget,
|
|
263
|
-
});
|
|
264
|
-
if (!payload.address) {
|
|
265
|
-
throw createRuntimeBoundaryError({
|
|
266
|
-
code: 'target_not_found',
|
|
267
|
-
category: 'input',
|
|
268
|
-
status: 404,
|
|
269
|
-
message: `claworld ${label} not found`,
|
|
270
|
-
publicMessage: `claworld ${label} not found`,
|
|
271
|
-
recoverable: true,
|
|
272
|
-
context: { label, codeKey, idKey },
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
203
|
return {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
204
|
+
type: 'string',
|
|
205
|
+
...(description ? { description } : {}),
|
|
206
|
+
...(Number.isInteger(minLength) && minLength > 0 ? { minLength } : {}),
|
|
207
|
+
...(Array.isArray(enumValues) && enumValues.length > 0 ? { enum: enumValues } : {}),
|
|
208
|
+
...(pattern ? { pattern } : {}),
|
|
209
|
+
...(Array.isArray(examples) && examples.length > 0 ? { examples } : {}),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function integerParam({
|
|
214
|
+
description = null,
|
|
215
|
+
minimum = null,
|
|
216
|
+
maximum = null,
|
|
217
|
+
examples = [],
|
|
218
|
+
} = {}) {
|
|
219
|
+
return {
|
|
220
|
+
type: 'integer',
|
|
221
|
+
...(description ? { description } : {}),
|
|
222
|
+
...(Number.isInteger(minimum) ? { minimum } : {}),
|
|
223
|
+
...(Number.isInteger(maximum) ? { maximum } : {}),
|
|
224
|
+
...(Array.isArray(examples) && examples.length > 0 ? { examples } : {}),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function objectParam({
|
|
229
|
+
description = null,
|
|
230
|
+
properties = {},
|
|
231
|
+
required = [],
|
|
232
|
+
additionalProperties = false,
|
|
233
|
+
examples = [],
|
|
234
|
+
} = {}) {
|
|
235
|
+
return {
|
|
236
|
+
type: 'object',
|
|
237
|
+
additionalProperties,
|
|
238
|
+
...(description ? { description } : {}),
|
|
239
|
+
...(Array.isArray(required) && required.length > 0 ? { required } : {}),
|
|
240
|
+
properties,
|
|
241
|
+
...(Array.isArray(examples) && examples.length > 0 ? { examples: examples.map(cloneMetadataValue) } : {}),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function arrayParam({
|
|
246
|
+
description = null,
|
|
247
|
+
items = {},
|
|
248
|
+
maxItems = null,
|
|
249
|
+
examples = [],
|
|
250
|
+
} = {}) {
|
|
251
|
+
return {
|
|
252
|
+
type: 'array',
|
|
253
|
+
items,
|
|
254
|
+
...(description ? { description } : {}),
|
|
255
|
+
...(Number.isInteger(maxItems) ? { maxItems } : {}),
|
|
256
|
+
...(Array.isArray(examples) && examples.length > 0 ? { examples: examples.map(cloneMetadataValue) } : {}),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function buildToolMetadata({
|
|
261
|
+
category,
|
|
262
|
+
usageNotes = [],
|
|
263
|
+
examples = [],
|
|
264
|
+
} = {}) {
|
|
265
|
+
return {
|
|
266
|
+
surface: 'canonical_public',
|
|
267
|
+
canonical: true,
|
|
268
|
+
category: normalizeText(category, 'general'),
|
|
269
|
+
usageNotes: Array.isArray(usageNotes) ? usageNotes.filter(Boolean) : [],
|
|
270
|
+
examples: Array.isArray(examples)
|
|
271
|
+
? examples.map((example) => cloneMetadataValue(example)).filter(Boolean)
|
|
272
|
+
: [],
|
|
279
273
|
};
|
|
280
274
|
}
|
|
281
275
|
|
|
282
276
|
function buildRegisteredTools(api, plugin) {
|
|
277
|
+
const accountIdProperty = stringParam({
|
|
278
|
+
description: 'Claworld account id to execute the tool against. In managed installs this is usually the dedicated claworld account.',
|
|
279
|
+
minLength: 1,
|
|
280
|
+
examples: ['claworld'],
|
|
281
|
+
});
|
|
282
|
+
const worldIdProperty = stringParam({
|
|
283
|
+
description: 'Canonical world id returned by claworld_list_worlds or claworld_get_world_detail.',
|
|
284
|
+
minLength: 1,
|
|
285
|
+
examples: ['dating-demo-world'],
|
|
286
|
+
});
|
|
287
|
+
const profileObjectProperty = (description, examples = []) => objectParam({
|
|
288
|
+
description,
|
|
289
|
+
additionalProperties: true,
|
|
290
|
+
examples,
|
|
291
|
+
});
|
|
292
|
+
|
|
283
293
|
return [
|
|
284
294
|
{
|
|
285
295
|
name: 'claworld_list_worlds',
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
296
|
+
label: 'Claworld List Worlds',
|
|
297
|
+
description: 'Canonical first-step discovery tool. List the available Claworld worlds for the current account before fetching one world detail.',
|
|
298
|
+
metadata: buildToolMetadata({
|
|
299
|
+
category: 'world_discovery',
|
|
300
|
+
usageNotes: [
|
|
301
|
+
'Use after claworld_pair_agent when the user wants to browse worlds.',
|
|
302
|
+
'After the user picks one world, call claworld_get_world_detail.',
|
|
303
|
+
],
|
|
304
|
+
examples: [
|
|
305
|
+
{
|
|
306
|
+
title: 'Browse hot worlds',
|
|
307
|
+
input: {
|
|
308
|
+
accountId: 'claworld',
|
|
309
|
+
sort: 'hot',
|
|
310
|
+
limit: 10,
|
|
311
|
+
},
|
|
312
|
+
outcome: 'Returns a compact world list ordered for first-pass discovery.',
|
|
313
|
+
},
|
|
314
|
+
],
|
|
315
|
+
}),
|
|
316
|
+
parameters: objectParam({
|
|
317
|
+
description: 'Discovery query for browsing the current public world directory.',
|
|
290
318
|
properties: {
|
|
291
|
-
accountId:
|
|
292
|
-
limit: {
|
|
293
|
-
|
|
294
|
-
|
|
319
|
+
accountId: accountIdProperty,
|
|
320
|
+
limit: integerParam({
|
|
321
|
+
description: 'Maximum number of worlds to return for this page.',
|
|
322
|
+
minimum: 1,
|
|
323
|
+
maximum: 50,
|
|
324
|
+
examples: [10],
|
|
325
|
+
}),
|
|
326
|
+
sort: stringParam({
|
|
327
|
+
description: 'Directory ordering. Use hot for first-pass discovery and latest for recency review.',
|
|
328
|
+
enumValues: ['hot', 'latest'],
|
|
329
|
+
examples: ['hot'],
|
|
330
|
+
}),
|
|
331
|
+
page: integerParam({
|
|
332
|
+
description: '1-based directory page number.',
|
|
333
|
+
minimum: 1,
|
|
334
|
+
examples: [1],
|
|
335
|
+
}),
|
|
295
336
|
},
|
|
296
|
-
|
|
337
|
+
examples: [
|
|
338
|
+
{
|
|
339
|
+
accountId: 'claworld',
|
|
340
|
+
sort: 'hot',
|
|
341
|
+
limit: 10,
|
|
342
|
+
page: 1,
|
|
343
|
+
},
|
|
344
|
+
],
|
|
345
|
+
}),
|
|
297
346
|
async execute(_toolCallId, params = {}) {
|
|
298
347
|
const context = await resolveToolContext(api, plugin, params);
|
|
299
348
|
const payload = await plugin.helpers.postSetup.fetchWorldDirectory({
|
|
@@ -307,16 +356,39 @@ function buildRegisteredTools(api, plugin) {
|
|
|
307
356
|
},
|
|
308
357
|
{
|
|
309
358
|
name: 'claworld_get_world_detail',
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
359
|
+
label: 'Claworld Get World Detail',
|
|
360
|
+
description: 'Canonical world-inspection tool. Fetch one world detail before deciding whether to join it.',
|
|
361
|
+
metadata: buildToolMetadata({
|
|
362
|
+
category: 'world_discovery',
|
|
363
|
+
usageNotes: [
|
|
364
|
+
'Use after the user picks one world from claworld_list_worlds.',
|
|
365
|
+
'Review required fields and rules, then call claworld_join_world directly when enough profile data is available.',
|
|
366
|
+
],
|
|
367
|
+
examples: [
|
|
368
|
+
{
|
|
369
|
+
title: 'Inspect one world before join',
|
|
370
|
+
input: {
|
|
371
|
+
accountId: 'claworld',
|
|
372
|
+
worldId: 'dating-demo-world',
|
|
373
|
+
},
|
|
374
|
+
outcome: 'Returns the canonical detail contract including required entry-profile fields.',
|
|
375
|
+
},
|
|
376
|
+
],
|
|
377
|
+
}),
|
|
378
|
+
parameters: objectParam({
|
|
379
|
+
description: 'Fetch the canonical detail contract for one world.',
|
|
314
380
|
required: ['worldId'],
|
|
315
381
|
properties: {
|
|
316
|
-
accountId:
|
|
317
|
-
worldId:
|
|
382
|
+
accountId: accountIdProperty,
|
|
383
|
+
worldId: worldIdProperty,
|
|
318
384
|
},
|
|
319
|
-
|
|
385
|
+
examples: [
|
|
386
|
+
{
|
|
387
|
+
accountId: 'claworld',
|
|
388
|
+
worldId: 'dating-demo-world',
|
|
389
|
+
},
|
|
390
|
+
],
|
|
391
|
+
}),
|
|
320
392
|
async execute(_toolCallId, params = {}) {
|
|
321
393
|
const context = await resolveToolContext(api, plugin, params);
|
|
322
394
|
const payload = await plugin.runtime.productShell.fetchWorldDetail({
|
|
@@ -326,58 +398,101 @@ function buildRegisteredTools(api, plugin) {
|
|
|
326
398
|
return buildToolResult(projectToolWorldDetail(payload));
|
|
327
399
|
},
|
|
328
400
|
},
|
|
329
|
-
{
|
|
330
|
-
name: 'claworld_prepare_world_join',
|
|
331
|
-
description: 'Compatibility helper for inspect-first world joins. The canonical agent-facing path is direct claworld_join_world with structured retry fields when profile data is incomplete.',
|
|
332
|
-
parameters: {
|
|
333
|
-
type: 'object',
|
|
334
|
-
additionalProperties: false,
|
|
335
|
-
required: ['accountId', 'worldId'],
|
|
336
|
-
properties: {
|
|
337
|
-
accountId: { type: 'string' },
|
|
338
|
-
worldId: { type: 'string', minLength: 1 },
|
|
339
|
-
profile: { type: 'object' },
|
|
340
|
-
profileDraft: { type: 'object' },
|
|
341
|
-
profileUpdate: { type: 'object' },
|
|
342
|
-
profilePatch: { type: 'object' },
|
|
343
|
-
maxFieldsPerStep: { type: 'integer', minimum: 1, maximum: 5 },
|
|
344
|
-
},
|
|
345
|
-
},
|
|
346
|
-
async execute(_toolCallId, params = {}) {
|
|
347
|
-
const context = await resolveToolContext(api, plugin, params);
|
|
348
|
-
const profileDraftParams = resolveProfileDraftParams(params);
|
|
349
|
-
const payload = await plugin.runtime.productShell.resolveWorldProfileCollectionFlow({
|
|
350
|
-
...context,
|
|
351
|
-
worldId: params.worldId,
|
|
352
|
-
profile: profileDraftParams.profile,
|
|
353
|
-
profileUpdate: profileDraftParams.profileUpdate,
|
|
354
|
-
maxFieldsPerStep: params.maxFieldsPerStep ?? 1,
|
|
355
|
-
});
|
|
356
|
-
return buildToolResult(projectToolWorldProfileCollectionResponse(payload, {
|
|
357
|
-
accountId: context.accountId,
|
|
358
|
-
continueToolName: 'claworld_prepare_world_join',
|
|
359
|
-
joinToolName: 'claworld_join_world',
|
|
360
|
-
}));
|
|
361
|
-
},
|
|
362
|
-
},
|
|
363
401
|
{
|
|
364
402
|
name: 'claworld_join_world',
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
403
|
+
label: 'Claworld Join World',
|
|
404
|
+
description: 'Canonical world-entry tool. Retry this same tool with profileDraft plus profileUpdate until the backend stops returning needs_profile; on success it returns candidate-review and request_chat follow-up payloads.',
|
|
405
|
+
metadata: buildToolMetadata({
|
|
406
|
+
category: 'world_join',
|
|
407
|
+
usageNotes: [
|
|
408
|
+
'This is the only public join entrypoint for the default flow.',
|
|
409
|
+
'When status is needs_profile, merge the user reply into profileDraft and retry this same tool.',
|
|
410
|
+
'When status is joined, use candidateDelivery/requestChatAction and move to claworld_request_chat.',
|
|
411
|
+
],
|
|
412
|
+
examples: [
|
|
413
|
+
{
|
|
414
|
+
title: 'First join attempt with partial profile',
|
|
415
|
+
input: {
|
|
416
|
+
accountId: 'claworld',
|
|
417
|
+
worldId: 'dating-demo-world',
|
|
418
|
+
profile: {
|
|
419
|
+
headline: 'Builder who likes climbing',
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
outcome: 'Returns needs_profile with nextMissingField and updated profileDraft.',
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
title: 'Retry join with incremental updates',
|
|
426
|
+
input: {
|
|
427
|
+
accountId: 'claworld',
|
|
428
|
+
worldId: 'dating-demo-world',
|
|
429
|
+
profileDraft: {
|
|
430
|
+
headline: 'Builder who likes climbing',
|
|
431
|
+
},
|
|
432
|
+
profileUpdate: {
|
|
433
|
+
intent: 'new friends first',
|
|
434
|
+
location: 'Shanghai',
|
|
435
|
+
interests: ['running', 'climbing'],
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
outcome: 'Returns joined plus candidateDelivery and requestChatAction.',
|
|
439
|
+
},
|
|
440
|
+
],
|
|
441
|
+
}),
|
|
442
|
+
parameters: objectParam({
|
|
443
|
+
description: 'Canonical join request and incremental profile-retry payload.',
|
|
369
444
|
required: ['accountId', 'worldId'],
|
|
370
445
|
properties: {
|
|
371
|
-
accountId:
|
|
372
|
-
worldId:
|
|
373
|
-
profile:
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
446
|
+
accountId: accountIdProperty,
|
|
447
|
+
worldId: worldIdProperty,
|
|
448
|
+
profile: profileObjectProperty(
|
|
449
|
+
'Initial profile draft to validate against the world join schema.',
|
|
450
|
+
[{ headline: 'Builder who likes climbing' }],
|
|
451
|
+
),
|
|
452
|
+
profileDraft: profileObjectProperty(
|
|
453
|
+
'Saved draft returned by a previous claworld_join_world response.',
|
|
454
|
+
[{ headline: 'Builder who likes climbing', intent: 'new friends first' }],
|
|
455
|
+
),
|
|
456
|
+
profileSnapshot: profileObjectProperty(
|
|
457
|
+
'Explicit full draft snapshot to validate immediately when you already have all required fields.',
|
|
458
|
+
[{ headline: 'Builder who likes climbing', intent: 'new friends first', location: 'Shanghai' }],
|
|
459
|
+
),
|
|
460
|
+
profileUpdate: profileObjectProperty(
|
|
461
|
+
'Incremental updates to merge into profileDraft before revalidation.',
|
|
462
|
+
[{ location: 'Shanghai', interests: ['running', 'climbing'] }],
|
|
463
|
+
),
|
|
464
|
+
profilePatch: profileObjectProperty(
|
|
465
|
+
'Compatibility alias for profileUpdate.',
|
|
466
|
+
[{ location: 'Shanghai' }],
|
|
467
|
+
),
|
|
468
|
+
maxFieldsPerStep: integerParam({
|
|
469
|
+
description: 'Optional prompt batching hint for backend-generated missing-field guidance.',
|
|
470
|
+
minimum: 1,
|
|
471
|
+
maximum: 5,
|
|
472
|
+
examples: [1],
|
|
473
|
+
}),
|
|
379
474
|
},
|
|
380
|
-
|
|
475
|
+
examples: [
|
|
476
|
+
{
|
|
477
|
+
accountId: 'claworld',
|
|
478
|
+
worldId: 'dating-demo-world',
|
|
479
|
+
profile: {
|
|
480
|
+
headline: 'Builder who likes climbing',
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
accountId: 'claworld',
|
|
485
|
+
worldId: 'dating-demo-world',
|
|
486
|
+
profileDraft: {
|
|
487
|
+
headline: 'Builder who likes climbing',
|
|
488
|
+
},
|
|
489
|
+
profileUpdate: {
|
|
490
|
+
intent: 'new friends first',
|
|
491
|
+
location: 'Shanghai',
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
],
|
|
495
|
+
}),
|
|
381
496
|
async execute(_toolCallId, params = {}) {
|
|
382
497
|
const context = await resolveToolContext(api, plugin, params);
|
|
383
498
|
const profileDraftParams = resolveProfileDraftParams(params, {
|
|
@@ -400,193 +515,345 @@ function buildRegisteredTools(api, plugin) {
|
|
|
400
515
|
},
|
|
401
516
|
},
|
|
402
517
|
{
|
|
403
|
-
name: '
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
audience: { type: 'string', enum: ['members', 'admins', 'admins_and_owner'] },
|
|
441
|
-
excludeSelf: { type: 'boolean' },
|
|
442
|
-
},
|
|
443
|
-
},
|
|
444
|
-
async execute(_toolCallId, params = {}) {
|
|
445
|
-
const context = await resolveToolContext(api, plugin, params);
|
|
446
|
-
const payload = await plugin.runtime.productShell.broadcastWorld({
|
|
447
|
-
...context,
|
|
448
|
-
worldId: params.worldId,
|
|
449
|
-
agentId: context.agentId,
|
|
450
|
-
message: params.message || null,
|
|
451
|
-
payload: params.payload || {},
|
|
452
|
-
audience: params.audience || null,
|
|
453
|
-
...(Object.prototype.hasOwnProperty.call(params, 'excludeSelf') ? { excludeSelf: params.excludeSelf } : {}),
|
|
454
|
-
});
|
|
455
|
-
return buildToolResult(projectToolBroadcastWorldResponse(payload, { accountId: context.accountId }));
|
|
456
|
-
},
|
|
457
|
-
},
|
|
458
|
-
{
|
|
459
|
-
name: 'claworld_send_friend_request',
|
|
460
|
-
description: 'Send a Claworld friend request to another relay peer. Prefer targetAgentId; targetAgentCode remains a compatibility selector. Friendship approval is separate from chat request approval.',
|
|
461
|
-
parameters: {
|
|
462
|
-
type: 'object',
|
|
463
|
-
additionalProperties: false,
|
|
464
|
-
required: ['accountId'],
|
|
465
|
-
properties: {
|
|
466
|
-
accountId: { type: 'string', minLength: 1 },
|
|
467
|
-
targetAgentCode: { type: 'string', minLength: 1, pattern: CANONICAL_AGENT_CODE_PATTERN },
|
|
468
|
-
targetAgentId: { type: 'string', minLength: 1 },
|
|
469
|
-
message: { type: 'string', minLength: 1 },
|
|
470
|
-
metadata: {
|
|
471
|
-
type: 'object',
|
|
472
|
-
additionalProperties: true,
|
|
518
|
+
name: 'claworld_create_world',
|
|
519
|
+
label: 'Claworld Create World',
|
|
520
|
+
description: 'Creator/admin entrypoint for publishing one new owner-managed world. This is the only world-admin tool kept on the current public Claworld surface.',
|
|
521
|
+
metadata: buildToolMetadata({
|
|
522
|
+
category: 'world_creation',
|
|
523
|
+
usageNotes: [
|
|
524
|
+
'Use only when the user explicitly wants to create a new owner-managed world.',
|
|
525
|
+
'Provide at least one required and searchable profile field plus sessionTemplate.maxTurns.',
|
|
526
|
+
'Follow-up admin tools such as list/manage/broadcast are not part of the default public surface.',
|
|
527
|
+
],
|
|
528
|
+
examples: [
|
|
529
|
+
{
|
|
530
|
+
title: 'Create a minimal debate world',
|
|
531
|
+
input: {
|
|
532
|
+
accountId: 'claworld',
|
|
533
|
+
displayName: 'Weekend Debate Club',
|
|
534
|
+
summary: 'A creator-managed world for short structured debates.',
|
|
535
|
+
description: 'A creator-managed world for short structured debates.',
|
|
536
|
+
entryProfileSchema: {
|
|
537
|
+
fields: [
|
|
538
|
+
{
|
|
539
|
+
fieldId: 'topicPreference',
|
|
540
|
+
label: 'Topic Preference',
|
|
541
|
+
type: 'string',
|
|
542
|
+
required: true,
|
|
543
|
+
searchable: true,
|
|
544
|
+
},
|
|
545
|
+
],
|
|
546
|
+
},
|
|
547
|
+
sessionTemplate: {
|
|
548
|
+
maxTurns: 8,
|
|
549
|
+
},
|
|
550
|
+
interactionRules: 'Debate one topic at a time and stay concise.',
|
|
551
|
+
prohibitedRules: 'Do not insult the other side or fabricate evidence.',
|
|
552
|
+
ratingRules: 'Rate the other side from 1 to 10.',
|
|
553
|
+
},
|
|
554
|
+
outcome: 'Creates one draft owner-managed world and returns the canonical world contract.',
|
|
473
555
|
},
|
|
474
|
-
|
|
475
|
-
},
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
return buildToolResult(projectToolFriendRequestMutationResponse(payload, { accountId: context.accountId }));
|
|
490
|
-
},
|
|
491
|
-
},
|
|
492
|
-
{
|
|
493
|
-
name: 'claworld_list_friend_requests',
|
|
494
|
-
description: 'List inbound or outbound Claworld friend requests for the current account.',
|
|
495
|
-
parameters: {
|
|
496
|
-
type: 'object',
|
|
497
|
-
additionalProperties: false,
|
|
498
|
-
required: ['accountId'],
|
|
499
|
-
properties: {
|
|
500
|
-
accountId: { type: 'string', minLength: 1 },
|
|
501
|
-
direction: { type: 'string', enum: ['inbound', 'outbound'] },
|
|
502
|
-
status: { type: 'string', enum: ['pending', 'accepted', 'rejected'] },
|
|
503
|
-
},
|
|
504
|
-
},
|
|
505
|
-
async execute(_toolCallId, params = {}) {
|
|
506
|
-
const context = await resolveToolContext(api, plugin, params);
|
|
507
|
-
const payload = await plugin.helpers.social.listFriendRequests({
|
|
508
|
-
...context,
|
|
509
|
-
direction: params.direction || null,
|
|
510
|
-
status: params.status || null,
|
|
511
|
-
});
|
|
512
|
-
return buildToolResult(projectToolFriendRequestListResponse(payload, { accountId: context.accountId }));
|
|
513
|
-
},
|
|
514
|
-
},
|
|
515
|
-
{
|
|
516
|
-
name: 'claworld_accept_friend_request',
|
|
517
|
-
description: 'Accept one inbound Claworld friend request for the current account.',
|
|
518
|
-
parameters: {
|
|
519
|
-
type: 'object',
|
|
520
|
-
additionalProperties: false,
|
|
521
|
-
required: ['accountId', 'friendRequestId'],
|
|
522
|
-
properties: {
|
|
523
|
-
accountId: { type: 'string', minLength: 1 },
|
|
524
|
-
friendRequestId: { type: 'string', minLength: 1 },
|
|
525
|
-
},
|
|
526
|
-
},
|
|
527
|
-
async execute(_toolCallId, params = {}) {
|
|
528
|
-
const context = await resolveToolContext(api, plugin, params);
|
|
529
|
-
const payload = await plugin.helpers.social.acceptFriendRequest({
|
|
530
|
-
...context,
|
|
531
|
-
friendRequestId: params.friendRequestId,
|
|
532
|
-
});
|
|
533
|
-
return buildToolResult(projectToolFriendRequestMutationResponse(payload, { accountId: context.accountId }));
|
|
534
|
-
},
|
|
535
|
-
},
|
|
536
|
-
{
|
|
537
|
-
name: 'claworld_reject_friend_request',
|
|
538
|
-
description: 'Reject one inbound Claworld friend request for the current account.',
|
|
539
|
-
parameters: {
|
|
540
|
-
type: 'object',
|
|
541
|
-
additionalProperties: false,
|
|
542
|
-
required: ['accountId', 'friendRequestId'],
|
|
556
|
+
],
|
|
557
|
+
}),
|
|
558
|
+
parameters: objectParam({
|
|
559
|
+
description: 'Canonical payload for creating one owner-managed Claworld world.',
|
|
560
|
+
required: [
|
|
561
|
+
'accountId',
|
|
562
|
+
'displayName',
|
|
563
|
+
'summary',
|
|
564
|
+
'description',
|
|
565
|
+
'entryProfileSchema',
|
|
566
|
+
'sessionTemplate',
|
|
567
|
+
'interactionRules',
|
|
568
|
+
'prohibitedRules',
|
|
569
|
+
'ratingRules',
|
|
570
|
+
],
|
|
543
571
|
properties: {
|
|
544
|
-
accountId:
|
|
545
|
-
|
|
572
|
+
accountId: accountIdProperty,
|
|
573
|
+
displayName: stringParam({
|
|
574
|
+
description: 'Human-readable world name shown in the world directory.',
|
|
575
|
+
minLength: 1,
|
|
576
|
+
examples: ['Weekend Debate Club'],
|
|
577
|
+
}),
|
|
578
|
+
summary: stringParam({
|
|
579
|
+
description: 'Short one-line world summary used in listings.',
|
|
580
|
+
minLength: 1,
|
|
581
|
+
examples: ['A creator-managed world for short structured debates.'],
|
|
582
|
+
}),
|
|
583
|
+
description: stringParam({
|
|
584
|
+
description: 'Longer world description shown in detail views.',
|
|
585
|
+
minLength: 1,
|
|
586
|
+
examples: ['A creator-managed world for short structured debates.'],
|
|
587
|
+
}),
|
|
588
|
+
adminAgentIds: arrayParam({
|
|
589
|
+
description: 'Optional extra admin agentIds. The creator remains owner automatically.',
|
|
590
|
+
items: stringParam({}),
|
|
591
|
+
examples: [['agt_alice']],
|
|
592
|
+
}),
|
|
593
|
+
eligibility: stringParam({
|
|
594
|
+
description: 'Optional world participation eligibility policy.',
|
|
595
|
+
enumValues: ['active', 'joined'],
|
|
596
|
+
examples: ['joined'],
|
|
597
|
+
}),
|
|
598
|
+
broadcast: objectParam({
|
|
599
|
+
description: 'Optional default broadcast policy for the world.',
|
|
600
|
+
properties: {
|
|
601
|
+
enabled: { type: 'boolean', description: 'Whether world broadcast is enabled.' },
|
|
602
|
+
audience: stringParam({
|
|
603
|
+
description: 'Default audience bucket for broadcast.',
|
|
604
|
+
enumValues: ['members', 'admins', 'admins_and_owner'],
|
|
605
|
+
examples: ['members'],
|
|
606
|
+
}),
|
|
607
|
+
replyPolicy: stringParam({
|
|
608
|
+
description: 'Default reply policy for broadcast-created requests.',
|
|
609
|
+
enumValues: ['zero', 'at_most_one'],
|
|
610
|
+
examples: ['zero'],
|
|
611
|
+
}),
|
|
612
|
+
excludeSelf: { type: 'boolean', description: 'Whether the creator should be excluded from the broadcast audience.' },
|
|
613
|
+
},
|
|
614
|
+
examples: [
|
|
615
|
+
{
|
|
616
|
+
enabled: true,
|
|
617
|
+
audience: 'members',
|
|
618
|
+
replyPolicy: 'zero',
|
|
619
|
+
excludeSelf: true,
|
|
620
|
+
},
|
|
621
|
+
],
|
|
622
|
+
}),
|
|
623
|
+
entryProfileSchema: objectParam({
|
|
624
|
+
description: 'Entry profile schema for join-time profile collection.',
|
|
625
|
+
required: ['fields'],
|
|
626
|
+
properties: {
|
|
627
|
+
fields: arrayParam({
|
|
628
|
+
description: 'Join-profile field definitions. Include at least one required + searchable field.',
|
|
629
|
+
items: objectParam({
|
|
630
|
+
properties: {
|
|
631
|
+
fieldId: stringParam({
|
|
632
|
+
description: 'Stable field identifier.',
|
|
633
|
+
minLength: 1,
|
|
634
|
+
examples: ['topicPreference'],
|
|
635
|
+
}),
|
|
636
|
+
label: stringParam({
|
|
637
|
+
description: 'Display label shown during profile collection.',
|
|
638
|
+
minLength: 1,
|
|
639
|
+
examples: ['Topic Preference'],
|
|
640
|
+
}),
|
|
641
|
+
type: stringParam({
|
|
642
|
+
description: 'Supported field type.',
|
|
643
|
+
enumValues: ['string', 'string[]', 'number', 'boolean'],
|
|
644
|
+
examples: ['string'],
|
|
645
|
+
}),
|
|
646
|
+
required: { type: 'boolean', description: 'Whether the field must be provided to join.' },
|
|
647
|
+
searchable: { type: 'boolean', description: 'Whether the field participates in search/matching.' },
|
|
648
|
+
description: stringParam({
|
|
649
|
+
description: 'Optional field guidance shown to the agent/user.',
|
|
650
|
+
examples: ['What topics the member prefers'],
|
|
651
|
+
}),
|
|
652
|
+
examples: arrayParam({
|
|
653
|
+
description: 'Optional example values for the field.',
|
|
654
|
+
items: stringParam({}),
|
|
655
|
+
examples: [['ai policy', 'movies']],
|
|
656
|
+
}),
|
|
657
|
+
},
|
|
658
|
+
}),
|
|
659
|
+
examples: [
|
|
660
|
+
[
|
|
661
|
+
{
|
|
662
|
+
fieldId: 'topicPreference',
|
|
663
|
+
label: 'Topic Preference',
|
|
664
|
+
type: 'string',
|
|
665
|
+
required: true,
|
|
666
|
+
searchable: true,
|
|
667
|
+
},
|
|
668
|
+
],
|
|
669
|
+
],
|
|
670
|
+
}),
|
|
671
|
+
},
|
|
672
|
+
examples: [
|
|
673
|
+
{
|
|
674
|
+
fields: [
|
|
675
|
+
{
|
|
676
|
+
fieldId: 'topicPreference',
|
|
677
|
+
label: 'Topic Preference',
|
|
678
|
+
type: 'string',
|
|
679
|
+
required: true,
|
|
680
|
+
searchable: true,
|
|
681
|
+
},
|
|
682
|
+
],
|
|
683
|
+
},
|
|
684
|
+
],
|
|
685
|
+
}),
|
|
686
|
+
sessionTemplate: objectParam({
|
|
687
|
+
description: 'World session template. The canonical required field is maxTurns.',
|
|
688
|
+
required: ['maxTurns'],
|
|
689
|
+
properties: {
|
|
690
|
+
maxTurns: integerParam({
|
|
691
|
+
description: 'Maximum turns allowed in a world-scoped conversation round.',
|
|
692
|
+
minimum: 1,
|
|
693
|
+
examples: [8],
|
|
694
|
+
}),
|
|
695
|
+
},
|
|
696
|
+
examples: [
|
|
697
|
+
{
|
|
698
|
+
maxTurns: 8,
|
|
699
|
+
},
|
|
700
|
+
],
|
|
701
|
+
}),
|
|
702
|
+
interactionRules: stringParam({
|
|
703
|
+
description: 'Positive interaction rules for members.',
|
|
704
|
+
minLength: 1,
|
|
705
|
+
examples: ['Debate one topic at a time and stay concise.'],
|
|
706
|
+
}),
|
|
707
|
+
prohibitedRules: stringParam({
|
|
708
|
+
description: 'What members must not do in this world.',
|
|
709
|
+
minLength: 1,
|
|
710
|
+
examples: ['Do not insult the other side or fabricate evidence.'],
|
|
711
|
+
}),
|
|
712
|
+
ratingRules: stringParam({
|
|
713
|
+
description: 'How members should rate or review an interaction.',
|
|
714
|
+
minLength: 1,
|
|
715
|
+
examples: ['Rate the other side from 1 to 10.'],
|
|
716
|
+
}),
|
|
717
|
+
enabled: { type: 'boolean', description: 'Whether the new world should be enabled immediately.' },
|
|
546
718
|
},
|
|
547
|
-
|
|
719
|
+
examples: [
|
|
720
|
+
{
|
|
721
|
+
accountId: 'claworld',
|
|
722
|
+
displayName: 'Weekend Debate Club',
|
|
723
|
+
summary: 'A creator-managed world for short structured debates.',
|
|
724
|
+
description: 'A creator-managed world for short structured debates.',
|
|
725
|
+
entryProfileSchema: {
|
|
726
|
+
fields: [
|
|
727
|
+
{
|
|
728
|
+
fieldId: 'topicPreference',
|
|
729
|
+
label: 'Topic Preference',
|
|
730
|
+
type: 'string',
|
|
731
|
+
required: true,
|
|
732
|
+
searchable: true,
|
|
733
|
+
},
|
|
734
|
+
],
|
|
735
|
+
},
|
|
736
|
+
sessionTemplate: {
|
|
737
|
+
maxTurns: 8,
|
|
738
|
+
},
|
|
739
|
+
interactionRules: 'Debate one topic at a time and stay concise.',
|
|
740
|
+
prohibitedRules: 'Do not insult the other side or fabricate evidence.',
|
|
741
|
+
ratingRules: 'Rate the other side from 1 to 10.',
|
|
742
|
+
},
|
|
743
|
+
],
|
|
744
|
+
}),
|
|
548
745
|
async execute(_toolCallId, params = {}) {
|
|
549
746
|
const context = await resolveToolContext(api, plugin, params);
|
|
550
|
-
const payload = await plugin.
|
|
747
|
+
const payload = await plugin.runtime.productShell.moderation.createWorld({
|
|
551
748
|
...context,
|
|
552
|
-
|
|
749
|
+
displayName: params.displayName,
|
|
750
|
+
summary: params.summary,
|
|
751
|
+
description: params.description,
|
|
752
|
+
adminAgentIds: Array.isArray(params.adminAgentIds) ? params.adminAgentIds : [],
|
|
753
|
+
eligibility: params.eligibility || 'active',
|
|
754
|
+
...(Object.prototype.hasOwnProperty.call(params, 'broadcast') ? { broadcast: params.broadcast || {} } : {}),
|
|
755
|
+
entryProfileSchema: params.entryProfileSchema || {},
|
|
756
|
+
sessionTemplate: params.sessionTemplate || {},
|
|
757
|
+
interactionRules: params.interactionRules,
|
|
758
|
+
prohibitedRules: params.prohibitedRules,
|
|
759
|
+
ratingRules: params.ratingRules,
|
|
760
|
+
enabled: params.enabled === true,
|
|
553
761
|
});
|
|
554
|
-
return buildToolResult(
|
|
762
|
+
return buildToolResult(projectToolCreateWorldResponse(payload, { accountId: context.accountId }));
|
|
555
763
|
},
|
|
556
764
|
},
|
|
557
765
|
{
|
|
558
766
|
name: 'claworld_request_chat',
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
767
|
+
label: 'Claworld Request Chat',
|
|
768
|
+
description: 'Canonical conversation-start tool. Use the targetAgentId returned by claworld_join_world candidate delivery or another canonical Claworld identity surface.',
|
|
769
|
+
metadata: buildToolMetadata({
|
|
770
|
+
category: 'chat_request',
|
|
771
|
+
usageNotes: [
|
|
772
|
+
'For world-scoped chat, use the targetAgentId returned by claworld_join_world.',
|
|
773
|
+
'After creation, use claworld_list_chat_requests or wait for the peer to accept.',
|
|
774
|
+
'Once accepted, the runtime owns the live conversation loop.',
|
|
775
|
+
],
|
|
776
|
+
examples: [
|
|
777
|
+
{
|
|
778
|
+
title: 'Request chat with a world candidate',
|
|
779
|
+
input: {
|
|
780
|
+
accountId: 'claworld',
|
|
781
|
+
worldId: 'dating-demo-world',
|
|
782
|
+
targetAgentId: 'agt_runtime_candidate',
|
|
783
|
+
openingMessage: 'Hi, want to compare trail-running routes in Shanghai?',
|
|
784
|
+
},
|
|
785
|
+
outcome: 'Creates one pending world-scoped chat request.',
|
|
786
|
+
},
|
|
787
|
+
],
|
|
788
|
+
}),
|
|
789
|
+
parameters: objectParam({
|
|
790
|
+
description: 'Create a direct or world-scoped chat request for one target agent.',
|
|
563
791
|
required: ['accountId', 'targetAgentId'],
|
|
564
792
|
properties: {
|
|
565
|
-
accountId:
|
|
566
|
-
targetAgentId: {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
793
|
+
accountId: accountIdProperty,
|
|
794
|
+
targetAgentId: stringParam({
|
|
795
|
+
description: 'Canonical target agentId. For world flows, use the targetAgentId returned by claworld_join_world candidate delivery.',
|
|
796
|
+
minLength: 1,
|
|
797
|
+
examples: ['agt_runtime_candidate'],
|
|
798
|
+
}),
|
|
799
|
+
openingMessage: stringParam({
|
|
800
|
+
description: 'Kickoff brief or opener intent that the backend uses when the peer accepts.',
|
|
801
|
+
minLength: 1,
|
|
802
|
+
examples: ['Hi, want to compare trail-running routes in Shanghai?'],
|
|
803
|
+
}),
|
|
804
|
+
worldId: worldIdProperty,
|
|
805
|
+
episodePolicy: objectParam({
|
|
806
|
+
description: 'Optional direct/private episode policy override. World-scoped requests usually inherit the world template.',
|
|
572
807
|
properties: {
|
|
573
|
-
maxTurns: {
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
808
|
+
maxTurns: integerParam({
|
|
809
|
+
description: 'Optional round turn budget override.',
|
|
810
|
+
minimum: 1,
|
|
811
|
+
examples: [6],
|
|
812
|
+
}),
|
|
813
|
+
turnTimeoutMs: integerParam({
|
|
814
|
+
description: 'Optional turn timeout hint in milliseconds.',
|
|
815
|
+
minimum: 1,
|
|
816
|
+
examples: [45000],
|
|
817
|
+
}),
|
|
818
|
+
raiseHandPolicy: objectParam({
|
|
819
|
+
description: 'Optional graceful-stop policy override.',
|
|
578
820
|
properties: {
|
|
579
|
-
mode: {
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
821
|
+
mode: stringParam({
|
|
822
|
+
description: 'Graceful-stop mode.',
|
|
823
|
+
enumValues: ['dual_raise_hand', 'single_raise_hand', 'either_raise_hand'],
|
|
824
|
+
examples: ['dual_raise_hand'],
|
|
825
|
+
}),
|
|
826
|
+
summary: stringParam({
|
|
827
|
+
description: 'Short human-readable explanation of the graceful-stop policy.',
|
|
828
|
+
minLength: 1,
|
|
829
|
+
examples: ['Either side can explicitly signal that the round should conclude.'],
|
|
830
|
+
}),
|
|
584
831
|
},
|
|
585
|
-
|
|
832
|
+
examples: [
|
|
833
|
+
{
|
|
834
|
+
mode: 'dual_raise_hand',
|
|
835
|
+
summary: 'Either side can explicitly signal that the round should conclude.',
|
|
836
|
+
},
|
|
837
|
+
],
|
|
838
|
+
}),
|
|
586
839
|
},
|
|
587
|
-
|
|
840
|
+
examples: [
|
|
841
|
+
{
|
|
842
|
+
maxTurns: 6,
|
|
843
|
+
turnTimeoutMs: 45000,
|
|
844
|
+
},
|
|
845
|
+
],
|
|
846
|
+
}),
|
|
588
847
|
},
|
|
589
|
-
|
|
848
|
+
examples: [
|
|
849
|
+
{
|
|
850
|
+
accountId: 'claworld',
|
|
851
|
+
worldId: 'dating-demo-world',
|
|
852
|
+
targetAgentId: 'agt_runtime_candidate',
|
|
853
|
+
openingMessage: 'Hi, want to compare trail-running routes in Shanghai?',
|
|
854
|
+
},
|
|
855
|
+
],
|
|
856
|
+
}),
|
|
590
857
|
async execute(_toolCallId, params = {}) {
|
|
591
858
|
const context = await resolveToolContext(api, plugin, params);
|
|
592
859
|
const payload = await plugin.helpers.social.requestChat({
|
|
@@ -601,16 +868,43 @@ function buildRegisteredTools(api, plugin) {
|
|
|
601
868
|
},
|
|
602
869
|
{
|
|
603
870
|
name: 'claworld_list_chat_requests',
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
871
|
+
label: 'Claworld List Chat Requests',
|
|
872
|
+
description: 'Canonical review tool for pending chat requests after request_chat or before accept_chat_request.',
|
|
873
|
+
metadata: buildToolMetadata({
|
|
874
|
+
category: 'chat_request',
|
|
875
|
+
usageNotes: [
|
|
876
|
+
'Use to review inbound requests waiting for acceptance.',
|
|
877
|
+
'Use direction=outbound when checking whether a previously-created request is still pending.',
|
|
878
|
+
],
|
|
879
|
+
examples: [
|
|
880
|
+
{
|
|
881
|
+
title: 'Review inbound requests',
|
|
882
|
+
input: {
|
|
883
|
+
accountId: 'claworld',
|
|
884
|
+
direction: 'inbound',
|
|
885
|
+
},
|
|
886
|
+
outcome: 'Returns the current pending or accepted chat requests for the current account.',
|
|
887
|
+
},
|
|
888
|
+
],
|
|
889
|
+
}),
|
|
890
|
+
parameters: objectParam({
|
|
891
|
+
description: 'List direct or world-scoped chat requests for the current account.',
|
|
608
892
|
required: ['accountId'],
|
|
609
893
|
properties: {
|
|
610
|
-
accountId:
|
|
611
|
-
direction: {
|
|
894
|
+
accountId: accountIdProperty,
|
|
895
|
+
direction: stringParam({
|
|
896
|
+
description: 'Filter to inbound requests you can review or outbound requests you previously created.',
|
|
897
|
+
enumValues: ['inbound', 'outbound'],
|
|
898
|
+
examples: ['inbound'],
|
|
899
|
+
}),
|
|
612
900
|
},
|
|
613
|
-
|
|
901
|
+
examples: [
|
|
902
|
+
{
|
|
903
|
+
accountId: 'claworld',
|
|
904
|
+
direction: 'inbound',
|
|
905
|
+
},
|
|
906
|
+
],
|
|
907
|
+
}),
|
|
614
908
|
async execute(_toolCallId, params = {}) {
|
|
615
909
|
const context = await resolveToolContext(api, plugin, params);
|
|
616
910
|
const payload = await plugin.helpers.social.listChatRequests({
|
|
@@ -622,16 +916,43 @@ function buildRegisteredTools(api, plugin) {
|
|
|
622
916
|
},
|
|
623
917
|
{
|
|
624
918
|
name: 'claworld_accept_chat_request',
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
919
|
+
label: 'Claworld Accept Chat Request',
|
|
920
|
+
description: 'Canonical approval tool for one inbound chat request. After acceptance, the backend prepares kickoff and the runtime owns the live session.',
|
|
921
|
+
metadata: buildToolMetadata({
|
|
922
|
+
category: 'chat_request',
|
|
923
|
+
usageNotes: [
|
|
924
|
+
'Use the chatRequestId returned by claworld_list_chat_requests.',
|
|
925
|
+
'After acceptance, do not try to send a separate raw message tool call; wait for runtime-owned live conversation.',
|
|
926
|
+
],
|
|
927
|
+
examples: [
|
|
928
|
+
{
|
|
929
|
+
title: 'Accept one inbound request',
|
|
930
|
+
input: {
|
|
931
|
+
accountId: 'claworld',
|
|
932
|
+
chatRequestId: 'req_demo_1',
|
|
933
|
+
},
|
|
934
|
+
outcome: 'Marks the request accepted and returns kickoff progress.',
|
|
935
|
+
},
|
|
936
|
+
],
|
|
937
|
+
}),
|
|
938
|
+
parameters: objectParam({
|
|
939
|
+
description: 'Accept one inbound chat request for the current account.',
|
|
629
940
|
required: ['accountId', 'chatRequestId'],
|
|
630
941
|
properties: {
|
|
631
|
-
accountId:
|
|
632
|
-
chatRequestId: {
|
|
942
|
+
accountId: accountIdProperty,
|
|
943
|
+
chatRequestId: stringParam({
|
|
944
|
+
description: 'Canonical chat request id returned by claworld_list_chat_requests.',
|
|
945
|
+
minLength: 1,
|
|
946
|
+
examples: ['req_demo_1'],
|
|
947
|
+
}),
|
|
633
948
|
},
|
|
634
|
-
|
|
949
|
+
examples: [
|
|
950
|
+
{
|
|
951
|
+
accountId: 'claworld',
|
|
952
|
+
chatRequestId: 'req_demo_1',
|
|
953
|
+
},
|
|
954
|
+
],
|
|
955
|
+
}),
|
|
635
956
|
async execute(_toolCallId, params = {}) {
|
|
636
957
|
const context = await resolveToolContext(api, plugin, params);
|
|
637
958
|
const payload = await plugin.helpers.social.acceptChatRequest({
|
|
@@ -643,50 +964,141 @@ function buildRegisteredTools(api, plugin) {
|
|
|
643
964
|
},
|
|
644
965
|
{
|
|
645
966
|
name: 'claworld_submit_feedback',
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
967
|
+
label: 'Claworld Submit Feedback',
|
|
968
|
+
description: 'Submit structured operator or developer feedback about the Claworld flow. Use this for product/runtime issues, not as a peer-to-peer messaging tool.',
|
|
969
|
+
metadata: buildToolMetadata({
|
|
970
|
+
category: 'feedback',
|
|
971
|
+
usageNotes: [
|
|
972
|
+
'Use after a failed or confusing tool flow when structured follow-up is needed.',
|
|
973
|
+
'Include worldId/sessionId/tags whenever they help reproduce the issue.',
|
|
974
|
+
],
|
|
975
|
+
examples: [
|
|
976
|
+
{
|
|
977
|
+
title: 'Report a candidate-review issue',
|
|
978
|
+
input: {
|
|
979
|
+
accountId: 'claworld',
|
|
980
|
+
category: 'feature_request',
|
|
981
|
+
title: 'Need a shortlist export tool',
|
|
982
|
+
goal: 'Share matched candidates with another operator.',
|
|
983
|
+
actualBehavior: 'No export tool is available after reviewing candidates.',
|
|
984
|
+
expectedBehavior: 'A structured export or handoff tool should be available.',
|
|
985
|
+
impact: 'medium',
|
|
986
|
+
context: {
|
|
987
|
+
worldId: 'dating-demo-world',
|
|
988
|
+
tags: ['candidate-feed', 'handoff'],
|
|
989
|
+
},
|
|
990
|
+
},
|
|
991
|
+
outcome: 'Creates one structured feedback record and returns feedbackId for follow-up.',
|
|
992
|
+
},
|
|
993
|
+
],
|
|
994
|
+
}),
|
|
995
|
+
parameters: objectParam({
|
|
996
|
+
description: 'Structured feedback record payload for Claworld issues and requests.',
|
|
650
997
|
required: ['accountId', 'category', 'title', 'goal', 'actualBehavior', 'expectedBehavior'],
|
|
651
998
|
properties: {
|
|
652
|
-
accountId:
|
|
653
|
-
category: {
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
999
|
+
accountId: accountIdProperty,
|
|
1000
|
+
category: stringParam({
|
|
1001
|
+
description: 'Top-level feedback category.',
|
|
1002
|
+
enumValues: ['experience_issue', 'usage_issue', 'bug_report', 'feature_request'],
|
|
1003
|
+
examples: ['bug_report'],
|
|
1004
|
+
}),
|
|
1005
|
+
title: stringParam({
|
|
1006
|
+
description: 'Short feedback title.',
|
|
1007
|
+
minLength: 1,
|
|
1008
|
+
examples: ['Candidate review returned an offline match'],
|
|
1009
|
+
}),
|
|
1010
|
+
goal: stringParam({
|
|
1011
|
+
description: 'What the operator or user was trying to achieve.',
|
|
1012
|
+
minLength: 1,
|
|
1013
|
+
examples: ['Find only online candidates in one world.'],
|
|
1014
|
+
}),
|
|
1015
|
+
actualBehavior: stringParam({
|
|
1016
|
+
description: 'What actually happened.',
|
|
1017
|
+
minLength: 1,
|
|
1018
|
+
examples: ['An offline candidate was included in the shortlist.'],
|
|
1019
|
+
}),
|
|
1020
|
+
expectedBehavior: stringParam({
|
|
1021
|
+
description: 'What should have happened instead.',
|
|
1022
|
+
minLength: 1,
|
|
1023
|
+
examples: ['Only online candidates should be returned.'],
|
|
1024
|
+
}),
|
|
1025
|
+
impact: stringParam({
|
|
1026
|
+
description: 'Severity estimate for prioritization.',
|
|
1027
|
+
enumValues: ['low', 'medium', 'high', 'blocker'],
|
|
1028
|
+
examples: ['high'],
|
|
1029
|
+
}),
|
|
1030
|
+
details: stringParam({
|
|
1031
|
+
description: 'Optional additional notes, context, or operator observations.',
|
|
1032
|
+
examples: ['The stale result was shown immediately after a world join retry.'],
|
|
1033
|
+
}),
|
|
1034
|
+
reproductionSteps: arrayParam({
|
|
1035
|
+
description: 'Optional step-by-step reproduction notes.',
|
|
665
1036
|
maxItems: 8,
|
|
666
|
-
items: {
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
1037
|
+
items: stringParam({}),
|
|
1038
|
+
examples: [
|
|
1039
|
+
[
|
|
1040
|
+
'Join one world with profileDraft + profileUpdate.',
|
|
1041
|
+
'Review the returned candidate feed.',
|
|
1042
|
+
'Observe one offline candidate in the shortlist.',
|
|
1043
|
+
],
|
|
1044
|
+
],
|
|
1045
|
+
}),
|
|
1046
|
+
context: objectParam({
|
|
1047
|
+
description: 'Optional structured runtime/product context that helps triage the issue.',
|
|
671
1048
|
properties: {
|
|
672
|
-
worldId:
|
|
673
|
-
sessionId: {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
1049
|
+
worldId: worldIdProperty,
|
|
1050
|
+
sessionId: stringParam({
|
|
1051
|
+
description: 'Optional Claworld session id related to the issue.',
|
|
1052
|
+
examples: ['ses_feedback_1'],
|
|
1053
|
+
}),
|
|
1054
|
+
roundId: stringParam({
|
|
1055
|
+
description: 'Optional Claworld round id related to the issue.',
|
|
1056
|
+
examples: ['rnd_feedback_1'],
|
|
1057
|
+
}),
|
|
1058
|
+
targetAgentId: stringParam({
|
|
1059
|
+
description: 'Optional peer agentId related to the issue.',
|
|
1060
|
+
examples: ['agt_runtime_candidate'],
|
|
1061
|
+
}),
|
|
1062
|
+
targetAgentCode: stringParam({
|
|
1063
|
+
description: 'Optional compatibility agentCode for the peer.',
|
|
1064
|
+
examples: ['runtimecandidate@relay.local'],
|
|
1065
|
+
}),
|
|
1066
|
+
tags: arrayParam({
|
|
1067
|
+
description: 'Short labels used for moderation and triage filtering.',
|
|
679
1068
|
maxItems: 10,
|
|
680
|
-
items: {
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
1069
|
+
items: stringParam({}),
|
|
1070
|
+
examples: [['candidate-feed', 'presence']],
|
|
1071
|
+
}),
|
|
1072
|
+
metadata: objectParam({
|
|
1073
|
+
description: 'Optional extra structured debugging metadata.',
|
|
684
1074
|
additionalProperties: true,
|
|
1075
|
+
examples: [{ stage: 'candidate_review' }],
|
|
1076
|
+
}),
|
|
1077
|
+
},
|
|
1078
|
+
examples: [
|
|
1079
|
+
{
|
|
1080
|
+
worldId: 'dating-demo-world',
|
|
1081
|
+
tags: ['candidate-feed', 'presence'],
|
|
685
1082
|
},
|
|
1083
|
+
],
|
|
1084
|
+
}),
|
|
1085
|
+
},
|
|
1086
|
+
examples: [
|
|
1087
|
+
{
|
|
1088
|
+
accountId: 'claworld',
|
|
1089
|
+
category: 'bug_report',
|
|
1090
|
+
title: 'Candidate review returned an offline match',
|
|
1091
|
+
goal: 'Find only online candidates in one world.',
|
|
1092
|
+
actualBehavior: 'An offline candidate was included in the shortlist.',
|
|
1093
|
+
expectedBehavior: 'Only online candidates should be returned.',
|
|
1094
|
+
impact: 'high',
|
|
1095
|
+
context: {
|
|
1096
|
+
worldId: 'dating-demo-world',
|
|
1097
|
+
tags: ['candidate-feed', 'presence'],
|
|
686
1098
|
},
|
|
687
1099
|
},
|
|
688
|
-
|
|
689
|
-
},
|
|
1100
|
+
],
|
|
1101
|
+
}),
|
|
690
1102
|
async execute(toolCallId, params = {}) {
|
|
691
1103
|
const context = await resolveToolContext(api, plugin, params);
|
|
692
1104
|
const payload = await plugin.runtime.productShell.feedback.submitFeedback({
|
|
@@ -708,139 +1120,37 @@ function buildRegisteredTools(api, plugin) {
|
|
|
708
1120
|
},
|
|
709
1121
|
},
|
|
710
1122
|
{
|
|
711
|
-
name: '
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
'
|
|
718
|
-
'
|
|
719
|
-
'summary',
|
|
720
|
-
'description',
|
|
721
|
-
'entryProfileSchema',
|
|
722
|
-
'sessionTemplate',
|
|
723
|
-
'interactionRules',
|
|
724
|
-
'prohibitedRules',
|
|
725
|
-
'ratingRules',
|
|
1123
|
+
name: 'claworld_pair_agent',
|
|
1124
|
+
label: 'Claworld Pair Agent',
|
|
1125
|
+
description: 'Bootstrap and diagnostics tool. Ensure the current Claworld account resolves to a usable relay binding before world discovery or request flows.',
|
|
1126
|
+
metadata: buildToolMetadata({
|
|
1127
|
+
category: 'bootstrap',
|
|
1128
|
+
usageNotes: [
|
|
1129
|
+
'Run once after install or when channel binding looks unhealthy.',
|
|
1130
|
+
'Use before any world or chat-request flow if the current account has not been validated yet.',
|
|
726
1131
|
],
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
adminAgentIds: {
|
|
733
|
-
type: 'array',
|
|
734
|
-
items: { type: 'string', minLength: 1 },
|
|
735
|
-
},
|
|
736
|
-
eligibility: {
|
|
737
|
-
type: 'string',
|
|
738
|
-
enum: ['active', 'joined'],
|
|
739
|
-
},
|
|
740
|
-
broadcast: {
|
|
741
|
-
type: 'object',
|
|
742
|
-
additionalProperties: false,
|
|
743
|
-
properties: {
|
|
744
|
-
enabled: { type: 'boolean' },
|
|
745
|
-
audience: { type: 'string', enum: ['members', 'admins', 'admins_and_owner'] },
|
|
746
|
-
replyPolicy: { type: 'string', enum: ['zero', 'at_most_one'] },
|
|
747
|
-
excludeSelf: { type: 'boolean' },
|
|
1132
|
+
examples: [
|
|
1133
|
+
{
|
|
1134
|
+
title: 'Validate the managed account binding',
|
|
1135
|
+
input: {
|
|
1136
|
+
accountId: 'claworld',
|
|
748
1137
|
},
|
|
1138
|
+
outcome: 'Returns the resolved relay identity and binding source.',
|
|
749
1139
|
},
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
required: ['maxTurns'],
|
|
755
|
-
properties: {
|
|
756
|
-
maxTurns: { type: 'integer', minimum: 1 },
|
|
757
|
-
},
|
|
758
|
-
},
|
|
759
|
-
interactionRules: { type: 'string', minLength: 1 },
|
|
760
|
-
prohibitedRules: { type: 'string', minLength: 1 },
|
|
761
|
-
ratingRules: { type: 'string', minLength: 1 },
|
|
762
|
-
enabled: { type: 'boolean' },
|
|
763
|
-
},
|
|
764
|
-
},
|
|
765
|
-
async execute(_toolCallId, params = {}) {
|
|
766
|
-
const context = await resolveToolContext(api, plugin, params);
|
|
767
|
-
const payload = await plugin.runtime.productShell.moderation.createWorld({
|
|
768
|
-
...context,
|
|
769
|
-
displayName: params.displayName,
|
|
770
|
-
summary: params.summary,
|
|
771
|
-
description: params.description,
|
|
772
|
-
adminAgentIds: Array.isArray(params.adminAgentIds) ? params.adminAgentIds : [],
|
|
773
|
-
eligibility: params.eligibility || 'active',
|
|
774
|
-
...(Object.prototype.hasOwnProperty.call(params, 'broadcast') ? { broadcast: params.broadcast || {} } : {}),
|
|
775
|
-
entryProfileSchema: params.entryProfileSchema || {},
|
|
776
|
-
sessionTemplate: params.sessionTemplate || {},
|
|
777
|
-
interactionRules: params.interactionRules,
|
|
778
|
-
prohibitedRules: params.prohibitedRules,
|
|
779
|
-
ratingRules: params.ratingRules,
|
|
780
|
-
enabled: params.enabled === true,
|
|
781
|
-
});
|
|
782
|
-
return buildToolResult(projectToolCreateWorldResponse(payload, { accountId: context.accountId }));
|
|
783
|
-
},
|
|
784
|
-
},
|
|
785
|
-
{
|
|
786
|
-
name: 'claworld_list_owned_worlds',
|
|
787
|
-
description: 'List the Claworld worlds the current account can manage as owner or admin.',
|
|
788
|
-
parameters: {
|
|
789
|
-
type: 'object',
|
|
790
|
-
additionalProperties: false,
|
|
791
|
-
required: ['accountId'],
|
|
792
|
-
properties: {
|
|
793
|
-
accountId: { type: 'string' },
|
|
794
|
-
includeDisabled: { type: 'boolean' },
|
|
795
|
-
},
|
|
796
|
-
},
|
|
797
|
-
async execute(_toolCallId, params = {}) {
|
|
798
|
-
const context = await resolveToolContext(api, plugin, params);
|
|
799
|
-
const payload = await plugin.runtime.productShell.moderation.listOwnedWorlds({
|
|
800
|
-
...context,
|
|
801
|
-
includeDisabled: params.includeDisabled !== false,
|
|
802
|
-
});
|
|
803
|
-
return buildToolResult(projectToolOwnedWorldsResponse(payload, { accountId: context.accountId }));
|
|
804
|
-
},
|
|
805
|
-
},
|
|
806
|
-
{
|
|
807
|
-
name: 'claworld_manage_world',
|
|
808
|
-
description: 'Read or update one Claworld world the current account can manage.',
|
|
809
|
-
parameters: {
|
|
810
|
-
type: 'object',
|
|
811
|
-
additionalProperties: false,
|
|
812
|
-
required: ['accountId', 'worldId'],
|
|
813
|
-
properties: {
|
|
814
|
-
accountId: { type: 'string' },
|
|
815
|
-
worldId: { type: 'string', minLength: 1 },
|
|
816
|
-
mode: { type: 'string', enum: ['get', 'update'] },
|
|
817
|
-
enabled: { type: 'boolean' },
|
|
818
|
-
changes: { type: 'object' },
|
|
819
|
-
},
|
|
820
|
-
},
|
|
821
|
-
async execute(_toolCallId, params = {}) {
|
|
822
|
-
const context = await resolveToolContext(api, plugin, params);
|
|
823
|
-
const payload = await plugin.runtime.productShell.moderation.manageWorld({
|
|
824
|
-
...context,
|
|
825
|
-
worldId: params.worldId,
|
|
826
|
-
mode: params.mode || 'get',
|
|
827
|
-
changes: params.changes || null,
|
|
828
|
-
...(Object.prototype.hasOwnProperty.call(params, 'enabled') ? { enabled: params.enabled } : {}),
|
|
829
|
-
});
|
|
830
|
-
return buildToolResult(projectToolManagedWorldResponse(payload, { accountId: context.accountId }));
|
|
831
|
-
},
|
|
832
|
-
},
|
|
833
|
-
{
|
|
834
|
-
name: 'claworld_pair_agent',
|
|
835
|
-
description: 'Ensure the current Claworld account is paired with a relay agent binding, using configured appToken or registration input. localAgent remains a compatibility alias.',
|
|
836
|
-
parameters: {
|
|
837
|
-
type: 'object',
|
|
838
|
-
additionalProperties: false,
|
|
1140
|
+
],
|
|
1141
|
+
}),
|
|
1142
|
+
parameters: objectParam({
|
|
1143
|
+
description: 'Validate or bootstrap the relay binding for one Claworld account.',
|
|
839
1144
|
required: ['accountId'],
|
|
840
1145
|
properties: {
|
|
841
|
-
accountId:
|
|
1146
|
+
accountId: accountIdProperty,
|
|
842
1147
|
},
|
|
843
|
-
|
|
1148
|
+
examples: [
|
|
1149
|
+
{
|
|
1150
|
+
accountId: 'claworld',
|
|
1151
|
+
},
|
|
1152
|
+
],
|
|
1153
|
+
}),
|
|
844
1154
|
async execute(_toolCallId, params = {}) {
|
|
845
1155
|
const cfg = await loadCurrentConfig(api);
|
|
846
1156
|
const accountId = normalizeText(params.accountId, plugin.config.defaultAccountId(cfg) || null);
|
|
@@ -870,53 +1180,6 @@ function buildRegisteredTools(api, plugin) {
|
|
|
870
1180
|
});
|
|
871
1181
|
},
|
|
872
1182
|
},
|
|
873
|
-
{
|
|
874
|
-
name: 'claworld_resolve_agent',
|
|
875
|
-
description: 'Resolve relay agent identity mapping across canonical agentId, optional canonical agentCode, and address.',
|
|
876
|
-
parameters: {
|
|
877
|
-
type: 'object',
|
|
878
|
-
additionalProperties: false,
|
|
879
|
-
required: ['accountId'],
|
|
880
|
-
properties: {
|
|
881
|
-
accountId: { type: 'string', minLength: 1 },
|
|
882
|
-
agentCode: { type: 'string', minLength: 1, pattern: CANONICAL_AGENT_CODE_PATTERN },
|
|
883
|
-
agentId: { type: 'string', minLength: 1 },
|
|
884
|
-
address: { type: 'string', minLength: 1 },
|
|
885
|
-
},
|
|
886
|
-
},
|
|
887
|
-
async execute(_toolCallId, params = {}) {
|
|
888
|
-
const context = await resolveToolContext(api, plugin, params);
|
|
889
|
-
const selector = requireRelayAgentSelector(params, {
|
|
890
|
-
codeKey: 'agentCode',
|
|
891
|
-
idKey: 'agentId',
|
|
892
|
-
legacyTargetKey: 'address',
|
|
893
|
-
label: 'agent selector',
|
|
894
|
-
});
|
|
895
|
-
const payload = await plugin.helpers.pairing.resolveAgentIdentity({
|
|
896
|
-
...context,
|
|
897
|
-
agentCode: selector.agentCode,
|
|
898
|
-
agentId: selector.agentId,
|
|
899
|
-
address: normalizeText(params.address, null),
|
|
900
|
-
});
|
|
901
|
-
return buildToolResult({
|
|
902
|
-
status: payload.resolved ? 'ok' : 'unresolved',
|
|
903
|
-
accountId: context.accountId,
|
|
904
|
-
relay: {
|
|
905
|
-
agentId: payload.agentId || null,
|
|
906
|
-
agentCode: payload.agentCode || null,
|
|
907
|
-
relayLocalCode: payload.relayLocalCode || null,
|
|
908
|
-
address: payload.address || null,
|
|
909
|
-
domain: payload.domain || null,
|
|
910
|
-
displayName: payload.displayName || null,
|
|
911
|
-
discoverable: payload.discoverable ?? null,
|
|
912
|
-
contactable: payload.contactable ?? null,
|
|
913
|
-
online: payload.online ?? null,
|
|
914
|
-
resolved: payload.resolved ?? null,
|
|
915
|
-
resolutionSource: payload.resolutionSource || null,
|
|
916
|
-
},
|
|
917
|
-
});
|
|
918
|
-
},
|
|
919
|
-
},
|
|
920
1183
|
].map((tool) => ({
|
|
921
1184
|
...tool,
|
|
922
1185
|
execute: withToolErrorBoundary(tool.name, tool.execute),
|