@xfxstudio/claworld 2026.4.22-testing.5 → 2026.4.22-testing.7
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 +4 -4
- package/index.js +14 -0
- package/openclaw.plugin.json +7 -7
- package/package.json +1 -1
- package/skills/claworld-a2a-channel-agent/SKILL.md +22 -6
- package/skills/claworld-help/SKILL.md +38 -232
- package/skills/claworld-join-and-chat/SKILL.md +63 -496
- package/skills/claworld-manage-worlds/SKILL.md +50 -252
- package/src/lib/relay/agent-readable-markdown.js +4 -2
- package/src/lib/relay/kickoff-progress.js +8 -0
- package/src/openclaw/index.js +25 -0
- package/src/openclaw/plugin/claworld-channel-plugin.js +496 -2
- package/src/openclaw/plugin/config-schema.js +3 -3
- package/src/openclaw/plugin/onboarding.js +1 -1
- package/src/openclaw/plugin/register-tooling.js +2 -2
- package/src/openclaw/plugin/register.js +865 -99
- package/src/openclaw/plugin/relay-client.js +16 -0
- package/src/openclaw/runtime/demo-session-bootstrap.js +48 -0
- package/src/openclaw/runtime/inbound-session-router.js +20 -4
- package/src/openclaw/runtime/outbound-session-bridge.js +60 -0
- package/src/openclaw/runtime/product-shell-helper.js +125 -24
- package/src/openclaw/runtime/session-routing.js +144 -0
- package/src/openclaw/runtime/tool-contracts.js +72 -20
- package/src/openclaw/runtime/tool-inventory.js +29 -25
- package/src/openclaw/runtime/working-memory.js +1086 -0
- package/src/openclaw/runtime/workspace-resolver.js +109 -0
- package/src/openclaw/runtime/world-moderation-helper.js +11 -1
- package/src/product-shell/contracts/world-orchestration.js +7 -4
|
@@ -683,6 +683,7 @@ export class ClaworldRelayClient extends EventEmitter {
|
|
|
683
683
|
const cleanup = () => {
|
|
684
684
|
if (timeout) clearTimeout(timeout);
|
|
685
685
|
this.off('reply.accepted', onReplyAccepted);
|
|
686
|
+
this.off('command.accepted', onCommandAccepted);
|
|
686
687
|
this.off('disconnect', onDisconnect);
|
|
687
688
|
this.off('close', onDisconnect);
|
|
688
689
|
};
|
|
@@ -707,6 +708,20 @@ export class ClaworldRelayClient extends EventEmitter {
|
|
|
707
708
|
settleResolve(message);
|
|
708
709
|
};
|
|
709
710
|
|
|
711
|
+
const onCommandAccepted = (message = {}) => {
|
|
712
|
+
const command = message?.data?.command && typeof message.data.command === 'object'
|
|
713
|
+
? message.data.command
|
|
714
|
+
: {};
|
|
715
|
+
if (normalizeOptionalText(command.name) !== 'delivery.reply.requested') return;
|
|
716
|
+
const commandDeliveryId = [
|
|
717
|
+
command.deliveryId,
|
|
718
|
+
command.aggregateId,
|
|
719
|
+
command.partitionKey,
|
|
720
|
+
].map((value) => normalizeOptionalText(value)).find(Boolean) || null;
|
|
721
|
+
if (commandDeliveryId !== normalizedDeliveryId) return;
|
|
722
|
+
settleResolve(message);
|
|
723
|
+
};
|
|
724
|
+
|
|
710
725
|
const onDisconnect = (info = {}) => {
|
|
711
726
|
settleReject(createRuntimeBoundaryError({
|
|
712
727
|
code: 'relay_reply_ack_disconnected',
|
|
@@ -725,6 +740,7 @@ export class ClaworldRelayClient extends EventEmitter {
|
|
|
725
740
|
};
|
|
726
741
|
|
|
727
742
|
this.on('reply.accepted', onReplyAccepted);
|
|
743
|
+
this.on('command.accepted', onCommandAccepted);
|
|
728
744
|
this.on('disconnect', onDisconnect);
|
|
729
745
|
this.on('close', onDisconnect);
|
|
730
746
|
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildAgentWorkingMemoryArtifactIndex,
|
|
3
|
+
buildManagementSessionKey,
|
|
4
|
+
createManagementWorkingMemoryBootstrapContext,
|
|
5
|
+
} from './session-routing.js';
|
|
6
|
+
|
|
1
7
|
export function createDemoSessionBootstrap() {
|
|
2
8
|
return {
|
|
3
9
|
defaults: {
|
|
@@ -28,5 +34,47 @@ export function createDemoSessionBootstrap() {
|
|
|
28
34
|
status: 'planned',
|
|
29
35
|
};
|
|
30
36
|
},
|
|
37
|
+
createManagementBootstrapPlan({
|
|
38
|
+
agentId,
|
|
39
|
+
trigger = 'management_wake',
|
|
40
|
+
workingMemoryRoot = '.claworld',
|
|
41
|
+
now = null,
|
|
42
|
+
event = {},
|
|
43
|
+
} = {}) {
|
|
44
|
+
const context = createManagementWorkingMemoryBootstrapContext({
|
|
45
|
+
agentId,
|
|
46
|
+
trigger,
|
|
47
|
+
workingMemoryRoot,
|
|
48
|
+
now,
|
|
49
|
+
event,
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
status: context.sessionKey ? 'planned' : 'invalid',
|
|
53
|
+
sessionKind: 'management',
|
|
54
|
+
sessionKey: context.sessionKey,
|
|
55
|
+
agentId: context.agentId,
|
|
56
|
+
trigger: context.trigger,
|
|
57
|
+
artifactIndex: context.artifactIndex,
|
|
58
|
+
steps: context.bootstrapChecklist,
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
createAgentWorkingMemoryPlan({
|
|
62
|
+
agentId,
|
|
63
|
+
workingMemoryRoot = '.claworld',
|
|
64
|
+
now = null,
|
|
65
|
+
} = {}) {
|
|
66
|
+
const artifactIndex = buildAgentWorkingMemoryArtifactIndex({
|
|
67
|
+
agentId,
|
|
68
|
+
root: workingMemoryRoot,
|
|
69
|
+
now,
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
status: 'planned',
|
|
73
|
+
agentId: artifactIndex.agentId,
|
|
74
|
+
sessionKey: buildManagementSessionKey(artifactIndex.agentId),
|
|
75
|
+
artifactIndex,
|
|
76
|
+
requiredFiles: artifactIndex.requiredFiles,
|
|
77
|
+
};
|
|
78
|
+
},
|
|
31
79
|
};
|
|
32
80
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { OPENCLAW_RUNTIME_PATH, createRuntimePathTrace } from './runtime-path.js';
|
|
2
|
+
import { resolveRuntimeSessionTarget } from './session-routing.js';
|
|
2
3
|
|
|
3
4
|
function normalizeText(value, fallback = null) {
|
|
4
5
|
if (value == null) return fallback;
|
|
@@ -17,15 +18,21 @@ export function createInboundSessionRouter() {
|
|
|
17
18
|
routeInboundEvent(event = {}, options = {}) {
|
|
18
19
|
const eventType = normalizeText(event.eventType || event.type, null);
|
|
19
20
|
const deliveryId = normalizeText(event.deliveryId || event.event_id || event.eventId, null);
|
|
20
|
-
const sessionKey = normalizeText(event.sessionKey, null);
|
|
21
21
|
const payload = normalizePayload(event.payload);
|
|
22
|
+
const target = resolveRuntimeSessionTarget(event, options);
|
|
23
|
+
const sessionKey = target.sessionKey;
|
|
22
24
|
return {
|
|
23
|
-
action: 'route_delivery',
|
|
24
|
-
target:
|
|
25
|
+
action: target.sessionKind === 'management' ? 'route_management_input' : 'route_delivery',
|
|
26
|
+
target: target.target,
|
|
25
27
|
fallbackTarget: normalizeText(options.fallbackTarget, 'mainagent'),
|
|
28
|
+
sessionKind: target.sessionKind,
|
|
26
29
|
eventType,
|
|
27
30
|
deliveryId,
|
|
28
31
|
sessionKey,
|
|
32
|
+
managementSessionKey: target.managementSessionKey,
|
|
33
|
+
conversationSessionKey: target.conversationSessionKey,
|
|
34
|
+
targetAgentId: target.targetAgentId,
|
|
35
|
+
conversationKey: target.conversationKey,
|
|
29
36
|
payload,
|
|
30
37
|
metadata: event.metadata && typeof event.metadata === 'object' && !Array.isArray(event.metadata)
|
|
31
38
|
? { ...event.metadata }
|
|
@@ -35,7 +42,16 @@ export function createInboundSessionRouter() {
|
|
|
35
42
|
eventId: deliveryId,
|
|
36
43
|
direction: 'inbound',
|
|
37
44
|
}),
|
|
38
|
-
status:
|
|
45
|
+
status: (
|
|
46
|
+
target.sessionKind === 'management'
|
|
47
|
+
&& sessionKey
|
|
48
|
+
&& eventType
|
|
49
|
+
) || (
|
|
50
|
+
eventType === 'delivery'
|
|
51
|
+
&& deliveryId
|
|
52
|
+
&& sessionKey
|
|
53
|
+
&& normalizeText(payload.text, null)
|
|
54
|
+
)
|
|
39
55
|
? 'resolved'
|
|
40
56
|
: 'invalid',
|
|
41
57
|
};
|
|
@@ -4,6 +4,16 @@ function normalizeText(value, fallback = null) {
|
|
|
4
4
|
return normalized || fallback;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
function clonePayload(value = null) {
|
|
8
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return {};
|
|
9
|
+
return JSON.parse(JSON.stringify(value));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function buildManagementSessionKey(agentId = null) {
|
|
13
|
+
const normalizedAgentId = normalizeText(agentId, null);
|
|
14
|
+
return normalizedAgentId ? `management:${normalizedAgentId}` : null;
|
|
15
|
+
}
|
|
16
|
+
|
|
7
17
|
export function createOutboundSessionBridge() {
|
|
8
18
|
return {
|
|
9
19
|
createReplyEnvelope({
|
|
@@ -25,5 +35,55 @@ export function createOutboundSessionBridge() {
|
|
|
25
35
|
},
|
|
26
36
|
};
|
|
27
37
|
},
|
|
38
|
+
createLongRunningIntentHandoffEnvelope({
|
|
39
|
+
agentId,
|
|
40
|
+
intentId = null,
|
|
41
|
+
summary,
|
|
42
|
+
allowedActions = [],
|
|
43
|
+
reportPolicy = 'material_updates',
|
|
44
|
+
sourceSessionKey = null,
|
|
45
|
+
payload = {},
|
|
46
|
+
} = {}) {
|
|
47
|
+
const sessionKey = buildManagementSessionKey(agentId);
|
|
48
|
+
return {
|
|
49
|
+
eventType: 'management_wake',
|
|
50
|
+
sessionKind: 'management',
|
|
51
|
+
sessionKey,
|
|
52
|
+
payload: {
|
|
53
|
+
eventType: 'management_wake',
|
|
54
|
+
reason: 'external_main_long_running_intent_handoff',
|
|
55
|
+
intentId: normalizeText(intentId, null),
|
|
56
|
+
summary: normalizeText(summary, ''),
|
|
57
|
+
allowedActions: Array.isArray(allowedActions)
|
|
58
|
+
? allowedActions.map((action) => normalizeText(action, null)).filter(Boolean)
|
|
59
|
+
: [],
|
|
60
|
+
reportPolicy: normalizeText(reportPolicy, 'material_updates'),
|
|
61
|
+
sourceSessionKey: normalizeText(sourceSessionKey, null),
|
|
62
|
+
targetAgentId: normalizeText(agentId, null),
|
|
63
|
+
...clonePayload(payload),
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
createManagementReportEnvelope({
|
|
68
|
+
agentId,
|
|
69
|
+
reportId = null,
|
|
70
|
+
reportText,
|
|
71
|
+
targetSessionKey = null,
|
|
72
|
+
payload = {},
|
|
73
|
+
} = {}) {
|
|
74
|
+
return {
|
|
75
|
+
eventType: 'management_report',
|
|
76
|
+
sessionKind: 'external_main',
|
|
77
|
+
sessionKey: normalizeText(targetSessionKey, null),
|
|
78
|
+
payload: {
|
|
79
|
+
eventType: 'management_report',
|
|
80
|
+
reportId: normalizeText(reportId, null),
|
|
81
|
+
text: normalizeText(reportText, ''),
|
|
82
|
+
sourceSessionKey: buildManagementSessionKey(agentId),
|
|
83
|
+
sourceAgentId: normalizeText(agentId, null),
|
|
84
|
+
...clonePayload(payload),
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
},
|
|
28
88
|
};
|
|
29
89
|
}
|
|
@@ -146,6 +146,7 @@ function normalizeWorldDetail(payload = {}) {
|
|
|
146
146
|
ownerAgentId: normalizeText(payload.ownerAgentId, null),
|
|
147
147
|
worldRole: normalizeWorldRole(payload.worldRole, null),
|
|
148
148
|
enabled: typeof payload.enabled === 'boolean' ? payload.enabled : null,
|
|
149
|
+
broadcast: normalizeBroadcastConfig(payload.broadcast),
|
|
149
150
|
requiredFieldCount: normalizeInteger(payload.requiredFieldCount, requiredFields.length) || requiredFields.length,
|
|
150
151
|
optionalFieldCount: normalizeInteger(payload.optionalFieldCount, optionalFields.length) || optionalFields.length,
|
|
151
152
|
requiredFields,
|
|
@@ -187,6 +188,7 @@ function normalizeWorldDetail(payload = {}) {
|
|
|
187
188
|
worldRole: normalizeWorldRole(payload.worldRole, null),
|
|
188
189
|
enabled: typeof management.enabled === 'boolean' ? management.enabled : null,
|
|
189
190
|
statusLabel: normalizeText(management.status, null),
|
|
191
|
+
broadcast: normalizeBroadcastConfig(management.broadcast || payload.broadcast || world.broadcast),
|
|
190
192
|
requiredFieldCount: 1,
|
|
191
193
|
optionalFieldCount: 0,
|
|
192
194
|
requiredFields,
|
|
@@ -253,6 +255,16 @@ function normalizeSearchAction(action = null) {
|
|
|
253
255
|
};
|
|
254
256
|
}
|
|
255
257
|
|
|
258
|
+
function normalizeBroadcastConfig(broadcast = null) {
|
|
259
|
+
if (!broadcast || typeof broadcast !== 'object' || Array.isArray(broadcast)) return null;
|
|
260
|
+
return {
|
|
261
|
+
enabled: typeof broadcast.enabled === 'boolean' ? broadcast.enabled : null,
|
|
262
|
+
audience: normalizeText(broadcast.audience, null),
|
|
263
|
+
replyPolicy: normalizeText(broadcast.replyPolicy, null),
|
|
264
|
+
excludeSelf: typeof broadcast.excludeSelf === 'boolean' ? broadcast.excludeSelf : null,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
256
268
|
function normalizeCompatibilitySignal(signal = {}, index = 0) {
|
|
257
269
|
return {
|
|
258
270
|
signalId: normalizeText(signal.signalId, `signal_${index + 1}`),
|
|
@@ -348,18 +360,16 @@ function normalizeCandidateFeedResponse(payload = {}, { worldId = null, agentId
|
|
|
348
360
|
};
|
|
349
361
|
}
|
|
350
362
|
|
|
363
|
+
|
|
364
|
+
function normalizeActionPayload(value = null) {
|
|
365
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
|
|
366
|
+
}
|
|
367
|
+
|
|
351
368
|
export function normalizeWorldJoinResponse(payload = {}, { worldId = null, agentId = null } = {}) {
|
|
352
369
|
const membership = payload.membership && typeof payload.membership === 'object' ? payload.membership : null;
|
|
353
370
|
const normalizedWorldId = normalizeText(payload.worldId, worldId || 'unknown-world');
|
|
354
371
|
const normalizedAgentId = normalizeText(payload.agentId || membership?.agentId, agentId || null);
|
|
355
372
|
const membershipStatus = normalizeText(payload.membershipStatus || membership?.status, 'unknown');
|
|
356
|
-
const candidateFeed = payload.candidateFeed && typeof payload.candidateFeed === 'object'
|
|
357
|
-
? normalizeCandidateFeedResponse(payload.candidateFeed, {
|
|
358
|
-
worldId: normalizedWorldId,
|
|
359
|
-
agentId: normalizedAgentId,
|
|
360
|
-
})
|
|
361
|
-
: null;
|
|
362
|
-
|
|
363
373
|
return {
|
|
364
374
|
status: normalizeText(payload.status, membershipStatus === 'active' ? 'joined' : 'accepted'),
|
|
365
375
|
worldId: normalizedWorldId,
|
|
@@ -373,15 +383,15 @@ export function normalizeWorldJoinResponse(payload = {}, { worldId = null, agent
|
|
|
373
383
|
membership,
|
|
374
384
|
nextAction: normalizeText(
|
|
375
385
|
payload.nextAction,
|
|
376
|
-
membershipStatus === 'active' ? '
|
|
386
|
+
membershipStatus === 'active' ? 'search_world_members_or_view_activity' : null,
|
|
377
387
|
),
|
|
378
388
|
nextStageSummary: payload.nextStageSummary && typeof payload.nextStageSummary === 'object'
|
|
379
389
|
? payload.nextStageSummary
|
|
380
390
|
: {},
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
391
|
+
memberSearchAction: normalizeActionPayload(payload.memberSearchAction),
|
|
392
|
+
worldActivityAction: normalizeActionPayload(payload.worldActivityAction),
|
|
393
|
+
subscribeWorldAction: normalizeActionPayload(payload.subscribeWorldAction),
|
|
394
|
+
requestChatAction: normalizeActionPayload(payload.requestChatAction),
|
|
385
395
|
orchestration: payload.orchestration && typeof payload.orchestration === 'object'
|
|
386
396
|
? payload.orchestration
|
|
387
397
|
: null,
|
|
@@ -681,6 +691,64 @@ export async function searchWorlds({
|
|
|
681
691
|
});
|
|
682
692
|
}
|
|
683
693
|
|
|
694
|
+
export async function search({
|
|
695
|
+
cfg = {},
|
|
696
|
+
accountId = null,
|
|
697
|
+
runtimeConfig = null,
|
|
698
|
+
scope = 'mixed',
|
|
699
|
+
worldId = null,
|
|
700
|
+
agentId = null,
|
|
701
|
+
query = null,
|
|
702
|
+
limit = null,
|
|
703
|
+
sort = null,
|
|
704
|
+
page = null,
|
|
705
|
+
fetchImpl,
|
|
706
|
+
logger = console,
|
|
707
|
+
} = {}) {
|
|
708
|
+
if (typeof fetchImpl !== 'function') {
|
|
709
|
+
throw new Error('fetch is unavailable for claworld product-shell search helper');
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
|
|
713
|
+
const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
|
|
714
|
+
const searchResult = await fetchJson(fetchImpl, `${baseUrl}/v1/search`, {
|
|
715
|
+
method: 'POST',
|
|
716
|
+
headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
|
|
717
|
+
accept: 'application/json',
|
|
718
|
+
'content-type': 'application/json',
|
|
719
|
+
...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
|
|
720
|
+
}),
|
|
721
|
+
body: JSON.stringify({
|
|
722
|
+
scope: normalizeText(scope, 'mixed'),
|
|
723
|
+
worldId: normalizeText(worldId, null),
|
|
724
|
+
agentId: normalizeText(agentId, null),
|
|
725
|
+
query: normalizeText(query, null),
|
|
726
|
+
sort: normalizeText(sort, null),
|
|
727
|
+
limit: limit == null ? null : normalizeInteger(limit, 0),
|
|
728
|
+
page: page == null ? null : normalizeInteger(page, 0),
|
|
729
|
+
}),
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
if (!searchResult.ok) {
|
|
733
|
+
logger.error?.('[claworld:product-shell] search failed', {
|
|
734
|
+
status: searchResult.status,
|
|
735
|
+
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
736
|
+
scope: normalizeText(scope, 'mixed'),
|
|
737
|
+
worldId: normalizeText(worldId, null),
|
|
738
|
+
body: searchResult.body,
|
|
739
|
+
});
|
|
740
|
+
throw createProductShellHttpError('search', searchResult, {
|
|
741
|
+
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
742
|
+
worldId: normalizeText(worldId, null),
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
return {
|
|
747
|
+
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
748
|
+
...searchResult.body,
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
|
|
684
752
|
export async function joinWorld({
|
|
685
753
|
cfg = {},
|
|
686
754
|
accountId = null,
|
|
@@ -828,34 +896,67 @@ export async function fetchWorldCandidateFeed({
|
|
|
828
896
|
|
|
829
897
|
const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
|
|
830
898
|
const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
|
|
831
|
-
const requestUrl = new URL(`${baseUrl}/v1/worlds/${encodeURIComponent(resolvedWorldId)}/candidates`);
|
|
832
|
-
requestUrl.searchParams.set('agentId', resolvedAgentId);
|
|
833
899
|
const normalizedLimit = normalizeInteger(limit, 0);
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
}
|
|
837
|
-
const candidateFeed = await fetchJson(fetchImpl, requestUrl.toString(), {
|
|
900
|
+
const searchResult = await fetchJson(fetchImpl, `${baseUrl}/v1/worlds/${encodeURIComponent(resolvedWorldId)}/search`, {
|
|
901
|
+
method: 'POST',
|
|
838
902
|
headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
|
|
839
903
|
accept: 'application/json',
|
|
904
|
+
'content-type': 'application/json',
|
|
840
905
|
...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
|
|
841
906
|
}),
|
|
907
|
+
body: JSON.stringify({
|
|
908
|
+
agentId: resolvedAgentId,
|
|
909
|
+
query: null,
|
|
910
|
+
sort: 'match',
|
|
911
|
+
limit: normalizedLimit > 0 ? normalizedLimit : null,
|
|
912
|
+
}),
|
|
842
913
|
});
|
|
843
914
|
|
|
844
|
-
if (!
|
|
845
|
-
logger.error?.('[claworld:product-shell] candidate feed
|
|
846
|
-
status:
|
|
915
|
+
if (!searchResult.ok) {
|
|
916
|
+
logger.error?.('[claworld:product-shell] candidate feed compatibility search failed', {
|
|
917
|
+
status: searchResult.status,
|
|
847
918
|
worldId: resolvedWorldId,
|
|
848
919
|
agentId: resolvedAgentId,
|
|
849
920
|
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
850
|
-
body:
|
|
921
|
+
body: searchResult.body,
|
|
851
922
|
});
|
|
852
|
-
throw createProductShellHttpError('world_candidate_feed',
|
|
923
|
+
throw createProductShellHttpError('world_candidate_feed', searchResult, {
|
|
853
924
|
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
854
925
|
worldId: resolvedWorldId,
|
|
855
926
|
});
|
|
856
927
|
}
|
|
857
928
|
|
|
858
|
-
|
|
929
|
+
const searchPayload = searchResult.body && typeof searchResult.body === 'object' ? searchResult.body : {};
|
|
930
|
+
const normalizedSearch = normalizeWorldMemberSearchResponse(searchPayload, {
|
|
931
|
+
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
932
|
+
});
|
|
933
|
+
return normalizeCandidateFeedResponse({
|
|
934
|
+
worldId: resolvedWorldId,
|
|
935
|
+
agentId: resolvedAgentId,
|
|
936
|
+
viewerMembershipId: searchPayload.viewerMembershipId,
|
|
937
|
+
generatedAt: searchPayload.generatedAt,
|
|
938
|
+
limit: normalizedSearch.limit,
|
|
939
|
+
totalCandidates: normalizedSearch.totalMatches,
|
|
940
|
+
candidateSource: searchPayload.candidateSource || 'active_memberships',
|
|
941
|
+
status: normalizedSearch.items.length > 0 ? 'feed_ready' : 'no_candidates_ready',
|
|
942
|
+
nextAction: normalizedSearch.nextAction,
|
|
943
|
+
candidates: normalizedSearch.items.map((item, index) => ({
|
|
944
|
+
candidateId: item.membershipId || `candidate_${index + 1}`,
|
|
945
|
+
sourceMembershipId: item.membershipId || null,
|
|
946
|
+
worldId: item.worldId || resolvedWorldId,
|
|
947
|
+
online: item.online === true,
|
|
948
|
+
rank: index + 1,
|
|
949
|
+
score: item.score,
|
|
950
|
+
agentCode: item.agentCode,
|
|
951
|
+
requestChat: item.requestChat,
|
|
952
|
+
profileSummary: item.profileSummary,
|
|
953
|
+
deliveryReason: {
|
|
954
|
+
summary: item.reasonSummary || item.headline || null,
|
|
955
|
+
},
|
|
956
|
+
worldFeedbackSummary: item.worldFeedbackSummary,
|
|
957
|
+
joinedAt: item.joinedAt,
|
|
958
|
+
})),
|
|
959
|
+
}, {
|
|
859
960
|
worldId: resolvedWorldId,
|
|
860
961
|
agentId: resolvedAgentId,
|
|
861
962
|
});
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CLAWORLD_CONTEXT_DIR,
|
|
3
|
+
CLAWORLD_JOURNAL_DIR,
|
|
4
|
+
CLAWORLD_REPORTS_DIR,
|
|
5
|
+
CLAWORLD_WORKING_MEMORY_DIR,
|
|
6
|
+
CLAWORLD_WORKING_MEMORY_FILES,
|
|
7
|
+
} from './working-memory.js';
|
|
8
|
+
|
|
9
|
+
function normalizeText(value, fallback = null) {
|
|
10
|
+
if (value == null) return fallback;
|
|
11
|
+
const normalized = String(value).trim();
|
|
12
|
+
return normalized || fallback;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function normalizePayload(payload = null) {
|
|
16
|
+
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) return {};
|
|
17
|
+
return { ...payload };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const CLAWORLD_SESSION_KINDS = Object.freeze({
|
|
21
|
+
externalMain: 'external_main',
|
|
22
|
+
management: 'management',
|
|
23
|
+
conversation: 'conversation',
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const CLAWORLD_MANAGEMENT_EVENT_TYPES = Object.freeze([
|
|
27
|
+
'notification',
|
|
28
|
+
'domain_notification',
|
|
29
|
+
'management_wake',
|
|
30
|
+
'management_tick',
|
|
31
|
+
'conversation_lifecycle',
|
|
32
|
+
'platform_recommendation',
|
|
33
|
+
'ops_recommendation',
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
export function buildManagementSessionKey(agentId = null) {
|
|
37
|
+
const normalizedAgentId = normalizeText(agentId, null);
|
|
38
|
+
return normalizedAgentId ? `management:${normalizedAgentId}` : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function buildConversationSessionKey(conversationKey = null, fallbackSessionKey = null) {
|
|
42
|
+
const normalizedConversationKey = normalizeText(conversationKey, null);
|
|
43
|
+
if (normalizedConversationKey) return `conversation:${normalizedConversationKey}`;
|
|
44
|
+
return normalizeText(fallbackSessionKey, null);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function resolveRuntimeSessionTarget(event = {}, options = {}) {
|
|
48
|
+
const payload = normalizePayload(event.payload);
|
|
49
|
+
const eventType = normalizeText(event.eventType || event.type || payload.eventType, null);
|
|
50
|
+
const targetAgentId = normalizeText(
|
|
51
|
+
event.targetAgentId,
|
|
52
|
+
normalizeText(payload.targetAgentId, normalizeText(options.targetAgentId, null)),
|
|
53
|
+
);
|
|
54
|
+
const conversationKey = normalizeText(
|
|
55
|
+
event.conversationKey,
|
|
56
|
+
normalizeText(payload.conversationKey, normalizeText(options.conversationKey, null)),
|
|
57
|
+
);
|
|
58
|
+
const providedSessionKey = normalizeText(
|
|
59
|
+
event.sessionKey,
|
|
60
|
+
normalizeText(payload.sessionKey, normalizeText(options.sessionKey, null)),
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
if (CLAWORLD_MANAGEMENT_EVENT_TYPES.includes(eventType)) {
|
|
64
|
+
const managementSessionKey = normalizeText(
|
|
65
|
+
options.managementSessionKey,
|
|
66
|
+
buildManagementSessionKey(targetAgentId),
|
|
67
|
+
);
|
|
68
|
+
return {
|
|
69
|
+
sessionKind: CLAWORLD_SESSION_KINDS.management,
|
|
70
|
+
target: normalizeText(options.managementTarget, 'management_session'),
|
|
71
|
+
sessionKey: managementSessionKey || providedSessionKey,
|
|
72
|
+
managementSessionKey: managementSessionKey || null,
|
|
73
|
+
conversationSessionKey: conversationKey ? buildConversationSessionKey(conversationKey) : null,
|
|
74
|
+
targetAgentId,
|
|
75
|
+
conversationKey,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const conversationSessionKey = buildConversationSessionKey(conversationKey, providedSessionKey);
|
|
80
|
+
return {
|
|
81
|
+
sessionKind: CLAWORLD_SESSION_KINDS.conversation,
|
|
82
|
+
target: normalizeText(options.sessionTarget, 'conversation_session'),
|
|
83
|
+
sessionKey: conversationSessionKey,
|
|
84
|
+
managementSessionKey: targetAgentId ? buildManagementSessionKey(targetAgentId) : null,
|
|
85
|
+
conversationSessionKey,
|
|
86
|
+
targetAgentId,
|
|
87
|
+
conversationKey,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function buildAgentWorkingMemoryArtifactIndex({
|
|
92
|
+
agentId = null,
|
|
93
|
+
root = CLAWORLD_WORKING_MEMORY_DIR,
|
|
94
|
+
now = null,
|
|
95
|
+
} = {}) {
|
|
96
|
+
const normalizedAgentId = normalizeText(agentId, 'unknown-agent');
|
|
97
|
+
const basePath = normalizeText(root, CLAWORLD_WORKING_MEMORY_DIR).replace(/\/+$/, '');
|
|
98
|
+
const profilePath = `${basePath}/${CLAWORLD_WORKING_MEMORY_FILES.profile}`;
|
|
99
|
+
const memoryPath = `${basePath}/${CLAWORLD_WORKING_MEMORY_FILES.memory}`;
|
|
100
|
+
const nowPath = `${basePath}/${CLAWORLD_WORKING_MEMORY_FILES.now}`;
|
|
101
|
+
return {
|
|
102
|
+
agentId: normalizedAgentId,
|
|
103
|
+
generatedAt: normalizeText(now, null),
|
|
104
|
+
workingMemoryRoot: basePath,
|
|
105
|
+
profilePath,
|
|
106
|
+
memoryPath,
|
|
107
|
+
nowPath,
|
|
108
|
+
journalPath: `${basePath}/${CLAWORLD_JOURNAL_DIR}/`,
|
|
109
|
+
reportsPath: `${basePath}/${CLAWORLD_REPORTS_DIR}/`,
|
|
110
|
+
contextPath: `${basePath}/${CLAWORLD_CONTEXT_DIR}/`,
|
|
111
|
+
requiredFiles: [profilePath, memoryPath, nowPath],
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function createManagementWorkingMemoryBootstrapContext({
|
|
116
|
+
agentId = null,
|
|
117
|
+
trigger = 'management_wake',
|
|
118
|
+
event = {},
|
|
119
|
+
workingMemoryRoot = CLAWORLD_WORKING_MEMORY_DIR,
|
|
120
|
+
now = null,
|
|
121
|
+
} = {}) {
|
|
122
|
+
const artifactIndex = buildAgentWorkingMemoryArtifactIndex({
|
|
123
|
+
agentId,
|
|
124
|
+
root: workingMemoryRoot,
|
|
125
|
+
now,
|
|
126
|
+
});
|
|
127
|
+
return {
|
|
128
|
+
sessionKind: CLAWORLD_SESSION_KINDS.management,
|
|
129
|
+
sessionKey: buildManagementSessionKey(agentId),
|
|
130
|
+
agentId: normalizeText(agentId, null),
|
|
131
|
+
trigger: normalizeText(trigger, 'management_wake'),
|
|
132
|
+
workingMemory: artifactIndex,
|
|
133
|
+
artifactIndex,
|
|
134
|
+
bootstrapChecklist: [
|
|
135
|
+
'read PROFILE.md for autonomy policy and authorization boundaries',
|
|
136
|
+
'read MEMORY.md for durable people/world/user preference context',
|
|
137
|
+
'read NOW.md for active standing intents and report policy',
|
|
138
|
+
'load recent journal and report pointers before deciding actions',
|
|
139
|
+
'verify backend facts with public tools before acting',
|
|
140
|
+
'write journal/report evidence for important management decisions',
|
|
141
|
+
],
|
|
142
|
+
event: normalizePayload(event),
|
|
143
|
+
};
|
|
144
|
+
}
|