feat(bazaarlink): add authHint to existing APIKEY_PROVIDERS entry (#4522)

Adds authHint + enriched freeNote/apiHint on the existing bazaarlink entry (distinct from the closed-redundant #4497). Integrity test included.

Integrated into release/v3.8.33.
This commit is contained in:
Abhishek Divekar
2026-06-22 00:12:45 +05:30
committed by GitHub
parent 9ade3e5f52
commit f91cf72c16
2 changed files with 97 additions and 10 deletions

View File

@@ -999,9 +999,12 @@ export const APIKEY_PROVIDERS = {
textIcon: "BZ",
website: "https://bazaarlink.ai",
hasFree: true,
freeNote: "Free tier with auto:free routing — zero-cost inference, no credit card required",
freeNote:
"Free tier: 4M tokens/day per account with auto:free routing — zero-cost inference, no credit card required.",
authHint:
"Use your BazaarLink API key (starts with sk-bl-) in Authorization: Bearer <key>. OpenAI SDK works with base URL https://bazaarlink.ai/api/v1. Models use provider/model-name format.",
apiHint:
"Get free API key at https://bazaarlink.ai — use model 'auto:free' for zero-cost inference. OpenAI-compatible.",
"Create a free API key at https://bazaarlink.ai — model 'auto:free' routes to zero-cost inference. All models use the provider/model-name format, e.g. xiaomi/mimo-v2.5-pro.",
},
xai: {
id: "xai",
@@ -1745,7 +1748,8 @@ export const APIKEY_PROVIDERS = {
textIcon: "GLB",
website: "https://opengateway.gitlawb.com",
hasFree: false,
freeNote: "Free MiMo (xiaomi/mimo-v2.5) revoked 2026-05 — Opengateway is now a pay-as-you-go credit gateway; no recurring free model.",
freeNote:
"Free MiMo (xiaomi/mimo-v2.5) revoked 2026-05 — Opengateway is now a pay-as-you-go credit gateway; no recurring free model.",
apiHint: "Get your API key from Gitlawb Opengateway dashboard.",
},
"gitlawb-gmi": {
@@ -1757,7 +1761,8 @@ export const APIKEY_PROVIDERS = {
textIcon: "GMI",
website: "https://opengateway.gitlawb.com",
hasFree: false,
freeNote: "Free Nemotron promo ended 2026-06 — the GMI Cloud route is now pay-as-you-go credit only.",
freeNote:
"Free Nemotron promo ended 2026-06 — the GMI Cloud route is now pay-as-you-go credit only.",
apiHint: "Get your API key from Gitlawb Opengateway dashboard.",
},
"inference-net": {
@@ -1974,7 +1979,8 @@ export const APIKEY_PROVIDERS = {
textIcon: "CH",
website: "https://chutes.ai",
hasFree: false,
freeNote: "No free tier as of 2026 — Chutes moved to pay-as-you-go (free Early Access ended 2026-03).",
freeNote:
"No free tier as of 2026 — Chutes moved to pay-as-you-go (free Early Access ended 2026-03).",
authHint: "Bearer API key for the Chutes OpenAI-compatible gateway.",
passthroughModels: true,
},
@@ -2082,7 +2088,8 @@ export const APIKEY_PROVIDERS = {
textIcon: "IF",
website: "https://xinghuo.xfyun.cn",
hasFree: true,
freeNote: "Spark Lite is free (2 QPS rate-limited), but iFlytek ToS §2.4(3) prohibits programmatic extraction and requires Chinese real-name auth — use with caution.",
freeNote:
"Spark Lite is free (2 QPS rate-limited), but iFlytek ToS §2.4(3) prohibits programmatic extraction and requires Chinese real-name auth — use with caution.",
passthroughModels: true,
authHint: "Get API key at console.xfyun.cn",
},
@@ -2108,7 +2115,8 @@ export const APIKEY_PROVIDERS = {
textIcon: "YI",
website: "https://01.ai",
hasFree: false,
freeNote: "No free API tier (2026) — Yi-Light retired; platform.01.ai is pay-as-you-go (Yi-Lightning paid). Open weights are download-only.",
freeNote:
"No free API tier (2026) — Yi-Light retired; platform.01.ai is pay-as-you-go (Yi-Lightning paid). Open weights are download-only.",
passthroughModels: true,
authHint: "Get API key at platform.lingyiwanwu.com",
},
@@ -2186,7 +2194,8 @@ export const APIKEY_PROVIDERS = {
textIcon: "SD",
website: "https://xinghuo.xfyun.cn",
hasFree: true,
freeNote: "Spark Lite free (alias for iflytek), but ToS restricts to personal/non-commercial use and prohibits relaying access to third parties — use with caution.",
freeNote:
"Spark Lite free (alias for iflytek), but ToS restricts to personal/non-commercial use and prohibits relaying access to third parties — use with caution.",
passthroughModels: true,
authHint: "Get API key at console.xfyun.cn",
},
@@ -2296,7 +2305,8 @@ export const APIKEY_PROVIDERS = {
textIcon: "MA",
website: "https://monsterapi.ai",
hasFree: true,
freeNote: "One-time signup trial credits for decentralized GPU inference (no recurring free plan). No credit card required.",
freeNote:
"One-time signup trial credits for decentralized GPU inference (no recurring free plan). No credit card required.",
passthroughModels: true,
authHint: "Get API key at monsterapi.ai",
},
@@ -2439,7 +2449,8 @@ export const APIKEY_PROVIDERS = {
textIcon: "TK",
website: "https://tokenrouter.com",
hasFree: true,
freeNote: "Free tier includes the MiniMax 3 model. Get your API key at https://tokenrouter.com.",
freeNote:
"Free tier includes the MiniMax 3 model. Get your API key at https://tokenrouter.com.",
authHint:
"Use your TokenRouter API key in Authorization: Bearer <key>. Fully OpenAI-compatible. API base URL: https://api.tokenrouter.com/v1.",
apiHint:

View File

@@ -0,0 +1,76 @@
import { describe, it } from "node:test";
import assert from "node:assert";
describe("bazaarlink provider entry in APIKEY_PROVIDERS", () => {
it("exists with required fields", async () => {
const { APIKEY_PROVIDERS } = await import("../../src/shared/constants/providers.ts");
const p = (APIKEY_PROVIDERS as Record<string, Record<string, unknown>>)["bazaarlink"];
assert.ok(p, "bazaarlink must exist in APIKEY_PROVIDERS");
assert.equal(p.id, "bazaarlink");
assert.equal(p.alias, "bzl");
assert.equal(p.name, "BazaarLink");
assert.equal(p.icon, "storefront");
assert.equal(p.color, "#6366F1");
assert.equal(p.textIcon, "BZ");
assert.equal(p.website, "https://bazaarlink.ai");
});
it("advertises the free tier and includes authHint", async () => {
const { APIKEY_PROVIDERS } = await import("../../src/shared/constants/providers.ts");
const p = (
APIKEY_PROVIDERS as Record<
string,
{ hasFree?: boolean; authHint?: string; freeNote?: string; apiHint?: string }
>
)["bazaarlink"];
assert.equal(p.hasFree, true, "bazaarlink should advertise a free tier");
assert.ok(p.authHint, "bazaarlink must have an authHint field");
assert.ok(p.authHint.includes("sk-bl-"), "authHint should mention the sk-bl- key prefix");
assert.ok(p.freeNote, "bazaarlink must have a freeNote describing the free tier");
assert.ok(p.apiHint, "bazaarlink must have an apiHint");
assert.ok(p.apiHint.includes("bazaarlink.ai"), "apiHint should reference bazaarlink.ai");
});
it("is registered in the execution registry", async () => {
const { getRegistryEntry } = await import("../../open-sse/config/providerRegistry.ts");
const entry = getRegistryEntry("bazaarlink");
assert.ok(entry, "bazaarlink must have a registry entry");
assert.equal(entry.format, "openai");
assert.equal(entry.authType, "apikey");
assert.ok(entry.baseUrl, "registry entry must have a baseUrl");
assert.ok(entry.modelsUrl, "registry entry must have a modelsUrl");
assert.ok(
entry.models && entry.models.length > 0,
"registry entry must list at least one model"
);
assert.ok(
entry.models.some((m: { id: string }) => m.id === "auto:free"),
"registry must include auto:free model"
);
assert.ok(
entry.models.some((m: { id: string }) => m.id === "mimo-v2.5-pro"),
"registry must include mimo-v2.5-pro"
);
});
it("is resolvable through the static catalog for managed connections", async () => {
const { resolveStaticProviderCatalogEntry } =
await import("../../src/lib/providers/catalog.ts");
const entry = resolveStaticProviderCatalogEntry("bazaarlink");
assert.ok(entry, "bazaarlink must resolve through the static provider catalog");
assert.ok(entry.id, "bazaarlink", "resolved entry id must match");
assert.equal(entry.category, "apikey", "bazaarlink must be in the apikey category");
});
it("passes isManagedProviderConnectionId check so connections can be created", async () => {
const { isManagedProviderConnectionId } = await import("../../src/lib/providers/catalog.ts");
const result = isManagedProviderConnectionId("bazaarlink");
assert.equal(result, true, "bazaarlink must pass isManagedProviderConnectionId");
});
it("supports bulk API key add (not excluded)", async () => {
const { supportsBulkApiKey } = await import("../../src/shared/constants/providers.ts");
const result = supportsBulkApiKey("bazaarlink");
assert.equal(result, true, "bazaarlink must support bulk API key add");
});
});