fix: canonicalize topic session transcript fallback#64869
Conversation
Greptile SummaryThis PR fixes a session transcript file path inconsistency for Telegram topic sessions. When an inbound turn lacks Confidence Score: 5/5Safe to merge — targeted fix for a well-understood data-path bug with matching regression coverage. The change is minimal and correctly uses the existing parseSessionThreadInfo helper. The ?? fallback ensures MessageThreadId still takes precedence; the new path only activates when it is absent. Both tests are well-structured with proper cleanup. No P0/P1 findings. No files require special attention. Reviews (1): Last reviewed commit: "fix: canonicalize topic session transcri..." | Re-trigger Greptile |
When initSessionState has a topic-scoped SessionKey but no MessageThreadId, fallback transcript selection should still land on the topic-qualified JSONL path instead of the bare session file. Match the existing transcript resolver by parsing the thread id from the session key, and cover the regression with a session init test that loads the Telegram session-conversation grammar. Regeneration-Prompt: | Investigate why a Telegram topic session could alternate between <session-id>.jsonl and <session-id>-topic-<n>.jsonl for the same logical session. The fix should be in OpenClaw's session initialization path, not in lossless-claw. Keep behavior unchanged when MessageThreadId is present, but when the inbound turn only carries a topic-scoped SessionKey, derive the same topic-specific transcript path that the canonical transcript resolver would use. Add a regression test that proves initSessionState chooses the topic-qualified file even without MessageThreadId, and make the test load the session-conversation registry needed to parse Telegram :topic: grammar.
58535ee to
539b090
Compare
* fix: canonicalize topic session transcript fallback When initSessionState has a topic-scoped SessionKey but no MessageThreadId, fallback transcript selection should still land on the topic-qualified JSONL path instead of the bare session file. Match the existing transcript resolver by parsing the thread id from the session key, and cover the regression with a session init test that loads the Telegram session-conversation grammar. Regeneration-Prompt: | Investigate why a Telegram topic session could alternate between <session-id>.jsonl and <session-id>-topic-<n>.jsonl for the same logical session. The fix should be in OpenClaw's session initialization path, not in lossless-claw. Keep behavior unchanged when MessageThreadId is present, but when the inbound turn only carries a topic-scoped SessionKey, derive the same topic-specific transcript path that the canonical transcript resolver would use. Add a regression test that proves initSessionState chooses the topic-qualified file even without MessageThreadId, and make the test load the session-conversation registry needed to parse Telegram :topic: grammar. * fix: preserve topic session transcript history
* fix: canonicalize topic session transcript fallback When initSessionState has a topic-scoped SessionKey but no MessageThreadId, fallback transcript selection should still land on the topic-qualified JSONL path instead of the bare session file. Match the existing transcript resolver by parsing the thread id from the session key, and cover the regression with a session init test that loads the Telegram session-conversation grammar. Regeneration-Prompt: | Investigate why a Telegram topic session could alternate between <session-id>.jsonl and <session-id>-topic-<n>.jsonl for the same logical session. The fix should be in OpenClaw's session initialization path, not in lossless-claw. Keep behavior unchanged when MessageThreadId is present, but when the inbound turn only carries a topic-scoped SessionKey, derive the same topic-specific transcript path that the canonical transcript resolver would use. Add a regression test that proves initSessionState chooses the topic-qualified file even without MessageThreadId, and make the test load the session-conversation registry needed to parse Telegram :topic: grammar. * fix: preserve topic session transcript history
* fix: canonicalize topic session transcript fallback When initSessionState has a topic-scoped SessionKey but no MessageThreadId, fallback transcript selection should still land on the topic-qualified JSONL path instead of the bare session file. Match the existing transcript resolver by parsing the thread id from the session key, and cover the regression with a session init test that loads the Telegram session-conversation grammar. Regeneration-Prompt: | Investigate why a Telegram topic session could alternate between <session-id>.jsonl and <session-id>-topic-<n>.jsonl for the same logical session. The fix should be in OpenClaw's session initialization path, not in lossless-claw. Keep behavior unchanged when MessageThreadId is present, but when the inbound turn only carries a topic-scoped SessionKey, derive the same topic-specific transcript path that the canonical transcript resolver would use. Add a regression test that proves initSessionState chooses the topic-qualified file even without MessageThreadId, and make the test load the session-conversation registry needed to parse Telegram :topic: grammar. * fix: preserve topic session transcript history
* fix: canonicalize topic session transcript fallback When initSessionState has a topic-scoped SessionKey but no MessageThreadId, fallback transcript selection should still land on the topic-qualified JSONL path instead of the bare session file. Match the existing transcript resolver by parsing the thread id from the session key, and cover the regression with a session init test that loads the Telegram session-conversation grammar. Regeneration-Prompt: | Investigate why a Telegram topic session could alternate between <session-id>.jsonl and <session-id>-topic-<n>.jsonl for the same logical session. The fix should be in OpenClaw's session initialization path, not in lossless-claw. Keep behavior unchanged when MessageThreadId is present, but when the inbound turn only carries a topic-scoped SessionKey, derive the same topic-specific transcript path that the canonical transcript resolver would use. Add a regression test that proves initSessionState chooses the topic-qualified file even without MessageThreadId, and make the test load the session-conversation registry needed to parse Telegram :topic: grammar. * fix: preserve topic session transcript history
What
Fix OpenClaw session initialization so topic-scoped sessions keep using the topic-qualified transcript path even when an inbound turn does not carry
MessageThreadId.Why
We traced LCM session-history loss to OpenClaw alternating between
<session-id>.jsonland<session-id>-topic-<n>.jsonlfor the same Telegram topic session. That made one logical session look like two transcript files and triggered session-file rotation handling downstream.Changes
SessionKeyduring session init fallbackMessageThreadIdTesting
pnpm -C /Users/phaedrus/Projects/openclaw exec vitest run src/auto-reply/reply/session.test.ts -t "records topic-specific session files" --reporter=verbosepnpm -C /Users/phaedrus/Projects/openclaw exec vitest run src/auto-reply/reply/session.test.ts --reporter=dot