fix(telegram): mirror outbound replies to session transcript#79502
Conversation
|
Codex review: needs changes before merge. Summary Reproducibility: yes. by source inspection and supplied before-fix logs. Current main carries a Telegram session key into direct reply dispatch, but Real behavior proof Next step before merge Security Review findings
Review detailsBest possible solution: Keep the Telegram-owned mirror callback, but route appends through the canonical session transcript mirror semantics and ensure each delivered final answer is mirrored exactly once. Do we have a high-confidence way to reproduce the issue? Yes, by source inspection and supplied before-fix logs. Current main carries a Telegram session key into direct reply dispatch, but Is this the best way to solve the issue? No, not as submitted. The owner-boundary direction is right, but the patch should preserve the real session id/header and dedupe semantics, and it should choose one mirror source for preview-finalized long finals. Full review comments:
Overall correctness: patch is incorrect Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 884b6af77c00. |
299edaf to
1ff6ae9
Compare
011345d to
c02762e
Compare
Real behavior proofBefore fix (current main, v2026.5.6)Environment: Ubuntu 24.04 arm64, OpenClaw 2026.5.6, Telegram supergroup with topic binding, agent Gateway debug logs ( Result: ❌ No Root cause confirmed$ ls -la ~/.openclaw/agents/kiro-general/sessions/
# Only sessions.json exists — NO .jsonl transcript file
# sessions.json references: 973b8d06-...-topic-1172.jsonl (does not exist)The session transcript is never created because Comparison with working embedded-backend agent (same gateway, same group)Agent This confirms the delivery pipeline works correctly for embedded backends (which go through After fix (this PR)The
Note: Full live Telegram bot verification requires building and deploying the patched gateway. The fix is validated via source inspection + 85 passing telegram delivery/dispatch tests that exercise the same code paths. Re-review progress:
|
Requesting
|
|
BlueBubbles is deprecated and no longer ships as a bundled OpenClaw channel. Use iMessage via |
22b16ed to
1ad484f
Compare
1ad484f to
3ec179e
Compare
3ec179e to
dbc5c79
Compare
Telegram's deliverReplies dispatches via Grammy SDK directly, bypassing deliverOutboundPayloads where the channel-mirror writer runs. Outbound assistant replies were never appended to the session transcript, leaving Telegram .jsonl files empty (the sessions.json sessionFile path was populated but the file was never created on disk). Add an optional transcriptMirror callback param to deliverReplies and populate it from bot-message-dispatch's deliveryBaseOptions. Reuses the existing appendAssistantMessageToSessionTranscript helper that deliverOutboundPayloads already calls. Also mirrors preview-finalized replies so the transcript captures all final assistant output. Plugin SDK boundary expansion: re-export appendAssistantMessageToSessionTranscript from plugin-sdk/agent-harness-runtime so extension code can call it without reaching into core src/. API baseline regenerated. Addresses openclaw#75991 for telegram + CLI runtime combinations. Supersedes openclaw#77484 (incorporates reviewer feedback: preview- finalized mirror + changelog entry).
dbc5c79 to
2eb139a
Compare
|
Landed via rebase onto main.
Thanks @adagues! |
Summary
Telegram's
deliverRepliesdispatches via Grammy SDK directly, bypassingdeliverOutboundPayloadswhere the channel-mirror writer (appendAssistantMessageToSessionTranscript, introduced in #1031) runs. Outbound assistant replies were never appended to the session transcript, leaving Telegram.jsonlfiles empty — thesessions.jsonsessionFilefield was populated but the file was never created on disk.This causes CLI-backend agents (e.g.
kiro/claude-opus-4.7) bound to Telegram topics to silently lose all responses: the gateway generates the response (visible in debug logs ascli stdout:), but without a session transcript,sessionIdresolves tounknownand the delivery pipeline is bypassed entirely.Mirrors the same fix shape as #53607 (discord) and #75529 (bluebubbles). Addresses the missing-mirror behavior reported in #75991 (includes a new Linux/kiro-cli reproduction in comments). Supersedes the closed #77484 and incorporates its reviewer feedback (preview-finalized mirror + changelog entry).
Changes
extensions/telegram/src/bot/delivery.replies.ts: Add optionaltranscriptMirrorcallback param todeliverReplies. After successful delivery, aggregates text/media from all normalized replies and calls the mirror callback (fire-and-forget with error logging).extensions/telegram/src/bot-message-dispatch.ts: PopulatestranscriptMirrorindeliveryBaseOptionsfromctxPayload.SessionKey+route.agentId. Also mirrors preview-finalized replies. Silent NO_REPLY fallback explicitly opts out.src/plugin-sdk/agent-harness-runtime.ts: Re-exportappendAssistantMessageToSessionTranscriptso extension code can call it without reaching into coresrc/.docs/.generated/plugin-sdk-api-baseline.sha256: Regenerated viapnpm plugin-sdk:api:gen.CHANGELOG.md: Added entry under Unreleased > Fixes.Real behavior proof
Environment
Ubuntu 24.04 arm64, OpenClaw 2026.5.6, Telegram supergroup with topic binding, agent
kiro-generalusing CLI backend (kiro/claude-opus-4.7).Before fix (current main, v2026.5.6)
Gateway debug logs (
logging.level: "debug"):Result: ❌ No
[telegram] sendMessageever fires. The user never receives the response. Zerolane enqueue/lane dequeueevents. The.jsonlsession transcript file does not exist on disk despitesessions.jsonreferencing it.Root cause confirmed
The session transcript is never created because
deliverRepliesdispatches via Grammy SDK directly and bypassesdeliverOutboundPayloadswhereappendAssistantMessageToSessionTranscriptruns.Comparison with working embedded-backend agent (same gateway, same group)
Agent
colossus(embedded Bedrock backend) on topic:1 in the same supergroup shows proper delivery lifecycle:This confirms the delivery pipeline works correctly for embedded backends (which go through
deliverOutboundPayloads) but fails for CLI-backend agents that rely ondeliverRepliesdirect Grammy path.After fix (this PR, commit 3709a33)
The
transcriptMirrorcallback indeliverRepliesnow writes the.jsonltranscript entry after each successful Grammy delivery:bot-message-dispatch.tswirestranscriptMirrorusingctxPayload.SessionKey+route.agentId→ callsappendAssistantMessageToSessionTranscriptdelivery.replies.tscollects delivered content (text + media) across all reply chunks, then invokes the mirror callback once all chunks are deliveredbot-message-dispatch.tsThis ensures:
.jsonlfile is created on first deliverysessionId(notunknown)Note: Full live CLI-backend Telegram verification requires a
visibleReplies: automaticgroup config override (default group modemessage_tool_onlysuppresses CLI-backend direct delivery), which cannot be cleanly isolated on a production gateway without downtime. The fix is validated via source inspection, 190 passing tests exercising the same code paths, and the before-fix logs demonstrating the exact failure point this callback addresses.Verification
pnpm tsgo:core✅pnpm tsgo:extensions✅pnpm check:architecture✅pnpm plugin-sdk:api:check✅ (baseline regenerated)pnpm test(acceptance criteria): 190 tests, 0 failures ✅Risk / scope notes
deliverRepliescallers compile unchanged.Closes #75991