Class: HermesAgent::Client::Resources::Jobs

Inherits:
Object
  • Object
show all
Defined in:
lib/hermes_agent/client/resources/jobs.rb

Overview

The jobs resource: the Jobs API (/api/jobs) for scheduled background work — cron-like recurring tasks, one-shot deferred tasks, and watchdog scripts. On a server configured with an API key, these calls require a bearer token (see HermesAgent::Client / Configuration).

Note this resource lives under /api/jobs, not /v1, and is not advertised in /v1/capabilities — it may be gated, versioned separately, or absent in some builds; confirm against a server that exposes it.

No terminal state to poll. The server deletes a job once it is exhausted: a one-shot (once) job is gone after its single run, and a repeat-capped job is gone after its final run. After that, #get (and #trigger) raise NotFoundError — a client cannot poll such a job for its outcome once it completes.

Instance Method Summary collapse

Instance Method Details

#create(name:, schedule:, prompt: nil, repeat: nil, deliver: nil, skills: nil, script: nil, no_agent: nil, **extra) ⇒ Entities::Job

Create a scheduled job. name and schedule are required.

schedule is a string parsed server-side into a once / interval / cron schedule: a bare duration ("30m"), an absolute timestamp ("2027-02-03T14:00:00"), an interval ("every 30m"), or a cron expression ("0 9 * * *"). The override slots (model, provider, base_url, workdir, profile, context_from) are not writable via this API and so are not parameters — they are silently ignored if sent. A caller who really wants to send unmodeled fields can pass them through extra.

Parameters:

  • name (String)

    The job name (required).

  • schedule (String)

    The schedule string (required; see above).

  • prompt (String, nil) (defaults to: nil)

    The task instruction. Omitted when nil.

  • repeat (Integer, nil) (defaults to: nil)

    The maximum number of runs (nil = unbounded). Omitted when nil.

  • deliver (String, nil) (defaults to: nil)

    The delivery target (defaults server-side to "local"). Omitted when nil. Not validated on write.

  • skills (Array<String>, nil) (defaults to: nil)

    Attached skill names. Omitted when nil.

  • script (String, nil) (defaults to: nil)

    A script path under ~/.hermes/scripts/. Omitted when nil. Note: the reference gateway's create handler silently drops this field (it stays null); kept as a parameter for forward-compatibility and other deployments.

  • no_agent (Boolean, nil) (defaults to: nil)

    Whether to skip the LLM and deliver the script's stdout verbatim. Omitted when nil (so false is sent). Note: like script, silently dropped by the reference gateway's create handler (stays false).

  • extra (Hash)

    Additional request-body fields merged in as-is.

Returns:

Raises:

  • (BadRequestError)

    On a missing name/schedule (400).

  • (ServerError)

    On an unparseable schedule — the server returns 500, not 400, even though it is really invalid input.

  • (APIError)

    If the server returns another non-2xx response.



88
89
90
91
92
93
94
95
96
97
98
# File 'lib/hermes_agent/client/resources/jobs.rb', line 88

def create(name:, schedule:, prompt: nil, repeat: nil, deliver: nil,
           skills: nil, script: nil, no_agent: nil, **extra)
  body = {name: name, schedule: schedule, **extra}
  body[:prompt] = prompt unless prompt.nil?
  body[:repeat] = repeat unless repeat.nil?
  body[:deliver] = deliver unless deliver.nil?
  body[:skills] = skills unless skills.nil?
  body[:script] = script unless script.nil?
  body[:no_agent] = no_agent unless no_agent.nil?
  Entities::Job.new(@transport.post("/api/jobs", body).body["job"])
end

#delete(job_id) ⇒ Boolean

Delete a job (also cancels any in-flight run).

Parameters:

  • job_id (String)

    The job id (12 hex characters).

Returns:

  • (Boolean)

    true (mapped from the server's {"ok": true}).

Raises:

  • (NotFoundError)

    If no such job exists.

  • (APIError)

    If the server returns another non-2xx response.



162
163
164
# File 'lib/hermes_agent/client/resources/jobs.rb', line 162

def delete(job_id)
  @transport.delete("/api/jobs/#{job_id}")["ok"] == true
end

#get(job_id) ⇒ Entities::Job

Retrieve a job by id.

Parameters:

  • job_id (String)

    The job id (12 hex characters).

Returns:

Raises:

  • (NotFoundError)

    If no such job exists — including a job the server already deleted because it was exhausted (a once job after its run, or a capped job after its final run).

  • (APIError)

    If the server returns another non-2xx response.



110
111
112
# File 'lib/hermes_agent/client/resources/jobs.rb', line 110

def get(job_id)
  Entities::Job.new(@transport.get("/api/jobs/#{job_id}")["job"])
end

#list(include_disabled: false) ⇒ Array<Entities::Job>

List the scheduled jobs. By default the server returns only enabled jobs; pass include_disabled: true to include paused/disabled ones. (The list is never paginated — the full set is always returned.)

Parameters:

  • include_disabled (Boolean) (defaults to: false)

    Whether to include disabled (paused) jobs. Defaults to false (enabled jobs only).

Returns:

  • (Array<Entities::Job>)

    The jobs (empty when there are none).

Raises:

  • (APIError)

    If the server returns a non-2xx response.



46
47
48
49
50
# File 'lib/hermes_agent/client/resources/jobs.rb', line 46

def list(include_disabled: false)
  path = include_disabled ? "/api/jobs?include_disabled=true" : "/api/jobs"
  body = @transport.get(path)
  Array(body["jobs"]).map { |raw| Entities::Job.new(raw) }
end

#pause(job_id) ⇒ Entities::Job

Pause a job without deleting it (sets enabled: false). Idempotent: pausing an already-paused job is not an error.

Parameters:

  • job_id (String)

    The job id (12 hex characters).

Returns:

Raises:

  • (NotFoundError)

    If no such job exists.

  • (APIError)

    If the server returns another non-2xx response.



175
176
177
# File 'lib/hermes_agent/client/resources/jobs.rb', line 175

def pause(job_id)
  Entities::Job.new(@transport.post("/api/jobs/#{job_id}/pause", {}).body["job"])
end

#resume(job_id) ⇒ Entities::Job

Resume a paused job (recomputes next_run_at from the resume time). Idempotent: resuming an already-scheduled job is not an error.

Parameters:

  • job_id (String)

    The job id (12 hex characters).

Returns:

Raises:

  • (NotFoundError)

    If no such job exists.

  • (APIError)

    If the server returns another non-2xx response.



188
189
190
# File 'lib/hermes_agent/client/resources/jobs.rb', line 188

def resume(job_id)
  Entities::Job.new(@transport.post("/api/jobs/#{job_id}/resume", {}).body["job"])
end

#trigger(job_id) ⇒ Entities::Job

Trigger a job to run out of schedule.

This is asynchronous: it advances the job's next_run_at to "now" so the scheduler picks it up on its next tick, then returns the job immediately — it does not block on or return the run's result, and last_run_at / last_status / repeat.completed are not yet updated when it returns. (For a one-shot or final-run job, the job may be deleted once it fires, so it cannot be polled afterward — see #get.)

Parameters:

  • job_id (String)

    The job id (12 hex characters).

Returns:

Raises:

  • (NotFoundError)

    If no such job exists.

  • (APIError)

    If the server returns another non-2xx response.



207
208
209
# File 'lib/hermes_agent/client/resources/jobs.rb', line 207

def trigger(job_id)
  Entities::Job.new(@transport.post("/api/jobs/#{job_id}/run", {}).body["job"])
end

#update(job_id, name: nil, schedule: nil, prompt: nil, repeat: nil, deliver: nil, skills: nil, script: nil, no_agent: nil, **extra) ⇒ Entities::Job

Update a job (a partial merge over the writable fields). Sent fields are merged onto the existing job; a sent schedule is re-parsed and next_run_at recomputed. The override slots are not writable here either (silently ignored), so they are not parameters.

Parameters:

  • job_id (String)

    The job id (12 hex characters).

  • name (String, nil) (defaults to: nil)

    A new name. Omitted when nil.

  • schedule (String, nil) (defaults to: nil)

    A new schedule string (re-parsed). Omitted when nil.

  • prompt (String, nil) (defaults to: nil)

    A new prompt. Omitted when nil.

  • repeat (Integer, nil) (defaults to: nil)

    A new run cap. Omitted when nil.

  • deliver (String, nil) (defaults to: nil)

    A new delivery target. Omitted when nil.

  • skills (Array<String>, nil) (defaults to: nil)

    New skill names. Omitted when nil.

  • script (String, nil) (defaults to: nil)

    A new script path. Omitted when nil. Note: silently dropped by the reference gateway (see #create).

  • no_agent (Boolean, nil) (defaults to: nil)

    A new no_agent flag. Omitted when nil. Note: silently dropped by the reference gateway (see #create).

  • extra (Hash)

    Additional request-body fields merged in as-is.

Returns:

Raises:



140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/hermes_agent/client/resources/jobs.rb', line 140

def update(job_id, name: nil, schedule: nil, prompt: nil, repeat: nil,
           deliver: nil, skills: nil, script: nil, no_agent: nil, **extra)
  body = {**extra}
  body[:name] = name unless name.nil?
  body[:schedule] = schedule unless schedule.nil?
  body[:prompt] = prompt unless prompt.nil?
  body[:repeat] = repeat unless repeat.nil?
  body[:deliver] = deliver unless deliver.nil?
  body[:skills] = skills unless skills.nil?
  body[:script] = script unless script.nil?
  body[:no_agent] = no_agent unless no_agent.nil?
  Entities::Job.new(@transport.patch("/api/jobs/#{job_id}", body)["job"])
end