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:
MUH. IQRAM BAHRING
2026-09-19 12:21:14 +08:00
parent 604b4d85d5
commit 9d7821bdcc
3 changed files with 121 additions and 14 deletions
+80
View File
@@ -0,0 +1,80 @@
// The Usage page lists providers from two sources:
// 1. active LLM connections (deduped by provider id), and
// 2. noAuth free providers that need no connection (e.g. opencode).
//
// Hidden providers (devin-cli, mimo-free) must NOT be auto-added — they are
// excluded from the Providers page, so surfacing them in Usage (with zero
// connections and zero traffic) is a leak. Regression: devin-cli showed up in
// Usage but nowhere in Providers.
import { describe, it, expect } from "vitest";
import { buildUsageProviderList } from "../../src/shared/utils/usageProviders.js";
const isLLM = () => true;
describe("buildUsageProviderList", () => {
it("does not auto-add hidden noAuth free providers", () => {
const freeProviders = {
opencode: { id: "opencode", name: "OpenCode", noAuth: true },
"devin-cli": { id: "devin-cli", name: "Devin CLI", noAuth: true, hidden: true },
"mimo-free": { id: "mimo-free", name: "MiMo Free", noAuth: true, hidden: true },
};
const list = buildUsageProviderList({
connections: [],
freeProviders,
isLLMProvider: isLLM,
});
const ids = list.map((p) => p.provider);
expect(ids).toContain("opencode");
expect(ids).not.toContain("devin-cli");
expect(ids).not.toContain("mimo-free");
});
it("includes active LLM connections, deduped by provider", () => {
const list = buildUsageProviderList({
connections: [
{ provider: "codex", isActive: true },
{ provider: "codex", isActive: true },
{ provider: "zed", isActive: true },
],
freeProviders: {},
isLLMProvider: isLLM,
});
expect(list.map((p) => p.provider)).toEqual(["codex", "zed"]);
});
it("skips inactive connections and non-LLM providers", () => {
const list = buildUsageProviderList({
connections: [
{ provider: "codex", isActive: false },
{ provider: "whisper", isActive: true },
],
freeProviders: {},
isLLMProvider: (id) => id !== "whisper",
});
expect(list).toEqual([]);
});
it("does not duplicate a free provider that already has a connection", () => {
const freeProviders = {
opencode: { id: "opencode", name: "OpenCode", noAuth: true },
};
const list = buildUsageProviderList({
connections: [{ provider: "opencode", isActive: true }],
freeProviders,
isLLMProvider: isLLM,
});
expect(list.map((p) => p.provider)).toEqual(["opencode"]);
});
it("attaches nodeName from the lookup when present", () => {
const list = buildUsageProviderList({
connections: [{ provider: "node-1", isActive: true }],
freeProviders: {},
nodeNameMap: { "node-1": "My Node" },
isLLMProvider: isLLM,
});
expect(list[0].nodeName).toBe("My Node");
});
});