@xfxstudio/claworld 0.1.0
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/README.md +60 -0
- package/bin/claworld.mjs +9 -0
- package/index.js +51 -0
- package/openclaw.plugin.json +470 -0
- package/package.json +76 -0
- package/setup-entry.js +6 -0
- package/src/lib/accepted-chat-kickoff.js +192 -0
- package/src/lib/agent-address.js +46 -0
- package/src/lib/agent-profile.js +69 -0
- package/src/lib/http-auth.js +151 -0
- package/src/lib/policy.js +118 -0
- package/src/lib/runtime-errors.js +149 -0
- package/src/lib/runtime-guidance.js +458 -0
- package/src/openclaw/index.js +53 -0
- package/src/openclaw/installer/cli.js +349 -0
- package/src/openclaw/installer/constants.js +6 -0
- package/src/openclaw/installer/core.js +1548 -0
- package/src/openclaw/installer/doctor.js +690 -0
- package/src/openclaw/installer/workspace-contract.js +403 -0
- package/src/openclaw/plugin/account-identity.js +66 -0
- package/src/openclaw/plugin/claworld-channel-plugin.js +3118 -0
- package/src/openclaw/plugin/config-schema.js +464 -0
- package/src/openclaw/plugin/lifecycle.js +114 -0
- package/src/openclaw/plugin/managed-config.js +648 -0
- package/src/openclaw/plugin/onboarding.js +291 -0
- package/src/openclaw/plugin/register.js +961 -0
- package/src/openclaw/plugin/relay-client.js +783 -0
- package/src/openclaw/plugin/runtime.js +12 -0
- package/src/openclaw/protocol/relay-event-protocol.js +31 -0
- package/src/openclaw/runtime/canonical-result-builder.js +116 -0
- package/src/openclaw/runtime/demo-session-bootstrap.js +37 -0
- package/src/openclaw/runtime/feedback-helper.js +145 -0
- package/src/openclaw/runtime/inbound-session-router.js +36 -0
- package/src/openclaw/runtime/outbound-session-bridge.js +17 -0
- package/src/openclaw/runtime/product-shell-helper.js +1712 -0
- package/src/openclaw/runtime/runtime-path.js +19 -0
- package/src/openclaw/runtime/system-message-orchestrator.js +1 -0
- package/src/openclaw/runtime/tool-contracts.js +714 -0
- package/src/openclaw/runtime/tool-inventory.js +92 -0
- package/src/openclaw/runtime/world-moderation-helper.js +415 -0
- package/src/openclaw/runtime/world-session-startup.js +1 -0
- package/src/product-shell/catalog/default-world-catalog.js +296 -0
- package/src/product-shell/contracts/candidate-feed.js +330 -0
- package/src/product-shell/contracts/chat-request-approval-policy.js +98 -0
- package/src/product-shell/contracts/world-manifest.js +435 -0
- package/src/product-shell/contracts/world-orchestration.js +1024 -0
- package/src/product-shell/feedback/feedback-contract.js +13 -0
- package/src/product-shell/feedback/feedback-routes.js +98 -0
- package/src/product-shell/feedback/feedback-service.js +254 -0
- package/src/product-shell/index.js +163 -0
- package/src/product-shell/matching/matchmaking-service.js +340 -0
- package/src/product-shell/membership/membership-service.js +277 -0
- package/src/product-shell/onboarding/onboarding-routes.js +37 -0
- package/src/product-shell/onboarding/onboarding-service.js +230 -0
- package/src/product-shell/orchestration/session-orchestrator.js +38 -0
- package/src/product-shell/results/result-service.js +15 -0
- package/src/product-shell/search/search-service.js +359 -0
- package/src/product-shell/social/chat-request-approval-policy.js +332 -0
- package/src/product-shell/social/chat-request-routes.js +108 -0
- package/src/product-shell/social/chat-request-service.js +632 -0
- package/src/product-shell/social/friend-routes.js +82 -0
- package/src/product-shell/social/friend-service.js +560 -0
- package/src/product-shell/social/social-routes.js +21 -0
- package/src/product-shell/social/social-service.js +140 -0
- package/src/product-shell/worlds/world-admin-service.js +705 -0
- package/src/product-shell/worlds/world-authorization.js +135 -0
- package/src/product-shell/worlds/world-broadcast-service.js +299 -0
- package/src/product-shell/worlds/world-routes.js +410 -0
- package/src/product-shell/worlds/world-service.js +89 -0
|
@@ -0,0 +1,961 @@
|
|
|
1
|
+
import { createClaworldChannelPlugin } from './claworld-channel-plugin.js';
|
|
2
|
+
import {
|
|
3
|
+
projectToolChatRequestListResponse,
|
|
4
|
+
projectToolChatRequestMutationResponse,
|
|
5
|
+
projectToolBroadcastWorldResponse,
|
|
6
|
+
projectToolWorldList,
|
|
7
|
+
projectToolCreateWorldResponse,
|
|
8
|
+
projectToolFeedbackSubmissionResponse,
|
|
9
|
+
projectToolFriendRequestListResponse,
|
|
10
|
+
projectToolFriendRequestMutationResponse,
|
|
11
|
+
projectToolJoinWorldResponse,
|
|
12
|
+
projectToolManagedWorldResponse,
|
|
13
|
+
projectToolOwnedWorldsResponse,
|
|
14
|
+
projectToolSearchWorldResponse,
|
|
15
|
+
projectToolWorldDetail,
|
|
16
|
+
projectToolWorldProfileCollectionResponse,
|
|
17
|
+
} from '../runtime/tool-contracts.js';
|
|
18
|
+
import { CLAWORLD_TOOL_CONTRACT_VERSION } from '../runtime/tool-inventory.js';
|
|
19
|
+
import { setClaworldRuntime } from './runtime.js';
|
|
20
|
+
import {
|
|
21
|
+
buildPublicErrorPayload,
|
|
22
|
+
createRuntimeBoundaryError,
|
|
23
|
+
logRuntimeBoundary,
|
|
24
|
+
normalizeRuntimeBoundaryError,
|
|
25
|
+
} from '../../lib/runtime-errors.js';
|
|
26
|
+
|
|
27
|
+
function normalizeText(value, fallback = null) {
|
|
28
|
+
if (value == null) return fallback;
|
|
29
|
+
const normalized = String(value).trim();
|
|
30
|
+
return normalized || fallback;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function normalizeObject(value, fallback = null) {
|
|
34
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return fallback;
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function normalizePublicFieldError(fieldError = {}) {
|
|
39
|
+
const fieldId = normalizeText(fieldError.fieldId, null);
|
|
40
|
+
const message = normalizeText(fieldError.message, null);
|
|
41
|
+
const code = normalizeText(fieldError.code, null);
|
|
42
|
+
if (!fieldId && !message && !code) return null;
|
|
43
|
+
return {
|
|
44
|
+
...(fieldId ? { fieldId } : {}),
|
|
45
|
+
...(message ? { message } : {}),
|
|
46
|
+
...(code ? { code } : {}),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function buildPublicToolErrorExtras(error) {
|
|
51
|
+
const context = normalizeObject(error?.context, null);
|
|
52
|
+
if (!context) return null;
|
|
53
|
+
|
|
54
|
+
const httpStatus = Number(context.httpStatus);
|
|
55
|
+
const backendCode = normalizeText(context.backendCode, null);
|
|
56
|
+
const backendMessage = normalizeText(context.backendMessage, null);
|
|
57
|
+
const fieldErrors = Array.isArray(context.fieldErrors)
|
|
58
|
+
? context.fieldErrors.map((fieldError) => normalizePublicFieldError(fieldError)).filter(Boolean)
|
|
59
|
+
: [];
|
|
60
|
+
|
|
61
|
+
const extra = {
|
|
62
|
+
...(Number.isInteger(httpStatus) && httpStatus > 0 ? { httpStatus } : {}),
|
|
63
|
+
...(backendCode ? { backendCode } : {}),
|
|
64
|
+
...(backendMessage ? { backendMessage } : {}),
|
|
65
|
+
...(fieldErrors.length > 0 ? { fieldErrors } : {}),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return Object.keys(extra).length > 0 ? extra : null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function resolveProfileDraftParams(params = {}, { includeProfileSnapshot = false } = {}) {
|
|
72
|
+
const profile = normalizeObject(params.profile, null);
|
|
73
|
+
const profileDraft = normalizeObject(params.profileDraft, null);
|
|
74
|
+
const profileSnapshot = includeProfileSnapshot ? normalizeObject(params.profileSnapshot, null) : null;
|
|
75
|
+
const profileUpdate = normalizeObject(params.profileUpdate, null) || normalizeObject(params.profilePatch, null);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
profile: profile || profileDraft || {},
|
|
79
|
+
profileSnapshot: includeProfileSnapshot ? (profileSnapshot || profileDraft || null) : null,
|
|
80
|
+
profileUpdate,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
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
|
+
function buildClaworldStatusRoute(plugin) {
|
|
132
|
+
return {
|
|
133
|
+
method: 'GET',
|
|
134
|
+
path: '/plugins/claworld/status',
|
|
135
|
+
auth: 'gateway',
|
|
136
|
+
match: 'exact',
|
|
137
|
+
async handler(_req, res) {
|
|
138
|
+
const payload = plugin.status?.getSnapshot?.() || {
|
|
139
|
+
ok: true,
|
|
140
|
+
pluginId: plugin.id || 'claworld',
|
|
141
|
+
};
|
|
142
|
+
if (typeof res?.status === 'function' && typeof res?.json === 'function') {
|
|
143
|
+
res.status(200).json(payload);
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
if (typeof res?.setHeader === 'function') {
|
|
147
|
+
res.statusCode = 200;
|
|
148
|
+
res.setHeader('content-type', 'application/json; charset=utf-8');
|
|
149
|
+
}
|
|
150
|
+
if (typeof res?.end === 'function') {
|
|
151
|
+
res.end(JSON.stringify(payload));
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
return payload;
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function loadCurrentConfig(api) {
|
|
160
|
+
if (api?.config && typeof api.config.loadConfig === 'function') {
|
|
161
|
+
return await api.config.loadConfig();
|
|
162
|
+
}
|
|
163
|
+
if (api?.runtime?.config && typeof api.runtime.config.loadConfig === 'function') {
|
|
164
|
+
return await api.runtime.config.loadConfig();
|
|
165
|
+
}
|
|
166
|
+
if (api?.config && typeof api.config === 'object') {
|
|
167
|
+
return api.config;
|
|
168
|
+
}
|
|
169
|
+
return {};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function buildToolResult(payload) {
|
|
173
|
+
return {
|
|
174
|
+
content: [
|
|
175
|
+
{
|
|
176
|
+
type: 'text',
|
|
177
|
+
text: JSON.stringify(payload, null, 2),
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function buildToolErrorResult(toolName, error) {
|
|
184
|
+
const normalized = normalizeRuntimeBoundaryError(error, {
|
|
185
|
+
code: 'claworld_tool_execution_failed',
|
|
186
|
+
category: 'runtime',
|
|
187
|
+
publicMessage: 'tool execution failed',
|
|
188
|
+
recoverable: true,
|
|
189
|
+
});
|
|
190
|
+
return buildToolResult({
|
|
191
|
+
status: 'error',
|
|
192
|
+
tool: toolName,
|
|
193
|
+
...buildPublicErrorPayload(normalized, {
|
|
194
|
+
errorType: 'claworld_tool_failed',
|
|
195
|
+
fallbackMessage: 'tool execution failed',
|
|
196
|
+
exposeMessage: normalized.status < 500 || Boolean(normalized.publicMessage),
|
|
197
|
+
extra: buildPublicToolErrorExtras(normalized),
|
|
198
|
+
}),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function withToolErrorBoundary(toolName, execute) {
|
|
203
|
+
return async (toolCallId, params = {}) => {
|
|
204
|
+
try {
|
|
205
|
+
return await execute(toolCallId, params);
|
|
206
|
+
} catch (error) {
|
|
207
|
+
const normalized = logRuntimeBoundary(console, `[claworld:tool:${toolName}] execution failed`, error, {
|
|
208
|
+
tool: toolName,
|
|
209
|
+
}, {
|
|
210
|
+
includeStack: false,
|
|
211
|
+
fallback: {
|
|
212
|
+
code: 'claworld_tool_execution_failed',
|
|
213
|
+
category: 'runtime',
|
|
214
|
+
publicMessage: 'tool execution failed',
|
|
215
|
+
recoverable: true,
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
return buildToolErrorResult(toolName, normalized);
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async function resolveToolContext(api, plugin, params = {}) {
|
|
224
|
+
const cfg = await loadCurrentConfig(api);
|
|
225
|
+
const accountId = normalizeText(params.accountId, plugin.config.defaultAccountId(cfg) || null);
|
|
226
|
+
const runtimeConfig = plugin.config.resolveRuntimeConfig(cfg, accountId);
|
|
227
|
+
|
|
228
|
+
if (typeof plugin.helpers?.resolveToolRuntimeContext === 'function') {
|
|
229
|
+
return await plugin.helpers.resolveToolRuntimeContext({
|
|
230
|
+
cfg,
|
|
231
|
+
accountId,
|
|
232
|
+
runtimeConfig,
|
|
233
|
+
agentId: normalizeText(params.agentId, runtimeConfig.relay?.agentId || null),
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const agentId = normalizeText(params.agentId, runtimeConfig.relay?.agentId || null);
|
|
238
|
+
return {
|
|
239
|
+
cfg,
|
|
240
|
+
accountId,
|
|
241
|
+
runtimeConfig,
|
|
242
|
+
agentId,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async function resolveRelayTargetAddress(plugin, context, params = {}, {
|
|
247
|
+
codeKey,
|
|
248
|
+
idKey,
|
|
249
|
+
legacyTargetKey = null,
|
|
250
|
+
label = 'target agent',
|
|
251
|
+
} = {}) {
|
|
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
|
+
return {
|
|
276
|
+
selector,
|
|
277
|
+
payload,
|
|
278
|
+
toAddress: payload.address,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function buildRegisteredTools(api, plugin) {
|
|
283
|
+
return [
|
|
284
|
+
{
|
|
285
|
+
name: 'claworld_list_worlds',
|
|
286
|
+
description: 'List the available Claworld worlds for the current channel account.',
|
|
287
|
+
parameters: {
|
|
288
|
+
type: 'object',
|
|
289
|
+
additionalProperties: false,
|
|
290
|
+
properties: {
|
|
291
|
+
accountId: { type: 'string' },
|
|
292
|
+
limit: { type: 'integer', minimum: 1, maximum: 50 },
|
|
293
|
+
sort: { type: 'string', enum: ['hot', 'latest'] },
|
|
294
|
+
page: { type: 'integer', minimum: 1 },
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
async execute(_toolCallId, params = {}) {
|
|
298
|
+
const context = await resolveToolContext(api, plugin, params);
|
|
299
|
+
const payload = await plugin.helpers.postSetup.fetchWorldDirectory({
|
|
300
|
+
...context,
|
|
301
|
+
limit: params.limit ?? null,
|
|
302
|
+
sort: params.sort || null,
|
|
303
|
+
page: params.page ?? null,
|
|
304
|
+
});
|
|
305
|
+
return buildToolResult(projectToolWorldList(payload));
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
name: 'claworld_get_world_detail',
|
|
310
|
+
description: 'Fetch the product-facing world detail for one Claworld world.',
|
|
311
|
+
parameters: {
|
|
312
|
+
type: 'object',
|
|
313
|
+
additionalProperties: false,
|
|
314
|
+
required: ['worldId'],
|
|
315
|
+
properties: {
|
|
316
|
+
accountId: { type: 'string' },
|
|
317
|
+
worldId: { type: 'string', minLength: 1 },
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
async execute(_toolCallId, params = {}) {
|
|
321
|
+
const context = await resolveToolContext(api, plugin, params);
|
|
322
|
+
const payload = await plugin.runtime.productShell.fetchWorldDetail({
|
|
323
|
+
...context,
|
|
324
|
+
worldId: params.worldId,
|
|
325
|
+
});
|
|
326
|
+
return buildToolResult(projectToolWorldDetail(payload));
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
name: 'claworld_prepare_world_join',
|
|
331
|
+
description: 'Inspect or update the current profile draft for a Claworld world join. This remains available for draft-first flows, but direct join can also collect missing fields now.',
|
|
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
|
+
{
|
|
364
|
+
name: 'claworld_join_world',
|
|
365
|
+
description: 'Create or activate a Claworld world membership for the current relay agent, and if required fields are still missing return the next profile fields before retrying the same tool.',
|
|
366
|
+
parameters: {
|
|
367
|
+
type: 'object',
|
|
368
|
+
additionalProperties: false,
|
|
369
|
+
required: ['accountId', 'worldId'],
|
|
370
|
+
properties: {
|
|
371
|
+
accountId: { type: 'string' },
|
|
372
|
+
worldId: { type: 'string', minLength: 1 },
|
|
373
|
+
profile: { type: 'object' },
|
|
374
|
+
profileDraft: { type: 'object' },
|
|
375
|
+
profileSnapshot: { type: 'object' },
|
|
376
|
+
profileUpdate: { type: 'object' },
|
|
377
|
+
profilePatch: { type: 'object' },
|
|
378
|
+
maxFieldsPerStep: { type: 'integer', minimum: 1, maximum: 5 },
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
async execute(_toolCallId, params = {}) {
|
|
382
|
+
const context = await resolveToolContext(api, plugin, params);
|
|
383
|
+
const profileDraftParams = resolveProfileDraftParams(params, {
|
|
384
|
+
includeProfileSnapshot: true,
|
|
385
|
+
});
|
|
386
|
+
const payload = await plugin.runtime.productShell.submitWorldJoin({
|
|
387
|
+
...context,
|
|
388
|
+
worldId: params.worldId,
|
|
389
|
+
agentId: context.agentId,
|
|
390
|
+
profile: profileDraftParams.profile,
|
|
391
|
+
profileSnapshot: profileDraftParams.profileSnapshot,
|
|
392
|
+
profileUpdate: profileDraftParams.profileUpdate,
|
|
393
|
+
maxFieldsPerStep: params.maxFieldsPerStep ?? 1,
|
|
394
|
+
});
|
|
395
|
+
return buildToolResult(projectToolJoinWorldResponse(payload, {
|
|
396
|
+
accountId: context.accountId,
|
|
397
|
+
continueToolName: 'claworld_join_world',
|
|
398
|
+
joinToolName: 'claworld_join_world',
|
|
399
|
+
}));
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
name: 'claworld_search_world',
|
|
404
|
+
description: 'Search the selected Claworld world for active online agents. Results return canonical agentId plus a compatibility playerId alias.',
|
|
405
|
+
parameters: {
|
|
406
|
+
type: 'object',
|
|
407
|
+
additionalProperties: false,
|
|
408
|
+
required: ['accountId', 'worldId'],
|
|
409
|
+
properties: {
|
|
410
|
+
accountId: { type: 'string' },
|
|
411
|
+
worldId: { type: 'string', minLength: 1 },
|
|
412
|
+
query: { type: 'object' },
|
|
413
|
+
limit: { type: 'integer', minimum: 1, maximum: 25 },
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
async execute(_toolCallId, params = {}) {
|
|
417
|
+
const context = await resolveToolContext(api, plugin, params);
|
|
418
|
+
const payload = await plugin.runtime.productShell.submitWorldSearch({
|
|
419
|
+
...context,
|
|
420
|
+
worldId: params.worldId,
|
|
421
|
+
agentId: context.agentId,
|
|
422
|
+
query: params.query || {},
|
|
423
|
+
limit: params.limit ?? null,
|
|
424
|
+
});
|
|
425
|
+
return buildToolResult(projectToolSearchWorldResponse(payload, { accountId: context.accountId }));
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
name: 'claworld_broadcast_world',
|
|
430
|
+
description: 'Create batch world-scoped chat requests for the configured audience in a Claworld world.',
|
|
431
|
+
parameters: {
|
|
432
|
+
type: 'object',
|
|
433
|
+
additionalProperties: false,
|
|
434
|
+
required: ['accountId', 'worldId'],
|
|
435
|
+
properties: {
|
|
436
|
+
accountId: { type: 'string' },
|
|
437
|
+
worldId: { type: 'string', minLength: 1 },
|
|
438
|
+
message: { type: 'string', minLength: 1 },
|
|
439
|
+
payload: { type: 'object' },
|
|
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,
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
async execute(_toolCallId, params = {}) {
|
|
477
|
+
const context = await resolveToolContext(api, plugin, params);
|
|
478
|
+
const target = await resolveRelayTargetAddress(plugin, context, params, {
|
|
479
|
+
codeKey: 'targetAgentCode',
|
|
480
|
+
idKey: 'targetAgentId',
|
|
481
|
+
label: 'friend request target',
|
|
482
|
+
});
|
|
483
|
+
const payload = await plugin.helpers.social.sendFriendRequest({
|
|
484
|
+
...context,
|
|
485
|
+
toAddress: target.toAddress,
|
|
486
|
+
message: params.message || null,
|
|
487
|
+
metadata: normalizeObject(params.metadata, null) || {},
|
|
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'],
|
|
543
|
+
properties: {
|
|
544
|
+
accountId: { type: 'string', minLength: 1 },
|
|
545
|
+
friendRequestId: { type: 'string', minLength: 1 },
|
|
546
|
+
},
|
|
547
|
+
},
|
|
548
|
+
async execute(_toolCallId, params = {}) {
|
|
549
|
+
const context = await resolveToolContext(api, plugin, params);
|
|
550
|
+
const payload = await plugin.helpers.social.rejectFriendRequest({
|
|
551
|
+
...context,
|
|
552
|
+
friendRequestId: params.friendRequestId,
|
|
553
|
+
});
|
|
554
|
+
return buildToolResult(projectToolFriendRequestMutationResponse(payload, { accountId: context.accountId }));
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
name: 'claworld_request_chat',
|
|
559
|
+
description: 'Create a direct or world-scoped chat request for another relay peer using its canonical targetAgentId. `openingMessage` is treated as a kickoff brief/opener intent; if the peer accepts, the backend constructs the kickoff bundle, wakes the sender runtime first, and delivers the sender-composed opener to the recipient runtime.',
|
|
560
|
+
parameters: {
|
|
561
|
+
type: 'object',
|
|
562
|
+
additionalProperties: false,
|
|
563
|
+
required: ['accountId', 'targetAgentId'],
|
|
564
|
+
properties: {
|
|
565
|
+
accountId: { type: 'string', minLength: 1 },
|
|
566
|
+
targetAgentId: { type: 'string', minLength: 1 },
|
|
567
|
+
openingMessage: { type: 'string', minLength: 1 },
|
|
568
|
+
worldId: { type: 'string', minLength: 1 },
|
|
569
|
+
episodePolicy: {
|
|
570
|
+
type: 'object',
|
|
571
|
+
additionalProperties: false,
|
|
572
|
+
properties: {
|
|
573
|
+
maxTurns: { type: 'integer', minimum: 1 },
|
|
574
|
+
turnTimeoutMs: { type: 'integer', minimum: 1 },
|
|
575
|
+
raiseHandPolicy: {
|
|
576
|
+
type: 'object',
|
|
577
|
+
additionalProperties: false,
|
|
578
|
+
properties: {
|
|
579
|
+
mode: {
|
|
580
|
+
type: 'string',
|
|
581
|
+
enum: ['dual_raise_hand', 'single_raise_hand', 'either_raise_hand'],
|
|
582
|
+
},
|
|
583
|
+
summary: { type: 'string', minLength: 1 },
|
|
584
|
+
},
|
|
585
|
+
},
|
|
586
|
+
},
|
|
587
|
+
},
|
|
588
|
+
},
|
|
589
|
+
},
|
|
590
|
+
async execute(_toolCallId, params = {}) {
|
|
591
|
+
const context = await resolveToolContext(api, plugin, params);
|
|
592
|
+
const payload = await plugin.helpers.social.requestChat({
|
|
593
|
+
...context,
|
|
594
|
+
targetAgentId: params.targetAgentId,
|
|
595
|
+
openingMessage: params.openingMessage || null,
|
|
596
|
+
worldId: params.worldId || null,
|
|
597
|
+
episodePolicy: params.episodePolicy || null,
|
|
598
|
+
});
|
|
599
|
+
return buildToolResult(projectToolChatRequestMutationResponse(payload, { accountId: context.accountId }));
|
|
600
|
+
},
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
name: 'claworld_list_chat_requests',
|
|
604
|
+
description: 'List pending inbound or outbound Claworld chat requests for the current account.',
|
|
605
|
+
parameters: {
|
|
606
|
+
type: 'object',
|
|
607
|
+
additionalProperties: false,
|
|
608
|
+
required: ['accountId'],
|
|
609
|
+
properties: {
|
|
610
|
+
accountId: { type: 'string', minLength: 1 },
|
|
611
|
+
direction: { type: 'string', enum: ['inbound', 'outbound'] },
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
async execute(_toolCallId, params = {}) {
|
|
615
|
+
const context = await resolveToolContext(api, plugin, params);
|
|
616
|
+
const payload = await plugin.helpers.social.listChatRequests({
|
|
617
|
+
...context,
|
|
618
|
+
direction: params.direction || null,
|
|
619
|
+
});
|
|
620
|
+
return buildToolResult(projectToolChatRequestListResponse(payload, { accountId: context.accountId }));
|
|
621
|
+
},
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
name: 'claworld_accept_chat_request',
|
|
625
|
+
description: 'Accept one inbound Claworld chat request for the current account.',
|
|
626
|
+
parameters: {
|
|
627
|
+
type: 'object',
|
|
628
|
+
additionalProperties: false,
|
|
629
|
+
required: ['accountId', 'chatRequestId'],
|
|
630
|
+
properties: {
|
|
631
|
+
accountId: { type: 'string', minLength: 1 },
|
|
632
|
+
chatRequestId: { type: 'string', minLength: 1 },
|
|
633
|
+
},
|
|
634
|
+
},
|
|
635
|
+
async execute(_toolCallId, params = {}) {
|
|
636
|
+
const context = await resolveToolContext(api, plugin, params);
|
|
637
|
+
const payload = await plugin.helpers.social.acceptChatRequest({
|
|
638
|
+
...context,
|
|
639
|
+
chatRequestId: params.chatRequestId,
|
|
640
|
+
});
|
|
641
|
+
return buildToolResult(projectToolChatRequestMutationResponse(payload, { accountId: context.accountId }));
|
|
642
|
+
},
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
name: 'claworld_submit_feedback',
|
|
646
|
+
description: 'Submit structured feedback about a Claworld experience issue, usage issue, bug, or requested feature.',
|
|
647
|
+
parameters: {
|
|
648
|
+
type: 'object',
|
|
649
|
+
additionalProperties: false,
|
|
650
|
+
required: ['accountId', 'category', 'title', 'goal', 'actualBehavior', 'expectedBehavior'],
|
|
651
|
+
properties: {
|
|
652
|
+
accountId: { type: 'string' },
|
|
653
|
+
category: {
|
|
654
|
+
type: 'string',
|
|
655
|
+
enum: ['experience_issue', 'usage_issue', 'bug_report', 'feature_request'],
|
|
656
|
+
},
|
|
657
|
+
title: { type: 'string', minLength: 1 },
|
|
658
|
+
goal: { type: 'string', minLength: 1 },
|
|
659
|
+
actualBehavior: { type: 'string', minLength: 1 },
|
|
660
|
+
expectedBehavior: { type: 'string', minLength: 1 },
|
|
661
|
+
impact: { type: 'string', enum: ['low', 'medium', 'high', 'blocker'] },
|
|
662
|
+
details: { type: 'string' },
|
|
663
|
+
reproductionSteps: {
|
|
664
|
+
type: 'array',
|
|
665
|
+
maxItems: 8,
|
|
666
|
+
items: { type: 'string' },
|
|
667
|
+
},
|
|
668
|
+
context: {
|
|
669
|
+
type: 'object',
|
|
670
|
+
additionalProperties: false,
|
|
671
|
+
properties: {
|
|
672
|
+
worldId: { type: 'string' },
|
|
673
|
+
sessionId: { type: 'string' },
|
|
674
|
+
roundId: { type: 'string' },
|
|
675
|
+
targetAgentId: { type: 'string' },
|
|
676
|
+
targetAgentCode: { type: 'string' },
|
|
677
|
+
tags: {
|
|
678
|
+
type: 'array',
|
|
679
|
+
maxItems: 10,
|
|
680
|
+
items: { type: 'string' },
|
|
681
|
+
},
|
|
682
|
+
metadata: {
|
|
683
|
+
type: 'object',
|
|
684
|
+
additionalProperties: true,
|
|
685
|
+
},
|
|
686
|
+
},
|
|
687
|
+
},
|
|
688
|
+
},
|
|
689
|
+
},
|
|
690
|
+
async execute(toolCallId, params = {}) {
|
|
691
|
+
const context = await resolveToolContext(api, plugin, params);
|
|
692
|
+
const payload = await plugin.runtime.productShell.feedback.submitFeedback({
|
|
693
|
+
...context,
|
|
694
|
+
category: params.category,
|
|
695
|
+
title: params.title,
|
|
696
|
+
goal: params.goal,
|
|
697
|
+
actualBehavior: params.actualBehavior,
|
|
698
|
+
expectedBehavior: params.expectedBehavior,
|
|
699
|
+
impact: params.impact || null,
|
|
700
|
+
details: params.details || null,
|
|
701
|
+
reproductionSteps: Array.isArray(params.reproductionSteps) ? params.reproductionSteps : [],
|
|
702
|
+
context: params.context || {},
|
|
703
|
+
toolCallId,
|
|
704
|
+
pluginVersion: plugin.meta?.version || null,
|
|
705
|
+
toolContractVersion: CLAWORLD_TOOL_CONTRACT_VERSION,
|
|
706
|
+
});
|
|
707
|
+
return buildToolResult(projectToolFeedbackSubmissionResponse(payload));
|
|
708
|
+
},
|
|
709
|
+
},
|
|
710
|
+
{
|
|
711
|
+
name: 'claworld_create_world',
|
|
712
|
+
description: 'Create a new owner-managed Claworld world.',
|
|
713
|
+
parameters: {
|
|
714
|
+
type: 'object',
|
|
715
|
+
additionalProperties: false,
|
|
716
|
+
required: [
|
|
717
|
+
'accountId',
|
|
718
|
+
'displayName',
|
|
719
|
+
'summary',
|
|
720
|
+
'description',
|
|
721
|
+
'entryProfileSchema',
|
|
722
|
+
'sessionTemplate',
|
|
723
|
+
'interactionRules',
|
|
724
|
+
'prohibitedRules',
|
|
725
|
+
'ratingRules',
|
|
726
|
+
],
|
|
727
|
+
properties: {
|
|
728
|
+
accountId: { type: 'string' },
|
|
729
|
+
displayName: { type: 'string', minLength: 1 },
|
|
730
|
+
summary: { type: 'string', minLength: 1 },
|
|
731
|
+
description: { type: 'string', minLength: 1 },
|
|
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' },
|
|
748
|
+
},
|
|
749
|
+
},
|
|
750
|
+
entryProfileSchema: { type: 'object' },
|
|
751
|
+
sessionTemplate: {
|
|
752
|
+
type: 'object',
|
|
753
|
+
additionalProperties: false,
|
|
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,
|
|
839
|
+
required: ['accountId'],
|
|
840
|
+
properties: {
|
|
841
|
+
accountId: { type: 'string', minLength: 1 },
|
|
842
|
+
},
|
|
843
|
+
},
|
|
844
|
+
async execute(_toolCallId, params = {}) {
|
|
845
|
+
const cfg = await loadCurrentConfig(api);
|
|
846
|
+
const accountId = normalizeText(params.accountId, plugin.config.defaultAccountId(cfg) || null);
|
|
847
|
+
const runtimeConfig = plugin.config.resolveRuntimeConfig(cfg, accountId);
|
|
848
|
+
const payload = await plugin.helpers.pairing.ensureAgentPairing({
|
|
849
|
+
cfg,
|
|
850
|
+
accountId,
|
|
851
|
+
runtimeConfig,
|
|
852
|
+
});
|
|
853
|
+
return buildToolResult({
|
|
854
|
+
status: payload.status,
|
|
855
|
+
reason: payload.reason || null,
|
|
856
|
+
accountId: payload.runtimeConfig?.accountId || accountId,
|
|
857
|
+
bindingSource: payload.bindingSource || null,
|
|
858
|
+
relay: {
|
|
859
|
+
agentId: payload.runtimeConfig?.relay?.agentId || payload.relayAgent?.agentId || null,
|
|
860
|
+
agentCode: payload.relayAgent?.agentCode || null,
|
|
861
|
+
relayLocalCode: payload.relayAgent?.relayLocalCode || null,
|
|
862
|
+
address: payload.relayAgent?.address || null,
|
|
863
|
+
domain: payload.relayAgent?.domain || null,
|
|
864
|
+
displayName: payload.relayAgent?.displayName || null,
|
|
865
|
+
discoverable: payload.relayAgent?.discoverable ?? null,
|
|
866
|
+
contactable: payload.relayAgent?.contactable ?? null,
|
|
867
|
+
online: payload.relayAgent?.online ?? null,
|
|
868
|
+
resolved: payload.relayAgent?.resolved ?? null,
|
|
869
|
+
},
|
|
870
|
+
});
|
|
871
|
+
},
|
|
872
|
+
},
|
|
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
|
+
].map((tool) => ({
|
|
921
|
+
...tool,
|
|
922
|
+
execute: withToolErrorBoundary(tool.name, tool.execute),
|
|
923
|
+
}));
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
export function registerClaworldPluginFull(api, plugin) {
|
|
927
|
+
if (!plugin) {
|
|
928
|
+
throw new Error('registerClaworldPluginFull requires a plugin instance');
|
|
929
|
+
}
|
|
930
|
+
if (typeof api.registerHttpRoute === 'function') {
|
|
931
|
+
api.registerHttpRoute(buildClaworldStatusRoute(plugin));
|
|
932
|
+
}
|
|
933
|
+
if (typeof api.registerTool === 'function') {
|
|
934
|
+
for (const tool of buildRegisteredTools(api, plugin)) {
|
|
935
|
+
api.registerTool(tool, { optional: true });
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
return plugin;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
export function registerClaworldPlugin(api, options = {}) {
|
|
942
|
+
if (!api || typeof api.registerChannel !== 'function') {
|
|
943
|
+
throw new Error('registerClaworldPlugin requires api.registerChannel');
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
if (api.runtime) {
|
|
947
|
+
setClaworldRuntime(api.runtime);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
const {
|
|
951
|
+
plugin: existingPlugin = null,
|
|
952
|
+
...pluginOptions
|
|
953
|
+
} = options;
|
|
954
|
+
const plugin = existingPlugin || createClaworldChannelPlugin(pluginOptions);
|
|
955
|
+
api.registerChannel({ plugin });
|
|
956
|
+
registerClaworldPluginFull(api, plugin);
|
|
957
|
+
return plugin;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
export { buildClaworldStatusRoute };
|
|
961
|
+
export default registerClaworldPlugin;
|