Skip to content

feat(telegram): unify progress fallback with assistant preview lane#95522

Closed
snowzlmbot wants to merge 10 commits into
openclaw:mainfrom
snowzlmbot:fix/telegram-unify-progress-placeholder-assistant-preview
Closed

feat(telegram): unify progress fallback with assistant preview lane#95522
snowzlmbot wants to merge 10 commits into
openclaw:mainfrom
snowzlmbot:fix/telegram-unify-progress-placeholder-assistant-preview

Conversation

@snowzlmbot

@snowzlmbot snowzlmbot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes #95004.

Telegram progress streaming currently has two related gaps:

  • default Telegram progress streaming can appear stuck when upstream answer activity exists but no tool/progress row is available yet;
  • users who want full assistant partial previews while keeping the existing progress/tool draft need an explicit opt-in path rather than replacing progress mode with partial/block behavior.

This PR is a canonical combined proposal that keeps the low-noise default fix from #95183 and incorporates the optional assistant-preview lane from #82303.

Relationship to Prior PRs / Attribution

This PR intentionally combines two existing approaches:

Credit for the assistant-preview lane design, config surface, and original regression coverage goes to @Fuma2013 in #82303. This branch cherry-picks those commits and preserves their author attribution, then resolves the interaction with #95183's richer progress draft behavior.

Summary

  • Keep the default Telegram progress behavior low-noise:
    • no assistant answer text is streamed into the progress draft by default;
    • upstream answer activity can still materialize a stable label-only progress placeholder so Telegram does not look stuck.
  • Keep bounded short-preview behavior for non-progress Telegram drafts:
    • short first previews still respect the debounce;
    • if the turn stays active past the bounded delay, the draft materializes instead of remaining invisible forever.
  • Add opt-in Telegram assistant preview lane:
    • streaming.progress.assistantPreview: true preserves the existing progress/tool draft;
    • assistant partial text streams on a separate transient assistant lane;
    • the assistant preview lane is cleared/reset before final answer delivery.
  • Preserve fix(telegram): materialize streaming progress placeholders #95183's rich progress draft rendering while adapting feat(telegram): add progress assistant preview lane #82303's assistant-preview regression to the HTML progress preview shape.
  • Cancels delayed first-preview timers in clear() so cleanup cannot leave a pending preview flush after a draft is removed.

Behavior Matrix

  • streaming.mode: "progress" only:
    • progress/tool/status draft remains the visible progress surface;
    • answer activity can show a label-only placeholder after the bounded delay;
    • assistant answer text is not streamed into the progress draft.
  • streaming.mode: "progress", streaming.progress.assistantPreview: true:
    • progress/tool/status draft remains intact;
    • assistant partial text uses a separate transient assistant preview lane;
    • final answer delivery clears the assistant preview lane.
  • non-progress answer previews:
    • short initial previews are still debounced, but silence is bounded by minInitialDelayMs.

Real behavior proof

  • Behavior or issue addressed: Telegram progress streaming should no longer look silent by default when answer activity exists without a tool/progress row, and opt-in streaming.progress.assistantPreview: true should keep the progress/tool draft while rendering assistant partial text on a separate transient assistant preview lane.
  • Real environment tested: Linux local OpenClaw checkout on combined PR head 7541abe2753b58f3d0f53839f96f9bc926f42507.
  • Exact steps or command run after this patch:
git diff --check origin/main...HEAD
pnpm config:channels:check
pnpm config:schema:check
node scripts/run-vitest.mjs \
  extensions/telegram/src/draft-stream.test.ts \
  extensions/telegram/src/bot-message-dispatch.test.ts \
  extensions/telegram/src/lane-delivery.test.ts \
  src/channels/progress-draft-compositor.test.ts \
  src/plugin-sdk/channel-streaming.test.ts \
  src/agents/model-runtime-policy.test.ts
  • Evidence after fix: terminal output from the exact-head local run showed:
[base-config-schema] ok
[test] passed 4 Vitest shards in 38.41s

extension-telegram: bot-message-dispatch.test.ts — 131 passed
extension-telegram: draft-stream.test.ts — 48 passed
extension-telegram: lane-delivery.test.ts — 41 passed
channels: progress-draft-compositor.test.ts — 15 passed
plugin-sdk: channel-streaming.test.ts — 30 passed
unit-fast: model-runtime-policy.test.ts — 13 passed

Total targeted tests: 278 passed.

Live Telegram Bot API delayed-clear proof also ran against a private proof chat with token/chat redacted:
- before fix: delayed first-preview timer remained active after `clear()` and fired after cleanup;
- after fix: `clear()` called `clearTimeout`, active timer count dropped to 0, and the timer did not fire after cleanup;
- after fix: no stray Telegram send/edit/delete remained after the delay window.
- after rebase to latest main (`7541abe2753b58f3d0f53839f96f9bc926f42507`): exact-head live proof again showed `clearTimeout(timerId=1)`, active timer count `0` after `clear()`, `timerFiredAfterClear=false`, and no Telegram send/edit/delete after the delay window.
  • Observed result after fix: the combined candidate preserves the default progress draft as a stable rich Telegram progress surface while preventing assistant answer text from entering that default progress draft; when streaming.progress.assistantPreview is enabled, assistant partial text is observed on the separate assistant lane and the progress draft remains intact. The generated channel metadata and base config schema also validate for the new config surface. The live Telegram Bot API delayed-clear proof shows the old post-clear timer fire is gone after this fix.
  • What was not tested: full Telegram Desktop UI rendering was not re-run here; this proof used direct Telegram Bot API calls plus runtime timer instrumentation, and GitHub Actions is still validating exact head 7541abe2753b58f3d0f53839f96f9bc926f42507 after the assistant-lane bounded-delay fix.

Live Telegram Bot API timer cleanup proof

A real Telegram Bot API proof was run with the configured test bot token against a private proof chat. Token and chat identifiers are redacted in the captured evidence.

Scenario:

  1. Create a Telegram draft stream with minInitialChars: 80 and minInitialDelayMs: 1200.
  2. Send a below-threshold first preview (Proof <label>), then flush once so the delayed first-preview timer is scheduled.
  3. Call clear() before the delay elapses.
  4. Wait beyond the original delay window and record Bot API calls plus runtime timer events.

Before/after evidence:

#95183 before fix (70c0948...)
- after flush: active delayed timers = 1
- after clear(): active delayed timers = 1
- after 1200ms: timer fired after clear = true
- Telegram send/edit/delete calls after clear: 0/0/0

#95183 after fix (1ab0ba3...)
- after flush: active delayed timers = 1
- clear() called clearTimeout(timerId=1)
- after clear(): active delayed timers = 0
- after 1200ms: timer fired after clear = false
- Telegram send/edit/delete calls after clear: 0/0/0

#95522 before fix (3296107...)
- after flush: active delayed timers = 1
- after clear(): active delayed timers = 1
- after 1200ms: timer fired after clear = true
- Telegram send/edit/delete calls after clear: 0/0/0

#95522 after fix (ae1b0bd...)
- after flush: active delayed timers = 1
- clear() called clearTimeout(timerId=1)
- after clear(): active delayed timers = 0
- after 1200ms: timer fired after clear = false
- Telegram send/edit/delete calls after clear: 0/0/0

Observed result: before the fix, clear() removed the visible draft state but left the delayed first-preview timer alive until it fired after cleanup. After the fix, clear() cancels the pending timer immediately, so no delayed flush runs after draft cleanup. The live Bot API run also confirms that the cleanup scenario does not leave a stray Telegram message after the fix.

Generated metadata / upgrade compatibility proof

The only stored-data-model warning from ClawSweeper is for src/config/bundled-channel-config-metadata.generated.ts. This PR does not add or migrate persisted runtime data. The generated metadata change exposes the new optional Telegram config key streaming.progress.assistantPreview so config UIs/schema consumers can discover it. Existing configs remain compatible because the field is optional and defaults to disabled behavior.

Compatibility checks run on the combined head:

pnpm config:channels:check
pnpm config:schema:check

Result: both checks passed after regenerating src/config/bundled-channel-config-metadata.generated.ts; no migration step is required.

Live Telegram Bot API assistant-preview lane proof

A live Telegram Bot API proof was run on exact head 7541abe2753b58f3d0f53839f96f9bc926f42507 with token/chat identifiers redacted. This proof targets the review concern that short opt-in assistant previews could stay invisible until final delivery.

Timeline from the redacted proof log:

T+0.0s  progress marker visible via Bot API sendMessage, message id tail 6922
T+5.0s  bounded assistant preview timer fired
T+5.2s  assistant preview visible as a separate Bot API sendMessage, message id tail 6923
T+5.5s  final answer visible as a separate Bot API sendMessage, message id tail 6924
T+7.5s  assistant preview deleted
T+7.7s  progress marker deleted
T+8.6s  final proof message deleted

Observed result: with streaming.progress.assistantPreview enabled, the progress marker and assistant preview are separate visible messages, the short assistant preview no longer waits until final delivery, and cleanup removes the transient preview/marker so no stale preview remains.

The screen-recording window for clipping the GIF is the 20:32 GMT+8 proof run.

Dedicated Telegram test bot recording proof

A second live proof was run with the dedicated Telegram test bot against the dedicated private test chat. The bot token and full chat id are stored only in local secret files and are not included in this PR.

Exact PR head: 7541abe2753b58f3d0f53839f96f9bc926f42507.

Visible Telegram timeline from the dedicated test bot run:

20:54:59 GMT+8  progress placeholder sent to the dedicated test chat
                 text: [20:54:59 GMT+8] PR #95522 progress placeholder / OC proof progress / 🛠️ Exec

20:55:01 GMT+8  short assistant preview was scheduled with a 5000ms bounded timer
20:55:06 GMT+8  short assistant preview became visible as a separate message
                 text: [20:55:01] short

20:55:06 GMT+8  final answer was sent as a separate message
                 text: [20:55:06 GMT+8] PR #95522 final answer / OC proof ... final answer

20:55:11 GMT+8  assistant preview was deleted
20:55:11 GMT+8  progress placeholder was deleted
20:55:12 GMT+8  final proof message was deleted

Redacted Bot API log summary:

sendMessage count: 3
deleteMessage count: 3
boundedPreviewTimerScheduled: true
boundedPreviewTimerFired: true
progress message id tail: 23
assistant preview message id tail: 24
final answer message id tail: 25

Observed result: in the dedicated Telegram test chat, the progress marker appears first, the short opt-in assistant preview appears as a separate message after the bounded delay, the final answer is sent separately, and transient proof messages are cleaned up. This is the screen-recording window intended for GIF clipping.

Public GIF / MP4 evidence assets

The dedicated Telegram test-bot screen-recording evidence has been clipped and hosted on the snowzlmbot/openclaw fork on an evidence-only branch, separate from this PR's code branch so the PR diff stays clean.

Correction: the usable proof window is in the latter half of the operator recording. The hosted assets below use the corrected late-recording segment, not the earlier/incorrect first-half clip.

Stable evidence commit: ad7e8c792476817dab2a56f789bb2125c5f0f40f

Recommended GIF evidence:

PR #95522 Telegram dedicated-bot proof

Additional assets:

The clip shows the dedicated Telegram test bot sequence: progress placeholder first, short opt-in assistant preview after the bounded delay, final answer separately, then cleanup. The bot token and full chat id are not included in the hosted assets or PR text.

Rebase / CI scope note

After the timer proof update, check-test-types on #95522 failed on an upstream scripts/control-ui-i18n.ts import of ./lib/windows-taskkill.mjs that was included because the combined PR still had an older base SHA. I rebased #95522 onto latest main so that upstream script change is no longer part of this PR diff. The post-rebase diff remains limited to Telegram/streaming/config/doc surfaces.

Post-rebase validation on exact head 7541abe2753b58f3d0f53839f96f9bc926f42507:

git diff --check origin/main...HEAD
pnpm config:channels:check
pnpm config:schema:check
node scripts/run-vitest.mjs \
  extensions/telegram/src/draft-stream.test.ts \
  extensions/telegram/src/bot-message-dispatch.test.ts \
  extensions/telegram/src/lane-delivery.test.ts \
  src/channels/progress-draft-compositor.test.ts \
  src/plugin-sdk/channel-streaming.test.ts \
  src/agents/model-runtime-policy.test.ts

Result: config checks passed and 278 targeted tests passed.

Validation

Local targeted validation on this combined branch:

git diff --check origin/main...HEAD
pnpm config:channels:check
pnpm config:schema:check
node scripts/run-vitest.mjs \
  extensions/telegram/src/draft-stream.test.ts \
  extensions/telegram/src/bot-message-dispatch.test.ts \
  extensions/telegram/src/lane-delivery.test.ts \
  src/channels/progress-draft-compositor.test.ts \
  src/plugin-sdk/channel-streaming.test.ts \
  src/agents/model-runtime-policy.test.ts

Result:

  • config channel metadata check passed;
  • base config schema check passed;
  • targeted Vitest shards passed: 278 tests.

Risk / Review Notes

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: telegram Channel integration: telegram agents Agent runtime and tooling size: M labels Jun 21, 2026
@snowzlmbot

Copy link
Copy Markdown
Contributor Author

@clawsweeper review-pr

@clawsweeper

clawsweeper Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jun 21, 2026
@clawsweeper

clawsweeper Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 21, 2026, 9:57 AM ET / 13:57 UTC.

Summary
The PR adds bounded Telegram draft materialization, a progress-mode placeholder, and an opt-in Telegram streaming.progress.assistantPreview lane with docs, config/schema updates, SDK surface budgeting, and tests.

PR surface: Source +147, Tests +208, Docs +20, Generated 0, Other 0. Total +375 across 18 files.

Reproducibility: yes. Current main has source-level paths for suppressed short first previews and progress-mode answer partial suppression, and the PR includes live Telegram proof for the after-fix behavior.

Review metrics: 2 noteworthy metrics.

  • Config/API Surface: 1 Telegram config key added; 1 public SDK helper added. This is the compatibility-sensitive part of the PR that needs maintainer acceptance before merge.
  • Visible Telegram Defaults: 2 default visibility paths changed. Short first previews can materialize after a delay and progress-mode answer activity can create a label placeholder for existing users.

Stored data model
Persistent data-model change detected: unknown-data-model-change: src/config/bundled-channel-config-metadata.generated.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #95004
Summary: This PR is a candidate combined fix for the canonical Telegram draft-suppression issue and overlaps two narrower open PRs that split the default placeholder and assistant-preview concerns.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster ✨ media proof bonus
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Maintainer chooses the combined PR versus the split path through the two narrower open PRs.
  • [P2] Wait for exact-head required checks to complete before merge.

Mantis proof suggestion
A maintainer-controlled Telegram Desktop proof would directly exercise the visible transport behavior that this PR changes. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis telegram desktop proof: verify this PR progress placeholder, bounded assistant preview, final answer, and cleanup with streaming.progress.assistantPreview=true.

Risk before merge

  • [P1] Merging intentionally changes default Telegram progress visibility: users may now see a bounded placeholder where current main can stay silent until final delivery.
  • [P1] The PR adds one Telegram config key and one public SDK helper, so maintainers should deliberately accept the new config/API surface before merge.
  • [P1] Two narrower open PRs already cover the default placeholder fix and assistant-preview feature separately, so maintainers need to choose whether this combined PR is the canonical path.
  • [P1] Exact-head checks were still queued or recently unstable in live GitHub status; that is a normal merge gate to wait for, not a code finding.

Maintainer options:

  1. Accept The Combined Telegram Surface
    Maintainers can land this after exact-head required checks finish if they want one PR to close the default placeholder bug and add the opt-in assistant-preview lane together.
  2. Split The Product Choice
    Maintainers can land the narrower default placeholder fix first and keep the assistant-preview lane as a separate opt-in product decision.
  3. Narrow This Branch Before Merge
    If maintainers want the bug fix without new public config or SDK surface, this branch should drop the assistant-preview lane and related public helper before merge.

Next step before merge

  • [P2] Human maintainer review is the next action because the remaining decision is whether to accept the combined Telegram config/API behavior or keep the narrower PRs separate; no narrow automated repair remains.

Security
Cleared: No concrete security or supply-chain concern was found; the diff changes Telegram runtime/config/docs/tests, SDK surface accounting, and generated config metadata, not workflows, dependencies, secrets, install scripts, or package resolution.

Review details

Best possible solution:

Maintainers should either accept this combined Telegram behavior/API surface after exact-head gates finish, or choose the split path by landing #95183 first and revisiting #82303 separately.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main has source-level paths for suppressed short first previews and progress-mode answer partial suppression, and the PR includes live Telegram proof for the after-fix behavior.

Is this the best way to solve the issue?

Unclear as product direction, technically acceptable as implementation: the combined patch is coherent, but maintainers must decide whether it is better than landing the split default-fix and assistant-preview PRs separately.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against b28e68e0ceb2.

Label changes

Label justifications:

  • P2: This is a normal-priority Telegram streaming improvement with channel-limited blast radius and strong source/proof signal.
  • merge-risk: 🚨 compatibility: The diff adds a new Telegram config key and public SDK helper that become part of the upgrade-visible config/API surface.
  • merge-risk: 🚨 message-delivery: The diff changes when Telegram progress, assistant preview, and final messages appear, clear, and finalize during active turns.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (linked_artifact): The PR body includes redacted live Telegram Bot API output and hosted visual evidence showing progress placeholder, bounded assistant preview, final answer, and cleanup; the downloaded GIF checksum matched the hosted checksum.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes redacted live Telegram Bot API output and hosted visual evidence showing progress placeholder, bounded assistant preview, final answer, and cleanup; the downloaded GIF checksum matched the hosted checksum.
  • mantis: telegram-visible-proof: Mantis should capture Telegram visible proof. The PR changes visible Telegram streaming behavior that is easy to demonstrate in Telegram Desktop: placeholder, assistant preview, final answer, and cleanup.
Evidence reviewed

PR surface:

Source +147, Tests +208, Docs +20, Generated 0, Other 0. Total +375 across 18 files.

View PR surface stats
Area Files Added Removed Net
Source 8 159 12 +147
Tests 6 215 7 +208
Docs 2 22 2 +20
Config 0 0 0 0
Generated 1 5 5 0
Other 1 7 7 0
Total 18 408 33 +375

What I checked:

Likely related people:

  • obviyus: Ayaan Zaidi authored recent Telegram preview/progress commits and earlier Telegram streaming simplifications on the same dispatcher and docs surface. (role: recent Telegram streaming contributor; confidence: high; commits: a8b5f5d5518b, 663fabbe30eb, e8b142feb117; files: extensions/telegram/src/bot-message-dispatch.ts, extensions/telegram/src/draft-stream.ts, docs/channels/telegram.md)
  • vincentkoc: Current-main blame for the threshold-bearing dispatcher and draft stream points to recent commits by Vincent Koc, with adjacent channel progress-detail work in the same area. (role: recent area contributor; confidence: medium; commits: a4c8b17b9e, 5e329f40656a; files: extensions/telegram/src/bot-message-dispatch.ts, extensions/telegram/src/draft-stream.ts, src/channels/progress-draft-compositor.ts)
  • Cameron Beeley: Recent commits changed verbose/commentary progress behavior and shared channel progress rendering that this PR builds on. (role: adjacent progress-draft contributor; confidence: medium; commits: dc55a5b112a5, c1300455d942; files: extensions/telegram/src/bot-message-dispatch.ts, src/channels/streaming.ts)
  • steipete: Peter Steinberger carried several plugin SDK, channel seam, and Telegram runtime refactors around the public streaming helper and extension boundary touched by this PR. (role: plugin SDK and Telegram runtime refactor contributor; confidence: medium; commits: 62ddc9d9e0, 07d9f725b6, 673878188d; files: src/plugin-sdk/channel-streaming.ts, src/channels/streaming.ts, extensions/telegram/src/bot-message-dispatch.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. mantis: telegram-visible-proof Mantis should capture Telegram visible proof. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jun 21, 2026
@snowzlmbot
snowzlmbot force-pushed the fix/telegram-unify-progress-placeholder-assistant-preview branch from cf536ce to 3296107 Compare June 21, 2026 08:47
@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Force-pushed a metadata-only rewrite for commit identity hygiene.

What changed:

@clawsweeper review-pr

@clawsweeper

clawsweeper Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@openclaw-barnacle openclaw-barnacle Bot removed the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jun 21, 2026
@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Pushed the same focused fix for the delayed-preview timer finding on the combined branch.

What changed:

  • createTelegramDraftStream.clear() now cancels the delayed first-preview timer before cleanup.
  • Added the fake-timer regression for clear() cancelling a below-threshold pending first preview.
  • Updated the PR body with a checker-recognized Real behavior proof section and generated-metadata compatibility proof.

Validation:

git diff --check origin/main...HEAD
pnpm config:channels:check
pnpm config:schema:check
node scripts/run-vitest.mjs \
  extensions/telegram/src/draft-stream.test.ts \
  extensions/telegram/src/bot-message-dispatch.test.ts \
  extensions/telegram/src/lane-delivery.test.ts \
  src/channels/progress-draft-compositor.test.ts \
  src/plugin-sdk/channel-streaming.test.ts \
  src/agents/model-runtime-policy.test.ts

Result: 278 targeted tests passed; local proof-policy evaluation accepts the PR body as real behavior proof.

@clawsweeper review-pr

@clawsweeper

clawsweeper Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. label Jun 21, 2026
@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Added live Telegram Bot API before/after proof to the PR body.

What the redacted live proof shows:

  • Before the timer cleanup fix, the delayed first-preview timer remained active after clear() and fired after cleanup.
  • After the fix, clear() calls clearTimeout; active timer count drops to 0 immediately and the timer does not fire after cleanup.
  • Direct Bot API logs also show no stray Telegram send/edit/delete after the delay window.

The proof used the configured test bot token against a private proof chat; token and chat identifiers are redacted in the PR evidence.

@clawsweeper review-pr

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jun 21, 2026
@snowzlmbot
snowzlmbot force-pushed the fix/telegram-unify-progress-placeholder-assistant-preview branch from ae1b0bd to 8f16960 Compare June 21, 2026 09:40
@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Rebased #95522 onto latest main and pushed head 8f1696032d880721dbebb17d2f3f9db61f09b057.

Why:

  • check-test-types failed on upstream scripts/control-ui-i18n.ts / windows-taskkill.mjs typing because the combined PR still carried an older base SHA.
  • Rebase removes that upstream script change from this PR diff instead of adding an unrelated type declaration to this Telegram PR.

Post-rebase validation:

git diff --check origin/main...HEAD
pnpm config:channels:check
pnpm config:schema:check
node scripts/run-vitest.mjs \
  extensions/telegram/src/draft-stream.test.ts \
  extensions/telegram/src/bot-message-dispatch.test.ts \
  extensions/telegram/src/lane-delivery.test.ts \
  src/channels/progress-draft-compositor.test.ts \
  src/plugin-sdk/channel-streaming.test.ts \
  src/agents/model-runtime-policy.test.ts

Result: config checks passed and 278 targeted tests passed.

Also re-ran the live Telegram Bot API delayed-clear proof on exact head 8f1696032d: clearTimeout(timerId=1), active timer count 0 after clear(), no post-clear timer fire, and no stray Telegram send/edit/delete after the delay window.

@clawsweeper review-pr

@clawsweeper

clawsweeper Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@NianJiuZst

Copy link
Copy Markdown
Contributor

Complementary observations on top of ClawSweeper's detailed review:

Cluster overlap is real. ClawSweeper flagged this PR as combining concerns that overlap with #95183 (default placeholder fix) and #82303 (assistant preview lane). I agree — and the overlap is worth resolving before merging because each piece changes user-visible Telegram behavior independently:

  • The default-placeholder change shifts what existing users see during active turns even when they don't opt into the assistant preview.
  • The assistant preview lane is an additive opt-in surface but its delay logic determines whether users see stale previews at all.
  • The new config key (streaming.progress.assistantPreview) is a public Telegram config surface change.

If maintainers want all three, merging this PR is fine — but they should explicitly accept the combined product (which ClawSweeper's review flagged as a P1). If not, the recommended path is to land #95183 first (default fix only), then revisit #82303 (assistant preview) as a separate opt-in.

Specific to the lane-delay concern (P1 #1). The bot-message-dispatch delay logic uses a per-lane threshold without a bounded delay, which ClawSweeper notes can keep short opt-in previews invisible until final delivery. This is the kind of subtle timing bug that's easy to miss in tests but obvious to users — they see no preview, then a final answer, with no in-between. Two suggestions:

  • Move the per-lane delay calc to a single helper so both lanes (default + assistant) compute from the same source. Drift between two delay formulas is the most likely source of the "stays invisible" bug.
  • Add a "preview must be at least N chars OR M ms old" rule. Either gate keeps users from seeing flickery one-word previews.

Real Telegram proof is missing. ClawSweeper notes the proof only covers delayed-clear timer cleanup. For a PR that changes visible Telegram behavior (placeholder text, preview ordering, final-answer ordering), proof should be one redacted Telegram Desktop recording showing:

  1. User sends message
  2. Progress placeholder appears
  3. (if assistant preview on) Assistant preview updates appear separately from the placeholder
  4. Final answer replaces both, with no stale preview lingering
  5. Edit/cleanup fires correctly on the final answer

Mantis proof request in the review comment is the right path. If you can't get Telegram proof pre-merge, the maintainer option #3 (accept source-only transport risk) is the explicit alternative.

Bundled-config-metadata migration. ClawSweeper flagged src/config/bundled-channel-config-metadata.generated.ts as a data-model change requiring migration/upgrade review. If this PR introduces a new key but no migration helper, users upgrading won't have the new default applied — worth either running the migration helper or explicitly documenting "default applies only on fresh install".

@openclaw-barnacle openclaw-barnacle Bot added the scripts Repository scripts label Jun 21, 2026
@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Pushed 9948803b8f07f6b4acbccd707ae1c425a80e9069 to address the PR-caused checks-node-core-fast failure.

What failed and why:

  • test/scripts/plugin-sdk-surface-report.test.ts failed because this combined PR intentionally adds one public SDK helper surface for streaming.progress.assistantPreview.
  • The implementation was correct, but scripts/plugin-sdk-surface-report.mjs still had the old public export/callable/deprecated budgets.

Fix:

  • Updated the plugin SDK surface budgets to match the intentional assistant-preview public helper surface.
  • This keeps the new public API explicit and reviewable instead of silently hiding the surface change.

Validation:

git diff --check origin/main...HEAD
node scripts/plugin-sdk-surface-report.mjs --check
OPENCLAW_PLUGIN_SDK_MAX_PUBLIC_DEPRECATED_EXPORTS_BY_ENTRYPOINT='{"core":2}' node scripts/plugin-sdk-surface-report.mjs --check
node scripts/run-vitest.mjs \
  test/scripts/plugin-sdk-surface-report.test.ts \
  src/plugin-sdk/channel-streaming.test.ts \
  src/agents/model-runtime-policy.test.ts \
  extensions/telegram/src/draft-stream.test.ts \
  extensions/telegram/src/bot-message-dispatch.test.ts \
  extensions/telegram/src/lane-delivery.test.ts \
  src/channels/progress-draft-compositor.test.ts

Result: surface report checks passed and 282 targeted tests passed.

CI note:

@clawsweeper review-pr

@snowzlmbot
snowzlmbot force-pushed the fix/telegram-unify-progress-placeholder-assistant-preview branch from 9948803 to 77786d8 Compare June 21, 2026 11:57
@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Rebased onto latest main and pushed head 77786d88f6b88d4c3621d933bd227e21ea7aa962.

What was fixed in this PR:

  • The PR-caused checks-node-core-fast failure was the plugin SDK surface budget: this combined PR intentionally adds the public assistant-preview helper surface, so scripts/plugin-sdk-surface-report.mjs now accounts for that explicit public API growth.

What was not caused by this PR:

  • check-test-types and checks-node-core-tooling were upstream drift:
    • missing windows-taskkill.mjs declaration for scripts/control-ui-i18n.ts;
    • stale test-projects routing expectation for newly added top-level helper tests.
  • Latest main contains those upstream fixes, so this PR now absorbs them through rebase instead of adding unrelated tooling/type patches.

Validation after rebase:

git diff --check origin/main...HEAD
node scripts/plugin-sdk-surface-report.mjs --check
pnpm config:channels:check
pnpm config:schema:check
node scripts/run-vitest.mjs \
  test/scripts/plugin-sdk-surface-report.test.ts \
  src/plugin-sdk/channel-streaming.test.ts \
  src/agents/model-runtime-policy.test.ts \
  extensions/telegram/src/draft-stream.test.ts \
  extensions/telegram/src/bot-message-dispatch.test.ts \
  extensions/telegram/src/lane-delivery.test.ts \
  src/channels/progress-draft-compositor.test.ts

Result: surface report/config checks passed and 282 targeted tests passed.

@clawsweeper review-pr

@clawsweeper

clawsweeper Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Addressed the P1 lane-delay concern from the review thread and NianJiuZst's comment.

What changed:

  • The initial preview threshold/delay calculation is now centralized in resolveDraftLaneInitialPreview(...).
  • The opt-in assistant preview lane now receives the same bounded initial-preview delay rule as normal answer drafts.
  • Added regression coverage that streaming.progress.assistantPreview creates the assistant lane with minInitialChars: 30 and minInitialDelayMs: 5000.

Validation:

git diff --check origin/main...HEAD
node scripts/run-vitest.mjs \
  extensions/telegram/src/bot-message-dispatch.test.ts \
  extensions/telegram/src/draft-stream.test.ts \
  extensions/telegram/src/lane-delivery.test.ts \
  src/channels/progress-draft-compositor.test.ts \
  src/plugin-sdk/channel-streaming.test.ts \
  src/agents/model-runtime-policy.test.ts

Result: targeted tests passed (278 tests across Telegram/channel/plugin-sdk/policy shards).

Live Telegram Bot API proof on head 7541abe2753b58f3d0f53839f96f9bc926f42507:

  • T+0: progress marker visible (sendMessage, id tail 6922).
  • T+5s: short assistant preview appears separately (sendMessage, id tail 6923) after the 5000ms bounded preview timer fires.
  • T+5.5s: final answer sent separately (sendMessage, id tail 6924).
  • Cleanup: assistant preview and progress marker deleted; no stale preview remains.
  • Token/chat ids are redacted in the stored proof log.

This proof is intended to support clipping a GIF from the screen recording around the 20:32 GMT+8 run.

@clawsweeper review-pr

@clawsweeper

clawsweeper Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 21, 2026
@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Added the dedicated Telegram test bot recording proof to the PR body.

Dedicated-bot proof details:

  • Exact head: 7541abe2753b58f3d0f53839f96f9bc926f42507.
  • Test target: dedicated private Telegram proof chat; bot token and full chat id are kept only in local secret files and are not included here.
  • Visible timeline in the recording window:
    • 20:54:59 GMT+8: progress placeholder appears.
    • 20:55:01 GMT+8: short assistant preview is scheduled with the 5000ms bounded timer.
    • 20:55:06 GMT+8: short assistant preview appears as a separate message.
    • 20:55:06 GMT+8: final answer is sent separately.
    • 20:55:11-20:55:12 GMT+8: transient proof messages are cleaned up.
  • Redacted Bot API summary: sendMessage=3, deleteMessage=3, boundedPreviewTimerScheduled=true, boundedPreviewTimerFired=true.

This should support the GIF clip from the operator recording. Once the recording file is uploaded, I can trim the 20:54:59-20:55:12 GMT+8 window into a GIF and attach it.

@clawsweeper review-pr

@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Pushed c5299afdaf7fe6b573b9090edce7e9d36825a3f3 for the remaining SDK mode-gate review point.

What changed:

  • resolveChannelProgressDraftAssistantPreview(...) now returns false unless the normalized streaming mode is progress.
  • Added SDK regressions for partial, block, and off modes with progress.assistantPreview: true; all resolve to false.
  • This keeps the new helper tied to the progress-only assistant-preview feature surface and prevents plugin consumers from observing it as active in non-progress modes.

Validation:

git diff --check origin/main...HEAD
node scripts/plugin-sdk-surface-report.mjs --check
node scripts/run-vitest.mjs \
  src/plugin-sdk/channel-streaming.test.ts \
  src/agents/model-runtime-policy.test.ts \
  extensions/telegram/src/bot-message-dispatch.test.ts \
  extensions/telegram/src/draft-stream.test.ts \
  extensions/telegram/src/lane-delivery.test.ts \
  src/channels/progress-draft-compositor.test.ts

Result: surface report passed; targeted tests passed (278 total across plugin-sdk, policy, Telegram, and channel shards).

Note: the earlier preflight failure was a checkout/fetch infrastructure failure (git fetch RPC reset / early EOF), not a PR code failure. Rerun attempts were blocked by GitHub permissions, so this push will trigger a fresh CI run.

@clawsweeper review-pr

@clawsweeper

clawsweeper Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper could not start a re-review for this item.

Reason: re-review requires an open issue or PR.

@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Added hosted GIF/MP4 evidence links to the PR body.

Evidence hosting:

The assets are on an evidence-only branch in snowzlmbot/openclaw, separate from this PR's code branch, so the PR diff remains clean. The hosted clip shows the dedicated Telegram test-bot sequence: progress placeholder → bounded assistant preview → final answer → cleanup. Bot token and full chat id are not included.

@clawsweeper review-pr

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 21, 2026
@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Corrected the hosted GIF/MP4 evidence to use the late-half proof window from the operator recording.

Updated evidence hosting:

The previous evidence commit pointed at an earlier clip. The PR body now points to this corrected late-recording segment, which shows the dedicated Telegram test bot sequence: progress placeholder → bounded assistant preview → final answer → cleanup. Bot token and full chat id are not included.

@clawsweeper review-pr

@obviyus

obviyus commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Thanks for pulling this together and for the detailed Telegram proof.

We are going to close this one because the main user-facing gap is already covered on main: #95183 fixed the progress-placeholder/silent-run path, streaming.progress.commentary covers preamble/commentary text in progress mode, and partial / block modes remain the supported way to stream assistant answer text. Adding a second temporary assistant-preview message on top of progress mode would create extra Telegram message churn and another config surface for behavior we already cover through those existing modes.

Appreciate the work here, especially the careful live proof.

@obviyus obviyus closed this Jun 21, 2026
@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Resolved the merge conflict by rebuilding this PR branch cleanly on top of latest main.

What changed:

  • Latest main already contains the default placeholder / delayed-clear fixes from fix(telegram): materialize streaming progress placeholders #95183, so this PR no longer carries those overlapping commits.
  • Rebuilt feat(telegram): unify progress fallback with assistant preview lane #95522 from origin/main and replayed only the assistant-preview / SDK / proof-specific commits:
    • feat(telegram): add progress assistant preview lane
    • fix(telegram): scope assistant preview config
    • test(telegram): align assistant preview with rich progress drafts
    • test(plugin-sdk): account for assistant preview public surface
    • fix(telegram): bound assistant preview initial delay
    • fix(plugin-sdk): gate assistant preview to progress mode

Current head: 38bd21e11c50d35e4fc523b23227b028f34c5084

Scope check:

Validation:

git diff --check origin/main...HEAD
node scripts/plugin-sdk-surface-report.mjs --check
pnpm config:channels:check
pnpm config:schema:check
node scripts/run-vitest.mjs \
  test/scripts/plugin-sdk-surface-report.test.ts \
  src/plugin-sdk/channel-streaming.test.ts \
  src/agents/model-runtime-policy.test.ts \
  extensions/telegram/src/bot-message-dispatch.test.ts \
  extensions/telegram/src/draft-stream.test.ts \
  extensions/telegram/src/lane-delivery.test.ts \
  src/channels/progress-draft-compositor.test.ts

Result: surface/config checks passed; targeted Vitest passed (282 tests total).

@clawsweeper review-pr

@snowzlmbot

snowzlmbot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

感谢你整理这些信息,以及提供的详细的 Telegram 证据。

我们将关闭此问题,因为面向用户的主要缺陷已在 #95183 中得到解决main:#95183修复了进度占位符/静默运行路径,streaming.progress.commentary涵盖了进度模式下的前言/注释文本,并且partial/block模式仍然是流式传输助手答案文本的支持方式。在进度模式之上添加第二个临时助手预览消息会增加 Telegram 消息的变更,并且需要为我们已经通过现有模式实现的行为增加额外的配置项。

非常欣赏这项工作,尤其是细致的现场验证。

Thanks for your review

@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Superseded by clean replacement PR #95573.

#95522 conflicted after #95183 landed on main; #95573 was rebuilt from the latest main and keeps only the remaining assistant-preview / SDK / docs changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling channel: telegram Channel integration: telegram docs Improvements or additions to documentation mantis: telegram-visible-proof Mantis should capture Telegram visible proof. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. scripts Repository scripts size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

issue(telegram): preview streaming can suppress drafts that Web already shows

4 participants