@nbardy/oompa 0.7.2 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/agentnet/src/agentnet/agent.clj +9 -8
- package/agentnet/src/agentnet/cli.clj +268 -77
- package/agentnet/src/agentnet/cli.clj.bak +1384 -0
- package/agentnet/src/agentnet/core.clj +17 -2
- package/agentnet/src/agentnet/harness.clj +69 -36
- package/agentnet/src/agentnet/runs.clj +5 -3
- package/agentnet/src/agentnet/tasks.clj +6 -0
- package/agentnet/src/agentnet/worker.clj +676 -226
- package/bin/oompa.js +5 -1
- package/config/prompts/_task_header.md +2 -2
- package/oompa.example.json +4 -4
- package/package.json +5 -3
- package/scripts/README.md +6 -0
- package/scripts/__pycache__/stream_bridge.cpython-314.pyc +0 -0
- package/scripts/copy-repo-code.sh +110 -0
- package/scripts/install-babashka.js +97 -0
- package/scripts/test-harness-resume.sh +229 -0
|
@@ -8,6 +8,21 @@
|
|
|
8
8
|
(defn now-ms []
|
|
9
9
|
(System/currentTimeMillis))
|
|
10
10
|
|
|
11
|
+
(defn- normalize-priority
|
|
12
|
+
"Coerce :priority to a sortable number.
|
|
13
|
+
Accepts: integer, \"P1\"/\"P2\" strings, numeric strings, nil.
|
|
14
|
+
Unknown/nil → 1000 (low priority)."
|
|
15
|
+
[p]
|
|
16
|
+
(cond
|
|
17
|
+
(number? p) p
|
|
18
|
+
(nil? p) 1000
|
|
19
|
+
(string? p)
|
|
20
|
+
(let [s (str/upper-case (str/trim p))]
|
|
21
|
+
(cond
|
|
22
|
+
(str/starts-with? s "P") (try (Integer/parseInt (subs s 1)) (catch Exception _ 1000))
|
|
23
|
+
:else (try (Integer/parseInt s) (catch Exception _ 1000))))
|
|
24
|
+
:else 1000))
|
|
25
|
+
|
|
11
26
|
(defn format-ago
|
|
12
27
|
"Return human-readable relative time string for epoch milliseconds."
|
|
13
28
|
[^long ts-ms]
|
|
@@ -50,7 +65,7 @@
|
|
|
50
65
|
|
|
51
66
|
(defn- queue-lines [tasks]
|
|
52
67
|
(->> tasks
|
|
53
|
-
(sort-by (juxt (comp
|
|
68
|
+
(sort-by (juxt (comp normalize-priority :priority) :id))
|
|
54
69
|
(map (fn [{:keys [id summary]}]
|
|
55
70
|
(format "`%s` • %s" id summary)))))
|
|
56
71
|
|
|
@@ -82,7 +97,7 @@
|
|
|
82
97
|
|
|
83
98
|
(defn- backlog-entries [tasks]
|
|
84
99
|
(->> tasks
|
|
85
|
-
(sort-by (juxt (comp
|
|
100
|
+
(sort-by (juxt (comp normalize-priority :priority) :id))
|
|
86
101
|
(map #(select-keys % [:id :summary]))
|
|
87
102
|
(remove #(nil? (:id %)))
|
|
88
103
|
(take 7)
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
;; NDJSON Output Parsing (harness-specific, lives here not in agent-cli)
|
|
38
38
|
;; =============================================================================
|
|
39
39
|
|
|
40
|
-
(defn- parse-
|
|
41
|
-
"Parse
|
|
42
|
-
Returns {:session-id string|nil, :text string|nil}."
|
|
40
|
+
(defn- parse-unified-jsonl-output
|
|
41
|
+
"Parse unified JSONL emitted by `agent-cli run`.
|
|
42
|
+
Returns {:session-id string|nil, :text string|nil, :warning string|nil}."
|
|
43
43
|
[s]
|
|
44
44
|
(let [raw (or s "")
|
|
45
45
|
events (->> (str/split-lines raw)
|
|
@@ -49,27 +49,47 @@
|
|
|
49
49
|
(catch Exception _
|
|
50
50
|
nil))))
|
|
51
51
|
doall)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
events)
|
|
58
|
-
(some-> (re-find #"(ses_[A-Za-z0-9]+)" raw) second))
|
|
52
|
+
event-types (->> events (keep :type) distinct (take 8) vec)
|
|
53
|
+
session-id (some->> events
|
|
54
|
+
(keep #(when (= "session.started" (:type %))
|
|
55
|
+
(:sessionId %)))
|
|
56
|
+
last)
|
|
59
57
|
text (->> events
|
|
60
|
-
(keep (
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
(keep #(when (= "text.delta" (:type %)) (:text %)))
|
|
59
|
+
(remove str/blank?)
|
|
60
|
+
(str/join ""))
|
|
61
|
+
stderr-text (->> events
|
|
62
|
+
(keep #(when (= "stderr" (:type %)) (:text %)))
|
|
63
|
+
(remove str/blank?)
|
|
64
|
+
(str/join ""))
|
|
65
|
+
errors (->> events
|
|
66
|
+
(keep #(when (= "error" (:type %)) (:message %)))
|
|
67
|
+
(remove str/blank?)
|
|
68
|
+
vec)
|
|
69
|
+
warning (cond
|
|
70
|
+
(and (not (str/blank? raw)) (empty? events))
|
|
71
|
+
"agent-cli returned non-empty output, but no unified JSONL events were parsed."
|
|
72
|
+
|
|
73
|
+
(seq errors)
|
|
74
|
+
(str "agent-cli reported error events: " (str/join " | " (take 3 errors)))
|
|
75
|
+
|
|
76
|
+
(and (seq events) (str/blank? text))
|
|
77
|
+
(str "agent-cli returned unified events, but no text deltas were extracted"
|
|
78
|
+
" (types=" (if (seq event-types)
|
|
79
|
+
(str/join "," event-types)
|
|
80
|
+
"unknown")
|
|
81
|
+
").")
|
|
82
|
+
|
|
83
|
+
:else nil)]
|
|
71
84
|
{:session-id session-id
|
|
72
|
-
:text (
|
|
85
|
+
:text (cond
|
|
86
|
+
(not (str/blank? text)) text
|
|
87
|
+
(seq errors) (str/join "\n" errors)
|
|
88
|
+
(not (str/blank? stderr-text)) stderr-text
|
|
89
|
+
:else nil)
|
|
90
|
+
:warning warning
|
|
91
|
+
:raw-snippet (when-not (str/blank? raw)
|
|
92
|
+
(subs raw 0 (min 400 (count raw))))}))
|
|
73
93
|
|
|
74
94
|
;; =============================================================================
|
|
75
95
|
;; Env Helpers
|
|
@@ -154,11 +174,7 @@
|
|
|
154
174
|
|
|
155
175
|
(defn build-cmd
|
|
156
176
|
"Build CLI command vector via agent-cli JSON input.
|
|
157
|
-
|
|
158
|
-
and resolves the binary to an absolute path.
|
|
159
|
-
|
|
160
|
-
agent-cli owns all CLI flag syntax (session create/resume, model decomposition,
|
|
161
|
-
bypass flags, prompt delivery). This function just maps oompa opts to JSON."
|
|
177
|
+
Used for probe/debug flows. Execution should prefer `run-command!`."
|
|
162
178
|
[harness-kw opts]
|
|
163
179
|
(let [input (-> {:harness (name harness-kw)
|
|
164
180
|
:bypassPermissions true}
|
|
@@ -188,6 +204,26 @@
|
|
|
188
204
|
:prompt prompt
|
|
189
205
|
:close "")))
|
|
190
206
|
|
|
207
|
+
(defn run-command!
|
|
208
|
+
"Execute a harness through `agent-cli run`, which emits unified JSONL events."
|
|
209
|
+
[harness-kw opts]
|
|
210
|
+
(let [input (-> {:harness (name harness-kw)
|
|
211
|
+
:mode "conversation"
|
|
212
|
+
:prompt (:prompt opts)
|
|
213
|
+
:cwd (:cwd opts)
|
|
214
|
+
:yolo true}
|
|
215
|
+
(cond->
|
|
216
|
+
(:model opts) (assoc :model (:model opts))
|
|
217
|
+
(and (:session-id opts) (not (:resume? opts))) (assoc :sessionId (:session-id opts))
|
|
218
|
+
(and (:session-id opts) (:resume? opts)) (assoc :resumeSessionId (:session-id opts))
|
|
219
|
+
(:reasoning opts) (assoc :reasoningEffort (:reasoning opts))
|
|
220
|
+
(or (= harness-kw :gemini) (gemini-alias? harness-kw))
|
|
221
|
+
(assoc :debugRawEvents true))
|
|
222
|
+
(add-extra-args harness-kw opts)
|
|
223
|
+
json/generate-string)]
|
|
224
|
+
(process/sh ["agent-cli" "run" "--input" "-"]
|
|
225
|
+
{:in input :out :string :err :string})))
|
|
226
|
+
|
|
191
227
|
;; =============================================================================
|
|
192
228
|
;; Session Management
|
|
193
229
|
;; =============================================================================
|
|
@@ -207,17 +243,14 @@
|
|
|
207
243
|
;; =============================================================================
|
|
208
244
|
|
|
209
245
|
(defn parse-output
|
|
210
|
-
"Parse
|
|
211
|
-
For :plain, returns output as-is.
|
|
246
|
+
"Parse unified JSONL output from `agent-cli run`.
|
|
212
247
|
Returns {:output string, :session-id string}."
|
|
213
248
|
[harness-kw raw-output session-id]
|
|
214
|
-
(let [
|
|
215
|
-
(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
{:output raw-output
|
|
220
|
-
:session-id session-id})))
|
|
249
|
+
(let [parsed (parse-unified-jsonl-output raw-output)]
|
|
250
|
+
{:output (or (:text parsed) raw-output)
|
|
251
|
+
:session-id (or (:session-id parsed) session-id)
|
|
252
|
+
:warning (:warning parsed)
|
|
253
|
+
:raw-snippet (:raw-snippet parsed)}))
|
|
221
254
|
|
|
222
255
|
;; =============================================================================
|
|
223
256
|
;; Probe / Health Check — delegates to agent-cli check
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"Write a review log for one cycle of a worker.
|
|
106
106
|
Contains: verdict, round number, full reviewer output, diff file list."
|
|
107
107
|
[swarm-id worker-id cycle round
|
|
108
|
-
{:keys [verdict output diff-files]}]
|
|
108
|
+
{:keys [verdict output diff-files duration-ms]}]
|
|
109
109
|
(ensure-run-dirs! swarm-id)
|
|
110
110
|
(let [filename (format "%s-c%d-r%d.json" worker-id cycle round)]
|
|
111
111
|
(write-json! (str (reviews-dir swarm-id) "/" filename)
|
|
@@ -115,6 +115,7 @@
|
|
|
115
115
|
:verdict (name verdict)
|
|
116
116
|
:timestamp (str (java.time.Instant/now))
|
|
117
117
|
:output output
|
|
118
|
+
:duration-ms (or duration-ms 0)
|
|
118
119
|
:diff-files (vec diff-files)})))
|
|
119
120
|
|
|
120
121
|
;; =============================================================================
|
|
@@ -128,7 +129,7 @@
|
|
|
128
129
|
Written at cycle end so dashboards can track progress in real-time."
|
|
129
130
|
[swarm-id worker-id cycle
|
|
130
131
|
{:keys [run outcome duration-ms claimed-task-ids recycled-tasks
|
|
131
|
-
error-snippet review-rounds session-id]}]
|
|
132
|
+
error-snippet review-rounds session-id timing-ms]}]
|
|
132
133
|
(when swarm-id
|
|
133
134
|
(let [filename (format "%s-c%d.json" worker-id cycle)]
|
|
134
135
|
(write-json! (str (cycles-dir swarm-id) "/" filename)
|
|
@@ -142,7 +143,8 @@
|
|
|
142
143
|
:recycled-tasks (or recycled-tasks [])
|
|
143
144
|
:error-snippet error-snippet
|
|
144
145
|
:review-rounds (or review-rounds 0)
|
|
145
|
-
:session-id session-id
|
|
146
|
+
:session-id session-id
|
|
147
|
+
:timing-ms timing-ms}))))
|
|
146
148
|
|
|
147
149
|
;; =============================================================================
|
|
148
150
|
;; Read helpers (for cmd-status, dashboards)
|
|
@@ -210,6 +210,12 @@
|
|
|
210
210
|
(unclaim-task! task))
|
|
211
211
|
(mapv :id to-recycle)))
|
|
212
212
|
|
|
213
|
+
(defn recycle-all-current!
|
|
214
|
+
"Move every task from current/ back to pending/.
|
|
215
|
+
Returns vector of recycled task IDs."
|
|
216
|
+
[]
|
|
217
|
+
(recycle-tasks! (current-task-ids)))
|
|
218
|
+
|
|
213
219
|
(defn all-complete?
|
|
214
220
|
"True if no pending or current tasks"
|
|
215
221
|
[]
|