hermes-agent/tests/plugins
Ben 4c8bbe6416 feat(cron): Chronos NAS-mediated managed-cron provider (scale-to-zero)
Phase 4D. The first non-default CronScheduler: plugins/cron/chronos/. Inert
unless cron.provider=chronos; resolve_cron_scheduler falls back to the built-in
if unavailable, so cron never loses its trigger.

Files:
- chronos/__init__.py — ChronosCronScheduler + register(ctx).
  * is_available(): config-only, NO network (portal_url + callback_url + a
    stored Nous access token via get_provider_auth_state). Returns False →
    resolver falls back to built-in.
  * start(): reconcile() then RETURN — no blocking loop, no 60s wake (DQ-1:
    this is what makes scale-to-zero real; the machine wakes only on a
    NAS→agent fire).
  * _arm_one_shot(job): POST NAS provision {job_id, fire_at, agent_callback_url,
    dedup_key=job_id:fire_at}. Agent owns the time → sub-minute fires survive
    (no scheduler 1-minute floor).
  * reconcile(): converge NAS arms toward jobs.json — arm missing/changed-time,
    cancel orphaned, skip paused. Cold process rebuilds from jobs.json +
    idempotent dedup_key.
  * on_jobs_changed(): reconcile (re-arm/cancel the affected one-shot).
  * fire_due(): ABC default (CAS claim + run_one_job) THEN re-arm the next
    one-shot. Job gone (one-shot done / repeat-N exhausted) → no re-arm.
- chronos/_nas_client.py — thin HTTP wrapper for provision/cancel/list using
  the agent's existing refresh-aware Nous token (resolve_nous_access_token).
  Names no scheduler vendor; holds no scheduler creds.
- chronos/plugin.yaml — discovery metadata.

INVARIANT: zero "qstash"/"upstash" hits in plugins/cron, gateway, hermes_cli,
website/docs — the external scheduler is a NAS-internal detail, never named
agent-side.

Tests (13, all NAS mocked, zero network): is_available off-without-config +
on-with-config + makes-no-network; arm payload incl. sub-minute + noop without
next_run; reconcile arms-all / cancels-orphan / skips-paused / skips-already-
armed; fire_due re-arms next / no re-arm when job gone / no re-arm when claim
lost.
2026-06-18 14:40:56 +10:00
..
browser fix(browser): self-review pass — dead-import, log levels, future-proofing 2026-05-17 04:04:15 -07:00
dashboard_auth feat(dashboard-auth): add generic self-hosted OIDC provider 2026-06-04 03:23:45 -07:00
image_gen fix(image_gen): use gpt-5.5 for Codex image host 2026-06-06 19:31:51 -07:00
memory fix(openviking): don't block the command thread on session switch; lock turn state 2026-06-18 00:21:21 +05:30
model_providers fix: route minimax m3 reasoning controls through profile 2026-06-15 07:08:43 -07:00
platforms/photon fix(photon): preserve text in mixed iMessage attachments (salvage #46513) (#46818) 2026-06-17 16:14:24 -05:00
transcription feat(stt): add stt.providers.<name> command-provider registry 2026-05-25 01:41:19 -07:00
tts feat(tts): add register_tts_provider() plugin hook (closes #30398) 2026-05-24 18:04:54 -07:00
video_gen fix(xai): route video models by modality 2026-06-01 19:00:30 -07:00
web revert(web): remove keyless Parallel search fallback (#46350) 2026-06-14 16:47:57 -07:00
__init__.py fix: mem0 API v2 compat, prefetch context fencing, secret redaction (#5423) 2026-04-05 22:43:33 -07:00
test_achievements_plugin.py test: use subprocesses for each test file (#29016) 2026-05-21 16:40:04 +05:30
test_chronos_cron.py feat(cron): Chronos NAS-mediated managed-cron provider (scale-to-zero) 2026-06-18 14:40:56 +10:00
test_discord_runtime_failure.py fix(discord): recover from runtime gateway task exits (#44383) 2026-06-11 15:39:01 -04:00
test_disk_cleanup_plugin.py test: assert disk cleanup prunes protected walks 2026-06-15 05:25:27 -07:00
test_google_meet_audio.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_google_meet_node.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_google_meet_plugin.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_google_meet_realtime.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_kanban_attachments.py feat(kanban): file attachments on tasks (#35395) 2026-05-30 07:41:04 -07:00
test_kanban_dashboard_plugin.py fix(dashboard): sanction plugin WS/upload auth via SDK helpers (gated mode) 2026-06-03 16:59:36 -07:00
test_kanban_worker_runs.py feat(kanban): add POST /runs/{run_id}/terminate endpoint 2026-05-29 00:21:54 -07:00
test_langfuse_plugin.py fix(langfuse): redact base64 data URIs instead of truncating into invalid base64 2026-06-10 10:49:36 +05:30
test_nemo_relay_plugin.py fix(nemo-relay): preserve downstream errors in adaptive execution (#42691) 2026-06-09 02:31:10 -07:00
test_plugin_dashboard_auth_contract.py fix(dashboard): sanction plugin WS/upload auth via SDK helpers (gated mode) 2026-06-03 16:59:36 -07:00
test_retaindb_plugin.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_security_guidance_plugin.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_teams_pipeline_plugin.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00