



























@@ -696,6 +696,14 @@ function normalizeModelCatalogNumber(value: unknown): number | undefined {
696696return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined;
697697}
698698699+function normalizeModelCatalogPositiveNumber(value: unknown): number | undefined {
700+return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined;
701+}
702+703+function normalizeModelCatalogPositiveInteger(value: unknown): number | undefined {
704+return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : undefined;
705+}
706+699707function normalizeModelCatalogTieredCost(
700708value: unknown,
701709): PluginManifestModelCatalogTieredCost[] | undefined {
@@ -756,6 +764,72 @@ function normalizeModelCatalogCost(value: unknown): PluginManifestModelCatalogCo
756764return Object.keys(cost).length > 0 ? cost : undefined;
757765}
758766767+function normalizeModelCatalogCompat(value: unknown): ModelCompatConfig | undefined {
768+if (!isRecord(value)) {
769+return undefined;
770+}
771+const compat: Record<string, unknown> = {};
772+const booleanFields = [
773+"supportsStore",
774+"supportsPromptCacheKey",
775+"supportsDeveloperRole",
776+"supportsReasoningEffort",
777+"supportsUsageInStreaming",
778+"supportsTools",
779+"supportsStrictMode",
780+"requiresStringContent",
781+"requiresToolResultName",
782+"requiresAssistantAfterToolResult",
783+"requiresThinkingAsText",
784+"nativeWebSearchTool",
785+"requiresMistralToolIds",
786+"requiresOpenAiAnthropicToolPayload",
787+] as const;
788+for (const field of booleanFields) {
789+if (typeof value[field] === "boolean") {
790+compat[field] = value[field];
791+}
792+}
793+794+const stringFields = ["toolSchemaProfile", "toolCallArgumentsEncoding"] as const;
795+for (const field of stringFields) {
796+const normalized = normalizeOptionalString(value[field]) ?? "";
797+if (normalized) {
798+compat[field] = normalized;
799+}
800+}
801+802+const stringListFields = [
803+"visibleReasoningDetailTypes",
804+"unsupportedToolSchemaKeywords",
805+] as const;
806+for (const field of stringListFields) {
807+const normalized = normalizeTrimmedStringList(value[field]);
808+if (normalized.length > 0) {
809+compat[field] = normalized;
810+}
811+}
812+813+const maxTokensField = normalizeOptionalString(value.maxTokensField) ?? "";
814+if (maxTokensField === "max_completion_tokens" || maxTokensField === "max_tokens") {
815+compat.maxTokensField = maxTokensField;
816+}
817+818+const thinkingFormat = normalizeOptionalString(value.thinkingFormat) ?? "";
819+if (
820+thinkingFormat === "openai" ||
821+thinkingFormat === "openrouter" ||
822+thinkingFormat === "deepseek" ||
823+thinkingFormat === "zai" ||
824+thinkingFormat === "qwen" ||
825+thinkingFormat === "qwen-chat-template"
826+) {
827+compat.thinkingFormat = thinkingFormat;
828+}
829+830+return Object.keys(compat).length > 0 ? (compat as ModelCompatConfig) : undefined;
831+}
832+759833function normalizeModelCatalogStatus(value: unknown): PluginManifestModelCatalogStatus | undefined {
760834const status = normalizeOptionalString(value) ?? "";
761835return MODEL_CATALOG_STATUSES.has(status)
@@ -777,11 +851,11 @@ function normalizeModelCatalogModel(value: unknown): PluginManifestModelCatalogM
777851const headers = normalizeStringMap(value.headers);
778852const input = normalizeModelCatalogInputs(value.input);
779853const reasoning = typeof value.reasoning === "boolean" ? value.reasoning : undefined;
780-const contextWindow = normalizeModelCatalogNumber(value.contextWindow);
781-const contextTokens = normalizeModelCatalogNumber(value.contextTokens);
782-const maxTokens = normalizeModelCatalogNumber(value.maxTokens);
854+const contextWindow = normalizeModelCatalogPositiveNumber(value.contextWindow);
855+const contextTokens = normalizeModelCatalogPositiveInteger(value.contextTokens);
856+const maxTokens = normalizeModelCatalogPositiveNumber(value.maxTokens);
783857const cost = normalizeModelCatalogCost(value.cost);
784-const compat = isRecord(value.compat) ? (value.compat as ModelCompatConfig) : undefined;
858+const compat = normalizeModelCatalogCompat(value.compat);
785859const status = normalizeModelCatalogStatus(value.status);
786860const statusReason = normalizeOptionalString(value.statusReason) ?? "";
787861const replaces = normalizeTrimmedStringList(value.replaces);
@@ -810,14 +884,15 @@ function normalizeModelCatalogModel(value: unknown): PluginManifestModelCatalogM
810884811885function normalizeModelCatalogProviders(
812886value: unknown,
887+ownedProviders: ReadonlySet<string>,
813888): Record<string, PluginManifestModelCatalogProvider> | undefined {
814889if (!isRecord(value)) {
815890return undefined;
816891}
817892const providers: Record<string, PluginManifestModelCatalogProvider> = {};
818893for (const [rawProviderId, rawProvider] of Object.entries(value)) {
819894const providerId = normalizeSafeRecordKey(rawProviderId);
820-if (!providerId || !isRecord(rawProvider)) {
895+if (!providerId || !ownedProviders.has(providerId) || !isRecord(rawProvider)) {
821896continue;
822897}
823898const models = Array.isArray(rawProvider.models)
@@ -843,6 +918,7 @@ function normalizeModelCatalogProviders(
843918844919function normalizeModelCatalogAliases(
845920value: unknown,
921+ownedProviders: ReadonlySet<string>,
846922): Record<string, PluginManifestModelCatalogAlias> | undefined {
847923if (!isRecord(value)) {
848924return undefined;
@@ -854,7 +930,7 @@ function normalizeModelCatalogAliases(
854930continue;
855931}
856932const provider = normalizeOptionalString(rawTarget.provider) ?? "";
857-if (!provider) {
933+if (!provider || !ownedProviders.has(provider)) {
858934continue;
859935}
860936const api = normalizeModelCatalogApi(rawTarget.api);
@@ -896,6 +972,7 @@ function normalizeModelCatalogSuppressions(
896972897973function normalizeModelCatalogDiscovery(
898974value: unknown,
975+ownedProviders: ReadonlySet<string>,
899976): Record<string, PluginManifestModelCatalogDiscovery> | undefined {
900977if (!isRecord(value)) {
901978return undefined;
@@ -904,21 +981,24 @@ function normalizeModelCatalogDiscovery(
904981for (const [rawProviderId, rawMode] of Object.entries(value)) {
905982const providerId = normalizeSafeRecordKey(rawProviderId);
906983const mode = normalizeOptionalString(rawMode) ?? "";
907-if (providerId && MODEL_CATALOG_DISCOVERY_MODES.has(mode)) {
984+if (providerId && ownedProviders.has(providerId) && MODEL_CATALOG_DISCOVERY_MODES.has(mode)) {
908985discovery[providerId] = mode as PluginManifestModelCatalogDiscovery;
909986}
910987}
911988return Object.keys(discovery).length > 0 ? discovery : undefined;
912989}
913990914-function normalizeManifestModelCatalog(value: unknown): PluginManifestModelCatalog | undefined {
991+function normalizeManifestModelCatalog(
992+value: unknown,
993+ownedProviders: ReadonlySet<string>,
994+): PluginManifestModelCatalog | undefined {
915995if (!isRecord(value)) {
916996return undefined;
917997}
918-const providers = normalizeModelCatalogProviders(value.providers);
919-const aliases = normalizeModelCatalogAliases(value.aliases);
998+const providers = normalizeModelCatalogProviders(value.providers, ownedProviders);
999+const aliases = normalizeModelCatalogAliases(value.aliases, ownedProviders);
9201000const suppressions = normalizeModelCatalogSuppressions(value.suppressions);
921-const discovery = normalizeModelCatalogDiscovery(value.discovery);
1001+const discovery = normalizeModelCatalogDiscovery(value.discovery, ownedProviders);
9221002const modelCatalog = {
9231003 ...(providers ? { providers } : {}),
9241004 ...(aliases ? { aliases } : {}),
@@ -1237,7 +1317,7 @@ export function loadPluginManifest(
12371317const providers = normalizeTrimmedStringList(raw.providers);
12381318const providerDiscoveryEntry = normalizeOptionalString(raw.providerDiscoveryEntry);
12391319const modelSupport = normalizeManifestModelSupport(raw.modelSupport);
1240-const modelCatalog = normalizeManifestModelCatalog(raw.modelCatalog);
1320+const modelCatalog = normalizeManifestModelCatalog(raw.modelCatalog, new Set(providers));
12411321const providerEndpoints = normalizeManifestProviderEndpoints(raw.providerEndpoints);
12421322const cliBackends = normalizeTrimmedStringList(raw.cliBackends);
12431323const syntheticAuthRefs = normalizeTrimmedStringList(raw.syntheticAuthRefs);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。