feat: catalogue dynamique modèles Codex/Claude avec compatibilité CLI locale
Ajout du catalogue enrichi pour les modèles Codex et Claude avec: - Compatibilité estimée avec la version CLI locale détectée - Source d'origine (catalogue/Provider) pour chaque entrée - Support du catalogue Provider API externe - Matrice de compatibilité embarquée dans l'application Frontend: - UI de configuration des modèles avec affichage des états de compatibilité - Suggestions dynamiques avec badges de compatibilité - Messages d'aide contextuels (compatible/unknown/likelyTooRecent) - Alertes non-bloquantes pour les modèles trop récents - Gestion des échecs de catalogue avec saisie manuelle conservée Backend: - Ports CliVersionReader, ProviderModelCatalogue, CompatibilityMatrixSource - Implémentations: ProcessCliVersionReader, HttpProviderModelCatalogue, EmbeddedCompatibilityMatrix - Enrichissement des DTOs avec compatibility, cli_version, warnings - Tests unitaires complets pour le resolver de catalogue
This commit is contained in:
63
frontend/src/adapters/profileCatalog.ts
Normal file
63
frontend/src/adapters/profileCatalog.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import type {
|
||||
ModelCatalogSource,
|
||||
ModelCompatibility,
|
||||
ProfileModelCatalog,
|
||||
ProfileModelCatalogEntry,
|
||||
} from "@/domain";
|
||||
|
||||
type PartialCatalogEntry = Partial<ProfileModelCatalogEntry> & {
|
||||
adapter?: "claude" | "codex";
|
||||
modelId?: string;
|
||||
displayName?: string;
|
||||
};
|
||||
|
||||
function compatibilityOf(value: unknown): ModelCompatibility {
|
||||
return value === "compatible" ||
|
||||
value === "unknown" ||
|
||||
value === "likelyTooRecent"
|
||||
? value
|
||||
: "unknown";
|
||||
}
|
||||
|
||||
function sourceOf(value: unknown): ModelCatalogSource {
|
||||
return value === "provider" ? "provider" : "catalogue";
|
||||
}
|
||||
|
||||
function normalizeEntry(raw: PartialCatalogEntry): ProfileModelCatalogEntry {
|
||||
const modelId = raw.modelId ?? "";
|
||||
return {
|
||||
adapter: raw.adapter ?? "codex",
|
||||
modelId,
|
||||
displayName: raw.displayName ?? modelId,
|
||||
aliases: Array.isArray(raw.aliases) ? raw.aliases : [],
|
||||
recommended: Boolean(raw.recommended),
|
||||
compatibility: compatibilityOf(raw.compatibility),
|
||||
source: sourceOf(raw.source),
|
||||
};
|
||||
}
|
||||
|
||||
export function normalizeProfileModelCatalog(raw: unknown): ProfileModelCatalog {
|
||||
if (Array.isArray(raw)) {
|
||||
return {
|
||||
models: raw.map((entry) => normalizeEntry(entry as PartialCatalogEntry)),
|
||||
cliVersion: null,
|
||||
warnings: [],
|
||||
};
|
||||
}
|
||||
|
||||
const catalog =
|
||||
raw && typeof raw === "object"
|
||||
? (raw as Partial<ProfileModelCatalog>)
|
||||
: {};
|
||||
|
||||
return {
|
||||
models: Array.isArray(catalog.models)
|
||||
? catalog.models.map((entry) => normalizeEntry(entry as PartialCatalogEntry))
|
||||
: [],
|
||||
cliVersion:
|
||||
typeof catalog.cliVersion === "string" ? catalog.cliVersion : null,
|
||||
warnings: Array.isArray(catalog.warnings)
|
||||
? catalog.warnings.map(String)
|
||||
: [],
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user