athena-agent-launcher 0.3.3 → 0.3.4
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/lib/hosted-gateway.mjs +27 -6
- package/package.json +1 -1
package/lib/hosted-gateway.mjs
CHANGED
|
@@ -37,11 +37,12 @@ const TURN_TIMEOUT_MS = 120_000; // hard cap on a single turn
|
|
|
37
37
|
const SKEW_MS = 60_000; // M2: max clock skew for the HMAC timestamp
|
|
38
38
|
const REPLAY_TTL_MS = 120_000; // M2: nonce cache window (> skew)
|
|
39
39
|
const DEFAULT_RATE_PER_MIN = 30; // M6: token-bucket refill
|
|
40
|
-
const DEFAULT_MAX_CONCURRENCY = 1; // M6: in-flight cap (pilot = 1)
|
|
40
|
+
const DEFAULT_MAX_CONCURRENCY = 1; // M6: in-flight cap (pilot = 1) — load-bearing for arm custody, do NOT raise
|
|
41
|
+
const BUSY_RETRY_AFTER_MS = 2000; // DAE-16: hint the poller waits before retrying a busy container
|
|
41
42
|
|
|
42
|
-
function sendJson(res, status, obj) {
|
|
43
|
+
function sendJson(res, status, obj, headers) {
|
|
43
44
|
const body = JSON.stringify(obj);
|
|
44
|
-
res.writeHead(status, { "content-type": "application/json; charset=utf-8" });
|
|
45
|
+
res.writeHead(status, { "content-type": "application/json; charset=utf-8", ...(headers || {}) });
|
|
45
46
|
res.end(body);
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -292,12 +293,32 @@ export async function startHostedGateway({ hermesBin, env, hermesHome, hostedGat
|
|
|
292
293
|
// M6 — rate limit, then hard concurrency cap. Fail closed (429), never open.
|
|
293
294
|
if (!takeToken()) {
|
|
294
295
|
logEvent({ event: "rate_limited", request_id: requestId, status: 429 });
|
|
295
|
-
sendJson(
|
|
296
|
+
sendJson(
|
|
297
|
+
res,
|
|
298
|
+
429,
|
|
299
|
+
{ status: "rate_limited", reason: "rate_limited", message: "Too many requests — try again shortly.", retry_after_ms: BUSY_RETRY_AFTER_MS },
|
|
300
|
+
{ "retry-after": String(Math.ceil(BUSY_RETRY_AFTER_MS / 1000)) },
|
|
301
|
+
);
|
|
296
302
|
return;
|
|
297
303
|
}
|
|
298
304
|
if (inFlight >= maxConcurrency) {
|
|
299
|
-
|
|
300
|
-
|
|
305
|
+
// DAE-16 (D3 container half): a turn is already in flight. max_concurrency
|
|
306
|
+
// stays 1 (load-bearing for arm custody — never raised), so instead of
|
|
307
|
+
// blocking or a bare 429 we return an IMMEDIATE, TYPED busy signal the
|
|
308
|
+
// poller (IRIS-24) relays. Contract: HTTP 429 + Retry-After, body
|
|
309
|
+
// { status:"busy", reason:"turn_in_flight", message, retry_after_ms }.
|
|
310
|
+
logEvent({ event: "busy", request_id: requestId, status: 429, reason: "turn_in_flight", in_flight: inFlight });
|
|
311
|
+
sendJson(
|
|
312
|
+
res,
|
|
313
|
+
429,
|
|
314
|
+
{
|
|
315
|
+
status: "busy",
|
|
316
|
+
reason: "turn_in_flight",
|
|
317
|
+
message: "The agent is still processing a previous message — try again shortly.",
|
|
318
|
+
retry_after_ms: BUSY_RETRY_AFTER_MS,
|
|
319
|
+
},
|
|
320
|
+
{ "retry-after": String(Math.ceil(BUSY_RETRY_AFTER_MS / 1000)) },
|
|
321
|
+
);
|
|
301
322
|
return;
|
|
302
323
|
}
|
|
303
324
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "athena-agent-launcher",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "Run an Athena-configured agent locally. Resolves runtime + bindings from the Athena control plane and spawns the correct agent binary (Anthropic SDK, OpenClaw, or Hermes).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|