open-agents-ai 0.184.55 → 0.184.57

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.
Files changed (2) hide show
  1. package/dist/index.js +70 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -62035,6 +62035,38 @@ function getVersion3() {
62035
62035
  }
62036
62036
  return "0.0.0";
62037
62037
  }
62038
+ function getEndpointUsage(label) {
62039
+ let u = endpointUsage.get(label);
62040
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
62041
+ if (!u) {
62042
+ u = { requestTimestamps: [], tokensToday: 0, tokenDate: today };
62043
+ endpointUsage.set(label, u);
62044
+ }
62045
+ if (u.tokenDate !== today) {
62046
+ u.tokensToday = 0;
62047
+ u.tokenDate = today;
62048
+ }
62049
+ return u;
62050
+ }
62051
+ function checkEndpointRateLimit(ep, estimatedTokens) {
62052
+ const rpm = ep.limits?.maxRequestsPerMinute ?? 60;
62053
+ const tpd = ep.limits?.maxTokensPerDay ?? 1e5;
62054
+ const usage = getEndpointUsage(ep.label);
62055
+ const now = Date.now();
62056
+ usage.requestTimestamps = usage.requestTimestamps.filter((t) => now - t < 6e4);
62057
+ if (usage.requestTimestamps.length >= rpm) {
62058
+ return `Rate limit exceeded for ${ep.label}: ${rpm} requests/minute. Try again in ${Math.ceil((usage.requestTimestamps[0] + 6e4 - now) / 1e3)}s.`;
62059
+ }
62060
+ if (estimatedTokens && usage.tokensToday + estimatedTokens > tpd) {
62061
+ return `Daily token limit exceeded for ${ep.label}: ${usage.tokensToday}/${tpd} tokens today.`;
62062
+ }
62063
+ return null;
62064
+ }
62065
+ function recordEndpointUsage(label, tokens) {
62066
+ const usage = getEndpointUsage(label);
62067
+ usage.requestTimestamps.push(Date.now());
62068
+ usage.tokensToday += tokens;
62069
+ }
62038
62070
  async function refreshEndpointRegistry() {
62039
62071
  endpointRegistry.length = 0;
62040
62072
  modelRouteMap.clear();
@@ -62068,6 +62100,10 @@ async function refreshEndpointRegistry() {
62068
62100
  label,
62069
62101
  url: sp.tunnelUrl,
62070
62102
  type: "vllm",
62103
+ limits: {
62104
+ maxRequestsPerMinute: sp.limits?.maxRequestsPerMinute ?? 60,
62105
+ maxTokensPerDay: sp.limits?.maxTokensPerDay ?? 1e5
62106
+ },
62071
62107
  authKey: sp.authKey
62072
62108
  });
62073
62109
  }
@@ -62122,10 +62158,18 @@ function resolveModelEndpoint(modelId) {
62122
62158
  const exact = modelRouteMap.get(modelId);
62123
62159
  if (exact)
62124
62160
  return exact;
62125
- for (const [prefixed, route] of modelRouteMap) {
62161
+ for (const [, route] of modelRouteMap) {
62126
62162
  if (route.originalId === modelId)
62127
62163
  return route;
62128
62164
  }
62165
+ const slashIdx = modelId.indexOf("/");
62166
+ if (slashIdx > 0) {
62167
+ const prefix = modelId.slice(0, slashIdx);
62168
+ const rest = modelId.slice(slashIdx + 1);
62169
+ const ep = endpointRegistry.find((e) => e.label === prefix);
62170
+ if (ep)
62171
+ return { endpoint: ep, originalId: rest };
62172
+ }
62129
62173
  if (endpointRegistry.length > 0) {
62130
62174
  return { endpoint: endpointRegistry[0], originalId: modelId };
62131
62175
  }
@@ -62407,6 +62451,13 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
62407
62451
  const targetUrl = route?.endpoint.url ?? ollamaUrl;
62408
62452
  const targetType = route?.endpoint.type ?? loadConfig().backendType ?? "ollama";
62409
62453
  const originalModel = route?.originalId ?? model;
62454
+ if (route?.endpoint) {
62455
+ const limitErr = checkEndpointRateLimit(route.endpoint);
62456
+ if (limitErr) {
62457
+ jsonResponse(res, 429, { error: limitErr });
62458
+ return;
62459
+ }
62460
+ }
62410
62461
  const routedBody = { ...requestBody, model: originalModel };
62411
62462
  if (targetType === "vllm" || targetType === "openai") {
62412
62463
  const payload = JSON.stringify(routedBody);
@@ -62441,8 +62492,11 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
62441
62492
  }
62442
62493
  const parsed = JSON.parse(result.body);
62443
62494
  if (parsed.usage) {
62495
+ const totalTok = (parsed.usage.prompt_tokens ?? 0) + (parsed.usage.completion_tokens ?? 0);
62444
62496
  metrics.totalTokensIn += parsed.usage.prompt_tokens ?? 0;
62445
62497
  metrics.totalTokensOut += parsed.usage.completion_tokens ?? 0;
62498
+ if (route?.endpoint)
62499
+ recordEndpointUsage(route.endpoint.label, totalTok);
62446
62500
  }
62447
62501
  jsonResponse(res, 200, parsed);
62448
62502
  } catch (err) {
@@ -63096,6 +63150,19 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
63096
63150
  await handlePutConfigEndpoint(req, res);
63097
63151
  return;
63098
63152
  }
63153
+ if (pathname === "/v1/usage" && method === "GET") {
63154
+ const usageData = {};
63155
+ for (const ep of endpointRegistry) {
63156
+ const u = getEndpointUsage(ep.label);
63157
+ usageData[ep.label] = {
63158
+ requestsLastMinute: u.requestTimestamps.filter((t) => Date.now() - t < 6e4).length,
63159
+ tokensToday: u.tokensToday,
63160
+ limits: ep.limits ?? { maxRequestsPerMinute: "unlimited", maxTokensPerDay: "unlimited" }
63161
+ };
63162
+ }
63163
+ jsonResponse(res, 200, { usage: usageData, totalTokensIn: metrics.totalTokensIn, totalTokensOut: metrics.totalTokensOut });
63164
+ return;
63165
+ }
63099
63166
  if (pathname === "/v1/commands" && method === "GET") {
63100
63167
  handleGetCommands(res);
63101
63168
  return;
@@ -63288,7 +63355,7 @@ async function apiServeCommand(opts, config) {
63288
63355
  server.on("close", resolve36);
63289
63356
  });
63290
63357
  }
63291
- var endpointRegistry, modelRouteMap, metrics, startedAt, runningProcesses;
63358
+ var endpointRegistry, modelRouteMap, endpointUsage, metrics, startedAt, runningProcesses;
63292
63359
  var init_serve = __esm({
63293
63360
  "packages/cli/dist/api/serve.js"() {
63294
63361
  "use strict";
@@ -63298,6 +63365,7 @@ var init_serve = __esm({
63298
63365
  init_profiles();
63299
63366
  endpointRegistry = [];
63300
63367
  modelRouteMap = /* @__PURE__ */ new Map();
63368
+ endpointUsage = /* @__PURE__ */ new Map();
63301
63369
  metrics = {
63302
63370
  requests: /* @__PURE__ */ new Map(),
63303
63371
  totalTokensIn: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.184.55",
3
+ "version": "0.184.57",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",