summaryrefslogtreecommitdiffhomepage
path: root/packages/transport-http
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-28 12:43:29 +0900
committerAdam Malczewski <[email protected]>2026-06-28 12:43:29 +0900
commit2d276669a0cb41959fc67d17bc58e77853dc3eb5 (patch)
treeb70893b7450522fe9d5b7e627423498ae972e191 /packages/transport-http
parentf9d1ca533ad2c5d71a3bc349934d54c09de305bf (diff)
downloaddispatch-2d276669a0cb41959fc67d17bc58e77853dc3eb5.tar.gz
dispatch-2d276669a0cb41959fc67d17bc58e77853dc3eb5.zip
feat(concurrency-fixes): usage-gate + adaptive headroom + configurable cooldown
Diffstat (limited to 'packages/transport-http')
-rw-r--r--packages/transport-http/src/app.ts49
1 files changed, 49 insertions, 0 deletions
diff --git a/packages/transport-http/src/app.ts b/packages/transport-http/src/app.ts
index 0fcc8f0..ee7b2de 100644
--- a/packages/transport-http/src/app.ts
+++ b/packages/transport-http/src/app.ts
@@ -8,6 +8,7 @@ import type {
ComputerListResponse,
ComputerResponse,
ComputerStatusResponse,
+ ConcurrencyCooldownResponse,
ConcurrencyLimitResponse,
ConcurrencyLimitsResponse,
ConcurrencyStatusResponse,
@@ -31,6 +32,7 @@ import type {
QueueResponse,
ReasoningEffortResponse,
SetCompactPercentRequest,
+ SetConcurrencyCooldownRequest,
SetConcurrencyLimitRequest,
SetConversationComputerRequest,
SetSystemPromptTemplateRequest,
@@ -687,6 +689,53 @@ export function createApp(opts: CreateServerOptions): Hono {
return c.json({ ok: true, providerId }, 200);
});
+ app.get("/concurrency/cooldown/:providerId", (c) => {
+ const providerId = c.req.param("providerId");
+ if (opts.concurrencyService === undefined) {
+ return c.json({ error: "Concurrency service not available" }, 503);
+ }
+ // A cooldown may be the default (when a limit is configured but no explicit
+ // cooldown was set) or explicitly set. getCooldown returns undefined only
+ // when the provider has NO state at all (no limit, no cooldown) — treat that
+ // as "not configured".
+ const cooldownMs = opts.concurrencyService.getCooldown(providerId);
+ if (cooldownMs === undefined) {
+ return c.json({ error: "No concurrency configuration for this provider" }, 404);
+ }
+ const body: ConcurrencyCooldownResponse = { providerId, cooldownMs };
+ return c.json(body, 200);
+ });
+
+ app.put("/concurrency/cooldown/:providerId", async (c) => {
+ const providerId = c.req.param("providerId");
+ if (opts.concurrencyService === undefined) {
+ return c.json({ error: "Concurrency service not available" }, 503);
+ }
+
+ let body: unknown;
+ try {
+ body = await c.req.json();
+ } catch {
+ log.warn("concurrency: invalid JSON body");
+ return c.json({ error: "Invalid JSON body" }, 400);
+ }
+
+ const parsed = body as SetConcurrencyCooldownRequest;
+ if (
+ parsed === null ||
+ typeof parsed !== "object" ||
+ typeof parsed.cooldownMs !== "number" ||
+ !Number.isInteger(parsed.cooldownMs) ||
+ parsed.cooldownMs < 0
+ ) {
+ return c.json({ error: "Body must be { cooldownMs: <non-negative integer> }" }, 400);
+ }
+
+ opts.concurrencyService.setCooldown(providerId, parsed.cooldownMs);
+ const responseBody: ConcurrencyCooldownResponse = { providerId, cooldownMs: parsed.cooldownMs };
+ return c.json(responseBody, 200);
+ });
+
app.get("/concurrency/status", (c) => {
if (opts.concurrencyService === undefined) {
const body: ConcurrencyStatusResponse = { providers: [] };