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:
2026-07-26 16:09:10 +02:00
parent e7bf1d3666
commit ca70ec75f4
25 changed files with 1582 additions and 167 deletions

View File

@ -42,7 +42,7 @@ import type {
ProjectWorkState,
ProjectSystemPermissions,
ProfileAvailability,
ProfileModelCatalogEntry,
ProfileModelCatalog,
ResolvedAgentSystemPermissions,
SystemPermissionSet,
Skill,
@ -74,6 +74,7 @@ import type {
} from "@/ports";
import { normalizeProjectWorkState } from "../workStateNormalization";
import { normalizeTurnPage } from "../conversationNormalization";
import { normalizeProfileModelCatalog } from "../profileCatalog";
import type { HttpInvoker } from "./httpInvoker";
export class HttpProjectGateway implements ProjectGateway {
@ -183,11 +184,11 @@ export class HttpProfileGateway implements ProfileGateway {
request: { seedProfileId: input.seedProfileId, name: input.name, model: input.model },
});
}
listClaudeModels(): Promise<ProfileModelCatalogEntry[]> {
return this.http.invoke<ProfileModelCatalogEntry[]>("list_claude_models");
async listClaudeModels(): Promise<ProfileModelCatalog> {
return normalizeProfileModelCatalog(await this.http.invoke<unknown>("list_claude_models"));
}
listCodexModels(): Promise<ProfileModelCatalogEntry[]> {
return this.http.invoke<ProfileModelCatalogEntry[]>("list_codex_models");
async listCodexModels(): Promise<ProfileModelCatalog> {
return normalizeProfileModelCatalog(await this.http.invoke<unknown>("list_codex_models"));
}
configureProfiles(profiles: AgentProfile[]): Promise<AgentProfile[]> {
return this.http.invoke<AgentProfile[]>("configure_profiles", { request: { profiles } });