sensorium-mcp 2.16.6 → 2.16.8
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/dist/dashboard.d.ts.map +1 -1
- package/dist/dashboard.js +31 -38
- package/dist/dashboard.js.map +1 -1
- package/dist/http-server.d.ts.map +1 -1
- package/dist/http-server.js +0 -3
- package/dist/http-server.js.map +1 -1
- package/dist/index.js +14 -20
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +9 -0
- package/dist/intent.d.ts.map +1 -0
- package/dist/intent.js +33 -0
- package/dist/intent.js.map +1 -0
- package/dist/tool-definitions.d.ts.map +1 -1
- package/dist/tool-definitions.js +0 -17
- package/dist/tool-definitions.js.map +1 -1
- package/dist/tools/utility-tools.d.ts.map +1 -1
- package/dist/tools/utility-tools.js +0 -32
- package/dist/tools/utility-tools.js.map +1 -1
- package/dist/tools/wait-tool.d.ts.map +1 -1
- package/dist/tools/wait-tool.js +13 -6
- package/dist/tools/wait-tool.js.map +1 -1
- package/package.json +1 -1
- package/dist/rate-limiter.d.ts +0 -95
- package/dist/rate-limiter.d.ts.map +0 -1
- package/dist/rate-limiter.js +0 -311
- package/dist/rate-limiter.js.map +0 -1
package/dist/rate-limiter.js
DELETED
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Rate Limiter — Coordinates API usage across concurrent agent sessions.
|
|
3
|
-
*
|
|
4
|
-
* Problem: When 4+ agents run simultaneously, each making GitHub/OpenAI/web
|
|
5
|
-
* requests, external APIs start returning 429 (Too Many Requests).
|
|
6
|
-
*
|
|
7
|
-
* Solution: A shared in-process rate limiter that:
|
|
8
|
-
* 1. Tracks API calls per service per sliding window
|
|
9
|
-
* 2. Implements token-bucket rate limiting per service
|
|
10
|
-
* 3. Provides an MCP tool for agents to check/acquire capacity
|
|
11
|
-
* 4. Advises agents to back off when limits approach
|
|
12
|
-
*
|
|
13
|
-
* Architecture:
|
|
14
|
-
* - ServiceBucket: token-bucket per service (GitHub, OpenAI, etc.)
|
|
15
|
-
* - SessionTracker: per-session call counts for fair queuing
|
|
16
|
-
* - acquireCapacity(): agents call this before making API calls
|
|
17
|
-
* - getUsageStats(): dashboard visibility into rate state
|
|
18
|
-
*/
|
|
19
|
-
const DEFAULT_SERVICES = {
|
|
20
|
-
github: {
|
|
21
|
-
maxRequests: 5000,
|
|
22
|
-
windowMs: 60 * 60 * 1000, // 1 hour (GitHub API limit)
|
|
23
|
-
burstSize: 30,
|
|
24
|
-
refillRate: 1.4, // ~5000/hour
|
|
25
|
-
description: "GitHub API",
|
|
26
|
-
},
|
|
27
|
-
openai: {
|
|
28
|
-
maxRequests: 500,
|
|
29
|
-
windowMs: 60 * 1000, // 1 minute
|
|
30
|
-
burstSize: 20,
|
|
31
|
-
refillRate: 8.3, // ~500/min
|
|
32
|
-
description: "OpenAI API",
|
|
33
|
-
},
|
|
34
|
-
web: {
|
|
35
|
-
maxRequests: 60,
|
|
36
|
-
windowMs: 60 * 1000, // 1 minute
|
|
37
|
-
burstSize: 10,
|
|
38
|
-
refillRate: 1, // 60/min
|
|
39
|
-
description: "Web requests",
|
|
40
|
-
},
|
|
41
|
-
telegram: {
|
|
42
|
-
maxRequests: 30,
|
|
43
|
-
windowMs: 1000, // 1 second (Telegram bot limit: 30 msg/s)
|
|
44
|
-
burstSize: 30,
|
|
45
|
-
refillRate: 30,
|
|
46
|
-
description: "Telegram API",
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
function createBucket(config) {
|
|
50
|
-
return {
|
|
51
|
-
tokens: config.burstSize,
|
|
52
|
-
lastRefill: Date.now(),
|
|
53
|
-
config,
|
|
54
|
-
callLog: [],
|
|
55
|
-
hourlyCallCount: 0,
|
|
56
|
-
hourlyWindowStart: Date.now(),
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
function refillBucket(bucket) {
|
|
60
|
-
const now = Date.now();
|
|
61
|
-
const elapsed = (now - bucket.lastRefill) / 1000;
|
|
62
|
-
bucket.tokens = Math.min(bucket.config.burstSize, bucket.tokens + elapsed * bucket.config.refillRate);
|
|
63
|
-
bucket.lastRefill = now;
|
|
64
|
-
// Reset hourly counter if window expired
|
|
65
|
-
if (now - bucket.hourlyWindowStart >= 60 * 60 * 1000) {
|
|
66
|
-
bucket.hourlyCallCount = 0;
|
|
67
|
-
bucket.hourlyWindowStart = now;
|
|
68
|
-
}
|
|
69
|
-
// Prune old call log entries — find cutoff via binary search instead of O(n) shift
|
|
70
|
-
const windowStart = now - bucket.config.windowMs;
|
|
71
|
-
let pruneIndex = 0;
|
|
72
|
-
while (pruneIndex < bucket.callLog.length && bucket.callLog[pruneIndex] < windowStart) {
|
|
73
|
-
pruneIndex++;
|
|
74
|
-
}
|
|
75
|
-
if (pruneIndex > 0) {
|
|
76
|
-
bucket.callLog = bucket.callLog.slice(pruneIndex);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
class RateLimiter {
|
|
80
|
-
buckets = new Map();
|
|
81
|
-
sessions = new Map();
|
|
82
|
-
serviceConfigs;
|
|
83
|
-
constructor(customConfigs) {
|
|
84
|
-
// Merge defaults with custom configs
|
|
85
|
-
this.serviceConfigs = { ...DEFAULT_SERVICES };
|
|
86
|
-
if (customConfigs) {
|
|
87
|
-
for (const [service, overrides] of Object.entries(customConfigs)) {
|
|
88
|
-
if (overrides) {
|
|
89
|
-
this.serviceConfigs[service] = {
|
|
90
|
-
...(this.serviceConfigs[service] ?? DEFAULT_SERVICES.web),
|
|
91
|
-
...overrides,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// Initialize buckets
|
|
97
|
-
for (const [service, config] of Object.entries(this.serviceConfigs)) {
|
|
98
|
-
this.buckets.set(service, createBucket(config));
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Try to acquire capacity for an API call.
|
|
103
|
-
* Call this BEFORE making an external API request.
|
|
104
|
-
*/
|
|
105
|
-
acquire(service, mcpSessionId, threadId, count = 1) {
|
|
106
|
-
// Ensure bucket exists (auto-create for unknown services)
|
|
107
|
-
if (!this.buckets.has(service)) {
|
|
108
|
-
const config = this.serviceConfigs[service] ?? { ...DEFAULT_SERVICES.web, description: service };
|
|
109
|
-
this.serviceConfigs[service] = config;
|
|
110
|
-
this.buckets.set(service, createBucket(config));
|
|
111
|
-
}
|
|
112
|
-
const bucket = this.buckets.get(service);
|
|
113
|
-
refillBucket(bucket);
|
|
114
|
-
// Validate count
|
|
115
|
-
if (count <= 0)
|
|
116
|
-
count = 1;
|
|
117
|
-
const activeSessions = this.getActiveSessionCount();
|
|
118
|
-
const usage = Math.min(1.0, bucket.callLog.length / bucket.config.maxRequests);
|
|
119
|
-
// Fair share: if multiple sessions, each gets proportional quota
|
|
120
|
-
const fairShare = activeSessions > 1 ? bucket.config.burstSize / activeSessions : bucket.config.burstSize;
|
|
121
|
-
const sessionCalls = this.sessions.get(mcpSessionId)?.serviceCalls[service] ?? 0;
|
|
122
|
-
// Check if this session is hogging the resource
|
|
123
|
-
const isHogging = activeSessions > 1 && sessionCalls > fairShare * 1.5;
|
|
124
|
-
if (bucket.tokens < count) {
|
|
125
|
-
// Not enough tokens — DON'T track denied requests in session stats (bug fix)
|
|
126
|
-
const waitMs = Math.ceil((count - bucket.tokens) / bucket.config.refillRate * 1000);
|
|
127
|
-
return {
|
|
128
|
-
allowed: false,
|
|
129
|
-
waitMs,
|
|
130
|
-
usage,
|
|
131
|
-
activeSessions,
|
|
132
|
-
message: `Rate limit reached for ${bucket.config.description}. ` +
|
|
133
|
-
`${activeSessions} active agents sharing capacity. ` +
|
|
134
|
-
`Wait ${Math.ceil(waitMs / 1000)}s before retrying.` +
|
|
135
|
-
(isHogging ? " You're using more than your fair share — please slow down." : ""),
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
// Only track session AFTER confirming the request is allowed
|
|
139
|
-
this.touchSession(mcpSessionId, threadId, service, count);
|
|
140
|
-
// Warning thresholds
|
|
141
|
-
const warningLevel = usage > 0.8 ? "high"
|
|
142
|
-
: usage > 0.5 ? "moderate"
|
|
143
|
-
: "normal";
|
|
144
|
-
// Consume tokens and track
|
|
145
|
-
bucket.tokens -= count;
|
|
146
|
-
const now = Date.now();
|
|
147
|
-
for (let i = 0; i < count; i++) {
|
|
148
|
-
bucket.callLog.push(now);
|
|
149
|
-
}
|
|
150
|
-
bucket.hourlyCallCount += count;
|
|
151
|
-
let message = `OK — ${bucket.config.description}: ${Math.floor(bucket.tokens)}/${bucket.config.burstSize} tokens available`;
|
|
152
|
-
if (activeSessions > 1) {
|
|
153
|
-
message += `, ${activeSessions} agents sharing`;
|
|
154
|
-
}
|
|
155
|
-
if (warningLevel === "high") {
|
|
156
|
-
message += ". ⚠️ Approaching rate limit — consider spacing out requests.";
|
|
157
|
-
}
|
|
158
|
-
else if (warningLevel === "moderate") {
|
|
159
|
-
message += ". Usage moderate — monitoring.";
|
|
160
|
-
}
|
|
161
|
-
if (isHogging) {
|
|
162
|
-
message += " ⚠️ You're using more than your fair share — other agents need capacity too.";
|
|
163
|
-
}
|
|
164
|
-
return {
|
|
165
|
-
allowed: true,
|
|
166
|
-
usage,
|
|
167
|
-
activeSessions,
|
|
168
|
-
message,
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Record API calls that bypass the acquire() flow (e.g., implicit calls).
|
|
173
|
-
* Use this for tracking only — doesn't block.
|
|
174
|
-
*/
|
|
175
|
-
record(service, mcpSessionId, threadId, count = 1) {
|
|
176
|
-
if (count <= 0)
|
|
177
|
-
count = 1;
|
|
178
|
-
if (!this.buckets.has(service))
|
|
179
|
-
return;
|
|
180
|
-
const bucket = this.buckets.get(service);
|
|
181
|
-
refillBucket(bucket);
|
|
182
|
-
const now = Date.now();
|
|
183
|
-
for (let i = 0; i < count; i++) {
|
|
184
|
-
bucket.callLog.push(now);
|
|
185
|
-
}
|
|
186
|
-
bucket.hourlyCallCount += count;
|
|
187
|
-
// Consume tokens for record-only too — keeps stats consistent
|
|
188
|
-
bucket.tokens = Math.max(0, bucket.tokens - count);
|
|
189
|
-
this.touchSession(mcpSessionId, threadId, service, count);
|
|
190
|
-
}
|
|
191
|
-
/** Get comprehensive usage statistics for the dashboard. */
|
|
192
|
-
getStats() {
|
|
193
|
-
const now = Date.now();
|
|
194
|
-
const services = [];
|
|
195
|
-
for (const [service, bucket] of this.buckets) {
|
|
196
|
-
refillBucket(bucket);
|
|
197
|
-
const sessionBreakdown = [];
|
|
198
|
-
for (const [sessionId, session] of this.sessions) {
|
|
199
|
-
const calls = session.serviceCalls[service] ?? 0;
|
|
200
|
-
if (calls > 0) {
|
|
201
|
-
sessionBreakdown.push({
|
|
202
|
-
mcpSessionId: sessionId,
|
|
203
|
-
threadId: session.threadId,
|
|
204
|
-
calls,
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
services.push({
|
|
209
|
-
service,
|
|
210
|
-
description: bucket.config.description,
|
|
211
|
-
callsInWindow: bucket.callLog.length,
|
|
212
|
-
maxPerWindow: bucket.config.maxRequests,
|
|
213
|
-
usagePercent: Math.min(100, Math.round((bucket.callLog.length / bucket.config.maxRequests) * 100)),
|
|
214
|
-
availableTokens: Math.floor(bucket.tokens),
|
|
215
|
-
burstCapacity: bucket.config.burstSize,
|
|
216
|
-
sessionBreakdown,
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
// Total calls in last hour — use dedicated hourly counter (not callLog which
|
|
220
|
-
// gets pruned to short windows for services like telegram/openai)
|
|
221
|
-
let totalCallsLastHour = 0;
|
|
222
|
-
for (const bucket of this.buckets.values()) {
|
|
223
|
-
totalCallsLastHour += bucket.hourlyCallCount;
|
|
224
|
-
}
|
|
225
|
-
return {
|
|
226
|
-
services,
|
|
227
|
-
activeSessions: this.getActiveSessionCount(),
|
|
228
|
-
totalCallsLastHour,
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
/** Remove a session from tracking (called when session ends). */
|
|
232
|
-
removeSession(mcpSessionId) {
|
|
233
|
-
this.sessions.delete(mcpSessionId);
|
|
234
|
-
}
|
|
235
|
-
/** Reset all counters (useful for testing). */
|
|
236
|
-
reset() {
|
|
237
|
-
for (const [service, config] of Object.entries(this.serviceConfigs)) {
|
|
238
|
-
this.buckets.set(service, createBucket(config));
|
|
239
|
-
}
|
|
240
|
-
this.sessions.clear();
|
|
241
|
-
}
|
|
242
|
-
// ── Private helpers ─────────────────────────────────────────────────────
|
|
243
|
-
touchSession(mcpSessionId, threadId, service, count) {
|
|
244
|
-
let session = this.sessions.get(mcpSessionId);
|
|
245
|
-
if (!session) {
|
|
246
|
-
session = {
|
|
247
|
-
mcpSessionId,
|
|
248
|
-
threadId,
|
|
249
|
-
serviceCalls: {},
|
|
250
|
-
lastActivity: Date.now(),
|
|
251
|
-
totalCalls: 0,
|
|
252
|
-
};
|
|
253
|
-
this.sessions.set(mcpSessionId, session);
|
|
254
|
-
}
|
|
255
|
-
session.lastActivity = Date.now();
|
|
256
|
-
session.serviceCalls[service] = (session.serviceCalls[service] ?? 0) + count;
|
|
257
|
-
session.totalCalls += count;
|
|
258
|
-
if (threadId !== undefined)
|
|
259
|
-
session.threadId = threadId;
|
|
260
|
-
}
|
|
261
|
-
getActiveSessionCount() {
|
|
262
|
-
const staleThreshold = Date.now() - 5 * 60 * 1000; // 5 min
|
|
263
|
-
let active = 0;
|
|
264
|
-
for (const session of this.sessions.values()) {
|
|
265
|
-
if (session.lastActivity > staleThreshold)
|
|
266
|
-
active++;
|
|
267
|
-
}
|
|
268
|
-
return active;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
// ─── Singleton ──────────────────────────────────────────────────────────────
|
|
272
|
-
/** Global rate limiter instance — shared across all MCP sessions in-process. */
|
|
273
|
-
export const rateLimiter = new RateLimiter(parseEnvOverrides());
|
|
274
|
-
/**
|
|
275
|
-
* Parse environment variable overrides for rate limits.
|
|
276
|
-
* Format: RATE_LIMIT_{SERVICE}_{FIELD}=value
|
|
277
|
-
* Example: RATE_LIMIT_GITHUB_MAX_REQUESTS=3000
|
|
278
|
-
*/
|
|
279
|
-
function parseEnvOverrides() {
|
|
280
|
-
const overrides = {};
|
|
281
|
-
let hasOverrides = false;
|
|
282
|
-
for (const [key, value] of Object.entries(process.env)) {
|
|
283
|
-
const match = key.match(/^RATE_LIMIT_(\w+)_(MAX_REQUESTS|WINDOW_MS|BURST_SIZE|REFILL_RATE)$/i);
|
|
284
|
-
if (match && value) {
|
|
285
|
-
const service = match[1].toLowerCase();
|
|
286
|
-
const field = match[2].toLowerCase();
|
|
287
|
-
const num = Number(value);
|
|
288
|
-
if (!Number.isFinite(num))
|
|
289
|
-
continue;
|
|
290
|
-
if (!overrides[service])
|
|
291
|
-
overrides[service] = {};
|
|
292
|
-
hasOverrides = true;
|
|
293
|
-
switch (field) {
|
|
294
|
-
case "max_requests":
|
|
295
|
-
overrides[service].maxRequests = num;
|
|
296
|
-
break;
|
|
297
|
-
case "window_ms":
|
|
298
|
-
overrides[service].windowMs = num;
|
|
299
|
-
break;
|
|
300
|
-
case "burst_size":
|
|
301
|
-
overrides[service].burstSize = num;
|
|
302
|
-
break;
|
|
303
|
-
case "refill_rate":
|
|
304
|
-
overrides[service].refillRate = num;
|
|
305
|
-
break;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
return hasOverrides ? overrides : undefined;
|
|
310
|
-
}
|
|
311
|
-
//# sourceMappingURL=rate-limiter.js.map
|
package/dist/rate-limiter.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"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"}
|