Skip to content

Commit 0adf012

Browse files
ericdalloeca-agent
andcommitted
Show job name in bg_job list/read_output/kill outputs
Surface the value passed via shell_command's `background` arg (stored as `:summary`) as a quoted prefix in the bg_job tool outputs, so users see e.g. `Background job "dev-server" (job-1) killed.` instead of just the id. 🤖 Generated with [eca](https://eca.dev) Co-Authored-By: eca-agent <git@eca.dev>
1 parent 0a3cbb8 commit 0adf012

3 files changed

Lines changed: 51 additions & 21 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- `bg_job` now shows the job name (from `shell_command`'s `background` arg) in `list`, `read_output` and `kill` outputs, e.g. `Background job "dev-server" (job-1) killed.`.
6+
57
## 0.135.3
68

79
- Fix plugin primary agents being dropped from the selector when model sync finishes after plugin resolution.

‎src/eca/features/tools/background.clj‎

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,21 @@
66

77
(set! *warn-on-reflection* true)
88

9-
;; ---------------------------------------------------------------------------
10-
;; Action handlers
11-
;; ---------------------------------------------------------------------------
9+
(defn ^:private job-prefix
10+
"Render `\"<name>\" (job-id)` when the job has a `:summary`, otherwise just the id."
11+
[{:keys [id summary]}]
12+
(if-let [s (not-empty summary)]
13+
(str "\"" s "\" (" id ")")
14+
id))
1215

1316
(defn ^:private action-list [_arguments]
1417
(let [jobs (remove :notified (bg/list-jobs))]
1518
(if (seq jobs)
1619
(tools.util/single-text-content
1720
(string/join
1821
"\n"
19-
(map (fn [{:keys [id type label summary status exit-code] :as job}]
20-
(str "- " id
21-
(when summary (str " (" summary ")"))
22+
(map (fn [{:keys [type label status exit-code] :as job}]
23+
(str "- " (job-prefix job)
2224
" [" (name type) "] "
2325
(name status)
2426
(when exit-code (str " (exit " exit-code ")"))
@@ -30,31 +32,30 @@
3032
(defn ^:private action-read-output [{:keys [job-id]}]
3133
(if-let [result (bg/read-output! job-id)]
3234
(let [{:keys [lines dropped status exit-code]} result
35+
prefix (if-let [job (bg/get-job job-id)]
36+
(job-prefix job)
37+
job-id)
3338
output (if (seq lines)
3439
(string/join "\n" (map bg/format-output-line lines))
3540
"(no new output)")]
3641
(tools.util/single-text-content
37-
(str "Job " job-id " — " (name status)
42+
(str "Job " prefix " — " (name status)
3843
(when exit-code (str " (exit " exit-code ")"))
3944
(when (pos? dropped) (str "\n[" dropped " lines dropped from buffer]"))
4045
"\n\n" output)))
4146
(tools.util/single-text-content (str "Background job " job-id " not found.") true)))
4247

4348
(defn ^:private action-kill [{:keys [job-id]}]
44-
(if (bg/get-job job-id)
49+
(if-let [job (bg/get-job job-id)]
4550
(if (bg/kill-job! job-id)
46-
(tools.util/single-text-content (str "Background job " job-id " killed."))
51+
(tools.util/single-text-content (str "Background job " (job-prefix job) " killed."))
4752
(let [current-status (:status (bg/get-job job-id))]
4853
(tools.util/single-text-content
49-
(str "Background job " job-id " is not running"
54+
(str "Background job " (job-prefix job) " is not running"
5055
(when current-status (str " (status: " (name current-status) ")")) ".")
5156
true)))
5257
(tools.util/single-text-content (str "Background job " job-id " not found.") true)))
5358

54-
;; ---------------------------------------------------------------------------
55-
;; Tool handler
56-
;; ---------------------------------------------------------------------------
57-
5859
(defn ^:private bg-job [arguments _ctx]
5960
(let [action (get arguments "action")
6061
job-id (get arguments "job_id")]
@@ -68,10 +69,6 @@
6869
(tools.util/single-text-content "job_id is required for kill action." true))
6970
(tools.util/single-text-content (str "Unknown action: " action ". Use list, read_output, or kill.") true))))
7071

71-
;; ---------------------------------------------------------------------------
72-
;; Tool definition
73-
;; ---------------------------------------------------------------------------
74-
7572
(def definitions
7673
{"bg_job"
7774
{:description (tools.util/read-tool-description "bg_job")
@@ -84,10 +81,14 @@
8481
:required ["action"]}
8582
:summary-fn (fn [{:keys [args]}]
8683
(let [action (get args "action")
87-
job-id (get args "job_id")]
84+
job-id (get args "job_id")
85+
label (when job-id
86+
(if-let [job (bg/get-job job-id)]
87+
(job-prefix job)
88+
job-id))]
8889
(case action
8990
"list" "Listing background jobs"
90-
"read_output" (str "Reading output of " job-id)
91-
"kill" (str "Killing " job-id)
91+
"read_output" (str "Reading output of " label)
92+
"kill" (str "Killing " label)
9293
"Managing background job")))
9394
:handler #'bg-job}})

‎test/eca/features/background_tasks_test.clj‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,13 @@
254254
(let [result (handler {"action" "list"} {})]
255255
(is (match? {:error false
256256
:contents [{:type :text :text #"job-\d+.*npm run dev"}]}
257+
result))))
258+
259+
(testing "list includes quoted job name when summary is set"
260+
(bg/register-shell-job! {:label "npm test" :summary "dev-server" :process (mock-process) :working-directory "/tmp"})
261+
(let [result (handler {"action" "list"} {})]
262+
(is (match? {:error false
263+
:contents [{:type :text :text #"\"dev-server\" \(job-\d+\).*npm test"}]}
257264
result)))))))
258265

259266
(deftest bg-job-tool-read-output-test
@@ -276,6 +283,13 @@
276283
{:text "oops" :stream :stderr}] :total-lines 2})
277284
(is (match? {:error false
278285
:contents [{:type :text :text #"hello\n\[stderr\] oops"}]}
286+
(handler {"action" "read_output" "job_id" (:id job)} {})))))
287+
288+
(testing "read_output header includes quoted job name when summary is set"
289+
(let [job (bg/register-shell-job! {:label "test" :summary "my-job" :process (mock-process) :working-directory "/tmp"})]
290+
(reset! (:output* job) {:lines [{:text "hi" :stream :stdout}] :total-lines 1})
291+
(is (match? {:error false
292+
:contents [{:type :text :text #"Job \"my-job\" \(job-\d+\) — running"}]}
279293
(handler {"action" "read_output" "job_id" (:id job)} {}))))))))
280294

281295
(deftest bg-job-tool-kill-test
@@ -303,6 +317,19 @@
303317
(bg/kill-job! (:id job))
304318
(is (match? {:error true
305319
:contents [{:type :text :text #"not running"}]}
320+
(handler {"action" "kill" "job_id" (:id job)} {})))))
321+
322+
(testing "kill running job with summary includes name in output"
323+
(let [job (bg/register-shell-job! {:label "server3" :summary "my-server" :process (mock-process) :working-directory "/tmp"})]
324+
(is (match? {:error false
325+
:contents [{:type :text :text #"Background job \"my-server\" \(job-\d+\) killed\."}]}
326+
(handler {"action" "kill" "job_id" (:id job)} {})))))
327+
328+
(testing "kill already-stopped job with summary"
329+
(let [job (bg/register-shell-job! {:label "server4" :summary "another-server" :process (mock-process) :working-directory "/tmp"})]
330+
(bg/kill-job! (:id job))
331+
(is (match? {:error true
332+
:contents [{:type :text :text #"Background job \"another-server\" \(job-\d+\) is not running"}]}
306333
(handler {"action" "kill" "job_id" (:id job)} {}))))))))
307334

308335
(deftest bg-job-tool-unknown-action-test

0 commit comments

Comments
 (0)