feat(cron): monitor-mode jobs (monitor_script/monitor_url) + blocked_config status (issue #861) (#871)

- CronJob model gains optional monitor_script/monitor_url (additive-safe)
- Job editor: Monitor mode section (off/script/url) with XOR source clearing;
  disabled while no-agent is set (backend invariant); new jobs apply monitor
  via create -> follow-up PUT with rollback delete on failure (the REST create
  model drops the fields)
- Job list/details: blocked_config renders as a distinct error badge
  ('Blocked (config)'), no_change as informational; monitor source shown in
  run details

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
M57andM57 authored and GitHub committed 2026-08-10 15:35:05 +03:00
1 parent 4a034684bb
commit a9cb89a925
7 files changed
+448 -21

No files matched your search

@@ -38,6 +38,10 @@ data class CronJob(
val workdir: String? = null,
val no_agent: Boolean? = null,
val repeat: CronJobRepeat? = null,
// Monitor-mode jobs (backend cron/monitor.py): a source script/URL whose
// output is hashed each tick — the agent runs only when it changes.
val monitor_script: String? = null,
val monitor_url: String? = null,
) {
val scheduleText: String
get() =
@@ -52,4 +56,8 @@ data class CronJob(
val nextRunTime: String
get() = next_run ?: next_run_at ?: ""
/** The configured monitor source (script or URL), if any. */
val monitorSource: String?
get() = monitor_script ?: monitor_url
}
@@ -18,6 +18,11 @@ data class CreateCronJobRequest(
val workdir: String? = null,
val no_agent: Boolean = false,
val repeat: Int? = null,
// Monitor mode. NOTE: the backend REST create model does not carry these
// yet (they are silently dropped on POST) — the ViewModel applies them
// via a follow-up PUT; keep them here for forward compatibility.
val monitor_script: String? = null,
val monitor_url: String? = null,
)
@Serializable