Skip to content

fix: emit message:sent hook on Telegram streaming preview finalization#50917

Merged
obviyus merged 8 commits intoopenclaw:mainfrom
bugkill3r:fix/telegram-message-sent-hook-streaming
Mar 20, 2026
Merged

fix: emit message:sent hook on Telegram streaming preview finalization#50917
obviyus merged 8 commits intoopenclaw:mainfrom
bugkill3r:fix/telegram-message-sent-hook-streaming

Conversation

@bugkill3r
Copy link
Copy Markdown
Contributor

Summary

  • Emit message:sent hook when Telegram streaming preview is finalized, not just on sendPayload path
  • Add messageId to the preview-delivered callback for parity with normal delivery
  • Skip hook emission for preview-retained paths where delivery is uncertain

Closes #50878

@openclaw-barnacle openclaw-barnacle bot added channel: telegram Channel integration: telegram size: S labels Mar 20, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 20, 2026

Greptile Summary

This PR correctly closes a gap where message:sent hooks were only fired on the sendPayload path, leaving preview-finalized deliveries (Telegram streaming previews that are edited in place) silent to hook consumers. The fix is well-targeted: a new onPreviewDelivered callback is threaded through createLaneTextDeliverer, called from every "preview-finalized" return site, and left un-called for "preview-retained" paths where the visible content is ambiguous.

Key changes:

  • A new "regressive-skipped" variant is split out of the previous "edited" return value in tryUpdatePreviewForLane / finalizePreview, allowing the caller to emit the hook with the actual visible text (lastPartialText / archivedPreview.textSnapshot) rather than the shorter incoming text when a regressive update is skipped.
  • emitMessageSentHooks is exported from delivery.replies.ts and re-exported through delivery.ts so bot-message-dispatch.ts can reuse it, keeping the hook payload consistent with the sendPayload path.
  • Six new tests cover the primary paths. One gap remains: the stopCreatesFirstPreview sub-path (where the stream had no message ID before stopDraftLane is called) exercises the previewMessageId ?? lane.stream?.messageId() fallback, but there is no test asserting that onPreviewDelivered fires with the correct post-stop message ID in that scenario.
  • Minor: the ?? text fallbacks in the regressive-skip handlers (archivedPreview.textSnapshot ?? text and lane.lastPartialText ?? text) are dead code since both fields are required string values and the ?? operator only activates on null/undefined.

Confidence Score: 4/5

  • This PR is safe to merge; the core logic is correct, hooks fire on all expected paths, and the previously problematic regressive-skip content mismatch is fixed.
  • The implementation is logically sound across all preview-finalized delivery paths. The "regressive-skipped" split and the visible-text selection are correct. The only gaps are a missing test for the stopCreatesFirstPreview path's onPreviewDelivered emission, and dead ?? text fallbacks that are unreachable at runtime. No functional bugs were found.
  • extensions/telegram/src/lane-delivery.test.ts — the stopCreatesFirstPreview + onPreviewDelivered scenario is untested.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/telegram/src/lane-delivery.test.ts
Line: 561-568

Comment:
**Missing test for `stopCreatesFirstPreview` + `onPreviewDelivered` path**

The existing test covers the case where the stream already has a message ID before delivery (`answerMessageId: 999`), so `previewMessageId` is captured as a valid number and the `?? lane.stream?.messageId()` fallback on lines 536 and 544 of `lane-delivery-text-deliverer.ts` is never actually exercised.

The path where stop creates the _first_ preview message (i.e., `answerMessageIdAfterStop: 777`, no initial `answerMessageId`) is exercised by the existing "primes stop-created previews with final text before editing" test, but that test makes no assertion on `onPreviewDelivered`. This leaves the `previewMessageId ?? lane.stream?.messageId()` fallback logic — which was specifically introduced in this PR to surface the message ID for that case — untested.

Consider adding a test similar to the existing "primes stop-created previews with final text before editing" case that also asserts the hook fires with the correct message ID:

```ts
it("calls onPreviewDelivered when stop-created first preview is finalized", async () => {
  const harness = createHarness({ answerMessageIdAfterStop: 777 });

  const result = await harness.deliverLaneText({
    laneName: "answer",
    text: "Hello final",
    payload: { text: "Hello final" },
    infoKind: "final",
  });

  expect(result).toBe("preview-finalized");
  expect(harness.onPreviewDelivered).toHaveBeenCalledWith("Hello final", 777);
});
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/telegram/src/lane-delivery-text-deliverer.ts
Line: 435-439

Comment:
**Unreachable fallback in `archivedPreview.textSnapshot ?? text`**

`ArchivedPreview.textSnapshot` is a required `string` field, so it can never be `null` or `undefined` at runtime. The `?? text` fallback is therefore dead code — it can never activate.

The same pattern appears at line 543 in the active-stream path (`lane.lastPartialText ?? text`): `DraftLaneState.lastPartialText` is also typed as a required `string`, so the fallback is similarly unreachable there.

Both expressions could be simplified:

```suggestion
        const visibleText = archivedPreview.textSnapshot;
        params.onPreviewDelivered?.(visibleText, archivedPreview.messageId);
```

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: "fix: pass visible pr..."

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c465b2b3b8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +528 to +530
if (finalized === "edited") {
markActivePreviewComplete(laneName);
params.onPreviewDelivered?.(text, previewMessageId ?? lane.stream?.messageId());
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don't emit message_sent for regressive finals that skip the edit

finalized === "edited" is broader than a real preview finalization here: tryUpdatePreviewForLane() also returns "edited" from the regressive-skip branch in extensions/telegram/src/lane-delivery-text-deliverer.ts:341-344, where we intentionally keep the longer preview text and never call editPreview. In that case this callback will emit message_sent with the shorter final text even though Telegram is still showing the older preview content (for example when the last partial is "Sure." and the final becomes "Sure"). Any plugin or internal message:sent automation will record content that was not actually sent.

Useful? React with 👍 / 👎.

@bugkill3r
Copy link
Copy Markdown
Contributor Author

@greptile-apps review

Comment on lines 528 to 531
if (finalized === "edited") {
markActivePreviewComplete(laneName);
params.onPreviewDelivered?.(text, previewMessageId ?? lane.stream?.messageId());
return "preview-finalized";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Regressive-skip path passes wrong content to hook

When shouldSkipRegressivePreviewUpdate returns true (i.e., the final text is shorter than the current streamed preview), tryUpdatePreviewForLane returns "edited" without modifying the Telegram message — the longer preview text remains visible. However, onPreviewDelivered is then called with text (the shorter, regressed value), so hook consumers receive content that doesn't match what the user actually sees.

Concretely, the existing test "keeps existing preview when final text regresses" sets lastPartialText = "Recovered final answer." but delivers text = "Recovered final answer" (no period). After this PR, onPreviewDelivered("Recovered final answer", 999) fires even though Telegram still shows "Recovered final answer.".

To align the hook content with the displayed message in this case, consider passing lane.lastPartialText (the actual visible text) instead of text:

// Before emitting, prefer the current preview text if the edit was skipped
// (regressive-skip): the displayed message is the longer preview, not `text`.
params.onPreviewDelivered?.(text, previewMessageId ?? lane.stream?.messageId());

The new onPreviewDelivered tests don't cover this path — adding a case would help catch regressions.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/telegram/src/lane-delivery-text-deliverer.ts
Line: 528-531

Comment:
**Regressive-skip path passes wrong content to hook**

When `shouldSkipRegressivePreviewUpdate` returns `true` (i.e., the final text is shorter than the current streamed preview), `tryUpdatePreviewForLane` returns `"edited"` without modifying the Telegram message — the longer preview text remains visible. However, `onPreviewDelivered` is then called with `text` (the shorter, regressed value), so hook consumers receive content that doesn't match what the user actually sees.

Concretely, the existing test "keeps existing preview when final text regresses" sets `lastPartialText = "Recovered final answer."` but delivers `text = "Recovered final answer"` (no period). After this PR, `onPreviewDelivered("Recovered final answer", 999)` fires even though Telegram still shows `"Recovered final answer."`.

To align the hook content with the displayed message in this case, consider passing `lane.lastPartialText` (the actual visible text) instead of `text`:

```
// Before emitting, prefer the current preview text if the edit was skipped
// (regressive-skip): the displayed message is the longer preview, not `text`.
params.onPreviewDelivered?.(text, previewMessageId ?? lane.stream?.messageId());
```

The new `onPreviewDelivered` tests don't cover this path — adding a case would help catch regressions.

How can I resolve this? If you propose a fix, please make it concise.

@bugkill3r
Copy link
Copy Markdown
Contributor Author

@greptile-apps review

@bugkill3r
Copy link
Copy Markdown
Contributor Author

@greptile-apps review - please review latest commit be0a6cd which addresses the regressive-skip path

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: be0a6cdfd8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 547 to 551
if (finalized === "retained") {
markActivePreviewComplete(laneName);
// Do not emit onPreviewDelivered for retained paths — the edit
// failed/was ambiguous, so the visible message may still be stale.
return "preview-retained";
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Emit message_sent for stop-flushed retained previews

When the first visible preview is created during stopDraftLane(), tryEditPreviewMessage() returns "retained" precisely because the final text has already been flushed to Telegram (extensions/telegram/src/lane-delivery-text-deliverer.ts:247-252). This new blanket skip therefore drops message_sent / message:sent hooks for a fully delivered text-only final whenever the follow-up edit fails after that stop flush. A transient post-flush edit failure is enough to reproduce it, so this patch still misses one of the preview-finalization paths it was meant to cover.

Useful? React with 👍 / 👎.

Comment on lines +561 to +568
it("calls onPreviewDelivered when preview is finalized via edit", async () => {
const harness = createHarness({ answerMessageId: 999 });

const result = await deliverFinalAnswer(harness, HELLO_FINAL);

expect(result).toBe("preview-finalized");
expect(harness.onPreviewDelivered).toHaveBeenCalledWith(HELLO_FINAL, 999);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing test for stopCreatesFirstPreview + onPreviewDelivered path

The existing test covers the case where the stream already has a message ID before delivery (answerMessageId: 999), so previewMessageId is captured as a valid number and the ?? lane.stream?.messageId() fallback on lines 536 and 544 of lane-delivery-text-deliverer.ts is never actually exercised.

The path where stop creates the first preview message (i.e., answerMessageIdAfterStop: 777, no initial answerMessageId) is exercised by the existing "primes stop-created previews with final text before editing" test, but that test makes no assertion on onPreviewDelivered. This leaves the previewMessageId ?? lane.stream?.messageId() fallback logic — which was specifically introduced in this PR to surface the message ID for that case — untested.

Consider adding a test similar to the existing "primes stop-created previews with final text before editing" case that also asserts the hook fires with the correct message ID:

it("calls onPreviewDelivered when stop-created first preview is finalized", async () => {
  const harness = createHarness({ answerMessageIdAfterStop: 777 });

  const result = await harness.deliverLaneText({
    laneName: "answer",
    text: "Hello final",
    payload: { text: "Hello final" },
    infoKind: "final",
  });

  expect(result).toBe("preview-finalized");
  expect(harness.onPreviewDelivered).toHaveBeenCalledWith("Hello final", 777);
});
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/telegram/src/lane-delivery.test.ts
Line: 561-568

Comment:
**Missing test for `stopCreatesFirstPreview` + `onPreviewDelivered` path**

The existing test covers the case where the stream already has a message ID before delivery (`answerMessageId: 999`), so `previewMessageId` is captured as a valid number and the `?? lane.stream?.messageId()` fallback on lines 536 and 544 of `lane-delivery-text-deliverer.ts` is never actually exercised.

The path where stop creates the _first_ preview message (i.e., `answerMessageIdAfterStop: 777`, no initial `answerMessageId`) is exercised by the existing "primes stop-created previews with final text before editing" test, but that test makes no assertion on `onPreviewDelivered`. This leaves the `previewMessageId ?? lane.stream?.messageId()` fallback logic — which was specifically introduced in this PR to surface the message ID for that case — untested.

Consider adding a test similar to the existing "primes stop-created previews with final text before editing" case that also asserts the hook fires with the correct message ID:

```ts
it("calls onPreviewDelivered when stop-created first preview is finalized", async () => {
  const harness = createHarness({ answerMessageIdAfterStop: 777 });

  const result = await harness.deliverLaneText({
    laneName: "answer",
    text: "Hello final",
    payload: { text: "Hello final" },
    infoKind: "final",
  });

  expect(result).toBe("preview-finalized");
  expect(harness.onPreviewDelivered).toHaveBeenCalledWith("Hello final", 777);
});
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fe4934e781

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +513 to +516
onPreviewDelivered: (content, messageId) => {
const hookRunner = getGlobalHookRunner();
const hasMessageSentHooks = hookRunner?.hasHooks("message_sent") ?? false;
emitMessageSentHooks({
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Run message_sending hooks before emitting preview message_sent

onPreviewDelivered() emits message_sent/message:sent directly here, but deliverReplies() is still the only Telegram path that runs runMessageSending() and updates or cancels the outgoing content (extensions/telegram/src/bot/delivery.replies.ts:607-633). In deployments that use a message_sending plugin for Telegram, any preview-finalized reply will now report success with the raw preview text even though the sending hook never had a chance to rewrite or veto it, so hook consumers can observe a message that was never processed by the normal outbound pipeline.

Useful? React with 👍 / 👎.

@obviyus obviyus self-assigned this Mar 20, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 67e7786239

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +631 to +632
if (info.kind === "final") {
emitPreviewFinalizedHook(result);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Emit preview-finalized hooks for buffered answer finals

When a final payload is split into reasoning plus answer text, the answer segment is buffered at extensions/telegram/src/bot-message-dispatch.ts:609-618 and later sent via flushBufferedFinalAnswer() at extensions/telegram/src/bot-message-dispatch.ts:588-605. This change only emits the new preview-finalized hook on the direct deliverLaneText() result in the main loop, so buffered finals that stay in the preview still never fire message:sent. That means mixed reasoning/answer replies (for example think-tag finals) still miss the hook for the actual answer message, which is the main preview-finalization case this patch was supposed to cover.

Useful? React with 👍 / 👎.

@obviyus obviyus force-pushed the fix/telegram-message-sent-hook-streaming branch from 67e7786 to 51b3e03 Compare March 20, 2026 17:11
@obviyus obviyus merged commit 4266e26 into openclaw:main Mar 20, 2026
11 checks passed
@obviyus
Copy link
Copy Markdown
Contributor

obviyus commented Mar 20, 2026

Landed on main.

Thanks @bugkill3r.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 51b3e034eb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +488 to +492
emitInternalMessageSentHook({
sessionKeyForInternalHooks: deliveryBaseOptions.sessionKeyForInternalHooks,
chatId: deliveryBaseOptions.chatId,
accountId: deliveryBaseOptions.accountId,
content: result.delivery.content,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Emit plugin message_sent hooks for preview-finalized replies

When a Telegram text-only final is delivered by finalizing the streaming preview, emitPreviewFinalizedHook() only calls emitInternalMessageSentHook(). The normal send path in extensions/telegram/src/bot/delivery.replies.ts invokes runMessageSent(...) for plugin message_sent hooks after each delivered reply, so preview-finalized replies still never reach plugin-based automations or telemetry. This is especially visible when there is no SessionKey, because the new path becomes a total no-op instead of matching normal delivery behavior.

Useful? React with 👍 / 👎.

Yaohua-Leo pushed a commit to Yaohua-Leo/openclaw that referenced this pull request Mar 20, 2026
openclaw#50917)

* fix: emit message:sent hook on Telegram streaming preview finalization

* fix: include messageId in preview-delivered hook callback

* fix: skip message:sent hook for preview-retained paths

* fix: correct JSDoc for onPreviewDelivered callback

* fix: pass visible preview text on regressive-skip path

* fix: remove dead fallbacks and add stopCreatesFirstPreview test

* Update extensions/telegram/src/lane-delivery-text-deliverer.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: align telegram preview sent hooks (openclaw#50917) (thanks @bugkill3r)

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
JohnJAS pushed a commit to JohnJAS/openclaw that referenced this pull request Mar 22, 2026
openclaw#50917)

* fix: emit message:sent hook on Telegram streaming preview finalization

* fix: include messageId in preview-delivered hook callback

* fix: skip message:sent hook for preview-retained paths

* fix: correct JSDoc for onPreviewDelivered callback

* fix: pass visible preview text on regressive-skip path

* fix: remove dead fallbacks and add stopCreatesFirstPreview test

* Update extensions/telegram/src/lane-delivery-text-deliverer.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: align telegram preview sent hooks (openclaw#50917) (thanks @bugkill3r)

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
pholpaphankorn pushed a commit to pholpaphankorn/openclaw that referenced this pull request Mar 22, 2026
openclaw#50917)

* fix: emit message:sent hook on Telegram streaming preview finalization

* fix: include messageId in preview-delivered hook callback

* fix: skip message:sent hook for preview-retained paths

* fix: correct JSDoc for onPreviewDelivered callback

* fix: pass visible preview text on regressive-skip path

* fix: remove dead fallbacks and add stopCreatesFirstPreview test

* Update extensions/telegram/src/lane-delivery-text-deliverer.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: align telegram preview sent hooks (openclaw#50917) (thanks @bugkill3r)

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
frankekn pushed a commit to artwalker/openclaw that referenced this pull request Mar 23, 2026
openclaw#50917)

* fix: emit message:sent hook on Telegram streaming preview finalization

* fix: include messageId in preview-delivered hook callback

* fix: skip message:sent hook for preview-retained paths

* fix: correct JSDoc for onPreviewDelivered callback

* fix: pass visible preview text on regressive-skip path

* fix: remove dead fallbacks and add stopCreatesFirstPreview test

* Update extensions/telegram/src/lane-delivery-text-deliverer.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: align telegram preview sent hooks (openclaw#50917) (thanks @bugkill3r)

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 28, 2026
openclaw#50917)

* fix: emit message:sent hook on Telegram streaming preview finalization

* fix: include messageId in preview-delivered hook callback

* fix: skip message:sent hook for preview-retained paths

* fix: correct JSDoc for onPreviewDelivered callback

* fix: pass visible preview text on regressive-skip path

* fix: remove dead fallbacks and add stopCreatesFirstPreview test

* Update extensions/telegram/src/lane-delivery-text-deliverer.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: align telegram preview sent hooks (openclaw#50917) (thanks @bugkill3r)

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
(cherry picked from commit 4266e26)

# Conflicts:
#	extensions/telegram/src/bot-message-dispatch.test.ts
#	extensions/telegram/src/lane-delivery.test.ts
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 28, 2026
openclaw#50917)

* fix: emit message:sent hook on Telegram streaming preview finalization

* fix: include messageId in preview-delivered hook callback

* fix: skip message:sent hook for preview-retained paths

* fix: correct JSDoc for onPreviewDelivered callback

* fix: pass visible preview text on regressive-skip path

* fix: remove dead fallbacks and add stopCreatesFirstPreview test

* Update extensions/telegram/src/lane-delivery-text-deliverer.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: align telegram preview sent hooks (openclaw#50917) (thanks @bugkill3r)

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
(cherry picked from commit 4266e26)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: telegram Channel integration: telegram size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

message:sent hook not emitted when Telegram streaming preview finalizes

2 participants