@nbardy/oompa 0.7.1 → 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 CHANGED
@@ -83,9 +83,9 @@ This repo has a fleshed out version of the idea. The oompa loompas are organized
83
83
  ```json
84
84
  {
85
85
  "workers": [
86
- {"model": "claude:opus", "prompt": ["config/prompts/planner.md"], "iterations": 5, "count": 1},
87
- {"model": "codex:gpt-5.3-codex:medium", "prompt": ["config/prompts/executor.md"], "iterations": 10, "count": 2, "can_plan": false},
88
- {"model": "opencode:opencode/kimi-k2.5-free", "prompt": ["config/prompts/executor.md"], "iterations": 10, "count": 1, "can_plan": false}
86
+ {"model": "claude:opus", "prompt": ["config/prompts/planner.md"], "max_cycle": 5, "count": 1},
87
+ {"model": "codex:gpt-5.3-codex:medium", "prompt": ["config/prompts/executor.md"], "max_cycle": 10, "count": 2, "can_plan": false},
88
+ {"model": "opencode:opencode/kimi-k2.5-free", "prompt": ["config/prompts/executor.md"], "max_cycle": 10, "count": 1, "can_plan": false}
89
89
  ]
90
90
  }
91
91
  ```
@@ -101,9 +101,12 @@ This spawns:
101
101
  |-------|----------|-------------|
102
102
  | `model` | yes | `harness:model` or `harness:model:reasoning` (e.g. `codex:gpt-5.3-codex:medium`, `claude:opus`, `opencode:opencode/kimi-k2.5-free`) |
103
103
  | `prompt` | no | String or array of paths — concatenated into one prompt |
104
- | `iterations` | no | Max iterations per worker (default: 10) |
104
+ | `max_cycle` | no | Max worker cycles for JSON config runs (default: 10) |
105
105
  | `count` | no | Number of workers with this config (default: 1) |
106
106
  | `can_plan` | no | If `false`, worker waits for tasks before starting (default: `true`) |
107
+ | `max_wait_for_tasks` | no | Max seconds a `can_plan: false` worker waits for queue work (default: `600`) |
108
+
109
+ `oompa loop` still uses the CLI flag `--iterations`. JSON worker configs use `max_cycle`.
107
110
 
108
111
  #### Composable prompts
109
112
 
@@ -191,7 +194,10 @@ cd oompa
191
194
  echo "Build a simple todo API with CRUD endpoints" > spec.md
192
195
 
193
196
  # Run the swarm
194
- ./swarm.bb swarm
197
+ ./swarm.bb run
198
+
199
+ # Run detached with startup validation (fails fast if startup fails)
200
+ ./swarm.bb run --detach --config oompa.json
195
201
  ```
196
202
 
197
203
  ## Install (npm)
@@ -212,7 +218,12 @@ oompa swarm
212
218
  ## Commands
213
219
 
214
220
  ```bash
215
- oompa swarm [file] # Run from oompa.json (default)
221
+ oompa run [file] # Run from config (defaults: oompa.json, oompa/oompa.json)
222
+ oompa run --detach --config oompa.json
223
+ oompa swarm [file] # Direct swarm command (foreground)
224
+ oompa list # List 20 most recent swarms
225
+ oompa list --all # Full swarm history
226
+ oompa view [swarm-id] # Per-worker runtime status (default: latest swarm)
216
227
  oompa tasks # Show task status
217
228
  oompa check # Check available backends
218
229
  oompa cleanup # Remove worktrees
@@ -88,16 +88,39 @@
88
88
  attach (into ["--attach" attach])
89
89
  true (conj prompt))))
90
90
 
91
- (defmethod build-command :gemini
92
- [_ {:keys [model]} prompt cwd]
93
- (cond-> ["gemini" "--yolo"]
91
+ (defn- gemini-cmd
92
+ [agent-type model prompt]
93
+ (cond-> [(name agent-type) "--yolo"]
94
94
  model (into ["-m" model])
95
95
  true (into ["-p" prompt])))
96
96
 
97
+ (defn- gemini-alias?
98
+ [agent-type]
99
+ (and (keyword? agent-type)
100
+ (re-matches #"^gemini\\d+$" (name agent-type))))
101
+
102
+ (defmethod build-command :gemini
103
+ [_ {:keys [model]} prompt cwd]
104
+ (gemini-cmd :gemini model prompt))
105
+
106
+ (defmethod build-command :gemini1
107
+ [agent-type {:keys [model]} prompt cwd]
108
+ (gemini-cmd agent-type model prompt))
109
+
110
+ (defmethod build-command :gemini2
111
+ [agent-type {:keys [model]} prompt cwd]
112
+ (gemini-cmd agent-type model prompt))
113
+
114
+ (defmethod build-command :gemini3
115
+ [agent-type {:keys [model]} prompt cwd]
116
+ (gemini-cmd agent-type model prompt))
117
+
97
118
  (defmethod build-command :default
98
- [agent-type _ _ _]
99
- (throw (ex-info (str "Unknown agent type: " agent-type)
100
- {:agent-type agent-type})))
119
+ [agent-type {:keys [model]} prompt _]
120
+ (if (gemini-alias? agent-type)
121
+ (gemini-cmd agent-type model prompt)
122
+ (throw (ex-info (str "Unknown agent type: " agent-type)
123
+ {:agent-type agent-type}))))
101
124
 
102
125
  ;; =============================================================================
103
126
  ;; Process Execution
@@ -153,16 +176,12 @@
153
176
  #"(?m)^\s*#oompa_directive:include_file\s+\"([^\"]+)\"\s*$")
154
177
 
155
178
  (defn- read-file-cached
156
- "Read a prompt file once and cache by canonical path."
179
+ "Reads prompts fresh on each run so roles can be edited live. It is a fast op."
157
180
  [path]
158
181
  (when path
159
- (if-let [cached (get @prompt-file-cache path)]
160
- cached
161
- (let [f (io/file path)]
162
- (when (.exists f)
163
- (let [content (slurp f)]
164
- (swap! prompt-file-cache assoc path content)
165
- content))))))
182
+ (let [f (io/file path)]
183
+ (when (.exists f)
184
+ (slurp f)))))
166
185
 
167
186
  (defn- resolve-include-path
168
187
  "Resolve an include path relative to the file that declares it."
@@ -253,6 +272,11 @@
253
272
  [output]
254
273
  (boolean (re-find #"COMPLETE_AND_READY_FOR_MERGE" (or output ""))))
255
274
 
275
+ (defn needs-followup-signal?
276
+ "Check if output contains NEEDS_FOLLOWUP signal"
277
+ [output]
278
+ (boolean (re-find #"NEEDS_FOLLOWUP" (or output ""))))
279
+
256
280
  (defn parse-claim-signal
257
281
  "Extract task IDs from CLAIM(...) signal in output.
258
282
  Returns vector of task ID strings, or nil if no CLAIM signal found.
@@ -396,12 +420,13 @@
396
420
  (defn check-available
397
421
  "Check if agent backend is available"
398
422
  [agent-type]
399
- (let [cmd (case agent-type
400
- :codex ["codex" "--version"]
401
- :claude ["claude" "--version"]
402
- :opencode ["opencode" "--version"]
403
- :gemini ["gemini" "--version"]
404
- ["echo" "unknown"])]
423
+ (let [cmd (cond
424
+ (= :codex agent-type) ["codex" "--version"]
425
+ (= :claude agent-type) ["claude" "--version"]
426
+ (= :opencode agent-type) ["opencode" "--version"]
427
+ (= :gemini agent-type) ["gemini" "--version"]
428
+ (gemini-alias? agent-type) [(name agent-type) "--version"]
429
+ :else ["echo" "unknown"])]
405
430
  (try
406
431
  (let [{:keys [exit]} (process/sh cmd {:out :string :err :string})]
407
432
  (zero? exit))