@xfxstudio/claworld 2026.6.5 → 2026.6.10-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/README.md +9 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/claworld-help/SKILL.md +2 -2
- package/skills/claworld-main-session/SKILL.md +2 -0
- package/skills/claworld-management-session/SKILL.md +1 -0
- package/src/openclaw/plugin/conversation-viewer-env.js +56 -0
- package/src/openclaw/plugin/conversation-viewer.js +1117 -0
- package/src/openclaw/plugin/onboarding.js +1 -1
- package/src/openclaw/plugin/register-tooling.js +6 -3
- package/src/openclaw/plugin/register.js +70 -16
- package/src/openclaw/runtime/tool-contracts.js +40 -0
|
@@ -247,7 +247,7 @@ async function applyManagedOnboardingConfig({
|
|
|
247
247
|
`Remote backend: ${managedOptions.serverUrl}`,
|
|
248
248
|
managedOptions.appToken
|
|
249
249
|
? 'Activation state: ready via configured appToken'
|
|
250
|
-
: 'Activation state: pending until claworld_manage_account(action=
|
|
250
|
+
: 'Activation state: pending until claworld_manage_account(action=activate_account) runs',
|
|
251
251
|
'This flow refreshes plugin-side config and binds claworld onto the selected local agent. It does not run installer commands or start a backend service.',
|
|
252
252
|
];
|
|
253
253
|
await prompter.note(
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
} from '../runtime/backend-error-context.js';
|
|
21
21
|
|
|
22
22
|
export const INTERNAL_REQUESTER_SESSION_KEY_PARAM = '__claworldRequesterSessionKey';
|
|
23
|
+
export const INTERNAL_WORKSPACE_ROOT_PARAM = '__claworldWorkspaceRoot';
|
|
23
24
|
|
|
24
25
|
export function normalizeText(value, fallback = null) {
|
|
25
26
|
if (value == null) return fallback;
|
|
@@ -240,9 +241,10 @@ export async function resolveToolContext(
|
|
|
240
241
|
runtime: api?.runtime || null,
|
|
241
242
|
accountId,
|
|
242
243
|
runtimeConfig,
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
244
|
+
agentId: normalizeText(params.agentId, runtimeConfig.relay?.agentId || null),
|
|
245
|
+
requesterSessionKey: normalizeText(params[INTERNAL_REQUESTER_SESSION_KEY_PARAM], null),
|
|
246
|
+
workspaceRoot: normalizeText(params[INTERNAL_WORKSPACE_ROOT_PARAM], null),
|
|
247
|
+
});
|
|
246
248
|
if (
|
|
247
249
|
requiredPublicIdentityCapability
|
|
248
250
|
&& (
|
|
@@ -282,6 +284,7 @@ export async function resolveToolContext(
|
|
|
282
284
|
runtimeConfig,
|
|
283
285
|
agentId,
|
|
284
286
|
requesterSessionKey: normalizeText(params[INTERNAL_REQUESTER_SESSION_KEY_PARAM], null),
|
|
287
|
+
workspaceRoot: normalizeText(params[INTERNAL_WORKSPACE_ROOT_PARAM], null),
|
|
285
288
|
};
|
|
286
289
|
}
|
|
287
290
|
|
|
@@ -2,6 +2,10 @@ import {
|
|
|
2
2
|
createClaworldChannelPlugin,
|
|
3
3
|
recordClaworldRuntimeAssistantOutput,
|
|
4
4
|
} from './claworld-channel-plugin.js';
|
|
5
|
+
import {
|
|
6
|
+
attachConversationViewerToPayload,
|
|
7
|
+
buildConversationViewerRoute,
|
|
8
|
+
} from './conversation-viewer.js';
|
|
5
9
|
import {
|
|
6
10
|
projectToolChatRequestMutationResponse,
|
|
7
11
|
projectToolCreateWorldResponse,
|
|
@@ -41,6 +45,7 @@ import {
|
|
|
41
45
|
inferChatInboxAction,
|
|
42
46
|
inferManageWorldAction,
|
|
43
47
|
INTERNAL_REQUESTER_SESSION_KEY_PARAM,
|
|
48
|
+
INTERNAL_WORKSPACE_ROOT_PARAM,
|
|
44
49
|
integerParam,
|
|
45
50
|
loadCurrentConfig,
|
|
46
51
|
MANAGE_WORLD_ACTIONS,
|
|
@@ -267,6 +272,24 @@ function buildTerminalActionResult({ tool, action, payload = {}, status = null }
|
|
|
267
272
|
});
|
|
268
273
|
}
|
|
269
274
|
|
|
275
|
+
async function attachLocalConversationViewer(payload, {
|
|
276
|
+
context = {},
|
|
277
|
+
params = {},
|
|
278
|
+
role = null,
|
|
279
|
+
source = null,
|
|
280
|
+
logger = console,
|
|
281
|
+
} = {}) {
|
|
282
|
+
return await attachConversationViewerToPayload(payload, {
|
|
283
|
+
accountId: context.accountId || null,
|
|
284
|
+
viewerAgentId: context.agentId || null,
|
|
285
|
+
role,
|
|
286
|
+
source,
|
|
287
|
+
cfg: context.cfg || {},
|
|
288
|
+
workspaceRoot: context.workspaceRoot || params[INTERNAL_WORKSPACE_ROOT_PARAM] || null,
|
|
289
|
+
logger,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
|
|
270
293
|
function normalizeChatInboxListFiltersInput(params = {}) {
|
|
271
294
|
const source = normalizeObject(params.filters, {}) || {};
|
|
272
295
|
const normalized = {
|
|
@@ -1093,10 +1116,17 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
|
|
|
1093
1116
|
conversationKey,
|
|
1094
1117
|
localSessionKey,
|
|
1095
1118
|
});
|
|
1119
|
+
const payloadWithViewer = await attachLocalConversationViewer(payload, {
|
|
1120
|
+
context,
|
|
1121
|
+
params,
|
|
1122
|
+
role: 'participant',
|
|
1123
|
+
source: 'close_conversation',
|
|
1124
|
+
logger: getHookLogger(api),
|
|
1125
|
+
});
|
|
1096
1126
|
return buildTerminalActionResult({
|
|
1097
1127
|
tool: manageConversationsTool,
|
|
1098
1128
|
action,
|
|
1099
|
-
payload,
|
|
1129
|
+
payload: payloadWithViewer,
|
|
1100
1130
|
});
|
|
1101
1131
|
}
|
|
1102
1132
|
requireManageWorldField('action', `action must be one of ${TERMINAL_CONVERSATION_ACTIONS.join(', ')}`);
|
|
@@ -1691,6 +1721,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
1691
1721
|
'Do not use this tool for replying inside an already-open Claworld chat or for runtime live turns.',
|
|
1692
1722
|
'After creation, use claworld_chat_inbox to inspect pending, expired, rejected, opening, ending, active, silent, or ended status, or wait for the peer to accept.',
|
|
1693
1723
|
'Once accepted, the runtime owns the live conversation loop.',
|
|
1724
|
+
'If the result includes conversationViewer.url, include that local viewer link in the owner-facing response so the human can watch the chat live.',
|
|
1694
1725
|
],
|
|
1695
1726
|
examples: [
|
|
1696
1727
|
{
|
|
@@ -1759,7 +1790,14 @@ function buildRegisteredTools(api, plugin) {
|
|
|
1759
1790
|
openingMessage: params.openingMessage || null,
|
|
1760
1791
|
worldId: params.worldId || null,
|
|
1761
1792
|
});
|
|
1762
|
-
|
|
1793
|
+
const payloadWithViewer = await attachLocalConversationViewer(payload, {
|
|
1794
|
+
context,
|
|
1795
|
+
params,
|
|
1796
|
+
role: 'requester',
|
|
1797
|
+
source: 'request_chat',
|
|
1798
|
+
logger: getHookLogger(api),
|
|
1799
|
+
});
|
|
1800
|
+
return buildToolResult(projectToolChatRequestMutationResponse(payloadWithViewer, { accountId: context.accountId }));
|
|
1763
1801
|
},
|
|
1764
1802
|
},
|
|
1765
1803
|
{
|
|
@@ -1778,6 +1816,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
1778
1816
|
'For user requests to contact, PK, continue, or re-engage a Claworld peer, use claworld_manage_conversations(action=request) with the intended direct or world scope.',
|
|
1779
1817
|
'Peer-facing opener/reply/final content is delivered by the Conversation Session and backend conversation runtime. Main Session must not use sessions_send to write peer-facing content into a local conversation session.',
|
|
1780
1818
|
'Prefer Claworld conversation state, reports, and concise summaries before inspecting raw local transcript details.',
|
|
1819
|
+
'If an accept result includes conversationViewer.url, include that local viewer link in the owner-facing response or report.',
|
|
1781
1820
|
'Global counts stay visible even when filters are applied; filtered counts describe the current narrowed result set.',
|
|
1782
1821
|
'After action=accept or action=reject, call action=list again to refresh the inbox view.',
|
|
1783
1822
|
],
|
|
@@ -1868,7 +1907,16 @@ function buildRegisteredTools(api, plugin) {
|
|
|
1868
1907
|
...context,
|
|
1869
1908
|
chatRequestId,
|
|
1870
1909
|
});
|
|
1871
|
-
|
|
1910
|
+
const payloadWithViewer = action === 'accept'
|
|
1911
|
+
? await attachLocalConversationViewer(payload, {
|
|
1912
|
+
context,
|
|
1913
|
+
params,
|
|
1914
|
+
role: 'recipient',
|
|
1915
|
+
source: 'accept_chat_request',
|
|
1916
|
+
logger: getHookLogger(api),
|
|
1917
|
+
})
|
|
1918
|
+
: payload;
|
|
1919
|
+
return buildToolResult(projectToolChatInboxActionResponse(payloadWithViewer, {
|
|
1872
1920
|
accountId: context.accountId,
|
|
1873
1921
|
action,
|
|
1874
1922
|
}));
|
|
@@ -1956,7 +2004,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
1956
2004
|
examples: ['Moza', '小发发'],
|
|
1957
2005
|
}),
|
|
1958
2006
|
profile: stringParam({
|
|
1959
|
-
description: 'Global plain-text profile for this account. Maximum
|
|
2007
|
+
description: 'Global plain-text profile for this account. Maximum 500 characters. Use an empty string to clear it. HTML is not supported.',
|
|
1960
2008
|
examples: ['喜欢慢节奏介绍和小范围世界,也愿意先让 agent 帮我做初步认识。🙂'],
|
|
1961
2009
|
}),
|
|
1962
2010
|
chatRequestApprovalPolicy: chatRequestApprovalPolicyProperty,
|
|
@@ -2148,7 +2196,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
2148
2196
|
}));
|
|
2149
2197
|
}
|
|
2150
2198
|
|
|
2151
|
-
export function registerClaworldPluginFull(api, plugin) {
|
|
2199
|
+
export function registerClaworldPluginFull(api, plugin, { fetchImpl = globalThis.fetch } = {}) {
|
|
2152
2200
|
if (!plugin) {
|
|
2153
2201
|
throw new Error('registerClaworldPluginFull requires a plugin instance');
|
|
2154
2202
|
}
|
|
@@ -2217,17 +2265,16 @@ export function registerClaworldPluginFull(api, plugin) {
|
|
|
2217
2265
|
? event.params
|
|
2218
2266
|
: {};
|
|
2219
2267
|
const requesterSessionKey = normalizeText(ctx?.sessionKey, null);
|
|
2220
|
-
if (
|
|
2221
|
-
toolName !== 'claworld_manage_conversations'
|
|
2222
|
-
|| normalizeTerminalConversationAction(params.action, null) !== 'request'
|
|
2223
|
-
|| !requesterSessionKey
|
|
2224
|
-
) {
|
|
2225
|
-
return;
|
|
2226
|
-
}
|
|
2268
|
+
if (toolName !== 'claworld_manage_conversations') return;
|
|
2227
2269
|
const logger = getHookLogger(api);
|
|
2270
|
+
let workspaceRoot = null;
|
|
2228
2271
|
try {
|
|
2229
|
-
|
|
2230
|
-
if (
|
|
2272
|
+
workspaceRoot = await resolveHookWorkspaceRoot(api, event, ctx);
|
|
2273
|
+
if (
|
|
2274
|
+
workspaceRoot
|
|
2275
|
+
&& requesterSessionKey
|
|
2276
|
+
&& normalizeTerminalConversationAction(params.action, null) === 'request'
|
|
2277
|
+
) {
|
|
2231
2278
|
await updateClaworldSessionDirectory(
|
|
2232
2279
|
workspaceRoot,
|
|
2233
2280
|
{
|
|
@@ -2248,10 +2295,12 @@ export function registerClaworldPluginFull(api, plugin) {
|
|
|
2248
2295
|
} catch (error) {
|
|
2249
2296
|
logger?.warn?.('[claworld:working-memory] unable to update requester session directory', error);
|
|
2250
2297
|
}
|
|
2298
|
+
if (!requesterSessionKey && !workspaceRoot) return;
|
|
2251
2299
|
return {
|
|
2252
2300
|
params: {
|
|
2253
2301
|
...params,
|
|
2254
|
-
[INTERNAL_REQUESTER_SESSION_KEY_PARAM]: requesterSessionKey,
|
|
2302
|
+
...(requesterSessionKey ? { [INTERNAL_REQUESTER_SESSION_KEY_PARAM]: requesterSessionKey } : {}),
|
|
2303
|
+
...(workspaceRoot ? { [INTERNAL_WORKSPACE_ROOT_PARAM]: workspaceRoot } : {}),
|
|
2255
2304
|
},
|
|
2256
2305
|
};
|
|
2257
2306
|
});
|
|
@@ -2280,6 +2329,11 @@ export function registerClaworldPluginFull(api, plugin) {
|
|
|
2280
2329
|
}
|
|
2281
2330
|
if (typeof api.registerHttpRoute === 'function') {
|
|
2282
2331
|
api.registerHttpRoute(buildClaworldStatusRoute(plugin));
|
|
2332
|
+
api.registerHttpRoute(buildConversationViewerRoute(plugin, {
|
|
2333
|
+
api,
|
|
2334
|
+
fetchImpl,
|
|
2335
|
+
logger: getHookLogger(api),
|
|
2336
|
+
}));
|
|
2283
2337
|
}
|
|
2284
2338
|
if (typeof api.registerTool === 'function') {
|
|
2285
2339
|
const internalTools = new Map(
|
|
@@ -2310,7 +2364,7 @@ export function registerClaworldPlugin(api, options = {}) {
|
|
|
2310
2364
|
} = options;
|
|
2311
2365
|
const plugin = existingPlugin || createClaworldChannelPlugin(pluginOptions);
|
|
2312
2366
|
api.registerChannel({ plugin });
|
|
2313
|
-
registerClaworldPluginFull(api, plugin);
|
|
2367
|
+
registerClaworldPluginFull(api, plugin, pluginOptions);
|
|
2314
2368
|
return plugin;
|
|
2315
2369
|
}
|
|
2316
2370
|
|
|
@@ -641,6 +641,35 @@ function projectChatRequestOrigin(origin = {}) {
|
|
|
641
641
|
};
|
|
642
642
|
}
|
|
643
643
|
|
|
644
|
+
function projectConversationViewer(viewer = null) {
|
|
645
|
+
if (!viewer || typeof viewer !== 'object' || Array.isArray(viewer)) return null;
|
|
646
|
+
const id = normalizeText(viewer.id, normalizeText(viewer.viewerId, null));
|
|
647
|
+
const url = normalizeText(viewer.url, null);
|
|
648
|
+
if (!id && !url && normalizeText(viewer.status, null) !== 'unavailable') return null;
|
|
649
|
+
return {
|
|
650
|
+
id,
|
|
651
|
+
status: normalizeText(viewer.status, 'ready'),
|
|
652
|
+
url,
|
|
653
|
+
localFile: normalizeText(viewer.localFile, null),
|
|
654
|
+
fileUrl: normalizeText(viewer.fileUrl, null),
|
|
655
|
+
chatRequestId: normalizeText(viewer.chatRequestId, null),
|
|
656
|
+
conversationKey: normalizeText(viewer.conversationKey, null),
|
|
657
|
+
localSessionKey: normalizeText(viewer.localSessionKey, null),
|
|
658
|
+
replay: viewer.replay && typeof viewer.replay === 'object' && !Array.isArray(viewer.replay)
|
|
659
|
+
? {
|
|
660
|
+
firstOpenReplaysEndedConversation: typeof viewer.replay.firstOpenReplaysEndedConversation === 'boolean'
|
|
661
|
+
? viewer.replay.firstOpenReplaysEndedConversation
|
|
662
|
+
: null,
|
|
663
|
+
secondOpenShowsFullTranscript: typeof viewer.replay.secondOpenShowsFullTranscript === 'boolean'
|
|
664
|
+
? viewer.replay.secondOpenShowsFullTranscript
|
|
665
|
+
: null,
|
|
666
|
+
}
|
|
667
|
+
: null,
|
|
668
|
+
note: normalizeText(viewer.note, null),
|
|
669
|
+
reason: normalizeText(viewer.reason, null),
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
|
|
644
673
|
function projectChatRequestItem(request = {}) {
|
|
645
674
|
if (!request || typeof request !== 'object') return null;
|
|
646
675
|
const requestContext = request.requestContext && typeof request.requestContext === 'object' && !Array.isArray(request.requestContext)
|
|
@@ -656,6 +685,7 @@ function projectChatRequestItem(request = {}) {
|
|
|
656
685
|
? request.conversation
|
|
657
686
|
: requestContext.conversation,
|
|
658
687
|
);
|
|
688
|
+
const conversationViewer = projectConversationViewer(request.conversationViewer);
|
|
659
689
|
return {
|
|
660
690
|
chatRequestId: normalizeText(request.chatRequestId || request.requestId, null),
|
|
661
691
|
status: normalizeText(request.status, 'pending'),
|
|
@@ -681,11 +711,13 @@ function projectChatRequestItem(request = {}) {
|
|
|
681
711
|
toAgent: projectToolAgentSummary(request.toAgent),
|
|
682
712
|
counterparty: projectToolAgentSummary(request.counterparty),
|
|
683
713
|
conversation,
|
|
714
|
+
...(conversationViewer ? { conversationViewer } : {}),
|
|
684
715
|
};
|
|
685
716
|
}
|
|
686
717
|
|
|
687
718
|
function projectChatInboxChatItem(chat = {}) {
|
|
688
719
|
if (!chat || typeof chat !== 'object' || Array.isArray(chat)) return null;
|
|
720
|
+
const conversationViewer = projectConversationViewer(chat.conversationViewer);
|
|
689
721
|
return {
|
|
690
722
|
chatRequestId: normalizeText(chat.chatRequestId, null),
|
|
691
723
|
status: normalizeText(chat.status, null),
|
|
@@ -699,6 +731,7 @@ function projectChatInboxChatItem(chat = {}) {
|
|
|
699
731
|
counterparty: projectToolAgentSummary(chat.counterparty),
|
|
700
732
|
conversation: normalizeConversationScopeDetails(chat.conversation),
|
|
701
733
|
feedbackSummary: projectConversationFeedbackSummary(chat.feedbackSummary),
|
|
734
|
+
...(conversationViewer ? { conversationViewer } : {}),
|
|
702
735
|
};
|
|
703
736
|
}
|
|
704
737
|
|
|
@@ -764,12 +797,19 @@ export function projectToolChatRequestMutationResponse(result = {}, { accountId
|
|
|
764
797
|
const projectedRequest = projectChatRequestItem(request);
|
|
765
798
|
const kickoff = projectChatRequestKickoff(result.kickoff || result.request?.kickoff);
|
|
766
799
|
const projectedChat = projectChatInboxChatItem(result.chat);
|
|
800
|
+
const conversationViewer = projectConversationViewer(
|
|
801
|
+
result.conversationViewer
|
|
802
|
+
|| request?.conversationViewer
|
|
803
|
+
|| result.request?.conversationViewer
|
|
804
|
+
|| result.chat?.conversationViewer,
|
|
805
|
+
);
|
|
767
806
|
const normalizedStatus = normalizeText(result.status, projectedRequest?.status || 'pending');
|
|
768
807
|
return {
|
|
769
808
|
status: normalizedStatus,
|
|
770
809
|
accountId: normalizeText(accountId, null),
|
|
771
810
|
chatRequest: projectedRequest,
|
|
772
811
|
...(projectedChat ? { chat: projectedChat } : {}),
|
|
812
|
+
...(conversationViewer ? { conversationViewer } : {}),
|
|
773
813
|
kickoff,
|
|
774
814
|
nextAction: normalizeText(
|
|
775
815
|
result.nextAction,
|