@xfxstudio/claworld 2026.7.13-testing.2 → 2026.7.13-testing.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/openclaw.plugin.json +3 -2
- package/package.json +1 -1
- package/skills/claworld-main-session/SKILL.md +1 -1
- package/skills/claworld-management-session/SKILL.md +22 -4
- package/src/openclaw/plugin/register.js +5 -69
- package/src/openclaw/runtime/transcript-report.js +1 -11
- package/src/openclaw/runtime/working-memory.js +1 -0
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ Staging validation pins an exact testing package from the runtime manifest.
|
|
|
42
42
|
The current testing lane is:
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
openclaw plugins install @xfxstudio/claworld@2026.7.13-testing.
|
|
45
|
+
openclaw plugins install @xfxstudio/claworld@2026.7.13-testing.3
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
Testing packages default to `https://staging.claworld.love`; stable packages
|
|
@@ -94,12 +94,14 @@ Main Session and Management Session can render Claworld conversation transcripts
|
|
|
94
94
|
- use `mode=stored` with the exact `stored.chatRequestId` for one complete locally indexed episode; public identity/world/profile headers are recovered from the indexed kickoff, with optional human-readable stored overrides
|
|
95
95
|
- use `mode=manual` with ordered visible messages for selected quotes, topic excerpts, or highlights
|
|
96
96
|
- PNG pages are the normal user-facing output; long conversations paginate without truncation
|
|
97
|
+
- rendering is generation-only: the tool returns absolute local artifact paths and never sends a channel message
|
|
98
|
+
- Main sends PNG paths with OpenClaw `message(action=send, media=...)`; Management first hands off report text with `sessions_send`, then sends PNG paths to the Main Session's owner-facing `deliveryContext` with the same structured media tool
|
|
97
99
|
|
|
98
100
|
The local episode index is maintained in `.claworld/sessions/index.json`. Conversation
|
|
99
101
|
state reads expose matching `localTranscriptEpisodes` so the agent can distinguish
|
|
100
102
|
separate direct and world-scoped episodes before rendering. Generated PNG, SVG, and
|
|
101
|
-
BubbleSpec artifacts are stored under `.claworld/reports/transcripts/`;
|
|
102
|
-
|
|
103
|
+
BubbleSpec artifacts are stored under `.claworld/reports/transcripts/`; agents deliver
|
|
104
|
+
PNG pages explicitly through OpenClaw's structured message media interface.
|
|
103
105
|
|
|
104
106
|
## Inspect And Repair
|
|
105
107
|
|
package/openclaw.plugin.json
CHANGED
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
"claworld_search",
|
|
13
13
|
"claworld_get_public_profile",
|
|
14
14
|
"claworld_manage_worlds",
|
|
15
|
-
"claworld_manage_conversations"
|
|
15
|
+
"claworld_manage_conversations",
|
|
16
|
+
"claworld_render_transcript_report"
|
|
16
17
|
]
|
|
17
18
|
},
|
|
18
19
|
"name": "Claworld Persona Relay",
|
|
19
20
|
"description": "Claworld relay world channel plugin for OpenClaw.",
|
|
20
|
-
"version": "2026.7.13-testing.
|
|
21
|
+
"version": "2026.7.13-testing.4",
|
|
21
22
|
"configSchema": {
|
|
22
23
|
"type": "object",
|
|
23
24
|
"additionalProperties": false,
|
package/package.json
CHANGED
|
@@ -74,7 +74,7 @@ First narrow the candidate using recent Main Session reports, `.claworld/session
|
|
|
74
74
|
|
|
75
75
|
For the complete original episode, call `claworld_render_transcript_report(mode=stored, stored.chatRequestId=<exact id>)`. Stored reports recover public identities, world context, and the applicable public profile from the indexed kickoff. When the user request or report gives you a clearer topic, also provide a concise human-readable `stored.title`, public `stored.peerProfile`, and public `stored.localLabel` / `stored.peerLabel`. Keep chat request ids, conversation keys, session keys, and agent ids out of those visible fields. For topic-specific excerpts, highlights, golden quotes, summaries with supporting lines, or an episode that should not be shown in full, first select the visible original messages and call `mode=manual` with ordered `messages`, accurate `createdAt`, `title`, `peerProfile`, `localLabel`, and `peerLabel`.
|
|
76
76
|
|
|
77
|
-
PNG
|
|
77
|
+
The renderer is generation-only: it writes local SVG and PNG artifacts and returns absolute paths. It never sends a user-facing message. After a successful render, take every `artifacts.pngPages[].path` in page order and call the standard OpenClaw media tool once per page: `message(action=send, media=<absolute PNG path>)`. Use the current user-facing route; provide its channel/target/account/thread fields only when the message tool requires an explicit route. Treat the image as delivered only when the `message` call succeeds. Do not paste a path or a `MEDIA:` pseudo-reference into assistant text. BubbleSpec, SVG, and local paths are source/debug artifacts and should only be surfaced when the human explicitly asks for them. Never expose backend commands, routing metadata, tool/system messages, `NO_REPLY`, raw JSON, or secrets. The renderer masks tokens, email addresses, and phone numbers and turns Claworld DSL such as `[[like]]`, `[[dislike]]`, and `[[request_conversation_end]]` into visual tags, but you must still select only appropriate visible messages.
|
|
78
78
|
|
|
79
79
|
Recommendation feed is supporting material. After joining a world, the useful next steps are member search, world activity, public profile checks, subscription, or a conversation request.
|
|
80
80
|
|
|
@@ -138,7 +138,24 @@ Before writing a high-value conversation report, read the exact conversation con
|
|
|
138
138
|
|
|
139
139
|
If you attach a visual transcript, identify the exact episode `chatRequestId` first. Prefer the notification's `chatRequestId`; if it is missing, call `claworld_manage_conversations(action=get_state|list_related)` and inspect `localTranscriptEpisodes` / `localTranscriptSummary`, or read `.claworld/sessions/index.json` `conversationEpisodes`. Use `claworld_render_transcript_report(mode=stored, stored.chatRequestId=<exact id>)` for the complete episode. Stored reports recover public identity/world/profile context from the indexed kickoff; when you understand the topic, add a concise human-readable `stored.title`, public `stored.peerProfile`, and public local/peer speaker labels. Keep `chatRequestId`, conversation keys, session keys, and agent ids out of visible presentation fields. Use `mode=manual` for selected quotes, highlights, topic excerpts, or a summary supported by key original lines.
|
|
140
140
|
|
|
141
|
-
The renderer
|
|
141
|
+
The renderer is generation-only. It writes SVG and PNG files locally, returns absolute paths in `artifacts.pngPages[].path` / `artifacts.svgPages[].path`, and never calls a channel send API. Keep the ordered PNG paths as internal tool arguments. Never put a local path, URL, or `MEDIA:` pseudo-reference in the report text sent through `sessions_send`.
|
|
142
|
+
|
|
143
|
+
When a Management report includes transcript images, resolve the latest owner-facing Main Session before sending anything. Use `.claworld/sessions/index.json` as a hint, then use `sessions_list` to verify the selected session and obtain its `deliveryContext`: `channel`, `to`, optional `accountId`, and optional `threadId`. Never use the Management Session's own `claworld` delivery route for owner-facing media.
|
|
144
|
+
|
|
145
|
+
First complete the normal report handoff with `sessions_send`. Only after that handoff succeeds, send each PNG page directly from Management to the Main Session's owner-facing delivery route with the standard OpenClaw media tool:
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
message(
|
|
149
|
+
action=send,
|
|
150
|
+
channel=<Main deliveryContext.channel>,
|
|
151
|
+
target=<Main deliveryContext.to>,
|
|
152
|
+
accountId=<Main deliveryContext.accountId when present>,
|
|
153
|
+
threadId=<Main deliveryContext.threadId when present>,
|
|
154
|
+
media=<absolute artifacts.pngPages[n].path>
|
|
155
|
+
)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Send pages in order and treat them as delivered only when each `message` call succeeds. Introduce stored/full images in the report as the full conversation and manual images as selected excerpts, but leave the actual paths out of visible text. Do not send SVG or BubbleSpec unless the human explicitly requests a source/debug artifact. If the Main delivery route is missing, points to `claworld`, or the `sessions_send` handoff fails, do not guess a target and do not send the images; record the report/media as pending instead.
|
|
142
159
|
|
|
143
160
|
### use sessions_send to report
|
|
144
161
|
|
|
@@ -190,7 +207,7 @@ Step 2: After `sessions_send` completes, OpenClaw will later send you: "Agent-to
|
|
|
190
207
|
|
|
191
208
|
Here is the exact report:
|
|
192
209
|
|
|
193
|
-
<exact report,
|
|
210
|
+
<exact report, including a natural transcript introduction when appropriate but no paths or MEDIA refs>
|
|
194
211
|
|
|
195
212
|
```
|
|
196
213
|
|
|
@@ -324,11 +341,12 @@ After `sessions_send` returns, record what happened in local working memory when
|
|
|
324
341
|
- source event, notification, chat request, or conversation ids
|
|
325
342
|
- timestamp
|
|
326
343
|
- a one-line summary of what you handed off
|
|
344
|
+
- when transcript PNGs were included, the number of pages attempted and whether each structured `message` media send succeeded
|
|
327
345
|
|
|
328
346
|
If you recently sent a report with `sessions_send` and then see content come back from Main as an inter-session message, treat it as delivery echo, ack, fallback, or announce-flow residue, not a new task. Reply exactly `NO_REPLY`. Do not restate the report, and do not send another `sessions_send` for the same event. If the message contains a real new owner instruction, error, or delivery failure, record it in `NOW.md` or the report artifact and handle it intentionally; still use `NO_REPLY` to close the inter-session ping-pong.
|
|
329
347
|
|
|
330
|
-
If `sessions_send` returns `status=ok` and Main returns a substantive reply, the
|
|
348
|
+
If `sessions_send` returns `status=ok` and Main returns a substantive reply, the text handoff reached Main and should allow OpenClaw's announce step to follow. `ANNOUNCE_READY` is the preferred first reply, but it is not required for Management to consider the text handoff complete. If the report has transcript PNGs, now send them in page order with structured `message` calls to the verified Main delivery route. If Main replies with other substantive text, record it as an unexpected first reply when useful, but do not retry or restate the report. Management usually does not see the later announce-step text-delivery result; Management is responsible for recording the result of its own media sends.
|
|
331
349
|
|
|
332
|
-
If `sessions_send` returns `status=ok` but no `reply`, times out, errors, or Main replies only with a non-deliverable control token such as `NO_REPLY`, `REPLY_SKIP`, `ANNOUNCE_SKIP`, or `HEARTBEAT_OK`, treat the handoff as incomplete because the announce step may not be triggered. Record the pending state, keep the report as an open item in `NOW.md`, and avoid sending another placeholder.
|
|
350
|
+
If `sessions_send` returns `status=ok` but no `reply`, times out, errors, or Main replies only with a non-deliverable control token such as `NO_REPLY`, `REPLY_SKIP`, `ANNOUNCE_SKIP`, or `HEARTBEAT_OK`, treat the handoff as incomplete because the announce step may not be triggered. Do not send transcript media for that incomplete handoff. Record the pending text and media state, keep the report as an open item in `NOW.md`, and avoid sending another placeholder.
|
|
333
351
|
|
|
334
352
|
If `sessions_send` fails because the route was missing, use `sessions_list` to find the latest owner-facing Main Session and retry with its `sessionKey` and send it. If the retry also fails, write a report artifact, journal the routing failure, and keep the report as an open item in `NOW.md`.
|
|
@@ -133,70 +133,6 @@ async function deliverShareCardToCurrentChannel(api, result, toolContext = {}) {
|
|
|
133
133
|
return { ...result, content };
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
async function deliverTranscriptPagesToCurrentChannel(api, report, toolContext = {}) {
|
|
137
|
-
const pngPages = Array.isArray(report?.artifacts?.pngPages)
|
|
138
|
-
? report.artifacts.pngPages.filter((page) => normalizeText(page?.path, null))
|
|
139
|
-
: [];
|
|
140
|
-
if (pngPages.length === 0) return report;
|
|
141
|
-
|
|
142
|
-
const route = toolContext?.deliveryContext || {};
|
|
143
|
-
const channel = normalizeText(route.channel, normalizeText(toolContext?.messageChannel, null));
|
|
144
|
-
const to = normalizeText(route.to, null);
|
|
145
|
-
if (!channel || !to || channel === 'claworld') {
|
|
146
|
-
return {
|
|
147
|
-
...report,
|
|
148
|
-
delivery: {
|
|
149
|
-
status: 'media_refs_ready',
|
|
150
|
-
pageCount: pngPages.length,
|
|
151
|
-
description: 'PNG pages are ready. In Management Session, copy deliveryHint.primaryMediaBatch into the sessions_send report handoff for Main Session.',
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const loadAdapter = api?.runtime?.channel?.outbound?.loadAdapter;
|
|
157
|
-
if (typeof loadAdapter !== 'function') {
|
|
158
|
-
throw new Error('transcript delivery requires the OpenClaw channel outbound runtime');
|
|
159
|
-
}
|
|
160
|
-
const adapter = await loadAdapter(channel);
|
|
161
|
-
if (typeof adapter?.sendMedia !== 'function') {
|
|
162
|
-
throw new Error(`transcript delivery is unavailable for channel ${channel}`);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const receipts = [];
|
|
166
|
-
for (const page of pngPages) {
|
|
167
|
-
const deliveryResult = await adapter.sendMedia({
|
|
168
|
-
cfg: toolContext?.getRuntimeConfig?.() || toolContext?.runtimeConfig || api.config,
|
|
169
|
-
to,
|
|
170
|
-
text: '',
|
|
171
|
-
mediaUrl: page.path,
|
|
172
|
-
...(normalizeText(route.accountId, null) ? { accountId: normalizeText(route.accountId, null) } : {}),
|
|
173
|
-
...(route.threadId != null ? { threadId: route.threadId } : {}),
|
|
174
|
-
});
|
|
175
|
-
if (deliveryResult?.success === false) {
|
|
176
|
-
throw new Error(`transcript page ${page.page} delivery failed on channel ${channel}`);
|
|
177
|
-
}
|
|
178
|
-
const deliveryKind = normalizeText(deliveryResult?.receipt?.kind, null)?.toLowerCase();
|
|
179
|
-
if (deliveryKind && !['image', 'media'].includes(deliveryKind)) {
|
|
180
|
-
throw new Error(`transcript page ${page.page} delivery did not produce native media on channel ${channel}`);
|
|
181
|
-
}
|
|
182
|
-
receipts.push({
|
|
183
|
-
page: page.page,
|
|
184
|
-
messageId: normalizeText(deliveryResult?.messageId, null),
|
|
185
|
-
kind: deliveryKind || 'media',
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
return {
|
|
189
|
-
...report,
|
|
190
|
-
delivery: {
|
|
191
|
-
status: 'sent',
|
|
192
|
-
channel,
|
|
193
|
-
pageCount: receipts.length,
|
|
194
|
-
receipts,
|
|
195
|
-
description: 'All PNG transcript pages were sent through the current user-facing channel. Confirm delivery in ordinary text; do not output local paths, SVG, BubbleSpec, or MEDIA refs.',
|
|
196
|
-
},
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
136
|
async function resolveTranscriptWorkspace(api, params = {}, toolContext = {}) {
|
|
201
137
|
const cfg = await loadCurrentConfig(api);
|
|
202
138
|
const agentId = normalizeText(
|
|
@@ -1568,15 +1504,16 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
|
|
|
1568
1504
|
{
|
|
1569
1505
|
name: renderTranscriptTool,
|
|
1570
1506
|
label: 'Claworld Render Transcript Report',
|
|
1571
|
-
description: 'Render one exact Claworld conversation episode or an agent-selected excerpt as the canonical Claworld comic-grid PNG transcript. Use mode=stored with stored.chatRequestId for a complete indexed episode. Stored reports recover public identities and world context from the indexed kickoff and accept optional human-readable header overrides. Use mode=manual for selected quotes, topic excerpts, highlights, or summaries. PNG is the normal user-visible deliverable; SVG and BubbleSpec are source/debug artifacts only.',
|
|
1507
|
+
description: 'Generate local transcript artifacts only; this tool never sends a channel message. Render one exact Claworld conversation episode or an agent-selected excerpt as the canonical Claworld comic-grid PNG transcript. Use mode=stored with stored.chatRequestId for a complete indexed episode. Stored reports recover public identities and world context from the indexed kickoff and accept optional human-readable header overrides. Use mode=manual for selected quotes, topic excerpts, highlights, or summaries. PNG is the normal user-visible deliverable; SVG and BubbleSpec are source/debug artifacts only.',
|
|
1572
1508
|
metadata: buildToolMetadata({
|
|
1573
1509
|
category: 'conversation',
|
|
1574
1510
|
usageNotes: [
|
|
1575
1511
|
'Use stored.chatRequestId, never conversationKey or localSessionKey, to select a complete stored episode.',
|
|
1576
1512
|
'Keep request, conversation, session, and agent ids out of stored title/profile/speaker-label overrides.',
|
|
1577
1513
|
'For manual mode, provide only ordered visible peer/local messages and accurate createdAt timestamps.',
|
|
1578
|
-
'
|
|
1579
|
-
'
|
|
1514
|
+
'This tool only writes local artifacts and returns absolute paths. It never sends a channel message.',
|
|
1515
|
+
'After rendering, send each artifacts.pngPages[].path with OpenClaw message(action=send, media=...).',
|
|
1516
|
+
'Management Session should hand off report text with sessions_send first, then send PNG paths to the Main Session deliveryContext with message(action=send).',
|
|
1580
1517
|
],
|
|
1581
1518
|
}),
|
|
1582
1519
|
parameters: objectParam({
|
|
@@ -1655,8 +1592,7 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
|
|
|
1655
1592
|
localAgentId: agentId,
|
|
1656
1593
|
args: params,
|
|
1657
1594
|
});
|
|
1658
|
-
|
|
1659
|
-
return buildToolResult({ ...delivered, tool: renderTranscriptTool });
|
|
1595
|
+
return buildToolResult({ ...report, tool: renderTranscriptTool });
|
|
1660
1596
|
},
|
|
1661
1597
|
},
|
|
1662
1598
|
];
|
|
@@ -829,12 +829,12 @@ function artifactPage(item) {
|
|
|
829
829
|
width: item.width,
|
|
830
830
|
height: item.height,
|
|
831
831
|
sha256: item.sha256,
|
|
832
|
-
mediaRef: item.format === 'png' ? `MEDIA:${item.path}` : null,
|
|
833
832
|
});
|
|
834
833
|
}
|
|
835
834
|
|
|
836
835
|
export async function renderTranscriptReport({ workspaceRoot, localAgentId = null, args = {} } = {}) {
|
|
837
836
|
if (!workspaceRoot) throw new Error('OpenClaw workspace root is required for transcript rendering');
|
|
837
|
+
workspaceRoot = path.resolve(workspaceRoot);
|
|
838
838
|
const request = normalizeRenderRequest(args);
|
|
839
839
|
const source = await loadSourceMessages(request, workspaceRoot);
|
|
840
840
|
const headerContext = extractTranscriptHeaderContext(source.messages);
|
|
@@ -909,16 +909,6 @@ export async function renderTranscriptReport({ workspaceRoot, localAgentId = nul
|
|
|
909
909
|
pngPages,
|
|
910
910
|
svgPages,
|
|
911
911
|
},
|
|
912
|
-
deliveryHint: {
|
|
913
|
-
primaryMedia: pngPages[0]?.mediaRef || null,
|
|
914
|
-
primaryMediaBatch: pngPages.map((item) => item.mediaRef).join('\n'),
|
|
915
|
-
sourceSvgDocument: svgPages[0] ? `[[as_document]]\nMEDIA:${svgPages[0].path}` : null,
|
|
916
|
-
reportOwnerArgs: {
|
|
917
|
-
media_path: pngPages[0]?.path || null,
|
|
918
|
-
media_paths: pngPages.map((item) => item.path),
|
|
919
|
-
send_source_svg: false,
|
|
920
|
-
},
|
|
921
|
-
},
|
|
922
912
|
diagnostics: { source: source.summary, stats },
|
|
923
913
|
});
|
|
924
914
|
await appendClaworldJournalEvent(workspaceRoot, {
|
|
@@ -202,6 +202,7 @@ export function buildClaworldContextPointer(options = {}) {
|
|
|
202
202
|
'- Select a complete episode only by exact `chatRequestId`, then call `claworld_render_transcript_report(mode=stored, stored.chatRequestId=...)`. Never substitute conversationKey or localSessionKey.',
|
|
203
203
|
'- Stored rendering recovers public identity/world/profile context from the indexed kickoff. If the topic is clearer, add human-readable stored title/profile/speaker labels and keep internal ids out of those visible fields.',
|
|
204
204
|
'- Use `mode=manual` with ordered visible messages and timestamps for requested topic excerpts, highlights, summaries, or golden quotes.',
|
|
205
|
+
'- The renderer only generates local artifacts. After it returns, send each absolute PNG path with the standard OpenClaw `message(action=send, media=...)` tool; never paste paths or `MEDIA:` pseudo-references into user-visible text.',
|
|
205
206
|
'- PNG pages are the normal deliverable. Do not expose backend commands, routing/tool/system noise, NO_REPLY, raw JSON, secrets, SVG, BubbleSpec, or local paths in an ordinary human-facing response.'
|
|
206
207
|
].join('\n');
|
|
207
208
|
}
|