Files
unibots/tools/ratelimit.go
T
agent fc644ecd6e feat: import agents_and_robots platform as unibots (Matrix-out, unibus transport)
Reemplaza el scaffold del echobot por la plataforma completa de bots traida
desde ~/DataProyects/Github/agents_and_robots tras la operacion Matrix-out:
los bots ya no hablan por Matrix sino por el bus unibus (modelo todo-rooms +
E2E via shell/transportunibus sobre github.com/enmanuel/unibus/pkg/client).

- go.mod: replace de unibus -> ../unibus y de fn-registry -> ../../../.. (paths
  relativos reajustados a la nueva ubicacion dentro de fn_registry).
- app.md: bump a 0.2.0, descripcion + arquitectura + comandos + gotchas reales.
- modulo Go conservado como github.com/enmanuel/agents (sin reescribir imports).

agents_and_robots queda archivado como museo de la era Matrix.
2026-06-07 11:50:13 +02:00

71 lines
1.6 KiB
Go

package tools
import (
"sync"
"time"
)
// RateLimiter tracks tool call counts per key (typically roomID) using a
// sliding window. It is safe for concurrent use.
type RateLimiter struct {
maxCalls int
window time.Duration
mu sync.Mutex
buckets map[string][]time.Time
}
// NewRateLimiter creates a rate limiter that allows maxCalls per window per key.
func NewRateLimiter(maxCalls int, window time.Duration) *RateLimiter {
return &RateLimiter{
maxCalls: maxCalls,
window: window,
buckets: make(map[string][]time.Time),
}
}
// Allow checks whether a call for the given key is within the rate limit.
// If allowed, it records the call and returns true. Otherwise returns false.
func (rl *RateLimiter) Allow(key string) bool {
rl.mu.Lock()
defer rl.mu.Unlock()
now := time.Now()
cutoff := now.Add(-rl.window)
// Trim expired entries
calls := rl.buckets[key]
start := 0
for start < len(calls) && calls[start].Before(cutoff) {
start++
}
calls = calls[start:]
if len(calls) >= rl.maxCalls {
rl.buckets[key] = calls
return false
}
rl.buckets[key] = append(calls, now)
return true
}
// Cleanup removes stale entries for keys that have no recent calls.
// Should be called periodically to prevent memory growth.
func (rl *RateLimiter) Cleanup() {
rl.mu.Lock()
defer rl.mu.Unlock()
cutoff := time.Now().Add(-rl.window)
for key, calls := range rl.buckets {
start := 0
for start < len(calls) && calls[start].Before(cutoff) {
start++
}
if start >= len(calls) {
delete(rl.buckets, key)
} else {
rl.buckets[key] = calls[start:]
}
}
}