Skip to content

fix: deliver cron MEDIA tags as native attachments#4517

Closed
boobutler wants to merge 1 commit into
NousResearch:mainfrom
boobutler:fix/cron-media-delivery
Closed

fix: deliver cron MEDIA tags as native attachments#4517
boobutler wants to merge 1 commit into
NousResearch:mainfrom
boobutler:fix/cron-media-delivery

Conversation

@boobutler

@boobutler boobutler commented Apr 2, 2026

Copy link
Copy Markdown

Summary

Cron-scheduled deliveries to Telegram were sending raw MEDIA:/path/to/file text instead of native image attachments. This fix routes cron delivery through the same media extraction path used by live chat responses.

Root Cause

_deliver_result() in cron/scheduler.py (line 209) passed delivery_content directly to _send_to_platform() without extracting MEDIA: tags first. The live chat path handles this via BasePlatformAdapter.extract_media(), but the cron delivery path bypassed it entirely — so Telegram users received the literal tag string instead of an attached image.

Evidence from gateway.error.log:

WARNING gateway.platforms.base: [Telegram] Failed to send media (.png\nmedi): File not found: /tmp/analyst/charts/oil_30min.png\nMEDI

The error log shows the path was mangled into one long string with embedded newlines, proving the raw content was sent instead of extracting individual MEDIA lines.

Investigation

The 2026-04-03 Argus morning scan (job d7d7376d595b) ran at 10:06 AM and produced a valid report with 4 charts generated in /tmp/analyst/charts/:

  • oil_30min.png
  • near_7d.png
  • grass_7d.png
  • silver_30min.png

The response saved to cron/output/d7d7376d595b/2026-04-03_10-06-05.md shows proper MEDIA tags in the output (lines 386-389). The agent did its part perfectly — the failure was entirely in the delivery plumbing.

Fix

  • Import BasePlatformAdapter.extract_media in _deliver_result() and call it on delivery_content after optional wrapping.
  • Pass cleaned_content (tags stripped) and media_files (extracted paths) into _send_to_platform() for both the normal asyncio.run path and the ThreadPoolExecutor fallback.

Testing

  • Added test_delivery_extracts_media_before_sending in tests/cron/test_scheduler.py to verify MEDIA: tags are stripped from sent text and forwarded as media_files.
  • Extended the clean-output wrapping test to assert media_files == [] when no tags are present.
  • Verified locally with focused tests:
    • source venv/bin/activate && python -m pytest tests/cron/test_scheduler.py -q -n0 -k \"TestDeliverResultWrapping\"
    • Result: 6 passed, 34 deselected

Notes

  • This is a targeted fix for the cron delivery path only.
  • Broader scheduler test failures observed locally were pre-existing and unrelated to this change.
  • Requires gateway restart after patching (the delivery logic runs in the gateway process).
  • One-shot cron jobs with deliver: "telegram" (no chat ID) are silently skipped when TELEGRAM_HOME_CHANNEL env var is not set — use deliver: "origin" or deliver: "telegram:<chat_id>" for explicit targeting.

- extract MEDIA tags in cron scheduler before platform delivery
- pass cleaned text and media_files into send_message_tool
- add regression test for cron MEDIA extraction
@boobutler boobutler force-pushed the fix/cron-media-delivery branch from 8596488 to 700dc40 Compare April 3, 2026 17:52
@boobutler

Copy link
Copy Markdown
Author

Investigation findings (Apr 3, 2026)

Test setup pitfall discovered

The MEDIA extraction fix is correct, but test/validation cron jobs were failing completely (not just showing raw text) because _resolve_delivery_target() silently returns None when deliver: "telegram" is used without a chat_id and TELEGRAM_HOME_CHANNEL env var isn't set. Test jobs must use deliver: "telegram:<chat_id>" or deliver: "origin".

Gateway restart

After patching cron/scheduler.py, the gateway process must be restarted for the fix to take effect. On macOS with launchd, kill <PID> followed by auto-restart worked when launchctl kickstart failed due to user context mismatch.

Argus cron job behavior

The argus-closing-scan job's argus skill contained a workaround note warning about the cron MEDIA bug. The Argus agent was already working around it by not relying on cron attachments for images — confirming the scope and impact.

Status

  • Fix verified: BasePlatformAdapter.extract_media() is called in _deliver_result() before _send_to_platform()
  • Tests pass: test_delivery_extracts_media_before_sending added
  • Branch rebased onto latest origin/main and pushed
  • Pending merge into upstream hermes-agent

@teknium1

teknium1 commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Your core fix (adding extract_media to the delivery path) was already merged in PR #5598. The remaining live adapter path issue was fixed in PR #5921 with credit to all contributors. Thanks @boobutler!

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