Skip to content

feat(telegram): accept .html/.htm document uploads and inject stripped text - #36209

Open
nitishrajnr wants to merge 1 commit into
NousResearch:mainfrom
nitishrajnr:feat/telegram-html-document-ingest
Open

feat(telegram): accept .html/.htm document uploads and inject stripped text#36209
nitishrajnr wants to merge 1 commit into
NousResearch:mainfrom
nitishrajnr:feat/telegram-html-document-ingest

Conversation

@nitishrajnr

Copy link
Copy Markdown

Problem

.html files attached as Telegram documents are currently rejected:

Unsupported document type '.html'. Supported types: .cfg, .csv, .docx, .ini, .json, .log, .md, .pdf, .pptx, .py, .sh, .toml, .ts, .txt, .xlsx, .xml, .yaml, .yml, .zip

This blocks a common workflow — sending exported web pages, saved articles, design runbooks, or HTML reports straight into a chat.

Fix

  1. Add .html and .htmtext/html to SUPPORTED_DOCUMENT_TYPES in gateway/platforms/base.py.
  2. Extend the existing text-injection branch in gateway/platforms/telegram.py (currently only handles .md / .txt) with an HTML→text path:
    • Uses BeautifulSoup when available (clean structured strip).
    • Falls back to a small regex + html.unescape strip when bs4 isn't installed — so this does not introduce a new hard dependency.
    • Reuses the same 100 KB injection cap.
    • ImportError-only fallback keeps genuine parse failures surfaceable via the outer logger.warning.

Behaviour after the patch

User sends runbook.html (25 KB) → Hermes injects:

[Content of runbook.html (HTML stripped to text)]:
<clean text of the page>

…into event.text exactly like .md / .txt today. The cached file path is still attached to media_urls.

Why inline-text injection (not just whitelisting)

Whitelisting alone would cache the file but leave the agent with raw <div> markup or no content at all. The existing .md/.txt injection pattern already establishes the precedent.

Out of scope

  • Discord adapter — same gap exists there (same log line); happy to follow up in a separate PR.
  • Adding beautifulsoup4 to pyproject.toml — left out intentionally; the regex fallback is sufficient and avoids dependency churn.

Test plan

  1. Send any .html file ≤100 KB from a Telegram chat to a Hermes instance.
  2. Confirm agent receives the content (no rejection) and can answer questions grounded in the file.

Verified locally with a 25 KB .html runbook on a live Hermes profile.

…d text

Previously, .html files sent as Telegram document attachments were rejected
with 'Unsupported document type'. This adds .html and .htm to
SUPPORTED_DOCUMENT_TYPES and extends the existing text-injection branch
(used for .md and .txt) to inline HTML content as plain text into
event.text — so the agent receives readable content instead of a path
to a cached HTML blob.

- Adds .html/.htm → text/html to SUPPORTED_DOCUMENT_TYPES (base.py).
- Adds an injection branch in the Telegram adapter that uses
  BeautifulSoup when available and falls back to a regex+html.unescape
  tag-strip when it isn't, so no new hard dependency is introduced.
- 100 KB injection cap shared with the existing .md/.txt branch.
- ImportError-only fallback so genuine parse failures still surface in
  the catch-all logger.warning.

Use case: users sending exported web pages, saved articles, design
runbooks or HTML reports get parsed content instead of an unsupported-
type error.
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/gateway Gateway runner, session dispatch, delivery platform/telegram Telegram bot adapter labels Jun 1, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to existing open PRs on the same gap: #12702 (simple .html/.htm allowlist addition) and #19224 (broader document-intelligence pipeline with BeautifulSoup). This PR adds Telegram-specific HTML→text injection on top of the allowlist. Maintainers may want to consolidate the allowlist change with #12702 and the cross-platform extract_media() allowlist fixes (#30518, #31560) to avoid fragmenting the HTML-support work.

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for addressing HTML document ingestion. Current main has since generalized acceptance and inline injection, but the markup-stripping portion remains distinct.

Problems

  • The diff targets gateway/platforms/telegram.py, which no longer exists on current main; the live handler is plugins/platforms/telegram/adapter.py:7900-8034 after 5600105478ffde29d7566b45421b100eaa29c4ef moved the adapter.
  • 4314d451ca961cb50c3430197a3a2c7a8575fd0e already accepts every authorized inbound document and makes .html/.htm text-injectable through gateway/platforms/base.py:1393-1406. Current Telegram injection raw-decodes at plugins/platforms/telegram/adapter.py:8013-8023; Discord and Slack do the same at plugins/platforms/discord/adapter.py:6433-6449 and plugins/platforms/slack/adapter.py:3116-3129. A Telegram-only stripper would diverge from that current shared behavior.
  • The PR diff contains no regression test for HTML stripping.

Suggested changes

  • Port the remaining stripping behavior to the current adapter location and resolve whether it should be shared across platform text injection.
  • Add a Telegram document test asserting cached HTML is injected as text without tags and remains subject to the 100 KiB cap.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026

@GottZ GottZ 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.

This was generated by AI during triage.

Summary

Two PRs address HTML document ingestion: #36209 adds an allowlist entry plus BeautifulSoup/regex-based Telegram-only text extraction, while #40584 adds the same allowlist support plus a tested Telegram-only sanitizer. Current main already accepts and raw-inlines HTML across Telegram, Discord, and Slack, so only shared markup cleanup remains unresolved.

Related pull requests

  • #36209 related — (+24/-0) — keep open for re-scope, not merge-ready as-is: the allowlist/inline-ingestion portion is already on main, and the remaining BeautifulSoup/regex stripping targets the obsolete gateway/platforms/telegram.py path without regression tests. This follows the visible keep_open review on #36209: port the sanitizer to a shared current-main path and cover all affected adapters.
  • #40584 [closed] duplicate — (+80/-1) — closed as superseded in its current form: it duplicates the already-landed HTML acceptance path and implements sanitization only in the obsolete Telegram handler, although its non-content stripping logic and regression tests remain useful reference material. The visible keep_open review proposed salvaging it as shared cross-platform cleanup, but the author subsequently closed it and agreed that any follow-up should use the shared current adapter path with cross-adapter coverage.

Duplicates

#36209 and #40584 substantially duplicate the obsolete HTML/HTM allowlist and Telegram inline-injection changes; #40584 additionally provides a more explicit sanitizer and regression tests.

Suggested consolidation

Use #36209 as the consolidation vehicle, but merge it only after replacing its current diff with shared HTML sanitization for the live Telegram, Discord, and Slack injection paths and adding cross-adapter regression coverage. Keep #40584 closed as superseded/duplicate, while reusing its sanitizer cases and tests as reference for the re-scoped #36209.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    subgraph Dup36209 ["PRs duplicating each other"]
        P36209["PR #36209 (open)"]
        P40584["PR #40584 (closed)"]
    end
    class P36209 open
    class P40584 closed
    class P36209 target
    click P36209 "https://github.com/NousResearch/hermes-agent/pull/36209"
    click P40584 "https://github.com/NousResearch/hermes-agent/pull/40584"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed or no verify verdict yet (state tag in the node label).

Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 8 kB of PR diffs, 4 kB of issue/PR text, 5 kB of discussion (6 comments), 1 verify verdict. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

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

Labels

comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have platform/telegram Telegram bot adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants