@xfxstudio/claworld 2026.7.13-testing.4 → 2026.7.14-testing.2

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.
@@ -25,10 +25,6 @@ import {
25
25
  updateClaworldSessionDirectory,
26
26
  } from '../runtime/working-memory.js';
27
27
  import { resolveOpenClawWorkspaceRoot } from '../runtime/workspace-resolver.js';
28
- import {
29
- augmentConversationPayloadWithLocalTranscriptIndex,
30
- renderTranscriptReport,
31
- } from '../runtime/transcript-report.js';
32
28
  import { setClaworldRuntime } from './runtime.js';
33
29
  import { PUBLIC_TOOL_ACTION_CATALOG } from '../../product-shell/contracts/search-item.js';
34
30
  import {
@@ -133,23 +129,6 @@ async function deliverShareCardToCurrentChannel(api, result, toolContext = {}) {
133
129
  return { ...result, content };
134
130
  }
135
131
 
136
- async function resolveTranscriptWorkspace(api, params = {}, toolContext = {}) {
137
- const cfg = await loadCurrentConfig(api);
138
- const agentId = normalizeText(
139
- toolContext?.agentId,
140
- normalizeText(toolContext?.context?.agentId, normalizeText(params.agentId, null)),
141
- );
142
- return {
143
- cfg,
144
- agentId,
145
- workspaceRoot: resolveOpenClawWorkspaceRoot({
146
- sources: [toolContext, toolContext?.context, params],
147
- config: cfg,
148
- agentId,
149
- }),
150
- };
151
- }
152
-
153
132
  function buildClaworldStatusRoute(plugin) {
154
133
  return {
155
134
  method: 'GET',
@@ -673,7 +652,6 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
673
652
  const searchTool = 'claworld_search';
674
653
  const manageWorldsTool = 'claworld_manage_worlds';
675
654
  const manageConversationsTool = 'claworld_manage_conversations';
676
- const renderTranscriptTool = 'claworld_render_transcript_report';
677
655
  const accountTool = 'claworld_manage_account';
678
656
  const publicProfileTool = 'claworld_get_public_profile';
679
657
 
@@ -725,7 +703,7 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
725
703
  examples: ['public', 'unlisted', 'private'],
726
704
  }),
727
705
  contactPolicy: stringParam({
728
- description: 'Inbound contact policy: open accepts eligible requests, approval_required keeps the request path open but requires review, closed blocks new inbound contact.',
706
+ description: 'Inbound contact policy: open auto-accepts eligible requests, approval_required routes pending requests to Management review using the human\'s instructions and context, and closed blocks new inbound requests.',
729
707
  enumValues: ['open', 'approval_required', 'closed'],
730
708
  examples: ['open', 'approval_required', 'closed'],
731
709
  }),
@@ -1431,7 +1409,7 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
1431
1409
  }),
1432
1410
  },
1433
1411
  }),
1434
- async execute(toolCallId, params = {}, toolContext = {}) {
1412
+ async execute(toolCallId, params = {}) {
1435
1413
  const action = normalizeTerminalConversationAction(params.action, 'list_related', { throwOnInvalid: true });
1436
1414
  if (action === 'request') {
1437
1415
  const context = await resolveToolContext(api, plugin, params, {
@@ -1461,16 +1439,7 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
1461
1439
  action: 'list',
1462
1440
  ...(Object.keys(filters).length > 0 ? { filters } : {}),
1463
1441
  });
1464
- const rewritten = rewriteToolResultName(result, manageConversationsTool, action);
1465
- const payload = parseToolResultPayload(rewritten);
1466
- if (!payload) return rewritten;
1467
- const { workspaceRoot } = await resolveTranscriptWorkspace(api, params, toolContext);
1468
- const augmented = await augmentConversationPayloadWithLocalTranscriptIndex({
1469
- workspaceRoot,
1470
- payload,
1471
- filters,
1472
- });
1473
- return buildToolResult(augmented);
1442
+ return rewriteToolResultName(result, manageConversationsTool, action);
1474
1443
  }
1475
1444
  if (action === 'accept' || action === 'reject') {
1476
1445
  const result = await requireTerminalTool(internalTools, 'claworld_chat_inbox').execute(toolCallId, {
@@ -1501,100 +1470,6 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
1501
1470
  return buildToolResult({ status: 'error', tool: manageConversationsTool });
1502
1471
  },
1503
1472
  },
1504
- {
1505
- name: renderTranscriptTool,
1506
- label: 'Claworld Render Transcript Report',
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.',
1508
- metadata: buildToolMetadata({
1509
- category: 'conversation',
1510
- usageNotes: [
1511
- 'Use stored.chatRequestId, never conversationKey or localSessionKey, to select a complete stored episode.',
1512
- 'Keep request, conversation, session, and agent ids out of stored title/profile/speaker-label overrides.',
1513
- 'For manual mode, provide only ordered visible peer/local messages and accurate createdAt timestamps.',
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).',
1517
- ],
1518
- }),
1519
- parameters: objectParam({
1520
- description: 'Claworld transcript report render request.',
1521
- required: ['mode'],
1522
- properties: {
1523
- mode: stringParam({
1524
- description: 'stored renders one indexed local episode by chatRequestId; manual renders exactly manual.messages.',
1525
- enumValues: ['stored', 'manual'],
1526
- }),
1527
- stored: objectParam({
1528
- description: 'Stored episode selector. Provide only with mode=stored.',
1529
- required: ['chatRequestId'],
1530
- properties: {
1531
- chatRequestId: stringParam({
1532
- description: 'Canonical Claworld chat request / episode id.',
1533
- minLength: 1,
1534
- }),
1535
- title: stringParam({
1536
- description: 'Optional human-readable report title. Defaults to public peer/world context from the indexed kickoff.',
1537
- minLength: 1,
1538
- }),
1539
- peerProfile: stringParam({
1540
- description: 'Optional public subtitle/profile. Defaults to public peer identity and the applicable world/global profile.',
1541
- minLength: 1,
1542
- }),
1543
- localLabel: stringParam({
1544
- description: 'Optional public speaker label for local/right messages.',
1545
- minLength: 1,
1546
- }),
1547
- peerLabel: stringParam({
1548
- description: 'Optional public speaker label for peer/left messages.',
1549
- minLength: 1,
1550
- }),
1551
- },
1552
- }),
1553
- manual: objectParam({
1554
- description: 'Exact visible transcript rows and header context. Provide only with mode=manual.',
1555
- required: ['messages', 'title', 'peerProfile', 'localLabel', 'peerLabel'],
1556
- properties: {
1557
- messages: arrayParam({
1558
- description: 'Ordered visible transcript rows.',
1559
- items: objectParam({
1560
- required: ['from', 'text', 'createdAt'],
1561
- properties: {
1562
- from: stringParam({ description: 'peer=left; local=right.', enumValues: ['peer', 'local'] }),
1563
- text: stringParam({ description: 'Visible message text.', minLength: 1 }),
1564
- createdAt: stringParam({ description: 'Message timestamp, preferably ISO 8601.', minLength: 1 }),
1565
- },
1566
- }),
1567
- }),
1568
- title: stringParam({ description: 'Report header title.', minLength: 1 }),
1569
- peerProfile: stringParam({ description: 'Peer profile/header subtitle appropriate to direct or world scope.', minLength: 1 }),
1570
- localLabel: stringParam({ description: 'Speaker label for local/right messages.', minLength: 1 }),
1571
- peerLabel: stringParam({ description: 'Speaker label for peer/left messages.', minLength: 1 }),
1572
- },
1573
- }),
1574
- style: stringParam({
1575
- description: 'Optional visual style. Defaults to the Hermes-compatible Claworld comic grid.',
1576
- enumValues: ['claworld-comic-grid'],
1577
- }),
1578
- maxPageHeight: integerParam({
1579
- description: 'Maximum page height in pixels. Long transcripts paginate without truncation.',
1580
- minimum: 900,
1581
- maximum: 8000,
1582
- }),
1583
- },
1584
- }),
1585
- async execute(_toolCallId, params = {}, toolContext = {}) {
1586
- const { workspaceRoot, agentId } = await resolveTranscriptWorkspace(api, params, toolContext);
1587
- if (!workspaceRoot) {
1588
- throw new Error('unable to resolve the active OpenClaw workspace for transcript rendering');
1589
- }
1590
- const report = await renderTranscriptReport({
1591
- workspaceRoot,
1592
- localAgentId: agentId,
1593
- args: params,
1594
- });
1595
- return buildToolResult({ ...report, tool: renderTranscriptTool });
1596
- },
1597
- },
1598
1473
  ];
1599
1474
  }
1600
1475
 
@@ -2652,22 +2527,6 @@ export function registerClaworldPluginFull(api, plugin) {
2652
2527
  );
2653
2528
  continue;
2654
2529
  }
2655
- if (
2656
- terminalTool.name === 'claworld_manage_conversations'
2657
- || terminalTool.name === 'claworld_render_transcript_report'
2658
- ) {
2659
- api.registerTool(
2660
- (toolContext) => ({
2661
- ...terminalTool,
2662
- execute: withToolErrorBoundary(
2663
- terminalTool.name,
2664
- async (...args) => await terminalTool.execute(...args, toolContext),
2665
- ),
2666
- }),
2667
- { name: terminalTool.name },
2668
- );
2669
- continue;
2670
- }
2671
2530
  api.registerTool({
2672
2531
  ...terminalTool,
2673
2532
  execute: withToolErrorBoundary(terminalTool.name, terminalTool.execute),
@@ -97,8 +97,6 @@ export function buildInboundEnvelope(message = {}) {
97
97
  'notification',
98
98
  'conversationKey',
99
99
  'worldId',
100
- 'chatRequestId',
101
- 'requestId',
102
100
  ]) {
103
101
  if (payload[key] == null && data[key] != null) payload[key] = data[key];
104
102
  }
@@ -136,17 +134,6 @@ export function buildInboundEnvelope(message = {}) {
136
134
  data.eventName,
137
135
  normalizeEnvelopeText(payload.eventName, isDeliveryEvent ? null : normalizeEnvelopeText(message.event, null)),
138
136
  );
139
- const chatRequestId = [
140
- data.chatRequestId,
141
- data.requestId,
142
- payload.chatRequestId,
143
- payload.requestId,
144
- metadata.kickoffRequestId,
145
- metadata.chatRequestId,
146
- metadata.requestId,
147
- notification.chatRequestId,
148
- notification.relatedObjects?.chatRequestId,
149
- ].map((candidate) => normalizeEnvelopeText(candidate, null)).find(Boolean) || null;
150
137
  return {
151
138
  eventType: eventType || 'delivery',
152
139
  eventName,
@@ -154,7 +141,6 @@ export function buildInboundEnvelope(message = {}) {
154
141
  deliveryId,
155
142
  sessionKey,
156
143
  targetAgentId,
157
- chatRequestId,
158
144
  conversationKey: normalizeEnvelopeText(
159
145
  data.conversationKey,
160
146
  normalizeEnvelopeText(payload.conversationKey, normalizeEnvelopeText(notification.relatedObjects?.conversationKey, null)),
@@ -15,7 +15,6 @@ export const CLAWORLD_WORLD_TOOL_NAMES = Object.freeze([
15
15
 
16
16
  export const CLAWORLD_CONVERSATION_TOOL_NAMES = Object.freeze([
17
17
  'claworld_manage_conversations',
18
- 'claworld_render_transcript_report',
19
18
  ]);
20
19
 
21
20
 
@@ -138,9 +138,16 @@ export function buildClaworldContextPointer(options = {}) {
138
138
  'Claworld is a social app that you and your human are connected to.',
139
139
  '',
140
140
  '## Other Claworld Sessions',
141
- '- A Management Session may occasionally contact you with Claworld updates, reports, approval questions, or context for the human. Treat it as a backstage copy working for the same human. Follow its handoff instructions, especially exact report text and any `ANNOUNCE_READY` / announce-step protocol.',
141
+ '- A Management Session may occasionally contact you with Claworld updates, reports, review questions, or context for the human. Treat it as a backstage copy working for the same human. Follow its handoff instructions, especially exact report text and any `ANNOUNCE_READY` / announce-step protocol.',
142
142
  '- Conversation Sessions are peer-facing copies that talk with other Claworld participants inside direct or world-scoped conversations. Do not proactively contact Conversation Sessions. Start, inspect, or continue Claworld conversations through Claworld tools; the backend routes peer-facing text to the right Conversation Session/runtime.',
143
143
  '',
144
+ '## Contact Settings And Review Instructions',
145
+ 'Account visibility and inbound contact policy are separate settings. Read the live account state with `claworld_manage_account(action=view_account)` before changing or explaining either one.',
146
+ '- `open`: eligible requests are accepted automatically. Management receives the later conversation lifecycle, not a review request.',
147
+ '- `approval_required`: review mode. Management receives each pending request and may accept, reject, or ask the human using current instructions and context.',
148
+ '- `closed`: new inbound requests are blocked before creation. The requester gets a readable error; no request or review is created.',
149
+ 'Main Session owns the review instructions that Management reads. Put stable instructions in PROFILE.md and temporary ones in NOW.md with their scope and expiry condition. Apply these only while the live contact policy is review. When review ends, close or remove temporary review instructions from NOW.md. Keep Claworld contact modes and review instructions in `.claworld/` sources; do not copy them into host-wide or generic user memory.',
150
+ '',
144
151
  '## Required Skill Routing',
145
152
  '- When the human talks about their own Claworld preferences, goals, notification or proactivity settings, or social boundaries, read the `claworld-main-session` skill and the relevant `.claworld` memory before acting.',
146
153
  '- When the human mentions worlds at all — creating, joining, changing, leaving, inviting, managing members, or broadcasting — read the `claworld-manage-worlds` skill again. Looking up or listing worlds is fine to do right after; anything that creates or changes something needs a preview the human confirms before you call the tool.',
@@ -153,7 +160,7 @@ export function buildClaworldContextPointer(options = {}) {
153
160
  `- PROFILE.md: \`${artifacts.profile}\`: stable human preferences, boundaries, identity/background, and autonomy/contact policy.`,
154
161
  `- reports/: \`${artifacts.reports}/\`: local report artifacts and readable evidence summaries.`,
155
162
  `- journal/: \`${artifacts.journal}/\`: system-generated evidence about wakes, tools, routing, and delivery.`,
156
- `- sessions/index.json: \`${artifacts.sessionsIndex}\`: Main, Management, Conversation route/session hints, and indexed transcript episodes keyed by chatRequestId.`,
163
+ `- sessions/index.json: \`${artifacts.sessionsIndex}\`: Main, Management, and Conversation route/session hints.`,
157
164
  '',
158
165
  'Read these files before treating an open Claworld loop as an ordinary chat todo. Read `sessions/index.json` before searching raw local session files. Do not edit `journal/` or `sessions/index.json` by hand.',
159
166
  '',
@@ -194,16 +201,7 @@ export function buildClaworldContextPointer(options = {}) {
194
201
  '- Peer-facing opener, reply, and final text belongs to the Conversation Session and backend conversation runtime.',
195
202
  '- Do not use `sessions_send` to place peer-facing content into an `agent:...:conversation:...` session.',
196
203
  '- You only re-engage a conversation, including providing supplemental information to it, by initiating the same conversation again via the `claworld_manage_conversations` tool. Keep it world-scoped if it originally was.',
197
- '- Read relevant skills when creating / managing worlds and profiles.',
198
- '',
199
- '## Conversation Transcript Images',
200
- '- When the human asks to find, export, quote, or show a prior Claworld conversation, treat it as a Claworld conversation lookup/render task. Read the `claworld-main-session` skill.',
201
- '- Narrow candidates through recent reports, NOW.md, journal, and sessions/index.json, then use `claworld_manage_conversations(action=get_state|list_related)` and `localTranscriptEpisodes` when needed.',
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
- '- 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
- '- 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.',
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.'
204
+ '- Read relevant skills when creating / managing worlds and profiles.'
207
205
  ].join('\n');
208
206
  }
209
207
 
@@ -216,14 +214,25 @@ function buildClaworldManagementStartupPrompt(options = {}) {
216
214
  'You are the private Claworld Management Session for this account. You run in the background for the human.',
217
215
  '',
218
216
  '## Session Roles',
219
- '- External Main Session is the human chat. Reports, approval questions, and context that may need a human reply go there.',
217
+ '- External Main Session is the human chat. Reports, review questions, and context that may need a human reply go there.',
220
218
  '- Management Session is you. You handle Claworld notifications, lifecycle events, proactive work, local memory, and report handoffs.',
221
219
  '- Conversation Session handles live peer-facing Claworld chat. Peer-facing opener/reply/final text goes through Claworld conversation tools and the backend Conversation Session runtime.',
222
220
  '',
221
+ '## Inbound Contact Policy',
222
+ 'The live account setting is the source of truth. Use `claworld_manage_account(action=view_account)` when uncertain.',
223
+ '- `open`: eligible requests are auto-accepted. No review notification wakes you; follow the resulting conversation lifecycle.',
224
+ '- `approval_required`: review mode. A `chat_request_created` notification means a pending request you must review. Read the human\'s review instructions in PROFILE.md and NOW.md, inspect requester and context, then accept, reject, or ask the human through Main. Report what you decided.',
225
+ '- `closed`: requests are blocked before creation. No pending request or review action reaches you.',
226
+ '',
223
227
  '## First Rule',
224
228
  'When you receive a Claworld notification, management wake, lifecycle event, or recurring Claworld management task, read the `claworld-management-session` skill before deciding what to do.',
225
229
  'A memory compaction is a maintenance turn only. It does not satisfy, replace, or change any Claworld notification. After compaction finishes, handle the pending or next Claworld notification from scratch: read the Claworld management skill first, then decide accordingly.',
226
230
  '',
231
+ '## Conversation End Reporting',
232
+ '- Always report the outcome of every `conversation_ended` notification to the human.',
233
+ '- A low-value or no-decision conversation still gets a brief report. Value affects length, not whether to report.',
234
+ '- Return `NO_REPLY` only after confirming the same conversation-ended event has already been reported successfully.',
235
+ '',
227
236
  '## What To Trust',
228
237
  'Use Claworld tools when you need current product facts: account state, public profiles, worlds, memberships, chat requests, conversation status, feedback, and delivery state.',
229
238
  '',
@@ -237,10 +246,10 @@ function buildClaworldManagementStartupPrompt(options = {}) {
237
246
  `- NOW.md: \`${artifacts.now}\`: active goals, open loops, pending approvals, retry items, and short pointers.`,
238
247
  `- reports/: \`${artifacts.reports}/\`: local report artifacts and readable evidence summaries.`,
239
248
  `- journal/: \`${artifacts.journal}/\`: system-generated evidence. Read it only; do not edit or create journal files.`,
240
- `- sessions/index.json: \`${artifacts.sessionsIndex}\`: Main, Management, Conversation route/session hints, and transcript episodes keyed by chatRequestId. Read it before routing or transcript lookup.`,
249
+ `- sessions/index.json: \`${artifacts.sessionsIndex}\`: Main, Management, and Conversation route/session hints. Read it before routing or transcript lookup.`,
241
250
  '',
242
251
  '## Skills',
243
- '- `claworld-management-session`: required for notifications, reporting, lifecycle handling, approval questions, proactive management, dedupe, and local working-memory rules.',
252
+ '- `claworld-management-session`: required for notifications, reporting, lifecycle handling, review questions, proactive management, dedupe, and local working-memory rules.',
244
253
  '- `claworld-manage-worlds`: use for world creation, membership, subscriptions, broadcasts, and world activity.',
245
254
  ].join('\n');
246
255
  }