clawconnect-agent 0.1.9 → 0.1.11

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.
Files changed (44) hide show
  1. package/dist/commands/send-file.d.ts +1 -0
  2. package/dist/commands/send-file.js +46 -2
  3. package/dist/commands/send-file.js.map +1 -1
  4. package/dist/core/relay/mobile-chat-run-bridge.d.ts +13 -8
  5. package/dist/core/relay/mobile-chat-run-bridge.js +11 -2
  6. package/dist/core/relay/mobile-chat-run-bridge.js.map +1 -1
  7. package/dist/core/relay/timeline-event-builder.d.ts +1 -0
  8. package/dist/core/relay/timeline-event-builder.js +1 -0
  9. package/dist/core/relay/timeline-event-builder.js.map +1 -1
  10. package/dist/core/relay/timeline-event-log.d.ts +5 -0
  11. package/dist/core/relay/timeline-event-log.js +7 -0
  12. package/dist/core/relay/timeline-event-log.js.map +1 -1
  13. package/dist/hermes/hermes-relay-manager.d.ts +3 -1
  14. package/dist/hermes/hermes-relay-manager.js +93 -56
  15. package/dist/hermes/hermes-relay-manager.js.map +1 -1
  16. package/dist/hermes/runtime/hermes-runtime-artifacts.js +21 -11
  17. package/dist/hermes/runtime/hermes-runtime-artifacts.js.map +1 -1
  18. package/dist/hermes/runtime/hermes-runtime-chat.d.ts +1 -1
  19. package/dist/hermes/runtime/hermes-runtime-chat.js +305 -62
  20. package/dist/hermes/runtime/hermes-runtime-chat.js.map +1 -1
  21. package/dist/hermes/runtime/hermes-runtime-history.d.ts +1 -0
  22. package/dist/hermes/runtime/hermes-runtime-history.js +171 -9
  23. package/dist/hermes/runtime/hermes-runtime-history.js.map +1 -1
  24. package/dist/hermes/runtime/hermes-runtime-models.js +54 -8
  25. package/dist/hermes/runtime/hermes-runtime-models.js.map +1 -1
  26. package/dist/hermes/runtime/hermes-runtime-usage.d.ts +1 -0
  27. package/dist/hermes/runtime/hermes-runtime-usage.js +55 -18
  28. package/dist/hermes/runtime/hermes-runtime-usage.js.map +1 -1
  29. package/dist/hermes/runtime/hermes-runtime-values.js +23 -1
  30. package/dist/hermes/runtime/hermes-runtime-values.js.map +1 -1
  31. package/dist/index.js +2 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/openclaw/relay/chat-history.d.ts +4 -0
  34. package/dist/openclaw/relay/chat-history.js +171 -0
  35. package/dist/openclaw/relay/chat-history.js.map +1 -1
  36. package/dist/openclaw/relay/outgoing-media-relay.d.ts +1 -0
  37. package/dist/openclaw/relay/outgoing-media-relay.js +271 -9
  38. package/dist/openclaw/relay/outgoing-media-relay.js.map +1 -1
  39. package/dist/openclaw/relay-manager.js +179 -13
  40. package/dist/openclaw/relay-manager.js.map +1 -1
  41. package/dist/openclaw/session-store.d.ts +5 -0
  42. package/dist/openclaw/session-store.js +121 -1
  43. package/dist/openclaw/session-store.js.map +1 -1
  44. package/package.json +1 -1
@@ -1,8 +1,10 @@
1
+ import { existsSync } from "fs";
1
2
  import { readFile } from "fs/promises";
2
3
  import { homedir } from "os";
3
- import { join } from "path";
4
+ import { extname, join, resolve } from "path";
4
5
  import { uploadFileToRelay } from "../../core/relay/file-upload.js";
5
6
  const OUTGOING_MEDIA_RE = /\/api\/chat\/media\/outgoing\/[^/]+\/([^/]+)\/full(?:$|[?#])/;
7
+ const OPENCLAW_MEDIA_CONTROL_PREFIX_RE = /^MEDIA:\s*(?:file:\/\/|~\/|\/)/i;
6
8
  export async function relayOutgoingMediaInPayload(payload, opts) {
7
9
  if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
8
10
  return payload;
@@ -12,23 +14,39 @@ export async function relayOutgoingMediaInPayload(payload, opts) {
12
14
  return payload;
13
15
  }
14
16
  const content = message.content;
17
+ if (typeof content === "string") {
18
+ const sanitizedText = stripOpenClawMediaControlLines(content);
19
+ return sanitizedText === content
20
+ ? payload
21
+ : {
22
+ ...payload,
23
+ message: {
24
+ ...message,
25
+ content: sanitizedText,
26
+ },
27
+ };
28
+ }
15
29
  if (!Array.isArray(content)) {
16
30
  return payload;
17
31
  }
18
32
  let changed = false;
19
- const nextContent = await Promise.all(content.map(async (block) => {
20
- const nextBlock = await relayOutgoingMediaBlock(block, opts);
33
+ const sourceRunId = payloadSourceRunId(payload);
34
+ const relayedContent = await Promise.all(content.map(async (block) => {
35
+ const nextBlock = await relayOutgoingMediaBlock(block, { ...opts, sourceRunId });
21
36
  changed ||= nextBlock !== block;
22
37
  return nextBlock;
23
38
  }));
24
- if (!changed) {
39
+ const sanitizedContent = sanitizeOpenClawMediaControlBlocks(relayedContent);
40
+ changed ||= sanitizedContent.changed;
41
+ const localArtifactBlocks = await relayLocalArtifactPathsInContent(sanitizedContent.content, payload, opts);
42
+ if (!changed && localArtifactBlocks.length === 0) {
25
43
  return payload;
26
44
  }
27
45
  return {
28
46
  ...payload,
29
47
  message: {
30
48
  ...message,
31
- content: nextContent,
49
+ content: [...sanitizedContent.content, ...localArtifactBlocks],
32
50
  },
33
51
  };
34
52
  }
@@ -40,16 +58,42 @@ export async function relayOutgoingMediaInHistoryResponse(response, opts) {
40
58
  if (!Array.isArray(messages)) {
41
59
  return response;
42
60
  }
61
+ const responseRecord = response;
62
+ const responseSessionKey = firstString(responseRecord.sessionKey, responseRecord.sessionId);
63
+ const messageResult = await relayOutgoingMediaInMessageList(messages, responseSessionKey, opts);
64
+ const snapshot = responseRecord.timelineSnapshot;
65
+ const snapshotMessages = snapshot && typeof snapshot === "object" && !Array.isArray(snapshot)
66
+ ? snapshot.messages
67
+ : undefined;
68
+ const snapshotResult = Array.isArray(snapshotMessages)
69
+ ? await relayOutgoingMediaInMessageList(snapshotMessages, responseSessionKey, opts)
70
+ : undefined;
71
+ const changed = messageResult.changed || Boolean(snapshotResult?.changed);
72
+ return changed
73
+ ? {
74
+ ...responseRecord,
75
+ messages: messageResult.messages,
76
+ ...(snapshotResult
77
+ ? {
78
+ timelineSnapshot: {
79
+ ...snapshot,
80
+ messages: snapshotResult.messages,
81
+ },
82
+ }
83
+ : {}),
84
+ }
85
+ : response;
86
+ }
87
+ async function relayOutgoingMediaInMessageList(messages, sessionKey, opts) {
43
88
  let changed = false;
44
89
  const nextMessages = await Promise.all(messages.map(async (message) => {
45
- const wrapper = await relayOutgoingMediaInPayload({ message }, opts);
90
+ const wrapperInput = sessionKey ? { sessionKey, message } : { message };
91
+ const wrapper = await relayOutgoingMediaInPayload(wrapperInput, opts);
46
92
  const nextMessage = wrapper.message ?? message;
47
93
  changed ||= nextMessage !== message;
48
94
  return nextMessage;
49
95
  }));
50
- return changed
51
- ? { ...response, messages: nextMessages }
52
- : response;
96
+ return { messages: nextMessages, changed };
53
97
  }
54
98
  async function relayOutgoingMediaBlock(block, opts) {
55
99
  if (!block || typeof block !== "object" || Array.isArray(block)) {
@@ -78,23 +122,30 @@ async function relayOutgoingMediaBlock(block, opts) {
78
122
  sessionKey,
79
123
  filePath,
80
124
  senderDisplayName: opts.senderDisplayName,
125
+ sourceRunId: opts.sourceRunId,
81
126
  });
82
127
  opts.cache?.set(cacheKey, upload);
83
128
  }
84
129
  return {
85
130
  ...source,
86
131
  type: typeof source.type === "string" && source.type.trim() ? source.type : "image",
132
+ attachmentId,
87
133
  fileId: upload.fileId,
88
134
  fileName: record.alt || upload.fileName,
89
135
  mimeType: record.original?.contentType || upload.mimeType,
136
+ byteSize: record.original?.sizeBytes || upload.sizeBytes,
90
137
  sizeBytes: record.original?.sizeBytes || upload.sizeBytes,
138
+ width: record.original?.width || upload.imageWidth,
139
+ height: record.original?.height || upload.imageHeight,
91
140
  imageWidth: record.original?.width || upload.imageWidth,
92
141
  imageHeight: record.original?.height || upload.imageHeight,
93
142
  downloadUrl: upload.downloadPath,
94
143
  downloadPath: upload.downloadPath,
95
144
  expiresAt: upload.expiresAt,
145
+ sourceRunId: upload.sourceRunId,
96
146
  gatewayId: upload.gatewayId,
97
147
  sessionKey: upload.sessionKey,
148
+ transferState: "available",
98
149
  };
99
150
  }
100
151
  catch (error) {
@@ -109,6 +160,13 @@ function outgoingAttachmentId(url) {
109
160
  const match = OUTGOING_MEDIA_RE.exec(url);
110
161
  return match?.[1]?.trim() || undefined;
111
162
  }
163
+ function payloadSourceRunId(payload) {
164
+ const message = payload.message;
165
+ const messageRecord = message && typeof message === "object" && !Array.isArray(message)
166
+ ? message
167
+ : undefined;
168
+ return firstString(payload.sourceRunId, payload.source_run_id, payload.runId, payload.turnId, payload.messageId, payload.id, messageRecord?.sourceRunId, messageRecord?.source_run_id, messageRecord?.runId, messageRecord?.turnId, messageRecord?.messageId, messageRecord?.id);
169
+ }
112
170
  async function readOutgoingMediaRecord(attachmentId, recordsDir) {
113
171
  const root = recordsDir ?? join(homedir(), ".openclaw", "media", "outgoing", "records");
114
172
  const raw = await readFile(join(root, `${attachmentId}.json`), "utf8");
@@ -117,4 +175,208 @@ async function readOutgoingMediaRecord(attachmentId, recordsDir) {
117
175
  function firstString(...values) {
118
176
  return values.find((value) => typeof value === "string" && value.trim().length > 0)?.trim();
119
177
  }
178
+ async function relayLocalArtifactPathsInContent(content, payload, opts) {
179
+ if (opts.userMessage === undefined) {
180
+ return [];
181
+ }
182
+ if (content.some(isUploadedMediaBlock)) {
183
+ return [];
184
+ }
185
+ const text = content
186
+ .map((block) => {
187
+ if (!block || typeof block !== "object" || Array.isArray(block)) {
188
+ return "";
189
+ }
190
+ const record = block;
191
+ return record.type === "text" && typeof record.text === "string" ? record.text : "";
192
+ })
193
+ .filter(Boolean)
194
+ .join("\n");
195
+ const paths = extractDeliverablePaths(text, opts.userMessage);
196
+ if (paths.length === 0) {
197
+ return [];
198
+ }
199
+ const sessionKey = firstString(payload.sessionKey, payload.message?.sessionKey) ?? "main";
200
+ const runId = payloadSourceRunId(payload);
201
+ const blocks = [];
202
+ for (const filePath of paths) {
203
+ try {
204
+ const cacheKey = `${opts.gatewayId}:${sessionKey}:artifact:${filePath}`;
205
+ let upload = opts.cache?.get(cacheKey);
206
+ if (!upload) {
207
+ const request = {
208
+ relayServerUrl: opts.relayServerUrl,
209
+ relaySecret: opts.relaySecret,
210
+ gatewayId: opts.gatewayId,
211
+ sessionKey,
212
+ filePath,
213
+ senderDisplayName: opts.senderDisplayName,
214
+ sourceRunId: runId,
215
+ };
216
+ upload = await uploadFileToRelay(request);
217
+ opts.cache?.set(cacheKey, upload);
218
+ }
219
+ blocks.push(uploadToContentBlock(upload));
220
+ }
221
+ catch (error) {
222
+ console.warn(`[relay] failed to publish local artifact ${filePath}: ${String(error)}`);
223
+ }
224
+ }
225
+ return blocks;
226
+ }
227
+ function isUploadedMediaBlock(block) {
228
+ if (!block || typeof block !== "object" || Array.isArray(block)) {
229
+ return false;
230
+ }
231
+ const record = block;
232
+ const type = typeof record.type === "string" ? record.type.trim().toLowerCase() : "";
233
+ return ["image", "file", "voice", "audio"].includes(type) && typeof record.fileId === "string" && record.fileId.trim().length > 0;
234
+ }
235
+ function uploadToContentBlock(upload) {
236
+ const type = upload.mimeType.startsWith("image/")
237
+ ? "image"
238
+ : upload.mimeType.startsWith("audio/")
239
+ ? "audio"
240
+ : "file";
241
+ return compact({
242
+ type,
243
+ attachmentId: upload.fileId,
244
+ fileId: upload.fileId,
245
+ fileName: upload.fileName,
246
+ name: upload.fileName,
247
+ mimeType: upload.mimeType,
248
+ byteSize: upload.sizeBytes,
249
+ sizeBytes: upload.sizeBytes,
250
+ durationMs: upload.durationMs,
251
+ width: upload.imageWidth,
252
+ height: upload.imageHeight,
253
+ imageWidth: upload.imageWidth,
254
+ imageHeight: upload.imageHeight,
255
+ downloadUrl: upload.downloadPath,
256
+ downloadPath: upload.downloadPath,
257
+ expiresAt: upload.expiresAt,
258
+ sourceRunId: upload.sourceRunId,
259
+ gatewayId: upload.gatewayId,
260
+ sessionKey: upload.sessionKey,
261
+ status: "available",
262
+ transferState: "available",
263
+ });
264
+ }
265
+ function sanitizeOpenClawMediaControlBlocks(content) {
266
+ let changed = false;
267
+ const nextContent = [];
268
+ for (const block of content) {
269
+ if (!block || typeof block !== "object" || Array.isArray(block)) {
270
+ nextContent.push(block);
271
+ continue;
272
+ }
273
+ const record = block;
274
+ if (record.type !== "text" || typeof record.text !== "string") {
275
+ nextContent.push(block);
276
+ continue;
277
+ }
278
+ const text = record.text;
279
+ const sanitizedText = stripOpenClawMediaControlLines(text);
280
+ if (sanitizedText === text) {
281
+ nextContent.push(block);
282
+ continue;
283
+ }
284
+ changed = true;
285
+ // OpenClaw 的 MEDIA:/... 是内部桥接标记,不能显示成聊天文本,也不能从历史回放再次触发本地路径上传。
286
+ if (!sanitizedText.trim()) {
287
+ continue;
288
+ }
289
+ nextContent.push({ ...record, text: sanitizedText });
290
+ }
291
+ return { content: nextContent, changed };
292
+ }
293
+ function stripOpenClawMediaControlLines(text) {
294
+ if (!text.includes("MEDIA:")) {
295
+ return text;
296
+ }
297
+ const normalized = text
298
+ .replace(/\r\n/g, "\n")
299
+ .replace(/\r/g, "\n");
300
+ const stripped = normalized
301
+ .split("\n")
302
+ .filter((line) => !OPENCLAW_MEDIA_CONTROL_PREFIX_RE.test(line.trim()))
303
+ .join("\n")
304
+ .replace(/\n{3,}/g, "\n\n")
305
+ .trim();
306
+ return stripped;
307
+ }
308
+ function compact(record) {
309
+ return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));
310
+ }
311
+ const DELIVERABLE_EXTENSIONS = [
312
+ ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".tiff", ".svg",
313
+ ".mp4", ".mov", ".avi", ".mkv", ".webm",
314
+ ".mp3", ".wav", ".ogg", ".m4a", ".flac",
315
+ ".pdf", ".docx", ".doc", ".odt", ".rtf", ".txt", ".md",
316
+ ".xlsx", ".xls", ".csv", ".tsv", ".json", ".xml", ".yaml", ".yml",
317
+ ".pptx", ".ppt", ".odp", ".zip", ".tar", ".gz", ".tgz", ".bz2", ".7z",
318
+ ".html", ".htm",
319
+ ];
320
+ const DELIVERABLE_EXTENSION_PATTERN = DELIVERABLE_EXTENSIONS
321
+ .map((extension) => extension.slice(1).replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
322
+ .sort((a, b) => b.length - a.length)
323
+ .join("|");
324
+ const DELIVERABLE_PATH_REGEX_SOURCE = String.raw `(?:~|\/)[^\n"'` + "`" + String.raw `<>|]*?\.(?:${DELIVERABLE_EXTENSION_PATTERN})(?=$|[\s).,"'` + "`" + String.raw `,。;;::!??])`;
325
+ const DELIVERABLE_PATH_REGEX = new RegExp(String.raw `(?:^|[\s("'` + "`" + String.raw `::])(${DELIVERABLE_PATH_REGEX_SOURCE})`, "gi");
326
+ function extractDeliverablePaths(text, userMessage) {
327
+ if (userMessage !== undefined && !hasDeliverableSendIntent(userMessage)) {
328
+ return [];
329
+ }
330
+ const allowed = new Set(DELIVERABLE_EXTENSIONS);
331
+ const paths = new Set();
332
+ for (const match of text.matchAll(DELIVERABLE_PATH_REGEX)) {
333
+ const rawPath = match[1];
334
+ const absolutePath = rawPath.startsWith("~/") ? join(homedir(), rawPath.slice(2)) : rawPath;
335
+ if (allowed.has(extname(absolutePath).toLowerCase()) && existsSync(resolve(absolutePath))) {
336
+ paths.add(resolve(absolutePath));
337
+ }
338
+ }
339
+ return [...paths];
340
+ }
341
+ function hasDeliverableSendIntent(message) {
342
+ const text = message.trim().toLowerCase();
343
+ if (!text) {
344
+ return false;
345
+ }
346
+ if (/(不要|不用|别|无需|不需要).{0,20}(发|发送|传|上传|转发|分享|附件|attach|send|upload|share|deliver)/.test(text)
347
+ || /(只要|仅要).{0,20}(路径|文件名|名字|文本|文字)/.test(text)
348
+ || /\b(do not|don't|dont|no need to|without|not need to)\b.{0,30}\b(send|upload|attach|share|deliver)\b/.test(text)
349
+ || /\bonly\b.{0,30}\b(path|filename|file name|text)\b/.test(text)) {
350
+ return false;
351
+ }
352
+ const sendVerbs = [
353
+ "发", "发送", "传", "上传", "转发", "分享", "发给", "传给", "send", "upload", "attach", "share", "deliver",
354
+ ].join("|");
355
+ const deliverableWords = [
356
+ "文件", "图片", "照片", "图", "附件", "文档", "报告", "表格", "截图", "压缩包", "备份", "录音", "音频", "视频",
357
+ "file", "image", "photo", "picture", "attachment", "document", "report", "spreadsheet", "screenshot", "archive",
358
+ "zip", "pdf", "doc", "docx", "xlsx", "ppt", "pptx",
359
+ ].join("|");
360
+ const pathIntentPattern = new RegExp(`(?:(${sendVerbs}).{0,80}${DELIVERABLE_PATH_REGEX_SOURCE}|${DELIVERABLE_PATH_REGEX_SOURCE}.{0,80}(${sendVerbs}))`);
361
+ if (pathIntentPattern.test(text)) {
362
+ return true;
363
+ }
364
+ if (new RegExp(`(你.{0,6}(能|可以|会)|能不能|可不可以|能否|是否|会不会|支持).{0,30}(${sendVerbs}).{0,30}(${deliverableWords}).{0,8}(吗|么|嘛|\\?|?)?`).test(text)) {
365
+ return false;
366
+ }
367
+ const directChinesePatterns = [
368
+ new RegExp(`(把|将).{0,50}(${deliverableWords}).{0,30}(${sendVerbs})(给我|到手机|到移动端|过来|回来|一下|给这边)?`),
369
+ new RegExp(`(${sendVerbs})(这张|这个|这份|该|那张|那份|一张|几张|一些|些|一下)?[^,。,.!??]{0,24}(${deliverableWords})(给我|到手机|到移动端|过来|回来|一下|给这边)?`),
370
+ new RegExp(`(${sendVerbs})(给我|到手机|到移动端|过来|回来).{0,50}(${deliverableWords})?`),
371
+ new RegExp(`(给我|帮我).{0,20}(${sendVerbs}).{0,50}(${deliverableWords})`),
372
+ ];
373
+ if (directChinesePatterns.some((pattern) => pattern.test(text))) {
374
+ return true;
375
+ }
376
+ const englishPatterns = [
377
+ new RegExp(`\\b(send|upload|attach|share|deliver)\\b.{0,50}\\b(${deliverableWords})\\b`),
378
+ new RegExp(`\\b(${deliverableWords})\\b.{0,50}\\b(send|upload|attach|share|deliver)\\b`),
379
+ ];
380
+ return englishPatterns.some((pattern) => pattern.test(text));
381
+ }
120
382
  //# sourceMappingURL=outgoing-media-relay.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"outgoing-media-relay.js","sourceRoot":"","sources":["../../../src/openclaw/relay/outgoing-media-relay.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"outgoing-media-relay.js","sourceRoot":"","sources":["../../../src/openclaw/relay/outgoing-media-relay.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@ import { DEFAULT_GATEWAY_SESSION_DEFAULTS, buildContextUsageFingerprint, readCon
7
7
  import { appendUniqueSuffix, extractChatRole, extractChatText, normalizeChatEventPayload, normalizeChatState, withMessageText, } from "../core/relay/chat-payload.js";
8
8
  import { extractHistoryOutcome, readOpenClawTranscriptChatHistory, withTimeout, } from "./relay/chat-history.js";
9
9
  import { dedupeOpenClawChatSendUserMirrorTranscript, } from "./relay/transcript-dedupe.js";
10
- import { buildMobileAssistantErrorPayload, buildMobileAssistantFinalPayload, } from "../core/relay/mobile-chat-run-bridge.js";
10
+ import { buildMobileAssistantDeltaPayload, buildMobileAssistantErrorPayload, buildMobileAssistantFinalPayload, } from "../core/relay/mobile-chat-run-bridge.js";
11
11
  import { buildOfficeEventPayload } from "../core/relay/office-payload.js";
12
12
  import { prepareChatSendParams } from "./relay/chat-send-attachments.js";
13
13
  import { relayOutgoingMediaInHistoryResponse, relayOutgoingMediaInPayload } from "./relay/outgoing-media-relay.js";
@@ -279,7 +279,7 @@ export async function runRelayManager(opts) {
279
279
  text: outcome.text,
280
280
  includeTimelineEvents: true,
281
281
  });
282
- await publishAndSendGatewayEvent("chat", buildFinalPayloadFromHistoryOutcome(basePayload, outcome), true);
282
+ await publishAndSendGatewayEvent("chat", buildFinalPayloadFromHistoryOutcome(basePayload, outcome), true, context.promptText);
283
283
  return;
284
284
  }
285
285
  await publishAndSendGatewayEvent("chat", buildMobileAssistantErrorPayload({
@@ -327,7 +327,7 @@ export async function runRelayManager(opts) {
327
327
  }
328
328
  send({ type: "event", event: "office", payload: officePayload });
329
329
  }
330
- async function publishAndSendGatewayEvent(eventName, payload, publishOffice) {
330
+ async function publishAndSendGatewayEvent(eventName, payload, publishOffice, userMessage) {
331
331
  const outgoingPayload = eventName === "chat"
332
332
  ? await relayOutgoingMediaInPayload(payload, {
333
333
  relayServerUrl: opts.relayServerUrl,
@@ -335,6 +335,7 @@ export async function runRelayManager(opts) {
335
335
  gatewayId: opts.gatewayId,
336
336
  senderDisplayName: "OpenClaw",
337
337
  cache: outgoingMediaUploadCache,
338
+ userMessage,
338
339
  })
339
340
  : payload;
340
341
  if (publishOffice) {
@@ -470,6 +471,133 @@ export async function runRelayManager(opts) {
470
471
  function stripUndefinedHistoryMessageFields(message) {
471
472
  return Object.fromEntries(Object.entries(message).filter(([, value]) => value !== undefined));
472
473
  }
474
+ function mergeCanonicalChatPayload(basePayload, canonicalPayload) {
475
+ const base = asRecord(basePayload);
476
+ const canonical = asRecord(canonicalPayload);
477
+ if (!base) {
478
+ return canonicalPayload;
479
+ }
480
+ if (!canonical) {
481
+ return basePayload;
482
+ }
483
+ const baseMessage = asRecord(base.message);
484
+ const canonicalMessage = asRecord(canonical.message);
485
+ const merged = {
486
+ ...base,
487
+ ...canonical,
488
+ };
489
+ return baseMessage || canonicalMessage
490
+ ? {
491
+ ...merged,
492
+ message: {
493
+ ...(baseMessage ?? {}),
494
+ ...(canonicalMessage ?? {}),
495
+ },
496
+ }
497
+ : merged;
498
+ }
499
+ function resolveChatPayloadSeq(payload) {
500
+ return normalizeFiniteNumber(deepField(payload, ["seq", "sequence", "index"]))
501
+ ?? resolveChatPayloadTimestamp(payload);
502
+ }
503
+ function resolveChatPayloadTimestamp(payload) {
504
+ const value = normalizeFiniteNumber(deepField(payload, ["ts", "timestamp", "createdAt", "created_at", "time"]));
505
+ if (value !== undefined) {
506
+ return value > 10_000_000_000 ? Math.round(value) : Math.round(value * 1000);
507
+ }
508
+ return Date.now();
509
+ }
510
+ function extractChatErrorMessage(payload) {
511
+ const direct = firstNonEmptyString(deepField(payload, ["errorMessage", "error_message", "message", "text"]));
512
+ if (direct) {
513
+ return direct;
514
+ }
515
+ const error = asRecord(asRecord(payload)?.error);
516
+ const nested = firstNonEmptyString(error?.message, error?.userMessage, error?.detail);
517
+ return nested ?? "Request failed";
518
+ }
519
+ function mobileAssistantUsageFromPayload(payload) {
520
+ const record = asRecord(payload);
521
+ const usage = asRecord(record?.usage);
522
+ return stripUndefined({
523
+ currentModel: firstNonEmptyString(record?.currentModel, record?.model, usage?.currentModel, usage?.model),
524
+ provider: firstNonEmptyString(record?.provider, usage?.provider),
525
+ contextUsage: normalizeNonNegativeInteger(record?.contextUsage)
526
+ ?? normalizeNonNegativeInteger(record?.promptTokens)
527
+ ?? normalizeNonNegativeInteger(record?.inputTokens)
528
+ ?? normalizeNonNegativeInteger(usage?.contextUsage)
529
+ ?? normalizeNonNegativeInteger(usage?.promptTokens)
530
+ ?? normalizeNonNegativeInteger(usage?.inputTokens),
531
+ contextLimit: normalizeNonNegativeInteger(record?.contextLimit)
532
+ ?? normalizeNonNegativeInteger(record?.maxInputTokens)
533
+ ?? normalizeNonNegativeInteger(usage?.contextLimit)
534
+ ?? normalizeNonNegativeInteger(usage?.maxInputTokens),
535
+ });
536
+ }
537
+ function nonTextContentBlocks(payload) {
538
+ const payloadRecord = asRecord(payload);
539
+ const message = asRecord(payloadRecord?.message);
540
+ const topLevelContent = payloadRecord?.content;
541
+ const content = Array.isArray(message?.content)
542
+ ? message.content
543
+ : Array.isArray(topLevelContent)
544
+ ? topLevelContent
545
+ : [];
546
+ return content.filter((block) => {
547
+ const record = asRecord(block);
548
+ return Boolean(record?.type) && record?.type !== "text";
549
+ });
550
+ }
551
+ function nonTextContentBlocksFromHistory(message) {
552
+ return Array.isArray(message.content)
553
+ ? message.content.filter((block) => {
554
+ const record = asRecord(block);
555
+ return Boolean(record?.type) && record?.type !== "text";
556
+ })
557
+ : [];
558
+ }
559
+ function deepField(payload, keys) {
560
+ const record = asRecord(payload);
561
+ const message = asRecord(record?.message);
562
+ const data = asRecord(record?.data);
563
+ for (const key of keys) {
564
+ if (record && record[key] !== undefined)
565
+ return record[key];
566
+ if (message && message[key] !== undefined)
567
+ return message[key];
568
+ if (data && data[key] !== undefined)
569
+ return data[key];
570
+ }
571
+ return undefined;
572
+ }
573
+ function firstNonEmptyString(...values) {
574
+ for (const value of values) {
575
+ if (typeof value === "string" && value.trim().length > 0) {
576
+ return value.trim();
577
+ }
578
+ }
579
+ return undefined;
580
+ }
581
+ function normalizeFiniteNumber(value) {
582
+ const number = typeof value === "number" && Number.isFinite(value)
583
+ ? value
584
+ : typeof value === "string" && value.trim().length > 0
585
+ ? Number(value.trim())
586
+ : Number.NaN;
587
+ return Number.isFinite(number) ? number : undefined;
588
+ }
589
+ function normalizeNonNegativeInteger(value) {
590
+ const number = normalizeFiniteNumber(value);
591
+ return number !== undefined && number >= 0 ? Math.round(number) : undefined;
592
+ }
593
+ function stripUndefined(value) {
594
+ return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
595
+ }
596
+ function asRecord(value) {
597
+ return value && typeof value === "object" && !Array.isArray(value)
598
+ ? value
599
+ : undefined;
600
+ }
473
601
  relayWs.on("open", () => {
474
602
  console.log(`Connected to relay server (gatewayId=${opts.gatewayId})`);
475
603
  opts.onConnected?.();
@@ -524,11 +652,26 @@ export async function runRelayManager(opts) {
524
652
  const bufferedText = appendUniqueSuffix(previousText, currentText);
525
653
  chatBuffers.set(runId, bufferedText);
526
654
  if (role === "assistant" && bufferedText.trim()) {
527
- realtimePayload = withMessageText(normalizedPayload, bufferedText);
655
+ realtimePayload = resolvedSessionKey
656
+ ? mergeCanonicalChatPayload(normalizedPayload, buildMobileAssistantDeltaPayload({
657
+ run: { runId, sessionKey: resolvedSessionKey },
658
+ seq: resolveChatPayloadSeq(normalizedPayload),
659
+ timestampMs: resolveChatPayloadTimestamp(normalizedPayload),
660
+ delta: bufferedText,
661
+ includeTimelineEvents: true,
662
+ }))
663
+ : withMessageText(normalizedPayload, bufferedText);
528
664
  }
529
665
  }
530
666
  else if (state === "error" || state === "failed" || state === "fail" || state === "aborted") {
531
667
  chatBuffers.delete(runId);
668
+ if (role === "assistant" && resolvedSessionKey) {
669
+ realtimePayload = mergeCanonicalChatPayload(normalizedPayload, buildMobileAssistantErrorPayload({
670
+ run: { runId, sessionKey: resolvedSessionKey },
671
+ errorMessage: extractChatErrorMessage(normalizedPayload),
672
+ includeTimelineEvents: true,
673
+ }));
674
+ }
532
675
  }
533
676
  }
534
677
  if (state === "final" && resolvedSessionKey) {
@@ -542,8 +685,16 @@ export async function runRelayManager(opts) {
542
685
  if (runId) {
543
686
  chatRunContexts.delete(runId);
544
687
  }
545
- const outgoingPayload = withMessageText(normalizedPayload, resolvedText);
546
- void publishAndSendGatewayEvent(event, outgoingPayload, shouldPublishOffice);
688
+ const outgoingPayload = runId
689
+ ? mergeCanonicalChatPayload(normalizedPayload, buildMobileAssistantFinalPayload({
690
+ run: { runId, sessionKey: resolvedSessionKey },
691
+ text: resolvedText,
692
+ contentBlocks: nonTextContentBlocks(normalizedPayload),
693
+ includeTimelineEvents: true,
694
+ ...mobileAssistantUsageFromPayload(normalizedPayload),
695
+ }))
696
+ : withMessageText(normalizedPayload, resolvedText);
697
+ void publishAndSendGatewayEvent(event, outgoingPayload, shouldPublishOffice, runContext?.promptText);
547
698
  return;
548
699
  }
549
700
  const fetchHistory = () => requestChatHistoryFromClawConnect({ sessionKey: resolvedSessionKey, limit: 10 });
@@ -560,16 +711,31 @@ export async function runRelayManager(opts) {
560
711
  chatRunContexts.delete(runId);
561
712
  }
562
713
  if (outcome?.kind === "final") {
563
- const outgoingPayload = buildFinalPayloadFromHistoryOutcome(normalizedPayload, outcome);
564
- await publishAndSendGatewayEvent(event, outgoingPayload, shouldPublishOffice);
714
+ const basePayload = runId
715
+ ? buildMobileAssistantFinalPayload({
716
+ run: { runId, sessionKey: resolvedSessionKey },
717
+ text: outcome.text,
718
+ contentBlocks: nonTextContentBlocksFromHistory(outcome.message),
719
+ includeTimelineEvents: true,
720
+ ...mobileAssistantUsageFromPayload(normalizedPayload),
721
+ })
722
+ : normalizedPayload;
723
+ const outgoingPayload = buildFinalPayloadFromHistoryOutcome(basePayload, outcome);
724
+ await publishAndSendGatewayEvent(event, outgoingPayload, shouldPublishOffice, runContext?.promptText);
565
725
  return;
566
726
  }
567
727
  if (outcome?.kind === "error") {
568
- const outgoingPayload = {
569
- ...normalizedPayload,
570
- state: "error",
571
- errorMessage: outcome.errorMessage,
572
- };
728
+ const outgoingPayload = runId
729
+ ? mergeCanonicalChatPayload(normalizedPayload, buildMobileAssistantErrorPayload({
730
+ run: { runId, sessionKey: resolvedSessionKey },
731
+ errorMessage: outcome.errorMessage,
732
+ includeTimelineEvents: true,
733
+ }))
734
+ : {
735
+ ...normalizedPayload,
736
+ state: "error",
737
+ errorMessage: outcome.errorMessage,
738
+ };
573
739
  await publishAndSendGatewayEvent(event, outgoingPayload, shouldPublishOffice);
574
740
  return;
575
741
  }