hermes - 💡(How to fix) Fix [Followup] Mattermost plugin migration (#30916): batch uploads + proxy declaration + live-adapter proxy support [1 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

  1. Preserve the existing per-file error-recovery semantics: if any one file fails (e.g. exceeds Mattermost's max file size), the current code logs and continues. Batched-upload semantics should match (i.e. catch + retry remaining files in a smaller batch on partial failure, or accept all-or-nothing if simpler). Impact: Users behind a corporate proxy who configure MATTERMOST_PROXY will see cron deliveries succeed but live gateway messages fail with a connection error. Confusing.

Root Cause

Why this happens: When MattermostAdapter was originally written, proxy support wasn't wired in. The standalone path got proxy support during this PR because it's the path Discord/Teams plugins established the pattern on. The live adapter retained the older session-construction pattern.

Fix Action

Fixed

Code Example

# plugins/platforms/mattermost/plugin.yaml — add to optional_env:
  - name: MATTERMOST_PROXY
    description: "HTTP(S) proxy URL for outbound Mattermost API calls (cron / standalone delivery)."
    prompt: "Mattermost proxy URL"
    password: false

---

# plugins/platforms/mattermost/adapter.pyin MattermostAdapter.connect()
# around line 203:
from gateway.platforms.base import resolve_proxy_url, proxy_kwargs_for_aiohttp
_proxy = resolve_proxy_url(platform_env_var="MATTERMOST_PROXY")
_sess_kw, self._proxy_req_kw = proxy_kwargs_for_aiohttp(_proxy)
self._session = aiohttp.ClientSession(
    timeout=aiohttp.ClientTimeout(total=30),
    **_sess_kw,
)
# Then thread self._proxy_req_kw into every _api_get / _api_post / _api_delete
# request kwargs so per-request proxy options apply.
RAW_BUFFERClick to expand / collapse

Background

PR #30916 migrated the Mattermost adapter to a bundled plugin (gateway/platforms/mattermost.pyplugins/platforms/mattermost/adapter.py). During the migration we left three behavior / surface gaps as explicit follow-ups rather than expanding the PR's scope. Filing here so they're tracked.

The migration itself is behavior-preserving (6220/6220 tests pass with zero regressions). These follow-ups are real but non-blocking enhancements.

Follow-up 1 — Batch multi-file uploads on POST /api/v4/files

Status: Mattermost's POST /api/v4/files endpoint accepts multiple files in a single multipart form-data POST, but both the live adapter (MattermostAdapter._upload_file, plugins/platforms/mattermost/adapter.py:166) and the standalone sender (_standalone_send, ~line 920) currently upload one file per POST in a loop.

Impact: For multi-file cron deliveries or agent send_message calls that include multiple attachments, this is N round trips instead of 1. Latency-bound.

Why this is mattermost-specific:

  • Discord's POST /channels/{id}/messages actually accepts only one attachment per request — Discord can't batch.
  • Mattermost's POST /api/v4/files accepts multiple files form fields (API ref) — Mattermost can.

Proposed change:

  1. In _upload_file and _standalone_send, collect all files into one aiohttp.FormData() (multiple files fields) and POST once.
  2. The response's file_infos[] array already returns one entry per uploaded file in order — just collect every id instead of [0]["id"].
  3. Preserve the existing per-file error-recovery semantics: if any one file fails (e.g. exceeds Mattermost's max file size), the current code logs and continues. Batched-upload semantics should match (i.e. catch + retry remaining files in a smaller batch on partial failure, or accept all-or-nothing if simpler).

Sizing: Small — ~40 LoC change in two places, with tests in tests/gateway/test_mattermost.py for the live path and tests/tools/test_send_message_missing_platforms.py for the standalone path.

Follow-up 2 — Surface MATTERMOST_PROXY in plugin.yaml optional_env

Status: PR #30916 added MATTERMOST_PROXY support to _standalone_send (via gateway.platforms.base.resolve_proxy_url(platform_env_var="MATTERMOST_PROXY")), but the env var is not declared in plugin.yaml under optional_env. Users won't see it in hermes setup or hermes plugins inspect mattermost, even though the code reads it.

Impact: Discoverability — users on corporate networks needing a proxy will not know the env var exists unless they read the source.

Proposed change:

# plugins/platforms/mattermost/plugin.yaml — add to optional_env:
  - name: MATTERMOST_PROXY
    description: "HTTP(S) proxy URL for outbound Mattermost API calls (cron / standalone delivery)."
    prompt: "Mattermost proxy URL"
    password: false

Sizing: Trivial — one YAML block.

Follow-up 3 — Honor MATTERMOST_PROXY in the live adapter's aiohttp.ClientSession

Status: MattermostAdapter.connect() creates its aiohttp.ClientSession at plugins/platforms/mattermost/adapter.py:203 without any proxy configuration. Only the standalone sender (_standalone_send) honors MATTERMOST_PROXY. This is asymmetric — the in-process live adapter (used while the gateway is running) silently ignores the proxy env var that the cron/standalone path respects.

Impact: Users behind a corporate proxy who configure MATTERMOST_PROXY will see cron deliveries succeed but live gateway messages fail with a connection error. Confusing.

Why this happens: When MattermostAdapter was originally written, proxy support wasn't wired in. The standalone path got proxy support during this PR because it's the path Discord/Teams plugins established the pattern on. The live adapter retained the older session-construction pattern.

Proposed change:

# plugins/platforms/mattermost/adapter.py — in MattermostAdapter.connect()
# around line 203:
from gateway.platforms.base import resolve_proxy_url, proxy_kwargs_for_aiohttp
_proxy = resolve_proxy_url(platform_env_var="MATTERMOST_PROXY")
_sess_kw, self._proxy_req_kw = proxy_kwargs_for_aiohttp(_proxy)
self._session = aiohttp.ClientSession(
    timeout=aiohttp.ClientTimeout(total=30),
    **_sess_kw,
)
# Then thread self._proxy_req_kw into every _api_get / _api_post / _api_delete
# request kwargs so per-request proxy options apply.

Sizing: Medium — needs careful threading of _proxy_req_kw through every session.get/post call site in the adapter (~10 sites). Compare to gateway/platforms/discord/adapter.py which already does this for the in-process path; mirror that pattern.

Test plan: Add a unit test that constructs MattermostAdapter with MATTERMOST_PROXY=http://proxy.example and asserts the aiohttp.ClientSession is built with the right connector (or _req_kw carries proxy= on calls).

Related issues

  • #23704 — "Hermes cannot send messages with file attachments on Mattermost" — the standalone sender's media-upload support (added in PR #30916) addresses this for the cron path. The live in-process path already worked via MattermostAdapter._upload_file. Worth verifying against the reporter's environment after #30916 lands.
  • #13827 — "Gateway config-backed Home Assistant / Mattermost / Signal adapters are blocked by env-only requirement checks" — PR #30916's apply_yaml_config_fn for mattermost partially addresses this (YAML keys now flow through to env vars), but is_connected and check_fn still gate on the env vars. Needs a separate audit of all is_connected hooks across plugin platforms to read from PlatformConfig.token / .extra first.

Coordination

Wait for #30916 to merge before opening fix PRs for any of these.

cc @teknium1

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix [Followup] Mattermost plugin migration (#30916): batch uploads + proxy declaration + live-adapter proxy support [1 pull requests]