Skip to content

feat(telegram): add a persistThreadHistory option - #1079

Closed
mlenczewski-tidio wants to merge 1 commit into
vercel:mainfrom
tidio-tools:feat/telegram-persist-thread-history-option
Closed

mlenczewski-tidio wants to merge 1 commit into
vercel:mainfrom
tidio-tools:feat/telegram-persist-thread-history-option

Conversation

@mlenczewski-tidio

Copy link
Copy Markdown
Contributor

Summary

The Telegram adapter copies every incoming message into the Chat state adapter, and persistThreadHistory is typed as the literal true, so neither config nor a subclass can turn that off. An app that keeps its own transcript ends up with a second, unredacted copy of every message in the state store that nothing reads.

  • Adds a persistThreadHistory config option. It defaults to true, so nothing changes unless you set it, the same way the web adapter's persistMessageHistory works.
  • Types the field as boolean, so a subclass can override it too (override readonly persistThreadHistory = false).
  • Docs: a new row in the Telegram configuration table.

The adapter's own fetchMessages reads its in-process cache, not the state adapter, so turning the option off only affects what thread.messages / channel.messages can return from state.

Test plan

  • New config tests for the default (true) and persistThreadHistory: false.
  • New type test in subclass.test-d.ts showing a subclass can override the field with false. It fails against the old literal true declaration and passes with this change.
  • pnpm validate passes.

Checklist

  • All commits are signed and verified
  • All commits are signed off for the DCO (git commit -s)
  • pnpm validate passes
  • Changeset added (or N/A — see CONTRIBUTING.md)
  • Documentation updated (or N/A)

Telegram always copied every incoming message into the Chat state adapter,
and persistThreadHistory was typed as the literal `true`, so neither config
nor a subclass could turn it off. An app that keeps its own transcript ended
up with a second, unredacted copy of every message in the state store.

Add a persistThreadHistory config option, defaulting to true as before, and
type the field as boolean so a subclass can override it too.

Signed-off-by: Miłosz Lenczewski <m.lenczewski@tidio.net>
@mlenczewski-tidio
mlenczewski-tidio requested a review from a team October 21, 2026 11:50
@vercel

vercel Bot commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

@mlenczewski-tidio is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

@roboeve roboeve Bot left a comment

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.

Thanks for this. The change is small and correct: core only reads the flag in two places (incoming-message persistence and wiring the history cache into threads), so a per-instance boolean works, the default is unchanged, and minor is the right bump. A few things before merge:

Required

  • The wording undersells what the flag does. The JSDoc in types.ts, the docs row in telegram.mdx, and the changeset all say turning it off stops persisting incoming messages. It also stops persisting the bot's own sent messages: Thread and Channel only append posts when the history cache is wired in, and that cache is now gated on this flag (for example thread.ts L568 and channel.ts L339). Please say "incoming and sent messages", matching how the Twitch docs describe persistThreadHistory.

Nits

  • Existing data. Turning the flag off does not remove history that is already in the state adapter; it stays until its TTL expires. A sentence in the docs row would save people from assuming it gets purged.
  • Subclass override precedence. A subclass that declares override readonly persistThreadHistory = false ignores the persistThreadHistory config value, because subclass field initializers run after the base constructor. That is expected, but a short note on the field (or in the JSDoc) would make the precedence explicit.
  • Test coverage. The new tests assert the property value only. That is fine since chat.test.ts already covers the core gating, but an integration-style test showing a Telegram message is not appended to state with persistThreadHistory: false would lock in the end-to-end behavior.
  • Catalog (optional). packages/catalog/src/adapters/official/telegram.ts lists config-only options (nativeStreaming, streamingEditIntervalMs). Consider adding persistThreadHistory there, the way the web catalog entry lists persistMessageHistory.

@bensabic

Copy link
Copy Markdown
Collaborator

Thanks for this, @mlenczewski-tidio. We wanted to rebase it and add a few docs and test changes, but this branch lives in a fork owned by the tidio-tools organization, and GitHub doesn't let maintainers push to organization-owned forks. We've moved the work to #1098, which keeps your commit with your authorship and sign-off.

For future contributions, please open PRs from a fork under a personal account with "Allow edits by maintainers" turned on. Going forward we won't be able to accept PRs from organization-owned forks, since we can't make changes to them before merging.

@bensabic bensabic closed this Oct 27, 2026
bensabic added a commit that referenced this pull request Oct 27, 2026
This picks up #1079 from @mlenczewski-tidio. That PR comes from a fork
owned by the `tidio-tools` organization, and GitHub doesn't let
maintainers push to organization-owned forks, so we couldn't update it
in place. Their commit is kept with their authorship and sign-off, and a
second commit adds the follow-up changes. The branch is rebased onto
main, which resolves the merge conflict in
`packages/adapter-telegram/src/subclass.test-d.ts` with the new long
message tests.

The Telegram adapter copied every incoming message into the Chat state
adapter, and `persistThreadHistory` was typed as the literal `true`, so
neither config nor a subclass could turn it off. An app that keeps its
own transcript ended up with a second, unredacted copy of every message
in the state store. This adds a `persistThreadHistory` option that
defaults to `true`, and types the field as `boolean` so a subclass can
override it.

```ts
const telegram = createTelegramAdapter({ persistThreadHistory: false });
```

With `false`, the SDK saves neither incoming messages nor the bot's own
posts, so `thread.messages` and `bot.history.thread.list()` only see
what the current process has cached. On serverless that's empty after a
cold start. The Telegram docs, README, core history docs, and catalog
entry now describe this.

New tests run a real `Chat` with the Telegram adapter and check what
lands in state with the option on and off.

---------

Signed-off-by: Miłosz Lenczewski <m.lenczewski@tidio.net>
Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com>
Co-authored-by: Miłosz Lenczewski <m.lenczewski@tidio.net>
Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants