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.
- package/dist/hub/executor.js +96 -2
- package/package.json +1 -1
package/dist/hub/executor.js
CHANGED
|
@@ -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
|
|
144
|
-
|
|
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 {
|