feat(providers): integrate audited free-tier gateways (#9210)

* feat(providers): add Zylo UnoRouter and Poolside registries

* feat(providers): integrate audited free-tier gateways

* feat: add wave2 free-tier provider registries

* feat(providers): add Mixlayer Speka and TokenReply registries

* feat: add wave 2 free-tier provider registries

* fix: align meganova provider slug

* feat(providers): integrate wave2 free-tier gateways

* feat(providers): add Wave 3-A free-tier registries

* feat(providers): add HelyxAI Auriko and Poixe registries

* feat(providers): add Naga AI and Chat Oripe registries

* feat(providers): integrate wave3 free-tier gateways

* feat(providers): add FreeInference registry

* feat(providers): add Free.ai registry

* feat(providers): integrate wave4 free-tier gateways

* docs: synchronize provider and free-tier inventories

* refactor(providers): split audited gateway catalog

* feat(providers): add audited Void AI and HelixMind gateways

* feat(providers): finalize audited free-tier integration

* test(providers): update APIKEY split count to 229 after rebase onto release/v3.8.50

The rebase merged the release catalog (201 APIKEY providers) with the PR's
28 free-tier additions, yielding 229 total. Correct the characterization
count so the partition assertion reflects the true merged state.

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: backryun <bakryun0718@proton.me>
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-08-12 16:19:25 -03:00
committed by GitHub
parent f6ccd3cf9f
commit ecc89eef14
345 changed files with 9108 additions and 9012 deletions

View File

@@ -77,13 +77,21 @@ test("omniroute_agent_skills_list({category:'cli'}) returns exactly 21 entries",
assert.ok(result.skills.every((s: { category: string }) => s.category === "cli"));
});
test("omniroute_agent_skills_list({category:'config'}) returns exactly 1 entry", async () => {
const result = await agentSkillTools.omniroute_agent_skills_list.handler({ category: "config" });
assert.equal(result.count, 1, `Expected 1 config skill but got ${result.count}`);
assert.ok(result.skills.every((s: { category: string }) => s.category === "config"));
});
test("omniroute_agent_skills_list result includes coverage shape", async () => {
const result = await agentSkillTools.omniroute_agent_skills_list.handler({});
assert.ok(result.coverage != null, "coverage should be present");
assert.ok(typeof result.coverage.api === "object");
assert.ok(typeof result.coverage.cli === "object");
assert.ok(typeof result.coverage.config === "object");
assert.equal(result.coverage.api.total, 23);
assert.equal(result.coverage.cli.total, 21);
assert.equal(result.coverage.config.total, 1);
assert.ok(typeof result.coverage.totalSkills === "number");
assert.ok(typeof result.coverage.generatedAt === "string");
});
@@ -94,7 +102,7 @@ test("omniroute_agent_skills_list skill entries have required fields", async ()
assert.ok(typeof first.id === "string" && first.id.length > 0);
assert.ok(typeof first.name === "string" && first.name.length > 0);
assert.ok(typeof first.description === "string");
assert.ok(first.category === "api" || first.category === "cli");
assert.ok(first.category === "api" || first.category === "cli" || first.category === "config");
assert.ok(typeof first.area === "string");
assert.ok(typeof first.rawUrl === "string");
assert.ok(typeof first.githubUrl === "string");
@@ -105,6 +113,11 @@ test("AgentSkillsListSchema parses valid category filter", () => {
assert.equal(parsed.category, "api");
});
test("AgentSkillsListSchema parses config category filter", () => {
const parsed = AgentSkillsListSchema.parse({ category: "config" });
assert.equal(parsed.category, "config");
});
test("AgentSkillsListSchema rejects invalid category", () => {
assert.throws(() => AgentSkillsListSchema.parse({ category: "unknown" }));
});
@@ -140,6 +153,14 @@ test("omniroute_agent_skills_get({id:'cli-serve'}) resolves correct cli skill me
assert.ok(typeof skill!.name === "string" && skill!.name.length > 0);
});
test("omniroute_agent_skills_get({id:'config-codex-cli'}) resolves config skill metadata", async () => {
const { getSkillById } = await import("../../src/lib/agentSkills/catalog.ts");
const skill = getSkillById("config-codex-cli");
assert.ok(skill != null, "config-codex-cli should exist in catalog");
assert.equal(skill!.id, "config-codex-cli");
assert.equal(skill!.category, "config");
});
test("omniroute_agent_skills_get with invalid id throws Error", async () => {
await assert.rejects(
() => agentSkillTools.omniroute_agent_skills_get.handler({ id: "non-existent-skill-xyz" }),
@@ -167,14 +188,17 @@ test("omniroute_agent_skills_coverage({}) returns coverage shape", async () => {
assert.ok(result != null);
assert.ok(typeof result.api === "object");
assert.ok(typeof result.cli === "object");
assert.ok(typeof result.config === "object");
assert.equal(result.api.total, 23);
assert.equal(result.cli.total, 21);
assert.equal(result.config.total, 1);
assert.ok(typeof result.api.have === "number");
assert.ok(typeof result.cli.have === "number");
assert.ok(result.api.have >= 0 && result.api.have <= 23);
assert.ok(result.cli.have >= 0 && result.cli.have <= 21);
assert.ok(result.config.have >= 0 && result.config.have <= 1);
assert.ok(typeof result.totalSkills === "number");
assert.equal(result.totalSkills, result.api.have + result.cli.have + (result.config?.have ?? 0));
assert.equal(result.totalSkills, result.api.have + result.cli.have + result.config.have);
assert.ok(typeof result.generatedAt === "string");
// Validate ISO datetime format
assert.ok(!isNaN(Date.parse(result.generatedAt)), "generatedAt should be valid ISO datetime");

View File

@@ -9,6 +9,7 @@ const {
computeCoverage,
refreshCatalog,
API_SKILL_IDS,
CONFIG_SKILL_IDS,
CLI_SKILL_IDS,
} = await import("../../src/lib/agentSkills/catalog.ts");
const agentSkillsConstants = await import("../../src/shared/constants/agentSkills.ts");
@@ -25,11 +26,11 @@ test("API_SKILL_IDS has exactly 23 entries", () => {
assert.equal(API_SKILL_IDS.length, 23);
});
test("CLI_SKILL_IDS has exactly 20 entries", () => {
test("CLI_SKILL_IDS has exactly 21 entries", () => {
assert.equal(CLI_SKILL_IDS.length, 21);
});
test("getCatalog() contains exactly 22 api skills", () => {
test("getCatalog() contains exactly 23 api skills", () => {
const apiSkills = getCatalog().filter((s) => s.category === "api");
assert.equal(apiSkills.length, 23);
});
@@ -39,6 +40,15 @@ test("getCatalog() contains exactly 21 cli skills", () => {
assert.equal(cliSkills.length, 21);
});
test("CONFIG_SKILL_IDS has exactly 1 entry", () => {
assert.equal(CONFIG_SKILL_IDS.length, 1);
});
test("getCatalog() contains exactly 1 config skill", () => {
const configSkills = getCatalog().filter((s) => s.category === "config");
assert.equal(configSkills.length, 1);
});
// ─── ID format ────────────────────────────────────────────────────────────────
test("all skill IDs match regex ^[a-z][a-z0-9-]*$", () => {
@@ -218,6 +228,11 @@ test("computeCoverage() returns valid SkillCoverage shape", () => {
assert.ok(typeof cov.cli.have === "number");
assert.ok(cov.cli.have >= 0 && cov.cli.have <= 21);
assert.ok(typeof cov.config === "object");
assert.equal(cov.config.total, 1);
assert.ok(typeof cov.config.have === "number");
assert.ok(cov.config.have >= 0 && cov.config.have <= 1);
assert.equal(cov.totalSkills, cov.api.have + cov.cli.have + (cov.config?.have ?? 0));
// generatedAt must be a valid ISO datetime string
@@ -227,7 +242,7 @@ test("computeCoverage() returns valid SkillCoverage shape", () => {
);
});
test("computeCoverage() api.have + cli.have = totalSkills", () => {
test("computeCoverage() category totals add up to totalSkills", () => {
const cov = computeCoverage();
assert.equal(cov.totalSkills, cov.api.have + cov.cli.have + (cov.config?.have ?? 0));
});

View File

@@ -5,7 +5,7 @@
* Auth tested via requireManagementAuth with live DB in temp directory.
*
* Coverage goals:
* - GET /api/agent-skills — happy path (43 skills), filters, invalid category
* - GET /api/agent-skills — happy path (45 skills), filters, invalid category
* - GET /api/agent-skills/[id] — found, 404 not found
* - GET /api/agent-skills/[id]/raw — found, 404 not found, 502 on GitHub failure
* - GET /api/agent-skills/coverage — happy path
@@ -55,7 +55,7 @@ function makeRequest(
method: string,
url: string,
body?: unknown,
headers: Record<string, string> = {},
headers: Record<string, string> = {}
): Request {
return new Request(url, {
method,
@@ -120,7 +120,10 @@ test("GET /api/agent-skills?category=api — returns 23 api skills", async () =>
assert.equal(res.status, 200);
const body = (await res.json()) as { skills: Array<{ category: string }>; count: number };
assert.equal(body.count, 23);
assert.ok(body.skills.every((s) => s.category === "api"), "All skills should be api category");
assert.ok(
body.skills.every((s) => s.category === "api"),
"All skills should be api category"
);
});
test("GET /api/agent-skills?category=cli — returns 21 cli skills", async () => {
@@ -130,7 +133,23 @@ test("GET /api/agent-skills?category=cli — returns 21 cli skills", async () =>
assert.equal(res.status, 200);
const body = (await res.json()) as { skills: Array<{ category: string }>; count: number };
assert.equal(body.count, 21);
assert.ok(body.skills.every((s) => s.category === "cli"), "All skills should be cli category");
assert.ok(
body.skills.every((s) => s.category === "cli"),
"All skills should be cli category"
);
});
test("GET /api/agent-skills?category=config — returns 1 config skill", async () => {
const req = makeRequest("GET", "http://localhost/api/agent-skills?category=config");
const res = await listRoute.GET(req);
assert.equal(res.status, 200);
const body = (await res.json()) as { skills: Array<{ category: string }>; count: number };
assert.equal(body.count, 1);
assert.ok(
body.skills.every((s) => s.category === "config"),
"All skills should be config category"
);
});
test("GET /api/agent-skills?area=providers — returns only providers area skills", async () => {
@@ -154,7 +173,7 @@ test("GET /api/agent-skills?category=invalid — returns 400 with sanitized erro
// Hard Rule #12: no stack trace exposure
assert.ok(
!body.error.message.match(/\bat \/|\bat file:\/\//),
`Error message must not contain stack trace: "${body.error.message}"`,
`Error message must not contain stack trace: "${body.error.message}"`
);
});
@@ -192,7 +211,7 @@ test("GET /api/agent-skills/[id] — returns 404 with sanitized error for unknow
// Hard Rule #12: no stack trace exposure
assert.ok(
!body.error.message.match(/\bat \/|\bat file:\/\//),
`Error message must not contain stack trace: "${body.error.message}"`,
`Error message must not contain stack trace: "${body.error.message}"`
);
});
@@ -213,7 +232,7 @@ test("GET /api/agent-skills/[id]/raw — returns 404 with sanitized error for un
// Hard Rule #12: no stack trace exposure
assert.ok(
!body.error.message.match(/\bat \/|\bat file:\/\//),
`Error message must not contain stack trace: "${body.error.message}"`,
`Error message must not contain stack trace: "${body.error.message}"`
);
});
@@ -230,14 +249,14 @@ test("GET /api/agent-skills/[id]/raw — returns markdown or 502 for valid id (n
// Either 200 (network available) or 502 (no network) is acceptable
assert.ok(
res.status === 200 || res.status === 502 || res.status === 500,
`Expected 200, 502, or 500 but got ${res.status}`,
`Expected 200, 502, or 500 but got ${res.status}`
);
if (res.status === 200) {
const contentType = res.headers.get("content-type") ?? "";
assert.ok(
contentType.includes("text/markdown"),
`Expected text/markdown content-type, got: ${contentType}`,
`Expected text/markdown content-type, got: ${contentType}`
);
const cacheControl = res.headers.get("cache-control") ?? "";
assert.ok(cacheControl.includes("max-age=3600"), "Cache-Control should include max-age=3600");
@@ -247,7 +266,7 @@ test("GET /api/agent-skills/[id]/raw — returns markdown or 502 for valid id (n
assert.ok(body.error);
assert.ok(
!body.error.message.match(/\bat \/|\bat file:\/\//),
`Error message must not contain stack trace: "${body.error.message}"`,
`Error message must not contain stack trace: "${body.error.message}"`
);
}
});
@@ -291,7 +310,7 @@ test("POST /api/agent-skills/generate — 401 when auth is required and no token
// requireManagementAuth returns 401 or 403 when auth is required and no token
assert.ok(
res.status === 401 || res.status === 403,
`Expected 401 or 403 without auth, got ${res.status}`,
`Expected 401 or 403 without auth, got ${res.status}`
);
const body = (await res.json()) as { error: { message: string } | string };
@@ -300,7 +319,7 @@ test("POST /api/agent-skills/generate — 401 when auth is required and no token
typeof body.error === "string" ? body.error : (body.error as { message: string }).message;
assert.ok(
!errorMsg.match(/\bat \/|\bat file:\/\//),
`Error message must not contain stack trace: "${errorMsg}"`,
`Error message must not contain stack trace: "${errorMsg}"`
);
});
@@ -318,7 +337,7 @@ test("POST /api/agent-skills/generate — 400 when body is invalid (non-boolean
// But with invalid body, 400 should come first
assert.ok(
res.status === 400 || res.status === 503,
`Expected 400 (bad body) or 503 (generator unavailable), got ${res.status}`,
`Expected 400 (bad body) or 503 (generator unavailable), got ${res.status}`
);
const body = (await res.json()) as { error: { message: string } };
@@ -326,7 +345,7 @@ test("POST /api/agent-skills/generate — 400 when body is invalid (non-boolean
// Hard Rule #12: no stack trace exposure
assert.ok(
!body.error.message.match(/\bat \/|\bat file:\/\//),
`Error message must not contain stack trace: "${body.error.message}"`,
`Error message must not contain stack trace: "${body.error.message}"`
);
});
@@ -345,7 +364,7 @@ test("POST /api/agent-skills/generate — 503 when generator module unavailable
// Both are valid depending on merge state.
assert.ok(
res.status === 200 || res.status === 503,
`Expected 200 (generator available) or 503 (generator unavailable), got ${res.status}`,
`Expected 200 (generator available) or 503 (generator unavailable), got ${res.status}`
);
const body = (await res.json()) as Record<string, unknown>;
@@ -355,7 +374,7 @@ test("POST /api/agent-skills/generate — 503 when generator module unavailable
// Hard Rule #12: no stack trace exposure
assert.ok(
!err.message.match(/\bat \/|\bat file:\/\//),
`503 error message must not contain stack trace: "${err.message}"`,
`503 error message must not contain stack trace: "${err.message}"`
);
} else {
// 200: body should look like a GeneratorReport
@@ -380,7 +399,7 @@ test("POST /api/agent-skills/generate — 400 when request body is not JSON", as
// Hard Rule #12: no stack trace exposure
assert.ok(
!body.error.message.match(/\bat \/|\bat file:\/\//),
`Error message must not contain stack trace: "${body.error.message}"`,
`Error message must not contain stack trace: "${body.error.message}"`
);
});
@@ -394,23 +413,20 @@ test("Hard Rule #12: all error responses contain sanitized messages (no 'at /' p
// Collect error responses from various bad inputs
const errorResponses: Response[] = [
// Invalid category query
await listRoute.GET(
makeRequest("GET", "http://localhost/api/agent-skills?category=bad-val"),
),
await listRoute.GET(makeRequest("GET", "http://localhost/api/agent-skills?category=bad-val")),
// Unknown skill id
await idRoute.GET(makeRequest("GET", "http://localhost/api/agent-skills/unknown-id"), {
params: Promise.resolve({ id: "unknown-id" }),
}),
// Unknown raw skill id
await rawRoute.GET(
makeRequest("GET", "http://localhost/api/agent-skills/unknown-id/raw"),
{ params: Promise.resolve({ id: "unknown-id" }) },
),
await rawRoute.GET(makeRequest("GET", "http://localhost/api/agent-skills/unknown-id/raw"), {
params: Promise.resolve({ id: "unknown-id" }),
}),
// Invalid generate body (non-boolean)
await generateRoute.POST(
makeRequest("POST", "http://localhost/api/agent-skills/generate", {
dryRun: 42,
}),
})
),
];
@@ -419,14 +435,14 @@ test("Hard Rule #12: all error responses contain sanitized messages (no 'at /' p
const contentType = res.headers.get("content-type") ?? "";
assert.ok(
contentType.includes("application/json") || contentType.includes("json"),
`Error response must be JSON, got content-type: ${contentType}`,
`Error response must be JSON, got content-type: ${contentType}`
);
const body = (await res.json()) as { error?: { message?: string } };
const message = body?.error?.message ?? "";
assert.ok(
!message.match(/\bat \/|\bat file:\/\//),
`Stack trace detected in error response (status ${res.status}): "${message}"`,
`Stack trace detected in error response (status ${res.status}): "${message}"`
);
}
});

View File

@@ -136,8 +136,9 @@ test("AgentSkillSchema — .parse throws on invalid input", () => {
test("SkillCoverageSchema — valid coverage parses successfully", () => {
const input = {
api: { have: 23, total: 23 },
cli: { have: 20, total: 20 },
totalSkills: 42,
cli: { have: 21, total: 21 },
config: { have: 1, total: 1 },
totalSkills: 45,
generatedAt: new Date().toISOString(),
};
const result = SkillCoverageSchema.safeParse(input);
@@ -147,8 +148,9 @@ test("SkillCoverageSchema — valid coverage parses successfully", () => {
test("SkillCoverageSchema — wrong total literal (api.total=21) fails", () => {
const input = {
api: { have: 21, total: 21 },
cli: { have: 20, total: 20 },
totalSkills: 41,
cli: { have: 21, total: 21 },
config: { have: 1, total: 1 },
totalSkills: 44,
generatedAt: new Date().toISOString(),
};
const result = SkillCoverageSchema.safeParse(input);
@@ -158,8 +160,9 @@ test("SkillCoverageSchema — wrong total literal (api.total=21) fails", () => {
test("SkillCoverageSchema — wrong total literal (cli.total=19) fails", () => {
const input = {
api: { have: 23, total: 23 },
cli: { have: 19, total: 19 },
totalSkills: 41,
cli: { have: 20, total: 20 },
config: { have: 1, total: 1 },
totalSkills: 44,
generatedAt: new Date().toISOString(),
};
const result = SkillCoverageSchema.safeParse(input);
@@ -169,8 +172,9 @@ test("SkillCoverageSchema — wrong total literal (cli.total=19) fails", () => {
test("SkillCoverageSchema — invalid datetime fails", () => {
const input = {
api: { have: 23, total: 23 },
cli: { have: 20, total: 20 },
totalSkills: 42,
cli: { have: 21, total: 21 },
config: { have: 1, total: 1 },
totalSkills: 45,
generatedAt: "not-a-date",
};
const result = SkillCoverageSchema.safeParse(input);
@@ -180,8 +184,9 @@ test("SkillCoverageSchema — invalid datetime fails", () => {
test("SkillCoverageSchema — negative have value fails", () => {
const input = {
api: { have: -1, total: 23 },
cli: { have: 20, total: 20 },
totalSkills: 42,
cli: { have: 21, total: 21 },
config: { have: 1, total: 1 },
totalSkills: 45,
generatedAt: new Date().toISOString(),
};
const result = SkillCoverageSchema.safeParse(input);
@@ -207,6 +212,14 @@ test("ListQuerySchema — valid category parses successfully", () => {
}
});
test("ListQuerySchema — config category parses successfully", () => {
const result = ListQuerySchema.safeParse({ category: "config" });
assert.equal(result.success, true);
if (result.success) {
assert.equal(result.data.category, "config");
}
});
test("ListQuerySchema — invalid category fails", () => {
const result = ListQuerySchema.safeParse({ category: "invalid" });
assert.equal(result.success, false);

View File

@@ -8,6 +8,9 @@ import {
tallyDrift,
readProviderTotal,
countLocales,
readMcpFactsFromSource,
listLocalizedDocs,
makeRequiredCountsValidator,
} from "../../scripts/check/check-docs-counts-sync.mjs";
// Explicit types for the .mjs exports — keep the test at 0 no-explicit-any warnings.
@@ -24,6 +27,11 @@ const tally = tallyDrift as (
) => { strict: number; soft: number; lines: string[] };
const readTotal = readProviderTotal as () => number;
const locales = countLocales as () => number;
const mcpFacts = readMcpFactsFromSource as () => { tools: number; scopes: number } | null;
const localizedDocs = listLocalizedDocs as (relativePath: string) => string[];
const requireCounts = makeRequiredCountsValidator as (
requirements: { label: string; value: number }[]
) => (content: string) => { ok: boolean; detail: string };
const here = path.dirname(fileURLToPath(import.meta.url));
const GATE = path.resolve(here, "../../scripts/check/check-docs-counts-sync.mjs");
@@ -85,13 +93,38 @@ test("a missing file (null content) registers drift, not a crash", () => {
// --- live source readers (smoke) -----------------------------------------------------
test("readProviderTotal reads a real, positive total from the catalog", () => {
assert.ok(readTotal() > 100, "provider catalog total should be > 100");
assert.ok(readTotal() >= 300, "live provider catalog total should be at least 300");
});
test("countLocales reads a real, positive locale count from config/i18n.json", () => {
assert.ok(locales() >= 40, "i18n config should define at least 40 locales");
});
test("source-only MCP fallback matches the canonical inventory and scope union", () => {
assert.deepEqual(mcpFacts(), { tools: 107, scopes: 32 });
});
test("localized-doc discovery returns every locale root document", () => {
const readmes = localizedDocs("README.md");
assert.equal(readmes.length, 42);
assert.ok(readmes.includes("docs/i18n/pt-BR/README.md"));
assert.ok(readmes.includes("docs/i18n/zh-CN/README.md"));
});
test("required-count validator reports precisely which live markers are missing", () => {
const validate = requireCounts([
{ label: "providers", value: 327 },
{ label: "MCP tools", value: 107 },
{ label: "MCP scopes", value: 32 },
]);
assert.equal(validate("327 providers; 107 tools; 32 scopes").ok, true);
const stale = validate("290 providers; 104 tools; 31 scopes");
assert.equal(stale.ok, false);
assert.match(stale.detail, /providers=327/);
assert.match(stale.detail, /MCP tools=107/);
assert.match(stale.detail, /MCP scopes=32/);
});
// --- live gate smoke -----------------------------------------------------------------
test("the gate exits 0 against the current (synced) repo state", () => {
@@ -105,6 +138,7 @@ test("the gate exits 0 against the current (synced) repo state", () => {
// down to 1.37B, because no gate watched that number.
import {
checkFreeTierHeadline,
checkFreeTierInventory,
extractHeadlineClaims,
} from "../../scripts/check/check-docs-counts-sync.mjs";
@@ -146,9 +180,27 @@ test("free-tier gate passes when a file carries no headline at all", () => {
assert.equal(checkHeadline("no figures here", TOTALS).ok, true);
});
const checkInventory = checkFreeTierInventory as (
content: string,
totals: { pools: number; models: number }
) => { ok: boolean; detail: string };
test("free-tier inventory gate accepts the live pool/model counts", () => {
assert.equal(
checkInventory("43 provider pools / 522 model budget entries", { pools: 43, models: 522 }).ok,
true
);
});
test("free-tier inventory gate rejects stale model counts", () => {
const result = checkInventory("43 provider pools / 516 models", { pools: 43, models: 522 });
assert.equal(result.ok, false);
assert.match(result.detail, /live catalog has 43 pools \/ 522 model budget entries/);
});
// --- Generic numeric-claim gate (engines / MCP tools / scopes / CLI) --------
// Extends the same drift guard to the counts that silently drifted in v3.8.49:
// 11→12 engines, 94→104 MCP tools, 30→31 scopes, 26→33 CLI tools.
// 11→12 engines, 94→107 MCP tools, 30→32 scopes, 26→33 CLI tools.
import { makeNumberClaimValidator } from "../../scripts/check/check-docs-counts-sync.mjs";
const makeValidator = makeNumberClaimValidator as (
@@ -157,19 +209,19 @@ const makeValidator = makeNumberClaimValidator as (
) => (content: string) => { ok: boolean; detail: string };
test("MCP-tools gate accepts the aggregate and rejects a stale one", () => {
const v = makeValidator(104, {
const v = makeValidator(107, {
what: "MCP tools",
pattern: /(\d+) tools/gi,
skipBefore: /(tools?|definitions?)\s*\(\s*$/i,
skipAfter: /^\s*\(\d+ CLI/,
});
assert.equal(v("MCP Server (104 tools)").ok, true);
assert.equal(v("with 104 tools total").ok, true);
assert.equal(v("MCP Server (107 tools)").ok, true);
assert.equal(v("with 107 tools total").ok, true);
assert.equal(v("MCP Server (94 tools)").ok, false);
});
test("MCP-tools gate ignores per-module counts and the CLI catalog total", () => {
const v = makeValidator(104, {
const v = makeValidator(107, {
what: "MCP tools",
pattern: /(\d+) tools/gi,
skipBefore: /(tools?|definitions?)\s*\(\s*$/i,

View File

@@ -0,0 +1,101 @@
import assert from "node:assert/strict";
import test from "node:test";
import { deriveConfigFromRegistryModelsUrl } from "../../src/app/api/providers/[id]/models/discoveryConfig.ts";
const { REGISTRY } = await import("../../open-sse/config/providerRegistry.ts");
const { DefaultExecutor, getExecutor, hasSpecializedExecutor } =
await import("../../open-sse/executors/index.ts");
const { PROVIDER_ENDPOINTS } = await import("../../src/shared/constants/config.ts");
const { isValidModel } = await import("../../src/shared/constants/models.ts");
const { AGGREGATOR_PROVIDER_IDS } = await import("../../src/shared/constants/providers.ts");
const { APIKEY_PROVIDERS } = await import("../../src/shared/constants/providers/apikey/index.ts");
const providers = [
{
id: "void-ai",
endpoint: "https://api.voidai.app/v1/chat/completions",
modelsUrl: "https://api.voidai.app/v1/models",
hasFree: true,
},
{
id: "helixmind",
endpoint: "https://helixmind.online/v1/chat/completions",
modelsUrl: "https://helixmind.online/v1/models",
hasFree: false,
},
] as const;
for (const { id, endpoint, modelsUrl, hasFree } of providers) {
test(`${id} is fully wired through the public provider interfaces`, () => {
const registry = REGISTRY[id];
const metadata = APIKEY_PROVIDERS[id];
assert.ok(registry);
assert.ok(metadata);
assert.equal(registry.id, id);
assert.equal(registry.alias, id);
assert.equal(registry.format, "openai");
assert.equal(registry.executor, "default");
assert.equal(registry.authType, "apikey");
assert.equal(registry.authHeader, "bearer");
assert.equal(registry.baseUrl, endpoint);
assert.equal(registry.modelsUrl, modelsUrl);
assert.equal(registry.passthroughModels, true);
assert.deepEqual(registry.models, []);
assert.equal(PROVIDER_ENDPOINTS[id], endpoint);
assert.equal(metadata.id, id);
assert.equal(metadata.alias, id);
assert.equal(metadata.hasFree, hasFree);
assert.equal(metadata.passthroughModels, true);
assert.equal(AGGREGATOR_PROVIDER_IDS.has(id), true);
assert.equal(hasSpecializedExecutor(id), false);
const executor = getExecutor(id);
assert.ok(executor instanceof DefaultExecutor);
assert.equal(executor.buildUrl("live-model", false), endpoint);
assert.equal(isValidModel(id, "future/live-catalog-model"), true);
const discovery = deriveConfigFromRegistryModelsUrl(id);
assert.ok(discovery);
assert.equal(discovery.url, modelsUrl);
assert.deepEqual(discovery.parseResponse({ object: "list", data: [{ id: "live-model" }] }), [
{ id: "live-model" },
]);
});
}
test("Void AI metadata keeps the free-plan signal conditional", () => {
const metadata = APIKEY_PROVIDERS["void-ai"];
assert.match(metadata.freeNote ?? "", /free plan/i);
assert.match(metadata.freeNote ?? "", /conditional/i);
assert.match(metadata.freeNote ?? "", /no numeric quota/i);
assert.match(metadata.apiHint ?? "", /authentication.*account.*terms/i);
});
test("HelixMind exposes its verified alternate API surfaces without reviving old quota claims", () => {
const registry = REGISTRY.helixmind;
const metadata = APIKEY_PROVIDERS.helixmind;
assert.equal(registry.responsesBaseUrl, "https://helixmind.online/v1/responses");
assert.deepEqual(registry.alternateFormats, [
{
format: "claude",
baseUrl: "https://helixmind.online/v1/messages",
authHeader: "x-api-key",
label: "Anthropic-compatible",
},
{
format: "openai-responses",
baseUrl: "https://helixmind.online/v1/responses",
authHeader: "bearer",
label: "OpenAI Responses",
},
]);
assert.match(metadata.freeNote ?? "", /3 RPM\/50 RPD/i);
assert.match(metadata.freeNote ?? "", /no-card/i);
assert.match(metadata.freeNote ?? "", /not confirmed/i);
assert.doesNotMatch(metadata.freeNote ?? "", /free forever|unlimited/i);
});

View File

@@ -3,7 +3,7 @@
*
* Verifies:
* - Return shape matches §3.7 contract
* - Markdown table contains all 44 skill IDs
* - Markdown table contains all 45 skill IDs
* - Coverage bounds are within declared totals
* - metadata.source === "agent-skills-catalog"
* - metadata.generatedAt is an ISO datetime string
@@ -13,7 +13,11 @@ import assert from "node:assert/strict";
import { test } from "node:test";
import type { A2ATask } from "../../src/lib/a2a/taskManager.js";
import { executeListCapabilities } from "../../src/lib/a2a/skills/listCapabilities.js";
import { API_SKILL_IDS, CLI_SKILL_IDS } from "../../src/lib/agentSkills/catalog.js";
import {
API_SKILL_IDS,
CLI_SKILL_IDS,
CONFIG_SKILL_IDS,
} from "../../src/lib/agentSkills/catalog.js";
// Minimal stub — executeListCapabilities only receives the task arg but does not use it
const stubTask = {} as A2ATask;
@@ -31,20 +35,21 @@ test("executeListCapabilities returns shape matching §3.7 contract", async () =
const { metadata } = result;
assert.ok(metadata, "metadata exists");
assert.equal(metadata.source, "agent-skills-catalog", "metadata.source matches");
assert.equal(metadata.totalSkills, 45, "metadata.totalSkills === 45 (44 + config)");
assert.equal(metadata.totalSkills, 45, "metadata.totalSkills === 45");
assert.ok(metadata.coverage, "metadata.coverage exists");
assert.ok(metadata.coverage.api, "metadata.coverage.api exists");
assert.ok(metadata.coverage.cli, "metadata.coverage.cli exists");
assert.equal(metadata.coverage.api.total, 23, "api.total === 23");
assert.equal(metadata.coverage.cli.total, 20, "cli.total === 20");
assert.equal(metadata.coverage.cli.total, 21, "cli.total === 21");
assert.equal(metadata.coverage.config.total, 1, "config.total === 1");
});
test("executeListCapabilities markdown table contains all 44 API+CLI skill IDs", async () => {
test("executeListCapabilities markdown table contains all 45 skill IDs", async () => {
const result = await executeListCapabilities(stubTask);
const content = result.artifacts[0].content;
const allIds = [...API_SKILL_IDS, ...CLI_SKILL_IDS] as string[];
assert.equal(allIds.length, 44, "API+CLI catalog declares 44 skill IDs");
const allIds = [...API_SKILL_IDS, ...CLI_SKILL_IDS, ...CONFIG_SKILL_IDS] as string[];
assert.equal(allIds.length, 45, "catalog declares 45 skill IDs");
for (const id of allIds) {
assert.ok(content.includes(id), `Markdown table missing skill ID: ${id}`);
@@ -65,6 +70,13 @@ test("metadata.coverage.cli.have is within [0, 21]", async () => {
assert.ok(cli.have <= 21, "cli.have <= 21");
});
test("metadata.coverage.config.have is within [0, 1]", async () => {
const result = await executeListCapabilities(stubTask);
const { config } = result.metadata.coverage;
assert.ok(config.have >= 0, "config.have >= 0");
assert.ok(config.have <= 1, "config.have <= 1");
});
test("metadata.generatedAt is a valid ISO datetime", async () => {
const result = await executeListCapabilities(stubTask);
const { generatedAt } = result.metadata;