clawmoney 0.17.18 → 0.17.20

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.
@@ -140,8 +140,23 @@ function runCli(command, prompt, timeoutMs, orderId) {
140
140
  // back to either drawing the image with Python in /tmp (slow, ugly)
141
141
  // or hallucinating an image_path with no file behind it (worst
142
142
  // case, since the buyer pays for a nonexistent file). Verified on
143
- // codex 0.128.0 + gpt-5.5 xhigh, 2026-05-12.
144
- args = ["exec", "-s", "workspace-write", prompt, "--json", "--skip-git-repo-check"];
143
+ // codex 0.128.0 + gpt-5.5, 2026-05-12.
144
+ //
145
+ // -c model_reasoning_effort=medium overrides whatever the provider
146
+ // has in ~/.codex/config.toml (often "high" or "xhigh" for their
147
+ // own deep-thinking sessions). Hub buyers don't need that level of
148
+ // reasoning — for image gen the only reasoning step worth doing is
149
+ // "pick the right tool", everything after image_gen finishes is
150
+ // pure overhead that adds 60–90s per call. medium keeps quality
151
+ // similar to codex defaults but caps the tail latency.
152
+ args = [
153
+ "exec",
154
+ "-s", "workspace-write",
155
+ "-c", "model_reasoning_effort=medium",
156
+ prompt,
157
+ "--json",
158
+ "--skip-git-repo-check",
159
+ ];
145
160
  }
146
161
  else if (command === "gemini") {
147
162
  // gemini -p "..." -o json --yolo
@@ -158,21 +173,100 @@ function runCli(command, prompt, timeoutMs, orderId) {
158
173
  });
159
174
  let stdout = "";
160
175
  let stderr = "";
176
+ let earlyResolved = false;
177
+ const tryEarlyExit = () => {
178
+ if (earlyResolved)
179
+ return;
180
+ // Only attempt early exit for codex — others either don't stream
181
+ // events with this shape, or already finish promptly after their
182
+ // last output. Codex on xhigh/high reasoning_effort wastes 60–90s
183
+ // doing "final reflection" reasoning even after the agent_message
184
+ // is already emitted with the image_path. Once we see that
185
+ // message in the JSONL stream the deliverable is fully on disk
186
+ // and we can ship the order — kill the child to avoid burning
187
+ // buyer wall-time on reasoning we won't read.
188
+ if (command !== "codex")
189
+ return;
190
+ if (!hasCodexDeliverable(stdout))
191
+ return;
192
+ earlyResolved = true;
193
+ // SIGTERM is enough; codex closes its writer and we'll get a
194
+ // 'close' event shortly. Don't await — let the resolve below
195
+ // return the snapshot we already have.
196
+ try {
197
+ child.kill("SIGTERM");
198
+ }
199
+ catch {
200
+ // pid may already be gone
201
+ }
202
+ resolve({ stdout, stderr, exitCode: 0 });
203
+ };
161
204
  child.stdout.on("data", (chunk) => {
162
205
  stdout += chunk.toString();
206
+ tryEarlyExit();
163
207
  });
164
208
  child.stderr.on("data", (chunk) => {
165
209
  stderr += chunk.toString();
166
210
  });
167
211
  child.on("close", (code) => {
212
+ if (earlyResolved)
213
+ return;
168
214
  resolve({ stdout, stderr, exitCode: code });
169
215
  });
170
216
  child.on("error", (err) => {
217
+ if (earlyResolved)
218
+ return;
171
219
  stderr += err.message;
172
220
  resolve({ stdout, stderr, exitCode: null });
173
221
  });
174
222
  });
175
223
  }
224
+ /**
225
+ * Detect whether codex's JSONL stream already contains a final
226
+ * agent_message event whose text parses to JSON with an `image_path`.
227
+ * That's the signal that the image is on disk and the agent has
228
+ * acknowledged it — everything codex does after this point is its
229
+ * own final reasoning loop, which the buyer never sees.
230
+ *
231
+ * Scans newest-to-oldest so we exit as soon as we find the marker.
232
+ */
233
+ function hasCodexDeliverable(streamSoFar) {
234
+ const lines = streamSoFar.split("\n");
235
+ for (let i = lines.length - 1; i >= 0; i--) {
236
+ const line = lines[i].trim();
237
+ if (!line.startsWith("{"))
238
+ continue;
239
+ let event;
240
+ try {
241
+ event = JSON.parse(line);
242
+ }
243
+ catch {
244
+ continue;
245
+ }
246
+ if (event.type !== "item.completed")
247
+ continue;
248
+ const item = event.item;
249
+ if (item?.type !== "agent_message")
250
+ continue;
251
+ const text = item.text;
252
+ if (typeof text !== "string")
253
+ continue;
254
+ // Cheap pre-check before JSON.parse: must mention image_path.
255
+ if (!text.includes("image_path"))
256
+ continue;
257
+ try {
258
+ const parsed = JSON.parse(text);
259
+ const path = parsed.image_path;
260
+ if (typeof path === "string" && path.length > 0)
261
+ return true;
262
+ }
263
+ catch {
264
+ // text wasn't JSON; agent might be talking about image_path
265
+ // in prose. Keep looking — don't early-exit on prose.
266
+ }
267
+ }
268
+ return false;
269
+ }
176
270
  // ── JSON parser ──
177
271
  function parseJsonOutput(raw) {
178
272
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmoney",
3
- "version": "0.17.18",
3
+ "version": "0.17.20",
4
4
  "description": "ClawMoney CLI -- Earn rewards with your AI agent",
5
5
  "type": "module",
6
6
  "bin": {