@xfxstudio/claworld 2026.7.9-testing.3 → 2026.7.13-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.
@@ -27,9 +27,7 @@ import {
27
27
  import { resolveOpenClawWorkspaceRoot } from '../runtime/workspace-resolver.js';
28
28
  import {
29
29
  augmentConversationPayloadWithLocalTranscriptIndex,
30
- CLAWORLD_TRANSCRIPT_REPORT_STYLE,
31
- CLAWORLD_TRANSCRIPT_REPORT_TOOL_NAME,
32
- renderClaworldTranscriptReport,
30
+ renderTranscriptReport,
33
31
  } from '../runtime/transcript-report.js';
34
32
  import { setClaworldRuntime } from './runtime.js';
35
33
  import { PUBLIC_TOOL_ACTION_CATALOG } from '../../product-shell/contracts/search-item.js';
@@ -63,6 +61,159 @@ import {
63
61
  withToolErrorBoundary,
64
62
  } from './register-tooling.js';
65
63
 
64
+ function resolveShareCardToolResult(result) {
65
+ if (!Array.isArray(result?.content)) return null;
66
+ for (let index = 0; index < result.content.length; index += 1) {
67
+ const entry = result.content[index];
68
+ if (entry?.type !== 'text' || typeof entry.text !== 'string') continue;
69
+ try {
70
+ const payload = JSON.parse(entry.text);
71
+ const shareCard = normalizeObject(payload?.shareCard, null);
72
+ if (normalizeText(shareCard?.status, null) !== 'ready') continue;
73
+ const mediaUrl = normalizeText(
74
+ shareCard?.imageUrl,
75
+ normalizeText(shareCard?.downloadUrl, null),
76
+ );
77
+ if (!mediaUrl) continue;
78
+ return { index, entry, payload, shareCard, mediaUrl };
79
+ } catch {
80
+ continue;
81
+ }
82
+ }
83
+ return null;
84
+ }
85
+
86
+ async function deliverShareCardToCurrentChannel(api, result, toolContext = {}) {
87
+ const resolved = resolveShareCardToolResult(result);
88
+ if (!resolved) return result;
89
+
90
+ const route = toolContext?.deliveryContext || {};
91
+ const channel = normalizeText(route.channel, normalizeText(toolContext?.messageChannel, null));
92
+ const to = normalizeText(route.to, null);
93
+ if (!channel || !to) {
94
+ throw new Error('share-card delivery requires an active channel route');
95
+ }
96
+
97
+ const loadAdapter = api?.runtime?.channel?.outbound?.loadAdapter;
98
+ if (typeof loadAdapter !== 'function') {
99
+ throw new Error('share-card delivery requires the OpenClaw channel outbound runtime');
100
+ }
101
+ const adapter = await loadAdapter(channel);
102
+ if (typeof adapter?.sendMedia !== 'function') {
103
+ throw new Error(`share-card delivery is unavailable for channel ${channel}`);
104
+ }
105
+
106
+ const deliveryResult = await adapter.sendMedia({
107
+ cfg: toolContext?.getRuntimeConfig?.() || toolContext?.runtimeConfig || api.config,
108
+ to,
109
+ text: '',
110
+ mediaUrl: resolved.mediaUrl,
111
+ ...(normalizeText(route.accountId, null) ? { accountId: normalizeText(route.accountId, null) } : {}),
112
+ ...(route.threadId != null ? { threadId: route.threadId } : {}),
113
+ });
114
+ if (deliveryResult?.success === false) {
115
+ throw new Error(`share-card delivery failed on channel ${channel}`);
116
+ }
117
+ const deliveryKind = normalizeText(deliveryResult?.receipt?.kind, null)?.toLowerCase();
118
+ if (deliveryKind && !['image', 'media'].includes(deliveryKind)) {
119
+ throw new Error(`share-card delivery did not produce native media on channel ${channel}`);
120
+ }
121
+
122
+ const content = [...result.content];
123
+ content[resolved.index] = {
124
+ ...resolved.entry,
125
+ text: JSON.stringify({
126
+ ...resolved.payload,
127
+ shareCard: {
128
+ ...resolved.shareCard,
129
+ description: '分享卡图片已通过当前聊天渠道发送给用户。请只用一句普通文本确认分享卡已生成;不要下载、再次发送或输出 MEDIA:。',
130
+ },
131
+ }, null, 2),
132
+ };
133
+ return { ...result, content };
134
+ }
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
+ async function resolveTranscriptWorkspace(api, params = {}, toolContext = {}) {
201
+ const cfg = await loadCurrentConfig(api);
202
+ const agentId = normalizeText(
203
+ toolContext?.agentId,
204
+ normalizeText(toolContext?.context?.agentId, normalizeText(params.agentId, null)),
205
+ );
206
+ return {
207
+ cfg,
208
+ agentId,
209
+ workspaceRoot: resolveOpenClawWorkspaceRoot({
210
+ sources: [toolContext, toolContext?.context, params],
211
+ config: cfg,
212
+ agentId,
213
+ }),
214
+ };
215
+ }
216
+
66
217
  function buildClaworldStatusRoute(plugin) {
67
218
  return {
68
219
  method: 'GET',
@@ -481,118 +632,6 @@ function buildChatInboxFiltersParam({ description, worldIdProperty } = {}) {
481
632
  });
482
633
  }
483
634
 
484
- function buildTranscriptReportParameters() {
485
- return objectParam({
486
- description: 'Render a Claworld transcript into BubbleSpec, SVG pages, and PNG pages.',
487
- required: ['mode'],
488
- additionalProperties: false,
489
- properties: {
490
- mode: stringParam({
491
- description: 'Render source mode. Use stored for local OpenClaw conversation transcripts and manual for supplied excerpts.',
492
- enumValues: ['stored', 'manual'],
493
- examples: ['stored'],
494
- }),
495
- stored: objectParam({
496
- description: 'Local OpenClaw transcript source resolved through .claworld/sessions/index.json.',
497
- required: ['chatRequestId'],
498
- additionalProperties: false,
499
- properties: {
500
- chatRequestId: stringParam({
501
- description: 'Canonical Claworld chat request id to render from the local Conversation Session transcript index.',
502
- minLength: 1,
503
- examples: ['req_demo_1'],
504
- }),
505
- },
506
- }),
507
- manual: objectParam({
508
- description: 'Explicit transcript excerpt fallback. Use only when the exact conversation is not available in local storage.',
509
- required: ['messages', 'title', 'peerProfile', 'localLabel', 'peerLabel'],
510
- additionalProperties: false,
511
- properties: {
512
- messages: arrayParam({
513
- description: 'Ordered peer/local transcript messages.',
514
- items: objectParam({
515
- required: ['from', 'text', 'createdAt'],
516
- additionalProperties: false,
517
- properties: {
518
- from: stringParam({
519
- description: 'Speaker side from the owner account perspective.',
520
- enumValues: ['peer', 'local'],
521
- examples: ['peer'],
522
- }),
523
- text: stringParam({ description: 'Message text to render.', minLength: 1 }),
524
- createdAt: stringParam({ description: 'Parseable timestamp for this message.', minLength: 1 }),
525
- },
526
- }),
527
- }),
528
- title: stringParam({ description: 'Report title.', minLength: 1 }),
529
- peerProfile: stringParam({ description: 'Peer/profile subtitle shown under the report title.', minLength: 1 }),
530
- localLabel: stringParam({ description: 'Label for the local side.', minLength: 1 }),
531
- peerLabel: stringParam({ description: 'Label for the peer side.', minLength: 1 }),
532
- },
533
- }),
534
- style: stringParam({
535
- description: 'Transcript rendering style.',
536
- enumValues: [CLAWORLD_TRANSCRIPT_REPORT_STYLE],
537
- examples: [CLAWORLD_TRANSCRIPT_REPORT_STYLE],
538
- }),
539
- maxPageHeight: integerParam({
540
- description: 'Maximum SVG/PNG page height before pagination.',
541
- minimum: 900,
542
- maximum: 8000,
543
- examples: [2600],
544
- }),
545
- },
546
- });
547
- }
548
-
549
- async function resolveLocalWorkspaceRootForTool(api, _plugin, params = {}) {
550
- const cfg = await loadCurrentConfig(api);
551
- const agentId = resolveToolAgentId(params, null);
552
- return {
553
- agentId,
554
- workspaceRoot: resolveOpenClawWorkspaceRoot({
555
- sources: [params],
556
- config: cfg,
557
- agentId,
558
- }) || process.cwd(),
559
- };
560
- }
561
-
562
- async function augmentConversationToolResultWithTranscripts(api, plugin, params, filters, result, toolName, action) {
563
- const rewritten = rewriteToolResultName(result, toolName, action);
564
- const payload = parseToolResultPayload(rewritten);
565
- if (!payload || typeof payload !== 'object' || Array.isArray(payload)) return rewritten;
566
- const { workspaceRoot } = await resolveLocalWorkspaceRootForTool(api, plugin, params);
567
- const augmentedPayload = await augmentConversationPayloadWithLocalTranscriptIndex(payload, {
568
- workspaceRoot,
569
- filters,
570
- });
571
- return buildToolResult({
572
- ...augmentedPayload,
573
- tool: toolName,
574
- action,
575
- });
576
- }
577
-
578
- function stripTranscriptReportToolContextParams(params = {}) {
579
- const contextFields = new Set([
580
- 'workspaceRoot',
581
- 'workspaceDir',
582
- 'workspacePath',
583
- 'workspace',
584
- 'cwd',
585
- 'agent',
586
- 'context',
587
- 'session',
588
- 'agentId',
589
- 'localAgentId',
590
- ]);
591
- return Object.fromEntries(
592
- Object.entries(params || {}).filter(([key]) => !contextFields.has(key)),
593
- );
594
- }
595
-
596
635
  function validateChatInboxFilterInput(filters = {}, action) {
597
636
  const source = normalizeObject(filters, {}) || {};
598
637
  for (const key of Object.keys(source)) {
@@ -698,7 +737,7 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
698
737
  const searchTool = 'claworld_search';
699
738
  const manageWorldsTool = 'claworld_manage_worlds';
700
739
  const manageConversationsTool = 'claworld_manage_conversations';
701
- const transcriptReportTool = CLAWORLD_TRANSCRIPT_REPORT_TOOL_NAME;
740
+ const renderTranscriptTool = 'claworld_render_transcript_report';
702
741
  const accountTool = 'claworld_manage_account';
703
742
  const publicProfileTool = 'claworld_get_public_profile';
704
743
 
@@ -1456,7 +1495,7 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
1456
1495
  }),
1457
1496
  },
1458
1497
  }),
1459
- async execute(toolCallId, params = {}) {
1498
+ async execute(toolCallId, params = {}, toolContext = {}) {
1460
1499
  const action = normalizeTerminalConversationAction(params.action, 'list_related', { throwOnInvalid: true });
1461
1500
  if (action === 'request') {
1462
1501
  const context = await resolveToolContext(api, plugin, params, {
@@ -1486,15 +1525,16 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
1486
1525
  action: 'list',
1487
1526
  ...(Object.keys(filters).length > 0 ? { filters } : {}),
1488
1527
  });
1489
- return augmentConversationToolResultWithTranscripts(
1490
- api,
1491
- plugin,
1492
- params,
1528
+ const rewritten = rewriteToolResultName(result, manageConversationsTool, action);
1529
+ const payload = parseToolResultPayload(rewritten);
1530
+ if (!payload) return rewritten;
1531
+ const { workspaceRoot } = await resolveTranscriptWorkspace(api, params, toolContext);
1532
+ const augmented = await augmentConversationPayloadWithLocalTranscriptIndex({
1533
+ workspaceRoot,
1534
+ payload,
1493
1535
  filters,
1494
- result,
1495
- manageConversationsTool,
1496
- action,
1497
- );
1536
+ });
1537
+ return buildToolResult(augmented);
1498
1538
  }
1499
1539
  if (action === 'accept' || action === 'reject') {
1500
1540
  const result = await requireTerminalTool(internalTools, 'claworld_chat_inbox').execute(toolCallId, {
@@ -1526,30 +1566,97 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
1526
1566
  },
1527
1567
  },
1528
1568
  {
1529
- name: transcriptReportTool,
1569
+ name: renderTranscriptTool,
1530
1570
  label: 'Claworld Render Transcript Report',
1531
- description: 'Render a local Claworld conversation transcript into BubbleSpec, SVG pages, and PNG pages. Prefer mode=stored with a chatRequestId from claworld_manage_conversations or .claworld/sessions/index.json; use manual mode only for selected excerpts or fallback rendering.',
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.',
1532
1572
  metadata: buildToolMetadata({
1533
- category: 'transcript_report',
1573
+ category: 'conversation',
1534
1574
  usageNotes: [
1535
- 'Use mode=stored when the exact chatRequestId is known and the local Conversation Session transcript has been indexed.',
1536
- 'Use mode=manual only when the human asks for a selected excerpt or the stored transcript is unavailable.',
1537
- 'Use deliveryHint.messageTool or deliveryHint.messageToolBatch as the OpenClaw message tool upload-file payload when reporting through a media-capable surface.',
1538
- 'Do not paste raw transcript text to the human when this report rendering tool can produce the visual artifact.',
1575
+ 'Use stored.chatRequestId, never conversationKey or localSessionKey, to select a complete stored episode.',
1576
+ 'Keep request, conversation, session, and agent ids out of stored title/profile/speaker-label overrides.',
1577
+ 'For manual mode, provide only ordered visible peer/local messages and accurate createdAt timestamps.',
1578
+ 'Main Session calls send all PNG pages through the current user-facing channel when available.',
1579
+ 'Management Session calls return deliveryHint.primaryMediaBatch for inclusion in the sessions_send report handoff.',
1539
1580
  ],
1540
1581
  }),
1541
- parameters: buildTranscriptReportParameters(),
1542
- async execute(_toolCallId, params = {}) {
1543
- const { workspaceRoot, agentId } = await resolveLocalWorkspaceRootForTool(api, plugin, params);
1544
- const payload = await renderClaworldTranscriptReport({
1582
+ parameters: objectParam({
1583
+ description: 'Claworld transcript report render request.',
1584
+ required: ['mode'],
1585
+ properties: {
1586
+ mode: stringParam({
1587
+ description: 'stored renders one indexed local episode by chatRequestId; manual renders exactly manual.messages.',
1588
+ enumValues: ['stored', 'manual'],
1589
+ }),
1590
+ stored: objectParam({
1591
+ description: 'Stored episode selector. Provide only with mode=stored.',
1592
+ required: ['chatRequestId'],
1593
+ properties: {
1594
+ chatRequestId: stringParam({
1595
+ description: 'Canonical Claworld chat request / episode id.',
1596
+ minLength: 1,
1597
+ }),
1598
+ title: stringParam({
1599
+ description: 'Optional human-readable report title. Defaults to public peer/world context from the indexed kickoff.',
1600
+ minLength: 1,
1601
+ }),
1602
+ peerProfile: stringParam({
1603
+ description: 'Optional public subtitle/profile. Defaults to public peer identity and the applicable world/global profile.',
1604
+ minLength: 1,
1605
+ }),
1606
+ localLabel: stringParam({
1607
+ description: 'Optional public speaker label for local/right messages.',
1608
+ minLength: 1,
1609
+ }),
1610
+ peerLabel: stringParam({
1611
+ description: 'Optional public speaker label for peer/left messages.',
1612
+ minLength: 1,
1613
+ }),
1614
+ },
1615
+ }),
1616
+ manual: objectParam({
1617
+ description: 'Exact visible transcript rows and header context. Provide only with mode=manual.',
1618
+ required: ['messages', 'title', 'peerProfile', 'localLabel', 'peerLabel'],
1619
+ properties: {
1620
+ messages: arrayParam({
1621
+ description: 'Ordered visible transcript rows.',
1622
+ items: objectParam({
1623
+ required: ['from', 'text', 'createdAt'],
1624
+ properties: {
1625
+ from: stringParam({ description: 'peer=left; local=right.', enumValues: ['peer', 'local'] }),
1626
+ text: stringParam({ description: 'Visible message text.', minLength: 1 }),
1627
+ createdAt: stringParam({ description: 'Message timestamp, preferably ISO 8601.', minLength: 1 }),
1628
+ },
1629
+ }),
1630
+ }),
1631
+ title: stringParam({ description: 'Report header title.', minLength: 1 }),
1632
+ peerProfile: stringParam({ description: 'Peer profile/header subtitle appropriate to direct or world scope.', minLength: 1 }),
1633
+ localLabel: stringParam({ description: 'Speaker label for local/right messages.', minLength: 1 }),
1634
+ peerLabel: stringParam({ description: 'Speaker label for peer/left messages.', minLength: 1 }),
1635
+ },
1636
+ }),
1637
+ style: stringParam({
1638
+ description: 'Optional visual style. Defaults to the Hermes-compatible Claworld comic grid.',
1639
+ enumValues: ['claworld-comic-grid'],
1640
+ }),
1641
+ maxPageHeight: integerParam({
1642
+ description: 'Maximum page height in pixels. Long transcripts paginate without truncation.',
1643
+ minimum: 900,
1644
+ maximum: 8000,
1645
+ }),
1646
+ },
1647
+ }),
1648
+ async execute(_toolCallId, params = {}, toolContext = {}) {
1649
+ const { workspaceRoot, agentId } = await resolveTranscriptWorkspace(api, params, toolContext);
1650
+ if (!workspaceRoot) {
1651
+ throw new Error('unable to resolve the active OpenClaw workspace for transcript rendering');
1652
+ }
1653
+ const report = await renderTranscriptReport({
1545
1654
  workspaceRoot,
1546
- agentId,
1547
- args: stripTranscriptReportToolContextParams(params),
1548
- });
1549
- return buildToolResult({
1550
- ...payload,
1551
- tool: transcriptReportTool,
1655
+ localAgentId: agentId,
1656
+ args: params,
1552
1657
  });
1658
+ const delivered = await deliverTranscriptPagesToCurrentChannel(api, report, toolContext);
1659
+ return buildToolResult({ ...delivered, tool: renderTranscriptTool });
1553
1660
  },
1554
1661
  },
1555
1662
  ];
@@ -2595,11 +2702,40 @@ export function registerClaworldPluginFull(api, plugin) {
2595
2702
  const internalTools = new Map(
2596
2703
  buildRegisteredTools(api, plugin).map((tool) => [tool.name, tool]),
2597
2704
  );
2598
- for (const tool of createTerminalToolAdapters(api, plugin, internalTools).map((terminalTool) => ({
2599
- ...terminalTool,
2600
- execute: withToolErrorBoundary(terminalTool.name, terminalTool.execute),
2601
- }))) {
2602
- api.registerTool(tool);
2705
+ for (const terminalTool of createTerminalToolAdapters(api, plugin, internalTools)) {
2706
+ if (terminalTool.name === 'claworld_manage_account') {
2707
+ api.registerTool(
2708
+ (toolContext) => ({
2709
+ ...terminalTool,
2710
+ execute: withToolErrorBoundary(terminalTool.name, async (...args) => {
2711
+ const result = await terminalTool.execute(...args);
2712
+ return await deliverShareCardToCurrentChannel(api, result, toolContext);
2713
+ }),
2714
+ }),
2715
+ { name: terminalTool.name },
2716
+ );
2717
+ continue;
2718
+ }
2719
+ if (
2720
+ terminalTool.name === 'claworld_manage_conversations'
2721
+ || terminalTool.name === 'claworld_render_transcript_report'
2722
+ ) {
2723
+ api.registerTool(
2724
+ (toolContext) => ({
2725
+ ...terminalTool,
2726
+ execute: withToolErrorBoundary(
2727
+ terminalTool.name,
2728
+ async (...args) => await terminalTool.execute(...args, toolContext),
2729
+ ),
2730
+ }),
2731
+ { name: terminalTool.name },
2732
+ );
2733
+ continue;
2734
+ }
2735
+ api.registerTool({
2736
+ ...terminalTool,
2737
+ execute: withToolErrorBoundary(terminalTool.name, terminalTool.execute),
2738
+ });
2603
2739
  }
2604
2740
  }
2605
2741
  return plugin;
@@ -97,6 +97,8 @@ export function buildInboundEnvelope(message = {}) {
97
97
  'notification',
98
98
  'conversationKey',
99
99
  'worldId',
100
+ 'chatRequestId',
101
+ 'requestId',
100
102
  ]) {
101
103
  if (payload[key] == null && data[key] != null) payload[key] = data[key];
102
104
  }
@@ -134,6 +136,17 @@ export function buildInboundEnvelope(message = {}) {
134
136
  data.eventName,
135
137
  normalizeEnvelopeText(payload.eventName, isDeliveryEvent ? null : normalizeEnvelopeText(message.event, null)),
136
138
  );
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;
137
150
  return {
138
151
  eventType: eventType || 'delivery',
139
152
  eventName,
@@ -141,6 +154,7 @@ export function buildInboundEnvelope(message = {}) {
141
154
  deliveryId,
142
155
  sessionKey,
143
156
  targetAgentId,
157
+ chatRequestId,
144
158
  conversationKey: normalizeEnvelopeText(
145
159
  data.conversationKey,
146
160
  normalizeEnvelopeText(payload.conversationKey, normalizeEnvelopeText(notification.relatedObjects?.conversationKey, null)),
@@ -15,18 +15,15 @@ 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
- ]);
19
-
20
- export const CLAWORLD_TRANSCRIPT_TOOL_NAMES = Object.freeze([
21
18
  'claworld_render_transcript_report',
22
19
  ]);
23
20
 
21
+
24
22
  export const CLAWORLD_REGISTERED_TOOL_NAMES = Object.freeze([
25
23
  ...CLAWORLD_ACCOUNT_TOOL_NAMES,
26
24
  ...CLAWORLD_SEARCH_TOOL_NAMES,
27
25
  ...CLAWORLD_WORLD_TOOL_NAMES,
28
26
  ...CLAWORLD_CONVERSATION_TOOL_NAMES,
29
- ...CLAWORLD_TRANSCRIPT_TOOL_NAMES,
30
27
  ]);
31
28
 
32
29
  export const CLAWORLD_PUBLIC_TOOL_NAMES = Object.freeze([