@newbase-clawchat/openclaw-clawchat 2026.5.12-2 → 2026.5.12-21
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 +39 -17
- package/dist/index.js +3 -1
- package/dist/src/api-client.js +71 -12
- package/dist/src/api-types.test-d.js +10 -0
- package/dist/src/channel.js +5 -5
- package/dist/src/channel.setup.js +4 -17
- package/dist/src/clawchat-memory.js +290 -0
- package/dist/src/clawchat-metadata.js +235 -0
- package/dist/src/client.js +31 -93
- package/dist/src/commands.js +3 -3
- package/dist/src/config.js +58 -3
- package/dist/src/group-message-coalescer.js +107 -0
- package/dist/src/inbound.js +24 -28
- package/dist/src/login.runtime.js +82 -19
- package/dist/src/media-runtime.js +2 -3
- package/dist/src/message-mapper.js +1 -1
- package/dist/src/mock-transport.js +31 -0
- package/dist/src/outbound.js +281 -56
- package/dist/src/plugin-prompts.js +76 -0
- package/dist/src/profile-prompt.js +150 -0
- package/dist/src/profile-sync.js +169 -0
- package/dist/src/prompt-injection.js +25 -0
- package/dist/src/protocol-types.js +63 -0
- package/dist/src/protocol-types.typecheck.js +1 -0
- package/dist/src/protocol.js +2 -2
- package/dist/src/reply-dispatcher.js +143 -40
- package/dist/src/runtime.js +813 -109
- package/dist/src/storage.js +636 -0
- package/dist/src/tools-schema.js +70 -10
- package/dist/src/tools.js +600 -112
- package/dist/src/ws-alignment.js +8 -0
- package/dist/src/ws-client.js +588 -0
- package/index.ts +6 -1
- package/openclaw.plugin.json +44 -4
- package/package.json +4 -3
- package/prompts/platform.md +7 -0
- package/skills/clawchat/SKILL.md +90 -0
- package/src/api-client.test.ts +360 -15
- package/src/api-client.ts +127 -25
- package/src/api-types.test-d.ts +12 -0
- package/src/api-types.ts +71 -4
- package/src/buffered-stream.test.ts +1 -1
- package/src/buffered-stream.ts +1 -1
- package/src/channel.outbound.test.ts +270 -60
- package/src/channel.setup.ts +9 -18
- package/src/channel.test.ts +33 -25
- package/src/channel.ts +5 -7
- package/src/clawchat-memory.test.ts +372 -0
- package/src/clawchat-memory.ts +363 -0
- package/src/clawchat-metadata.test.ts +350 -0
- package/src/clawchat-metadata.ts +352 -0
- package/src/client.test.ts +57 -48
- package/src/client.ts +37 -129
- package/src/commands.test.ts +2 -2
- package/src/commands.ts +3 -3
- package/src/config.test.ts +169 -4
- package/src/config.ts +86 -6
- package/src/group-message-coalescer.test.ts +223 -0
- package/src/group-message-coalescer.ts +154 -0
- package/src/inbound.test.ts +106 -19
- package/src/inbound.ts +31 -35
- package/src/login.runtime.test.ts +294 -11
- package/src/login.runtime.ts +90 -21
- package/src/manifest.test.ts +86 -14
- package/src/media-runtime.test.ts +31 -2
- package/src/media-runtime.ts +7 -10
- package/src/message-mapper.test.ts +2 -2
- package/src/message-mapper.ts +2 -2
- package/src/mock-transport.test.ts +35 -0
- package/src/mock-transport.ts +38 -0
- package/src/outbound.test.ts +811 -95
- package/src/outbound.ts +332 -65
- package/src/plugin-entry.test.ts +3 -1
- package/src/plugin-prompts.test.ts +78 -0
- package/src/plugin-prompts.ts +92 -0
- package/src/profile-prompt.test.ts +435 -0
- package/src/profile-prompt.ts +208 -0
- package/src/profile-sync.test.ts +611 -0
- package/src/profile-sync.ts +268 -0
- package/src/prompt-injection.test.ts +39 -0
- package/src/prompt-injection.ts +45 -0
- package/src/protocol-types.test.ts +69 -0
- package/src/protocol-types.ts +296 -0
- package/src/protocol-types.typecheck.ts +89 -0
- package/src/protocol.ts +2 -2
- package/src/reply-dispatcher.test.ts +720 -135
- package/src/reply-dispatcher.ts +174 -42
- package/src/runtime.test.ts +3884 -337
- package/src/runtime.ts +956 -128
- package/src/storage.test.ts +692 -0
- package/src/storage.ts +989 -0
- package/src/streaming.test.ts +1 -1
- package/src/streaming.ts +1 -1
- package/src/tools-schema.ts +115 -13
- package/src/tools.test.ts +501 -10
- package/src/tools.ts +739 -133
- package/src/ws-alignment.ts +9 -0
- package/src/ws-client.test.ts +1218 -0
- package/src/ws-client.ts +662 -0
package/src/reply-dispatcher.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Fragment } from "./protocol-types.ts";
|
|
2
|
+
import type { ClawlingChatClient } from "./ws-client.ts";
|
|
2
3
|
import {
|
|
3
4
|
interactiveReplyToPresentation,
|
|
4
5
|
renderMessagePresentationFallbackText,
|
|
@@ -16,12 +17,16 @@ import {
|
|
|
16
17
|
mergeStreamingText,
|
|
17
18
|
type BufferedStreamSession,
|
|
18
19
|
} from "./buffered-stream.ts";
|
|
19
|
-
import {
|
|
20
|
+
import type { ChatType, EnvelopeRouting } from "./client.ts";
|
|
20
21
|
import type { ResolvedOpenclawClawlingAccount } from "./config.ts";
|
|
21
|
-
import { textToFragments } from "./message-mapper.ts";
|
|
22
22
|
import { uploadOutboundMedia, type ClawlingMediaFragment } from "./media-runtime.ts";
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
sendOpenclawClawlingText,
|
|
25
|
+
type OutboundReplyCtx,
|
|
26
|
+
type SendResult,
|
|
27
|
+
} from "./outbound.ts";
|
|
24
28
|
import { sendStreamingFailure } from "./streaming.ts";
|
|
29
|
+
import type { ClawChatStore } from "./storage.ts";
|
|
25
30
|
|
|
26
31
|
export interface ReplyDispatcherOptions {
|
|
27
32
|
cfg: OpenClawConfig;
|
|
@@ -52,6 +57,7 @@ export interface ReplyDispatcherOptions {
|
|
|
52
57
|
senderNickName: string;
|
|
53
58
|
bodyText: string;
|
|
54
59
|
};
|
|
60
|
+
store?: Pick<ClawChatStore, "insertMessage" | "claimMessageOnce" | "updateMessageByIdentity"> | null;
|
|
55
61
|
log?: { info?: (m: string) => void; error?: (m: string) => void };
|
|
56
62
|
}
|
|
57
63
|
|
|
@@ -64,6 +70,12 @@ type StreamingReplyHooks = {
|
|
|
64
70
|
onReasoningStream?: (payload: ReplyPayload) => Promise<void>;
|
|
65
71
|
};
|
|
66
72
|
|
|
73
|
+
type ClawChatReplyOptions = TypedReplyDispatcherResult["replyOptions"] &
|
|
74
|
+
StreamingReplyHooks & {
|
|
75
|
+
sourceReplyDeliveryMode: "automatic";
|
|
76
|
+
disableBlockStreaming?: boolean;
|
|
77
|
+
};
|
|
78
|
+
|
|
67
79
|
type RichAction = {
|
|
68
80
|
id: string;
|
|
69
81
|
label: string;
|
|
@@ -195,7 +207,7 @@ function resolvePayloadText(payload: ReplyPayload): string {
|
|
|
195
207
|
*/
|
|
196
208
|
export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOptions): {
|
|
197
209
|
dispatcher: TypedReplyDispatcherResult["dispatcher"];
|
|
198
|
-
replyOptions:
|
|
210
|
+
replyOptions: ClawChatReplyOptions;
|
|
199
211
|
markDispatchIdle: TypedReplyDispatcherResult["markDispatchIdle"];
|
|
200
212
|
} {
|
|
201
213
|
const {
|
|
@@ -207,6 +219,7 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
207
219
|
replyCtx,
|
|
208
220
|
inboundMessageId,
|
|
209
221
|
inboundForFinalReply,
|
|
222
|
+
store,
|
|
210
223
|
log,
|
|
211
224
|
} = options;
|
|
212
225
|
const routing: EnvelopeRouting = { chatId: target.chatId, chatType: target.chatType };
|
|
@@ -246,18 +259,94 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
246
259
|
let streamingClosed = false;
|
|
247
260
|
let runFailed = false;
|
|
248
261
|
let runDone = false;
|
|
262
|
+
let streamClaimAttempted = false;
|
|
249
263
|
// `streamCreatedEmitted` is the authoritative guard: once a `message.created`
|
|
250
264
|
// has been emitted for this dispatcher instance, never emit another — even
|
|
251
265
|
// if `onReplyStart` fires again or a pre-onReplyStart `onPartialReply`
|
|
252
266
|
// raced the lazy open path.
|
|
253
267
|
let streamCreatedEmitted = false;
|
|
254
268
|
|
|
269
|
+
const outboundEventType = () => (replyCtx ? "message.reply" : "message.send");
|
|
270
|
+
const outboundRaw = () => ({ target, replyCtx: replyCtx ?? null });
|
|
271
|
+
const claimOutbound = (
|
|
272
|
+
eventType: "message.created" | "message.send" | "message.reply",
|
|
273
|
+
messageId: string,
|
|
274
|
+
text: string,
|
|
275
|
+
raw: unknown,
|
|
276
|
+
): true | false | null => {
|
|
277
|
+
if (!store || !messageId) return null;
|
|
278
|
+
try {
|
|
279
|
+
return store.claimMessageOnce({
|
|
280
|
+
platform: "openclaw",
|
|
281
|
+
accountId: account.accountId,
|
|
282
|
+
kind: "message",
|
|
283
|
+
direction: "outbound",
|
|
284
|
+
eventType,
|
|
285
|
+
chatId: target.chatId,
|
|
286
|
+
messageId,
|
|
287
|
+
text,
|
|
288
|
+
raw,
|
|
289
|
+
});
|
|
290
|
+
} catch {
|
|
291
|
+
log?.error?.(`[${account.accountId}] openclaw-clawchat sqlite outbound claim failed`);
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
const updateOutbound = (
|
|
296
|
+
eventType: "message.reply",
|
|
297
|
+
messageId: string,
|
|
298
|
+
text: string,
|
|
299
|
+
raw: unknown,
|
|
300
|
+
) => {
|
|
301
|
+
if (!store || !messageId) return;
|
|
302
|
+
try {
|
|
303
|
+
store.updateMessageByIdentity({
|
|
304
|
+
accountId: account.accountId,
|
|
305
|
+
kind: "message",
|
|
306
|
+
direction: "outbound",
|
|
307
|
+
eventType,
|
|
308
|
+
chatId: target.chatId,
|
|
309
|
+
messageId,
|
|
310
|
+
text,
|
|
311
|
+
raw,
|
|
312
|
+
});
|
|
313
|
+
} catch {
|
|
314
|
+
log?.error?.(`[${account.accountId}] openclaw-clawchat sqlite outbound update failed; continuing`);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
const recordOutbound = (kind: "message" | "thinking", messageId: string, text: string) => {
|
|
318
|
+
if (!store || !messageId) return;
|
|
319
|
+
try {
|
|
320
|
+
store.insertMessage({
|
|
321
|
+
platform: "openclaw",
|
|
322
|
+
accountId: account.accountId,
|
|
323
|
+
kind,
|
|
324
|
+
direction: "outbound",
|
|
325
|
+
eventType: outboundEventType(),
|
|
326
|
+
chatId: target.chatId,
|
|
327
|
+
messageId,
|
|
328
|
+
text,
|
|
329
|
+
raw: outboundRaw(),
|
|
330
|
+
});
|
|
331
|
+
} catch {
|
|
332
|
+
log?.error?.(`[${account.accountId}] openclaw-clawchat sqlite outbound insert failed; continuing`);
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
const recordThinkingIfLinked = (messageId: string) => {
|
|
336
|
+
const thinkingText = reasoningText.trim();
|
|
337
|
+
if (!thinkingText) return;
|
|
338
|
+
recordOutbound("thinking", messageId, thinkingText);
|
|
339
|
+
reasoningText = "";
|
|
340
|
+
};
|
|
341
|
+
|
|
255
342
|
const mintStreamingMessageId = () =>
|
|
256
343
|
`${account.userId}-stream-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
344
|
+
const mintStaticMessageId = () =>
|
|
345
|
+
`${account.userId}-msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
257
346
|
|
|
258
347
|
const openSessionIfNeeded = () => {
|
|
259
|
-
if (!streamingEnabled || streamingSession || streamCreatedEmitted) return;
|
|
260
|
-
|
|
348
|
+
if (!streamingEnabled || streamingSession || streamCreatedEmitted || streamClaimAttempted) return;
|
|
349
|
+
streamClaimAttempted = true;
|
|
261
350
|
// Mint a fresh agent-side message_id at `message.created` time. All
|
|
262
351
|
// subsequent `message.add` / `message.done` / `message.reply` frames for
|
|
263
352
|
// this stream reuse it. Once the stream finalizes (done or reply), this
|
|
@@ -266,6 +355,21 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
266
355
|
// `replyTo.msgId`; keeping the two distinct avoids the agent's reply
|
|
267
356
|
// frames shadowing the user turn they answer.
|
|
268
357
|
streamingMessageId = mintStreamingMessageId();
|
|
358
|
+
const claimed = claimOutbound(
|
|
359
|
+
"message.created",
|
|
360
|
+
streamingMessageId,
|
|
361
|
+
"",
|
|
362
|
+
{ target, replyCtx: replyCtx ?? null, mode: "stream" },
|
|
363
|
+
);
|
|
364
|
+
if (claimed !== true) {
|
|
365
|
+
streamCreatedEmitted = false;
|
|
366
|
+
streamingMessageId = "";
|
|
367
|
+
log?.[claimed === false ? "info" : "error"]?.(
|
|
368
|
+
`[${account.accountId}] openclaw-clawchat stream outbound skipped reason=${claimed === false ? "duplicate" : "claim_unavailable"}`,
|
|
369
|
+
);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
streamCreatedEmitted = true;
|
|
269
373
|
streamingSession = openBufferedStreamingSession({
|
|
270
374
|
client,
|
|
271
375
|
routing,
|
|
@@ -318,16 +422,31 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
318
422
|
text: string,
|
|
319
423
|
mediaFragments: ClawlingMediaFragment[] = [],
|
|
320
424
|
richFragments: Fragment[] = [],
|
|
321
|
-
|
|
322
|
-
|
|
425
|
+
options: { recordMessage?: boolean } = {},
|
|
426
|
+
): Promise<SendResult | null> => {
|
|
427
|
+
if (!text.trim() && mediaFragments.length === 0 && richFragments.length === 0) return null;
|
|
323
428
|
log?.info?.(
|
|
324
429
|
`[${account.accountId}] openclaw-clawchat sending static text_len=${text.length} media=${mediaFragments.length} rich=${richFragments.length} to=${target.chatId}`,
|
|
325
430
|
);
|
|
326
|
-
|
|
431
|
+
const messageId = mintStaticMessageId();
|
|
432
|
+
const raw = { target, replyCtx: replyCtx ?? null, mode: "static" };
|
|
433
|
+
const claimed = options.recordMessage
|
|
434
|
+
? claimOutbound(outboundEventType(), messageId, text, raw)
|
|
435
|
+
: true;
|
|
436
|
+
if (claimed === false) {
|
|
437
|
+
log?.info?.(`[${account.accountId}] openclaw-clawchat outbound duplicate skipped msg=${messageId}`);
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
if (claimed === null) {
|
|
441
|
+
log?.error?.(`[${account.accountId}] openclaw-clawchat outbound skipped msg=${messageId} reason=claim_unavailable`);
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
const result = await sendOpenclawClawlingText({
|
|
327
445
|
client,
|
|
328
446
|
account,
|
|
329
447
|
to: target,
|
|
330
448
|
text,
|
|
449
|
+
messageId,
|
|
331
450
|
...(replyCtx ? { replyCtx } : {}),
|
|
332
451
|
...(richFragments.length > 0 ? { richFragments } : {}),
|
|
333
452
|
...(mediaFragments.length > 0 ? { mediaFragments } : {}),
|
|
@@ -336,6 +455,7 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
336
455
|
log?.info?.(
|
|
337
456
|
`[${account.accountId}] openclaw-clawchat send complete to=${target.chatId}`,
|
|
338
457
|
);
|
|
458
|
+
return result;
|
|
339
459
|
};
|
|
340
460
|
|
|
341
461
|
const logDetachedFailure = (action: string, error: unknown) => {
|
|
@@ -351,6 +471,7 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
351
471
|
const emitFinalConsolidatedMessage = async () => {
|
|
352
472
|
if (finalEmitted) return;
|
|
353
473
|
finalEmitted = true;
|
|
474
|
+
if (!streamingMessageId) return;
|
|
354
475
|
const mergedMedia = await uploadMediaUrls(accumulatedMediaUrls.slice());
|
|
355
476
|
const mergedText = streamText.trim();
|
|
356
477
|
if (!mergedText && finalRichFragments.length === 0 && mergedMedia.length === 0) {
|
|
@@ -362,29 +483,35 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
362
483
|
log?.info?.(
|
|
363
484
|
`[${account.accountId}] openclaw-clawchat emitting consolidated final (message.reply) msg=${streamingMessageId} text_len=${mergedText.length} media=${mergedMedia.length}`,
|
|
364
485
|
);
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
486
|
+
const finalReplyCtx: OutboundReplyCtx = {
|
|
487
|
+
replyToMessageId: inboundMessageId ?? streamingMessageId,
|
|
488
|
+
replyPreviewChatId: inboundForFinalReply?.chatId ?? target.chatId,
|
|
489
|
+
replyPreviewSenderId: inboundForFinalReply?.senderId ?? target.chatId,
|
|
490
|
+
replyPreviewNickName:
|
|
491
|
+
inboundForFinalReply?.senderNickName ?? inboundForFinalReply?.senderId ?? target.chatId,
|
|
492
|
+
replyPreviewText: inboundForFinalReply?.bodyText ?? "",
|
|
493
|
+
};
|
|
372
494
|
// Streaming message_id must match the created/add/done frames so the
|
|
373
|
-
// backend can correlate the consolidated reply with the stream.
|
|
374
|
-
|
|
495
|
+
// backend can correlate the consolidated reply with the stream. Use the
|
|
496
|
+
// ackable send path so disconnects queue the final user-visible answer.
|
|
497
|
+
await sendOpenclawClawlingText({
|
|
498
|
+
client,
|
|
499
|
+
account,
|
|
500
|
+
to: target,
|
|
501
|
+
text: mergedText,
|
|
375
502
|
messageId: streamingMessageId,
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
nickName:
|
|
381
|
-
inboundForFinalReply?.senderNickName ?? inboundForFinalReply?.senderId ?? target.chatId,
|
|
382
|
-
fragments: inboundForFinalReply?.bodyText
|
|
383
|
-
? [{ kind: "text", text: inboundForFinalReply.bodyText }]
|
|
384
|
-
: [],
|
|
385
|
-
},
|
|
386
|
-
body: { fragments: bodyFragments },
|
|
503
|
+
replyCtx: finalReplyCtx,
|
|
504
|
+
...(finalRichFragments.length > 0 ? { richFragments: finalRichFragments } : {}),
|
|
505
|
+
...(mergedMedia.length > 0 ? { mediaFragments: mergedMedia } : {}),
|
|
506
|
+
log,
|
|
387
507
|
});
|
|
508
|
+
updateOutbound(
|
|
509
|
+
"message.reply",
|
|
510
|
+
streamingMessageId,
|
|
511
|
+
mergedText,
|
|
512
|
+
{ target, replyCtx: replyCtx ?? null, mode: "stream-final" },
|
|
513
|
+
);
|
|
514
|
+
recordThinkingIfLinked(streamingMessageId);
|
|
388
515
|
};
|
|
389
516
|
|
|
390
517
|
const ingestFinalPayload = (payload: ReplyPayload, text: string, richFragment: Fragment | null) => {
|
|
@@ -443,7 +570,9 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
443
570
|
reasoningText = mergeStreamingText(reasoningText, text);
|
|
444
571
|
await queueStreamSnapshot();
|
|
445
572
|
} else {
|
|
446
|
-
|
|
573
|
+
reasoningText = mergeStreamingText(reasoningText, text);
|
|
574
|
+
const result = await sendStatic(text, [], [], { recordMessage: true });
|
|
575
|
+
if (result?.messageId) recordThinkingIfLinked(result.messageId);
|
|
447
576
|
}
|
|
448
577
|
return;
|
|
449
578
|
}
|
|
@@ -458,13 +587,21 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
458
587
|
);
|
|
459
588
|
// For streaming: consolidated final is emitted in onIdle after done.
|
|
460
589
|
// For static: emit immediately.
|
|
461
|
-
if (
|
|
590
|
+
if (streamingEnabled) {
|
|
591
|
+
if (text.trim()) {
|
|
592
|
+
await queueStreamSnapshot();
|
|
593
|
+
} else if (richFragment || urls.length > 0) {
|
|
594
|
+
openSessionIfNeeded();
|
|
595
|
+
}
|
|
596
|
+
} else {
|
|
462
597
|
const mediaFragments = await uploadMediaUrls(urls);
|
|
463
|
-
await sendStatic(
|
|
598
|
+
const result = await sendStatic(
|
|
464
599
|
text,
|
|
465
600
|
mediaFragments,
|
|
466
601
|
richFragment && account.richInteractions ? ([richFragment] as unknown as Fragment[]) : [],
|
|
602
|
+
{ recordMessage: true },
|
|
467
603
|
);
|
|
604
|
+
if (result?.messageId) recordThinkingIfLinked(result.messageId);
|
|
468
605
|
}
|
|
469
606
|
return;
|
|
470
607
|
}
|
|
@@ -478,14 +615,7 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
478
615
|
log?.info?.(
|
|
479
616
|
`[${account.accountId}] openclaw-clawchat mid-stream media emitted as separate message (count=${mediaFragments.length})`,
|
|
480
617
|
);
|
|
481
|
-
await
|
|
482
|
-
client,
|
|
483
|
-
account,
|
|
484
|
-
to: target,
|
|
485
|
-
text: "",
|
|
486
|
-
mediaFragments,
|
|
487
|
-
log,
|
|
488
|
-
});
|
|
618
|
+
await sendStatic("", mediaFragments, [], { recordMessage: true });
|
|
489
619
|
}
|
|
490
620
|
}
|
|
491
621
|
} else {
|
|
@@ -493,7 +623,7 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
493
623
|
const richFragments =
|
|
494
624
|
richFragment && account.richInteractions ? ([richFragment] as unknown as Fragment[]) : [];
|
|
495
625
|
if (text.trim() || mediaFragments.length > 0 || richFragments.length > 0) {
|
|
496
|
-
await sendStatic(text, mediaFragments, richFragments);
|
|
626
|
+
await sendStatic(text, mediaFragments, richFragments, { recordMessage: true });
|
|
497
627
|
}
|
|
498
628
|
}
|
|
499
629
|
},
|
|
@@ -563,6 +693,8 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
563
693
|
dispatcher: base.dispatcher,
|
|
564
694
|
replyOptions: {
|
|
565
695
|
...base.replyOptions,
|
|
696
|
+
sourceReplyDeliveryMode: "automatic",
|
|
697
|
+
...(streamingEnabled ? { disableBlockStreaming: false } : {}),
|
|
566
698
|
...streamingHooks,
|
|
567
699
|
},
|
|
568
700
|
markDispatchIdle: base.markDispatchIdle,
|