agent-relay-server 0.98.0 → 0.98.1

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/docs/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Agent Relay API",
5
- "version": "0.98.0",
5
+ "version": "0.98.1",
6
6
  "description": "Real-time message bus for inter-agent communication. Agent-first: this spec is designed for machine consumption — agents can self-discover the full API surface via GET /api/spec.",
7
7
  "license": {
8
8
  "name": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-relay-server",
3
- "version": "0.98.0",
3
+ "version": "0.98.1",
4
4
  "description": "Lightweight HTTP message relay for inter-agent communication across machines",
5
5
  "module": "src/index.ts",
6
6
  "type": "module",
@@ -34,7 +34,7 @@
34
34
  "CONTRIBUTING.md"
35
35
  ],
36
36
  "dependencies": {
37
- "agent-relay-sdk": "0.2.78",
37
+ "agent-relay-sdk": "0.2.79",
38
38
  "ajv": "^8.20.0"
39
39
  },
40
40
  "scripts": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-relay-runner",
3
3
  "description": "Thin Agent Relay runner bridge for Claude Code",
4
- "version": "0.98.0",
4
+ "version": "0.98.1",
5
5
  "agentRelayContracts": {
6
6
  "providerPluginProtocol": 1
7
7
  }
@@ -10,6 +10,7 @@ const PROVIDER_QUOTA_STALE_AFTER_MS = 10 * 60_000;
10
10
  const QUOTA_UTILIZATION_EPSILON = 1e-9;
11
11
  const QUOTA_RESET_BOUNDARY_ADVANCE_MS = 5_000;
12
12
  const QUOTA_RESET_UTILIZATION_MAX = 0.01;
13
+ const FIVE_HOUR_MS = 5 * 60 * 60_000;
13
14
 
14
15
  export interface ProviderQuotaAdvisoryInput {
15
16
  provider: string;
@@ -258,11 +259,20 @@ function quotaWindowUtilizationRegressed(existing: QuotaState["windows"][number]
258
259
  && !quotaWindowLooksReset(existing, incoming);
259
260
  }
260
261
 
261
- function publicQuotaState(quota: StoredQuotaState): QuotaState {
262
+ function publicQuotaState(quota: StoredQuotaState, now?: number): QuotaState {
263
+ let emulated = false;
264
+ const windows = quota.windows.map((window) => {
265
+ const period = quotaWindowPeriodMs(window.name);
266
+ if (now === undefined || period === undefined || typeof window.resetsAt !== "number" || !Number.isFinite(window.resetsAt) || now < window.resetsAt) return { ...window };
267
+ let resetsAt = window.resetsAt;
268
+ while (now >= resetsAt) resetsAt += period;
269
+ emulated = true;
270
+ return { ...window, utilization: 0, resetsAt };
271
+ });
262
272
  return {
263
- windows: quota.windows.map((window) => ({ ...window })),
264
- source: quota.source,
265
- updatedAt: quota.updatedAt,
273
+ windows,
274
+ source: emulated ? "emulated" : quota.source,
275
+ updatedAt: emulated && now !== undefined ? Math.max(quota.updatedAt, now) : quota.updatedAt,
266
276
  };
267
277
  }
268
278
 
@@ -287,7 +297,7 @@ function storedQuotaWindowSampleTimes(quota: StoredQuotaState): Map<string, numb
287
297
  }
288
298
 
289
299
  // Source priority for per-window precedence: "ingest" (WHAM/API) beats "probe" (agent self-report).
290
- const QUOTA_SOURCE_PRIORITY: Record<string, number> = { ingest: 3, header: 2, probe: 1, statusline: 0 };
300
+ const QUOTA_SOURCE_PRIORITY: Record<string, number> = { ingest: 3, header: 2, probe: 1, statusline: 0, emulated: -1 };
291
301
  function quotaSourcePriority(source: string): number {
292
302
  return QUOTA_SOURCE_PRIORITY[source] ?? 1;
293
303
  }
@@ -345,6 +355,12 @@ function quotaWindowSampleTimes(provider: string, accountKey: string, fallback?:
345
355
  return times;
346
356
  }
347
357
 
358
+ function quotaWindowPeriodMs(name: string): number | undefined {
359
+ if (name === "five_hour" || name === "primary") return FIVE_HOUR_MS;
360
+ if (name === "seven_day" || name === "seven_day_sonnet" || name === "seven_day_opus" || name === "secondary") return 7 * DAY_MS;
361
+ return undefined;
362
+ }
363
+
348
364
  function mergeQuotaWindows(existing: StoredQuotaState | undefined, incoming: QuotaState, provider: string, accountKey: string): {
349
365
  quota: StoredQuotaState;
350
366
  acceptedIncomingWindow: boolean;
@@ -434,7 +450,7 @@ function rowToSnapshot(row: ProviderQuotaSnapshotRow): ProviderQuotaSnapshot {
434
450
  function rowToRecord(row: ProviderQuotaRow, history: ProviderQuotaSnapshot[], now: number): ProviderQuotaRecord {
435
451
  const lastError = parseJson<ProviderQuotaError | undefined>(row.last_error, undefined);
436
452
  const lastUpdatedAt = row.last_updated_at ?? undefined;
437
- const quota = row.quota_state ? publicQuotaState(parseStoredQuotaState(row.quota_state, { windows: [], source: "probe", updatedAt: lastUpdatedAt ?? row.last_attempt_at })) : undefined;
453
+ const quota = row.quota_state ? publicQuotaState(parseStoredQuotaState(row.quota_state, { windows: [], source: "probe", updatedAt: lastUpdatedAt ?? row.last_attempt_at }), now) : undefined;
438
454
  const burn = quota ? deriveProviderQuotaBurn({
439
455
  provider: row.provider,
440
456
  quota,
package/src/quota.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { isRecord } from "agent-relay-sdk";
2
2
  import type { ProviderQuotaError, QuotaState, QuotaWindowName, QuotaSource, QuotaUnit } from "./types";
3
3
 
4
- const QUOTA_SOURCES = new Set<QuotaSource>(["header", "probe", "ingest", "statusline"]);
4
+ const QUOTA_SOURCES = new Set<QuotaSource>(["header", "probe", "ingest", "statusline", "emulated"]);
5
5
  const QUOTA_UNITS = new Set<QuotaUnit>(["tokens", "requests", "%"]);
6
6
  const QUOTA_WINDOWS = new Set<QuotaWindowName>(["five_hour", "seven_day", "seven_day_sonnet", "seven_day_opus", "primary", "secondary"]);
7
7