fix(telegram): mirror outbound replies to session transcript#77484
fix(telegram): mirror outbound replies to session transcript#77484syshiuen-create wants to merge 1 commit into
Conversation
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 param to deliverReplies and populate it from bot-message-dispatch's deliveryBaseOptions. Reuses the existing appendAssistantMessageToSessionTranscript helper that deliverOutboundPayloads already calls, so the delivery-mirror entry shape, parentId DAG handling, and write lock semantics stay identical to other channels. Silent NO_REPLY fallback explicitly opts out so sentinels do not reach the transcript. Mirrors the same fix shape as openclaw#53607 (discord) and openclaw#75529 (bluebubbles). Addresses the missing-mirror behavior reported in openclaw#75991 for telegram + claude-cli runtime combinations. 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.
|
Codex review: needs changes before merge. Summary Reproducibility: yes. from source inspection: current main has no transcript append in Next step before merge Security Review findings
Review detailsBest possible solution: Mirror every successful Telegram final assistant delivery that reaches the user, including both fresh Do we have a high-confidence way to reproduce the issue? Yes, from source inspection: current main has no transcript append in Is this the best way to solve the issue? No. The proposed direction is right for standard 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 a3f6f24b79a5. |
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).
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).
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).
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).
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).
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).
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).
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 #75991 for telegram + CLI runtime combinations. Supersedes #77484 (incorporates reviewer feedback: preview- finalized mirror + changelog entry).
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).
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).
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).
Summary
Telegram outbound assistant replies were never appended to the session
transcript: the
.jsonlfile thesessions.jsonsessionFilefieldpoints at simply did not exist on disk. The session metadata side (token
counts,
lastInteractionAt) updated correctly, so this is silent — theagent has no record of what it just sent.
Root cause:
extensions/telegram/src/bot/delivery.replies.ts::deliverRepliesdispatches via the Grammy SDK directly (
bot.api.sendMessage/sendPhoto/ etc.), bypassingdeliverOutboundPayloadswhere thechannel-mirror writer (
appendAssistantMessageToSessionTranscript,introduced in #1031) actually runs. Telegram is one of the channels that
never picked up that hook.
This mirrors the same fix shape as #53607 (discord) and #75529 (bluebubbles),
which patched the same gap for those channels. Addresses the missing-mirror
behavior reported in #75991 for telegram + claude-cli runtime combinations.
Changes
extensions/telegram/src/bot/delivery.replies.ts: add optionaltranscriptMirror?: { sessionKey, agentId? }param; after a successfuldelivery (and after
maybePinFirstDeliveredMessage), callappendAssistantMessageToSessionTranscript(...)withreply.text+mediaList. Reuses the same helperdeliverOutboundPayloadsalreadycalls so
delivery-mirrorentry shape, parentId DAG, and write-locksemantics stay identical to other channels.
extensions/telegram/src/bot-message-dispatch.ts: populatetranscriptMirrorindeliveryBaseOptionsfromctxPayload.SessionKey+route.agentId. Silent NO_REPLY fallbackexplicitly opts out (
transcriptMirror: undefined) so sentinels donot reach the transcript.
src/plugin-sdk/agent-harness-runtime.ts: re-exportappendAssistantMessageToSessionTranscriptso extension code cancall it without reaching into core
src/. The companiontranscript.runtime.tsalready exported the same function forinternal consumers; adding it to the SDK boundary mirrors how
appendSessionTranscriptMessageis already exposed alongside.docs/.generated/plugin-sdk-api-baseline.sha256: regenerated viapnpm plugin-sdk:api:genfor the new SDK export.Verification
Local (no Testbox):
pnpm tsgo:core✅pnpm tsgo:extensions✅pnpm check:architecture(import-cycles, madge, deprecated APIs, deprecated JSDoc) ✅pnpm test extensions/telegram/src/bot/delivery.test.ts extensions/telegram/src/bot-message-dispatch.test.ts✅ 159tests, 0 regressions
pnpm build✅pnpm plugin-sdk:api:check✅ after regenmessage through both telegram bots produced
<sessionFile>.jsonlfilesfor the first time, each containing one
model: "delivery-mirror"assistant entry with the reply text. Before the fix the jsonl files
were never created.
agent:main:hook:*andagent:main:mainsessionswere unaffected.
Risk / scope notes
deliverRepliescallers compile unchanged.bot-native-commands.tspaths (3 additionaldeliverRepliescallsitesfor inline-keyboard interactions) are intentionally not opted in here
— happy to add in a follow-up if maintainers want them mirrored.
deliverOutboundPayloadssimilarly; the email-inbox hook sessionshows the same symptom but via a different code path. Out of scope
for this fix.
user-side append is not added: the channel-mirror system(the
appendAssistantMessageToSessionTranscriptfamily) appears tobe assistant-only by design, and there is no public
appendUserMessage*API to mirror to. If user-side mirroring isintended, that is a separate change.