Files
OmniRoute/tests/unit/usage-command-json-format.test.ts
Praveen K Palaniswamy 65e81158ab fix(ollama): route models by advertised capability (#11088)
Landed with the design call resolved per the owner's pick — **option 1**: the synced store is now endpoint-agnostic (persistDiscoveredModels and managedModelImport no longer drop non-chat models at write time), and chat selectability moved to read time (auto-pool expansion in autoStrategy applies filterChatSelectableModels; the models-route projection already had its chatOnly filter). Your discovery test now passes end-to-end (3/3): /api/show capabilities persist per connection and image/embedding requests route through the advertising host.

Reconciliation notes: conflicted areas merged onto the current tip (adobe discovery import, requestedModel preflight signature, resolvedProvider fast-path coexists with the synced-route override — explicit resolution wins); carried base-red drains (#10055 memoization, #11071 test variants) dropped as already-landed; the managed-model-import exclusion test was propagated to the new contract (image/video models persist; the read filter still hides them from chat pickers — pinned by a new assertion). Full battery: 205/206 focused (the one red is a confirmed periodic-timer timing flake on the loaded devbox — 20/20 isolated), autoCombo vitest 30/30, combo suites 46/46, gates + typecheck clean.

Thank you @yourspraveen — the capability probe + routing design was right; it just needed the store contract opened up. Fixes #11087.
2026-08-23 11:45:01 -03:00

163 lines
5.8 KiB
TypeScript

/**
* #8 (OmniCopilot) — the usage command answered `text/plain`, which a UI cannot
* parse safely. The structured form (`?format=json`) returns the same
* `ApiKeyUsageLimitStatus` + `UsageSnapshot` the text is rendered from.
*
* These tests pin the contract the extension depends on: JSON when asked,
* text by default, the 403 as a structured reason rather than a bare string,
* and an error body that never carries a stack trace.
*/
import test from "node:test";
import assert from "node:assert/strict";
import { handleInternalUsageCommandHttpRequest } from "../../src/lib/usage/internalUsageCommand";
const NOW = Date.parse("2026-08-19T12:00:00.000Z");
const LIMIT_STATUS = {
enabled: true,
dailyLimitUsd: 5,
weeklyLimitUsd: 20,
dailySpentUsd: 1.25,
weeklySpentUsd: 8,
dailyWindowStartIso: "2026-08-19T03:00:00.000Z",
dailyResetAtIso: "2026-08-20T03:00:00.000Z",
weeklyWindowStartIso: "2026-08-16T03:00:00.000Z",
weeklyResetAtIso: "2026-08-23T03:00:00.000Z",
dailyExceeded: false,
weeklyExceeded: false,
};
function allowedDeps(overrides: Record<string, unknown> = {}) {
return {
now: () => NOW,
isValidApiKey: async (apiKey: string) => apiKey === "sk-allowed",
getApiKeyMetadata: async () => ({
id: "key-allowed",
name: "panel key",
allowUsageCommand: true,
usageLimitEnabled: true,
}),
getProviderConnections: async () => [
{ id: "conn-claude", provider: "claude", isActive: true },
{ id: "conn-codex", provider: "codex", isActive: true },
],
getAllProviderLimitsCache: () => ({
"conn-claude": {
plan: "Claude Max",
quotas: {
weekly: { used: 25, total: 100, remaining: 75, resetAt: "2026-08-25T03:00:00.000Z" },
},
message: null,
fetchedAt: new Date(NOW).toISOString(),
},
"conn-codex": {
plan: "Codex Pro",
quotas: {
weekly: { used: 9, total: 100, remaining: 91, resetAt: "2026-08-24T03:00:00.000Z" },
},
message: null,
fetchedAt: new Date(NOW).toISOString(),
},
}),
getProviderConnectionById: async () => null,
getProviderLimitsCache: () => null,
getQuotaPolicy: async () => ({ defaultThresholdPercent: 0, providerWindowDefaults: {} }),
getApiKeyUsageLimitStatus: async () => LIMIT_STATUS,
...overrides,
};
}
test("om-usage ?format=json returns the structured personal + provider quota", async () => {
const response = await handleInternalUsageCommandHttpRequest(
new Request("http://localhost/api/usage/om-usage?format=json", {
headers: { Authorization: "Bearer sk-allowed" },
}),
allowedDeps()
);
assert.equal(response.status, 200);
assert.match(response.headers.get("content-type") ?? "", /application\/json/);
const body = (await response.json()) as {
allowed: boolean;
personal: { dailySpentUsd: number } | null;
provider: { provider: string; connectionId: string } | null;
};
assert.equal(body.allowed, true);
assert.equal(body.personal?.dailySpentUsd, 1.25);
assert.equal(body.provider?.provider, "claude");
assert.equal(body.provider?.connectionId, "conn-claude");
});
test("om-usage without ?format stays text/plain (the historical contract)", async () => {
const response = await handleInternalUsageCommandHttpRequest(
new Request("http://localhost/api/usage/om-usage", {
headers: { Authorization: "Bearer sk-allowed" },
}),
allowedDeps()
);
assert.equal(response.status, 200);
assert.match(response.headers.get("content-type") ?? "", /text\/plain/);
const text = await response.text();
assert.match(text, /Personal quota/);
assert.match(text, /Provider quota/);
});
test("om-usage ?format=json returns every connection under providers[], not just the selected one", async () => {
// #11191 — a panel needs Codex + Claude side by side; the single `provider`
// pick is a terminal presentation choice, the collector had them all.
const response = await handleInternalUsageCommandHttpRequest(
new Request("http://localhost/api/usage/om-usage?format=json", {
headers: { Authorization: "Bearer sk-allowed" },
}),
allowedDeps()
);
assert.equal(response.status, 200);
const body = (await response.json()) as {
allowed: boolean;
provider: { provider: string } | null;
providers: Array<{ provider: string }>;
};
assert.equal(body.allowed, true);
const names = body.providers.map((s) => s.provider).sort();
assert.deepEqual(names, ["claude", "codex"]);
// the single-pick field is still present and one of them
assert.ok(["claude", "codex"].includes(body.provider?.provider ?? ""));
});
test("om-usage ?format=json reports a disallowed key as structured allowed:false", async () => {
// A usage panel must tell "this key may not ask" apart from "no data yet",
// which a bare 403 text body cannot express.
const response = await handleInternalUsageCommandHttpRequest(
new Request("http://localhost/api/usage/om-usage?format=json", {
headers: { Authorization: "Bearer sk-allowed" },
}),
allowedDeps({
getApiKeyMetadata: async () => ({ id: "key-off", allowUsageCommand: false }),
})
);
assert.equal(response.status, 403);
const body = (await response.json()) as { allowed: boolean };
assert.equal(body.allowed, false);
});
test("om-usage ?format=json rejects an invalid key and never leaks a stack trace", async () => {
const response = await handleInternalUsageCommandHttpRequest(
new Request("http://localhost/api/usage/om-usage?format=json", {
headers: { Authorization: "Bearer sk-wrong" },
}),
allowedDeps()
);
assert.equal(response.status, 401);
const body = (await response.json()) as { allowed: boolean; error?: { message?: string } };
assert.equal(body.allowed, false);
assert.ok(
!body.error?.message?.includes("at /"),
"error bodies must not carry stack frames (ERROR_SANITIZATION)"
);
});