fix: skip incomplete Surplus discovery rows
This commit is contained in:
@@ -380,16 +380,38 @@ function parseOffer(value: unknown, index: number): SurplusOffer {
|
|||||||
|
|
||||||
function parseDiscoveredModel(value: unknown, index: number): SurplusDiscoveredModel {
|
function parseDiscoveredModel(value: unknown, index: number): SurplusDiscoveredModel {
|
||||||
const item = record(value, `Surplus discovery item ${index}`);
|
const item = record(value, `Surplus discovery item ${index}`);
|
||||||
const pricing = record(item.pricing, `Surplus discovery item ${index}.pricing`);
|
const model = string(item.model, `Surplus discovery item ${index}.model`);
|
||||||
const metadata = record(item.metadata, `Surplus discovery item ${index}.metadata`);
|
const supported = boolean(
|
||||||
|
item.supported,
|
||||||
|
`Surplus discovery item ${index}.supported`,
|
||||||
|
);
|
||||||
|
const pricing = optionalRecord(item.pricing);
|
||||||
|
const metadata = optionalRecord(item.metadata) ?? {};
|
||||||
return {
|
return {
|
||||||
model: string(item.model, `Surplus discovery item ${index}.model`),
|
model,
|
||||||
supported: boolean(item.supported, `Surplus discovery item ${index}.supported`),
|
supported,
|
||||||
inputUsdPer1m: nonNegativeNumber(pricing.input_per_1m, `Surplus discovery item ${index}.pricing.input_per_1m`),
|
inputUsdPer1m: pricing
|
||||||
outputUsdPer1m: nonNegativeNumber(pricing.output_per_1m, `Surplus discovery item ${index}.pricing.output_per_1m`),
|
? optionalNonNegativeNumber(
|
||||||
priceUnit: optionalString(pricing.price_unit) ?? "M",
|
pricing.input_per_1m,
|
||||||
priceVariable: pricing.price_variable === undefined ? false : boolean(pricing.price_variable, `Surplus discovery item ${index}.pricing.price_variable`),
|
`Surplus discovery item ${index}.pricing.input_per_1m`,
|
||||||
providerModelId: string(metadata.provider_model_id, `Surplus discovery item ${index}.metadata.provider_model_id`),
|
) ?? 0
|
||||||
|
: 0,
|
||||||
|
outputUsdPer1m: pricing
|
||||||
|
? optionalNonNegativeNumber(
|
||||||
|
pricing.output_per_1m,
|
||||||
|
`Surplus discovery item ${index}.pricing.output_per_1m`,
|
||||||
|
) ?? 0
|
||||||
|
: 0,
|
||||||
|
priceUnit: pricing
|
||||||
|
? optionalString(pricing.price_unit) ?? "M"
|
||||||
|
: "unknown",
|
||||||
|
priceVariable: pricing?.price_variable === undefined
|
||||||
|
? false
|
||||||
|
: boolean(
|
||||||
|
pricing.price_variable,
|
||||||
|
`Surplus discovery item ${index}.pricing.price_variable`,
|
||||||
|
),
|
||||||
|
providerModelId: optionalString(metadata.provider_model_id) ?? "",
|
||||||
modelType: optionalString(metadata.model_type) ?? "unknown",
|
modelType: optionalString(metadata.model_type) ?? "unknown",
|
||||||
availabilityStatus:
|
availabilityStatus:
|
||||||
optionalString(metadata.availability_status) ?? "unknown",
|
optionalString(metadata.availability_status) ?? "unknown",
|
||||||
@@ -446,6 +468,14 @@ function record(value: unknown, field: string): Record<string, unknown> {
|
|||||||
return value as Record<string, unknown>;
|
return value as Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function optionalRecord(value: unknown): Record<string, unknown> | null {
|
||||||
|
if (value === null || value === undefined) return null;
|
||||||
|
if (typeof value !== "object" || Array.isArray(value)) {
|
||||||
|
throw new Error("Optional Surplus object has the wrong type");
|
||||||
|
}
|
||||||
|
return value as Record<string, unknown>;
|
||||||
|
}
|
||||||
function string(value: unknown, field: string): string {
|
function string(value: unknown, field: string): string {
|
||||||
if (typeof value !== "string" || value === "") throw new Error(`${field} must be a non-empty string`);
|
if (typeof value !== "string" || value === "") throw new Error(`${field} must be a non-empty string`);
|
||||||
return value;
|
return value;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export function selectSurplusModelCandidates(
|
|||||||
if (
|
if (
|
||||||
!market ||
|
!market ||
|
||||||
!model.supported ||
|
!model.supported ||
|
||||||
|
model.providerModelId === "" ||
|
||||||
model.availabilityStatus !== "available" ||
|
model.availabilityStatus !== "available" ||
|
||||||
model.modelType !== "text" ||
|
model.modelType !== "text" ||
|
||||||
model.priceUnit !== "M" ||
|
model.priceUnit !== "M" ||
|
||||||
|
|||||||
@@ -71,6 +71,35 @@ describe("SurplusClient", () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("normalizes unsupported discovery rows with null pricing as ineligible", async () => {
|
||||||
|
const client = new SurplusClient({
|
||||||
|
apiBaseUrl: "https://api.surplusintelligence.ai",
|
||||||
|
sellerApiKey: SELLER_KEY,
|
||||||
|
timeoutMs: 1_000,
|
||||||
|
fetchFn: async () => ndjsonResponse([JSON.stringify({
|
||||||
|
model: "unsupported",
|
||||||
|
supported: false,
|
||||||
|
pricing: null,
|
||||||
|
metadata: {
|
||||||
|
provider_model_id: "vendor/unsupported",
|
||||||
|
model_type: null,
|
||||||
|
availability_status: null,
|
||||||
|
},
|
||||||
|
})]),
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
client.discoverModels(PROVIDER_KEY, "https://openrouter.ai/api/v1"),
|
||||||
|
).resolves.toEqual([expect.objectContaining({
|
||||||
|
model: "unsupported",
|
||||||
|
inputUsdPer1m: 0,
|
||||||
|
outputUsdPer1m: 0,
|
||||||
|
priceUnit: "unknown",
|
||||||
|
modelType: "unknown",
|
||||||
|
availabilityStatus: "unknown",
|
||||||
|
})]);
|
||||||
|
});
|
||||||
|
|
||||||
it("rejects one malformed discovery line without returning a partial catalog", async () => {
|
it("rejects one malformed discovery line without returning a partial catalog", async () => {
|
||||||
const client = new SurplusClient({
|
const client = new SurplusClient({
|
||||||
apiBaseUrl: "https://api.surplusintelligence.ai",
|
apiBaseUrl: "https://api.surplusintelligence.ai",
|
||||||
|
|||||||
Reference in New Issue
Block a user