mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-26 09:02:11 +03:00
* fix(usage): wire agentrouter balance quota into dashboard Quota UI (#10078) * fix(usage): render AgentRouter wallet balance as USD in the Quota UI (#10078) The prior fix wired AgentRouter's balance into getUsageForProvider() and USAGE_SUPPORTED_PROVIDERS, but the actual dollar figure never reached the Dashboard Quota UI: quotas.balance.remaining carried a synthetic two-state percent (100/0) instead of the real dollarBalance, and the Provider Limits renderer only formats a row as "$X.XX" when isCredits/currency/creditCount are set, which the generic quota-parsing path never sets. A configured balance rendered as a bare "100% left" percentage, not USD. Shape quotas.balance.remaining as the real USD amount (clamped to 0) and add an agentrouter branch to quotaParsing.ts that builds a credits-style row (same buildCreditsQuota() pattern as DeepSeek/Claude extra-usage), so a configured balance shows a currency-formatted dollar amount and an exhausted balance always renders as exactly $0.00. --------- Co-authored-by: adevwithpurpose <adevwithpurpose@users.noreply.github.com>
86 lines
3.0 KiB
TypeScript
86 lines
3.0 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { USAGE_SUPPORTED_PROVIDERS } from "../../src/shared/constants/providers.ts";
|
|
import { supportsProviderQuota } from "../../src/shared/utils/providerQuotaVisibility.ts";
|
|
import {
|
|
USAGE_FETCHER_PROVIDERS,
|
|
getUsageForProvider,
|
|
} from "../../open-sse/services/usage.ts";
|
|
import {
|
|
getAgentrouterUsage,
|
|
} from "../../open-sse/services/usage/agentrouter.ts";
|
|
import {
|
|
invalidateAgentrouterQuotaCache,
|
|
type AgentrouterQuota,
|
|
} from "../../open-sse/services/agentrouterQuotaFetcher.ts";
|
|
|
|
const originalFetch = globalThis.fetch;
|
|
|
|
test.afterEach(() => {
|
|
globalThis.fetch = originalFetch;
|
|
});
|
|
|
|
/**
|
|
* #10078 — AgentRouter quota was missing from the dashboard:
|
|
* - USAGE_SUPPORTED_PROVIDERS (visibility gate) omitted "agentrouter", and
|
|
* - USAGE_FETCHER_PROVIDERS + getUsageForProvider (the provider-limits data
|
|
* path) had no "agentrouter" case, so /api/usage/provider-limits fell back
|
|
* to the generic "Usage API not implemented" message.
|
|
* These three assertions are the permanent regression guard (RED before the
|
|
* fix, GREEN after).
|
|
*/
|
|
test("#10078: agentrouter is present in USAGE_SUPPORTED_PROVIDERS", () => {
|
|
assert.equal(
|
|
USAGE_SUPPORTED_PROVIDERS.includes("agentrouter" as (typeof USAGE_SUPPORTED_PROVIDERS)[number]),
|
|
true
|
|
);
|
|
});
|
|
|
|
test("#10078: supportsProviderQuota('agentrouter') is true", () => {
|
|
assert.equal(supportsProviderQuota("agentrouter"), true);
|
|
});
|
|
|
|
test("#10078: agentrouter is present in USAGE_FETCHER_PROVIDERS", () => {
|
|
assert.equal(
|
|
USAGE_FETCHER_PROVIDERS.includes("agentrouter" as (typeof USAGE_FETCHER_PROVIDERS)[number]),
|
|
true
|
|
);
|
|
});
|
|
|
|
test("#10078: getUsageForProvider shapes the AgentRouter balance into a USD quota", async () => {
|
|
const connectionId = `agentrouter-vis-${Date.now()}`;
|
|
globalThis.fetch = (async () => {
|
|
return new Response(JSON.stringify({ data: { quota: 250_000 } }), {
|
|
status: 200,
|
|
headers: { "content-type": "application/json" },
|
|
});
|
|
}) as typeof fetch;
|
|
|
|
const usage = (await getUsageForProvider({
|
|
id: connectionId,
|
|
provider: "agentrouter",
|
|
providerSpecificData: { consoleApiKey: "system-access-token", newApiUserId: "42" },
|
|
})) as {
|
|
plan?: string;
|
|
quotas?: Record<string, { displayName?: string; remainingPercentage?: number }>;
|
|
remainingUsd?: number;
|
|
};
|
|
|
|
assert.equal(usage.plan, "AgentRouter");
|
|
assert.ok(usage.quotas);
|
|
const balance = usage.quotas.balance;
|
|
assert.ok(balance, "expected a `balance` quota entry");
|
|
assert.equal(balance.displayName, "Wallet Balance (USD)");
|
|
assert.equal(usage.remainingUsd, 0.5);
|
|
});
|
|
|
|
test("#10078: getAgentrouterUsage returns a graceful message when console credentials are missing", async () => {
|
|
const usage = (await getAgentrouterUsage(`missing-${Date.now()}`, {
|
|
provider: "agentrouter",
|
|
})) as { message?: string; quotas?: unknown };
|
|
|
|
assert.equal(typeof usage.message, "string");
|
|
assert.ok(/not available/i.test(usage.message || ""));
|
|
assert.equal(usage.quotas, undefined);
|
|
}); |