refactor(open-sse): P3§7 model defaults schema — centralize type/quotaFamily/strip/targetFormat

- Add providers/models/schema.js (MODEL_DEFAULTS + field resolvers)
- Accessors getModelTargetFormat/QuotaFamily/Strip use shared default resolvers
- getModelType keeps null contract unchanged; behavior verified equal
- No catalog forced into registry (models stay self-contained per docs decision)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
decolua
2026-06-13 21:13:37 +07:00
co-authored by Cursor
parent 5a042840fd
commit d2b0960bf7
2 changed files with 17 additions and 30 deletions
+4 -6
View File
@@ -1,6 +1,7 @@
import { PROVIDERS } from "./providers.js";
// PROVIDER_MODELS now built from providers/registry (transport + models co-located)
import { PROVIDER_MODELS } from "../providers/index.js";
import { modelQuotaFamily, modelStrip, modelTargetFormat } from "../providers/models/schema.js";
export { PROVIDER_MODELS };
@@ -34,8 +35,7 @@ export function findModelName(aliasOrId, modelId) {
export function getModelTargetFormat(aliasOrId, modelId) {
const models = PROVIDER_MODELS[aliasOrId];
if (!models) return null;
const found = models.find(m => m.id === modelId);
return found?.targetFormat || null;
return modelTargetFormat(models.find(m => m.id === modelId));
}
export function getModelType(aliasOrId, modelId) {
@@ -57,8 +57,7 @@ export function getModelUpstreamId(aliasOrId, modelId) {
export function getModelQuotaFamily(aliasOrId, modelId) {
const models = PROVIDER_MODELS[aliasOrId];
const found = models?.find(m => m.id === modelId);
return found?.quotaFamily || "normal";
return modelQuotaFamily(models?.find(m => m.id === modelId));
}
// OAuth providers that use short aliases (everything else: alias = id)
@@ -96,6 +95,5 @@ export function getModelsByProviderId(providerId) {
// Get strip list for a model entry (explicit opt-in only)
// Returns array of content types to strip, e.g. ["image", "audio"]
export function getModelStrip(alias, modelId) {
const entry = PROVIDER_MODELS[alias]?.find(m => m.id === modelId);
return entry?.strip || [];
return modelStrip(PROVIDER_MODELS[alias]?.find(m => m.id === modelId));
}
+13 -24
View File
@@ -1,32 +1,21 @@
// Model schema (Mongoose-lite): central defaults + normalizer + 3-tier resolver (skeleton, not wired)
// Centralized model defaults (caps declares positive capabilities)
// Model defaults centralized (was scattered as `m.type || "llm"`, `quotaFamily || "normal"`, etc.)
export const MODEL_DEFAULTS = {
type: "llm",
quotaFamily: "normal",
strip: [],
targetFormat: null,
caps: { vision: false, audioIn: false, thinking: false }
targetFormat: null
};
// Normalize a raw model entry over defaults (deep-merge caps)
export function normalizeModel(raw) {
return {
...MODEL_DEFAULTS,
...raw,
caps: { ...MODEL_DEFAULTS.caps, ...raw.caps },
upstreamModelId: raw.upstreamModelId || raw.id
};
// Resolve a single field with its default (keeps accessor call-sites one-liners)
export function modelType(model) {
return model?.type || MODEL_DEFAULTS.type;
}
// 3-tier fallback: defaults -> catalog canonical -> provider inline override (wins)
export function resolveModel(catalog, ref) {
const raw = typeof ref === "string" ? { id: ref } : ref;
return {
...MODEL_DEFAULTS,
...catalog[raw.id],
...raw,
caps: { ...MODEL_DEFAULTS.caps, ...catalog[raw.id]?.caps, ...raw.caps },
upstreamModelId: raw.upstreamModelId || catalog[raw.id]?.upstreamModelId || raw.id
};
export function modelQuotaFamily(model) {
return model?.quotaFamily || MODEL_DEFAULTS.quotaFamily;
}
export function modelStrip(model) {
return model?.strip || [];
}
export function modelTargetFormat(model) {
return model?.targetFormat || MODEL_DEFAULTS.targetFormat;
}