@xfxstudio/claworld 2026.4.14-testing.1 → 2026.4.16-testing.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/index.js +0 -50
- package/setup-entry.js +0 -6
- package/skills/claworld-a2a-channel-agent/SKILL.md +0 -218
- package/skills/claworld-help/SKILL.md +0 -304
- package/skills/claworld-join-and-chat/SKILL.md +0 -515
- package/skills/claworld-manage-worlds/SKILL.md +0 -283
- package/skills/claworld-manage-worlds/references/world-context-templates.md +0 -145
- package/src/lib/chat-request.js +0 -366
- package/src/lib/public-identity.js +0 -175
- package/src/lib/relay/agent-readable-markdown.js +0 -385
- package/src/lib/relay/kickoff-progress.js +0 -162
- package/src/lib/relay/kickoff-text.js +0 -191
- package/src/lib/relay/shared.js +0 -30
- package/src/lib/runtime-errors.js +0 -149
- package/src/openclaw/index.js +0 -51
- package/src/openclaw/plugin/account-identity.js +0 -73
- package/src/openclaw/plugin/claworld-channel-plugin.js +0 -3483
- package/src/openclaw/plugin/config-schema.js +0 -392
- package/src/openclaw/plugin/lifecycle.js +0 -114
- package/src/openclaw/plugin/managed-config.js +0 -1054
- package/src/openclaw/plugin/onboarding.js +0 -312
- package/src/openclaw/plugin/register-tooling.js +0 -728
- package/src/openclaw/plugin/register.js +0 -1609
- package/src/openclaw/plugin/relay-client-shared.js +0 -146
- package/src/openclaw/plugin/relay-client.js +0 -1469
- package/src/openclaw/plugin/runtime-backup.js +0 -105
- package/src/openclaw/plugin/runtime.js +0 -12
- package/src/openclaw/plugin-version.js +0 -67
- package/src/openclaw/protocol/relay-event-protocol.js +0 -43
- package/src/openclaw/runtime/backend-error-context.js +0 -91
- package/src/openclaw/runtime/canonical-result-builder.js +0 -126
- package/src/openclaw/runtime/demo-session-bootstrap.js +0 -32
- package/src/openclaw/runtime/feedback-helper.js +0 -145
- package/src/openclaw/runtime/inbound-session-router.js +0 -44
- package/src/openclaw/runtime/outbound-session-bridge.js +0 -29
- package/src/openclaw/runtime/product-shell-helper.js +0 -931
- package/src/openclaw/runtime/runtime-path.js +0 -19
- package/src/openclaw/runtime/system-message-orchestrator.js +0 -1
- package/src/openclaw/runtime/tool-contracts.js +0 -939
- package/src/openclaw/runtime/tool-inventory.js +0 -83
- package/src/openclaw/runtime/world-membership-helper.js +0 -320
- package/src/openclaw/runtime/world-moderation-helper.js +0 -508
- package/src/product-shell/contracts/chat-request-approval-policy.js +0 -93
- package/src/product-shell/contracts/world-orchestration.js +0 -734
- package/src/product-shell/orchestration/world-conversation-text.js +0 -229
|
@@ -1,392 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
applyRuntimeIdentity,
|
|
3
|
-
normalizeRuntimeRegistration,
|
|
4
|
-
resolveRuntimeAppToken,
|
|
5
|
-
} from './account-identity.js';
|
|
6
|
-
|
|
7
|
-
const REQUIRED_KEYS = ['enabled', 'serverUrl', 'apiKey', 'accountId'];
|
|
8
|
-
|
|
9
|
-
export const CLAWORLD_CHANNEL_ID = 'claworld';
|
|
10
|
-
|
|
11
|
-
const AGENT_REGISTRATION_SCHEMA = {
|
|
12
|
-
type: 'object',
|
|
13
|
-
additionalProperties: false,
|
|
14
|
-
properties: {
|
|
15
|
-
enabled: {
|
|
16
|
-
type: 'boolean',
|
|
17
|
-
description: 'Enable relay agent registration when this account does not already have an app token.',
|
|
18
|
-
default: false,
|
|
19
|
-
},
|
|
20
|
-
displayName: {
|
|
21
|
-
type: 'string',
|
|
22
|
-
minLength: 1,
|
|
23
|
-
description: 'Public display name to use when the relay agent is created or refreshed.',
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const LOCAL_AGENT_BOOTSTRAP_SCHEMA = AGENT_REGISTRATION_SCHEMA;
|
|
29
|
-
export const LOCAL_AGENT_BOOTSTRAP_REQUIRED = ['displayName'];
|
|
30
|
-
|
|
31
|
-
export const MANUAL_RELAY_BINDING_SCHEMA = {
|
|
32
|
-
type: 'object',
|
|
33
|
-
additionalProperties: false,
|
|
34
|
-
properties: {
|
|
35
|
-
appToken: {
|
|
36
|
-
type: 'string',
|
|
37
|
-
minLength: 1,
|
|
38
|
-
description: 'Canonical Claworld app token for this account. The runtime resolves the bound relay agent from this token.',
|
|
39
|
-
},
|
|
40
|
-
agentId: {
|
|
41
|
-
type: 'string',
|
|
42
|
-
minLength: 1,
|
|
43
|
-
description: 'Legacy relay agent id hint. Canonical flow resolves the binding from appToken at runtime.',
|
|
44
|
-
},
|
|
45
|
-
credentialToken: {
|
|
46
|
-
type: 'string',
|
|
47
|
-
minLength: 1,
|
|
48
|
-
description: 'Legacy alias for appToken.',
|
|
49
|
-
},
|
|
50
|
-
defaultTargetAgentId: {
|
|
51
|
-
type: 'string',
|
|
52
|
-
minLength: 1,
|
|
53
|
-
description: 'Default relay target agentId for minimal outbound testing.',
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const SINGLE_ACCOUNT_PROPERTIES = {
|
|
59
|
-
name: {
|
|
60
|
-
type: 'string',
|
|
61
|
-
minLength: 1,
|
|
62
|
-
description: 'Optional operator-facing name for this local Claworld account.',
|
|
63
|
-
},
|
|
64
|
-
enabled: { type: 'boolean', description: 'Enable the Claworld channel plugin.' },
|
|
65
|
-
serverUrl: {
|
|
66
|
-
type: 'string',
|
|
67
|
-
minLength: 1,
|
|
68
|
-
description: 'Relay backend base URL or websocket URL (http/https/ws/wss).',
|
|
69
|
-
},
|
|
70
|
-
apiKey: {
|
|
71
|
-
type: 'string',
|
|
72
|
-
minLength: 1,
|
|
73
|
-
description: 'Plugin/backend API key for future backend-authenticated control paths.',
|
|
74
|
-
},
|
|
75
|
-
appToken: {
|
|
76
|
-
type: 'string',
|
|
77
|
-
minLength: 1,
|
|
78
|
-
description: 'Canonical Claworld app token for this channel account.',
|
|
79
|
-
},
|
|
80
|
-
accountId: {
|
|
81
|
-
type: 'string',
|
|
82
|
-
minLength: 1,
|
|
83
|
-
description: 'Local OpenClaw-facing account id bound to this channel instance.',
|
|
84
|
-
},
|
|
85
|
-
toolProfile: {
|
|
86
|
-
type: 'string',
|
|
87
|
-
enum: ['minimal', 'default', 'world', 'full'],
|
|
88
|
-
description: 'Legacy ignored field retained for backward-compatible config parsing.',
|
|
89
|
-
},
|
|
90
|
-
heartbeatSeconds: {
|
|
91
|
-
type: 'integer',
|
|
92
|
-
minimum: 1,
|
|
93
|
-
description: 'Heartbeat cadence for the relay websocket client.',
|
|
94
|
-
default: 15,
|
|
95
|
-
},
|
|
96
|
-
reconnect: {
|
|
97
|
-
type: 'boolean',
|
|
98
|
-
description: 'Whether reconnect attempts are allowed after disconnect.',
|
|
99
|
-
default: true,
|
|
100
|
-
},
|
|
101
|
-
routing: {
|
|
102
|
-
type: 'object',
|
|
103
|
-
additionalProperties: false,
|
|
104
|
-
properties: {
|
|
105
|
-
sessionTarget: {
|
|
106
|
-
type: 'string',
|
|
107
|
-
enum: ['subagent', 'mainagent'],
|
|
108
|
-
default: 'mainagent',
|
|
109
|
-
},
|
|
110
|
-
fallbackTarget: {
|
|
111
|
-
type: 'string',
|
|
112
|
-
enum: ['mainagent', 'human(optional)'],
|
|
113
|
-
default: 'mainagent',
|
|
114
|
-
},
|
|
115
|
-
allowHumanInterrupt: {
|
|
116
|
-
type: 'boolean',
|
|
117
|
-
default: true,
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
testing: {
|
|
122
|
-
type: 'object',
|
|
123
|
-
additionalProperties: false,
|
|
124
|
-
properties: {
|
|
125
|
-
allowBridgedCommandDispatch: {
|
|
126
|
-
type: 'boolean',
|
|
127
|
-
description: 'Test-only switch that allows bridged relay turns beginning with slash commands to use the OpenClaw command fast-path.',
|
|
128
|
-
default: false,
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
registration: AGENT_REGISTRATION_SCHEMA,
|
|
133
|
-
relay: MANUAL_RELAY_BINDING_SCHEMA,
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
export const claworldChannelConfigJsonSchema = {
|
|
137
|
-
type: 'object',
|
|
138
|
-
additionalProperties: false,
|
|
139
|
-
properties: {
|
|
140
|
-
...SINGLE_ACCOUNT_PROPERTIES,
|
|
141
|
-
defaultAccount: {
|
|
142
|
-
type: 'string',
|
|
143
|
-
minLength: 1,
|
|
144
|
-
description: 'Default account id to use when multiple claworld accounts are configured.',
|
|
145
|
-
},
|
|
146
|
-
accounts: {
|
|
147
|
-
type: 'object',
|
|
148
|
-
minProperties: 1,
|
|
149
|
-
additionalProperties: {
|
|
150
|
-
type: 'object',
|
|
151
|
-
additionalProperties: false,
|
|
152
|
-
required: REQUIRED_KEYS,
|
|
153
|
-
properties: SINGLE_ACCOUNT_PROPERTIES,
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
export const claworldChannelConfigSchema = {
|
|
160
|
-
channelId: CLAWORLD_CHANNEL_ID,
|
|
161
|
-
required: REQUIRED_KEYS,
|
|
162
|
-
optional: ['name', 'heartbeatSeconds', 'reconnect', 'routing', 'testing', 'appToken', 'registration', 'relay', 'toolProfile', 'defaultAccount', 'accounts'],
|
|
163
|
-
jsonSchema: claworldChannelConfigJsonSchema,
|
|
164
|
-
description:
|
|
165
|
-
'最小 OpenClaw claworld channel 配置;支持单账号或 accounts.<id> 多账号模式。canonical flow uses appToken + registration.displayName bootstrap.',
|
|
166
|
-
routingShape: {
|
|
167
|
-
sessionTarget: 'mainagent',
|
|
168
|
-
fallbackTarget: 'mainagent',
|
|
169
|
-
allowHumanInterrupt: true,
|
|
170
|
-
},
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
function normalizeText(value, fallback = null) {
|
|
174
|
-
if (value == null) return fallback;
|
|
175
|
-
const normalized = String(value).trim();
|
|
176
|
-
return normalized || fallback;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function readRawClaworldRoot(config = {}) {
|
|
180
|
-
if (config?.channels?.[CLAWORLD_CHANNEL_ID]) return config.channels[CLAWORLD_CHANNEL_ID];
|
|
181
|
-
if (config?.[CLAWORLD_CHANNEL_ID]) return config[CLAWORLD_CHANNEL_ID];
|
|
182
|
-
return config;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function listConfiguredClaworldAccountIds(config = {}) {
|
|
186
|
-
const root = readRawClaworldRoot(config);
|
|
187
|
-
if (root?.accounts && typeof root.accounts === 'object') {
|
|
188
|
-
return Object.keys(root.accounts).filter(Boolean);
|
|
189
|
-
}
|
|
190
|
-
const single = root;
|
|
191
|
-
if (single?.accountId) return [single.accountId];
|
|
192
|
-
return [];
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function readDefaultAccountId(config = {}) {
|
|
196
|
-
const root = readRawClaworldRoot(config);
|
|
197
|
-
const configuredIds = listConfiguredClaworldAccountIds(config);
|
|
198
|
-
const explicit = String(root?.defaultAccount || '').trim();
|
|
199
|
-
if (explicit && configuredIds.includes(explicit)) return explicit;
|
|
200
|
-
if (root?.accounts?.default) return 'default';
|
|
201
|
-
return configuredIds[0] || null;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function readClaworldConfigSection(config = {}, accountId = null) {
|
|
205
|
-
const root = readRawClaworldRoot(config);
|
|
206
|
-
if (root?.accounts && typeof root.accounts === 'object') {
|
|
207
|
-
const normalizedAccountId = String(accountId || '').trim();
|
|
208
|
-
if (normalizedAccountId && root.accounts[normalizedAccountId]) return root.accounts[normalizedAccountId];
|
|
209
|
-
|
|
210
|
-
const defaultAccountId = readDefaultAccountId(config);
|
|
211
|
-
if (defaultAccountId && root.accounts[defaultAccountId]) return root.accounts[defaultAccountId];
|
|
212
|
-
|
|
213
|
-
const [firstAccount] = Object.values(root.accounts);
|
|
214
|
-
if (firstAccount) return firstAccount;
|
|
215
|
-
}
|
|
216
|
-
return root;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function determineCredentialStatus(candidate = {}) {
|
|
220
|
-
if (resolveRuntimeAppToken(candidate)) {
|
|
221
|
-
return { tokenSource: 'config', tokenStatus: 'available' };
|
|
222
|
-
}
|
|
223
|
-
if (normalizeRuntimeRegistration(candidate).enabled) {
|
|
224
|
-
return { tokenSource: 'registration', tokenStatus: 'registration_required' };
|
|
225
|
-
}
|
|
226
|
-
return { tokenSource: 'none', tokenStatus: 'missing' };
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function determineBindingStatus(candidate = {}) {
|
|
230
|
-
if (resolveRuntimeAppToken(candidate)) return 'bound';
|
|
231
|
-
if (normalizeRuntimeRegistration(candidate).enabled) return 'registration_pending';
|
|
232
|
-
return 'unbound';
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
export function validateClaworldChannelConfig(config = {}, accountId = null) {
|
|
236
|
-
const root = readRawClaworldRoot(config);
|
|
237
|
-
const candidate = readClaworldConfigSection(config, accountId) || {};
|
|
238
|
-
const missing = REQUIRED_KEYS.filter((key) => candidate[key] == null || candidate[key] === '');
|
|
239
|
-
const errors = [];
|
|
240
|
-
const registration = normalizeRuntimeRegistration(candidate);
|
|
241
|
-
const appToken = resolveRuntimeAppToken(candidate);
|
|
242
|
-
const configuredIds = listConfiguredClaworldAccountIds(config);
|
|
243
|
-
const hasMultipleAccounts = configuredIds.length > 1;
|
|
244
|
-
const explicitDefaultAccount = String(root?.defaultAccount || '').trim();
|
|
245
|
-
|
|
246
|
-
if (hasMultipleAccounts && !explicitDefaultAccount && !String(accountId || '').trim()) {
|
|
247
|
-
errors.push({ code: 'missing_default_account' });
|
|
248
|
-
}
|
|
249
|
-
if (explicitDefaultAccount && root?.accounts && !root.accounts[explicitDefaultAccount]) {
|
|
250
|
-
errors.push({ code: 'invalid_default_account', value: explicitDefaultAccount });
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
if (missing.length > 0) {
|
|
254
|
-
errors.push({ code: 'missing_required_keys', keys: missing });
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
if (candidate.serverUrl != null) {
|
|
258
|
-
try {
|
|
259
|
-
const parsed = new URL(candidate.serverUrl);
|
|
260
|
-
if (!['ws:', 'wss:', 'http:', 'https:'].includes(parsed.protocol)) {
|
|
261
|
-
errors.push({ code: 'invalid_server_url_protocol', value: parsed.protocol });
|
|
262
|
-
}
|
|
263
|
-
} catch {
|
|
264
|
-
errors.push({ code: 'invalid_server_url', value: candidate.serverUrl });
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (
|
|
269
|
-
candidate.heartbeatSeconds != null
|
|
270
|
-
&& (!Number.isFinite(Number(candidate.heartbeatSeconds)) || Number(candidate.heartbeatSeconds) <= 0)
|
|
271
|
-
) {
|
|
272
|
-
errors.push({ code: 'invalid_heartbeat_seconds', value: candidate.heartbeatSeconds });
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const sessionTarget = candidate.routing?.sessionTarget || 'mainagent';
|
|
276
|
-
const fallbackTarget = candidate.routing?.fallbackTarget || 'mainagent';
|
|
277
|
-
if (!['subagent', 'mainagent'].includes(sessionTarget)) {
|
|
278
|
-
errors.push({ code: 'invalid_session_target', value: sessionTarget });
|
|
279
|
-
}
|
|
280
|
-
if (!['mainagent', 'human(optional)'].includes(fallbackTarget)) {
|
|
281
|
-
errors.push({ code: 'invalid_fallback_target', value: fallbackTarget });
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (registration.enabled && !registration.displayName) {
|
|
285
|
-
errors.push({ code: 'missing_registration_display_name' });
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (candidate.relay?.agentId && !appToken) {
|
|
289
|
-
errors.push({ code: 'missing_relay_app_token' });
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
const runtimeIdentity = applyRuntimeIdentity({
|
|
293
|
-
enabled: Boolean(candidate.enabled),
|
|
294
|
-
serverUrl: candidate.serverUrl || null,
|
|
295
|
-
apiKey: candidate.apiKey || null,
|
|
296
|
-
appToken,
|
|
297
|
-
accountId: candidate.accountId || null,
|
|
298
|
-
defaultAccount: explicitDefaultAccount || null,
|
|
299
|
-
heartbeatSeconds: candidate.heartbeatSeconds == null ? 15 : Math.floor(Number(candidate.heartbeatSeconds)),
|
|
300
|
-
reconnect: candidate.reconnect !== false,
|
|
301
|
-
routing: {
|
|
302
|
-
sessionTarget,
|
|
303
|
-
fallbackTarget,
|
|
304
|
-
allowHumanInterrupt: candidate.routing?.allowHumanInterrupt !== false,
|
|
305
|
-
},
|
|
306
|
-
testing: {
|
|
307
|
-
allowBridgedCommandDispatch: candidate.testing?.allowBridgedCommandDispatch === true,
|
|
308
|
-
},
|
|
309
|
-
registration,
|
|
310
|
-
relay: {
|
|
311
|
-
agentId: candidate.relay?.agentId || null,
|
|
312
|
-
appToken,
|
|
313
|
-
credentialToken: appToken,
|
|
314
|
-
defaultTargetAgentId: candidate.relay?.defaultTargetAgentId || null,
|
|
315
|
-
},
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
return {
|
|
319
|
-
ok: errors.length === 0,
|
|
320
|
-
errors,
|
|
321
|
-
normalized: runtimeIdentity,
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
export function inspectClaworldChannelAccount(config = {}, accountId = null) {
|
|
326
|
-
const result = validateClaworldChannelConfig(config, accountId);
|
|
327
|
-
const normalized = result.normalized;
|
|
328
|
-
const configuredIds = listConfiguredClaworldAccountIds(config);
|
|
329
|
-
const { tokenSource, tokenStatus } = determineCredentialStatus(normalized);
|
|
330
|
-
const bindingStatus = determineBindingStatus(normalized);
|
|
331
|
-
const configured = Boolean(normalized.serverUrl && normalized.apiKey && normalized.accountId);
|
|
332
|
-
return {
|
|
333
|
-
accountId: normalized.accountId || accountId || readDefaultAccountId(config) || configuredIds[0] || 'default',
|
|
334
|
-
name: normalizeText(normalized.name, normalizeText(normalized.registration?.displayName, null)),
|
|
335
|
-
enabled: normalized.enabled,
|
|
336
|
-
configured,
|
|
337
|
-
configuredStatus: configured ? 'configured' : 'missing_required_config',
|
|
338
|
-
serverUrl: normalized.serverUrl,
|
|
339
|
-
heartbeatSeconds: normalized.heartbeatSeconds,
|
|
340
|
-
reconnect: normalized.reconnect,
|
|
341
|
-
routing: normalized.routing,
|
|
342
|
-
testing: normalized.testing,
|
|
343
|
-
appToken: normalized.appToken || null,
|
|
344
|
-
registration: normalized.registration,
|
|
345
|
-
relay: normalized.relay,
|
|
346
|
-
defaultAccount: normalized.defaultAccount,
|
|
347
|
-
bindingStatus,
|
|
348
|
-
tokenSource,
|
|
349
|
-
tokenStatus,
|
|
350
|
-
issues: result.errors,
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
export function projectClaworldStatusAccount(inspection = {}) {
|
|
355
|
-
// Keep the steady-state credential nested under relay/runtimeConfig so
|
|
356
|
-
// generic OpenClaw status does not misclassify Claworld as a bot+app token
|
|
357
|
-
// channel.
|
|
358
|
-
const { appToken: _appToken, ...statusAccount } = inspection || {};
|
|
359
|
-
return statusAccount;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
export function resolveClaworldRuntimeConfig(config = {}, accountId = null) {
|
|
363
|
-
const result = validateClaworldChannelConfig(config, accountId);
|
|
364
|
-
if (!result.ok) {
|
|
365
|
-
const detail = result.errors.map((error) => error.code).join(', ') || 'invalid_config';
|
|
366
|
-
throw new Error(`invalid claworld config: ${detail}`);
|
|
367
|
-
}
|
|
368
|
-
return {
|
|
369
|
-
...result.normalized,
|
|
370
|
-
accountId: result.normalized.accountId || accountId || readDefaultAccountId(config) || 'default',
|
|
371
|
-
relay: result.normalized.relay,
|
|
372
|
-
};
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
export function resolveClaworldChannelAccount(config = {}, accountId = null) {
|
|
376
|
-
const runtimeConfig = resolveClaworldRuntimeConfig(config, accountId);
|
|
377
|
-
const inspection = inspectClaworldChannelAccount(config, accountId);
|
|
378
|
-
return {
|
|
379
|
-
...projectClaworldStatusAccount(inspection),
|
|
380
|
-
runtimeReady: true,
|
|
381
|
-
resolvedFrom: accountId ? 'requested_account' : 'default_account',
|
|
382
|
-
runtimeConfig,
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
export function listClaworldAccountIds(config = {}) {
|
|
387
|
-
return listConfiguredClaworldAccountIds(config);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
export function defaultClaworldAccountId(config = {}) {
|
|
391
|
-
return readDefaultAccountId(config) || 'default';
|
|
392
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
logRuntimeBoundary,
|
|
3
|
-
serializeRuntimeBoundaryError,
|
|
4
|
-
} from '../../lib/runtime-errors.js';
|
|
5
|
-
|
|
6
|
-
export function createClaworldLifecycleManager({ connect, disconnect, logger = console } = {}) {
|
|
7
|
-
let started = false;
|
|
8
|
-
let connection = null;
|
|
9
|
-
let lastStartError = null;
|
|
10
|
-
let lastStartFailure = null;
|
|
11
|
-
let lastStopReason = null;
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
async start(context = {}) {
|
|
15
|
-
if (started) {
|
|
16
|
-
logger.warn?.('[openclaw:lifecycle] start ignored: already started');
|
|
17
|
-
return {
|
|
18
|
-
started: true,
|
|
19
|
-
reused: true,
|
|
20
|
-
connection,
|
|
21
|
-
lastStartError,
|
|
22
|
-
lastStartFailure,
|
|
23
|
-
lastStopReason,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
started = true;
|
|
28
|
-
lastStartError = null;
|
|
29
|
-
lastStartFailure = null;
|
|
30
|
-
lastStopReason = null;
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
connection = (await connect?.(context)) || null;
|
|
34
|
-
logger.info?.('[openclaw:lifecycle] started');
|
|
35
|
-
return {
|
|
36
|
-
started: true,
|
|
37
|
-
reused: false,
|
|
38
|
-
connection,
|
|
39
|
-
lastStartError,
|
|
40
|
-
lastStartFailure,
|
|
41
|
-
lastStopReason,
|
|
42
|
-
};
|
|
43
|
-
} catch (error) {
|
|
44
|
-
started = false;
|
|
45
|
-
connection = null;
|
|
46
|
-
const normalized = logRuntimeBoundary(logger, '[openclaw:lifecycle] start failed', error, null, {
|
|
47
|
-
includeStack: false,
|
|
48
|
-
fallback: {
|
|
49
|
-
code: 'openclaw_lifecycle_start_failed',
|
|
50
|
-
category: 'bootstrap',
|
|
51
|
-
publicMessage: 'OpenClaw Claworld lifecycle start failed',
|
|
52
|
-
recoverable: true,
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
lastStartError = normalized.message;
|
|
56
|
-
lastStartFailure = serializeRuntimeBoundaryError(normalized);
|
|
57
|
-
throw normalized;
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
async stop(reason = 'manual_stop') {
|
|
61
|
-
if (!started) {
|
|
62
|
-
return {
|
|
63
|
-
started: false,
|
|
64
|
-
stopped: false,
|
|
65
|
-
reason: 'not_started',
|
|
66
|
-
lastStartError,
|
|
67
|
-
lastStartFailure,
|
|
68
|
-
lastStopReason,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
started = false;
|
|
73
|
-
try {
|
|
74
|
-
await disconnect?.({ reason, connection });
|
|
75
|
-
} catch (error) {
|
|
76
|
-
connection = null;
|
|
77
|
-
const normalized = logRuntimeBoundary(logger, '[openclaw:lifecycle] stop failed', error, { reason }, {
|
|
78
|
-
includeStack: false,
|
|
79
|
-
fallback: {
|
|
80
|
-
code: 'openclaw_lifecycle_stop_failed',
|
|
81
|
-
category: 'runtime',
|
|
82
|
-
publicMessage: 'OpenClaw Claworld lifecycle stop failed',
|
|
83
|
-
recoverable: true,
|
|
84
|
-
},
|
|
85
|
-
});
|
|
86
|
-
throw normalized;
|
|
87
|
-
}
|
|
88
|
-
connection = null;
|
|
89
|
-
lastStopReason = reason;
|
|
90
|
-
logger.info?.(`[openclaw:lifecycle] stopped (${reason})`);
|
|
91
|
-
return {
|
|
92
|
-
started: false,
|
|
93
|
-
stopped: true,
|
|
94
|
-
reason,
|
|
95
|
-
lastStartError,
|
|
96
|
-
lastStartFailure,
|
|
97
|
-
lastStopReason,
|
|
98
|
-
};
|
|
99
|
-
},
|
|
100
|
-
async reconnect(context = {}) {
|
|
101
|
-
await this.stop('reconnect');
|
|
102
|
-
return this.start(context);
|
|
103
|
-
},
|
|
104
|
-
snapshot() {
|
|
105
|
-
return {
|
|
106
|
-
started,
|
|
107
|
-
hasConnection: Boolean(connection),
|
|
108
|
-
lastStartError,
|
|
109
|
-
lastStartFailure,
|
|
110
|
-
lastStopReason,
|
|
111
|
-
};
|
|
112
|
-
},
|
|
113
|
-
};
|
|
114
|
-
}
|