fix(usage): stop leaking hidden noAuth providers (devin-cli, mimo-free)
The Usage page auto-adds every noAuth free provider so connectionless providers (opencode) still appear. It did not filter the registry's hidden flag, so devin-cli and mimo-free — both category:"free" with noAuth:true and hidden:true — showed up in Usage despite having no connection and being absent from the Providers page (which does filter hidden). Extract the list assembly into buildUsageProviderList (shared/utils/ usageProviders.js) and skip hidden free providers there. Behavior for visible noAuth providers (opencode) and dedup of active connections is unchanged; covered by tests/unit/usage-provider-list.test.js.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { useState, useEffect, useMemo, useCallback, useRef } from "react";
|
||||
import { useSearchParams, useRouter } from "next/navigation";
|
||||
import { FREE_PROVIDERS, AI_PROVIDERS } from "@/shared/constants/providers";
|
||||
import { buildUsageProviderList } from "@/shared/utils/usageProviders";
|
||||
|
||||
// Keep providers without serviceKinds (default LLM) or with "llm" in serviceKinds
|
||||
function isLLMProvider(id) {
|
||||
@@ -232,21 +233,12 @@ export default function UsageStats({ period: periodProp, setPeriod: setPeriodPro
|
||||
for (const node of (nodesData?.nodes || [])) {
|
||||
nodeNameMap[node.id] = node.name;
|
||||
}
|
||||
const seen = new Set();
|
||||
const unique = (d?.connections || []).filter((c) => {
|
||||
if (c.isActive === false) return false;
|
||||
if (!isLLMProvider(c.provider)) return false;
|
||||
if (seen.has(c.provider)) return false;
|
||||
seen.add(c.provider);
|
||||
return true;
|
||||
}).map((c) => ({
|
||||
...c,
|
||||
nodeName: nodeNameMap[c.provider] || null,
|
||||
setProviders(buildUsageProviderList({
|
||||
connections: d?.connections || [],
|
||||
freeProviders: FREE_PROVIDERS,
|
||||
nodeNameMap,
|
||||
isLLMProvider,
|
||||
}));
|
||||
const noAuthProviders = Object.values(FREE_PROVIDERS)
|
||||
.filter((p) => p.noAuth && !seen.has(p.id) && isLLMProvider(p.id))
|
||||
.map((p) => ({ provider: p.id, name: p.name }));
|
||||
setProviders([...unique, ...noAuthProviders]);
|
||||
})
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// Provider list for the Usage page.
|
||||
//
|
||||
// Two sources, deduped by provider id:
|
||||
// 1. Active LLM connections (one entry per provider).
|
||||
// 2. noAuth free providers that need no connection (e.g. opencode).
|
||||
//
|
||||
// Hidden providers are excluded — the Providers page filters `hidden`, so a
|
||||
// hidden noAuth provider (devin-cli, mimo-free) must not leak into Usage with
|
||||
// zero connections and zero traffic.
|
||||
export function buildUsageProviderList({
|
||||
connections = [],
|
||||
freeProviders = {},
|
||||
nodeNameMap = {},
|
||||
isLLMProvider = () => true,
|
||||
} = {}) {
|
||||
const seen = new Set();
|
||||
const unique = connections
|
||||
.filter((c) => {
|
||||
if (c.isActive === false) return false;
|
||||
if (!isLLMProvider(c.provider)) return false;
|
||||
if (seen.has(c.provider)) return false;
|
||||
seen.add(c.provider);
|
||||
return true;
|
||||
})
|
||||
.map((c) => ({
|
||||
...c,
|
||||
nodeName: nodeNameMap[c.provider] || null,
|
||||
}));
|
||||
|
||||
const noAuthProviders = Object.values(freeProviders)
|
||||
.filter((p) => p.noAuth && !p.hidden && !seen.has(p.id) && isLLMProvider(p.id))
|
||||
.map((p) => ({ provider: p.id, name: p.name }));
|
||||
|
||||
return [...unique, ...noAuthProviders];
|
||||
}
|
||||
Reference in New Issue
Block a user