Add inline buttons for cron Telegram delivery - #38731
Conversation
b250012 to
f3eca6e
Compare
341c674 to
5bd39ec
Compare
|
Rebased this PR on the current main and resolved the cron/jobs.py conflict by preserving the new locked update_job() path while reapplying cron buttons/profile normalization. Validation run locally:
|
5bd39ec to
815f9a4
Compare
|
Refreshed this PR on current main and resolved the scheduler conflict by preserving main's current DeliveryRouter / Telegram DM-topic routing path while adding cron button metadata into the routed live-adapter delivery metadata. Also updated the Telegram test to load the adapter through the current plugin-adapter loader instead of the removed gateway.platforms.telegram module.\n\nWhy this is still useful:\n- cron deliveries often ask for a lightweight acknowledgement or choice; inline buttons let the user respond without starting a new ambiguous chat turn.\n- button responses are recorded locally in the cron journal, so the feature does not require a new core tool or external service.\n- the live-adapter path keeps existing topic routing and media routing behavior intact; buttons are only attached when a job explicitly defines them.\n\nValidation:\n- python3 -m py_compile cron/jobs.py cron/scheduler.py plugins/platforms/telegram/adapter.py tools/cronjob_tools.py tests/gateway/test_telegram_cron_buttons.py\n- scripts/run_tests.sh tests/gateway/test_telegram_cron_buttons.py tests/cron/test_scheduler.py\n- changed-file secret scan: clean |
815f9a4 to
ca25358
Compare
|
Rebased this PR onto current main and resolved the cron/jobs.py conflict by preserving both the new profile/default-model snapshot logic from main and the inline-button support from this branch. Local validation:
Live GitHub status after push: MERGEABLE / CLEAN. Checks are green except the existing neutral osv-scanner summary. |
7098483 to
9c869a6
Compare
|
Refreshed this PR on current main again and resolved the cron/jobs.py conflict. I preserved the current profile/default-model snapshot and scheduler behavior from main while keeping the inline-button delivery support from this branch. Local validation:
Live GitHub status after push:
|
fd21fd4 to
e1d83f1
Compare
|
Refreshed this PR onto current |
e1d83f1 to
ce09ea4
Compare
|
Follow-up after the rerun: arm64 still failed because the current upstream docker workflow writes the registry build cache even on pull_request runs. The failing log line was again:\n\n |
ce09ea4 to
7145ce2
Compare
|
Second follow-up: after the cache-write fix, CI got past the arm64 registry permission problem and exposed an unrelated base test drift in |
7145ce2 to
600b085
Compare
|
Refreshed again after main advanced and the PR became conflicting. Conflict was only in |
600b085 to
a93643d
Compare
|
Follow-up for the new arm64 docker failure. CI got past the previous conflicts, then failed in |
a93643d to
871ddeb
Compare
|
Follow-up: after the s6 temp-dir fix, the full Python slice exposed two timing-sensitive tests in |
6c9cff4 to
202d235
Compare
|
Refreshed this PR after What changed:
Validation:
Live status after push: |
202d235 to
639aaee
Compare
|
Refreshed this PR after What changed:
Validation before force-push:
Live status after push: |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the cron/Telegram integration work. The inline-button capability is not present on current main, but there are two correctness blockers.
Problems
plugins/platforms/telegram/adapter.py:4443encodes onlyjob_idand button index. The callback then reloads the current job list at:4491. If a job is edited after a message is delivered, tapping its old button can record the new item at that index rather than the choice shown to the user.tools/cronjob_tools.py:1095describes per-job profile execution, but the scheduler only operates under its active profile home (cron/scheduler.py:543-552,:2793,:2816,:3441) and does not consumejob["profile"]. Current cron isolation is intentionally profile-scoped.
Suggested changes
- Persist a delivery-time immutable button mapping or use an opaque callback token, then add a test for editing buttons after delivery.
- Drop the
profilefield from this feature scope. - Separate the unrelated S6 and test-flake changes from this Telegram cron-button work.
Automated hermes-sweeper review.
| logger.warning("[%s] failed to load cron job %s for button callback: %s", self.name, job_id, exc) | ||
| job = None | ||
|
|
||
| buttons = (job or {}).get("buttons") or [] |
There was a problem hiding this comment.
This resolves the click against the job's current button list, but callback data carries only the original index. If buttons are edited after a delivery, an old Telegram button can be journaled as a different current value. Persist a delivery-time mapping or resolve an opaque delivery token instead.
| @@ -1075,6 +1090,27 @@ def cronjob( | |||
| "type": "boolean", | |||
| "description": "When True, this job becomes CONTINUABLE: the user can reply to its delivery and the agent has the brief in context instead of asking 'what is that?'. On thread-capable platforms (Telegram topics, Discord/Slack threads) a dedicated thread is opened for the job and its replies; on DM-only platforms (WhatsApp/Signal) the brief is mirrored into the origin DM session. Use this for conversational recurring jobs the user will reply to — daily briefings, reminders that kick off follow-up work. Leave unset for fire-and-forget alerts/watchdogs. Overrides the global cron.mirror_delivery config for this one job. Only the origin chat is touched (never fan-out targets); no effect when deliver='local'." | |||
| }, | |||
| "profile": { | |||
| "type": "string", | |||
| "description": "Optional Hermes profile name to run the job under. When set, the scheduler resolves that profile, applies a context-local Hermes home override, loads that profile's config/.env for the run, and bridges HERMES_HOME into subprocesses. Any temporary process-environment changes from profile .env loading are restored after the job exits. Use 'default' for the root Hermes profile. Named profiles must already exist. When unset (default), preserves the scheduler's existing profile. On update, pass an empty string to clear. Jobs with profile run sequentially (not parallel) to keep profile-scoped runtime state isolated." | |||
There was a problem hiding this comment.
The scheduler does not implement this advertised per-job profile behavior: it resolves and loads only its active profile home. Please remove this field from the button feature rather than exposing a nonfunctional cross-profile execution contract.
|
@teknium1 thanks, addressed the cron Telegram button review blockers. Changes:
Validation: Also ran |
639aaee to
0d9682d
Compare
0d9682d to
f9aae99
Compare
|
Refreshed this PR after What changed:
Validation:
Live status after force-push:
|
f9aae99 to
edb5c37
Compare
|
Refreshed this PR after What changed:
Validation before/after push:
Live status after force-with-lease push:
|
edb5c37 to
858e2a0
Compare
|
Refreshed this PR after What changed:
Validation before push:
After push:
|
858e2a0 to
ee50aff
Compare
|
Refreshed this PR after What changed:
Validation before/after push:
Current live status after push:
|
Summary
buttonsstorage/schema support for cron jobs.~/.hermes/cron/button_responses.jsonl.Tests
python -m py_compile cron/jobs.py cron/scheduler.py tools/cronjob_tools.py gateway/platforms/telegram.py tests/gateway/test_telegram_cron_buttons.pyscripts/run_tests.sh tests/gateway/test_telegram_cron_buttons.py tests/gateway/test_telegram_clarify_buttons.py tests/gateway/test_telegram_approval_buttons.py tests/tools/test_cronjob_tools.py tests/cron