Context
The playground runs N engines by firing N independent POST /api/run calls (store/useEngineOutputs.ts -> Promise.all over runEngine). With all four engines selected that is four round trips through the proxy, four separate rate-limit charges against the heavy bucket, and four chances to partially fail with no shared deadline.
Proposal
POST /api/run/batch taking { sourceText, runs: [{ engine, flags?, timeoutMs? }] } and returning a result per entry, each carrying its own ok/meta.
- Fan out inside the gateway, reusing the per-key cache and the existing
inFlight coalescing.
- One rate-limit charge proportional to the number of engine spawns actually performed (cache hits should not be charged as spawns).
- The frontend switches to one call; the single-engine route stays for API users and embeds.
Acceptance criteria
- A four-engine run costs one HTTP request from the browser.
- Cached engines in a batch do not count against the heavy bucket.
- A single failing engine does not fail the batch.
Context
The playground runs N engines by firing N independent
POST /api/runcalls (store/useEngineOutputs.ts->Promise.alloverrunEngine). With all four engines selected that is four round trips through the proxy, four separate rate-limit charges against theheavybucket, and four chances to partially fail with no shared deadline.Proposal
POST /api/run/batchtaking{ sourceText, runs: [{ engine, flags?, timeoutMs? }] }and returning a result per entry, each carrying its ownok/meta.inFlightcoalescing.Acceptance criteria