Rebasely Beta: data may be purged

examples/MCP-tools Public

TypeScript · 25 lines · 1.5 KiB · at dae155a

// A token bucket: each client starts with `capacity` tool calls, spends one per call and gets// them back at `refillPerSecond`. Pure, so the tests run it without a Durable Object.export type Limit = { capacity: number; refillPerSecond: number };export type Bucket = { tokens: number; updated: number }; // updated: ms since the epochexport type Decision = { ok: true; remaining: number } | { ok: false; retryAfterSeconds: number };// 30 calls in a burst, back to full after a minute of quiet. Plenty for an agent working// through a task; a loop calling the same tool forever runs dry quickly.export const LIMIT: Limit = { capacity: 30, refillPerSecond: 0.5 };export function take(prev: Bucket | undefined, now: number, limit: Limit = LIMIT): { bucket: Bucket; decision: Decision } {  const elapsed = prev ? Math.max(0, now - prev.updated) / 1000 : 0;  const tokens = prev ? Math.min(limit.capacity, prev.tokens + elapsed * limit.refillPerSecond) : limit.capacity;  if (tokens >= 1) {    return { bucket: { tokens: tokens - 1, updated: now }, decision: { ok: true, remaining: Math.floor(tokens - 1) } };  }  const retryAfterSeconds = Math.ceil((1 - tokens) / limit.refillPerSecond);  return { bucket: { tokens, updated: now }, decision: { ok: false, retryAfterSeconds } };}// How long until an untouched bucket is full again, at which point it is the same as no bucket.export function msUntilFull(bucket: Bucket, limit: Limit = LIMIT): number {  return Math.ceil(((limit.capacity - bucket.tokens) / limit.refillPerSecond) * 1000);}