chrome-openclaw-sider 1.0.2 → 1.0.26

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 (58) hide show
  1. package/README.md +11 -1
  2. package/README.zh_CN.md +8 -6
  3. package/dist/index.d.ts +12 -0
  4. package/{index.ts → dist/index.js} +24 -17
  5. package/dist/setup-entry.d.ts +18 -0
  6. package/dist/setup-entry.js +8 -0
  7. package/dist/src/account.d.ts +54 -0
  8. package/{src/account.ts → dist/src/account.js} +70 -160
  9. package/dist/src/auth.d.ts +30 -0
  10. package/{src/auth.ts → dist/src/auth.js} +61 -128
  11. package/dist/src/auto-title.d.ts +20 -0
  12. package/dist/src/auto-title.js +22 -0
  13. package/dist/src/channel-auto-title.d.ts +23 -0
  14. package/dist/src/channel-auto-title.js +77 -0
  15. package/dist/src/channel-builders.d.ts +105 -0
  16. package/dist/src/channel-builders.js +238 -0
  17. package/dist/src/channel-hooks.d.ts +30 -0
  18. package/dist/src/channel-hooks.js +331 -0
  19. package/dist/src/channel-monitor.d.ts +34 -0
  20. package/dist/src/channel-monitor.js +341 -0
  21. package/dist/src/channel-relay.d.ts +117 -0
  22. package/dist/src/channel-relay.js +573 -0
  23. package/dist/src/channel-runtime.d.ts +32 -0
  24. package/dist/src/channel-runtime.js +85 -0
  25. package/dist/src/channel-send-result.d.ts +19 -0
  26. package/dist/src/channel-send-result.js +126 -0
  27. package/dist/src/channel-session-model.d.ts +19 -0
  28. package/dist/src/channel-session-model.js +244 -0
  29. package/dist/src/channel-state.d.ts +92 -0
  30. package/dist/src/channel-state.js +471 -0
  31. package/dist/src/channel-streaming.d.ts +117 -0
  32. package/dist/src/channel-streaming.js +645 -0
  33. package/dist/src/channel-types.d.ts +207 -0
  34. package/dist/src/channel-types.js +40 -0
  35. package/dist/src/channel-typing.d.ts +17 -0
  36. package/dist/src/channel-typing.js +79 -0
  37. package/dist/src/channel-util.d.ts +78 -0
  38. package/dist/src/channel-util.js +524 -0
  39. package/dist/src/channel.d.ts +14 -0
  40. package/dist/src/channel.js +1023 -0
  41. package/dist/src/config.d.ts +18 -0
  42. package/dist/src/config.js +38 -0
  43. package/dist/src/inbound-media.d.ts +37 -0
  44. package/{src/inbound-media.ts → dist/src/inbound-media.js} +33 -81
  45. package/dist/src/media-upload.d.ts +86 -0
  46. package/dist/src/media-upload.js +1222 -0
  47. package/dist/src/setup-core.d.ts +72 -0
  48. package/{src/setup-core.ts → dist/src/setup-core.js} +106 -194
  49. package/dist/src/user-agent.d.ts +4 -0
  50. package/dist/src/user-agent.js +6 -0
  51. package/openclaw.plugin.json +86 -0
  52. package/package.json +9 -13
  53. package/setup-entry.ts +0 -6
  54. package/src/channel.ts +0 -3862
  55. package/src/config.ts +0 -29
  56. package/src/media-upload.ts +0 -983
  57. package/src/remote-browser-support.ts +0 -64
  58. package/src/user-agent.ts +0 -17
@@ -0,0 +1,645 @@
1
+ import { resolveOutboundMediaUrls } from "openclaw/plugin-sdk/reply-payload";
2
+ import { logDebug, logWarn } from "./channel-runtime.js";
3
+ import {
4
+ buildPendingMessageContextForRun,
5
+ clearBindingRunId,
6
+ discardSiderRunState,
7
+ consumePendingMessageContextForRun,
8
+ enqueueCompletedParts,
9
+ flushFinalQueuedPartForRun,
10
+ flushQueuedPartsExceptTailForRun,
11
+ resolvePendingFinalTextForRun,
12
+ hasTextParts
13
+ } from "./channel-state.js";
14
+ import { mergeTextSegments } from "./channel-util.js";
15
+ import {
16
+ buildStreamingStartEvent,
17
+ buildStreamingDeltaEvent,
18
+ buildStreamingDoneEvent,
19
+ buildReasoningStartEvent,
20
+ buildReasoningDeltaEvent,
21
+ buildReasoningDoneEvent,
22
+ buildTextPart
23
+ } from "./channel-builders.js";
24
+ import {
25
+ sendSiderEventBestEffort,
26
+ sendMessageToSider
27
+ } from "./channel-relay.js";
28
+ import { buildSiderPartsFromReplyPayload } from "./media-upload.js";
29
+ function cleanupSiderRunAfterReply(params) {
30
+ clearBindingRunId(params.streamState.sessionKey, params.runId);
31
+ discardSiderRunState(params.runId);
32
+ params.streamState.currentRunId = void 0;
33
+ if (params.resetFallbackText !== false) {
34
+ resetAllFallbackTextState(params.streamState);
35
+ }
36
+ }
37
+ async function openStreamingSessionIfNeeded(params) {
38
+ if (params.laneState.active && params.laneState.streamId) {
39
+ return;
40
+ }
41
+ params.laneState.active = true;
42
+ params.laneState.streamId = crypto.randomUUID();
43
+ params.laneState.seq = 0;
44
+ const streamStartEvent = buildStreamingStartEvent({
45
+ sessionId: params.sessionId,
46
+ streamId: params.laneState.streamId,
47
+ accountId: params.account.accountId
48
+ });
49
+ await sendSiderEventBestEffort({
50
+ account: params.account,
51
+ sessionId: params.sessionId,
52
+ event: streamStartEvent,
53
+ context: "stream.start"
54
+ });
55
+ }
56
+ async function openReasoningSessionIfNeeded(params) {
57
+ if (params.laneState.active && params.laneState.streamId) {
58
+ return;
59
+ }
60
+ params.laneState.active = true;
61
+ params.laneState.streamId = crypto.randomUUID();
62
+ params.laneState.seq = 0;
63
+ const reasoningStartEvent = buildReasoningStartEvent({
64
+ sessionId: params.sessionId,
65
+ streamId: params.laneState.streamId,
66
+ accountId: params.account.accountId
67
+ });
68
+ logDebug("sending reasoning start event", {
69
+ accountId: params.account.accountId,
70
+ sessionId: params.sessionId,
71
+ eventType: reasoningStartEvent.eventType,
72
+ streamId: params.laneState.streamId,
73
+ context: "reasoning.start"
74
+ });
75
+ await sendSiderEventBestEffort({
76
+ account: params.account,
77
+ sessionId: params.sessionId,
78
+ event: reasoningStartEvent,
79
+ context: "reasoning.start"
80
+ });
81
+ }
82
+ async function sendStreamingDeltaEvent(params) {
83
+ if (!params.delta) {
84
+ return;
85
+ }
86
+ await openStreamingSessionIfNeeded({
87
+ account: params.account,
88
+ sessionId: params.sessionId,
89
+ laneState: params.streamState.answer
90
+ });
91
+ params.streamState.answer.seq += 1;
92
+ const streamDeltaEvent = buildStreamingDeltaEvent({
93
+ sessionId: params.sessionId,
94
+ streamId: params.streamState.answer.streamId,
95
+ seq: params.streamState.answer.seq,
96
+ delta: params.delta,
97
+ text: params.text,
98
+ accountId: params.account.accountId
99
+ });
100
+ logDebug("sending stream delta event", {
101
+ accountId: params.account.accountId,
102
+ sessionId: params.sessionId,
103
+ eventType: streamDeltaEvent.eventType,
104
+ streamId: params.streamState.answer.streamId,
105
+ seq: params.streamState.answer.seq,
106
+ deltaLength: params.delta.length,
107
+ textLength: params.text.length,
108
+ context: params.context
109
+ });
110
+ await sendSiderEventBestEffort({
111
+ account: params.account,
112
+ sessionId: params.sessionId,
113
+ event: streamDeltaEvent,
114
+ context: params.context
115
+ });
116
+ }
117
+ async function sendReasoningDeltaEvent(params) {
118
+ if (!params.delta) {
119
+ return;
120
+ }
121
+ await openReasoningSessionIfNeeded({
122
+ account: params.account,
123
+ sessionId: params.sessionId,
124
+ laneState: params.streamState.reasoning
125
+ });
126
+ params.streamState.reasoning.seq += 1;
127
+ const reasoningDeltaEvent = buildReasoningDeltaEvent({
128
+ sessionId: params.sessionId,
129
+ streamId: params.streamState.reasoning.streamId,
130
+ seq: params.streamState.reasoning.seq,
131
+ delta: params.delta,
132
+ text: params.text,
133
+ accountId: params.account.accountId
134
+ });
135
+ logDebug("sending reasoning delta event", {
136
+ accountId: params.account.accountId,
137
+ sessionId: params.sessionId,
138
+ eventType: reasoningDeltaEvent.eventType,
139
+ streamId: params.streamState.reasoning.streamId,
140
+ seq: params.streamState.reasoning.seq,
141
+ deltaLength: params.delta.length,
142
+ textLength: params.text.length,
143
+ context: params.context
144
+ });
145
+ await sendSiderEventBestEffort({
146
+ account: params.account,
147
+ sessionId: params.sessionId,
148
+ event: reasoningDeltaEvent,
149
+ context: params.context
150
+ });
151
+ }
152
+ async function closeStreamingSessionIfActive(params) {
153
+ if (!params.streamState.answer.active || !params.streamState.answer.streamId) {
154
+ return;
155
+ }
156
+ params.streamState.answer.seq += 1;
157
+ const streamDoneEvent = buildStreamingDoneEvent({
158
+ sessionId: params.sessionId,
159
+ streamId: params.streamState.answer.streamId,
160
+ seq: params.streamState.answer.seq,
161
+ accountId: params.account.accountId,
162
+ reason: params.reason
163
+ });
164
+ await sendSiderEventBestEffort({
165
+ account: params.account,
166
+ sessionId: params.sessionId,
167
+ event: streamDoneEvent,
168
+ context: params.context
169
+ });
170
+ params.streamState.answer.active = false;
171
+ params.streamState.answer.streamId = void 0;
172
+ params.streamState.answer.seq = 0;
173
+ }
174
+ async function closeReasoningSessionIfActive(params) {
175
+ if (!params.streamState.reasoning.active || !params.streamState.reasoning.streamId) {
176
+ return;
177
+ }
178
+ params.streamState.reasoning.seq += 1;
179
+ const reasoningDoneEvent = buildReasoningDoneEvent({
180
+ sessionId: params.sessionId,
181
+ streamId: params.streamState.reasoning.streamId,
182
+ seq: params.streamState.reasoning.seq,
183
+ accountId: params.account.accountId,
184
+ reason: params.reason
185
+ });
186
+ logDebug("sending reasoning done event", {
187
+ accountId: params.account.accountId,
188
+ sessionId: params.sessionId,
189
+ eventType: reasoningDoneEvent.eventType,
190
+ streamId: params.streamState.reasoning.streamId,
191
+ seq: params.streamState.reasoning.seq,
192
+ reason: params.reason,
193
+ context: params.context
194
+ });
195
+ await sendSiderEventBestEffort({
196
+ account: params.account,
197
+ sessionId: params.sessionId,
198
+ event: reasoningDoneEvent,
199
+ context: params.context
200
+ });
201
+ params.streamState.reasoning.active = false;
202
+ params.streamState.reasoning.streamId = void 0;
203
+ params.streamState.reasoning.seq = 0;
204
+ }
205
+ function enqueueStreamEventTask(params) {
206
+ const next = params.streamState.streamEventQueue.then(params.task).catch((err) => {
207
+ logWarn("sider stream event queue task failed", {
208
+ error: String(err)
209
+ });
210
+ });
211
+ params.streamState.streamEventQueue = next;
212
+ return next;
213
+ }
214
+ async function flushStreamEventQueue(streamState) {
215
+ await streamState.streamEventQueue;
216
+ }
217
+ function derivePartialDelta(params) {
218
+ const prev = params.previous;
219
+ const next = params.next;
220
+ if (!next) {
221
+ return "";
222
+ }
223
+ if (!prev) {
224
+ return next;
225
+ }
226
+ if (next === prev) {
227
+ return "";
228
+ }
229
+ if (next.startsWith(prev)) {
230
+ return next.slice(prev.length);
231
+ }
232
+ if (prev.startsWith(next)) {
233
+ return "";
234
+ }
235
+ const maxOverlap = Math.min(prev.length, next.length);
236
+ for (let overlap = maxOverlap; overlap > 0; overlap -= 1) {
237
+ if (prev.endsWith(next.slice(0, overlap))) {
238
+ return next.slice(overlap);
239
+ }
240
+ }
241
+ return next;
242
+ }
243
+ function mergeBlockTextIntoStreamState(params) {
244
+ params.streamState.answer.accumulatedBlockText = mergeTextSegments(
245
+ params.streamState.answer.accumulatedBlockText,
246
+ params.text
247
+ );
248
+ if (params.text) {
249
+ if (params.streamState.answer.assistantSeq <= 0) {
250
+ params.streamState.answer.assistantSeq = 1;
251
+ }
252
+ params.streamState.answer.fallbackAssistantSeq = params.streamState.answer.assistantSeq;
253
+ params.streamState.answer.fallbackCurrentText = mergeTextSegments(
254
+ params.streamState.answer.fallbackCurrentText,
255
+ params.text
256
+ );
257
+ }
258
+ }
259
+ function resolveCurrentStreamVisibleText(streamState) {
260
+ if (streamState.answer.streamDeltaMode === "partial" && streamState.answer.partialSnapshot) {
261
+ return streamState.answer.partialSnapshot;
262
+ }
263
+ return streamState.answer.accumulatedBlockText;
264
+ }
265
+ function resolveFallbackFinalText(streamState) {
266
+ if (streamState.answer.assistantSeq <= 0 || streamState.answer.fallbackAssistantSeq !== streamState.answer.assistantSeq) {
267
+ return "";
268
+ }
269
+ return mergeTextSegments(
270
+ streamState.answer.fallbackTextPrefix,
271
+ streamState.answer.fallbackCurrentText
272
+ ).trim();
273
+ }
274
+ function commitCurrentStreamTextToFallbackPrefix(streamState) {
275
+ if (streamState.answer.assistantSeq <= 0) {
276
+ streamState.answer.assistantSeq = 1;
277
+ }
278
+ streamState.answer.fallbackAssistantSeq = streamState.answer.assistantSeq;
279
+ streamState.answer.fallbackTextPrefix = mergeTextSegments(
280
+ streamState.answer.fallbackTextPrefix,
281
+ streamState.answer.fallbackCurrentText
282
+ );
283
+ streamState.answer.fallbackCurrentText = "";
284
+ }
285
+ function rotateAssistantMessageFallbackState(streamState) {
286
+ streamState.answer.assistantSeq += 1;
287
+ streamState.answer.fallbackAssistantSeq = streamState.answer.assistantSeq;
288
+ streamState.answer.fallbackCurrentText = "";
289
+ streamState.answer.fallbackTextPrefix = "";
290
+ }
291
+ function resetCurrentStreamTextState(streamState) {
292
+ streamState.answer.blockDeltaCount = 0;
293
+ streamState.answer.partialDeltaCount = 0;
294
+ streamState.answer.streamDeltaMode = "undecided";
295
+ streamState.answer.partialSnapshot = "";
296
+ streamState.answer.accumulatedBlockText = "";
297
+ }
298
+ function resetAllFallbackTextState(streamState) {
299
+ streamState.answer.assistantSeq = 0;
300
+ streamState.answer.fallbackAssistantSeq = 0;
301
+ streamState.answer.fallbackCurrentText = "";
302
+ streamState.answer.fallbackTextPrefix = "";
303
+ resetCurrentStreamTextState(streamState);
304
+ }
305
+ function resetReasoningStreamState(streamState) {
306
+ streamState.reasoning.snapshot = "";
307
+ streamState.reasoning.deltaCount = 0;
308
+ }
309
+ async function handleStreamingPartialSnapshot(params) {
310
+ if (params.streamState.answer.streamDeltaMode === "block") {
311
+ return;
312
+ }
313
+ if (params.streamState.answer.streamDeltaMode === "undecided") {
314
+ params.streamState.answer.streamDeltaMode = "partial";
315
+ }
316
+ if (!params.snapshot) {
317
+ return;
318
+ }
319
+ const delta = derivePartialDelta({
320
+ previous: params.streamState.answer.partialSnapshot,
321
+ next: params.snapshot
322
+ });
323
+ if (params.streamState.answer.assistantSeq <= 0) {
324
+ params.streamState.answer.assistantSeq = 1;
325
+ }
326
+ params.streamState.answer.fallbackAssistantSeq = params.streamState.answer.assistantSeq;
327
+ params.streamState.answer.partialSnapshot = params.snapshot;
328
+ params.streamState.answer.fallbackCurrentText = params.snapshot;
329
+ if (!delta) {
330
+ return;
331
+ }
332
+ await sendStreamingDeltaEvent({
333
+ account: params.account,
334
+ sessionId: params.sessionId,
335
+ streamState: params.streamState,
336
+ delta,
337
+ text: params.snapshot,
338
+ context: "stream.delta.partial"
339
+ });
340
+ params.streamState.answer.partialDeltaCount += 1;
341
+ }
342
+ async function handleReasoningSnapshot(params) {
343
+ if (!params.snapshot.trim()) {
344
+ return;
345
+ }
346
+ const delta = derivePartialDelta({
347
+ previous: params.streamState.reasoning.snapshot,
348
+ next: params.snapshot
349
+ });
350
+ params.streamState.reasoning.snapshot = params.snapshot;
351
+ if (!delta) {
352
+ return;
353
+ }
354
+ await sendReasoningDeltaEvent({
355
+ account: params.account,
356
+ sessionId: params.sessionId,
357
+ streamState: params.streamState,
358
+ delta,
359
+ text: params.snapshot,
360
+ context: "reasoning.delta"
361
+ });
362
+ params.streamState.reasoning.deltaCount += 1;
363
+ }
364
+ async function persistQueuedCompletedParts(params) {
365
+ if (params.parts.length === 0) {
366
+ return;
367
+ }
368
+ const runId = params.streamState.currentRunId;
369
+ if (!runId) {
370
+ for (const part of params.parts) {
371
+ await sendMessageToSider({
372
+ account: params.account,
373
+ sessionId: params.sessionId,
374
+ parts: [part]
375
+ });
376
+ }
377
+ return;
378
+ }
379
+ enqueueCompletedParts({
380
+ runId,
381
+ parts: params.parts,
382
+ sessionKey: params.streamState.sessionKey,
383
+ sessionId: params.sessionId,
384
+ accountId: params.account.accountId
385
+ });
386
+ await flushQueuedPartsExceptTailForRun({
387
+ runId,
388
+ account: params.account,
389
+ sessionId: params.sessionId,
390
+ context: params.context
391
+ });
392
+ }
393
+ function resolvePreferredDeferredFinalText(params) {
394
+ const fallbackText = (resolvePendingFinalTextForRun(params.runId) || resolveFallbackFinalText(params.streamState)).trim();
395
+ if (!hasTextParts(params.baseParts)) {
396
+ return fallbackText;
397
+ }
398
+ return "";
399
+ }
400
+ async function finalizeQueuedRunMessages(params) {
401
+ const runId = params.streamState.currentRunId;
402
+ if (!runId) {
403
+ if (params.parts.length === 0) {
404
+ return false;
405
+ }
406
+ for (let index = 0; index < params.parts.length; index += 1) {
407
+ const part = params.parts[index];
408
+ await sendMessageToSider({
409
+ account: params.account,
410
+ sessionId: params.sessionId,
411
+ parts: [part]
412
+ });
413
+ }
414
+ params.streamState.persistedFinalText = true;
415
+ return true;
416
+ }
417
+ if (params.parts.length > 0) {
418
+ enqueueCompletedParts({
419
+ runId,
420
+ parts: params.parts,
421
+ sessionKey: params.streamState.sessionKey,
422
+ sessionId: params.sessionId,
423
+ accountId: params.account.accountId
424
+ });
425
+ }
426
+ await flushQueuedPartsExceptTailForRun({
427
+ runId,
428
+ account: params.account,
429
+ sessionId: params.sessionId,
430
+ context: `${params.context}.except_tail`
431
+ });
432
+ const persisted = await flushFinalQueuedPartForRun({
433
+ runId,
434
+ account: params.account,
435
+ sessionId: params.sessionId,
436
+ stopReason: params.stopReason,
437
+ context: `${params.context}.final_tail`
438
+ });
439
+ if (persisted) {
440
+ params.streamState.persistedFinalText = true;
441
+ }
442
+ return persisted;
443
+ }
444
+ async function deliverReplyPayloadToSider(params) {
445
+ const payloadText = typeof params.payload.text === "string" ? params.payload.text : "";
446
+ const payloadMediaUrls = resolveOutboundMediaUrls(params.payload);
447
+ if (params.kind === "block") {
448
+ const delta = payloadText;
449
+ if (delta.length > 0) {
450
+ params.streamState.answer.blockDeltaCount += 1;
451
+ if (params.streamState.answer.streamDeltaMode !== "partial") {
452
+ if (params.streamState.answer.streamDeltaMode === "undecided") {
453
+ params.streamState.answer.streamDeltaMode = "block";
454
+ }
455
+ mergeBlockTextIntoStreamState({
456
+ streamState: params.streamState,
457
+ text: delta
458
+ });
459
+ await sendStreamingDeltaEvent({
460
+ account: params.account,
461
+ sessionId: params.sessionId,
462
+ streamState: params.streamState,
463
+ delta,
464
+ text: params.streamState.answer.accumulatedBlockText,
465
+ context: "stream.delta.block"
466
+ });
467
+ } else {
468
+ logDebug("skip block stream delta because partial streaming mode is active", {
469
+ accountId: params.account.accountId,
470
+ sessionId: params.sessionId,
471
+ deltaLength: delta.length,
472
+ partialDeltaCount: params.streamState.answer.partialDeltaCount,
473
+ streamDeltaMode: params.streamState.answer.streamDeltaMode
474
+ });
475
+ }
476
+ }
477
+ if (payloadMediaUrls.length === 0) {
478
+ return;
479
+ }
480
+ logDebug("block payload contains media; sending persisted sider message", {
481
+ accountId: params.account.accountId,
482
+ sessionId: params.sessionId,
483
+ mediaCount: payloadMediaUrls.length,
484
+ hasText: delta.length > 0
485
+ });
486
+ }
487
+ if (params.kind === "final") {
488
+ await flushStreamEventQueue(params.streamState);
489
+ if (!params.streamState.answer.active && params.streamState.answer.blockDeltaCount === 0) {
490
+ const finalText = payloadText;
491
+ if (finalText.length > 0) {
492
+ logDebug("no block delta observed; sending synthetic stream events from final payload", {
493
+ accountId: params.account.accountId,
494
+ sessionId: params.sessionId,
495
+ textLength: finalText.length
496
+ });
497
+ params.streamState.answer.accumulatedBlockText = finalText;
498
+ if (params.streamState.answer.assistantSeq <= 0) {
499
+ params.streamState.answer.assistantSeq = 1;
500
+ }
501
+ params.streamState.answer.fallbackAssistantSeq = params.streamState.answer.assistantSeq;
502
+ params.streamState.answer.fallbackCurrentText = finalText;
503
+ await sendStreamingDeltaEvent({
504
+ account: params.account,
505
+ sessionId: params.sessionId,
506
+ streamState: params.streamState,
507
+ delta: finalText,
508
+ text: finalText,
509
+ context: "stream.delta.final-fallback"
510
+ });
511
+ }
512
+ }
513
+ await closeStreamingSessionIfActive({
514
+ account: params.account,
515
+ sessionId: params.sessionId,
516
+ streamState: params.streamState,
517
+ reason: "final",
518
+ context: "stream.done"
519
+ });
520
+ params.streamState.pendingFinalPayloads.push(params.payload);
521
+ return;
522
+ }
523
+ const { parts: baseParts } = await buildSiderPartsFromReplyPayload({
524
+ account: params.account,
525
+ sessionId: params.sessionId,
526
+ payload: params.payload,
527
+ mediaLocalRoots: params.mediaLocalRoots
528
+ });
529
+ if (baseParts.length === 0) {
530
+ return;
531
+ }
532
+ const completedParts = params.kind === "block" ? baseParts.filter((part) => part.type !== "core.text") : baseParts;
533
+ if (completedParts.length === 0) {
534
+ return;
535
+ }
536
+ logDebug("queueing sider outbound message parts from payload", {
537
+ accountId: params.account.accountId,
538
+ sessionId: params.sessionId,
539
+ kind: params.kind,
540
+ partTypes: completedParts.map((part) => part.type),
541
+ mediaCount: payloadMediaUrls.length
542
+ });
543
+ await persistQueuedCompletedParts({
544
+ account: params.account,
545
+ sessionId: params.sessionId,
546
+ streamState: params.streamState,
547
+ parts: completedParts,
548
+ context: `payload.${params.kind}`
549
+ });
550
+ }
551
+ async function persistDeferredFinalReplyPayloadToSider(params) {
552
+ const { parts: baseParts } = await buildSiderPartsFromReplyPayload({
553
+ account: params.account,
554
+ sessionId: params.sessionId,
555
+ payload: params.payload,
556
+ mediaLocalRoots: params.mediaLocalRoots
557
+ });
558
+ const selectedFinalText = resolvePreferredDeferredFinalText({
559
+ streamState: params.streamState,
560
+ runId: params.streamState.currentRunId,
561
+ baseParts
562
+ });
563
+ const messageContext = buildPendingMessageContextForRun({
564
+ accountId: params.account.accountId,
565
+ runId: params.streamState.currentRunId,
566
+ includeFinalThinking: true
567
+ });
568
+ const parts = hasTextParts(baseParts) ? [...messageContext.parts, ...baseParts] : [
569
+ ...messageContext.parts,
570
+ ...selectedFinalText ? [buildTextPart(selectedFinalText)] : [],
571
+ ...baseParts
572
+ ];
573
+ logDebug("finalizing deferred sider outbound message parts from payload", {
574
+ accountId: params.account.accountId,
575
+ sessionId: params.sessionId,
576
+ runId: params.streamState.currentRunId,
577
+ partTypes: parts.map((part) => part.type),
578
+ selectedFinalTextLength: selectedFinalText.length
579
+ });
580
+ const cleanupRunId = messageContext.runId ?? params.streamState.currentRunId;
581
+ await finalizeQueuedRunMessages({
582
+ account: params.account,
583
+ sessionId: params.sessionId,
584
+ parts,
585
+ streamState: params.streamState,
586
+ stopReason: messageContext.stopReason,
587
+ context: "final.payload"
588
+ });
589
+ consumePendingMessageContextForRun({
590
+ runId: cleanupRunId,
591
+ consumeFinalThinking: true
592
+ });
593
+ cleanupSiderRunAfterReply({
594
+ streamState: params.streamState,
595
+ runId: cleanupRunId
596
+ });
597
+ }
598
+ async function persistStandaloneReplyPayloadToSider(params) {
599
+ const { parts } = await buildSiderPartsFromReplyPayload({
600
+ account: params.account,
601
+ sessionId: params.sessionId,
602
+ payload: params.payload,
603
+ mediaLocalRoots: params.mediaLocalRoots
604
+ });
605
+ if (parts.length === 0) {
606
+ return;
607
+ }
608
+ logDebug("sending standalone deferred final payload to sider", {
609
+ accountId: params.account.accountId,
610
+ sessionId: params.sessionId,
611
+ partTypes: parts.map((part) => part.type),
612
+ isError: params.payload.isError === true
613
+ });
614
+ await sendMessageToSider({
615
+ account: params.account,
616
+ sessionId: params.sessionId,
617
+ parts
618
+ });
619
+ }
620
+ export {
621
+ cleanupSiderRunAfterReply,
622
+ closeReasoningSessionIfActive,
623
+ closeStreamingSessionIfActive,
624
+ commitCurrentStreamTextToFallbackPrefix,
625
+ deliverReplyPayloadToSider,
626
+ derivePartialDelta,
627
+ enqueueStreamEventTask,
628
+ finalizeQueuedRunMessages,
629
+ flushStreamEventQueue,
630
+ handleReasoningSnapshot,
631
+ handleStreamingPartialSnapshot,
632
+ mergeBlockTextIntoStreamState,
633
+ openReasoningSessionIfNeeded,
634
+ openStreamingSessionIfNeeded,
635
+ persistDeferredFinalReplyPayloadToSider,
636
+ persistStandaloneReplyPayloadToSider,
637
+ resetAllFallbackTextState,
638
+ resetCurrentStreamTextState,
639
+ resetReasoningStreamState,
640
+ resolveCurrentStreamVisibleText,
641
+ resolveFallbackFinalText,
642
+ rotateAssistantMessageFallbackState,
643
+ sendReasoningDeltaEvent,
644
+ sendStreamingDeltaEvent
645
+ };